diff src/g23m-gprs/grlc/grlc_rds.c @ 1:fa8dc04885d8

src/g23m-*: import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:25:50 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/g23m-gprs/grlc/grlc_rds.c	Fri Oct 16 06:25:50 2020 +0000
@@ -0,0 +1,809 @@
+/* 
++----------------------------------------------------------------------------- 
+|  Project :  GPRS (8441)
+|  Modul   :  GRLC
++----------------------------------------------------------------------------- 
+|  Copyright 2002 Texas Instruments Berlin, AG 
+|                 All rights reserved. 
+| 
+|                 This file is confidential and a trade secret of Texas 
+|                 Instruments Berlin, AG 
+|                 The receipt of or possession of this file does not convey 
+|                 any rights to reproduce or disclose its contents or to 
+|                 manufacture, use, or sell anything it may describe, in 
+|                 whole, or in part, without the specific written consent of 
+|                 Texas Instruments Berlin, AG. 
++----------------------------------------------------------------------------- 
+|  Purpose :  This module implements signal handler functions for service
+|             RD of entity GRLC.
++----------------------------------------------------------------------------- 
+*/ 
+
+#ifndef GRLC_RDS_C
+#define GRLC_RDS_C
+#endif
+
+#define ENTITY_GRLC
+
+/*==== INCLUDES =============================================================*/
+#include <string.h>
+
+#include "typedefs.h"    /* to get Condat data types */
+
+#include "vsi.h"        /* to get a lot of macros */
+#include "macdef.h"
+#include "gprs.h"
+#include "gsm.h"        /* to get a lot of macros */
+#include "ccdapi.h"     /* to get CCD API */
+#include "cnf_grlc.h"    /* to get cnf-definitions */
+#include "mon_grlc.h"    /* to get mon-definitions */
+#include "prim.h"       /* to get the definitions of used SAP and directions */
+#include "message.h"
+#include "grlc.h"        /* to get the global entity definitions */
+#include "grlc_rdf.h"
+#include "grlc_tms.h"
+#include "grlc_f.h"
+#include "grlc_meass.h"
+
+/*==== CONST ================================================================*/
+const T_TIME T3192_Values[8] = {500, 1000, 1500, 1, 80, 120, 160, 200};
+
+/*==== LOCAL VARS ===========================================================*/
+
+/*==== PRIVATE FUNCTIONS ====================================================*/
+
+/*==== PUBLIC FUNCTIONS =====================================================*/
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_tm_rd_assign
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_TM_RD_ASSIGN
+|
+| Parameters  : dummy - description of parameter dummy
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_tm_rd_assign ( void ) 
+{ 
+  TRACE_ISIG( "sig_tm_rd_assign" );
+  
+  switch( GET_STATE( RD ) )
+  {
+    case RD_WAIT_FOR_STARTING_TIME_ACK:
+    case RD_WAIT_FOR_STARTING_TIME_UACK:
+      TRACE_EVENT_P3("DL reassignment during starting time :%ld: dl_tfi=%d, st_dl_tfi=%d"
+                                                                ,grlc_data->dl_tbf_start_time
+                                                                ,grlc_data->dl_tfi
+                                                                ,grlc_data->start_fn_dl_tfi);
+
+
+      /*lint -fallthrough*/
+
+    case RD_NULL:            
+      rd_tbf_init();
+      if(grlc_data->rd.rlc_mode EQ CGRLC_RLC_MODE_ACK)
+      {
+        SET_STATE(RD,RD_WAIT_FOR_STARTING_TIME_ACK);
+      }
+      else
+      {
+        SET_STATE(RD,RD_WAIT_FOR_STARTING_TIME_UACK);
+      }    
+      grlc_data->dl_index = 1;
+      grlc_data->tbf_ctrl[grlc_data->dl_index].tbf_type    = TBF_TYPE_DL;
+      grlc_data->tbf_ctrl[grlc_data->dl_index].tfi         = grlc_data->dl_tfi;
+      grlc_data->tbf_ctrl[grlc_data->dl_index].pdu_cnt     = 0;
+      grlc_data->tbf_ctrl[grlc_data->dl_index].rlc_oct_cnt = 0;
+      grlc_data->tbf_ctrl[grlc_data->dl_index].cnt_ts      = 0;
+      grlc_data->tbf_ctrl[grlc_data->dl_index].ack_cnt     = 0;
+      grlc_data->tbf_ctrl[grlc_data->dl_index].fbi         = 0;
+      grlc_data->tbf_ctrl[grlc_data->dl_index].ret_bsn     = 0;
+
+      grlc_data->rd.ack_ctrl.cnt_meas_rpt                 = ACK_CNT_MEAS_RPT_FIRST;
+      grlc_data->rd.ack_ctrl.cnt_other                    = ACK_CNT_NORMAL;
+      break;
+    case RD_ACK:
+    case RD_UACK:
+      vsi_t_stop(GRLC_handle,T3190); 
+      vsi_t_start(GRLC_handle,T3190,T3190_VALUE);
+      grlc_data->rd.next_tbf_params   = grlc_data->downlink_tbf;
+      grlc_data->rd.v_next_tbf_params = TRUE;
+      TRACE_EVENT_P3("dl tbf reassignment with tfi %d, nts=%d tbf_st_time=%ld"
+                                              ,grlc_data->dl_tfi
+                                              ,grlc_data->downlink_tbf.nts
+                                              ,grlc_data->dl_tbf_start_time);
+      break;
+    default:
+      TRACE_ERROR( "SIG_TM_RD_ASSIGN unexpected" );
+      {
+        TRACE_EVENT_P2("DL ASS: state=%d  t3192=%d "
+                                                                        ,grlc_data->rd.state
+                                                                        ,grlc_data->downlink_tbf.t3192_val );
+      }
+      break;
+  }
+} /* sig_tm_rd_assign() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_tm_rd_abrel
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_TM_RD_ABREL
+|
+| Parameters  : dummy - description of parameter dummy
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_tm_rd_abrel ( ULONG fn, BOOL poll) 
+{ 
+  TRACE_ISIG( "sig_tm_rd_abrel" );
+  
+  switch( GET_STATE( RD ) )
+  {
+    case RD_ACK:
+    case RD_REL_ACK:
+    case RD_UACK:
+    case RD_REL_UACK:
+    case RD_NET_REL:    
+    case RD_WAIT_FOR_STARTING_TIME_ACK:
+    case RD_WAIT_FOR_STARTING_TIME_UACK:
+      vsi_t_stop(GRLC_handle,T3190);
+      vsi_t_stop(GRLC_handle,T3192);
+	    
+      rd_free_desc_list_partions();
+      rd_free_database_partions();
+
+      grlc_data->tbf_ctrl[grlc_data->dl_index].vs_vr  = grlc_data->rd.vr;
+      grlc_data->tbf_ctrl[grlc_data->dl_index].va_vq  = grlc_data->rd.vq;
+      grlc_trace_tbf_par ( grlc_data->dl_index );
+       
+      if(!poll)
+      {
+        /*
+         * abnormal release: abort TBF
+         */
+        SET_STATE(RD,RD_NULL);          
+      }
+      else
+      {
+        SET_STATE(RD,RD_NET_REL);
+        grlc_data->rd.fn_p_tbf_rel = fn;
+        TRACE_EVENT_P2("p. tbf rel c_fn=%ld poll_fn=%d",fn,grlc_data->rd.fn_p_tbf_rel);
+      }
+      break;
+    default:
+      TRACE_ERROR( "SIG_TM_RD_ABREL unexpected" );
+      break;
+  }
+} /* sig_tm_rd_abrel() */
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_tm_rd_ul_req
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_TM_RD_UL_REQ
+|
+| Parameters  : dummy - description of parameter dummy
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_tm_rd_ul_req ( void) 
+{ 
+  TRACE_ISIG( "sig_tm_rd_ul_req" );
+  
+  switch( GET_STATE( RD ) )
+  {
+    case RD_ACK:
+    case RD_REL_ACK:
+    case RD_UACK:
+    case RD_REL_UACK:
+    case RD_WAIT_FOR_STARTING_TIME_ACK:
+    case RD_WAIT_FOR_STARTING_TIME_UACK:
+      grlc_data->rd.channel_req = TRUE;      
+      break;
+    default:
+      TRACE_ERROR( "SIG_TM_RD_UL_REQ unexpected" );
+      break;
+  }
+} /* sig_tm_rd_ul_req() */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_tm_rd_ul_req_stop
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_TM_RD_UL_REQ_STOP: No packet
+|               channel description shall be sent in packet downlink ack/nack,
+|               because a valid packet uplink assignment is received
+|
+| Parameters  : dummy - description of parameter dummy
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_tm_rd_ul_req_stop ( void) 
+{ 
+  TRACE_ISIG( "sig_tm_rd_ul_req_stop" );
+  /*
+   * do it in every state
+   */  
+  grlc_data->rd.channel_req = FALSE;
+
+} /* sig_tm_rd_ul_req_stop() */
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_tm_rd_nor_rel
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_TM_RD_NOR_REL
+|
+| Parameters  : dummy - description of parameter dummy
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_tm_rd_nor_rel ( void) 
+{ 
+  TRACE_ISIG( "sig_tm_rd_nor_rel" );
+  
+  switch( GET_STATE( RD ) )
+  {
+    case RD_NULL:
+    case RD_ACK:
+    case RD_REL_ACK:
+    case RD_UACK:
+    case RD_REL_UACK:
+    case RD_NET_REL:  
+    case RD_WAIT_FOR_STARTING_TIME_ACK:
+    case RD_WAIT_FOR_STARTING_TIME_UACK:
+      SET_STATE(RD,RD_NULL);
+      vsi_t_stop(GRLC_handle,T3190);
+      vsi_t_stop(GRLC_handle,T3192);	  
+      grlc_data->tbf_ctrl[grlc_data->dl_index].vs_vr  = grlc_data->rd.vr;
+      grlc_data->tbf_ctrl[grlc_data->dl_index].va_vq  = grlc_data->rd.vq; 
+      grlc_trace_tbf_par ( grlc_data->dl_index );
+      break;
+    default:
+      TRACE_ERROR( "SIG_TM_RD_NOR_REL unexpected" );
+      break;
+  }
+} /* sig_tm_rd_nor_rel() */
+
+
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_gff_rd_mac_ready_ind
++------------------------------------------------------------------------------
+| Description : Handles the Signal sig_gff_rd_mac_ready_ind
+|
+| Parameters  : *mac_dl_ready_ind - Ptr to primitive MAC_READY_IND
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_gff_rd_mac_ready_ind ( T_MAC_READY_IND * mac_dl_ready_ind)
+{
+  UBYTE   *ptr_block=NULL;
+  ULONG   delta_fn;
+   
+  TRACE_ISIG( "sig_gff_rd_mac_ready_ind" );
+
+
+  grlc_data->tbf_ctrl[grlc_data->dl_index].end_fn = mac_dl_ready_ind->fn;  
+
+  grlc_handle_poll_pos (mac_dl_ready_ind->fn);
+  delta_fn = rd_calc_delta_fn(mac_dl_ready_ind->fn);
+
+  switch( GET_STATE( RD ) )
+  {
+    case RD_WAIT_FOR_STARTING_TIME_ACK:
+    case RD_WAIT_FOR_STARTING_TIME_UACK:       
+      if(!grlc_check_if_tbf_start_is_elapsed ( grlc_data->dl_tbf_start_time, mac_dl_ready_ind->fn))
+      {
+        TRACE_EVENT_P2("WAIT FOR DL STARTING TIME, UL IS RUNNING st=%ld fn=%ld",grlc_data->dl_tbf_start_time
+                                                                              ,mac_dl_ready_ind->fn);
+        grlc_send_rem_poll_pos (mac_dl_ready_ind->fn);
+        return;
+      }
+      if(grlc_data->rd.rlc_mode EQ CGRLC_RLC_MODE_ACK)
+      {
+        SET_STATE(RD,RD_ACK);
+      }
+      else
+      {
+        SET_STATE(RD,RD_UACK);
+      } 
+      grlc_data->tbf_ctrl[grlc_data->dl_index].start_fn    = mac_dl_ready_ind->fn;
+      
+      TRACE_EVENT_P6("DL first call at fn = %ld (%ld) with tfi=%d, dl_mask=%x tbf_st_time=%ld ta=%d",
+                                        mac_dl_ready_ind->fn,
+                                        mac_dl_ready_ind->fn%42432,
+                                        grlc_data->dl_tfi,
+                                        grlc_data->dl_tn_mask,
+                                        grlc_data->dl_tbf_start_time,
+                                        grlc_data->ta_value);
+      rd_cgrlc_st_time_ind();
+      vsi_t_start(GRLC_handle,T3190,T3190_VALUE);
+
+      /*lint -fallthrough*/
+
+    case RD_ACK:
+    case RD_REL_ACK:
+    case RD_UACK:
+    case RD_REL_UACK:
+      if(grlc_data->rd.v_next_tbf_params AND
+          grlc_check_if_tbf_start_is_elapsed ( grlc_data->dl_tbf_start_time, mac_dl_ready_ind->fn))
+      {
+        grlc_data->rd.v_next_tbf_params = FALSE;
+        rd_cgrlc_st_time_ind();
+        vsi_t_start(GRLC_handle,T3190,T3190_VALUE);
+      }
+      if(grlc_data->rd.ch_req_in_ack_prog AND mac_dl_ready_ind->last_poll_resp)
+      {
+        grlc_data->rd.channel_req = TRUE;
+      }
+      else if(grlc_data->rd.ch_req_in_ack_prog)
+      {
+        sig_rd_tm_ul_req_cnf();
+        grlc_data->rd.ch_req_in_ack_prog = FALSE;
+      }
+
+      
+      if(grlc_data->rd.release_tbf)  
+      {
+        /*
+         * Packet downlink ack/nack with final ack bit set to 1 was programmed
+         */
+        grlc_data->rd.release_tbf = FALSE;
+        if(mac_dl_ready_ind->last_poll_resp EQ 0)
+        {
+          /*
+           * Transmission from L1 confirmed
+           */
+          grlc_data->rd.cnt_sent_f_ack++;
+        }
+
+      }
+
+       
+      if( grlc_data->rd.f_ack_ind AND
+          (grlc_data->rd.fn_p_tbf_rel NEQ 0xFFFFFFFF)  AND
+          grlc_check_if_tbf_start_is_elapsed ( grlc_data->rd.fn_p_tbf_rel, mac_dl_ready_ind->fn))
+      {
+        /*
+         * no addtional final downlink ack with fbi requested by the network
+         * T3192 can be started
+         */
+
+        vsi_t_stop(GRLC_handle,T3190);
+
+        if(grlc_data->rd.cnt_sent_f_ack)
+        { 
+          /*
+           * it is only a retransmission of the final dl ack. 
+           * Therefore t3192 is restarted, no offset is needed
+           */
+          vsi_t_start(GRLC_handle,T3192, T3192_Values[grlc_data->downlink_tbf.t3192_val]); 
+          TRACE_EVENT_P3("T3192 started:  rel_fn=%ld fn=%ld T3192=%d",grlc_data->rd.fn_p_tbf_rel,mac_dl_ready_ind->fn,grlc_data->downlink_tbf.t3192_val);
+        }
+        else
+        {
+          /*
+           * the first final dl ack is not retransmitted, therefore retransmission is required.
+           * start t3190 and wait for new poll position
+           */ 
+          vsi_t_start(GRLC_handle,T3190,T3190_VALUE);
+          TRACE_EVENT_P1("NO DL REL: ret needed T3190 is running %d",grlc_data->rd.cnt_sent_f_ack);
+        }  
+        grlc_data->rd.fn_p_tbf_rel = 0xFFFFFFFF;
+      }
+
+
+      if( (delta_fn EQ 4) 
+           OR 
+          (delta_fn EQ 5))                   
+      {
+        UBYTE  i=0;
+        UBYTE  index;
+        while(grlc_data->next_poll_array[grlc_data->poll_start_tbf].cnt 
+              AND 
+              (i<8))
+        {
+          if(grlc_data->next_poll_array[grlc_data->poll_start_tbf].poll_type[i] EQ CGRLC_POLL_DATA)
+          {
+           /* 
+            * poll positon in next frame present, 
+            * counter for for poll postions in one frame 
+            */
+            if( grlc_data->rd.channel_req                                OR /* uplink request */
+                grlc_data->rd.next_poll_block EQ NEXT_POLL_BLOCK_DL_DATA OR /* last poll block was not ack nack */
+                grlc_data->rd.f_ack_ind                                  OR /* final ack indicator */
+                !tm_is_ctrl_blk_rdy
+                   ( grlc_data->rd.ack_ctrl.cnt_meas_rpt, 
+                     grlc_data->rd.ack_ctrl.cnt_other     ) )               /* no ctrl message */
+            { 
+              if ( !((grlc_data->rd.rlc_mode EQ CGRLC_RLC_MODE_UACK) AND grlc_data->rd.f_ack_ind) )
+              {
+                /* 
+                 * sent downlink ack/nack 
+                 */
+                 ptr_block = rd_set_acknack();
+                 sig_rd_meas_qual_rpt_sent( );
+                 grlc_data->tbf_ctrl[grlc_data->dl_index].ack_cnt++;
+
+                 if( grlc_data->rd.ack_ctrl.cnt_meas_rpt > 0 )
+                   grlc_data->rd.ack_ctrl.cnt_meas_rpt--;
+                 
+                 if( grlc_data->rd.ack_ctrl.cnt_other > 0 )
+                   grlc_data->rd.ack_ctrl.cnt_other--;
+
+                 grlc_send_normal_burst(ptr_block, NULL, i);
+              }
+              else
+              {
+                /*
+                 * unacknowledged mode, send packet control acknowledgment
+                 */
+                if(grlc_data->burst_type EQ CGRLC_BURST_TYPE_NB)
+                {
+                   ptr_block = grlc_set_packet_ctrl_ack();
+                   grlc_send_normal_burst(ptr_block, NULL, i);
+                }
+                else
+                {
+                   /* send access burst. */
+                   grlc_send_access_burst(i);
+                }
+              }
+              grlc_data->rd.next_poll_block = NEXT_POLL_BLOCK_CTRL;
+              if(grlc_data->rd.f_ack_ind)
+              {
+                grlc_data->rd.release_tbf = TRUE;
+              }
+            }
+            else
+            { 
+              /* 
+               * sent control block 
+               */
+              ptr_block = tm_get_ctrl_blk( &index, TRUE );
+              grlc_send_normal_burst(NULL, ptr_block, i);
+              grlc_data->rd.next_poll_block = NEXT_POLL_BLOCK_DL_DATA;
+              
+              if( grlc_data->rd.ack_ctrl.cnt_meas_rpt EQ 0 )
+                grlc_data->rd.ack_ctrl.cnt_meas_rpt = ACK_CNT_NORMAL;
+                 
+              if( grlc_data->rd.ack_ctrl.cnt_other EQ 0 )
+                grlc_data->rd.ack_ctrl.cnt_other = ACK_CNT_NORMAL;
+            }
+          }
+          i++;
+        }
+      }
+      grlc_send_rem_poll_pos(mac_dl_ready_ind->fn);
+      break;
+    case RD_NET_REL:       
+      /* 
+       * send packet control acknowledgement and abort TBF
+       */
+      grlc_send_rem_poll_pos(mac_dl_ready_ind->fn);
+      if(grlc_data->rd.release_tbf)
+      {
+        SET_STATE(RD,RD_NULL);
+        grlc_data->rd.release_tbf = FALSE;                
+        TRACE_EVENT_P2("poll sent after packet tbf release(DL): current_fn=%ld rel_fn=%ld",
+                                        mac_dl_ready_ind->fn,
+                                        grlc_data->rd.fn_p_tbf_rel);
+        sig_rd_tm_end_of_tbf(FALSE);
+      }
+      if(grlc_check_if_tbf_start_is_elapsed ( grlc_data->rd.fn_p_tbf_rel, mac_dl_ready_ind->fn))
+      {
+        grlc_data->rd.release_tbf = TRUE;
+        TRACE_EVENT_P2("wait for poll confirm after packet tbf release(DL) current_fn=%ld rel_fn=%ld",
+                                        mac_dl_ready_ind->fn,
+                                        grlc_data->rd.fn_p_tbf_rel);
+      }
+	  break;
+    default:
+      TRACE_ERROR( "SIG_GFF_RD_MAC_READY_IND unexpected" );
+      break;
+  }
+} /* sig_gff_rd_mac_ready_ind() */
+
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_gff_rd_data
++------------------------------------------------------------------------------
+| Description : Handles the SIGNAL sig_gff_rd_data
+|
+| Parameters  : fn - current frame number
+|               tn - current timeslot number
+|               block_status - current block_status
+|               sp           - sp bit of mac header.
+|               bsn          - bsn number
+|               fbi          - fbi bit
+|               e_bit        - e bit
+|               ptr_dl_block - pointer to the dl data block
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_gff_rd_data (ULONG fn, UBYTE tn, USHORT block_status,UBYTE rrbp,UBYTE sp,UBYTE bsn,UBYTE fbi,UBYTE e_bit, UBYTE * ptr_dl_block) 
+{
+  UBYTE bsn_l;
+  UBYTE diff;
+  BOOL  InRange;
+  BOOL  li_correct;
+  T_CODING_SCHEME old_cs_type;
+
+
+  TRACE_FUNCTION( "sig_gff_rd_data" );
+
+  
+  grlc_data->tbf_ctrl[grlc_data->dl_index].cnt_ts++;
+
+
+  /*
+   * TESTMODE B
+   */
+  if (grlc_data->testmode.mode EQ CGRLC_LOOP)
+  {
+   /* 
+    * If the downlink TBF is established on more than one timeslot, the MS shall transmit in 
+    * the second uplink timeslot (if present) RLC/MAC blocks received on the second downlink 
+    * timeslot, and shall transmit in the third uplink timeslot (if present) RLC/MAC blocks 
+    * received in the third downlink timeslot and so on.
+    */
+    if (grlc_data->downlink_tbf.nts > 1)
+    {
+      if (tn - grlc_data->testmode.dl_ts_offset)
+      {
+        grlc_data->testmode.rec_data[1].block_status = block_status;
+        grlc_data->testmode.rec_data[1].e_bit        = e_bit;
+        memcpy(grlc_data->testmode.rec_data[1].payload,ptr_dl_block,50);
+      }
+      else
+      {
+        grlc_data->testmode.rec_data[0].block_status = block_status;
+        grlc_data->testmode.rec_data[0].e_bit        = e_bit;
+        memcpy(grlc_data->testmode.rec_data[0].payload,ptr_dl_block,50);
+      }
+    }
+    else
+    {
+      grlc_data->testmode.rec_data[0].block_status = block_status;
+      grlc_data->testmode.rec_data[0].e_bit        = e_bit;
+      memcpy(grlc_data->testmode.rec_data[0].payload,ptr_dl_block,50);
+    }
+
+    grlc_data->rd.f_ack_ind = rd_check_fbi(fbi,sp,fn,rrbp);
+
+    vsi_t_stop(GRLC_handle,T3190);
+    vsi_t_start(GRLC_handle,T3190,T3190_VALUE);
+
+    TRACE_EVENT_P6("DL DATA in testmode B at fn=%ld: bsn =%d, bs=%d,e_bit=%d, fbi=%d sp=%d "
+                            ,fn
+                            ,bsn
+                            ,block_status
+                            ,grlc_data->testmode.rec_data[0].e_bit
+                            ,fbi
+                            ,sp);
+    return;
+  }
+
+
+
+
+/******************************************************************************************/
+#if defined (_SIMULATION_)
+  TRACE_EVENT_P1("DL DATA bsn= %d",bsn);
+#endif /* defined (_SIMULATION_) */
+
+
+  if(grlc_data->rd.vq NEQ grlc_data->rd.vr)
+  {
+    TRACE_EVENT_P5("wait for neg acked blocks :bsn=%d  vr=%d vq=%d  fbi=%d fn=%ld",
+                                                            bsn,
+                                                            grlc_data->rd.vr,
+                                                            grlc_data->rd.vq,
+                                                            fbi,
+                                                            fn);
+  }
+/******************************************************************************************/
+  old_cs_type = grlc_data->rd.cs_type;
+  switch( GET_STATE( RD ) )
+  {    
+    case RD_WAIT_FOR_STARTING_TIME_ACK:
+      SET_STATE(RD,RD_ACK);    
+
+      /*lint -fallthrough*/
+
+    case RD_ACK     :
+      vsi_t_stop(GRLC_handle,T3190); 
+      vsi_t_start(GRLC_handle,T3190,T3190_VALUE);
+      bsn_l   = bsn;
+      InRange = rd_check_window_size(bsn_l);
+
+
+      if( !InRange  OR (grlc_data->rd.vn[bsn_l & WIN_MOD] EQ VN_RECEIVED))
+      {
+        grlc_data->tbf_ctrl[grlc_data->dl_index].ret_bsn++;
+        
+        if( fbi                      AND 
+            !grlc_data->rd.f_ack_ind AND
+           ((bsn_l+1) & 0x7F) EQ grlc_data->rd.vr)
+        { /* WORKAROUND FOR NORTEL, fbi bit is modified , only possible for last bsn*/ 
+          
+          grlc_data->rd.f_ack_ind=rd_check_fbi(fbi,sp,fn,rrbp);
+
+          TRACE_EVENT_P8("fbi modification in ret bsn=%d,vr=%d,vq=%d,sp=%d,fbi=%d,e=%d ptr[0]=%x,ptr[1]=%x",
+                                                                    bsn_l,
+                                                                    grlc_data->rd.vr,
+                                                                    grlc_data->rd.vq,
+                                                                    sp,
+                                                                    fbi,
+                                                                    e_bit,
+                                                                    ptr_dl_block[0],
+                                                                    ptr_dl_block[1]);
+
+        }
+        
+        return;
+      }
+      grlc_data->rd.rlc_data_len = rd_calc_rlc_data_len(block_status);
+      li_correct                = rd_read_li_m_of_block(ptr_dl_block,
+                                                        e_bit);
+      if((old_cs_type NEQ grlc_data->rd.cs_type) AND
+         (old_cs_type NEQ CS_ZERO))
+      {
+        TRACE_EVENT_P3("DL CS TYPE CHANGED from %d to %d, bsn=%d",old_cs_type,grlc_data->rd.cs_type,bsn_l);
+      }
+      
+      if(!li_correct)
+      {
+        grlc_data->rd.vn[bsn_l & WIN_MOD] = VN_INVALID;
+        TRACE_ERROR( "LI field is longer than RLC data block" );
+        return;
+      }
+     
+      /* 
+       * compute receive parameter
+       */
+      rd_comp_rec_par(bsn_l); 
+
+      rd_save_block( bsn_l, &(ptr_dl_block[grlc_data->rd.li_cnt]),
+                              fbi );
+
+#if defined (_SIMULATION_)
+  TRACE_EVENT_P1("first_ptr= %ld",grlc_data->rd.data_array[bsn_l & WIN_MOD].first);
+#endif /* defined (_SIMULATION_) */
+
+      diff = (grlc_data->rd.vq - bsn_l) & 0x7F;
+      while( ( diff <= WIN_SIZE)          AND
+             (grlc_data->rd.vq NEQ bsn_l) AND 
+             (grlc_data->rd.vn[bsn_l & WIN_MOD] EQ VN_RECEIVED )  )
+      {
+        rd_send_grlc_data_ind(bsn_l);		
+        bsn_l = (bsn_l+1)  & 0x7F;
+        diff  = (grlc_data->rd.vq - bsn_l) & 0x7F;
+      }       
+      
+      grlc_data->rd.f_ack_ind = rd_check_fbi(fbi,sp,fn,rrbp);
+      
+      break;
+    case RD_REL_ACK :    
+      /*
+       * all blocks are received, after sending p. dl ack nack timer t3192 will be restarted
+       */
+      grlc_data->tbf_ctrl[grlc_data->dl_index].ret_bsn++;
+
+      if(grlc_data->rd.f_ack_ind AND sp)
+      { /* 
+         * will be restarted at sending the dl ack nack: secure, in case of gaps.
+         * The value could be zero, therfore a offset is needed
+         */ 
+        vsi_t_stop(GRLC_handle,T3192); 
+        grlc_data->rd.fn_p_tbf_rel = grlc_decode_tbf_start_rel(fn,(USHORT)(rrbp+3));
+        TRACE_EVENT_P3("FINAL DL ACK RETR REQIURED t3192=%d rel_fn=%ld c_fn=%ld ",grlc_data->downlink_tbf.t3192_val,grlc_data->rd.fn_p_tbf_rel,fn);
+      }
+ /*     TRACE_EVENT_P7("BLOCK DISCARDED WAIT FOR TBF RELEASE f_ack=%d bsn=%d sp=%d rrbp=%d vr=%d vq=%d t3192=%d"
+                                                               ,grlc_data->rd.f_ack_ind
+                                                               ,bsn
+                                                               ,sp
+                                                               ,rrbp
+                                                               ,grlc_data->rd.vr
+                                                               ,grlc_data->rd.vq
+                                                               ,grlc_data->downlink_tbf.t3192_val);
+  */
+      break;    
+    case RD_WAIT_FOR_STARTING_TIME_UACK:
+      SET_STATE(RD,RD_UACK);
+
+      /*lint -fallthrough*/
+
+    case RD_UACK:
+      /*
+       * After receiving each block the timer T3190 should be restarted. 
+       */
+      vsi_t_stop(GRLC_handle,T3190); 
+      vsi_t_start(GRLC_handle,T3190,T3190_VALUE);
+
+      if(!rd_check_window_size(bsn))
+      {
+        TRACE_EVENT_P3("UACK bsn outside window: bsn=%d vr=%d vq=%d",bsn,grlc_data->rd.vr,grlc_data->rd.vq);
+        return;
+      }
+      
+      grlc_data->rd.rlc_data_len  = rd_calc_rlc_data_len(block_status);
+      li_correct                 = rd_read_li_m_of_block(ptr_dl_block, e_bit);
+      if(!li_correct)
+      {
+        TRACE_ERROR( "LI field is longer than RLC data block" );
+        return;
+      }
+     
+      /* 
+       * compute receive parameter 
+       */
+      rd_comp_rec_par(bsn); 
+      rd_save_block( bsn, &(ptr_dl_block[grlc_data->rd.li_cnt]), fbi );
+      if(!grlc_data->rd.inSequence)
+        rd_fill_blocks(bsn);
+
+      rd_send_grlc_data_ind(bsn);
+      
+      grlc_data->rd.f_ack_ind = rd_check_fbi(fbi,sp,fn,rrbp);
+
+      break;
+    case RD_REL_UACK:
+
+      if(fbi AND sp)
+      {
+        vsi_t_stop(GRLC_handle,T3192); 
+        grlc_data->rd.fn_p_tbf_rel = grlc_decode_tbf_start_rel(fn,(USHORT)(rrbp+3));
+        TRACE_EVENT_P4("data in REL_UACK restart t3192:  bsn=%d   t3192=%d fn=%ld rel_fn=%ld"
+                                                               ,bsn
+                                                               ,grlc_data->downlink_tbf.t3192_val
+                                                               ,fn
+                                                               ,grlc_data->rd.fn_p_tbf_rel);
+
+      }
+      break;
+    default:
+      TRACE_ERROR( "SIG_GFF_RD_DATA unexpected" );
+      break;
+  }
+
+} /* sig_gff_rd_data() */
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_ru_rd_get_downlink_release_state
++------------------------------------------------------------------------------
+| Description : This function returns true if RD is in release state( if
+|               fbi=1 is received in dowonlink data block. 
+|
+| Parameters  : release_state 
++------------------------------------------------------------------------------
+*/
+GLOBAL void sig_ru_rd_get_downlink_release_state( BOOL *release_started)
+{
+  *release_started = FALSE ;
+
+  if( (GET_STATE( RD ) EQ RD_REL_ACK ) OR
+      (GET_STATE( RD ) EQ RD_REL_UACK ) )
+  {
+     *release_started = TRUE;
+  }
+  else if(GET_STATE( RD ) EQ RD_NULL )
+  {
+     TRACE_ERROR("ERROR:sig_ru_rd_get_downlink_release_state called in RD NULL state");
+     *release_started = TRUE;
+  }
+}