view src/g23m-gprs/grlc/grlc_rus.c @ 268:f2e52cab0a73

abb_inth.c: check all interrupt causes, not just one The original code used if - else if - else if etc constructs, thus the first detected interrupt was the only one handled. However, Iota ITSTATREG is a clear-on-read register, thus if we only handle the first detected interrupt and skip checking the others, then the other interrupts will be lost, if more than one interrupt happened to occur in one ABB interrupt handling cycle - a form of rare race condition. Change the code to check all interrupts that were read in this cycle.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 13 Jun 2021 18:17:53 +0000
parents fa8dc04885d8
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  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
|             RU of entity GRLC.
+----------------------------------------------------------------------------- 
*/ 

#ifndef GRLC_RUS_C
#define GRLC_RUS_C
#endif

#define ENTITY_GRLC

/*==== INCLUDES =============================================================*/

#include <stdio.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_f.h"      
#include "grlc_tms.h"
#include "grlc_ruf.h"
#include <string.h>


/*==== CONST ================================================================*/
/*#ifdef TRACE_ERROR
#undef TRACE_ERROR
#define TRACE_ERROR(x)
#endif
#ifdef TRACE_FUNCTION
#undef TRACE_FUNCTION
#define TRACE_FUNCTION(x)
#endif
#ifdef TRACE_ISIG
#undef TRACE_ISIG
#define TRACE_ISIG(x)
#endif*/
/*==== LOCAL VARS ===========================================================*/

/*==== PRIVATE FUNCTIONS ====================================================*/

/*==== PUBLIC FUNCTIONS =====================================================*/



/*
+------------------------------------------------------------------------------
| Function    : sig_tm_ru_assign
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_TM_RU_ASSIGN
|
| Parameters  : dummy - description of parameter dummy
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_tm_ru_assign ( void) 
{ 
  TRACE_ISIG( "sig_tm_ru_assign" );
  
  switch( GET_STATE( RU ) )
  {
    case RU_WAIT_FOR_FIRST_CALL_ACK:
    case RU_WAIT_FOR_FIRST_CALL_UACK:
      /* 
       * reorg l1 one
       */
      {
        grlc_data->ru.write_pos_index -= grlc_data->ru.nts_max;      
      }
      TRACE_EVENT_P3("UL REASSIG during tbf starting time is running:%ld ul_tfi=%d st_fn_tfi=%d"
                                                                  ,grlc_data->ul_tbf_start_time
                                                                  ,grlc_data->ul_tfi
                                                                  ,grlc_data->start_fn_ul_tfi);

      /*lint -fallthrough*/

    case RU_NULL: 
      if(grlc_data->ul_tfi EQ 0xFF)
        grlc_data->ul_tfi = grlc_data->start_fn_ul_tfi;

	  switch( grlc_data->uplink_tbf.rlc_mode )
      {        
      case CGRLC_RLC_MODE_ACK:
      SET_STATE(RU,RU_WAIT_FOR_FIRST_CALL_ACK);
        ru_tbf_init(); 
        /*
         * sending the first block of the tbf
         */
        grlc_data->ru.N3104 = 0;

        while( grlc_data->ru.nts  AND
               tm_get_num_ctrl_blck( ) NEQ 0     )
        { /* 
           * next uplink block is a control block, 
           *  check if countdown procedure is statred or not
           */
          ru_send_control_block( );
        }     
        while(grlc_data->ru.nts AND grlc_data->ru.sdu_len)
        {
          ru_new_data();
        }
        while(grlc_data->ru.nts)
        {
          ru_ret_bsn();
        }
        break;
      case CGRLC_RLC_MODE_UACK:
      SET_STATE(RU,RU_WAIT_FOR_FIRST_CALL_UACK);
        ru_tbf_init();
        while( grlc_data->ru.nts  AND
               tm_get_num_ctrl_blck( ) NEQ 0     )
        { /* 
           * next uplink block is a control block, 
           *  check if countdown procedure is statred or not
           */
          ru_send_control_block( );
        }        
        while(grlc_data->ru.nts AND grlc_data->ru.sdu_len)
        {
          ru_new_data();
        }
        if(grlc_data->ru.cv EQ 0)
        {
          while( grlc_data->ru.nts 
                 AND (grlc_data->ru.count_cv_0 < 4) )
          {
            UBYTE bsn;
            bsn  = grlc_data->ru.vs - 1;
            bsn &= 0x7F;
            ru_send_mac_data_req(bsn);
            grlc_data->ru.count_cv_0++;
          }
        }
       break;
      default:
        TRACE_ERROR( "unknown RLC MODE for UL" );
        break;
      }      
      break;
    case RU_ACK:
    case RU_REL_ACK:      
    case RU_UACK:
    case RU_REL_UACK:
      /* 
       * store new params, modification at reaching starting time
       */
      grlc_data->ru.next_tbf_params   = grlc_data->uplink_tbf;
      grlc_data->ru.v_next_tbf_params = TRUE;
      break;
    default:
      TRACE_ERROR( "SIG_TM_RU_ASSIGN unexpected" );
      break;
  }
} /* sig_tm_ru_assign() */

/*
+------------------------------------------------------------------------------
| Function    : sig_tm_ru_abrel
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_TM_RU_ABREL
|
| Parameters  : dummy - description of parameter dummy
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_tm_ru_abrel (ULONG fn,BOOL poll_i) 
{ 
  TRACE_ISIG( "sig_tm_ru_abrel" );
  
  /*
   * stop all uplink timers 
   */
  vsi_t_stop(GRLC_handle,T3164);
  vsi_t_stop(GRLC_handle,T3166);
  vsi_t_stop(GRLC_handle,T3180);
  vsi_t_stop(GRLC_handle,T3182);  
  vsi_t_stop(GRLC_handle,T3184);/*timer for FA, used in simulation test*/  
  vsi_t_stop(GRLC_handle,T3188);/*timer for FA, used in simulation test*/

  if (grlc_data->prim_start_tbf < PRIM_QUEUE_SIZE_TOTAL)
  {
    grlc_data->prim_queue[grlc_data->prim_start_tbf].rlc_status  = FALSE;
    grlc_data->prim_queue[grlc_data->prim_start_tbf].cv_status   = FALSE;
    grlc_data->prim_queue[grlc_data->prim_start_tbf].last_bsn    = 0xFF;
  }
   if(!poll_i)
  {
    /*
     * abnormal release: abort TBF
     */
    grlc_data->tbf_ctrl[grlc_data->ul_index].end_fn = grlc_data->ul_fn;
    grlc_data->tbf_ctrl[grlc_data->ul_index].vs_vr  = grlc_data->ru.vs;
    grlc_data->tbf_ctrl[grlc_data->ul_index].va_vq  = grlc_data->ru.va;
    grlc_data->tbf_ctrl[grlc_data->ul_index].cnt_ts = grlc_data->ru.cnt_ts;
    grlc_trace_tbf_par ( grlc_data->ul_index );
    SET_STATE(RU,RU_NULL);
  }
  else
  {
    SET_STATE(RU,RU_NET_REL);
    grlc_data->ru.poll_fn = fn;
    TRACE_EVENT_P2("UL:RU_NET_REL p.tbf rel c_fn=%ld poll_fn=%d",grlc_data->dl_fn,grlc_data->ru.poll_fn);
  }

} /* sig_tm_ru_abrel() */



/*
+------------------------------------------------------------------------------
| Function    : sig_tm_ru_queue_status
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_TM_RU_QUEUE_STATUS
|
| Parameters  : dummy - description of parameter dummy
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_tm_ru_queue_status ( void) 
{ 
  TRACE_ISIG( "sig_tm_ru_queue_status" );
  
  switch( GET_STATE( RU ) )
  {
    case RU_WAIT_FOR_FIRST_CALL_ACK:
    case RU_WAIT_FOR_FIRST_CALL_UACK:
    case RU_ACK:
    case RU_UACK:
      grlc_data->ru.rlc_octet_cnt = ru_recalc_rlc_oct_cnt();
      break;
    default:
      /*
       * nothing to do
       */
      break;
  }
} /* sig_tm_ru_queue_status() */




/*
+------------------------------------------------------------------------------
| Function    : sig_gff_ru_ul_ack
+------------------------------------------------------------------------------
| Description : Handles the Signal SIG_GFF_RU_UL_ACK
|
| Parameters  : fn - current frame number
|               tn - current timeslot number
|               rrbp - rrbp parameter indicated in mac header
|               sp - sp parameter indicated in mac header
|
+------------------------------------------------------------------------------
*/

GLOBAL void sig_gff_ru_ul_ack (ULONG fn , UBYTE tn, UBYTE rrbp, UBYTE sp) 
{ 
  MCAST(d_ul_ack,D_GRLC_UL_ACK);

  TRACE_ISIG( "sig_gff_ru_ul_ack" );

#ifdef REL99
  /* Handling abnormal case
   * 8.7 While a TBF is in progress, if a mobile station receives a 
   * PACKET UPLINK ASSIGNMENT, PACKET UPLINK ACK/NACK or PACKET TIMESLOT RECONFIGURE 
   * message with message escape bit indicating EGPRS (resp. GPRS) contents whereas 
   * the current TBF mode is GPRS (resp. EGPRS), the mobile station shall ignore the 
   * message.
   */
  if(d_ul_ack->egprs_flag)
  {
    TRACE_ERROR( "EGPRS UL ACK/NACK received" );
    return;
  }
#endif

  grlc_data->tbf_ctrl[grlc_data->ul_index].ack_cnt++;
  
  
  if(grlc_data->uplink_tbf.mac_mode EQ CGRLC_MAC_MODE_FA)
  {
    vsi_t_stop(GRLC_handle,T3184);
    if(!d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.f_ack_ind)
    {
      vsi_t_start(GRLC_handle,T3184,T3184_VALUE);
      TRACE_EVENT("sig_gff_ru_ul_ack: T3184 started for FA");
    }
    sig_ru_tm_repeat_alloc();
  }

  switch( GET_STATE( RU ) )
  {    
    case RU_ACK     :
      if(ru_contention_resolution())
      {
        SET_STATE(RU,RU_NULL);
        return;
      }
      ru_update_vb();
      grlc_data->ru.va = ru_calc_va();  
      ru_delete_prims(grlc_data->ru.va);
      ru_handle_stall_ind();
      break;
    case RU_REL_ACK :
      /* 
       * For proper release of ul tbf
       */
      vsi_t_stop(GRLC_handle,T3182);
      if(ru_contention_resolution())
      {
        SET_STATE(RU,RU_NULL);
        return;
      }
      if(sp)
      {
        grlc_data->ru.poll_fn = grlc_calc_new_poll_pos(fn,rrbp);
        grlc_data->ru.poll_tn = tn;
      }
      if( !(d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.f_ack_ind) )
      {
        ru_update_vb();
        grlc_data->ru.va = ru_calc_va();
        ru_delete_prims(grlc_data->ru.va);
        ru_handle_stall_ind();
      }
      else if(d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.f_ack_ind AND 
              grlc_data->ru.cv EQ 0)
      {          
        SET_STATE(RU,RU_SEND_PCA);
        ru_delete_prims(grlc_data->ru.vs);
        grlc_data->ru.va                            = grlc_data->ru.vs;
        grlc_data->ru.nr_nacked_blks                = 0;
        grlc_data->tbf_ctrl[grlc_data->ul_index].fbi = 1;
        grlc_data->ru.reorg_l1_needed	             = TRUE;    /* delete blocks, dummies will be placed */
        if(!sp)
        {
          SET_STATE(RU,RU_NULL);
          TRACE_EVENT("FAI = 1 received but no poll");   
          vsi_t_stop(GRLC_handle,T3180);
          sig_ru_tm_error_ra();
        }
#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH
        else
        { /* network wishes to re-estab tbf on pacch */
          if(d_ul_ack->gprs_ul_ack_nack_info.release_99_str_d_ul_ack.tbf_est EQ 1 AND
             grlc_data->prim_start_tbf NEQ END_OF_LIST  AND /*UL data is present*/
             grlc_data->tbf_type       NEQ TBF_TYPE_CONC    /* No DL TBF */
            )
          {
            grlc_data->ru.tbf_re_est = TRUE;
            grlc_data->next_poll_array[grlc_data->poll_start_tbf].poll_type[tn] = CGRLC_POLL_RE_ASS;
          }

        }
#endif
      }      
      else
      {        
        /* 
         * if the mobile station has not started or has not completed the countdown procedure 
         * and it receives a Packet Uplink Ack/Nack with the Final Ack Indicator set, 
         * it shall perform an abnormal release with random access.
         */
        SET_STATE(RU,RU_NULL);
        TRACE_ERROR( "FBI set, but cv > 0" );   
        sig_ru_tm_error_ra();
      }
      break;
    case RU_UACK:
      grlc_data->ru.va = grlc_data->ru.vs;
      ru_handle_stall_ind();
      break;
    case RU_REL_UACK:
      /* 
       * For proper release of ul tbf
       */
      vsi_t_stop(GRLC_handle,T3182);
      grlc_data->ru.va = grlc_data->ru.vs;
      ru_handle_stall_ind();
      if(sp)
      {
        grlc_data->ru.poll_fn = grlc_calc_new_poll_pos(fn,rrbp);
        grlc_data->ru.poll_tn = tn;
        if( d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.f_ack_ind)
        {          
          SET_STATE(RU,RU_SEND_PCA);
          ru_delete_prims(grlc_data->ru.vs);

#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH
          if(d_ul_ack->gprs_ul_ack_nack_info.release_99_str_d_ul_ack.tbf_est EQ 1 AND
             grlc_data->prim_start_tbf NEQ END_OF_LIST  AND /*UL data is present*/
             grlc_data->tbf_type       NEQ TBF_TYPE_CONC    /* No DL TBF */
            )
          {
            grlc_data->ru.tbf_re_est = TRUE;
            grlc_data->next_poll_array[grlc_data->poll_start_tbf].poll_type[tn] = CGRLC_POLL_RE_ASS;
          }
#endif
        }  
      }
      /*
       * this part is a workaround to pass GCF 14.16.1
       * R&S is not setting the sp bit in final ack
       */
      else if( d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.f_ack_ind                AND
              (grlc_data->ru.cv EQ 0)                          AND
              (grlc_data->testmode.mode EQ CGRLC_TEST_RANDOM))
      {
        TRACE_EVENT("SP bit not set in PULACK, FBI BIT SET --> PERFORM IMMEDIATE RELEASE DURING TMA");
        sig_ru_tm_error_ra();
      }
      else if( d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.f_ack_ind                AND
              (grlc_data->testmode.mode EQ CGRLC_TEST_RANDOM))
      {
        TRACE_EVENT_P3("SP=0,FBI=1,CV=%d-> rlc_oct=%ld,sdu_l=%ld"
                                                                ,grlc_data->ru.cv
                                                                ,grlc_data->ru.rlc_octet_cnt
                                                                ,grlc_data->ru.sdu_len);
      }
      break;
    case RU_SEND_PCA :
      if(sp)
      {
        grlc_data->ru.poll_fn = grlc_calc_new_poll_pos(fn,rrbp);
        grlc_data->ru.poll_tn = tn;
        TRACE_EVENT_P1("NEW RU POLL FN AT =%ld ",grlc_data->ru.poll_fn);

#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH
        /* 
         * tbf re-establishment on pacch 
         */
        if(  d_ul_ack->gprs_ul_ack_nack_info.release_99_str_d_ul_ack.tbf_est         EQ  1            AND /* network wishes to re-estab tbf on pacch */
             grlc_data->prim_start_tbf NEQ END_OF_LIST  AND /* ul data is present*/
             grlc_data->tbf_type       NEQ TBF_TYPE_CONC    /* no dl tbf */
          )
        {
          grlc_data->ru.tbf_re_est = TRUE;
          grlc_data->next_poll_array[grlc_data->poll_start_tbf].poll_type[tn] = CGRLC_POLL_RE_ASS;           
        }
#endif
      }    
      break;
    default:
      TRACE_ERROR( "SIG_GFF_RU_UL_ACK unexpected" );
      break;
  }
  if(grlc_data->ru.cs_type NEQ (T_CODING_SCHEME)d_ul_ack->gprs_ul_ack_nack_info.chan_coding_cmd)
  {
    TRACE_EVENT_P7("ul ack:CS changed from %d to %d, ssn=%d, va=%d, vs=%d, neg_acked_blks=%d, fbi=%d ",
                                                grlc_data->ru.cs_type,
                                                d_ul_ack->gprs_ul_ack_nack_info.chan_coding_cmd,
                                                d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.ssn,
                                                grlc_data->ru.va,
                                                grlc_data->ru.vs,
                                                grlc_data->ru.nr_nacked_blks,
                                                d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.f_ack_ind);
    grlc_data->ru.cs_type = (T_CODING_SCHEME)d_ul_ack->gprs_ul_ack_nack_info.chan_coding_cmd;
    ru_change_of_cs(grlc_data->ru.cs_type);    
  }
  else if(grlc_data->ru.nr_nacked_blks OR d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.f_ack_ind)
  {
    ULONG rbb=0,i,dummy;
    for(i=0; i<d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.ssn;i++)
    {
      dummy = (USHORT)d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.rbb[WIN_SIZE-1-i];
      rbb  += dummy <<i; 
      if(i EQ 31)
        break;
    }
    TRACE_EVENT_P8("ul ack fn=%ld :ssn=%d,va=%d,vs=%d,neg_acked_blks=%d,fbi=%d,rbb=%lx,cnt_ts=%d",
                                                fn,
                                                d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.ssn,
                                                grlc_data->ru.va,
                                                grlc_data->ru.vs,
                                                grlc_data->ru.nr_nacked_blks,
                                                d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.f_ack_ind,
                                                rbb,
                                                grlc_data->ru.cnt_ts);
  }
  grlc_data->ru.bsn_ret = grlc_data->ru.va;


  
} /* sig_gff_ru_ul_ack() */


/*
+------------------------------------------------------------------------------
| Function    : sig_gff_ru_mac_ready_ind
+------------------------------------------------------------------------------
| Description : Handles the Signal SIG_GFF_RU_MAC_READY_IND
|
| Parameters  : *ptr_mac_ready_ind_i - Ptr to primitive MAC_READY_IND
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_gff_ru_mac_ready_ind ( T_MAC_READY_IND * mac_ul_ready_ind) 
{ 
  UBYTE             bsn=0xFF;
  BOOL              release_tbf=FALSE;
  UBYTE             rd_state=GET_STATE( RD );
  UBYTE ctrl_blk_active_idx;
  BOOL realloc_prr_allowed = FALSE;

  TRACE_ISIG( "sig_gff_ru_mac_ready_ind" );


#if defined (_SIMULATION_)
      TRACE_EVENT_P1("fn = %ld",mac_ul_ready_ind->fn ); 
      TRACE_EVENT_P9("wpi=%d sent=%ld\n current.cnt=%d,bsn[0]=%d,bsn[1]=%d,bsn[2]=%d,bsn[3]=%d,nts=%d,nts_max=%d",
                                                      grlc_data->ru.write_pos_index,
                                                      mac_ul_ready_ind->rlc_blocks_sent,
                                                      grlc_data->ru.pl_retrans_current.cnt,
                                                      grlc_data->ru.pl_retrans_current.blk[0],
                                                      grlc_data->ru.pl_retrans_current.blk[1],
                                                      grlc_data->ru.pl_retrans_current.blk[2],
                                                      grlc_data->ru.pl_retrans_current.blk[3],
                                                      grlc_data->ru.nts,
                                                      grlc_data->ru.nts_max);
#endif /* defined (_SIMULATION_) */

  ru_switch_ul_buffer (mac_ul_ready_ind->rlc_blocks_sent);
  ru_check_pl_ret(mac_ul_ready_ind->rlc_blocks_sent);
  if(grlc_data->ru.v_next_tbf_params AND
     grlc_check_if_tbf_start_is_elapsed ( grlc_data->ul_tbf_start_time, ((mac_ul_ready_ind->fn+5)%FN_MAX)))
  {
    ru_handle_tbf_start_in_ptm( mac_ul_ready_ind->rlc_blocks_sent);
    ru_cgrlc_st_time_ind();
  }
  grlc_handle_poll_pos (mac_ul_ready_ind->fn);
  ru_handle_nts (mac_ul_ready_ind->rlc_blocks_sent);

  switch( GET_STATE( RU ) )
  {
    case RU_WAIT_FOR_FIRST_CALL_ACK:
      if( !grlc_data->ru.v_next_tbf_params AND
          !grlc_check_if_tbf_start_is_elapsed ( grlc_data->ul_tbf_start_time, ((mac_ul_ready_ind->fn+5)%FN_MAX)))
      {
        TRACE_EVENT_P2("WAIT FOR UL STARTING TIME, DL IS RUNNING st=%ld c_fn=%ld",grlc_data->ul_tbf_start_time
                                                                              ,mac_ul_ready_ind->fn);
        grlc_send_rem_poll_pos(mac_ul_ready_ind->fn);
        return;
      }
      if(grlc_data->ru.first_usf)
      {
        /* 
         * Tbf starting time is reached, start T3164 
         */
        vsi_t_start(GRLC_handle,T3164,T3164_VALUE);
      }
      SET_STATE(RU,RU_ACK);
      grlc_data->tbf_ctrl[grlc_data->ul_index].start_fn = mac_ul_ready_ind->fn;      
      if(!grlc_data->ru.cd_active AND 
        (grlc_data->ru.tbc <= grlc_data->uplink_tbf.bs_cv_max))
      {
        grlc_data->ru.cd_active = TRUE;
        ru_set_prim_queue(grlc_data->ru.cd_active);
      }
      ru_cgrlc_st_time_ind();
      TRACE_EVENT_P9 ("UL first call:fn=%ld (%ld) tfi=%d ul_mask=%x st_fn=%ld pdu_cnt=%d,PST=%d,PSF=%d ta=%d",
                                            mac_ul_ready_ind->fn,
                                            mac_ul_ready_ind->fn%42432,
                                            grlc_data->ul_tfi,                                           
                                            grlc_data->ul_tn_mask,
                                            grlc_data->ul_tbf_start_time,
                                            grlc_data->grlc_data_req_cnt,
                                            grlc_data->prim_start_tbf,
                                            grlc_data->prim_start_free,
                                            grlc_data->ta_value);

      /*lint -fallthrough*/

    case RU_ACK     :
      /*
       * Handling of counter N3104
       */
      if(ru_handle_n3104())
      {
        SET_STATE(RU,RU_NULL);
        TRACE_ERROR( "counter N3104 reaches its maximum, contention resolution has failed" );
        TRACE_EVENT_P7("va=%d,vs=%d,cnt_ts=%d,fn=%d n3104_max=%d,n3104=%d,bs_cv_max=%d",
                                                  grlc_data->ru.va,
                                                  grlc_data->ru.vs,
                                                  grlc_data->ru.cnt_ts,
                                                  mac_ul_ready_ind->fn,
                                                  grlc_data->ru.N3104_MAX,
                                                  grlc_data->ru.N3104,
                                                  grlc_data->uplink_tbf.bs_cv_max);
        sig_ru_tm_error_ra();
        return;
      }
      /* 
       * IS THERE A CONTROL BLOCK TO SEND ? 
       */
      while(  grlc_data->ru.nts              AND
             !grlc_data->ru.cd_active        AND
              tm_get_num_ctrl_blck( ) NEQ 0     )
      { /* 
         * next uplink block is a control block, 
         *  check if countdown procedure is statred or not
         */
        ru_send_control_block( );
      }

      /* 
       * IS RETRANSMISSION NEEDED ? 
       */
      while(grlc_data->ru.nts)
      { 
        ctrl_blk_active_idx = ru_peek_for_ctrl_blk();
        if ((ctrl_blk_active_idx EQ 0xFF) OR
          realloc_prr_allowed EQ TRUE)     /*No control block , form data block*/
        { 
          while( (grlc_data->ru.vb[grlc_data->ru.bsn_ret & WIN_MOD] EQ VB_NACKED) AND 
                  grlc_data->ru.nts)
          {
            ru_ret_bsn();
          }

          while(grlc_data->ru.nts) 
          {  
           /* 
            * IS THERE A STALL CONDITION ? 
            */
            if(grlc_data->ru.vs EQ ((grlc_data->ru.va + WIN_SIZE) & 0x7F))
            {
              ru_stall_ind();
            }
           /* 
            * IS THERE MORE DATA ?
            */   
            else if(grlc_data->ru.sdu_len)
            {
              ru_new_data();
            }
            else
            {
              break;
            }
          } 
          realloc_prr_allowed = FALSE;
          break;
        }
        else
        {
          
          TRACE_EVENT_P1("reallocation of llc pdu (index)=%d",ctrl_blk_active_idx);
          
          /* if already one PRR in L1 Buffer , replace it with new PRR */
          if (grlc_data->ru.pl_retrans_current.blk[0]
            EQ (BLK_INDEX_TM + OFFSET_CTRL_BLOCK_IDX))
          {      
            grlc_data->ru.write_pos_index--;
            grlc_data->ru.pl_retrans_current.cnt--;
            grlc_data->ru.nts++;  
            TRACE_EVENT("prr in l1 buffer queue,replace with new prr");
          }
          sig_ru_tm_end_of_pdu(ctrl_blk_active_idx);    
          ru_send_control_block();    
          realloc_prr_allowed = TRUE;      
        }
      }
      if( grlc_data->ru.cv EQ 0)
      {
        SET_STATE(RU,RU_REL_ACK);
        grlc_data->ru.bsn_ret = grlc_data->ru.va;  
      }
      while(grlc_data->ru.nts)
      {
        ru_ret_bsn();
      }
      grlc_send_rem_poll_pos (mac_ul_ready_ind->fn);
      break;
    case RU_REL_ACK :
      /*
       * All blocks are sent, wait for the last ack.
       * If uplink resources are available retransmit window
       */
      if(ru_handle_n3104())
      {
        SET_STATE(RU,RU_NULL);
        TRACE_ERROR( "counter N3104 reaches its maximum, contention resolution has failed" );
        sig_ru_tm_error_ra();
        grlc_data->ru.nts = 0; /*to avoid transmitting of data*/
        return;
      }

      /* 
       * IS THERE A CONTROL BLOCK TO SEND ? 
       */
      while(  grlc_data->ru.nts              AND      
              tm_get_num_ctrl_blck( ) NEQ 0  AND
              ru_ctrl_blk_selection_allowed())
      { 
        /* 
         * next uplink block is a control block,          
         */
        TRACE_EVENT("Ctrl blk selected in RU_REL_ACK");
        ru_send_control_block( );
      }
      while(grlc_data->ru.nts)
      { 
        ctrl_blk_active_idx = ru_peek_for_ctrl_blk();
        if ((ctrl_blk_active_idx EQ 0xFF) OR
          realloc_prr_allowed EQ TRUE)     /*No control block , form data block*/
        { 
          while(grlc_data->ru.nts AND (grlc_data->ru.va NEQ grlc_data->ru.vs))
          {
            ru_ret_bsn();
          }
      
          while(grlc_data->ru.nts)
          {
            TRACE_EVENT_P3("ALL BLKS ACKED, wait for fbi in PUAN wpi=%d t3182=%d t3180=%d"
                                                                ,grlc_data->ru.write_pos_index
                                                                ,grlc_t_status( T3182 )
                                                                ,grlc_t_status( T3180 ));
            ru_send_ul_dummy_block();
          }
          realloc_prr_allowed = FALSE;
          break;
        }
        else
        {
          
          TRACE_EVENT_P1("reallocation of llc pdu (index)=%d",ctrl_blk_active_idx);
          
          /* if already one PRR in L1 Buffer , replace it with new PRR */
          if (grlc_data->ru.pl_retrans_current.blk[0]
            EQ (BLK_INDEX_TM + OFFSET_CTRL_BLOCK_IDX))
          {      
            grlc_data->ru.write_pos_index--;
            grlc_data->ru.pl_retrans_current.cnt--;
            grlc_data->ru.nts++;  
            TRACE_EVENT("prr in l1 buffer queue,replace with new prr");
          }
          sig_ru_tm_end_of_pdu(ctrl_blk_active_idx);    
          ru_send_control_block();    
          realloc_prr_allowed = TRUE;      
        }
      }
      grlc_send_rem_poll_pos (mac_ul_ready_ind->fn);
      break;
    case RU_SEND_PCA:
      while(grlc_data->ru.nts)
      {
        ru_send_ul_dummy_block();
      }
#ifdef _TARGET_     
      if( grlc_check_dist(mac_ul_ready_ind->fn,grlc_data->ru.poll_fn,100) )
      {      
        if ((mac_ul_ready_ind->fn NEQ grlc_data->ru.poll_fn) AND 
            (mac_ul_ready_ind->last_poll_resp EQ 0))
        {
          release_tbf = TRUE;
          /*TRACE_EVENT_P2("REL TBF:fn =%ld  new ru_poll_fn=%ld",
                                                                mac_ul_ready_ind->fn,
                                                                grlc_data->ru.poll_fn);*/

        }
        else if(mac_ul_ready_ind->last_poll_resp)
        {
          grlc_data->ru.poll_fn +=104;
          grlc_data->ru.poll_fn %= FN_MAX;
          TRACE_ERROR("UL GAP: UL TBF NOT RELEASED +104");
          TRACE_EVENT_P3("fn =%ld   new ru_poll_fn=%ld poll_staus=%d",
                                                                mac_ul_ready_ind->fn,
                                                                grlc_data->ru.poll_fn,
                                                                mac_ul_ready_ind->last_poll_resp);
        }
        if(grlc_data->missed_poll_fn EQ grlc_data->ru.poll_fn)
        {
          release_tbf = FALSE;
          grlc_data->ru.poll_fn +=104;
          grlc_data->ru.poll_fn %= FN_MAX;
          TRACE_ERROR("DL GAP: UL TBF NOT RELEASED +104");
          TRACE_EVENT_P3("fn =%ld   missed poll=%ld new ru_poll_fn=%ld",
                                                                mac_ul_ready_ind->fn,
                                                                grlc_data->missed_poll_fn,
                                                                grlc_data->ru.poll_fn);
        }

      }
#endif
#ifdef _SIMULATION_
      if(mac_ul_ready_ind->fn EQ grlc_data->ru.poll_fn)
        release_tbf = TRUE;
#endif
      grlc_send_rem_poll_pos (mac_ul_ready_ind->fn);
      if(release_tbf) 
      {
        vsi_t_stop(GRLC_handle,T3182);
        vsi_t_stop(GRLC_handle,T3180);
        if ( grlc_data->poll_start_tbf NEQ 0xFF  AND
             (!grlc_check_if_tbf_start_is_elapsed(grlc_data->dl_tbf_start_time,grlc_data->next_poll_array[grlc_data->   
                                                                     poll_start_tbf].fn)                AND
             (rd_state EQ RD_WAIT_FOR_STARTING_TIME_ACK  OR
              rd_state EQ RD_WAIT_FOR_STARTING_TIME_UACK)) )
        {
          grlc_data->ru.poll_fn = grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn;
          TRACE_EVENT_P2("UL DELAYED WHILE WAITING STARTING TIME DL poll_fn=%ld c_fn=%ld",grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn
                                                                              ,mac_ul_ready_ind->fn);
        }
        else
        {
          SET_STATE(RU,RU_NULL);
          grlc_data->tbf_ctrl[grlc_data->ul_index].end_fn = grlc_data->ul_fn;
          grlc_data->tbf_ctrl[grlc_data->ul_index].vs_vr  = grlc_data->ru.vs;
          grlc_data->tbf_ctrl[grlc_data->ul_index].va_vq  = grlc_data->ru.va;
          grlc_data->tbf_ctrl[grlc_data->ul_index].cnt_ts = grlc_data->ru.cnt_ts;
          grlc_trace_tbf_par ( grlc_data->ul_index );

#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH
          if(grlc_data->ru.tbf_re_est) 
          {
            /* 
             * signal tm to start timer 3168,re-establish tbf on pacch as poll sent succesfully 
             */
            sig_ru_tm_ul_re_est_tbf();
          }
          else 
#endif
          {
            sig_ru_tm_end_of_tbf();
          }
        }      
      }      
      break;

    case RU_WAIT_FOR_FIRST_CALL_UACK:
      if( !grlc_data->ru.v_next_tbf_params AND
          !grlc_check_if_tbf_start_is_elapsed ( grlc_data->ul_tbf_start_time, ((mac_ul_ready_ind->fn+5)%FN_MAX)))
      {
        TRACE_EVENT_P2("UACK MODE WAIT FOR UL STARTING TIME, DL IS RUNNING st=%ld c_fn=%ld",grlc_data->ul_tbf_start_time
                                                                              ,mac_ul_ready_ind->fn);
        grlc_send_rem_poll_pos(mac_ul_ready_ind->fn);
        return;
      }
      if(grlc_data->ru.first_usf)
      {
        /* 
         * Tbf starting time is reached, start T3164 
         */
        vsi_t_start(GRLC_handle,T3164,T3164_VALUE);
      }
      grlc_data->tbf_ctrl[grlc_data->ul_index].start_fn = mac_ul_ready_ind->fn;
      SET_STATE(RU,RU_UACK);
      if(!grlc_data->ru.cd_active AND 
        (grlc_data->ru.tbc <= grlc_data->uplink_tbf.bs_cv_max))
      {
        grlc_data->ru.cd_active = TRUE;
        ru_set_prim_queue(grlc_data->ru.cd_active);
      }
      ru_cgrlc_st_time_ind();
      TRACE_EVENT_P9 ("UL first call:fn=%ld (%ld) tfi=%d ul_mask=%x st_fn=%ld pdu_cnt=%d,PST=%d,PSF=%d ta=%d  UACK_MODE",
                                            mac_ul_ready_ind->fn,
                                            mac_ul_ready_ind->fn%42432,
                                            grlc_data->ul_tfi,                                           
                                            grlc_data->ul_tn_mask,
                                            grlc_data->ul_tbf_start_time,
                                            grlc_data->grlc_data_req_cnt,
                                            grlc_data->prim_start_tbf,
                                            grlc_data->prim_start_free,
                                            grlc_data->ta_value);
      /*lint -fallthrough*/

    case RU_UACK    :
      ru_del_prim_in_uack_mode ( mac_ul_ready_ind->rlc_blocks_sent);
      if(grlc_data->ru.last_bsn EQ LAST_BSN_STALL_CONDITION)
      { /*in uack mode is transmission at stall condition of data not allowed*/
        grlc_data->ru.nts = 0;
      }
      else if (grlc_data->ru.last_bsn EQ LAST_BSN_RESUME_UACK_MODE_AFTER_SI)
      { /* data transmission allowed after stall indication in rlc unackgnowledged mode*/
        grlc_data->ru.nts = grlc_data->ru.nts_max; 
        grlc_data->ru.last_bsn = LAST_BSN_NOT_BULIT;
        TRACE_EVENT(" STALL IND ELIMINATED IN RLC UACK");
      } 
      /* 
       * IS THERE A CONTROL BLOCK TO SEND ? 
       */
      while(  grlc_data->ru.nts              AND
             !grlc_data->ru.cd_active        AND
              tm_get_num_ctrl_blck( ) NEQ 0     )
      { 
        ru_send_control_block( );
      }
      /* 
       * IS THERE MORE DATA ?
       */
      while(grlc_data->ru.nts)
      { 
        ctrl_blk_active_idx = ru_peek_for_ctrl_blk();
        if ((ctrl_blk_active_idx EQ 0xFF) OR
          realloc_prr_allowed EQ TRUE)     /*No control block , form data block*/
        { 
          while( grlc_data->ru.nts AND 
                 grlc_data->ru.sdu_len )
          {
            ru_new_data();
          }
          if (grlc_test_mode_active())
          {
            /* 
             * to prevent stall indication in Testmode A/B
             */
            grlc_data->ru.va = grlc_data->ru.vs;
          }

          while( grlc_data->ru.nts 
                AND (grlc_data->ru.count_cv_0 < 4) )
          {
            bsn = (grlc_data->ru.vs - 1) % 128;
            ru_send_mac_data_req(bsn);
            grlc_data->ru.count_cv_0++;
          }
          while(grlc_data->ru.nts)
          {
            ru_send_ul_dummy_block();
          }
          realloc_prr_allowed = FALSE;
          break;
        }
        else
        {
          
          TRACE_EVENT_P1("reallocation of llc pdu (index)=%d",ctrl_blk_active_idx);
          
          /* if already one PRR in L1 Buffer , replace it with new PRR */
          if (grlc_data->ru.pl_retrans_current.blk[0]
            EQ (BLK_INDEX_TM + OFFSET_CTRL_BLOCK_IDX))
          {      
            grlc_data->ru.write_pos_index--;
            grlc_data->ru.pl_retrans_current.cnt--;
            grlc_data->ru.nts++;  
            TRACE_EVENT("prr in l1 buffer queue,replace with new prr");
          }
          sig_ru_tm_end_of_pdu(ctrl_blk_active_idx);    
          ru_send_control_block();    
          realloc_prr_allowed = TRUE;      
        }
      }

      if(grlc_data->ru.cv EQ 0)
      {
        SET_STATE(RU,RU_REL_UACK);
      }
      grlc_send_rem_poll_pos (mac_ul_ready_ind->fn);
      break;      
    case RU_REL_UACK:
      ru_del_prim_in_uack_mode ( mac_ul_ready_ind->rlc_blocks_sent);      
	  
      /* 
       * IS THERE A CONTROL BLOCK TO SEND ? 
       */
      while(  grlc_data->ru.nts              AND      
              tm_get_num_ctrl_blck( ) NEQ 0  AND
              ru_ctrl_blk_selection_allowed())
      { 
        /* 
         * next uplink block is a control block,          
         */
        TRACE_EVENT("Ctrl blk selected in RU_REL_UACK");
        ru_send_control_block( );
      }
      while(grlc_data->ru.nts)
      { 
        ctrl_blk_active_idx = ru_peek_for_ctrl_blk();
        if ((ctrl_blk_active_idx EQ 0xFF) OR
          realloc_prr_allowed EQ TRUE)     /*No control block , form data block*/
        { 
          while( grlc_data->ru.nts AND 
                (grlc_data->ru.count_cv_0 < 4) )
          {
            bsn = (grlc_data->ru.vs - 1) % 128;
            ru_send_mac_data_req(bsn);
            grlc_data->ru.count_cv_0++;
          }
          while(grlc_data->ru.nts)
          {
            ru_send_ul_dummy_block();
          }
          realloc_prr_allowed = FALSE;
          break;
        }
        else
        {
          
          TRACE_EVENT_P1("reallocation of llc pdu (index)=%d",ctrl_blk_active_idx);
          
          /* if already one PRR in L1 Buffer , replace it with new PRR */
          if (grlc_data->ru.pl_retrans_current.blk[0]
            EQ (BLK_INDEX_TM + OFFSET_CTRL_BLOCK_IDX))
          {      
            grlc_data->ru.write_pos_index--;
            grlc_data->ru.pl_retrans_current.cnt--;
            grlc_data->ru.nts++;  
            TRACE_EVENT("prr in l1 buffer queue,replace with new prr");
          }
          sig_ru_tm_end_of_pdu(ctrl_blk_active_idx);    
          ru_send_control_block();    
          realloc_prr_allowed = TRUE;      
        }
      }
      grlc_send_rem_poll_pos (mac_ul_ready_ind->fn);
      break;
      case RU_NET_REL:       
      /* 
       * send packet control acknowledgement and abort TBF
       */
      grlc_send_rem_poll_pos(mac_ul_ready_ind->fn);
      if(grlc_data->ru.release_tbf)
      {
        SET_STATE(RU,RU_NULL);
        grlc_data->ru.release_tbf = FALSE;                
        TRACE_EVENT_P2("poll sent after packet tbf release(UL): current_fn=%ld rel_fn=%ld",
                                        mac_ul_ready_ind->fn,
                                        grlc_data->ru.poll_fn);
        vsi_t_stop(GRLC_handle,T3180);
        vsi_t_stop(GRLC_handle,T3182);
        grlc_data->tbf_ctrl[grlc_data->ul_index].end_fn = grlc_data->ul_fn;
        grlc_data->tbf_ctrl[grlc_data->ul_index].vs_vr  = grlc_data->ru.vs;
        grlc_data->tbf_ctrl[grlc_data->ul_index].va_vq  = grlc_data->ru.va;
        grlc_data->tbf_ctrl[grlc_data->ul_index].cnt_ts = grlc_data->ru.cnt_ts;
        grlc_trace_tbf_par ( grlc_data->ul_index );
        sig_ru_tm_end_of_tbf();
      }
      if(grlc_check_if_tbf_start_is_elapsed ( grlc_data->ru.poll_fn, mac_ul_ready_ind->fn))
      {
        grlc_data->ru.release_tbf = TRUE;
        TRACE_EVENT_P2("wait for poll confirm after packet tbf release(UL) current_fn=%ld rel_fn=%ld",
                                        mac_ul_ready_ind->fn,
                                        grlc_data->ru.poll_fn);
      }
      break;
    default:
      TRACE_ERROR( "MAC_UL_READY_IND unexpected" );
      break;
  }

  if(grlc_data->uplink_tbf.mac_mode EQ CGRLC_MAC_MODE_FA  AND 
     grlc_data->uplink_tbf.fa_manag.current_alloc.alloc_end_fn EQ mac_ul_ready_ind->fn)
  {
    sig_ru_tm_end_of_fix_alloc();
  }



} /* sig_gff_ru_mac_ready_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_tm_ru_reset_poll_array
+------------------------------------------------------------------------------
| Description : Handles the Signal SIG_TM_RU_RESET_POLL_ARRAY.  
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/

GLOBAL void sig_tm_ru_reset_poll_array()
{
  UBYTE i,j;
  /*
   * handle not_transmitted control blocks
  */
  for (i=0;i<NEXT_POLL_ARRAY_SIZE;i++)
  { 
    /*
     * set free list
     */
    grlc_data->next_poll_array[i].next      = i+1;
    grlc_data->next_poll_array[i].fn        = 0xFFFFFFFF;
    grlc_data->next_poll_array[i].cnt       = 0;
    for(j=0; j< POLL_TYPE_ARRAY_SIZE; j++)
    {
      grlc_data->next_poll_array[i].poll_type[j] = CGRLC_POLL_NONE;
    }
  }
  /* 
   * last free entry points to 0xff
   */ 
  grlc_data->next_poll_array[NEXT_POLL_ARRAY_SIZE-1].next = 0xFF;  
  /* 
   * indicates invalid paramters
   */
  grlc_data->poll_start_free = 0;
  grlc_data->poll_start_tbf  = 0xFF;  
}