view src/g23m-gprs/grr/grr_f.c @ 662:8cd8fd15a095

SIM speed enhancement re-enabled and made configurable TI's original code supported SIM speed enhancement, but Openmoko had it disabled, and OM's disabling of speed enhancement somehow caused certain SIM cards to start working which didn't work before (OM's bug #666). Because our FC community is much smaller in year 2020 than OM's community was in their day, we are not able to find one of those #666-affected SIMs, thus the real issue they had encountered remains elusive. Thus our solution is to re-enable SIM speed enhancement and simply wait for if and when someone runs into a #666-affected SIM once again. We provide a SIM_allow_speed_enhancement global variable that allows SIM speed enhancement to be enabled or disabled per session, and an /etc/SIM_spenh file in FFS that allows it to enabled or disabled on a non-volatile basis. SIM speed enhancement is now enabled by default.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 24 May 2020 05:02:28 +0000
parents 219afcfc6250
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  GPRS (8441)
|  Modul   :  GRR
+----------------------------------------------------------------------------- 
|  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 global functions for GRR
+----------------------------------------------------------------------------- 
*/ 

#ifndef GRR_F_C
#define GRR_F_C
#endif

#define ENTITY_GRR

#ifdef _SIMULATION_

/*
 * Report warning 4005 as an error.
 * 
 * There are identical macro definitons in the GRR message and the RRGRR SAP 
 * document which should be aligned at all the time
 * (e.g. GPRS_RXLEV_ACCESS_MIN_INVALID, GPRS_MS_TXPWR_MAX_CCH, etc.)
 */
#pragma warning( error : 4005 )

#endif /* #ifdef _SIMULATION_ */

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

#include <stdio.h>
#include <string.h>     /* to get definition of memcpy() */ 
#include <math.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_grr.h"    /* to get cnf-definitions                            */
#include "mon_grr.h"    /* to get mon-definitions                            */
#include "prim.h"       /* to get the definitions of used SAP and directions */
#include "message.h"    /* to get message describtion                        */
#include "pcm.h"

#include "grr.h"        /* to get the global entity definitions              */

#include "grr_f.h"      /* to check own definitions         */
#include "grr_ctrlf.h"  /* to get definition of ctrl_init() */
#include "grr_tcf.h"    /* to get definition of tc_init()   */
#include "grr_cpapf.h"  /* to get definition of cpap_init() */
#include "grr_psif.h"   /* to get definition of psi_init()  */
#include "grr_pgf.h"    /* to get definition of pg_init()   */
#include "grr_gfpf.h"   /* to get definition of gfp_init()  */
#include "grr_meass.h"  /* to get definition of meas_init() */
#include "grr_csf.h"    /* to get definition of cs_init()   */
#include "grr_tcs.h"
#include "grr_em.h"     /*for Engineering mode*/ 

/*==== CONST ================================================================*/
/*
 * Mask- and shift tables for use with macro GET_N_BITS(N)
 */
static const 
UBYTE maskTab1[] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };

static const 
UBYTE maskTab2[] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 };

static const 
UBYTE shiftTab[] = { 0x00, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 };
/*==== DIAGNOSTICS ==========================================================*/

/*==== LOCAL VARS ===========================================================*/

static UBYTE* pBuf;     /* Global Var: pointer to air message data buffer    */
static int    startBit; /* Global Var: current pBuf decode offset            */
static int    bitLen;   /* Global Var: current remaining undecoded pbuf bits */
LOCAL T_LIST _local_dummy_list;
LOCAL T_f_range _local_rfl_contents;
/*==== GLOBAL VARS ===========================================================*/

/*==== LOCAL MACROS =========================================================*/
/*
 * GET_N_BITS reads next N (1..8) bits from UBYTE* pBuf, starting from integer
 * startBit. N is added to startBit and removed from bitLen after call to this 
 * macro.
 */
#define GET_N_BITS(N)                                                         \
          (( (startBit%8) + (N) <= 8)                                         \
           ? (pBuf[startBit/8] >> shiftTab[(startBit+(N))%8]) & maskTab1[N]   \
           : (pBuf[(startBit+(N))/8] >> shiftTab[(startBit+(N))%8]) +         \
           ((pBuf[startBit/8] & maskTab2[startBit%8]) << ((startBit+(N))%8))  \
          ); startBit += (N); bitLen -= (N)


/*==== FUNCTIONS PROTOTYPES =================================================*/
LOCAL BOOL grr_check_request_reference ( T_req_ref_p * req_ref_i );
LOCAL BOOL grr_check_glob_tfi ( T_glob_tfi * glob_tfi_i, UBYTE tn );
LOCAL BOOL grr_check_add_reject ( UBYTE tn );
LOCAL BOOL grr_check_add_1 ( T_add1 * add1_i,UBYTE tn );
LOCAL BOOL grr_check_add_2 ( T_add2 * add2_i,UBYTE tn );
LOCAL BOOL grr_check_add_3 ( T_add3 * add3_i,UBYTE tn );
LOCAL BOOL grr_check_add_4 ( T_add4 * add4_i,UBYTE tn );
LOCAL void grr_clean_up_seg_ctrl_blk_tbl ( void );
LOCAL void grr_align_seg_ctrl_blk_nxt ( void );

LOCAL UBYTE grr_decode_ie_tlli (BUF_tlli_value* tlli);
LOCAL UBYTE grr_decode_ie_pta (T_pta* pta);
LOCAL UBYTE grr_decode_ie_pwr_par (T_pwr_par* pwr_par);
LOCAL UBYTE grr_decode_ie_glob_tfi (T_glob_tfi* glob_tfi);
LOCAL UBYTE grr_decode_ie_meas_map (T_meas_map* meas_map);
LOCAL UBYTE grr_decode_ie_tbf_s_time (T_tbf_s_time* tbf_s_time);
LOCAL UBYTE grr_decode_ie_dyn_alloc_p (T_dyn_alloc_p* dyn_alloc_p);
LOCAL UBYTE grr_decode_ie_dyn_alloc_ts (T_dyn_alloc_ts* dyn_alloc_ts);
LOCAL UBYTE grr_decode_ie_freq_par (T_freq_par* freq_par);

LOCAL UBYTE grr_decode_dl_assignment (UBYTE* buf, int off, int len);
LOCAL UBYTE grr_decode_ul_assignment (UBYTE* buf, int off, int len);
LOCAL UBYTE grr_decode_ts_reconfig (UBYTE* buf, int off, int len);

LOCAL UBYTE grr_decode_pdch_release (UBYTE* buf, int off, int len);
LOCAL UBYTE grr_decode_polling_req (UBYTE* buf, int off, int len);
LOCAL UBYTE grr_decode_tbf_release_req (UBYTE* buf, int off, int len);

#ifdef REL99
LOCAL UBYTE grr_decode_ie_egprs_link_adpt_para(T_egprs_link_adpt_para *trgt);
LOCAL UBYTE  grr_decode_ie_compact_red_ma(T_compact_red_ma *trgt);
#endif

LOCAL void  grr_init_ms_data     ( void                                 );

/*
 * transmit power control 
 */
LOCAL void  grr_set_alpha_flags  ( BOOL              v_alpha,
                                   UBYTE             alpha              );

LOCAL void  grr_set_sngl_gamma   ( UBYTE             gamma,
                                   UBYTE             tn                 );

/*
 * NC and extended measurements
 */
LOCAL void  grr_init_rfreq_list  ( T_NC_RFREQ_LIST  *list               );

LOCAL void  grr_init_ncmeas_struct
                                 ( T_NCMEAS         *ncmeas,
                                   BOOL              is_cw              );

LOCAL void  grr_copy_em1_struct  ( T_XMEAS_EM1      *db_em1,
                                   T_em1            *ext_em1,
                                   BOOL              cpy_prm_set,
                                   UBYTE            *start_ext_lst_idx,
                                   UBYTE            *stop_ext_lst_idx   );

/*
 * database management
 */
LOCAL void  grr_init_db_srvc_param ( T_SC_DATABASE *db      );

LOCAL UBYTE grr_get_db_num         ( T_SC_DATABASE *db      );

/*
 * miscellaneous
 */
LOCAL void  grr_mrk_ext_lst_freq   ( T_EXT_FREQ_LIST *list  );

LOCAL UBYTE grr_ccd_error_handling ( UBYTE    entity_i      );

LOCAL void  grr_get_si_cell_alloc_list  ( T_LIST     *list  );

LOCAL BOOL  grr_get_psi_cell_alloc_list ( T_LIST     *list  );

LOCAL BOOL  grr_get_ms_alloc_list       ( T_LIST             *list,
                                          const T_gprs_ms_alloc_ie *ms_alloc );
/*==== FUNCTIONS ============================================================*/

/*
+------------------------------------------------------------------------------
| Function    : grr_check_request_reference
+------------------------------------------------------------------------------
| Description : The function grr_check_request_reference() compares the addresses
|               in req_ref_i with the entity data ent returns TRUE if the address
|               in req_ref_i is valid otherwise FALSE
|
| Parameters  : tlli_i - ptr to tlli buffer
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL grr_check_request_reference ( T_req_ref_p * req_ref_i )
{ 
  BOOL result = FALSE;
  UBYTE i,t1,t2,t3;
  USHORT acc_inf;

  t1 = req_ref_i->fn_mod.t1;
  t2 = req_ref_i->fn_mod.t2;
  t3 = req_ref_i->fn_mod.t3;
  acc_inf = req_ref_i->access_info;

  TRACE_FUNCTION( "grr_check_request_reference" );

  for(i=0;i<3;i++)
  {
    if( 
        (grr_data->req_ref[i].fn_mod.t1 EQ t1 )
        AND
        (grr_data->req_ref[i].fn_mod.t2 EQ t2 )
        AND
        (grr_data->req_ref[i].fn_mod.t3 EQ t3 )
        AND
        (grr_data->req_ref[i].access_info EQ acc_inf )
      )
    {
      result = TRUE;
      break;
    }
  }

  if(!result)
  {
    TRACE_EVENT("grr_check_request_reference failed");
  }

  return(result);
} /* grr_check_request_reference() */






/*
+------------------------------------------------------------------------------
| Function    : grr_check_glob_tfi();
+------------------------------------------------------------------------------
| Description : The function grr_check_glob_tfi() returns true if the TFI 
|               is correct.
|
| Parameters  : glob_tfi_i - pointer to global TFI structure
|               tn         - timeslot on which the message is received, this is
|                            required, because tfi is valid only for one 
|                            direction and the assigned PDCHs of a TBF(4.60 5.2)
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL grr_check_glob_tfi ( T_glob_tfi * glob_tfi_i, UBYTE tn )
{ 
  
  BOOL result = FALSE;
  TRACE_FUNCTION( "grr_check_glob_tfi" );


  if(glob_tfi_i->v_ul_tfi)
  {
    if((glob_tfi_i->ul_tfi EQ grr_data->uplink_tbf.tfi) AND
      ((0x80>>tn) & grr_data->uplink_tbf.ts_mask))
    {
      result = TRUE;
    }
  }
  else if(glob_tfi_i->v_dl_tfi)
  {
    if((glob_tfi_i->dl_tfi EQ grr_data->downlink_tbf.tfi) AND
      ((0x80>>tn) & grr_data->downlink_tbf.ts_mask))
    {
      result = TRUE;
    }
  }

  if(!result)
  {
    if(glob_tfi_i->v_ul_tfi)
    {
      TRACE_EVENT_P7("grr_check_glob_tfi failed: UL addressed tfi=%d, ul_tfi=%d, dl_tfi=%d || tn=%d ->mask=%x curr_mask=%x, st_mask=%x ",
                                        glob_tfi_i->ul_tfi,
                                        grr_data->uplink_tbf.tfi,
                                        grr_data->downlink_tbf.tfi,
                                        tn,
                                        0x80>>tn,
                                        grr_data->uplink_tbf.ts_mask,
                                        grr_data->uplink_tbf.ts_usage);
    }
    else if(glob_tfi_i->v_dl_tfi)
    {
      TRACE_EVENT_P7("grr_check_glob_tfi failed: DL addressed tfi=%d, ul_tfi=%d, dl_tfi=%d|| tn=%d ->mask=%x curr_mask=%x, st_mask=%x ",
                                        glob_tfi_i->dl_tfi,
                                        grr_data->uplink_tbf.tfi,
                                        grr_data->downlink_tbf.tfi,
                                        tn,
                                        0x80>>tn,
                                        grr_data->downlink_tbf.ts_mask,
                                        grr_data->downlink_tbf.ts_usage);

    }
    else
    {
      TRACE_EVENT("grr_check_glob_tfi failed: NO addressed tfi ");
    }
  }

  return(result);
  
} /* grr_check_glob_tfi() */



/*
+------------------------------------------------------------------------------
| Function    : grr_check_add_reject
+------------------------------------------------------------------------------
| Description : The function grr_check_add_reject() checks the address in
|               addtional rejects in a Packet Access Reject.
|
| Parameters  : tn - timeslot: need to check if tfi is on assigned PDCH
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL grr_check_add_reject ( UBYTE tn )
{ 
  MCAST(access_rej,D_ACCESS_REJ);
  BOOL result = FALSE;

  TRACE_FUNCTION( "grr_check_add_reject" );

  if(access_rej->reject.v_tlli_value)
    result = grr_check_all_tlli(& access_rej->reject.tlli_value);
  else if (access_rej->reject.req_ref_tfi.v_req_ref_p)
    result = grr_check_request_reference( & access_rej->reject.req_ref_tfi.req_ref_p);
  else if (access_rej->reject.req_ref_tfi.v_glob_tfi)
    result = grr_check_glob_tfi(& access_rej->reject.req_ref_tfi.glob_tfi,tn);

  /* SZML-SGLBL/004 */

  return(result); 
  
} /* grr_check_add_reject() */



/*
+------------------------------------------------------------------------------
| Function    : grr_check_add_1
+------------------------------------------------------------------------------
| Description : The function grr_check_add_1() compares address (add1).
|
| Parameters  : add1_i - pointer to address structure to check
|               tn     - timeslot: need to check if tfi is on assigned PDCH
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL grr_check_add_1 ( T_add1 * add1_i,UBYTE tn )
{ 

  BOOL result = FALSE;
  TRACE_FUNCTION( "grr_check_add_1" );

  if(add1_i->v_glob_tfi) 
    result = grr_check_glob_tfi( & add1_i->glob_tfi,tn );
  else if (add1_i->v_tlli_value) 
    result = grr_check_all_tlli(& add1_i->tlli_value);

  return(result); 
  
} /* grr_check_add_1() */



/*
+------------------------------------------------------------------------------
| Function    : grr_check_add_2
+------------------------------------------------------------------------------
| Description : The function grr_check_add_2() checks address structure 2(add2).
|
| Parameters  : add2_i - pointer address structure to check
|               tn     - timeslot: need to check if tfi is on assigned PDCH
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL grr_check_add_2 ( T_add2 * add2_i,UBYTE tn )
{ 

  BOOL result = FALSE;
  TRACE_FUNCTION( "grr_check_add_2" );

  if(add2_i->v_glob_tfi) 
    result = grr_check_glob_tfi( & add2_i->glob_tfi,tn );
  else if (add2_i->v_tlli_value) 
    result = grr_check_all_tlli(& add2_i->tlli_value);
  else if (add2_i->v_tqi)
    result = (add2_i->tqi EQ grr_data->tqi);
  
  return(result); 
  
} /* grr_check_add_2() */


/*
+------------------------------------------------------------------------------
| Function    : grr_check_add_3
+------------------------------------------------------------------------------
| Description : The function grr_check_add_3() checks address structure 3(add3). 
|
| Parameters  : add3_i - address of address structure to check
|               tn     - timeslot: need to check if tfi is on assigned PDCH
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL grr_check_add_3 ( T_add3 * add3_i,UBYTE tn )
{ 
  BOOL result = FALSE;

  TRACE_FUNCTION( "grr_check_add_3" );

  if(add3_i->v_glob_tfi) 
    result = grr_check_glob_tfi( & add3_i->glob_tfi,tn );
  else if (add3_i->v_tlli_value) 
    result = grr_check_all_tlli(& add3_i->tlli_value);
  else if (add3_i->v_tqi)
    result = (add3_i->tqi EQ grr_data->tqi);
  else if (add3_i->v_req_ref_p)
    result = grr_check_request_reference( & add3_i->req_ref_p);

  return(result); 
  
} /* grr_check_add_3() */


/* The following function is added for handling address 4*/
/*
+------------------------------------------------------------------------------
| Function    : grr_check_add_4
+------------------------------------------------------------------------------
| Description : The function grr_check_add_4() checks address structure 4(add4).
|
| Parameters  : add4_i - address of address structure to check
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL grr_check_add_4 ( T_add4 * add4_i,UBYTE tn  )
{
  BOOL result = FALSE;

  TRACE_FUNCTION( "grr_check_add_4" );

  if(add4_i->v_glob_tfi)
    result = grr_check_glob_tfi( & add4_i->glob_tfi,tn );
  else if (add4_i->tqi_req_ref_p.v_tqi)
    result = (add4_i->tqi_req_ref_p.tqi EQ grr_data->tqi);
  else if (add4_i->tqi_req_ref_p.v_req_ref_p)
    result = grr_check_request_reference( & add4_i->tqi_req_ref_p.req_ref_p);

  return(result);

} /* grr_check_add_4() */

/*
+------------------------------------------------------------------------------
| Function    : grr_clean_up_seg_ctrl_blk_tbl
+------------------------------------------------------------------------------
| Description : The function grr_clean_up_seg_ctrl_blk_tbl() checks the table 
|               for old entries to be 'deleted'.
|
| Parameters  : no
|
+------------------------------------------------------------------------------
*/
LOCAL void grr_clean_up_seg_ctrl_blk_tbl ( void )
{ 
  ULONG fn_i,T3200_i;
  UBYTE i;
  TRACE_FUNCTION( "grr_clean_up_seg_ctrl_blk_tbl" );
  for(i = 0;i < SEG_CTRL_BLOCK_SIZE;i++)
  {
    if(0xFF NEQ grr_data->seg_ctrl_blk.blk[i].rti)
    {
      fn_i = grr_data->dl_fn;
      T3200_i = grr_data->seg_ctrl_blk.blk[i].T3200;
      if((grr_data->seg_ctrl_blk.blk[i].T3200 < 60000) AND (fn_i > (FN_MAX - 60000)))
      {
        T3200_i += FN_MAX;
      }
      else if((grr_data->seg_ctrl_blk.blk[i].T3200 > (FN_MAX - 60000)) AND (fn_i < 60000))
      {
        fn_i += FN_MAX;
      }
      if((T3200_i < fn_i) OR (T3200_i > (fn_i + 60000)))
      {
        grr_data->seg_ctrl_blk.blk[i].rti = 0xFF;
      }
    }
  }
} /* grr_clean_up_seg_ctrl_blk_tbl() */


/*
+------------------------------------------------------------------------------
| Function    : grr_align_seg_ctrl_blk_nxt
+------------------------------------------------------------------------------
| Description : The function grr_align_seg_ctrl_blk_nxt() checks the table for
|               the next field to use and sets grr_data->seg_ctrl_blk.next.
|
| Parameters  : no
|
+------------------------------------------------------------------------------
*/
LOCAL void grr_align_seg_ctrl_blk_nxt ( void )
{ 
  ULONG T3200_i1,T3200_i2;
  UBYTE i,n;

  TRACE_FUNCTION( "grr_align_seg_ctrl_blk_nxt" );
  grr_data->seg_ctrl_blk.next++;
  grr_data->seg_ctrl_blk.next %= SEG_CTRL_BLOCK_SIZE;
  if(0xFF NEQ grr_data->seg_ctrl_blk.blk[grr_data->seg_ctrl_blk.next].rti)
  {
    for(i = 0;i < SEG_CTRL_BLOCK_SIZE;i++)
    { /* is there an empty field */
      if(0xFF EQ grr_data->seg_ctrl_blk.blk[i].rti)
        break;
    }
    if(SEG_CTRL_BLOCK_SIZE > i)
    { /* there is an empty field */
      grr_data->seg_ctrl_blk.next = i;
    }
    else
    {/* there is no empty field -> find the oldest entry */
      for(i = 0,n = 0;i < SEG_CTRL_BLOCK_SIZE;i++)
      {
        T3200_i1 = grr_data->seg_ctrl_blk.blk[i].T3200;
        T3200_i2 = grr_data->seg_ctrl_blk.blk[n].T3200;
        if((T3200_i1 > (FN_MAX - 60000)) AND (T3200_i2 < 60000))
        {
          T3200_i2 += FN_MAX;
        }
        else if((T3200_i2 > (FN_MAX - 60000)) AND (T3200_i1 < 60000))
        {
          T3200_i1 += FN_MAX;
        }
        if(T3200_i1 < T3200_i2)
        {
          n = i;
        }
      }
      grr_data->seg_ctrl_blk.next = n;
    }
  }
} /* grr_align_seg_ctrl_blk_nxt() */

/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ie_tlli
+------------------------------------------------------------------------------
| Description : This function decodes a compressed TLLI struct
|
| Parameters  : tlli     - BUF_tlli struct destination pointer
|
| Globals:      pBuf     - Ptr to the compressed TLLI buffer
|               startBit - Bit offset of the first TLLI bit
|               bitLen   - Lenght of the buffer in bits
|
| Returns     : ccdOK    - If no error is occured
|                        - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_ie_tlli (BUF_tlli_value* tlli)
{
  if (bitLen < 32)
    return ERR_MAND_ELEM_MISS;

  tlli->l_tlli_value = 32;
  tlli->o_tlli_value = startBit%8;

  tlli->b_tlli_value[0] = pBuf[startBit/8] & maskTab2[tlli->o_tlli_value];
  startBit += 8;

  tlli->b_tlli_value[1] = pBuf[startBit/8];
  startBit += 8;

  tlli->b_tlli_value[2] = pBuf[startBit/8];
  startBit += 8;

  tlli->b_tlli_value[3] = pBuf[startBit/8];
  startBit += 8;

  tlli->b_tlli_value[4] = pBuf[startBit/8] & ~(maskTab2[tlli->o_tlli_value]);

  bitLen   -= 32;

  return ccdOK;
}


/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ie_pta
+------------------------------------------------------------------------------
| Description : This function decodes a compressed T_pta struct
|
| Parameters  : pta      - T_pta struct destination pointer
|
| Globals:      pBuf     - Ptr to the compressed T_pta buffer
|               startBit - Bit offset of the first T_pta bit
|               bitLen   - Lenght of the buffer in bits
|
| Returns     : ccdOK    - If no error is occured
|                        - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_ie_pta (T_pta* pta)
{
  int bit;                                    

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  bit = GET_N_BITS(1);                        
  if (bit == 1)                               /* TIMING_ADVANCED_VALUE:bit(6) */
  {
    if (bitLen < 6)
      return ERR_MAND_ELEM_MISS;              

    pta->v_ta_value = TRUE;                   
    pta->ta_value   = GET_N_BITS(6);
  }

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  pta->v_ta_index_tn = GET_N_BITS(1);
  if (pta->v_ta_index_tn == 1)                         /* TIMING_ADVANCED_INDEX:bit(4) */
  {                                           /* TI.A.-TIMESLOT_NUMBER:bit(3) */
    if (bitLen < 7)
      return ERR_MAND_ELEM_MISS;              

    pta->ta_index_tn.ta_index   = GET_N_BITS(4);
    pta->ta_index_tn.ta_tn      = GET_N_BITS(3);
  }

  return ccdOK;
}


/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ie_pwr_par
+------------------------------------------------------------------------------
| Description : This function decodes a compressed T_pwr_par struct
|
| Parameters  : pwr_par      - T_pwr_par struct destination pointer
|
| Globals:      pBuf     - Ptr to the compressed T_pwr_par buffer
|               startBit - Bit offset of the first T_pwr_par bit
|               bitLen   - Lenght of the buffer in bits
|
| Returns     : ccdOK    - If no error is occured
|                        - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_ie_pwr_par (T_pwr_par* pwr_par)
{
  int i;
  int bit;                                    
                                              /* Power Control Parameters    */
  if (bitLen < 4)
    return ERR_MAND_ELEM_MISS;              

  pwr_par->alpha = GET_N_BITS(4);

  for (i=0; i<8; i++)
  {
    if (bitLen < 1)
      return ERR_MAND_ELEM_MISS;              

    bit = GET_N_BITS(1);

    if (bit == 1)
    {
      if (bitLen < 5)
        return ERR_MAND_ELEM_MISS;              

      pwr_par->gamma_tn[i].v_gamma = TRUE;    /* any values are allowed      */
      pwr_par->gamma_tn[i].gamma   = GET_N_BITS(5);
    }
  }

  return ccdOK;
}


/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ie_glob_tfi
+------------------------------------------------------------------------------
| Description : This function decodes a compressed T_glob_tfi struct
|
| Parameters  : glob_tfi   - T_glob_tfi struct destination pointer
|
| Globals:      pBuf       - Ptr to the compressed T_glob_tfi buffer
|               startBit   - Bit offset of the first T_glob_tfi bit
|               bitLen     - Lenght of the buffer in bits
|
| Returns     : ccdOK    - If no error is occured
|                        - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_ie_glob_tfi (T_glob_tfi* glob_tfi)
{
  if (bitLen < 6)
    return ERR_MAND_ELEM_MISS;              
  
  glob_tfi->flag = GET_N_BITS(1);
  if (glob_tfi->flag == 0)                    /* UPLINK_TFI                  */
  {
    glob_tfi->v_ul_tfi = TRUE;
    glob_tfi->ul_tfi   = GET_N_BITS(5);
  }
  else                                        /* DOWNLINK_TFI                */
  {
    glob_tfi->v_dl_tfi = TRUE;
    glob_tfi->dl_tfi   = GET_N_BITS(5);
  }

  return ccdOK;
}


/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ie_meas_map
+------------------------------------------------------------------------------
| Description : This function decodes a compressed T_meas_map struct
|
| Parameters  : meas_map   - T_meas_map struct destination pointer
|
| Globals:      pBuf       - Ptr to the compressed T_meas_map buffer
|               startBit   - Bit offset of the first T_meas_map bit
|               bitLen     - Lenght of the buffer in bits
|
| Returns     : ccdOK    - If no error is occured
|                        - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_ie_meas_map (T_meas_map* meas_map)
{
  USHORT h_byte;

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;              

  meas_map->meas_start_grr.flag = GET_N_BITS(1);
  if (meas_map->meas_start_grr.flag == 1)         /* Relative Frame Number Encod.*/
  {
    if (bitLen < 13)
      return ERR_MAND_ELEM_MISS;              

    meas_map->meas_start_grr.v_rel = TRUE;
                             h_byte = GET_N_BITS(5);
    meas_map->meas_start_grr.rel   = (h_byte << 8) + GET_N_BITS(8);
  }
  else                                        /* Absolute Frame Number Encod.*/
  {
    if (bitLen < 16)
      return ERR_MAND_ELEM_MISS;              

    meas_map->meas_start_grr.v_abs  = TRUE;
    meas_map->meas_start_grr.abs.t1 = GET_N_BITS(5);
    meas_map->meas_start_grr.abs.t3 = GET_N_BITS(6);
    meas_map->meas_start_grr.abs.t2 = GET_N_BITS(5);
  }

  if (bitLen < 13)
    return ERR_MAND_ELEM_MISS;

  meas_map->meas_inter  = GET_N_BITS(5);
  meas_map->meas_bitmap = GET_N_BITS(8);

  return ccdOK;
}


#ifdef REL99
/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ie_egprs_link_adpt_para
+------------------------------------------------------------------------------
| Description : This function decodes the EGPRS link adaptation parameters
|
| Parameters  : trgt   - T_egprs_link_adpt_para destination pointer
|
| Globals:      pBuf       - Ptr to the compressed T_egprs_link_adpt_para buffer
|               startBit   - Bit offset of the first T_egprs_link_adpt_para bit
|               bitLen     - Lenght of the buffer in bits
|
| Returns     : ccdOK    - If no error is occured
|                        - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_ie_egprs_link_adpt_para(T_egprs_link_adpt_para *trgt)
{

  TRACE_FUNCTION("grr_decode_ie_egprs_link_adpt_para");

  if (bitLen < 8) /*5+2+1*/
    return ERR_MAND_ELEM_MISS;

  trgt->egprs_ws = GET_N_BITS(5);
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;

  trgt->lqm_mode = GET_N_BITS(2);
  trgt->v_bep_period2 = GET_N_BITS(1);
  if(trgt->v_bep_period2)
  {
    trgt->bep_period2 = GET_N_BITS(4);
  }
  return ccdOK;
}


/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ie_compact_red_ma
+------------------------------------------------------------------------------
| Description : This function decodes the compact_red_ma parameters
|
| Parameters  : trgt   - T_compact_red_ma destination pointer
|
| Globals:      pBuf       - Ptr to the T_compact_red_ma buffer
|               startBit   - Bit offset of the first T_compact_red_ma bit
|               bitLen     - Lenght of the buffer in bits
|
| Returns     : ccdOK    - If no error is occured
|                        - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE  grr_decode_ie_compact_red_ma(T_compact_red_ma *trgt)
{
  UBYTE     i=0;

  TRACE_FUNCTION("grr_decode_ie_compact_red_ma");

  if (bitLen < 8) /*7(for length_reduced_bitmap)+1(for v_maio_2) */
    return ERR_MAND_ELEM_MISS;

  trgt->length_reduced_bitmap = GET_N_BITS(7);
  if(bitLen < trgt->c_reduced_ma_bitmap )
      return ERR_MAND_ELEM_MISS;

  for(i=0 ; i < trgt->c_reduced_ma_bitmap ;i++)
  {
    trgt->reduced_ma_bitmap[i] = GET_N_BITS(1);
  }
  trgt->v_maio_2 = GET_N_BITS(1);
  if(trgt->v_maio_2 == 1)
  {
    if (bitLen < 6)
      return ERR_MAND_ELEM_MISS;

    trgt->maio_2 = GET_N_BITS(6);
  }
  return ccdOK;
}

#endif


/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ie_tbf_s_time
+------------------------------------------------------------------------------
| Description : This function decodes a compressed T_tbf_s_time struct
|
| Parameters  : tbf_s_time - T_tbf_s_time struct destination pointer
|
| Globals:      pBuf       - Ptr to the compressed T_tbf_s_time buffer
|               startBit   - Bit offset of the first T_tbf_s_time bit
|               bitLen     - Lenght of the buffer in bits
|
| Returns     : ccdOK    - If no error is occured
|                        - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_ie_tbf_s_time (T_tbf_s_time* tbf_s_time)
{
  USHORT h_byte;
                                              /* TBF Starting Time: Starting */
                                              /* frame number description    */
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;              

  tbf_s_time->flag = GET_N_BITS(1);
  if (tbf_s_time->flag == 1)                  /* Relative Frame Number Encod.*/
  {
    if (bitLen < 13)
      return ERR_MAND_ELEM_MISS;              
    
    tbf_s_time->v_rel = TRUE;

               h_byte = GET_N_BITS(5);
    tbf_s_time->rel   = (h_byte << 8) + GET_N_BITS(8);
  }
  else                                        /* Absolute Frame Number Encod.*/
  {
    if (bitLen < 16)
      return ERR_MAND_ELEM_MISS;              
    
    tbf_s_time->v_abs = TRUE;

    tbf_s_time->abs.t1 = GET_N_BITS(5);
    tbf_s_time->abs.t3 = GET_N_BITS(6);
    tbf_s_time->abs.t2 = GET_N_BITS(5);
  }

  return ccdOK;
}

/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ie_dyn_alloc_p
+------------------------------------------------------------------------------
| Description : This function decodes a compressed Dynamic Allocation IE
|
| Parameters  : dyn_alloc_p - T_dyn_alloc_p struct destination pointer
|
| Globals:      pBuf        - Ptr to the compressed T_dyn_alloc_p buffer
|               startBit    - Bit offset of the first T_dyn_alloc_p bit
|               bitLen      - Lenght of the buffer in bits
|
| Returns     : ccdOK    - If no error is occured
|                        - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_ie_dyn_alloc_p (T_dyn_alloc_p* dyn_alloc_p)
{
  int i;
  int bit;                                    
  UBYTE  ret_code;


  if (bitLen < 2)                       
    return ERR_MAND_ELEM_MISS;

  dyn_alloc_p->xdyn_alloc = GET_N_BITS(1);

  dyn_alloc_p->flag2 = GET_N_BITS(1);
  if (dyn_alloc_p->flag2 == 1)                /* P0:bit(4), PR_MODE:bit(1)   */
  {
    if (bitLen < 5)
      return ERR_MAND_ELEM_MISS;

    dyn_alloc_p->v_p0      = TRUE;
    dyn_alloc_p->p0        = GET_N_BITS(4);
    dyn_alloc_p->v_pr_mode = TRUE;
    dyn_alloc_p->pr_mode   = GET_N_BITS(1);
  }

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;

  dyn_alloc_p->usf_grant = GET_N_BITS(1);     /* USF_GRANULARITY:bit(1)      */

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* UL_TFI_ASSIGNMENT : bit(5)  */
  {
    if (bitLen < 5)
      return ERR_MAND_ELEM_MISS;

    dyn_alloc_p->v_ul_tfi_assign = TRUE;
    dyn_alloc_p->ul_tfi_assign   = GET_N_BITS(5);
  }

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* RLC_DATA_B._GRANTED:bit(8)  */
  {
    if (bitLen < 8)
      return ERR_MAND_ELEM_MISS;

    dyn_alloc_p->v_rlc_db_granted = TRUE;
    dyn_alloc_p->rlc_db_granted   = GET_N_BITS(8);
  }

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* TBF Starting Time: Starting */
  {                                           /* frame number description    */
    ret_code = grr_decode_ie_tbf_s_time (&dyn_alloc_p->tbf_s_time);

    if (ret_code == ccdOK)
      dyn_alloc_p->v_tbf_s_time = TRUE;
    else
      return ret_code;
  }

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;

  dyn_alloc_p->flag = GET_N_BITS(1);
  if (dyn_alloc_p->flag == 0)                 /* Timeslot Allocation         */
  {
    for (i=0; i<8; i++)
    {
      if (bitLen < 1)
        return ERR_MAND_ELEM_MISS;

      bit = GET_N_BITS(1);
      if (bit == 1)
      {
        if (bitLen < 3)
          return ERR_MAND_ELEM_MISS;

        dyn_alloc_p->tn_alloc[i].v_usf = TRUE;
        dyn_alloc_p->tn_alloc[i].usf   = GET_N_BITS(3);
      }
    }

    dyn_alloc_p->v_tn_alloc = TRUE;
  }
  else                                        /* Timeslot Allocation with    */
  {                                           /*   Power Control Parameters  */
    if (bitLen < 4)
      return ERR_MAND_ELEM_MISS;

    dyn_alloc_p->tn_alloc_pwr.alpha = GET_N_BITS(4);

    for (i=0; i<8; i++)
    {
      if (bitLen < 1)
        return ERR_MAND_ELEM_MISS;

      bit = GET_N_BITS(1);
      if (bit == 1)
      {
        if (bitLen < 8)
          return ERR_MAND_ELEM_MISS;

        dyn_alloc_p->tn_alloc_pwr.usf_array[i].v_usf_g     = TRUE;
        dyn_alloc_p->tn_alloc_pwr.usf_array[i].usf_g.usf   = GET_N_BITS(3);
        dyn_alloc_p->tn_alloc_pwr.usf_array[i].usf_g.gamma = GET_N_BITS(5);
      }
    }

    dyn_alloc_p->v_tn_alloc_pwr = TRUE;
  }

  return ccdOK;
} /* grr_decode_ie_dyn_alloc_p */


/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ie_dyn_alloc_ts
+------------------------------------------------------------------------------
| Description : This function decodes a compressed Dynamic Allocation IE
|
| Parameters  : dyn_alloc_ts - T_dyn_alloc_ts struct destination pointer
|
| Globals:      pBuf        - Ptr to the compressed T_dyn_alloc_p buffer
|               startBit    - Bit offset of the first T_dyn_alloc_p bit
|               bitLen      - Lenght of the buffer in bits
|
| Returns     : ccdOK    - If no error is occured
|                        - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_ie_dyn_alloc_ts (T_dyn_alloc_ts* dyn_alloc_ts)
{
  int i;
  int bit;                                    
  UBYTE  ret_code;


  if (bitLen < 2)                       
    return ERR_MAND_ELEM_MISS;

  dyn_alloc_ts->xdyn_alloc = GET_N_BITS(1);

  dyn_alloc_ts->flag2 = GET_N_BITS(1);
  if (dyn_alloc_ts->flag2 == 1)                /* P0:bit(4), PR_MODE:bit(1)   */
  {
    if (bitLen < 5)
      return ERR_MAND_ELEM_MISS;

    dyn_alloc_ts->v_p0      = TRUE;
    dyn_alloc_ts->p0        = GET_N_BITS(4);
    dyn_alloc_ts->v_pr_mode = TRUE;
    dyn_alloc_ts->pr_mode   = GET_N_BITS(1);
  }

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;

  dyn_alloc_ts->usf_grant = GET_N_BITS(1);     /* USF_GRANULARITY:bit(1)      */

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* RLC_DATA_B._GRANTED:bit(8)  */
  {
    if (bitLen < 8)
      return ERR_MAND_ELEM_MISS;

    dyn_alloc_ts->v_rlc_db_granted = TRUE;
    dyn_alloc_ts->rlc_db_granted   = GET_N_BITS(8);
  }

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* TBF Starting Time: Starting */
  {                                           /* frame number description    */
    ret_code = grr_decode_ie_tbf_s_time (&dyn_alloc_ts->tbf_s_time);

    if (ret_code == ccdOK)
      dyn_alloc_ts->v_tbf_s_time = TRUE;
    else
      return ret_code;
  }

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;

  dyn_alloc_ts->flag = GET_N_BITS(1);
  if (dyn_alloc_ts->flag == 0)                 /* Timeslot Allocation         */
  {
    for (i=0; i<8; i++)
    {
      if (bitLen < 1)
        return ERR_MAND_ELEM_MISS;

      bit = GET_N_BITS(1);
      if (bit == 1)
      {
        if (bitLen < 3)
          return ERR_MAND_ELEM_MISS;

        dyn_alloc_ts->tn_alloc[i].v_usf = TRUE;
        dyn_alloc_ts->tn_alloc[i].usf   = GET_N_BITS(3);
      }
    }

    dyn_alloc_ts->v_tn_alloc = TRUE;
  }
  else                                        /* Timeslot Allocation with    */
  {                                           /*   Power Control Parameters  */
    if (bitLen < 4)
      return ERR_MAND_ELEM_MISS;

    dyn_alloc_ts->tn_alloc_pwr.alpha = GET_N_BITS(4);

    for (i=0; i<8; i++)
    {
      if (bitLen < 1)
        return ERR_MAND_ELEM_MISS;

      bit = GET_N_BITS(1);
      if (bit == 1)
      {
        if (bitLen < 8)
          return ERR_MAND_ELEM_MISS;

        dyn_alloc_ts->tn_alloc_pwr.usf_array[i].v_usf_g     = TRUE;
        dyn_alloc_ts->tn_alloc_pwr.usf_array[i].usf_g.usf   = GET_N_BITS(3);
        dyn_alloc_ts->tn_alloc_pwr.usf_array[i].usf_g.gamma = GET_N_BITS(5);
      }
    }

    dyn_alloc_ts->v_tn_alloc_pwr = TRUE;
  }

  return ccdOK;
} /* grr_decode_ie_dyn_alloc_ts */


/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ie_freq_par
+------------------------------------------------------------------------------
| Description : This function decodes a compressed T_freq_par struct
|
| Parameters  : freq_par - T_freq_par struct destination pointer
|
| Globals:      pBuf     - Ptr to the compressed T_freq_par buffer
|               startBit - Bit offset of the first T_freq_par bit
|               bitLen   - Lenght of the buffer in bits
|
| Returns     : ccdOK    - If no error is occured
|                        - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_ie_freq_par (T_freq_par* freq_par)
{
  int    i;                                      
  int    bit;                                    
  USHORT h_byte;


  if (bitLen < 5)
    return ERR_MAND_ELEM_MISS;                

  freq_par->tsc   = GET_N_BITS(3);            /* TSC : bit (3)               */

  freq_par->flag  = GET_N_BITS(1);
  freq_par->flag2 = GET_N_BITS(1);

  if (freq_par->flag == 0)             
  {
    if (freq_par->flag2 == 0)                 /* ARFCN : bit(10)             */
    {
      if (bitLen < 10)
        return ERR_MAND_ELEM_MISS;

      freq_par->v_arfcn = TRUE;
                    h_byte   = GET_N_BITS(2);
      freq_par->arfcn   = (h_byte << 8) + GET_N_BITS(8);
    }
    else                                      /* Indirect encoding           */
    {
      if (bitLen < 11)
        return ERR_MAND_ELEM_MISS;

      freq_par->indi_encod.maio   = GET_N_BITS(6);
      freq_par->indi_encod.ma_num = GET_N_BITS(4);

      bit = GET_N_BITS(1);
      if (bit == 1)
      {
        if (bitLen < 3)
          return ERR_MAND_ELEM_MISS;

        freq_par->indi_encod.v_chamge_ma_sub   = TRUE;
        freq_par->indi_encod.chamge_ma_sub.cm1 = GET_N_BITS(2);

        bit = GET_N_BITS(1);
        if (bit == 1)
        {
          if (bitLen < 2)
            return ERR_MAND_ELEM_MISS;

          freq_par->indi_encod.chamge_ma_sub.v_cm2 = TRUE;
          freq_par->indi_encod.chamge_ma_sub.cm2   = GET_N_BITS(2);
        }
      }

      freq_par->v_indi_encod = TRUE;
    }
  }
  else
  {
    if (freq_par->flag2 == 0)                 /* Direct encoding 1           */
    {
      if (bitLen < 13)
        return ERR_MAND_ELEM_MISS;

      freq_par->di_encod1.maio = GET_N_BITS(6);
      
      freq_par->di_encod1.gprs_ms_alloc_ie.hsn = GET_N_BITS(6);

      bit = GET_N_BITS(1);                    
      if (bit == 1)                           /* RFL number list             */
      {
        i = 0;

        do {
          if (i >= MAX_RFL_NUM_LIST)
            return ERR_MAND_ELEM_MISS;

          if (bitLen < 5)
            return ERR_MAND_ELEM_MISS;

          freq_par->di_encod1.gprs_ms_alloc_ie.rfl_num_list[i++].
                                                     rfl_num = GET_N_BITS(4);
          bit = GET_N_BITS(1);

        } while (bit == 1);
        
        freq_par->di_encod1.gprs_ms_alloc_ie.c_rfl_num_list = i; 
        freq_par->di_encod1.gprs_ms_alloc_ie.v_rfl_num_list = TRUE;
      }

      if (bitLen < 1)
        return ERR_MAND_ELEM_MISS;

      freq_par->di_encod1.gprs_ms_alloc_ie.flag = GET_N_BITS(1);
      if (freq_par->di_encod1.gprs_ms_alloc_ie.flag == 0)
      {                                       /* MA_LENGTH, MA_BITMAP        */
        if (bitLen < 6)
          return ERR_MAND_ELEM_MISS;

        i = GET_N_BITS(6);
        freq_par->di_encod1.gprs_ms_alloc_ie.ma_struct.ma_len   = i;
        freq_par->di_encod1.gprs_ms_alloc_ie.ma_struct.c_ma_map = i + 1;

        if (bitLen < (i + 1))
          return ERR_MAND_ELEM_MISS;

        for (i=0; i<freq_par->di_encod1.gprs_ms_alloc_ie.ma_struct.c_ma_map; i++)
        {
          freq_par->di_encod1.gprs_ms_alloc_ie.ma_struct.ma_map[i] = GET_N_BITS(1);
        }

        freq_par->di_encod1.gprs_ms_alloc_ie.v_ma_struct = TRUE;
      }
      else                                    /* ARFCN index list            */
      {
        if (bitLen < 1)
          return ERR_MAND_ELEM_MISS;

        bit = GET_N_BITS(1);                    
        if (bit == 1)                         
        {
          i = 0;

          do {
            if (i >= MAX_ARFCN_LIST)
              return ERR_MAND_ELEM_MISS;

            if (bitLen < 7)
              return ERR_MAND_ELEM_MISS;

            freq_par->di_encod1.gprs_ms_alloc_ie.arfcn_index_list[i++].
                                                 arfcn_index = GET_N_BITS(6);
            bit = GET_N_BITS(1);

          } while (bit == 1);
      
          freq_par->di_encod1.gprs_ms_alloc_ie.c_arfcn_index_list = i; 
          freq_par->di_encod1.gprs_ms_alloc_ie.v_rfl_num_list     = TRUE;
        }

        freq_par->di_encod1.gprs_ms_alloc_ie.v_arfcn_index_list = TRUE;
      }

      freq_par->v_di_encod1 = TRUE;
    }
    else                                      /* Direct encoding 2           */
    {
      if (bitLen < 16)
        return ERR_MAND_ELEM_MISS;

      freq_par->di_encod2.maio        = GET_N_BITS(6);
      freq_par->di_encod2.hsn         = GET_N_BITS(6);
      freq_par->di_encod2.len_ma_list = GET_N_BITS(4);
      freq_par->di_encod2.c_ma_list   = freq_par->di_encod2.len_ma_list + 3;

      if (bitLen < (freq_par->di_encod2.c_ma_list << 3))
        return ERR_MAND_ELEM_MISS;

      for (i=0; i<freq_par->di_encod2.c_ma_list; i++)
      {
        freq_par->di_encod2.ma_list[i] = GET_N_BITS(8);
      }

      freq_par->v_di_encod2 = TRUE;
    }
  }

  return ccdOK;
}

/*
+------------------------------------------------------------------------------
| Function    : grr_decode_dl_assignment
+------------------------------------------------------------------------------
| Description : For performance reasons this function replaces the call to the
|               function ccd_decodeMsg. If no error occured, the D_DL_ASSIGN 
|               message is decoded into _decodeCtrlMsg.
|
| Parameters  : buf    - pointer to beginning of the D_DL_ASSIGN IE
|               len    - lenght of the buffer in bits
|               off    - bit offset of the first bit in the buffer
|
| Returns     : ccdOK  - if no error is occured
|                      - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_dl_assignment (UBYTE* buf, int off, int len)
{ 
  int    bit;                                    
  UBYTE  ret_code;

  MCAST(pMsg, D_DL_ASSIGN);

  /*-------------------------------------------------------------------------*/
  startBit = off;                             /* Initiate global data        */
  bitLen   = len;
  pBuf     = buf;

  memset (pMsg, 0, sizeof(T_D_DL_ASSIGN));    /* init destination struct     */
  /*-------------------------------------------------------------------------*/

  if (bitLen < 8)                             
    return ERR_MAND_ELEM_MISS;
  
  pMsg->msg_type  = GET_N_BITS(6);            /* MESSAGE_TYPE : bit(6)       */
  
  /* --- DISTRIBUTION CONTENTS --- */

  pMsg->page_mode = GET_N_BITS(2);            /* PAGE_MODE : bit(2)          */ 

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ccdOK;                             

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* PERSISTENCE_LEVEL: bit(4)*4 */
  {
    if (bitLen < 16)
      return ERR_MAND_ELEM_MISS;
    
    pMsg->v_pers_lev = TRUE;                  

    pMsg->pers_lev.plev[0] = GET_N_BITS(4);
    pMsg->pers_lev.plev[1] = GET_N_BITS(4);
    pMsg->pers_lev.plev[2] = GET_N_BITS(4);
    pMsg->pers_lev.plev[3] = GET_N_BITS(4);
  }

  if (bitLen <= 0)
    return ccdOK;                             

  /* --- ADDRESS INFORMATON --- */

  /*-------------------------------------------------------------------------*/
  pMsg->add1.flag = GET_N_BITS(1);
  if (pMsg->add1.flag == 0)                   /* Global TFI                  */
  {
    ret_code = grr_decode_ie_glob_tfi (&pMsg->add1.glob_tfi);

    if (ret_code == ccdOK)
      pMsg->add1.v_glob_tfi = TRUE;
    else
      return ret_code;
  }
  else
  {
    if (bitLen < 1)
      return ERR_MAND_ELEM_MISS;              

    bit = GET_N_BITS(1);
    if (bit == 0)                             /* TLLI                        */
    {
      ret_code = grr_decode_ie_tlli (&pMsg->add1.tlli_value);

      if(ret_code == ccdOK)
        pMsg->add1.v_tlli_value = TRUE;               
      else
        return ret_code;
    }
    else
    {
      return ERR_MAND_ELEM_MISS;              
    }
  }

  /*-------------------------------------------------------------------------*/

  /* --- MESSAGE ESCAPE --- */
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* 1 equals to Message Escape  */
    return ccdOK;                             /*   then we are ready         */

  /* --- NON-DISTRIBUTION CONTENTS --- */

  if (bitLen < 12)
    return ERR_MAND_ELEM_MISS;                

  pMsg->mac_mode = GET_N_BITS(2);             /* MAC_MODE : bit(2)           */
  pMsg->rlc_mode = GET_N_BITS(1);             /* RLC_MODE : bit(1)           */
  pMsg->ctrl_ack = GET_N_BITS(1);             /* CONTROL_ACK : bit(1)        */
  pMsg->ts_alloc = GET_N_BITS(8);             /* TIMESLOT_ALLOCATION : bit(8)*/

  /*-------------------------------------------------------------------------*/

  ret_code = grr_decode_ie_pta (&pMsg->pta);  /* Packet Timing Advanced IE   */
  
  if(ret_code != ccdOK)
    return ret_code;

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* P0:bit(4)                   */
  {                                           /* BTS_PWR_CTRL_MODE : bit(1)  */
                                              /* PR_MODE : bit(1)            */
    if (bitLen < 6)
      return ERR_MAND_ELEM_MISS;              

    pMsg->v_bts_pwr_ctrl       = TRUE;        
    pMsg->bts_pwr_ctrl.p0      = GET_N_BITS(4);
    pMsg->bts_pwr_ctrl.mode    = GET_N_BITS(1);   
    pMsg->bts_pwr_ctrl.pr_mode = GET_N_BITS(1);
  }

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* Frequency Parameters IE     */
  {
    ret_code = grr_decode_ie_freq_par (&pMsg->pda_trnc_grp.freq_par);

    if (ret_code == ccdOK)
      pMsg->pda_trnc_grp.v_freq_par = TRUE;
    else
      return ret_code;
  }

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* DOWNL.TFI_ASSIGNEMENT:bit(5)*/
  {
    if (bitLen < 5)
      return ERR_MAND_ELEM_MISS;              

    pMsg->pda_trnc_grp.v_dl_tfi_assign = TRUE;             
    pMsg->pda_trnc_grp.dl_tfi_assign   = GET_N_BITS(5);  
  }
  
  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* Power Control Parameters    */
  {
    ret_code = grr_decode_ie_pwr_par (&pMsg->pda_trnc_grp.pwr_par);

    if (ret_code == ccdOK)
      pMsg->pda_trnc_grp.v_pwr_par = TRUE;
    else
      return ret_code;
  }

  /*-------------------------------------------------------------------------*/
  bit = GET_N_BITS(1);
  if (bit == 1)                               /* TBF Starting Time: Starting */
  {                                           /* frame number description    */
    ret_code = grr_decode_ie_tbf_s_time (&pMsg->pda_trnc_grp.tbf_s_time);

    if (ret_code == ccdOK)
      pMsg->pda_trnc_grp.v_tbf_s_time = TRUE;
    else
      return ret_code;
  }

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;              

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* Measurement Mapping         */
  {                                       
    ret_code = grr_decode_ie_meas_map (&pMsg->pda_trnc_grp.meas_map);

    if (ret_code == ccdOK)
      pMsg->pda_trnc_grp.v_meas_map = TRUE;
    else
      return ret_code;
  }

#ifdef REL99
  /*Extending the Packet downlink assignment message decoding
   *for R99 additions
   */
  pMsg->pda_trnc_grp.v_release_99_str_pda = GET_N_BITS(1);
  
  if(pMsg->pda_trnc_grp.v_release_99_str_pda == 1)
  {
    bit = GET_N_BITS(1);
    if(bit == 1)
    {
      ret_code = grr_decode_ie_egprs_link_adpt_para(
        &pMsg->pda_trnc_grp.release_99_str_pda.egprs_link_adpt_para);
      if(ret_code == ccdOK)
        pMsg->pda_trnc_grp.release_99_str_pda.v_egprs_link_adpt_para = TRUE;
      else
        return ret_code;
    }
    if(bitLen < 1)
      return ERR_MAND_ELEM_MISS;
    bit = GET_N_BITS(1);
    if(bit == 1)
    {
      if(bitLen < 2)
        return ERR_MAND_ELEM_MISS;
      pMsg->pda_trnc_grp.release_99_str_pda.v_p_ext_ta = TRUE;
      pMsg->pda_trnc_grp.release_99_str_pda.p_ext_ta = GET_N_BITS(2);
    }

    if(bitLen < 1)
      return ccdOK;
    bit = GET_N_BITS(1);
    if(bit == 1)
    {

      ret_code = grr_decode_ie_compact_red_ma(&pMsg->pda_trnc_grp.release_99_str_pda.compact_red_ma);
      if(ret_code == ccdOK)
        pMsg->pda_trnc_grp.release_99_str_pda.v_compact_red_ma = TRUE;
      else
        return ret_code;
    }
  }
#endif

  /* --- PADDING BITS --- */ /* -> currently not decoded and/or validated */

  return ccdOK;
}
/*
+------------------------------------------------------------------------------
| Function    : grr_decode_pdch_release
+------------------------------------------------------------------------------
| Description : For performance reasons this function replaces the call to the
|               function ccd_decodeMsg. If no error occured, the D_PDCH_RELEASE 
|               message is decoded into _decodeCtrlMsg.
|
| Parameters  : buf    - pointer to beginning of the D_PDCH_RELEASE IE
|               len    - lenght of the buffer in bits
|               off    - bit offset of the first bit in the buffer
|
| Returns     : ccdOK  - if no error is occured
|                      - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_pdch_release (UBYTE* buf, int off, int len)
{ 
  MCAST(pMsg, D_PDCH_RELEASE);

  /*-------------------------------------------------------------------------*/
  startBit = off;                             /* Initiate global data        */
  bitLen   = len;
  pBuf     = buf;

  memset (pMsg, 0, sizeof(T_D_PDCH_RELEASE)); /* init destination struct     */
  /*-------------------------------------------------------------------------*/

  if (bitLen < 8)                             
    return ERR_MAND_ELEM_MISS;
  
  pMsg->msg_type  = GET_N_BITS(6);            /* MESSAGE_TYPE : bit(6)       */
  
  /* --- DISTRIBUTION CONTENTS --- */

  pMsg->page_mode = GET_N_BITS(2);            /* PAGE_MODE : bit(2)          */ 

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ccdOK;                             

  pMsg->v_ts_available = GET_N_BITS(1);       /* TIMESLOT AVAILABLE bit(1)  */

  if (bitLen <= 0)
    return ccdOK;                             

  pMsg->ts_available   = GET_N_BITS(8);       /* TIMESLOT MASK     bit(8)   */

  /* --- PADDING BITS --- */ /* -> currently not decoded and/or validated */

  return ccdOK;
}

/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ul_assignment
+------------------------------------------------------------------------------
| Description : For performance reasons this function replaces the call to the
|               function ccd_decodeMsg. If no error occured, the D_UL_ASSIGN 
|               message is decoded into _decodeCtrlMsg.
|
| Parameters  : buf    - pointer to beginning of the D_DL_ASSIGN IE
|               len    - lenght of the buffer in bits
|               off    - bit offset of the first bit in the buffer
|
| Returns     : ccdOK  - if no error is occured
|                      - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_ul_assignment (UBYTE* buf, int off, int len)
{ 
  int    i;
  int    bit;                                    
  USHORT h_byte;
  UBYTE  ret_code;

  MCAST(pMsg, D_UL_ASSIGN);

  /*-------------------------------------------------------------------------*/
  startBit = off;                             /* Initiate global data        */
  bitLen   = len;
  pBuf     = buf;

  memset (pMsg, 0, sizeof(T_D_UL_ASSIGN));    /* init destination struct     */

  /*-------------------------------------------------------------------------*/

  if (bitLen < 8)                             
    return ERR_MAND_ELEM_MISS;
  
  pMsg->msg_type  = GET_N_BITS(6);            /* MESSAGE_TYPE : bit(6)       */
  
  /* --- DISTRIBUTION CONTENTS --- */

  pMsg->page_mode = GET_N_BITS(2);            /* PAGE_MODE : bit(2)          */ 

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ccdOK;                             

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* PERSISTENCE_LEVEL: bit(4)*4 */
  {
    if (bitLen < 16)
      return ERR_MAND_ELEM_MISS;
    
    pMsg->v_pers_lev = TRUE;                  

    pMsg->pers_lev.plev[0] = GET_N_BITS(4);
    pMsg->pers_lev.plev[1] = GET_N_BITS(4);
    pMsg->pers_lev.plev[2] = GET_N_BITS(4);
    pMsg->pers_lev.plev[3] = GET_N_BITS(4);
  }

  if (bitLen <= 0)
    return ccdOK;                             

  /*-------------------------------------------------------------------------*/

  /* --- ADDRESS INFORMATON --- */

  pMsg->add3.flag = GET_N_BITS(1);
  if (pMsg->add3.flag == 0)                   /* Global TFI                  */
  {
    ret_code = grr_decode_ie_glob_tfi (&pMsg->add3.glob_tfi);

    if (ret_code == ccdOK)
      pMsg->add3.v_glob_tfi = TRUE;
    else
      return ret_code;
  }
  else
  {
    if (bitLen < 1)
      return ERR_MAND_ELEM_MISS;              

    pMsg->add3.v_flag2 = TRUE;

    pMsg->add3.flag2 = GET_N_BITS(1);
    if (pMsg->add3.flag2 == 0)                /* TLLI                        */
    {
      if (bitLen < 32)
        return ERR_MAND_ELEM_MISS;

      ret_code = grr_decode_ie_tlli (&pMsg->add3.tlli_value);

      if(ret_code == ccdOK)
        pMsg->add3.v_tlli_value = TRUE;             
      else
        return ret_code;
    }
    else
    {
      if (bitLen < 1)
        return ERR_MAND_ELEM_MISS;              

      pMsg->add3.v_flag3 = TRUE;

      pMsg->add3.flag3 = GET_N_BITS(1);
      if (pMsg->add3.flag3 == 0)              /* TQI : bit(16)               */
      {
        if (bitLen < 16)
          return ERR_MAND_ELEM_MISS;              

        pMsg->add3.v_tqi = TRUE;             
                  h_byte = GET_N_BITS(8);
        pMsg->add3.tqi   = (h_byte << 8) + GET_N_BITS(8);
      }
      else                                    /* Packet Request Reference    */
      {
        if (bitLen < 27)
          return ERR_MAND_ELEM_MISS;              

        pMsg->add3.v_req_ref_p = TRUE;

                                  h_byte = GET_N_BITS(3);
        pMsg->add3.req_ref_p.access_info = (h_byte << 8) +  GET_N_BITS(8);

        pMsg->add3.req_ref_p.fn_mod.t1 = GET_N_BITS(5);
        pMsg->add3.req_ref_p.fn_mod.t3 = GET_N_BITS(6);
        pMsg->add3.req_ref_p.fn_mod.t2 = GET_N_BITS(5);
      }
    }
  }

  /*-------------------------------------------------------------------------*/

  /* --- MESSAGE ESCAPE --- */

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;

#ifdef REL99  
  pMsg->egprs_flag = GET_N_BITS(1);
  if (pMsg->egprs_flag == 1)
  {
    /* Extending the Packet uplink assignment message decoding 
	 * for EGPRS additions. We do not support EGPRS. So return
	 * doing nothing
	 */
    return ccdOK;
  }
#else
  bit = GET_N_BITS(1);
  if (bit == 1)                               /* 1 equals to Message Escape  */
    return ccdOK;                             /*   then we are ready         */
#endif

  /* When message egprs_flag is FALSE, the valid flags of all the 
   * corresponding conditional elements, is made TRUE here
   */
  pMsg->v_chan_coding_cmd = pMsg->v_tlli_chan_coding = TRUE;
  pMsg->v_pta = pMsg->v_flag = pMsg->v_flag2 = TRUE;
#ifdef REL99
  pMsg->v_release_99 = TRUE;
#endif

  /* --- NON-DISTRIBUTION CONTENTS --- */

  if (bitLen < 3)
    return ERR_MAND_ELEM_MISS;                

  pMsg->chan_coding_cmd  = GET_N_BITS(2);     /* CHANNEL_COD._COMMAND:bit(2) */

  pMsg->tlli_chan_coding = GET_N_BITS(1);     /* TLLI_BLOCK_CHAN_COD.:bit(1) */

  /*-------------------------------------------------------------------------*/
  ret_code = grr_decode_ie_pta (&pMsg->pta);  /* Packet Timing Advanced IE   */
  
  if(ret_code != ccdOK)
    return ret_code;

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* Frequency Parameters IE     */
  {
    ret_code = grr_decode_ie_freq_par (&pMsg->freq_par);

    if (ret_code == ccdOK)
      pMsg->v_freq_par = TRUE;
    else
      return ret_code;
  }

  /*-------------------------------------------------------------------------*/

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  pMsg->flag = GET_N_BITS(1);
  if (pMsg->flag == 0)                        
  {
    if (bitLen < 1)
      return ERR_MAND_ELEM_MISS;                

    pMsg->flag2 = GET_N_BITS(1);
    if (pMsg->flag2 == 1)                     /* 01: Dynamic Allocation IE   */
    {
      ret_code = grr_decode_ie_dyn_alloc_p (&pMsg->dyn_alloc_p);

      if (ret_code == ccdOK)
        pMsg->v_dyn_alloc_p = TRUE;
      else
        return ret_code;
    }
    else
    {
      /* ffs. */                              /* 00: for further extensions  */
    }
  }
  else
  {
    if (bitLen < 1)
      return ERR_MAND_ELEM_MISS;                

    pMsg->flag2 = GET_N_BITS(1);
    if (pMsg->flag2 == 0)                     /* 10: Single Block Allocation */
    {
      if (bitLen < 4)
        return ERR_MAND_ELEM_MISS;                

      pMsg->sin_alloc.tn = GET_N_BITS(3);

      if (bitLen < 1)
        return ERR_MAND_ELEM_MISS;

      bit = GET_N_BITS(1);
      if (bit == 1)
      {
        if (bitLen < 9)
          return ERR_MAND_ELEM_MISS;

        pMsg->sin_alloc.v_alf_gam = TRUE;
        pMsg->sin_alloc.alf_gam.alpha = GET_N_BITS(4);
        pMsg->sin_alloc.alf_gam.gamma = GET_N_BITS(5);
      }

      if (bitLen < 1)
        return ERR_MAND_ELEM_MISS;

      bit = GET_N_BITS(1);
      if (bit == 1)
      {
        if (bitLen < 6)
          return ERR_MAND_ELEM_MISS;

        pMsg->sin_alloc.v_bts_pwr_ctrl       = TRUE;
        pMsg->sin_alloc.bts_pwr_ctrl.p0      = GET_N_BITS(4);
        pMsg->sin_alloc.bts_pwr_ctrl.mode    = GET_N_BITS(1);
        pMsg->sin_alloc.bts_pwr_ctrl.pr_mode = GET_N_BITS(1);
      }

      ret_code = grr_decode_ie_tbf_s_time (&pMsg->sin_alloc.tbf_s_time);

      if (ret_code != ccdOK)
        return ret_code;

      pMsg->v_sin_alloc = TRUE;
    }
    else                                      /* 11: Fixed Allocation        */
    {
      if (bitLen < 1)
        return ERR_MAND_ELEM_MISS;

      bit = GET_N_BITS(1);
      if (bit == 1)
      {
        pMsg->f_alloc_ul.v_ul_tfi_assign = TRUE;
        pMsg->f_alloc_ul.ul_tfi_assign   = GET_N_BITS(5);
      }

      if (bitLen < 5)
        return ERR_MAND_ELEM_MISS;

      pMsg->f_alloc_ul.final_alloc = GET_N_BITS(1);;
      pMsg->f_alloc_ul.dl_ctrl_ts  = GET_N_BITS(3);;

      bit = GET_N_BITS(1);
      if (bit == 1)
      {
        if (bitLen < 6)
          return ERR_MAND_ELEM_MISS;

        pMsg->f_alloc_ul.v_bts_pwr_ctrl       = TRUE;
        pMsg->f_alloc_ul.bts_pwr_ctrl.p0      = GET_N_BITS(4);
        pMsg->f_alloc_ul.bts_pwr_ctrl.mode    = GET_N_BITS(1);
        pMsg->f_alloc_ul.bts_pwr_ctrl.pr_mode = GET_N_BITS(1);
      }

      pMsg->f_alloc_ul.flag = GET_N_BITS(1);
      if(pMsg->f_alloc_ul.flag == 0)
      {
        pMsg->f_alloc_ul.v_ts_alloc = TRUE;
        pMsg->f_alloc_ul.ts_alloc   = GET_N_BITS(8);
      }
      else
      {
        ret_code = grr_decode_ie_pwr_par (&pMsg->f_alloc_ul.pwr_par);

        if (ret_code == ccdOK)
          pMsg->f_alloc_ul.v_pwr_par = TRUE;
        else
          return ret_code;
      }

      if (bitLen < 1)
        return ERR_MAND_ELEM_MISS;

      pMsg->f_alloc_ul.half_dupelx = GET_N_BITS(1);

      ret_code = grr_decode_ie_tbf_s_time (&pMsg->f_alloc_ul.tbf_s_time);

      if (ret_code != ccdOK)
        return ret_code;

      bit = GET_N_BITS(1);
      if(bit == 0)
      {
        if (bitLen < 1)
          return ERR_MAND_ELEM_MISS;

        pMsg->f_alloc_ul.flag2 = GET_N_BITS(1);
        if (pMsg->f_alloc_ul.flag2 == 0)      /* with len Allocation Bitmap  */
        {
          if (bitLen < 8)
            return ERR_MAND_ELEM_MISS;

          pMsg->f_alloc_ul.block_struct.bl_o_bl_per = GET_N_BITS(1);
          pMsg->f_alloc_ul.block_struct.a_map_len   = GET_N_BITS(7);

          if (bitLen < pMsg->f_alloc_ul.block_struct.a_map_len)
            return ERR_MAND_ELEM_MISS;

          for (i=0; i<pMsg->f_alloc_ul.block_struct.a_map_len; i++)
          {
            pMsg->f_alloc_ul.block_struct.alloc_map[i] = GET_N_BITS(1);
          }

          pMsg->f_alloc_ul.block_struct.c_alloc_map = i;
          pMsg->f_alloc_ul.v_block_struct           = TRUE;
        }
        else                          /* without lenght of Allocation Bitmap */
        {                             /* Bitmap fills remainder of message   */
          pMsg->f_alloc_ul.v_alloc_map = TRUE;

          if (bitLen > 127)
            pMsg->f_alloc_ul.c_alloc_map = 127;
          else
            pMsg->f_alloc_ul.c_alloc_map = bitLen;

          for (i=0; i<pMsg->f_alloc_ul.c_alloc_map; i++)
          {
            pMsg->f_alloc_ul.alloc_map[i] = GET_N_BITS(1);
          }
        }
      }
      else
      {
         /* Message Escape */
      }

      pMsg->v_f_alloc_ul = TRUE;
    }
  }

#ifdef REL99
  /* Updation of packet uplink assignment message decoding for 
   * R99 extensions 
   */
  pMsg->release_99 = GET_N_BITS(1);
  if(pMsg->release_99 == 1)
  {
    if(bitLen < 2)
      return ERR_MAND_ELEM_MISS;
    pMsg->v_p_ext_ta = TRUE;
    pMsg->p_ext_ta = GET_N_BITS(2);
  }
#endif

  /* --- PADDING BITS --- */ /* -> currently not decoded and/or validated */
  return ccdOK;
}

/*
+------------------------------------------------------------------------------
| Function    : grr_decode_polling_req
+------------------------------------------------------------------------------
| Description : For performance reasons this function replaces the call to the
|               function ccd_decodeMsg. If no error occured, the D_POLLING_REQ 
|               message is decoded into _decodeCtrlMsg.
|
| Parameters  : buf    - pointer to beginning of the D_POLLING_REQ IE
|               len    - lenght of the buffer in bits
|               off    - bit offset of the first bit in the buffer
|
| Returns     : ccdOK  - if no error is occured
|                      - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_polling_req (UBYTE* buf, int off, int len)
{ 
  int    bit;                                    
  USHORT h_byte;
  UBYTE  ret_code;

  MCAST(pMsg, D_POLLING_REQ);

  /*-------------------------------------------------------------------------*/
  startBit = off;                             /* Initiate global data        */
  bitLen   = len;
  pBuf     = buf;

  memset (pMsg, 0, sizeof(T_D_POLLING_REQ));  /* init destination struct     */

  /*-------------------------------------------------------------------------*/

  if (bitLen < 8)                             
    return ERR_MAND_ELEM_MISS;
  
  pMsg->msg_type  = GET_N_BITS(6);            /* MESSAGE_TYPE : bit(6)       */
  
  /* --- DISTRIBUTION CONTENTS --- */

  pMsg->page_mode = GET_N_BITS(2);            /* PAGE_MODE : bit(2)          */ 


  /*-------------------------------------------------------------------------*/

  /* --- ADDRESS INFORMATON --- */

  pMsg->add2.flag = GET_N_BITS(1);
  if (pMsg->add2.flag == 0)                   /* Global TFI                  */
  {
    ret_code = grr_decode_ie_glob_tfi (&pMsg->add2.glob_tfi);

    if (ret_code == ccdOK)
      pMsg->add2.v_glob_tfi = TRUE;
    else
      return ret_code;
  }
  else
  {
    if (bitLen < 1)
      return ERR_MAND_ELEM_MISS;              

    pMsg->add2.v_flag2 = TRUE;

    pMsg->add2.flag2 = GET_N_BITS(1);
    if (pMsg->add2.flag2 == 0)                /* TLLI                        */
    {
      if (bitLen < 32)
        return ERR_MAND_ELEM_MISS;

      ret_code = grr_decode_ie_tlli (&pMsg->add2.tlli_value);

      if(ret_code == ccdOK)
        pMsg->add2.v_tlli_value = TRUE;             
      else
        return ret_code;
    }
    else
    {
      if (bitLen < 1)
        return ERR_MAND_ELEM_MISS;              

      bit = GET_N_BITS(1);
      if (bit == 0)                           /* TQI : bit(16)               */
      {
        if (bitLen < 16)
          return ERR_MAND_ELEM_MISS;              

        pMsg->add2.v_tqi = TRUE;             
                  h_byte = GET_N_BITS(8);
        pMsg->add2.tqi   = (h_byte << 8) + GET_N_BITS(8);
      }
      else 
      {
        return ERR_ADDR_INFO_PART;              
      }
    }
  }

  /*-------------------------------------------------------------------------*/

  /* --- TYPE OF ACK --- */

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  pMsg->ctrl_ack_type = GET_N_BITS(1);

  /* --- PADDING BITS --- */ /* -> currently not decoded and/or validated */

  return ccdOK;
}
/*
+------------------------------------------------------------------------------
| Function    : grr_decode_tbf_release_req
+------------------------------------------------------------------------------
| Description : For performance reasons this function replaces the call to the
|               function ccd_decodeMsg. If no error occured, the D_TBF_RELEASE 
|               message is decoded into _decodeCtrlMsg.
|
| Parameters  : buf    - pointer to beginning of the D_TBF_RELEASE IE
|               len    - lenght of the buffer in bits
|               off    - bit offset of the first bit in the buffer
|
| Returns     : ccdOK  - if no error is occured
|                      - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_tbf_release_req (UBYTE* buf, int off, int len)
{ 
  int    bit;                                    
  UBYTE  ret_code;

  MCAST(pMsg, D_TBF_RELEASE);

  /*-------------------------------------------------------------------------*/
  startBit = off;                             /* Initiate global data        */
  bitLen   = len;
  pBuf     = buf;

  memset (pMsg, 0, sizeof(T_D_TBF_RELEASE));  /* init destination struct     */

  /*-------------------------------------------------------------------------*/

  if (bitLen < 8)                             
    return ERR_MAND_ELEM_MISS;
  
  pMsg->msg_type  = GET_N_BITS(6);            /* MESSAGE_TYPE : bit(6)       */
  
  /* --- DISTRIBUTION CONTENTS --- */

  pMsg->page_mode = GET_N_BITS(2);            /* PAGE_MODE : bit(2)          */ 


  /*-------------------------------------------------------------------------*/

  /* --- ADDRESS INFORMATON --- */

  bit = GET_N_BITS(1);
  if (bit == 0)                               /* Global TFI                  */
  {
    ret_code = grr_decode_ie_glob_tfi (&pMsg->glob_tfi);

    if (ret_code NEQ ccdOK)
      return ret_code;
  }
  else
  {
    return ERR_ADDR_INFO_PART;              
  }

  /*-------------------------------------------------------------------------*/

  /* --- UPLINK/ DOWNLINK RELEASE VALUES --- */

  if (bitLen < 6)
    return ERR_MAND_ELEM_MISS;                

  pMsg->ul_release = GET_N_BITS(1);
  pMsg->dl_release = GET_N_BITS(1);
  pMsg->rel_cause  = GET_N_BITS(4);

  /* --- PADDING BITS --- */ /* -> currently not decoded and/or validated */

  return ccdOK;
}
/*
+------------------------------------------------------------------------------
| Function    : grr_decode_ts_reconfig
+------------------------------------------------------------------------------
| Description : For performance reasons this function replaces the call to the
|               function ccd_decodeMsg. If no error occured, the D_TS_RECONFIG
|               message is decoded into _decodeCtrlMsg.
|
| Parameters  : buf    - pointer to beginning of the D_TS_RECONFIG IE
|               len    - lenght of the buffer in bits
|               off    - bit offset of the first bit in the buffer
|
| Returns     : ccdOK  - if no error is occured
|                      - else CCD error code
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_decode_ts_reconfig (UBYTE* buf, int off, int len)
{ 
  int    i;
  int    bit;                                    
  UBYTE  ret_code;

  MCAST(pMsg, D_TS_RECONFIG);

  /*-------------------------------------------------------------------------*/
  startBit = off;                             /* Initiate global data        */
  bitLen   = len;
  pBuf     = buf;

  memset (pMsg, 0, sizeof(T_D_TS_RECONFIG));  /* init destination struct     */

  /*-------------------------------------------------------------------------*/

  if (bitLen < 8)                             
    return ERR_MAND_ELEM_MISS;
  
  pMsg->msg_type  = GET_N_BITS(6);            /* MESSAGE_TYPE : bit(6)       */
  
  /* --- DISTRIBUTION CONTENTS --- */

  pMsg->page_mode = GET_N_BITS(2);            /* PAGE_MODE : bit(2)          */ 

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ccdOK;                             

  /*-------------------------------------------------------------------------*/
  bit = GET_N_BITS(1);
  if(bit == 0)                                /* GLOBAL_TFI                  */
  {
    ret_code = grr_decode_ie_glob_tfi (&pMsg->glob_tfi);

    if (ret_code != ccdOK)
      return ret_code;
  }

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

#ifdef REL99
  pMsg->egprs_flag = GET_N_BITS(1);
  if (pMsg->egprs_flag == 1)
  {
    /*EGPRS is not supported. Just return */
    return ccdOK;
  }
#else
  bit = GET_N_BITS(1);
  if (bit == 1)                               /* 1 equals to Message Escape  */
    return ccdOK;                             /*   then we are ready         */
#endif



  /* When message egprs_flag is FALSE, the valid flags of all the 
   * corresponding conditional elements, is made TRUE here
   */
  pMsg->v_chan_coding_cmd = pMsg->v_gpta = pMsg->v_dl_rlc_mode = TRUE;
  pMsg->v_ctrl_ack = pMsg->v_dl_tn_alloc = pMsg->v_flag = TRUE;

#ifdef REL99
  pMsg->v_release_99 = TRUE;
#endif



  /*-------------------------------------------------------------------------*/
  if (bitLen < 2)
    return ERR_MAND_ELEM_MISS;                

  pMsg->chan_coding_cmd = GET_N_BITS(2);      /* CHANNEL_COD._COMMAND:bit(2) */

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* TIMING_ADVANCED_VALUE       */
  {
    if (bitLen < 6)
      return ERR_MAND_ELEM_MISS;                

    pMsg->gpta.v_ta_value = TRUE;
    pMsg->gpta.ta_value   = GET_N_BITS(6);
  }

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  pMsg->gpta.flag = GET_N_BITS(1);
  if (pMsg->gpta.flag == 1)                   /* UPLINK_TIMING_ADVANCED      */
  {
    if (bitLen < 7)
      return ERR_MAND_ELEM_MISS;                

    pMsg->gpta.v_ul_ta_index = TRUE;
    pMsg->gpta.ul_ta_index   = GET_N_BITS(4);

    pMsg->gpta.v_ul_ta_tn    = TRUE;
    pMsg->gpta.ul_ta_tn      = GET_N_BITS(3);
  }

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  pMsg->gpta.flag2 = GET_N_BITS(1);
  if (pMsg->gpta.flag2 == 1)                  /* DOWNLINK_TIMING_ADVANCED    */
  {
    if (bitLen < 7)
      return ERR_MAND_ELEM_MISS;                

    pMsg->gpta.v_dl_ta_index = TRUE;
    pMsg->gpta.dl_ta_index   = GET_N_BITS(4);

    pMsg->gpta.v_dl_ta_tn    = TRUE;
    pMsg->gpta.dl_ta_tn      = GET_N_BITS(3);
  }

  /*-------------------------------------------------------------------------*/
  if (bitLen < 2)
    return ERR_MAND_ELEM_MISS;      
              
  pMsg->dl_rlc_mode = GET_N_BITS(1);
  pMsg->ctrl_ack    = GET_N_BITS(1);

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;      

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* DOWNLINK_TFI_ASSIGNMENT     */
  {
    if (bitLen < 5)
      return ERR_MAND_ELEM_MISS;      

    pMsg->v_dl_tfi = TRUE;
    pMsg->dl_tfi   = GET_N_BITS(5);
  }

  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;      

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* UPLINK_DFI_ASSIGNMENT       */
  {
    if (bitLen < 5)
      return ERR_MAND_ELEM_MISS;      

    pMsg->v_ul_tfi = TRUE;
    pMsg->ul_tfi   = GET_N_BITS(5);
  }

  /*-------------------------------------------------------------------------*/
  if (bitLen < 8)
    return ERR_MAND_ELEM_MISS;      

  pMsg->dl_tn_alloc = GET_N_BITS(8);          /* DOWNLINK_TIMESLOT_ALLOCATION*/

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  bit = GET_N_BITS(1);
  if (bit == 1)                               /* Frequency Parameters IE     */
  {
    ret_code = grr_decode_ie_freq_par (&pMsg->freq_par);

    if (ret_code == ccdOK)
      pMsg->v_freq_par = TRUE;
    else
      return ret_code;
  }

  /*-------------------------------------------------------------------------*/
  if (bitLen < 1)
    return ERR_MAND_ELEM_MISS;                

  pMsg->flag = GET_N_BITS(1);
  if (pMsg->flag == 0)                        /* Dynamic Allocation struct   */
  {
    ret_code = grr_decode_ie_dyn_alloc_ts (&pMsg->dyn_alloc_ts);

    if (ret_code == ccdOK)                      
      pMsg->v_dyn_alloc_ts = TRUE;
    else
      return ret_code;
  }
  else                                        /* Fixed Allocation struct     */
  {
    if (bitLen < 1)
      return ERR_MAND_ELEM_MISS;                

    pMsg->f_alloc_re.flag = GET_N_BITS(1);
    if (pMsg->f_alloc_re.flag == 0)           /* UPLINK_TIMESLOT_ALLOCATION  */
    {
      if (bitLen < 8)
        return ERR_MAND_ELEM_MISS;                

      pMsg->f_alloc_re.v_ul_ts_alloc = TRUE;
      pMsg->f_alloc_re.ul_ts_alloc   = GET_N_BITS(8);
    }
    else                                      /* Power Control Parameters IE */
    {
      ret_code = grr_decode_ie_pwr_par (&pMsg->f_alloc_re.pwr_par);

      if (ret_code == ccdOK)
        pMsg->f_alloc_re.v_pwr_par = TRUE;
      else
        return ret_code;
    }

    if (bitLen < 4)
      return ERR_MAND_ELEM_MISS;                

    pMsg->f_alloc_re.final_alloc = GET_N_BITS(1);
    pMsg->f_alloc_re.dl_ctrl_ts  = GET_N_BITS(3);

    bit = GET_N_BITS(1);
    if (bit == 1)
    {
      if (bitLen < 6)
        return ERR_MAND_ELEM_MISS;

      pMsg->f_alloc_re.v_bts_pwr_ctrl       = TRUE;
      pMsg->f_alloc_re.bts_pwr_ctrl.p0      = GET_N_BITS(4);
      pMsg->f_alloc_re.bts_pwr_ctrl.mode    = GET_N_BITS(1);
      pMsg->f_alloc_re.bts_pwr_ctrl.pr_mode = GET_N_BITS(1);
    }

    if (bitLen < 1)
      return ERR_MAND_ELEM_MISS;              

    bit = GET_N_BITS(1);
    if (bit == 1)                               /* Measurement Mapping         */
    {                                       
      ret_code = grr_decode_ie_meas_map (&pMsg->f_alloc_re.meas_map);

      if (ret_code == ccdOK)
        pMsg->f_alloc_re.v_meas_map = TRUE;
      else
        return ret_code;
    }
                                                /* TBF Starting Time           */
    ret_code = grr_decode_ie_tbf_s_time (&pMsg->f_alloc_re.tbf_s_time);

    if (ret_code != ccdOK)
      return ret_code;

    bit = GET_N_BITS(1);
    if(bit == 0)
    {
      if (bitLen < 1)
        return ERR_MAND_ELEM_MISS;

      pMsg->f_alloc_re.flag2 = GET_N_BITS(1);
      if (pMsg->f_alloc_re.flag2 == 0) /* with lenght of Allocation Bitmap */
      {
        if (bitLen < 8)
          return ERR_MAND_ELEM_MISS;

        pMsg->f_alloc_re.block_struct.bl_o_bl_per = GET_N_BITS(1);
        pMsg->f_alloc_re.block_struct.a_map_len   = GET_N_BITS(7);

        if (bitLen < pMsg->f_alloc_re.block_struct.a_map_len)
          return ERR_MAND_ELEM_MISS;

        for (i=0; i<pMsg->f_alloc_re.block_struct.a_map_len; i++)
        {
          pMsg->f_alloc_re.block_struct.alloc_map[i] = GET_N_BITS(1);
        }

        pMsg->f_alloc_re.block_struct.c_alloc_map = i;
        pMsg->f_alloc_re.v_block_struct           = TRUE;
      }
      else                          /* without lenght of Allocation Bitmap */
      {                             /* Bitmap fills remainder of message   */
        pMsg->f_alloc_re.v_alloc_map = TRUE;

        if (bitLen > 127)
          pMsg->f_alloc_re.c_alloc_map = 127;
        else
          pMsg->f_alloc_re.c_alloc_map = bitLen;

        for (i=0; i<pMsg->f_alloc_re.c_alloc_map; i++)
        {
          pMsg->f_alloc_re.alloc_map[i] = GET_N_BITS(1);
        }
      }
    }
    else
    {
       /* Message Escape */
    }

    pMsg->v_f_alloc_re = TRUE;
  }

#ifdef REL99
  /* Updation of packet time slot reconf message decoding for R99 
   * extensions
   */
  pMsg->release_99 = GET_N_BITS(1);
  if(pMsg->release_99 == 1)
  {
    if(bitLen < 2)
      return ERR_MAND_ELEM_MISS;
    pMsg->v_p_ext_ta = TRUE;
    pMsg->p_ext_ta = GET_N_BITS(2);
  }
#endif

  return ccdOK;
}

/*
+------------------------------------------------------------------------------
| Function    : grr_ccd_error_handling
+------------------------------------------------------------------------------
| Description : The function grr_ccd_error_handling() ...
|
| Parameters  : entity_i - the CCD was called for this entity
|
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_ccd_error_handling ( UBYTE entity_i  )
{ 
  UBYTE result = DELETE_MESSAGE;
  USHORT parlist [MAX_ERR_PAR];
  UBYTE first_error; 

  TRACE_FUNCTION( "grr_ccd_error_handling" );


  memset (parlist, 0, sizeof (parlist));
  
  first_error = ccd_getFirstError (entity_i, parlist);
  
  switch (first_error)
  {
    
  case ERR_PATTERN_MISMATCH:      /* A spare pattern does not match with  */
    /* the specified content                */
    /* Error params[0] = bitposition        */
    {
      MCAST(ptr,D_DL_ASSIGN);
      result = ptr->msg_type;
    }
    break;
    
  default:
    /* SZML-GLBL/010 */
    TRACE_ERROR( "Ctrl-Message will be deleted" );
    break;
  }
  
  return(result);

} /* grr_ccd_error_handling() */


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



/*
+------------------------------------------------------------------------------
| Function    : grr_check_ptmsi
+------------------------------------------------------------------------------
| Description : The function grr_check_ptmsi() checks the ptmsi and returns 
|               TRUE if the ptmsi is correct.
|
| Parameters  : ptmsi_i - ptr to ptmsi buffer
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_check_ptmsi ( BUF_ptmsi * ptmsi_i )
{ 
  ULONG ptmsi;
  BOOL result = FALSE;

  TRACE_FUNCTION( "grr_check_ptmsi" );
  
  ptmsi = grr_buffer2ulong( ptmsi_i );

  /*
   * if the new_pmsi is invalid the old should be onsidered s invalid too
   */
  if(grr_data->db.ms_id.new_ptmsi NEQ GMMRR_TMSI_INVALID)
  {
    if(grr_data->db.ms_id.old_ptmsi EQ ptmsi
    OR
    grr_data->db.ms_id.new_ptmsi EQ ptmsi)
    {
      result= TRUE;
    };
  }
  else
  {
    TRACE_EVENT_P2("NO valid PTMSI IN GRR PRESENT !!! old_ptmsi=%lx  new_ptmsi=%lx"
                                                            ,grr_data->db.ms_id.old_ptmsi
                                                            ,grr_data->db.ms_id.new_ptmsi);  
  }
  if(!result)
  {
    TRACE_EVENT_P5("OLD PTMSI: %LX, DESTINATION PTMSI: %LX   len=%d off=%d  NEW PTMSI=%lx"
                   ,grr_data->db.ms_id.old_ptmsi
                   ,ptmsi
                   ,ptmsi_i->l_ptmsi
                   ,ptmsi_i->o_ptmsi
                   ,grr_data->db.ms_id.new_ptmsi);
    
    TRACE_EVENT_P8("PTMSI BUF:buf[0 .. 7]=  %x %x %x %x %x %x %x %x "
                   ,ptmsi_i->b_ptmsi[0]
                   ,ptmsi_i->b_ptmsi[1]
                   ,ptmsi_i->b_ptmsi[2]
                   ,ptmsi_i->b_ptmsi[3]
                   ,ptmsi_i->b_ptmsi[4]
                   ,ptmsi_i->b_ptmsi[5]
                   ,ptmsi_i->b_ptmsi[6]
                   ,ptmsi_i->b_ptmsi[7]);

  }

  return(result);
} /* grr_check_ptmsi() */



/*
+------------------------------------------------------------------------------
| Function    : grr_check_tmsi
+------------------------------------------------------------------------------
| Description : The function grr_check_tmsi() checks the tmsi and returns 
|               TRUE if the tmsi is correct.
|
| Parameters  : tmsi_i - ptr to tmsi buffer
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_check_tmsi ( BUF_tmsi_field * tmsi_i )
{ 
  ULONG tmsi;
  BOOL result = FALSE;

  TRACE_FUNCTION( "grr_check_tmsi" );
  
  tmsi = grr_buffer2ulong( (BUF_ptmsi*) tmsi_i );
  
  if(tmsi EQ grr_data->db.ms_id.tmsi) result = TRUE;

  return(result);

} /* grr_check_tmsi() */




/*
+------------------------------------------------------------------------------
| Function    : grr_check_all_tlli
+------------------------------------------------------------------------------
| Description : The function grr_check_all_tlli() checks the tlli with all TLLI
|               GMM has assigned and returns TRUE if the tlli is between them. 
|
| Parameters  : tlli_i - ptr to tlli buffer
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_check_all_tlli ( BUF_tlli_value * tlli_i )
{ 
  ULONG tlli;
  BOOL result = FALSE;

  TRACE_FUNCTION( "grr_check_all_tlli" );
  
  tlli = grr_buffer2ulong( (BUF_ptmsi*)tlli_i );

  /*
   * if the new_tlli is invalid the old should be onsidered s invalid too
   */
  if(grr_data->db.ms_id.new_tlli NEQ GMMRR_TLLI_INVALID)
  {
    if(grr_data->db.ms_id.new_tlli EQ tlli)
    {
      grr_data->db.ms_id.received_tlli = grr_data->db.ms_id.new_tlli;
      result = TRUE;
    }
    else if (grr_data->db.ms_id.old_tlli EQ tlli)
    {
      
      grr_data->db.ms_id.received_tlli = grr_data->db.ms_id.old_tlli;
      result = TRUE;
    };
  }

  if(result)
  {
    tc_cgrlc_enable_req(CGRLC_QUEUE_MODE_DEFAULT,CGRLC_RA_DEFAULT,FALSE,CGRLC_ENAC_NORMAL);
  }
  else
  {
    TRACE_EVENT_P5("OLD TLLI: %LX, DESTINATION TLLI: %LX   len=%d off=%d  NEW TLLI=%lx"
                   ,grr_data->db.ms_id.old_tlli
                   ,tlli
                   ,tlli_i->l_tlli_value
                   ,tlli_i->o_tlli_value
                   ,grr_data->db.ms_id.new_tlli);
    
    TRACE_EVENT_P8("TLLI BUF:buf[0 .. 7]=  %x %x %x %x %x %x %x %x "
                   ,tlli_i->b_tlli_value[0]
                   ,tlli_i->b_tlli_value[1]
                   ,tlli_i->b_tlli_value[2]
                   ,tlli_i->b_tlli_value[3]
                   ,tlli_i->b_tlli_value[4]
                   ,tlli_i->b_tlli_value[5]
                   ,tlli_i->b_tlli_value[6]
                   ,tlli_i->b_tlli_value[7]);

  }

  return(result);

} /* grr_check_all_tlli() */



/*
+------------------------------------------------------------------------------
| Function    : grr_buffer2ulong
+------------------------------------------------------------------------------
| Description : The function grr_buffer2ulong() copy a 32-Bit-Buffer in a ULONG
|               variable
|               
|               SZML-GLBL/002
|
| Parameters  : ptmsi - pointer to buffer that contains the 32bit for the ULONG 
|
+------------------------------------------------------------------------------
*/
GLOBAL ULONG grr_buffer2ulong ( BUF_ptmsi * ptmsi)
{
  ULONG ul;
 
  UBYTE l, dummy; 
  USHORT i, ii;
  UBYTE off1, off2;
  
  TRACE_FUNCTION( "grr_buffer2ulong" ); 
  
  ul= 0;
  
  l = (UBYTE)ptmsi->l_ptmsi;
  
  off1 = ptmsi->o_ptmsi / 8;
  off2 = ptmsi->o_ptmsi % 8;
  
  dummy = 0;
  dummy = ptmsi->b_ptmsi[off1] << off2;
  
  if(l <= (8-off2))
  {
    dummy = dummy >> (8-l);
    ul |= dummy;
    return ul;
  }
  dummy = dummy >> off2;
  ul |= dummy;
  l -= (8-off2);
  
  do
  {
    off1++;
    
    if(l < 8)
    {
      dummy = ptmsi->b_ptmsi[off1] >> (8-l);
      ii = 1;
      ul = ul << l;
      for(i=0; i< l; i++)
      {
        ul = ul | (dummy & ii);
        ii *= 2;
      }
      return ul;  
    }
    else
    {
      ul = ul << 8;
      ul |= ptmsi->b_ptmsi[off1];
      l -= 8;
      if(l EQ 0)
        return ul;
    }
  }
  while(TRUE);
}






/*
+------------------------------------------------------------------------------
| Function    : grr_decode_rr
+------------------------------------------------------------------------------
| Description : The function grr_decode_rr() calls the function ccd_decodeMsg.
|               After the call the decoded Message is in _decodeCtrlMsg.
|               
|
| Parameters  : msg_ptr_i - pointer to buffer that should be decoded
|
+------------------------------------------------------------------------------
*/

GLOBAL UBYTE grr_decode_rr (   T_MSGBUF  *  msg_ptr_i )
{ 
  UBYTE result;


  TRACE_FUNCTION( "grr_decode_rr" );

  
  
  result = ccd_decodeMsg ( CCDENT_RR, 
                  DOWNLINK,
                  msg_ptr_i,
                  _decodedMsg, 
                  NOT_PRESENT_8BIT);


  if ( result EQ ccdError)
  {
    TRACE_ERROR( "grr_decode_rr - decoding of RR message failed" );

    result = grr_ccd_error_handling(CCDENT_RR);
  }
  else
  {
    MCAST(ptr, D_SYS_INFO_13); /* get one message from the RR message-base*/
    result = ptr->msg_type; /*  this is the type of the decoded message*/
  }
  
  return(result);
  
} /* grr_decode_rr() */


  
/*
+------------------------------------------------------------------------------
| Function    : grr_calc_new_poll_pos
+------------------------------------------------------------------------------
| Description : The function grr_calc_new_poll_pos() calculates the fn of the 
|               new poll position
|
| Parameters  : fn_i    - framenumber
|               rrbp_i  - relative position
|
+------------------------------------------------------------------------------
*/
GLOBAL ULONG grr_calc_new_poll_pos ( ULONG fn_i, UBYTE rrbp_i )
{ 
  ULONG result=0;
  TRACE_FUNCTION( "grr_calc_new_poll_pos" );

  switch( rrbp_i )
  {
  case 0:
    result = (fn_i+13);
    break;
  case 1:
    if((fn_i+18)%13)
      result = (fn_i+17);
    else
      result = (fn_i+18);
    break;
  case 2:
    if(((fn_i+21)%13) EQ 8)
      result = (fn_i+21);
    else
      result = (fn_i+22);
    break;
  case 3:
    result = (fn_i+26);
    break;
  default:
    TRACE_ERROR( "unexpected rrbp  value" );
    break;
  } /* switch (rrbp_i) */
  result = result % 0x297000;

  return result;

} /* grr_calc_new_poll_pos() */






/*
+------------------------------------------------------------------------------
| Function    : grr_encode_ctrl
+------------------------------------------------------------------------------
| Description : The function grr_encode_ctrl() build a T_SDU buffer that 
|               contains the encode Ctrl Block ready to transmit. 
|
| Parameters  : ULONG ptr_in_i - ptr to the input structure
|               ULONG ptr_out_i - ptr to begin of output buffer
|               UBYTE r_bit_i - value of r_bit
+------------------------------------------------------------------------------
*/
GLOBAL void grr_encode_ctrl ( UBYTE * ptr_in_i, 
                              T_MSGBUF * ptr_out_i, 
                              UBYTE r_bit_i)
{ 
  TRACE_FUNCTION( "grr_encode_ctrl" );

  ptr_out_i->buf[0] = grr_get_ul_ctrl_block_header( r_bit_i );
  ptr_out_i->o_buf  = BIT_UL_CTRL_BLOCK_MAC_HEADER;
  ptr_out_i->l_buf  = BIT_UL_CTRL_BLOCK_CONTENTS;

  ccd_codeMsg ( CCDENT_GRR, 
                UPLINK,
                ptr_out_i,
                ptr_in_i, 
                NOT_PRESENT_8BIT);

  ptr_out_i->l_buf += ptr_out_i->o_buf;
  ptr_out_i->o_buf  = 0;

} /* grr_encode_ctrl() */


/*
+------------------------------------------------------------------------------
| Function    : grr_save_persistence_level
+------------------------------------------------------------------------------
| Description : The function grr_save_persistence_level() saves the persistence 
|               level values to the data_base. 
|
| Parameters  : ptr2persistence_level_i - pointer to received data
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_save_persistence_level ( T_pers_lev * ptr2persistence_level_i )
{ 
  UBYTE i ;
  TRACE_FUNCTION( "grr_save_persistence_level" );


  for(i=0; i<4; i++)
  {
     psc_db->prach.pers_lev.plev[i] = ptr2persistence_level_i->plev[i];
  }

} /* grr_save_persistence_level() */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_db_mode
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL T_DB_MODE grr_get_db_mode( void )
{ 
  TRACE_FUNCTION( "grr_get_db_mode" );

  return( grr_data->sc_db_mode );

}/* grr_get_db_mode */

/*
+------------------------------------------------------------------------------
| Function    : grr_set_db_ptr
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_set_db_ptr( T_DB_MODE mode )
{ 
  UBYTE old_mode = grr_data->sc_db_mode;

  TRACE_FUNCTION( "grr_set_db_ptr" );

  switch( mode )
  {
    case( DB_MODE_INIT ):
      grr_data->sc_db_mode = (UBYTE)mode;
      
      psc_db  = &grr_data->sc_db_1;
      posc_db = NULL;
      prsc_db = NULL;
      pcr_db  = &grr_data->sc_db_2;
      break;

    case( DB_MODE_CC_REQ ):
      if( grr_data->sc_db_mode NEQ DB_MODE_CC_REQ )
      {
        grr_data->sc_db_mode = (UBYTE)mode;

        if( psc_db EQ &grr_data->sc_db_1 )
        {
          psc_db  = &grr_data->sc_db_2;
          posc_db = &grr_data->sc_db_1;
        }
        else
        {
          psc_db  = &grr_data->sc_db_1;
          posc_db = &grr_data->sc_db_2;
        }

        prsc_db = NULL;
        pcr_db  = NULL;
      }
      break;

    case( DB_MODE_SWAP ):
      {
        T_SC_DATABASE *db;

        if( posc_db EQ psc_db )
        {
          posc_db = pcr_db;
        }
        else if( posc_db EQ pcr_db )
        {
          posc_db = psc_db;
        }
        
        if( prsc_db EQ psc_db )
        {
          prsc_db = pcr_db;
        }
        else if( prsc_db EQ pcr_db )
        {
          prsc_db = psc_db;
        }

        db     = psc_db;
        psc_db = pcr_db;
        pcr_db = db;
      }
      break;

    case( DB_MODE_CC_ACC ):
      if( grr_data->sc_db_mode EQ DB_MODE_CC_REQ )
      {
        grr_data->sc_db_mode = (UBYTE)mode;

        if( psc_db EQ &grr_data->sc_db_1 )
        {
          pcr_db = &grr_data->sc_db_2;
        }
        else
        {
          pcr_db = &grr_data->sc_db_1;
        }
      }
/*
      else
      {
        TRACE_ERROR( "Database mode: !DB_MODE_CC_REQ -> DB_MODE_CC_ACC" );
      }
*/
      break;

    case( DB_MODE_CC_REJ ):
      if( grr_data->sc_db_mode EQ DB_MODE_CC_REQ )
      {
        grr_data->sc_db_mode = (UBYTE)mode;

        if( psc_db EQ &grr_data->sc_db_1 )
        {
          psc_db  = &grr_data->sc_db_2;
          prsc_db = &grr_data->sc_db_1;
          pcr_db  = &grr_data->sc_db_1;
        }
        else
        {
          psc_db  = &grr_data->sc_db_1;
          prsc_db = &grr_data->sc_db_2;
          pcr_db  = &grr_data->sc_db_2;
        }

        posc_db = NULL;
      }
/*
      else
      {
        TRACE_ERROR( "Database mode: !DB_MODE_CC_REQ -> DB_MODE_CC_REJ" );
      }
*/
      break;

    default:
      TRACE_ASSERT( mode EQ DB_MODE_INIT   OR
                    mode EQ DB_MODE_CC_REQ OR
                    mode EQ DB_MODE_CC_ACC OR
                    mode EQ DB_MODE_CC_REJ OR
                    mode EQ DB_MODE_SWAP      );
      break;
  }

  TRACE_EVENT_P6( "mode: %d -> %d, database: psc = %d, posc = %d, prsc = %d, pcr = %d",
                  old_mode, mode,
                  grr_get_db_num( psc_db  ), grr_get_db_num( posc_db ),
                  grr_get_db_num( prsc_db ), grr_get_db_num( pcr_db  ) );

}/* grr_set_db_ptr */

/*
+------------------------------------------------------------------------------
| Function    : grr_init_db_srvc_param
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
LOCAL void grr_init_db_srvc_param ( T_SC_DATABASE *db )
{ 
  T_SC_DATABASE *original_db = psc_db;

  TRACE_FUNCTION( "grr_init_db_srvc_param" );

  psc_db = db;
  
  ctrl_init_params( );

  psi_init( );

  pg_init_params( );

  psc_db = original_db;
  
  grr_set_pbcch( FALSE );

}/* grr_init_db_srvc_param */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_db_num
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  :
|
+------------------------------------------------------------------------------
*/
LOCAL UBYTE grr_get_db_num ( T_SC_DATABASE *db )
{ 
  UBYTE db_num;

  TRACE_FUNCTION( "grr_get_db_num" );

  if     ( db EQ NULL               ) db_num = 0;
  else if( db EQ &grr_data->sc_db_1 ) db_num = 1;
  else if( db EQ &grr_data->sc_db_2 ) db_num = 2;
  else                                db_num = 3;

  return( db_num );

}/* grr_get_db_num */

/*
+------------------------------------------------------------------------------
| Function    : grr_init_db
+------------------------------------------------------------------------------
| Description : The function grr_init_db initializes the database in GRR_DATA.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_init_db ( T_SC_DATABASE *db )
{
  TRACE_FUNCTION( "grr_init_db" );
 
  db->cell_info_for_gmm.access_status              = GPRS_ACCESS_BARRED; 
  db->cell_info_for_gmm.cell_info.cell_env.rai.rac = GMMRR_RAC_INVALID;
  db->gprs_attach_is_running                       = FALSE;
  db->non_drx_timer_running                        = FALSE;
  db->non_drx_timer                                = DRX_NO;
  db->nc2_non_drx_period_running                   = FALSE;

  grr_init_db_srvc_param( db );

#ifdef REL99
  db->network_rel = BSS_NW_REL_97;     /*Default Network Release 97 */
#endif

}/* grr_init_db */

/*
+------------------------------------------------------------------------------
| Function    : grr_init
+------------------------------------------------------------------------------
| Description : The function grr_init initializes the entity GRR
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_init ( void )
{ 
  TRACE_FUNCTION( "grr_init" );
  
  /* initialize all GRR data */
  grr_data = &grr_data_base;
  memset( grr_data, 0, sizeof( T_GRR_DATA ) );

  /* initialize the pointers to the databases */
  grr_set_db_ptr( DB_MODE_INIT );

  /* initialize the serving cell databases */
  grr_init_db( psc_db );
  grr_init_db( pcr_db );


  /* 
   * call of service init functions 
   */
  ctrl_init();
  tc_init();
  cpap_init(); 
  psi_init();
  pg_init();
  meas_init( IM_MODE_TRANSFER );
  cs_grr_init();
  gfp_init();

  ccd_register(CCD_REENTRANT);
  
  grr_init_ms_data( );

  grr_data->db.ms_id.old_ptmsi    = GMMRR_TMSI_INVALID;               /* No valid PTMSI*/
  grr_data->db.ms_id.new_ptmsi    = GMMRR_TMSI_INVALID;               /* No valid PTMSI*/
  grr_data->db.ms_id.old_tlli     = GMMRR_TLLI_INVALID;
  grr_data->db.ms_id.new_tlli     = GMMRR_TLLI_INVALID;

  /*
   * SZML-GLBL/003
   */  
  /*set ms capabilty*/
  grr_data->ms_cap[0].Rx   = 1;
  grr_data->ms_cap[0].Tx   = 1;
  grr_data->ms_cap[0].Sum  = 2;
  grr_data->ms_cap[0].Ttb  = 2;
  grr_data->ms_cap[0].Tra  = 4;  /* Tra value for all classes */

  grr_data->ms_cap[1].Rx   = 2;
  grr_data->ms_cap[1].Tx   = 1;
  grr_data->ms_cap[1].Sum  = 3;
  grr_data->ms_cap[1].Ttb  = 2;
  grr_data->ms_cap[1].Tra  = 3;

  grr_data->ms_cap[2].Rx   = 2;
  grr_data->ms_cap[2].Tx   = 2;
  grr_data->ms_cap[2].Sum  = 3;
  grr_data->ms_cap[2].Ttb  = 2;
  grr_data->ms_cap[2].Tra  = 3;

  grr_data->ms_cap[3].Rx   = 3;
  grr_data->ms_cap[3].Tx   = 1;
  grr_data->ms_cap[3].Sum  = 4;
  grr_data->ms_cap[3].Ttb  = 1;
  grr_data->ms_cap[3].Tra  = 3;

  grr_data->ms_cap[4].Rx   = 2;
  grr_data->ms_cap[4].Tx   = 2;
  grr_data->ms_cap[4].Sum  = 4;
  grr_data->ms_cap[4].Ttb  = 1;
  grr_data->ms_cap[4].Tra  = 3;

  grr_data->ms_cap[5].Rx   = 3;
  grr_data->ms_cap[5].Tx   = 2;
  grr_data->ms_cap[5].Sum  = 4;
  grr_data->ms_cap[5].Ttb  = 1;
  grr_data->ms_cap[5].Tra  = 3;

  grr_data->ms_cap[6].Rx   = 3;
  grr_data->ms_cap[6].Tx   = 3;
  grr_data->ms_cap[6].Sum  = 4;
  grr_data->ms_cap[6].Ttb  = 1;
  grr_data->ms_cap[6].Tra  = 3;

  grr_data->ms_cap[7].Rx   = 4;
  grr_data->ms_cap[7].Tx   = 1;
  grr_data->ms_cap[7].Sum  = 5;
  grr_data->ms_cap[7].Ttb  = 1;
  grr_data->ms_cap[7].Tra  = 2;

  grr_data->ms_cap[8].Rx   = 3;
  grr_data->ms_cap[8].Tx   = 2;
  grr_data->ms_cap[8].Sum  = 5;
  grr_data->ms_cap[8].Ttb  = 1;
  grr_data->ms_cap[8].Tra  = 2;

  grr_data->ms_cap[9].Rx   = 4;
  grr_data->ms_cap[9].Tx   = 2;
  grr_data->ms_cap[9].Sum  = 5;
  grr_data->ms_cap[9].Ttb  = 1;
  grr_data->ms_cap[9].Tra  = 2;

  grr_data->ms_cap[10].Rx   = 4;
  grr_data->ms_cap[10].Tx   = 3;
  grr_data->ms_cap[10].Sum  = 5;
  grr_data->ms_cap[10].Ttb  = 1;
  grr_data->ms_cap[10].Tra  = 2;

  grr_data->ms_cap[11].Rx   = 4;
  grr_data->ms_cap[11].Tx   = 4;
  grr_data->ms_cap[11].Sum  = 5;
  grr_data->ms_cap[11].Ttb  = 1;
  grr_data->ms_cap[11].Tra  = 2;


  memset(&grr_data->ta_params, 0xFF, sizeof(T_TA_PARAMS));
  grr_data->ta_params.ta_valid = FALSE;
  grr_data->cc_running         = FALSE;

  grr_data->uplink_tbf.access_type = CGRLC_AT_NULL; /* NO CELL UPDATE NEED */

  grr_data->test_mode = CGRLC_NO_TEST_MODE;

  grr_data->l1_del_tbf_start_fn = GRR_INVALID_FN; 

  grr_set_pbcch( FALSE );

  grr_data->cell_res_status = TRUE;

#ifdef REL99

#ifdef TI_PS_FF_QUAD_BAND_SUPPORT
  psc_db->band_indicator = NOT_PRESENT_8BIT;
#endif

  /* Initialize SGSN release to unknown value at Power ON */
  psc_db->sgsn_rel = PS_SGSN_UNKNOWN;

  cl_nwrl_set_sgsn_release(psc_db->sgsn_rel);

  /* Initialize the BSS release to R97 */
  psc_db->network_rel = BSS_NW_REL_97;
#endif

} /* grr_init() */

/*
+------------------------------------------------------------------------------
| Function    : grr_is_pbcch_present
+------------------------------------------------------------------------------
| Description : grr_is_pbcch_present returns whether the PBCCH is present or not
|
| Parameters  : no parameters
|
+------------------------------------------------------------------------------
*/

GLOBAL BOOL grr_is_pbcch_present (void)
{
  
  return (psc_db->pbcch.bcch.pbcch_present);
}/*grr_is_pbcch_present*/





/*
+------------------------------------------------------------------------------
| Function    : grr_random_value
+------------------------------------------------------------------------------
| Description : This function generates a random value between 0 and max_i-1           
|               The function is current implemented by a random sequence.
|               It may replace by a other generation method in the future,
|               i.e. last bits of framenumber, systemtime or powervalue etc..
|
| Parameters  : max_i -  return_value is between 0 and (max_i-1)
|                        maximum value 256
|
+------------------------------------------------------------------------------
*/
GLOBAL ULONG grr_random_value (UBYTE index, ULONG max_i)
{
  /* The indexing is done to avoid unpredictable distortion of uniform */
  /* probability distribution of random values delivered to a specific */
  /* caller */
  static ULONG next[3] = {1,1,1};
  ULONG return_value;
#ifdef _TARGET_  
  static BOOL initflag[3] = {FALSE,FALSE,FALSE};
  T_TIME time_val;
#endif

  TRACE_FUNCTION( "grr_random_value" );
  
  if(index > 2)
  {
    TRACE_ERROR("Invalid inex in random value generation function");
    return(0);
  }

#ifdef _SIMULATION_
  if (grr_data->tc.res_random)
  {
    UBYTE i;
    TRACE_EVENT( "grr_data->tc.res_random is set" );
    for (i=0; i<3; i++)
    {
      next[i] = 1;
    }
    grr_data->tc.res_random = 0;
  }
#endif


#ifdef _TARGET_
  /* on target each random value sequence is initialized on its first usage */
  /* with system time to get different sequences for each mobile and each   */
  /* caller */
  if(initflag[index] EQ FALSE)
  {
    vsi_t_time (VSI_CALLER &time_val);
    next[index] = (ULONG)time_val;
    initflag[index] = TRUE;
  }
#endif

  next[index] = next[index] * 1103515245 + 12345;
  return_value = (next[index]/65536) % (max_i);

#ifndef _TARGET_
  TRACE_EVENT_P3("random index: %d max: %d value: %d",index, max_i, return_value);
#endif /* _TARGET_ */

  return(return_value);
}


/*
+------------------------------------------------------------------------------
| Function    : grr_decode_tbf_start_abs
|------------------------------------------------------------------------------
| Description : The function grr_decode_tbf_start_abs() translates the TBF- 
|               Starting-Time-Absolute into full frame number. Therefore the 
|               received frame number is needed in grr_data->dl_fn !! 
|
| Parameters  : ptr2tbf_abs - pointer to the tbf_abs structure to be decoded
|
+------------------------------------------------------------------------------
*/
GLOBAL ULONG grr_decode_tbf_start_abs(T_abs *ptr2tbf_abs)
{ 
  ULONG var1,var2,var3,result;
  UBYTE var4;
  TRACE_FUNCTION( "grr_decode_tbf_start_abs" );

  var3 = (ULONG)ptr2tbf_abs->t3;
  var2 = (ULONG)ptr2tbf_abs->t2;
  var1 = (ULONG)ptr2tbf_abs->t1;
        
  result = (51 * ((26+var3 - var2)%26) + var3 + 1326 * var1);
  /* see GSM 04.08 v 6.4.2 section 10.5.2.38 */
  /* T_abs delivers only the fn modulo 42432 so it has to be adjusted to the */
  /* current fn.*/
  result += (grr_data->dl_fn-(grr_data->dl_fn%42432));
  if(result < grr_data->dl_fn)
  {
    if((result + 10808) < grr_data->dl_fn)
    {
      result += 42432;
    }
  }
  else if(result > (grr_data->dl_fn + 31623))
  {
    if(result < 42432)
      result += 2715648;
    result -= 42432;
  }
  /* fn has to be aligned to first tdma frame in a block */
  var4 = (UBYTE)(result%13);
  if(var4 > 8)
    result += (13 - var4);
  else if(var4 > 4)
    result += (8 - var4);
  else if(var4 > 0)
    result += (4 - var4);
  if(FN_MAX <= result)
    result %= FN_MAX;
  return result;
}  /* grr_decode_tbf_start_abs */



/*
+------------------------------------------------------------------------------
| Function    : grr_decode_tbf_start_rel
|------------------------------------------------------------------------------
| Description : The function grr_decode_tbf_start_rel() translates the TBF- 
|               Starting-Time-Relative into full frame number. Therefore the 
|               received frame number is needed in start_fn !! 
|
| Parameters  : rel_pos - number in blocks added to current framenuber
|
+------------------------------------------------------------------------------
*/
GLOBAL ULONG grr_decode_tbf_start_rel(ULONG start_fn, USHORT rel_pos)
{ 
  ULONG result;

  TRACE_FUNCTION( "grr_decode_tbf_start_rel" );
  
  result = 4+4*rel_pos + start_fn + rel_pos/3;
  
  if ((12 EQ (result%13))  OR
       (7 EQ (result%13))  OR
       (3 EQ (result%13)))
  {
    result += 1;  
  }
  if(FN_MAX <= result)
  {
    result %= FN_MAX;
  }

  return result;
}  /* grr_decode_tbf_start_rel */



/*
+------------------------------------------------------------------------------
| Function    : grr_calc_nr_of_set_bits
+------------------------------------------------------------------------------
| Description : this function calculates the number of set bits 
|               (for example timeslots) form value
|
| Parameters  : value - input value
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE grr_calc_nr_of_set_bits (  UBYTE value  )
{ 
  UBYTE tx_slots=0;
  UBYTE mask=128;
  UBYTE i;

  TRACE_FUNCTION( "grr_calc_nr_of_set_bits" );
        
  for(i=0; i<=7; i++)
  {
    if(value & mask)
      tx_slots++;
    mask>>=1;
  }
  /*
  if(tx_slots > 1)
  {
    TRACE_EVENT_P1("MULTISLOT: %d timeslots assigned ",tx_slots);
  }
  */
  return tx_slots;
} /* grr_calc_nr_of_set_bits() */

/*
+------------------------------------------------------------------------------
| Function    : grr_check_dist
+------------------------------------------------------------------------------
| Description : The function grr_check_dist() checks if high_i is bigger/equal 
|               than low_i(modulo calculation). 
|               The return value is true, if high_i is equal to low_i or 
|               bigger than low_i.
| Parameters  : high_i - expected high value
|               low_i  - expected low value
|               dist_i - max. allowed distance between high_i and low_i
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_check_dist ( ULONG high_i, ULONG low_i, ULONG dist_i)
{
  BOOL  result = FALSE;
  ULONG  real_dist;

  TRACE_FUNCTION( "grr_check_dist" );
    
  if (high_i >= low_i)
    real_dist = high_i - low_i;
  else
    real_dist = high_i + (FN_MAX-low_i);

  if (real_dist <= dist_i )
  {
     result = TRUE;
  }
  return result;
} /* grr_check_dist() */

/*
+------------------------------------------------------------------------------
| Function    : handle_ms_cap
+------------------------------------------------------------------------------
| Description : The function handle_ms_cap() checks if the ms capability is 
|               fulfilled or not 
| Parameters  : -
+------------------------------------------------------------------------------
*/
GLOBAL BOOL handle_ms_cap (UBYTE msg_type)
{
  UBYTE ms_class_index, dl_mask, ul_mask;
  BOOL check_ul;
  BOOL check_dl;

  TRACE_FUNCTION( "handle_ms_cap" );

  /*
   * use current slot mask if now new is assigned
   *
   */
  if(grr_data->downlink_tbf.ts_usage)
  {
    dl_mask = grr_data->downlink_tbf.ts_usage;
  }
  else
  {
    dl_mask = grr_data->downlink_tbf.ts_mask;
  }

    
  if(grr_data->uplink_tbf.ts_usage)
  {
    ul_mask = grr_data->uplink_tbf.ts_usage;
  }
  else
  {
    ul_mask = grr_data->uplink_tbf.ts_mask;
  }

  ms_class_index = grr_get_gprs_ms_class( ) - 1;

  switch(msg_type)
  {
    case UL_ASSIGNMENT:
      /* 
       * new uplink assignment received
       */
      check_ul = TRUE;
      if(grr_data->tbf_type EQ CGRLC_TBF_MODE_DL   OR
         grr_data->tbf_type EQ CGRLC_TBF_MODE_DL_UL  )
      {
        check_dl = TRUE;
      }
      else
      {
        check_dl = FALSE;
      }
      break;
    case DL_ASSIGNMENT:
      /* 
       * new uplink assignment received
       */
      check_dl = TRUE;
      if(grr_data->tbf_type EQ CGRLC_TBF_MODE_UL  OR
         grr_data->tbf_type EQ CGRLC_TBF_MODE_DL_UL   )
      {
        check_ul = TRUE;
      }
      else
      {
        check_ul = FALSE;
      }
      break;
    case UL_DL_ASSIGNMENT:
      /* 
       * new uplink and downlink assignment received
       */
      check_ul = TRUE;
      check_dl = TRUE;
      break;
    default:
      {
        TRACE_ERROR( "unexpected msg_type" );
        return FALSE;
      }
  }
  if (check_ul  AND
      ((grr_data->uplink_tbf.nts > grr_data->ms_cap[ms_class_index].Tx ) OR (!grr_data->uplink_tbf.nts)))
  {
    TRACE_ERROR( "uplink nts is bigger than allowed ms capability" );

    TRACE_EVENT_P8("MS CLASS ERROR 1: ul_mask=%x ul_nts=%d dl_mask=%x dl_nts=%d ms_class=%d Tx=%d Rx=%d sum=%d"
                                                                ,ul_mask
                                                                ,grr_data->uplink_tbf.nts
                                                                ,dl_mask
                                                                ,grr_data->downlink_tbf.nts
                                                                ,ms_class_index+1
                                                                ,grr_data->ms_cap[ms_class_index].Tx
                                                                ,grr_data->ms_cap[ms_class_index].Rx
                                                                ,grr_data->ms_cap[ms_class_index].Sum);
    return FALSE;
  }
  if (check_dl AND
      ((grr_data->downlink_tbf.nts > grr_data->ms_cap[ms_class_index].Rx) OR (!grr_data->downlink_tbf.nts)))
  {
    TRACE_ERROR( "downlink nts is bigger than allowed ms capability" );

    TRACE_EVENT_P8("MS CLASS ERROR 2:ul_mask=%x ul_nts=%d dl_mask=%x dl_nts=%d ms_class=%d Tx=%d Rx=%d sum=%d"
                                                                ,ul_mask
                                                                ,grr_data->uplink_tbf.nts
                                                                ,dl_mask
                                                                ,grr_data->downlink_tbf.nts
                                                                ,ms_class_index+1
                                                                ,grr_data->ms_cap[ms_class_index].Tx
                                                                ,grr_data->ms_cap[ms_class_index].Rx
                                                                ,grr_data->ms_cap[ms_class_index].Sum);
    return FALSE;
  }

  if (check_dl AND check_ul )
  {
    UBYTE help;

    if (((grr_data->uplink_tbf.nts + grr_data->downlink_tbf.nts)  > grr_data->ms_cap[ms_class_index].Sum) OR
         (!grr_data->uplink_tbf.nts) OR
         (!grr_data->downlink_tbf.nts))
    {
      TRACE_ERROR( "Sum bigger than allowed ms capability" );

      TRACE_EVENT_P8("MS CLASS ERROR 3:ul_mask=%x ul_nts=%d dl_mask=%x dl_nts=%d ms_class=%d Tx=%d Rx=%d sum=%d"
                                                                  ,ul_mask
                                                                  ,grr_data->uplink_tbf.nts
                                                                  ,dl_mask
                                                                  ,grr_data->downlink_tbf.nts
                                                                  ,ms_class_index+1
                                                                  ,grr_data->ms_cap[ms_class_index].Tx
                                                                  ,grr_data->ms_cap[ms_class_index].Rx
                                                                  ,grr_data->ms_cap[ms_class_index].Sum);
      return FALSE;
    }

    help = grr_calculate_Ttb(ul_mask,dl_mask);
    if (help < grr_data->ms_cap[ms_class_index].Ttb)
    {
      TRACE_ERROR("Ttb calculated not equal to the one of the multislot class ");
      TRACE_EVENT_P5("ul_mask=%x dl_mask=%x  ms_class=%d calc_ttb=%d ms_class_TTB=%d "
                                                                ,ul_mask
                                                                ,dl_mask
                                                                ,ms_class_index+1
                                                                ,help
                                                                ,grr_data->ms_cap[ms_class_index].Ttb);
      return FALSE;
    }
    help = grr_calculate_Tra(ul_mask,dl_mask);
    if ( help < grr_data->ms_cap[ms_class_index].Tra )
    {
      TRACE_ERROR("Tra calculated not equal to the one of the multislot class ");
      TRACE_EVENT_P5("ul_mask=%x dl_mask=%x  ms_class=%d calc_tra=%d ms_class_tra=%d "
                                                                ,ul_mask
                                                                ,dl_mask
                                                                ,ms_class_index+1
                                                                ,help
                                                                ,grr_data->ms_cap[ms_class_index].Tra);
      return FALSE;
    }
  }
  return TRUE;
} /* handle_ms_cap() */

/*
+------------------------------------------------------------------------------
| Function    : grr_copy_em1_struct
+------------------------------------------------------------------------------
| Description : The function grr_copy_em1_struct copies the em1 struct 
|               parameters.
|
| Parameters  : db_em1      - em1 structure in the GRR database
|               ext_em1     - em1 structure in the EXT measurement parameter
|               cpy_prm_set - indicates whether the new extended measurement 
|                             parameter overwrite the present ones due to a 
|                             messsage with higher sequence number
|
+------------------------------------------------------------------------------
*/
LOCAL void grr_copy_em1_struct( T_XMEAS_EM1 *db_em1,
                                T_em1       *ext_em1,
                                BOOL         cpy_prm_set,
                                UBYTE       *start_ext_lst_idx,
                                UBYTE       *stop_ext_lst_idx )
{
  UBYTE  i, j, m, n;

  TRACE_FUNCTION("grr_copy_em1_struct");

  if( cpy_prm_set )
  {
    /*
     * Copy EM1 struct parameters
     */
    db_em1->param.reporting_type = REP_TYPE_1;
    if(ext_em1->flag)
    {
      /*
       * check ext_reporting_type
       */
      switch(ext_em1->xrep_type)
      {
        case XREP_TYPE1:    /* 00 */
          db_em1->param.reporting_type = REP_TYPE_1;
          break;
        case XREP_TYPE2:    /* 01 */
          db_em1->param.reporting_type = REP_TYPE_2;
          db_em1->param.ncc_permitted  = ext_em1->ncc_permitted;
          break;
        case XREP_TYPE3:    /* 10 */
          db_em1->param.reporting_type = REP_TYPE_3;
          if(ext_em1->v_int_freq)
          {
            db_em1->param.int_frequency = ext_em1->int_freq;
          }
          else
          {
            db_em1->param.int_frequency = NOT_SET;
          }
          break;
        case XREP_RESERVED: /* 11 */
          db_em1->param.reporting_type = REP_TYPE_RES;
          break;
      }
    }

    /*
     * Check ext reporting period
     */
    db_em1->param.reporting_period = EXT_REP_PER_DEFAULT;
    if(ext_em1->v_xrep_per)
    {
      db_em1->param.reporting_period = ext_em1->xrep_per;
    }
  }

  /*
   * Copy extended frequency list Parameters
   */
  if(db_em1->list.number < RRGRR_MAX_ARFCN_EXT_MEAS)
  {
    /*
     * copy first EXT Frequency list structure
     */
    j                    = db_em1->list.number;
    *start_ext_lst_idx   = db_em1->list.number;
    db_em1->list.freq[j] = ext_em1->xfreq_list.start_freq;
    j++;

    /*
     * check remaining frequencies
     */
    for( i = 0;
         i < ext_em1->xfreq_list.nr_freq AND j < RRGRR_MAX_ARFCN_EXT_MEAS;
         i++ )
    {
      db_em1->list.freq[j] = 
        ( db_em1->list.freq[j-1] + ext_em1->xfreq_list.freq_diff_struct[i].freq_diff ) % 1024;
      j++;
    }

    /*
     * check whether EXT Frequency list structure is repeated
     */
    if(ext_em1->v_xfreq_list2)
    {
      for( m = 0; 
           m < ext_em1->c_xfreq_list2 AND j < RRGRR_MAX_ARFCN_EXT_MEAS;
           m++ )
      {
        db_em1->list.freq[j] = ext_em1->xfreq_list2[m].start_freq;
        j++;

        for( n = 0;
             n < ext_em1->xfreq_list2[m].nr_freq AND j < RRGRR_MAX_ARFCN_EXT_MEAS; 
             n++ )
        {
          db_em1->list.freq[j] =
            ( db_em1->list.freq[j-1] + ext_em1->xfreq_list2[m].freq_diff_struct[n].freq_diff ) % 1024;
          j++;
        }
      }
    }
    db_em1->list.number = j;
    *stop_ext_lst_idx   = db_em1->list.number - 1;
  }
  else
  {
    TRACE_ERROR("grr_copy_em1_struct EXT frequency list full");
  }
}/* grr_copy_em1_struct*/

/*
+------------------------------------------------------------------------------
| Function    : grr_prcs_xmeas_struct
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : db_xmeas    - extended measurement parameter in the GRR database
|               air_xmeas   - extended measurement parameter of the air interface
|                             message
|               cpy_prm_set - indicates whether the new extended measurement 
|                             parameter overwrite the present ones due to a 
|                             messsage with higher sequence number
|               new_idx     - sequence number of the message
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_prcs_xmeas_struct ( T_XMEAS     *db_xmeas, 
                                    T_xmeas_par *air_xmeas,
                                    BOOL         cpy_prm_set,
                                    UBYTE        new_inst_idx,
                                    UBYTE       *start_ext_lst_idx,
                                    UBYTE       *stop_ext_lst_idx )
{ 
  TRACE_FUNCTION( "grr_prcs_xmeas_struct" );
  
  /*
   * check ext meas order parameters:
   */
  switch(air_xmeas->xmeas_order)
  {
    case XMEAS_EM1:      /* 01 */
      db_xmeas->em_order_type = EM_EM1;
  
      if( cpy_prm_set )
      {
        db_xmeas->idx = new_inst_idx;
      }

      grr_copy_em1_struct( &db_xmeas->em1, &air_xmeas->em1, cpy_prm_set, 
                           start_ext_lst_idx, stop_ext_lst_idx );
      break;
    case XMEAS_RESET:    /* 11 */
      db_xmeas->em_order_type = EM_RESET;
      break;
    case XMEAS_EM0:      /* 00 */
    case XMEAS_RESERVED: /* 10 it is reseved but shall be interpreted as EM0 by the receiver */
      db_xmeas->em_order_type = EM_EM0;
      break;
  }
}/* grr_prcs_xmeas_struct */

/*
+------------------------------------------------------------------------------
| Function    : grr_init_xmeas_struct
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : xmeas  - pointer to extended measurement parameter
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_init_xmeas_struct( T_XMEAS *xmeas )
{ 
  TRACE_FUNCTION( "grr_init_xmeas_struct" );
  
  xmeas->idx                     = NOT_SET;
  xmeas->em_order_type           = EM_EMPTY;
  xmeas->em1.list.number         = 0;
  xmeas->em1.param.int_frequency = NOT_SET;
}/* grr_init_xmeas_struct */

/*
+------------------------------------------------------------------------------
| Function    : grr_prcs_nc_freq_list
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : db_list    - NC frequency list in the GRR database
|               v_air_list - valid flag for NC frequency list of the air
|                            interface message
|               air_list   - NC frequency list of the air interface message
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_prcs_nc_freq_list ( T_NC_LIST       *nc_list,
                                    T_NC_RFREQ_LIST *rfreq_list,
                                    BOOL             v_air_list,
                                    T_nc_freq_list  *air_list,
                                    T_INFO_TYPE      type,
                                    UBYTE            instance )
{ 
  UBYTE i, j; /* used for counting */

  TRACE_FUNCTION( "grr_prcs_nc_freq_list" );

  if( v_air_list EQ TRUE )
  {
    if( air_list->v_list_rf EQ TRUE )
    {
      /* process the list of removed frequencies */
      for( i = 0;
           i                  < air_list->list_rf.c_rfreq_index AND
           rfreq_list->number < MAX_NR_OF_NCELL; 
           i++ )
      {
        rfreq_list->idx[rfreq_list->number] = air_list->list_rf.rfreq_index[i];
        
        rfreq_list->number++;
      }      

      if( i < air_list->list_rf.c_rfreq_index )
      {
        TRACE_ERROR( "grr_prcs_nc_freq_list removed frequency list full" );
      }
    }

    if( air_list->v_list_af EQ TRUE )
    {
      UBYTE  number    = 0;
      USHORT last_freq;

      /* process the list of added frequencies */
      for( i = 0; i < air_list->c_list_af; i++ )
      {
        last_freq = 0;

        if( grr_store_cs_param
              ( nc_list,
                air_list->list_af[i].v_cs_par,
                &air_list->list_af[i].cs_par,
                type,
                instance,
                &number,
                &last_freq,
                air_list->list_af[i].start_freq,
                air_list->list_af[i].bsic ) EQ FALSE )
        {
          TRACE_EVENT( "grr_prcs_nc_freq_list: NC_MS list full" );

          return( v_air_list );
        }
        
        for( j = 0; j < air_list->list_af[i].nr_freq; j++ )
        {
          if( grr_store_cs_param
                ( nc_list,
                  air_list->list_af[i].afreq_s[j].v_cs_par,
                  &air_list->list_af[i].afreq_s[j].cs_par,
                  type,
                  instance,
                  &number,
                  &last_freq,
                  air_list->list_af[i].afreq_s[j].freq_diff_struct.freq_diff,
                  air_list->list_af[i].afreq_s[j].bsic ) EQ FALSE )
          {
            TRACE_EVENT( "grr_prcs_nc_freq_list: NC_MS list full" );

            return( v_air_list );
          }
        }
      }      
    }
  }

  return( v_air_list );
}/* grr_prcs_nc_freq_list */

/*
+------------------------------------------------------------------------------
| Function    : grr_prcs_nc_freq_final
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_prcs_nc_freq_final ( T_NC_LIST       *dest_list,
                                     T_NC_RFREQ_LIST *dest_rfreq,
                                     BOOL            *v_src_list_rfreq,
                                     T_NC_LIST       *src_list,
                                     T_NC_RFREQ_LIST *src_rfreq )
{ 
  BOOL  is_pbcch_present = grr_is_pbcch_present( );
  BOOL  is_identical;
  UBYTE i;

  TRACE_FUNCTION( "grr_prcs_nc_freq_final" );

  if( *v_src_list_rfreq EQ TRUE )
  {
    *v_src_list_rfreq = FALSE;

    /*
     * The change mark values should be increased in case 
     * at least one parameter has changed
     */
    if( dest_list->number  EQ src_list->number  AND
        dest_rfreq->number EQ src_rfreq->number     )
    {
      is_identical = TRUE;
    
      for( i = 0; i < dest_list->number AND is_identical; i++ )
      {
        if( is_pbcch_present )
        {
          is_identical =
            ( dest_list->info[i].arfcn EQ src_list->info[i].arfcn AND
              dest_list->info[i].bsic  EQ src_list->info[i].bsic      );
        }
        else
        {
          is_identical =
            ( dest_list->info[i].arfcn EQ src_list->info[i].arfcn );
        }
      }

      for( i = 0; i < dest_rfreq->number AND is_identical; i++ )
      {
        is_identical = ( dest_rfreq->idx[i] EQ src_rfreq->idx[i] );
      }
    }
    else
    {
      is_identical = FALSE;
    }

    if( !is_identical )
    {
      dest_list->chng_mrk.curr++;
    }

    /* copy remaining parameters except change mark */
    dest_list->number = src_list->number;

    memcpy( dest_list->info, src_list->info,
            sizeof( T_ncell_info ) * src_list->number );

    memcpy( dest_rfreq, src_rfreq, sizeof( T_NC_RFREQ_LIST ) );
  }
  else
  {
    if( dest_list->number NEQ 0 OR dest_rfreq->number NEQ 0 )
    {
      dest_list->number  = 0;
      dest_rfreq->number = 0;

      dest_list->chng_mrk.curr++;
    }
  }
}/* grr_prcs_nc_freq_final */

/*
+------------------------------------------------------------------------------
| Function    : grr_prcs_nc_param_struct
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : db_nc        - NC measurement parameter in the GRR database
|               air_nc       - NC measurement parameter of the air interface
|                              message
|               new_idx      - sequence number of the message
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_prcs_nc_param_struct ( T_NC_PARAM    *db_nc,
                                       T_nc_meas_par *ext_nc,
                                       UBYTE          new_idx )
{ 
  T_NC_ORDER ctrl_order;  /* NETWORK_CONTROL_ORDER */
  UBYTE      non_drx_per; /* NC_NON_DRX_PERIOD     */
  UBYTE      rep_per_i;   /* NC_REPORTING_PERIOD_I */
  UBYTE      rep_per_t;   /* NC_REPORTING_PERIOD_T */

  TRACE_FUNCTION( "grr_prcs_nc_param_struct" );

  /*
   * Store the network control order value in a temporary buffer
   */
  switch( ext_nc->ctrl_order )
  {
    case NCMEAS_NC0   : ctrl_order = NC_NC0;   break;
    case NCMEAS_NC1   : ctrl_order = NC_NC1;   break;
    case NCMEAS_NC2   : ctrl_order = NC_NC2;   break;
    case NCMEAS_RESET : 
    default           : ctrl_order = NC_RESET; break;
  }
 
  /*
   * Store the remaining parameters in temporary buffers
   */
  if(ext_nc->v_nc_meas_per)
  {
    non_drx_per = ext_nc->nc_meas_per.non_drx_per;
    rep_per_i   = ext_nc->nc_meas_per.rep_per_i;
    rep_per_t   = ext_nc->nc_meas_per.rep_per_t;
  }
  else
  {
    /*
     * Use default values, see 04.60 PSI5 Information Element Details
     */
    non_drx_per = NC_NON_DRX_PER_DEFAULT;
    rep_per_i   = NC_REP_PER_I_DEFAULT;
    rep_per_t   = NC_REP_PER_T_DEFAULT;
  }

  /*
   * The change mark values should be increased in case 
   * at least one parameter has changed
   */
  if( db_nc->ctrl_order  NEQ ctrl_order  OR
      db_nc->non_drx_per NEQ non_drx_per OR
      db_nc->rep_per_i   NEQ rep_per_i   OR
      db_nc->rep_per_t   NEQ rep_per_t      )
  {
    db_nc->chng_mrk.curr++;
  }

  db_nc->idx         = new_idx;
  db_nc->ctrl_order  = ctrl_order;
  db_nc->non_drx_per = non_drx_per;
  db_nc->rep_per_i   = rep_per_i;
  db_nc->rep_per_t   = rep_per_t;
}/* grr_prcs_nc_param_struct */

/*
+------------------------------------------------------------------------------
| Function    : grr_prcs_nc_param_final
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_prcs_nc_param_final ( T_NC_PARAM *dest_nc, 
                                      BOOL       *v_src_nc,
                                      T_NC_PARAM *src_nc )
{ 
  TRACE_FUNCTION( "grr_prcs_nc_param_final" );

  if( *v_src_nc EQ TRUE )
  {
    *v_src_nc = FALSE;

    /*
     * The change mark values should be increased in case 
     * at least one parameter has changed
     */
    if( dest_nc->ctrl_order  NEQ src_nc->ctrl_order  OR
        dest_nc->non_drx_per NEQ src_nc->non_drx_per OR
        dest_nc->rep_per_i   NEQ src_nc->rep_per_i   OR
        dest_nc->rep_per_t   NEQ src_nc->rep_per_t      )
    {
      dest_nc->chng_mrk.curr++;
    }

    /* Copy remaining parameters except change mark */
    dest_nc->idx         = src_nc->idx;
    dest_nc->ctrl_order  = src_nc->ctrl_order;
    dest_nc->non_drx_per = src_nc->non_drx_per;
    dest_nc->rep_per_i   = src_nc->rep_per_i;
    dest_nc->rep_per_t   = src_nc->rep_per_t;
  }
}/* grr_prcs_nc_param_final */

/*
+------------------------------------------------------------------------------
| Function    : grr_init_ncmeas_struct
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : ncmeas - pointer to NC measurement parameter
|               is_cw  - indicates whether the parameter pointer is related
|                        to cell wide or MS specific information
|
+------------------------------------------------------------------------------
*/
LOCAL void grr_init_ncmeas_struct( T_NCMEAS *ncmeas, BOOL is_cw )
{ 
  TRACE_FUNCTION( "grr_init_ncmeas_struct" );
  
  grr_init_nc_param( &ncmeas->param, is_cw );
  grr_init_nc_list( &ncmeas->list );
}/* grr_init_ncmeas_struct */

/*
+------------------------------------------------------------------------------
| Function    : grr_init_ncmeas_extd_struct
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : extd  - pointer to NC measurement extended parameter
|               is_cw - indicates whether the parameter pointer is related
|                       to cell wide or MS specific information
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_init_ncmeas_extd_struct ( T_NCMEAS_EXTENDED *extd, BOOL is_cw )
{ 
  TRACE_FUNCTION( "grr_init_ncmeas_extd_struct" );
  
  grr_init_ncmeas_struct( &extd->ncmeas, is_cw );
  grr_init_rfreq_list( &extd->rfreq );

#if defined (REL99) AND defined (TI_PS_FF_EMR)
  /* 
   * If PMO has not been received, PMO_USED shall be set to zero. 
   * Refer 3GPP TS 04.60 V8.17.0 (2002-12) Table 11.2.9d.2 
   */
  extd->pmo_ind = 0;
  extd->psi3_cm = NOT_SET;
  extd->ba_ind = NOT_SET;
#endif

}/* grr_init_ncmeas_extd_struct */

/*
+------------------------------------------------------------------------------
| Function    : grr_init_nc_list
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : list  - pointer to NC measurement list
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_init_nc_list( T_NC_LIST *list )
{ 
  TRACE_FUNCTION( "grr_init_nc_list" );
  
  list->number = 0;
}/* grr_init_nc_list */

/*
+------------------------------------------------------------------------------
| Function    : grr_init_nc_param
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : param - pointer to NC measurement parameter
|               is_cw - indicates whether the parameter pointer is related
|                       to cell wide or MS specific information
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_init_nc_param( T_NC_PARAM *param, BOOL is_cw )
{ 
  TRACE_FUNCTION( "grr_init_nc_param" );
  
  param->ctrl_order = ( is_cw EQ TRUE ? NC_NC0 : NC_EMPTY );
  param->idx        = NOT_SET;
}/* grr_init_nc_param */

/*
+------------------------------------------------------------------------------
| Function    : grr_init_rfreq_list
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : list  - pointer to NC measurement removed frequency list
|
+------------------------------------------------------------------------------
*/
LOCAL void grr_init_rfreq_list ( T_NC_RFREQ_LIST *list )
{ 
  TRACE_FUNCTION( "grr_init_rfreq_list" );
  
  list->number = 0;
}/* grr_init_rfreq_list */

/*
+------------------------------------------------------------------------------
| Function    : grr_sort_ext_lst_freq
+------------------------------------------------------------------------------
| Description : 
| Parameters  : 
+------------------------------------------------------------------------------
*/
GLOBAL void grr_sort_ext_lst_freq ( T_EXT_FREQ_LIST  *list,
                                    UBYTE             max_number,
                                    T_EXT_START_STOP *start_stop )
{
  UBYTE           i, j;     /* used for counting                    */
  T_EXT_FREQ_LIST tmp_list; /* temporary copy of EXT frequency list */

  tmp_list.number = 0;


  TRACE_FUNCTION( "grr_sort_ext_lst_freq" );

  for( i = 0; i < max_number; i++ )
  {
    if( start_stop[i].start NEQ RRGRR_INVALID_IDX AND 
        start_stop[i].stop  NEQ RRGRR_INVALID_IDX     )
    {
      for( j  = start_stop[i].start;
           j <= start_stop[i].stop;
           j++ )
      {
        tmp_list.freq[tmp_list.number] = list->freq[j];
        tmp_list.number++;
      }
    }
  }

  for( j = 0; j < tmp_list.number; j++ )
  {
    list->freq[j] = tmp_list.freq[j];
  }

  grr_mrk_ext_lst_freq( list );
} /* grr_sort_ext_lst_freq() */

/*
+------------------------------------------------------------------------------
| Function    : grr_mrk_ext_lst_freq
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
LOCAL void grr_mrk_ext_lst_freq ( T_EXT_FREQ_LIST *list )
{ 
  UBYTE i, j;

  TRACE_FUNCTION( "grr_mrk_ext_lst_freq" );

  if( list->number NEQ 0 )
  {
    for( i = 0; i < list->number - 1; i++ )
    {
      for( j = i + 1; 
           j < list->number AND IS_NOT_FLAGGED( list->freq[i],
                                                EM_VLDTY_ARFCN_MASK, 
                                                EM_NON_VLD_ARFCN );
           j++ )
      {
        if( list->freq[i] EQ list->freq[j] )
        {
          SET_FLAG( list->freq[i], EM_VLDTY_ARFCN_MASK, EM_NON_VLD_ARFCN, USHORT );       
        }
      }
    }
  }
}/* grr_mrk_ext_lst_freq */







/*
+------------------------------------------------------------------------------
| Function    : grr_create_channel_list
+------------------------------------------------------------------------------
| Description : The function grr_create_channel_list()  
|               Use a function from RR entity to extract frequencies from a frequency list structure
|               defined in 04.08
|               This function copies the frequencies into list. This function takes the arranging
|               of ARFCN into account cf. 12.10a GPRS Mobile Allocation in 04.60
| Parameters  : T_rfl*: pointer to the rfl received in PSI2 and UBYTE*list: pointer to 
|               the list similar to T_LIST
+------------------------------------------------------------------------------
*/
GLOBAL void grr_create_channel_list(T_rfl* rfl, UBYTE* list)
{
  T_f_range rfl_contents;
  UBYTE i;

  TRACE_FUNCTION( "grr_create_channel_list" );
  /*
   * Copy RFL contents into the T_LIST
   */
  memset (&rfl_contents, 0, sizeof(T_f_range));
  /* 
   * Length in bits
   */
  rfl_contents.l_f = (rfl->rfl_cont_len+3)*8;
  /*
   * Copy RFL content bits into the structure
   */
  for(i=0; i < rfl->c_rfl_cont; i++)
  {
    rfl_contents.b_f[i] = rfl->rfl_cont[i].flist;
  }
        
  /*
   * Use a function from RR
   * This function copies the frequencies into list. This function takes the arranging
   * of ARFCN into account cf. 12.10a GPRS Mobile Allocation in 04.60
   */
  for_create_channel_list (&rfl_contents, (T_LIST*)list);

}/* grr_create_channel_list */


/*
+------------------------------------------------------------------------------
| Function    : grr_get_si_cell_alloc_list
+------------------------------------------------------------------------------
| Description : 
|      
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
LOCAL void grr_get_si_cell_alloc_list( T_LIST *list )
{
#ifndef _TARGET_

  T_LIST cell_chan_des = {
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,
    0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0x00,0x00 }; 

#endif

  TRACE_FUNCTION( "grr_get_si_cell_alloc_list" );

  /*
   * Use cell allocation in SI1
   */

  /* Cell allocation is stored in rr at                                 */
  /* rr_data->sc_data.cd.cell_chan_desc for now use hazardous hack of   */
  /* access database of RR entity later make a new entity that replaces */
  /* RR and GRR or make a communication between RR and GRR to transfer  */
  /* list.                                                              */
  /* Used selfmade glumps hack function in RR to get cell allocation    */
  /* because getting typedefs from RR to use rr_data pointer is not     */
  /* that easy cause by name equalities in RR and GRR                   */

#ifndef _TARGET_

  srv_merge_list( list, &cell_chan_des );

#else
   
  /* TRACE_EVENT( "Use cell allocation in S1" ); */

  srv_get_cell_alloc_list( list );

#endif

} /* grr_get_si_cell_alloc_list */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_psi_cell_alloc_list
+------------------------------------------------------------------------------
| Description : 
|      
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL grr_get_psi_cell_alloc_list ( T_LIST *list )
{
  BOOL  rfl_not_found = FALSE;
  
  UBYTE n;
  UBYTE i;

  TRACE_FUNCTION( "grr_get_psi_cell_alloc_list" );

  for( n = 0; n < MAX_CELL_ALLOC; n++ )
  {
    if( psc_db->cell_alloc[n].rfl_num EQ NOT_SET )
    {
      if( n EQ 0 )
      {
#ifdef _SIMULATION_

        TRACE_ASSERT( FALSE );

#endif /* #ifdef _SIMULATION_ */

        rfl_not_found = TRUE;
      }
     
      break;
    }

    /* find rfl list with that number */
    i = 0;
   
    /* do not check the RFL received in an assignment message */
    while( i < MAX_RFL )
    {
      if( psc_db->rfl[i].num EQ psc_db->cell_alloc[n].rfl_num )
      {
        /* TRACE_EVENT_P1( "psc_db->rfl[i].num:%d", psc_db->rfl[i].num ); */
        break;
      }

      i++;
    }

    if( MAX_RFL > i )
    {
      srv_merge_list( list,                            /* output, result */ 
                      (T_LIST *)psc_db->rfl[i].list );
    }
    else
    {
#ifdef _SIMULATION_

      TRACE_ASSERT( FALSE );

#endif /* #ifdef _SIMULATION_ */

      rfl_not_found = TRUE;
      break;
    }
  }

  return( rfl_not_found EQ FALSE );

} /* grr_get_psi_cell_alloc_list */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_ms_alloc_list
+------------------------------------------------------------------------------
| Description : 
|      
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
LOCAL BOOL grr_get_ms_alloc_list ( T_LIST             *list,
                                   const T_gprs_ms_alloc_ie *ms_alloc )
{
  BOOL  rfl_not_found = FALSE;
  
  UBYTE n;
  UBYTE i;

  TRACE_FUNCTION( "grr_get_ms_alloc_list" );

  for( n = 0; n < ms_alloc->c_rfl_num_list; n++ )
  {
    if( ms_alloc->rfl_num_list[n].rfl_num EQ NOT_SET )
    {
#ifdef _SIMULATION_

      TRACE_ASSERT( FALSE );

#endif /* #ifdef _SIMULATION_ */

      rfl_not_found = TRUE;
      break;
    }

    /* find rfl list with that number */
    i = 0;
    
    while( i <= MAX_RFL )
    {
      if( psc_db->rfl[i].num EQ ms_alloc->rfl_num_list[n].rfl_num )
      {
        break;
      }

      i++;
    }

    if( MAX_RFL >= i )
    {
      srv_merge_list( list,                            /* output, result */ 
                      (T_LIST *)psc_db->rfl[i].list );
    }
    else
    {
#ifdef _SIMULATION_

      TRACE_ASSERT( FALSE );

#endif /* #ifdef _SIMULATION_ */

      rfl_not_found = TRUE;
      break;
    }
  }

  return( rfl_not_found EQ FALSE );

} /* grr_get_ms_alloc_list */

/*
+------------------------------------------------------------------------------
| Function    : grr_create_freq_list
+------------------------------------------------------------------------------
| Description : The function grr_create_freq_list()  
|      
|               Get the according GPRS Mobile Allocation: Take into account MA_NUMBER
|               Write frequencies into frequency list
|      
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_create_freq_list( UBYTE          ma_num,
                                  UBYTE          maio,
                                  T_p_chan_sel  *chan_sel,
                                  T_p_freq_list *freq_list )
{
  BOOL                pbcch_is_present = grr_is_pbcch_present( );
  UBYTE               n                = 0;
  T_gprs_ms_alloc_ie *gp_ma            = NULL;
  
  T_LIST list1;
  USHORT list2[64];
  
  TRACE_FUNCTION( "grr_create_freq_list" );

  memset(&list1, 0, sizeof(T_LIST));
  memset(list2, NOT_PRESENT_16BIT, sizeof(list2));

  gp_ma = grr_get_gprs_ma (ma_num);
  
  if( gp_ma EQ NULL )
  {
    TRACE_EVENT("No valid GPRS_MA found");
    return FALSE;
  }

  /*
   * Copy hopping sequence number and mobile allocation index offset
   */
  chan_sel->p_rf_ch.arfcn = ( ( USHORT )gp_ma->hsn << 8 ) | ( USHORT )maio;

  /* Now we have the GPRS Mobile Allocation corresponding to the ma_num.
   * Get the referenced set of radio frequency lists for this
   * particular GPRS Mobile Allocation IE.
   * If RFL number list is not present in the IE, then cell allocation
   * would be returned by this function.
   */
  if(!grr_get_ref_list_or_cell_allocation(&list1,gp_ma,ma_num))
  {
     TRACE_ERROR("Could not get ref list");
     return FALSE;
  }

  /*
   * Copy ARFCN values into freq_list
   */
  srv_create_list (&list1, list2, 64, TRUE, 0);

  /*
   * Take MA_BITMAP or ARFCN_INDEX into account
   */
  grr_ma_filter_list( 
                      list2, /* input*/
                      freq_list->p_rf_chan_no.p_radio_freq, /* output*/
                      gp_ma
                     );

  /*
   * Get number of copied frequencies
   */
  if(!grr_validate_and_count_frequencies(freq_list->p_rf_chan_no.p_radio_freq,
                                                  &(freq_list->p_rf_chan_cnt)))
  {
    TRACE_ERROR( "grr_create_freq_list: validation failed/freq count zero" );
    return FALSE;
  }
  
  chan_sel->hopping        = 1;  
  
  /* Frequencies stored in freq_list are in form used by 3GPP(g23) standards.
   * convert them to the form used by L1.
   */
  for( n = 0; n < freq_list->p_rf_chan_cnt; n++ )     
  {
    freq_list->p_rf_chan_no.p_radio_freq[n] = 
                grr_g23_arfcn_to_l1( freq_list->p_rf_chan_no.p_radio_freq[n] );
  }

  return TRUE;

}/* grr_create_freq_list*/


/*
+------------------------------------------------------------------------------
| Function    : grr_ma_filter_list
+------------------------------------------------------------------------------
| Description : The function grr_ma_filter_list()  
|               takes MA_BITMAP or ARFCN_INDEX into account
|
|      
| Parameters  : list1 pointer to the input list
|               list2: pointer to the output list
|               gp_ma: pointer to the GPRS Mobile Allocation
+------------------------------------------------------------------------------
*/
GLOBAL void grr_ma_filter_list( 
                               USHORT* list1, /* input*/
                               USHORT* list2, /* output*/
                               const T_gprs_ms_alloc_ie* gp_ma
                               )
{
  UBYTE m,n,i,j;
  TRACE_FUNCTION("grr_ma_filter_list");

  if(gp_ma->v_ma_struct)
  {
    /*
     * MA_BITMAP is valid. First received bit corresponds to the last of T_LIST
     * and the last value of
     */
    i=0, j=0;
    for(n=gp_ma->ma_struct.c_ma_map; n NEQ 0; n--)
    {
      if(gp_ma->ma_struct.ma_map[n-1])
      {
        /*
         * Corresponding frequency is valid
         */
        list2[j] = list1[i];
        j++;
      }
      i++;
      if(list1[i] EQ NOT_PRESENT_16BIT)
        break;
    }
    list2[j] = NOT_PRESENT_16BIT;
  }
  else
  {
    /*
     * Check whether ARFCN list is valid or not
     */
    if(gp_ma->v_arfcn_index_list)
    {
      BOOL is_index_in_the_list=FALSE;
      /*
       * ARFCN Index list is valid
       */
      i=0, j=0;
      for(n=0; n < 64; n++)
      {
        for(m=0; m < gp_ma->c_arfcn_index_list; m++)
        {
          if(n EQ gp_ma->arfcn_index_list[m].arfcn_index)
          {
            /*
             * ARFCN_INDEX is in the list
             */
            is_index_in_the_list = TRUE;
            break;
          }
        }
        if(!is_index_in_the_list)
        {
          list2[j] = list1[i];
          j++;
        }
        is_index_in_the_list = FALSE;
        i++;
        
        if(list1[i] EQ NOT_PRESENT_16BIT)
          break;
      }
      list2[j] = NOT_PRESENT_16BIT;
    }
    else
    {
      /*
       * All radio frequencies are valid
       */
      /*list2 = list1;*/
      memcpy(list2, list1, 64*sizeof(USHORT));
    }
  }
}/* grr_ma_filter_list*/








/*
+------------------------------------------------------------------------------
| Function    : grr_calc_t_diff
+------------------------------------------------------------------------------
| Description : The function grr_calc_t_diff() calculates the difference 
|               between two time stamps taken into account an overflow of the
|               system ticks counter value.
|
| Parameters  : t_start - starting time
|               t_stop  - stopping time
|
+------------------------------------------------------------------------------
*/
GLOBAL T_TIME grr_calc_t_diff (T_TIME t_start, T_TIME t_stop)
{
  T_TIME t_diff;

  TRACE_FUNCTION("grr_calc_t_diff");
  
  if( t_start <= t_stop )
  {
    t_diff = t_stop - t_start;
  }
  else
  {
    t_diff = t_stop + ( ( ~ ( (T_TIME)0 ) ) - t_start ) + 1;
  }

  return( t_diff );
}/*grr_calc_t_diff()*/

/*
+------------------------------------------------------------------------------
| Function    : grr_prepare_db_for_new_cell
+------------------------------------------------------------------------------
| Description : The function grr_prepare_db_for_new_cell prepares the psi 
|               parameters and sc_db parameters like pbcch and pccch for
|               reading new SI13 and if needed PSI messages
|
| Parameters  : void
+------------------------------------------------------------------------------
*/
GLOBAL void grr_prepare_db_for_new_cell ( void )
{
  TRACE_FUNCTION("grr_prepare_db_for_new_cell");
   
  psi_init();

  /*initial PCCCH organization parameters */
  memset(&psc_db->pccch, 0, sizeof(T_pccch_org_par)); 

  /* Initial paging group*/
  memset(&psc_db->paging_group, 0, sizeof(T_PAGING_GROUP));

  psc_db->cell_info_for_gmm.cell_info.cell_env.rai.rac = GMMRR_RAC_INVALID;

  grr_set_pbcch( FALSE );

}/* grr_prepare_db_for_new_cell*/


/*
+------------------------------------------------------------------------------
| Function    : grr_is_non_drx_mode
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  :
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_is_non_drx_mode ( void )
{
  TRACE_FUNCTION( "grr_is_non_drx_mode" );

  return( grr_data->ms.split_pg_cycle   EQ  GMMRR_NO_DRX       OR
          ( grr_data->ms.split_pg_cycle NEQ GMMRR_NO_DRX AND 
            grr_is_non_drx_period( )    EQ  TRUE             )    );

}/* grr_is_non_drx_mode */

/*
+------------------------------------------------------------------------------
| Function    : grr_is_non_drx_period
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : Input: void
|               Return: Sends TRUE if one of the three NON DRX period is valid,
|                       otherwise FALSE;
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_is_non_drx_period ( void )
{
  TRACE_FUNCTION( "grr_is_non_drx_period" );

  return( psc_db->gprs_attach_is_running     OR
          psc_db->non_drx_timer_running      OR
          psc_db->nc2_non_drx_period_running    );

}/* grr_is_non_drx_period */

/*
+------------------------------------------------------------------------------
| Function    : grr_handle_non_drx_period
+------------------------------------------------------------------------------
| Description : Handles the timer of non DRX mode
|
| Parameters  : non_drx_type          - type of non DRX mode
|               non_drx_timer_running - indicates whether non DRX period 
|                                       is active or not
+------------------------------------------------------------------------------
*/
GLOBAL void grr_handle_non_drx_period ( T_NON_DRX_TYPE non_drx_type,
                                        BOOL           non_drx_timer_running )
{ 
  TRACE_FUNCTION( "grr_handle_non_drx_period" );
  
  switch( non_drx_type )
  {
    case TRANSFER_NDRX:
      psc_db->non_drx_timer_running      = non_drx_timer_running;
      break;

    case GMM_NDRX:
      psc_db->gprs_attach_is_running     = non_drx_timer_running;
      break;

    case NC2_NDRX:
      psc_db->nc2_non_drx_period_running = non_drx_timer_running;
      break;
  }

  pg_non_drx( );

}/*grr_handle_non_drx_period*/ 

/*
+------------------------------------------------------------------------------
| Function    : grr_store_g_pwr_par
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_store_g_pwr_par ( T_g_pwr_par *g_pwr_par )
{ 
  TRACE_FUNCTION( "grr_store_g_pwr_par" );
  
  psc_db->v_g_pwr_par = TRUE;

  psc_db->g_pwr_par.alpha           = CLIP_ALPHA( g_pwr_par->alpha );
  psc_db->g_pwr_par.t_avg_w         = CLIP_T_AVG( g_pwr_par->t_avg_w );
  psc_db->g_pwr_par.t_avg_t         = CLIP_T_AVG( g_pwr_par->t_avg_t );
  psc_db->g_pwr_par.pb              = g_pwr_par->pb;
  psc_db->g_pwr_par.pc_meas_chan    = g_pwr_par->pc_meas_chan;
  psc_db->g_pwr_par.imeas_chan_list = g_pwr_par->imeas_chan_list;
  psc_db->g_pwr_par.n_avg_i         = g_pwr_par->n_avg_i;

  grr_data->pwr_ctrl_valid_flags.v_glbl_pwr_ctrl_param = TRUE;

} /* grr_store_g_pwr_par */

/*
+------------------------------------------------------------------------------
| Function    : grr_store_type_pwr_par
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_store_type_pwr_par ( T_pwr_par *pwr_par, BOOL use_prev )
{ 
  UBYTE i; /* used for counting */

  TRACE_FUNCTION( "grr_store_type_pwr_par" );
  
  grr_set_alpha_flags( TRUE, pwr_par->alpha );

  for( i = 0; i < 8; i++ )
  {
    /*
     * if the information element is not present for certain previously 
     * allocated timeslots, the MS shall continue to use the previous
     * power on these timeslots
     */
    if( pwr_par->gamma_tn[i].v_gamma OR !use_prev )
    {
      psc_db->pwr_par.gamma_tn[i].v_gamma = pwr_par->gamma_tn[i].v_gamma;
      psc_db->pwr_par.gamma_tn[i].gamma   = pwr_par->gamma_tn[i].gamma;
    }
  }

  grr_data->pwr_ctrl_valid_flags.v_pwr_ctrl_param = TRUE;

} /* grr_store_type_pwr_par */

/*
+------------------------------------------------------------------------------
| Function    : grr_store_type_tn_alloc_pwr
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_store_type_tn_alloc_pwr ( T_tn_alloc_pwr *pwr_par )
{ 
  UBYTE i; /* used for counting */

  TRACE_FUNCTION( "grr_store_type_tn_alloc_pwr" );
  
  grr_set_alpha_flags( TRUE, pwr_par->alpha );

  for( i = 0; i < 8; i++ )
  {
    psc_db->pwr_par.gamma_tn[i].v_gamma = pwr_par->usf_array[i].v_usf_g;
    psc_db->pwr_par.gamma_tn[i].gamma   = pwr_par->usf_array[i].usf_g.gamma;
  }

  grr_data->pwr_ctrl_valid_flags.v_pwr_ctrl_param = TRUE;
  
} /* grr_store_type_tn_alloc_pwr */

/*
+------------------------------------------------------------------------------
| Function    : grr_store_type_dyn_alloc
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_store_type_dyn_alloc ( T_dyn_alloc *pwr_par )
{ 
  UBYTE i; /* used for counting */

  TRACE_FUNCTION( "grr_store_type_dyn_alloc" );
  
  grr_set_alpha_flags( pwr_par->v_alpha, pwr_par->alpha );

  if( pwr_par->v_usf_gamma_csn1 EQ TRUE )
  {
    for( i = 0; i < 8; i++ )
    {
      psc_db->pwr_par.gamma_tn[i].v_gamma = pwr_par->usf_gamma_csn1[i].v_usf_gamma;
      psc_db->pwr_par.gamma_tn[i].gamma   = pwr_par->usf_gamma_csn1[i].usf_gamma.gamma;
    }
  }

  grr_data->pwr_ctrl_valid_flags.v_pwr_ctrl_param = TRUE;

} /* grr_store_type_dyn_alloc */

/*
+------------------------------------------------------------------------------
| Function    : grr_store_type_alf_gam
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_store_type_alf_gam ( T_alf_gam *pwr_par, UBYTE tn )
{ 
  TRACE_FUNCTION( "grr_store_type_alf_gam" );
  
  grr_set_alpha_flags( TRUE, pwr_par->alpha );
  grr_set_sngl_gamma ( pwr_par->gamma, tn );

  grr_data->pwr_ctrl_valid_flags.v_pwr_ctrl_param = TRUE;

} /* grr_store_type_alf_gam */

/*
+------------------------------------------------------------------------------
| Function    : grr_store_type_pck_upl_ass_ia
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_store_type_pck_upl_ass_ia ( T_tfi_ass_alloc *pwr_par,
                                            UBYTE             tn       )
{ 
  TRACE_FUNCTION( "grr_store_type_pck_upl_ass_ia" );
  
  grr_set_alpha_flags( pwr_par->v_alpha, pwr_par->alpha );
  grr_set_sngl_gamma ( pwr_par->gamma, tn );

  grr_data->pwr_ctrl_valid_flags.v_pwr_ctrl_param = TRUE;

} /* grr_store_type_pck_upl_ass_ia */

/*
+------------------------------------------------------------------------------
| Function    : grr_store_type_pck_snbl_ass_ia
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_store_type_pck_snbl_ass_ia ( T_sngl_block_alloc *pwr_par,
                                            UBYTE             tn       )
{ 
  TRACE_FUNCTION( "grr_store_type_pck_snbl_ass_ia" );
  
  grr_set_alpha_flags( pwr_par->v_alpha, pwr_par->alpha );
  grr_set_sngl_gamma ( pwr_par->gamma, tn );

} /* grr_store_type_pck_snbl_ass_ia */


/*
+------------------------------------------------------------------------------
| Function    : grr_store_type_tfi_ass_rlc
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_store_type_tfi_ass_rlc ( T_tfi_ass_rlc *pwr_par,
                                         UBYTE          tn       )
{ 
  TRACE_FUNCTION( "grr_store_type_tfi_ass_rlc" );
  
  grr_set_alpha_flags( pwr_par->v_alpha, pwr_par->alpha );
  grr_set_sngl_gamma ( pwr_par->gamma, tn );

  grr_data->pwr_ctrl_valid_flags.v_pwr_ctrl_param = TRUE;

} /* grr_store_type_tfi_ass_rlc */


/*
+------------------------------------------------------------------------------
| Function    : grr_store_type_alpha_gamma
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_store_type_alpha_gamma ( T_alpha_gamma *pwr_par,
                                         UBYTE          tn       )
{ 
  TRACE_FUNCTION( "grr_store_type_alpha_gamma" );
  
  grr_set_alpha_flags( TRUE, pwr_par->alpha );
  grr_set_sngl_gamma ( pwr_par->gamma, tn );

  grr_data->pwr_ctrl_valid_flags.v_pwr_ctrl_param = TRUE;

} /* grr_store_type_alpha_gamma */

/*
+------------------------------------------------------------------------------
| Function    : grr_store_type_pwr_ctrl
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_store_type_pwr_ctrl ( T_pwr_ctrl *pwr_par )
{ 
  UBYTE i; /* used for counting */

  TRACE_FUNCTION( "grr_store_type_pwr_ctrl" );
  
  grr_set_alpha_flags( TRUE, pwr_par->alpha );

  for( i = 0; i < 8; i++ )
  {
    psc_db->pwr_par.gamma_tn[i].v_gamma = pwr_par->tagged_gamma[i].v_gamma;
    psc_db->pwr_par.gamma_tn[i].gamma   = pwr_par->tagged_gamma[i].gamma;
  }

  grr_data->pwr_ctrl_valid_flags.v_pwr_ctrl_param = TRUE;

} /* grr_store_type_pwr_ctrl */



/*
+------------------------------------------------------------------------------
| Function    : grr_set_alpha_flags
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
LOCAL void grr_set_alpha_flags ( BOOL v_alpha, UBYTE alpha )
{ 
  TRACE_FUNCTION( "grr_set_alpha_flags" );
  
  if( v_alpha )
  {
    psc_db->pwr_par.v_alpha = TRUE;
    psc_db->pwr_par.alpha   = CLIP_ALPHA( alpha );
  }

  psc_db->v_pwr_par = TRUE;

} /* grr_set_alpha_flags */

/*
+------------------------------------------------------------------------------
| Function    : grr_set_sngl_gamma
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
LOCAL void grr_set_sngl_gamma ( UBYTE gamma, UBYTE tn )
{ 
  UBYTE i; /* used for counting */

  TRACE_FUNCTION( "grr_set_sngl_gamma" );
  
  for( i = 0; i < 8; i++ )
  {
    psc_db->pwr_par.gamma_tn[i].v_gamma = FALSE;
  }

  psc_db->pwr_par.gamma_tn[tn].v_gamma = TRUE;
  psc_db->pwr_par.gamma_tn[tn].gamma   = gamma;

} /* grr_set_sngl_gamma */

/*
+------------------------------------------------------------------------------
| Function    : grr_set_tbf_cfg_req_param
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_set_tbf_cfg_req_param
                                ( T_MPHP_ASSIGNMENT_REQ *tbf_cfg_req )
{ 
  TRACE_FUNCTION( "grr_set_tbf_cfg_req_param" );

  tbf_cfg_req->assign_id          = 0;
  grr_data->cs.last_assignment_id = tbf_cfg_req->assign_id; 
  tbf_cfg_req->m_class            = grr_get_gprs_ms_class( );
  tbf_cfg_req->if_meas_enable     = meas_im_get_permit( );
  tbf_cfg_req->pc_meas_chan       = psc_db->g_pwr_par.pc_meas_chan;
 
  if( psc_db->gprs_cell_opt.ab_type EQ AB_8_BIT )
  {
    tbf_cfg_req->burst_type = AB_8_BIT;
  }
  else
  {
    tbf_cfg_req->burst_type = AB_11_BIT;
  }
} /* grr_set_tbf_cfg_req_param */

/*
+------------------------------------------------------------------------------
| Function    : grr_init_ms_data
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
LOCAL void grr_init_ms_data ( void )
{ 
  TRACE_FUNCTION( "grr_init_ms_data" );

#ifdef _TARGET_
  grr_data->ms.reverts_NMO_III = TRUE;
  grr_data->ms.tbf_mon_ccch    = FALSE; /* Target: Not allowed*/
#else
  grr_data->ms.reverts_NMO_III = FALSE;
  grr_data->ms.tbf_mon_ccch    = TRUE; /* WIN 32: allowed*/
#endif
} /* grr_init_ms_data */




/*
+------------------------------------------------------------------------------
| Function    : grr_update_pacch
+------------------------------------------------------------------------------
| Description : The function grr_update_pacch updates the power reduction and 
|               access burst type in case of change and being in transfer mode
|
| Parameters  : none
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_update_pacch( void )
{ 
  TRACE_FUNCTION( "grr_update_pacch" );

  {
    PALLOC(update_psi, MPHP_UPDATE_PSI_PARAM_REQ);
    update_psi->pb         = psc_db->g_pwr_par.pb;
    update_psi->burst_type = psc_db->gprs_cell_opt.ab_type;    
    PSEND(hCommL1, update_psi);
  }

} /* grr_update_pacch */


/*
+------------------------------------------------------------------------------
| Function    : grr_imsi_mod
+------------------------------------------------------------------------------
| Description : The function grr_imsi_mod() returns the imsi modulo 1000
|
| Parameters  : in: NONE out: USHORT imsimod
|
+------------------------------------------------------------------------------
*/

GLOBAL USHORT grr_imsi_mod ()
{
  UBYTE i= grr_data->db.ms_id.imsi.number_of_digits;
  TRACE_FUNCTION("grr_imsi_mod ");
  
  return ((SHORT)grr_data->db.ms_id.imsi.digit[i - 3] * 100 +
        (SHORT)grr_data->db.ms_id.imsi.digit[i - 2] * 10 +
        (SHORT)grr_data->db.ms_id.imsi.digit[i - 1]);

}

/*
+------------------------------------------------------------------------------
| Function    : grr_set_buf_tlli
+------------------------------------------------------------------------------
| Description : The function grr_set_buf_tlli() fills the TLLI buffer.
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_set_buf_tlli ( BUF_tlli_value *buf_tlli_o, ULONG tlli_i )
{
  TRACE_FUNCTION( "grr_set_buf_tlli" );

  grr_set_tlli( &buf_tlli_o->l_tlli_value, 
                &buf_tlli_o->o_tlli_value,
                &buf_tlli_o->b_tlli_value[0],
                tlli_i );

} /* grr_set_buf_tlli */


/*
+------------------------------------------------------------------------------
| Function    : grr_set_tlli
+------------------------------------------------------------------------------
| Description : The function grr_set_tlli() fills the TLLI buffer.
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_set_tlli
                ( USHORT *l_tlli, USHORT *o_tlli, UBYTE *b_tlli, ULONG tlli )
{
  TRACE_FUNCTION( "grr_set_tlli" );

  *l_tlli   = 32;
  *o_tlli   = 0;
  
  b_tlli[0] = (UBYTE)((tlli >> 24) & 0x000000ff);
  b_tlli[1] = (UBYTE)((tlli >> 16) & 0x000000ff);
  b_tlli[2] = (UBYTE)((tlli >> 8 ) & 0x000000ff);
  b_tlli[3] = (UBYTE)((tlli      ) & 0x000000ff);

  /* unused byte must be set to 0x00, otherwise CCD has some problems */
  b_tlli[4] = 0;

} /* grr_set_tlli */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_tlli
+------------------------------------------------------------------------------
| Description : The function grr_get_tlli() returns the TLLI.
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL ULONG grr_get_tlli ( void )
{
  TRACE_FUNCTION( "grr_get_tlli" );

  return( grr_data->db.ms_id.new_tlli );

} /* grr_get_tlli */

/*
+------------------------------------------------------------------------------
| Function    : grr_encode_ul_ctrl_block
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_encode_ul_ctrl_block ( UBYTE *ul_ctrl_block, 
                                       UBYTE *ul_ctrl_data )
{
  T_CTRLBUF enc_block;

  TRACE_FUNCTION( "grr_encode_ul_ctrl_block" );

  grr_encode_ctrl( ul_ctrl_data, ( T_MSGBUF* )&enc_block , grr_data->r_bit );
  memcpy( ul_ctrl_block, enc_block.buf, BYTELEN( enc_block.l_buf ) );    

} /* grr_encode_ul_ctrl_block */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_ul_ctrl_block_header
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE grr_get_ul_ctrl_block_header ( UBYTE r_bit )
{
  TRACE_FUNCTION( "grr_get_ul_ctrl_block_header" );

  /* 
   * set Payload Type and R Bit
   */
  return( ( CTRL_BLK_NO_OPT << 6 ) | r_bit );

} /* grr_get_ul_ctrl_block_header */

/*
+------------------------------------------------------------------------------
| Function    : grr_check_if_tbf_start_is_elapsed
+------------------------------------------------------------------------------
| Description : The function grr_check_if_tbf_start_is_elapsed() checks if 
|               tbf starting time is elapsed or not, modulo calculation is 
|               needed
| Parameters  : start_fn    - tbf starting time
|               current_fn  - current frame number
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_check_if_tbf_start_is_elapsed ( ULONG start_fn, ULONG current_fn)
{
  BOOL  result = FALSE;
  ULONG d1;
  /* ULONG d2; */
  /* FN_MAX=0x297000 == 2715648 ==125463 seconds(4.62ms per frame)
   * the starting time is within  current_fn-10808 and current_fn+31623
   * modulo operation must be taken in account
   */
  TRACE_FUNCTION( "grr_check_if_tbf_start_is_elapsed" );

  /*
   * handle maximum distance for tbf starting time
   */

  if(start_fn EQ 0xFFFFFFFF)
  {
    result =TRUE;
    return result;
  }
  d1 = 10808;
  /* d2 = 31623; */
  if( (start_fn <= current_fn)     AND
      ((current_fn-start_fn) <= d1))
  {
    result = TRUE;
    TRACE_EVENT_P2(" case 1: st time elapsed st_fn=%ld  c_fn=%ld",start_fn,current_fn);
  }
  else if((start_fn >= current_fn) AND
          (FN_MAX-start_fn+current_fn) <= d1)
  {
    result = TRUE;
    TRACE_EVENT_P2("case 2: st time elapsed st_fn=%ld  c_fn=%ld",start_fn,current_fn);
  }
  else
  {
    TRACE_EVENT_P2("case 3: WAIT FOR ST TIME st_fn=%ld  c_fn=%ld",start_fn,current_fn);
  }

    

  return result;
} /* grr_check_if_tbf_start_is_elapsed() */

/*
+------------------------------------------------------------------------------
| Function    : grr_calculate_Tra
+------------------------------------------------------------------------------
| Description : The function has to calculate for mobile type 1 (ms_class 1-12)
|               the minimum timeslots between end of last previous downlink  
|               timeslot and the  next uplink or two consecutive uplinks.
|
| Parameters  : ul_usage : uplink timeslot mask
|               dl_usage : downlink timeslot mask
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE grr_calculate_Tra (UBYTE ul_usage, UBYTE dl_usage)
{
  UBYTE mask=0x80, z_mask=0;
  UBYTE Tx[8],Rx[8],ul_seted_slot,dl_seted_slot,j,i,tra,rc_dl_usage;

  TRACE_FUNCTION( "grr_calculate_Tra" );

  memset( Tx, 0, sizeof( Tx ) );
  memset( Rx, 0, sizeof( Rx ) );


  ul_seted_slot = 0;
  dl_seted_slot = 0;

  /*
   * detect position of uplink seted slots and the number of slots
   */
  if(ul_usage NEQ z_mask)
  {
    for(j=0;j<8;j++)
    {
      if(mask & ul_usage)
      {
        Tx[ul_seted_slot]=j+1;
        ul_seted_slot++;
      }
      mask>>=1;
    }
  }
  /*
   * detect position of downlink seted slots and the number of slots
   * and shift them for 3 positions(delay between uplink and downlink)
   */  
  mask        = 0x80; /* set again, it is reused*/
  rc_dl_usage = grr_reconstruct_dl_usage(dl_usage);
  if(rc_dl_usage NEQ z_mask)
  {
    for(i=0;i<=7;i++)
    {
      if(mask & rc_dl_usage)
      {
        Rx[dl_seted_slot]=i+1;
        dl_seted_slot++;
      }
      mask>>=1;
    }
  }
  tra=0xFF; /* set to invalid value */
  /*
   * calculate tra
   */
  for(i=0;i<ul_seted_slot;i++)
  {
    for(j=0;j<dl_seted_slot;j++)
    {
      if (Rx[j] EQ Tx[i])
      { /* tranmission and receiving at the same time not allowed*/
        tra=0;
        TRACE_EVENT_P6("OVERLAP TRA  Rx[%d]=%d  Tx[%d]=%d ul_mask=%x dl_mask=%x"
                                  ,j
                                  ,Rx[j]
                                  ,i
                                  ,Tx[i]
                                  ,ul_usage
                                  ,dl_usage);
        return tra;
      }
      else if(Rx[j] > Tx[i])
      {
        if(tra > (Rx[j] - Tx[i]-1))
        {
          tra = Rx[j] - Tx[i]-1;
        }
      }
      else
      {
        if(tra > (Rx[j]+8 - Tx[i]-1))
        {
          tra = Rx[j]+8 - Tx[i]-1;
        }
      }
    }      
  }
  return tra;
} /*grr_calculate_Tra */

/*
+------------------------------------------------------------------------------
| Function    : grr_calculate_Ttb
+------------------------------------------------------------------------------
| Description : The function has to calculate for mobile type 1 (ms_class 1-12)
|               the minimum timeslot between end of last previous uplink  
|               timeslot and the first next downlink or two cnsecutive Downlinks.
|
| Parameters  : ul_usage : uplink timeslot mask
|               dl_usage : downlink timeslot mask
|
+------------------------------------------------------------------------------
*/

GLOBAL UBYTE grr_calculate_Ttb (UBYTE ul_usage, UBYTE dl_usage)
{
  UBYTE mask=0x80, z_mask=0;
  UBYTE Tx[8],Rx[8],ul_seted_slot,dl_seted_slot,j,i,ttb;

  TRACE_FUNCTION( "grr_calculate_Ttb" );

  memset( Tx, 0, sizeof( Tx ) );
  memset( Rx, 0, sizeof( Rx ) );
 
  ul_seted_slot = 0;
  dl_seted_slot = 0;

  /*
   * detecte position of uplink seted slots and the number of slots  
   * uplink slots gets an offset of 3 positions(Air interface).
   */
  if(ul_usage NEQ z_mask)
  {
    for(j=0;j<8;j++)
    {
      if(mask & ul_usage)
      {
        Tx[ul_seted_slot]=j+1+3;
        ul_seted_slot++;
      }
      mask>>=1;
    }
  }
  /* 
   * detecte position of downlink seted slots and the number of slots 
   */
  mask=0x80;
  if(dl_usage NEQ z_mask)
  {
    for(i=0;i<=7;i++)
    {
      if(mask & dl_usage)
      {
        Rx[dl_seted_slot]=i+1;
        dl_seted_slot++;
      }
      mask>>=1;
    }
  }
  ttb=0xFF; /* set to invalid value */
  /*
   * calculate ttb
   */
  for(i=0;i<dl_seted_slot;i++)
  {
    for(j=0;j<ul_seted_slot;j++)
    {
      if ((Tx[j] EQ Rx[i])  OR
          !(Tx[j] - Rx[i]-8))
      { /* tranmission and receiving at the same time not allowed*/
        ttb=0;
        TRACE_EVENT_P6("OVERLAP TTB    Tx[%d]=%d  Rx[%d]=%d ul_mask=%x dl_mask=%x"
                                    ,j
                                    ,Tx[j]
                                    ,i
                                    ,Rx[i]
                                    ,ul_usage
                                    ,dl_usage);
        return ttb;
      }
      else if(Tx[j] > Rx[i])
      {
        if((Tx[j] - Rx[i] > 8) AND
           (ttb > (Tx[j] - Rx[i]-8-1)))
        {
          ttb  = Tx[j] - Rx[i]-8-1;
        }
        else if(ttb > (Tx[j] - Rx[i]-1))
        {
          ttb  = Tx[j] - Rx[i]-1;          
        }
      }
      else if(ttb > (Tx[j]+8 - Rx[i]-1) )
      {
        ttb = Tx[j]+8 - Rx[i]-1;
      }
    }
  }
  return ttb;
} /* grr_calculate_Ttb */


/*
+------------------------------------------------------------------------------
| Function    : grr_reconstruct_dl_usage
+------------------------------------------------------------------------------
| Description : this function converts the downlink slot mask. The first 3 MSB
|               are switched to the first LSB bits.
|               B0 is the MSB, B7 is the LSB
|               dl_usage (input)     : B0 B1 B2 B3 B4 B5 B6 B7
|               new_dl_usage (output): B3 B4 B5 B6 B7 B0 B1 B2
|
| Parameters  : dl_usage: this is timeslot mask for downlink
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE grr_reconstruct_dl_usage(UBYTE dl_usage)
{
  UBYTE help, new_dl_usage;

  TRACE_FUNCTION( "grr_reconstruct_dl_usage" );

  help         = 0xE0;
  help        &= dl_usage;
  dl_usage   <<= 3;
  help       >>= 5;
  new_dl_usage = dl_usage | help;

  return new_dl_usage;
}/* grr_reconstruct_dl_usage */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_gprs_ms_class
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE grr_get_gprs_ms_class ( void )
{
  T_rf_cap *rf_cap         = rr_csf_get_rf_capability( );
  UBYTE     gprs_ms_class;

  TRACE_FUNCTION( "grr_get_gprs_ms_class" );

  if( rf_cap NEQ NULL )
  {
    gprs_ms_class = rf_cap->rf_ms.gprs_ms_class;
  }
  else
  {
    gprs_ms_class = MSLOT_CLASS_1;

    TRACE_ERROR( "grr_get_gprs_ms_class: RF capabilities invalid" );
  }

  return( gprs_ms_class );

} /* grr_get_gprs_ms_class */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_next_ncell_param
+------------------------------------------------------------------------------
| Description : 
| Parameters  : 
+------------------------------------------------------------------------------
*/
GLOBAL T_ncell_info* grr_get_next_ncell_param ( UBYTE       max_number,
                                                T_NC_LIST  *list,
                                                T_INFO_SRC  info_src )
{
  UBYTE         i;
  T_ncell_info *ncell_info_max;
  T_ncell_info *ncell_info_next;

  TRACE_FUNCTION( "grr_get_next_ncell_param" );

  /*
   * looking for the next free entry or in case there is no more free entry
   * available, looking for the highest indexed entry which will be deleted
   */
  if( list->number < max_number )
  {
    ncell_info_max = &list->info[list->number];
  }
  else
  {
    ncell_info_max = &list->info[0];

    for( i = 1; i < max_number; i++ )
    {
      ncell_info_next = &list->info[i];

      if( ncell_info_next->info_src > ncell_info_max->info_src )
      {
        ncell_info_max = ncell_info_next;
      }
    }

    TRACE_ERROR( "grr_get_next_ncell_param: Number of NCELLs > max_number" );

    if( ncell_info_max->info_src < info_src )
    {
      TRACE_EVENT( "grr_get_next_ncell_param: Keep NCELL list" );

      ncell_info_max = NULL;
    }
    else if( ncell_info_max->info_src EQ info_src )
    {
      TRACE_ERROR( "grr_get_next_ncell_param: Two identical NCELL" );

      ncell_info_max = NULL;
    }
    else
    {
      TRACE_EVENT( "grr_get_next_ncell_param: Change NCELL list" );
    }
  }

  return( ncell_info_max );

}/* grr_get_next_ncell_param */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_next_bigger_ncell_param
+------------------------------------------------------------------------------
| Description : 
| Parameters  : 
+------------------------------------------------------------------------------
*/
GLOBAL T_ncell_info* grr_get_next_bigger_ncell_param ( T_NC_LIST  *list,
                                                       T_INFO_SRC  info_src )
{
  UBYTE         i;
  T_INFO_SRC    info_src_max;
  T_ncell_info *ncell_info_next;
  T_ncell_info *ncell_info_bigger = NULL;

  TRACE_FUNCTION( "grr_get_next_bigger_ncell_param" );

  if( list->number NEQ 0 )
  {
    /*
     * all indeces should be set to unused in case info_src EQ 0,
     * which marks the start of a new search process 
     */    
    if( info_src EQ 0 )
    {
      for( i = 0; i < list->number; i++ )
      {
        list->info[i].index = 0xFF;
      }
    }

    i            = 0;
    info_src_max = ~((T_INFO_SRC)0);

    do
    {
      ncell_info_next = &list->info[i];

      TRACE_ASSERT( info_src               NEQ ncell_info_next->info_src OR 
                    ncell_info_next->index NEQ 0xFF                         );


      if( info_src                  < ncell_info_next->info_src AND 
          ncell_info_next->info_src < info_src_max                  )
      {
        info_src_max      = ncell_info_next->info_src;
        ncell_info_bigger = ncell_info_next;
      }

      i++;
    }
    while( i < list->number );
  }

  return( ncell_info_bigger );

}/* grr_get_next_bigger_ncell_param */

/*
+------------------------------------------------------------------------------
| Function    : grr_store_cs_param
+------------------------------------------------------------------------------
| Description : 
| Parameters  : ncell_info     - neighbour cell information
|               v_cs_par       - valid falg for cell selection parameter
|               cs_par         - cell selection parameter
|               info_src       - source of neighbour cell information
|               arfcn          - absolute radio frequency channel number
|               bsic           - base station identity code
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_store_cs_param ( T_NC_LIST    *nc_list,
                                 BOOL          v_cs_par,
                                 T_cs_par     *cs_par,
                                 T_INFO_TYPE   type,
                                 UBYTE         instance,
                                 UBYTE        *number,
                                 USHORT       *freq,
                                 USHORT        freq_diff,
                                 UBYTE         bsic )
{
  T_INFO_SRC    info_src=0;
  T_ncell_info *ncell_info;

  TRACE_FUNCTION( "grr_store_cs_param" );

  NC_SET_TYPE    ( info_src, type     );
  NC_SET_INSTANCE( info_src, instance );
  NC_SET_NUMBER  ( info_src, *number  );

  ncell_info = grr_get_next_ncell_param( MAX_NR_OF_NCELL,
                                         nc_list, 
                                         info_src );

  if( ncell_info EQ NULL )
  {
    return( FALSE );
  }

  (*number)++;
  nc_list->number++;

  *freq = ( *freq + freq_diff ) % 1024;

  ncell_info->info_src = info_src;
  ncell_info->arfcn    = *freq;
  ncell_info->bsic     = bsic;

  ncell_info->v_cr_par = v_cs_par;

  if( v_cs_par EQ TRUE )
  {
    ncell_info->cr_par.same_ra_scell = cs_par->same_ra_scell;
    ncell_info->cr_par.exc_acc       = cs_par->exc_acc;
    ncell_info->cr_par.cell_ba       = cs_par->cell_ba;

#if !defined (NTRACE)

    if( grr_data->cs.v_crp_trace EQ TRUE )
    {
      TRACE_EVENT_P3( "grr_store_cs_param: cell barred status %d %d, info_src %x",
                      ncell_info->arfcn, ncell_info->cr_par.cell_ba, info_src );
    }

#endif /* #if !defined (NTRACE) */

    SET_GPRS_RXLEV_ACCESS_MIN
      ( ncell_info->cr_par.cr_par_1.cr_pow_par.gprs_rxlev_access_min,
        cs_par->v_cs_par_s1, cs_par->cs_par_s1.gprs_rxlev_access_min );

    SET_GPRS_MS_TXPWR_MAX_CCH
      ( ncell_info->cr_par.cr_par_1.cr_pow_par.gprs_ms_txpwr_max_cch,
        cs_par->v_cs_par_s1, cs_par->cs_par_s1.txpwr_max_cch );

    SET_GPRS_TEMP_OFFSET
      ( ncell_info->cr_par.cr_offset.gprs_temp_offset,
        cs_par->v_cs_par_s2, cs_par->cs_par_s2.gprs_temp_offset );

    SET_GPRS_PENALTY_TIME
      ( ncell_info->cr_par.cr_offset.gprs_penalty_time,
        cs_par->v_cs_par_s2, cs_par->cs_par_s2.gprs_penalty_time );

    SET_GPRS_RESEL_OFF
      ( ncell_info->cr_par.gprs_resel_off,
        cs_par->v_gprs_resel_off, cs_par->gprs_resel_off );

    ncell_info->cr_par.cr_par_1.v_hcs_par = cs_par->v_hcs_par;

    SET_GPRS_HCS_THR
      ( ncell_info->cr_par.cr_par_1.hcs_par.gprs_hcs_thr,
        cs_par->v_hcs_par, cs_par->hcs_par.gprs_hcs_thr );

    SET_GPRS_PRIO_CLASS
      ( ncell_info->cr_par.cr_par_1.hcs_par.gprs_prio_class,
        cs_par->v_hcs_par, cs_par->hcs_par.gprs_prio_class );

    grr_store_si13_pbcch_location( &ncell_info->cr_par,
                                   cs_par->v_si13_pbcch,
                                   &cs_par->si13_pbcch );
  }

  return( TRUE );

}/* grr_store_cs_param */

/*
+------------------------------------------------------------------------------
| Function    : grr_store_si13_pbcch_locaction
+------------------------------------------------------------------------------
| Description : 
| Parameters  : 
+------------------------------------------------------------------------------
*/
GLOBAL void grr_store_si13_pbcch_location ( T_CR_PAR     *cr_par,
                                            BOOL          v_si13_pbcch,
                                            T_si13_pbcch *si13_pbcch )
{
  TRACE_FUNCTION( "grr_store_si13_pbcch_locaction" );

  cr_par->v_si13_pbcch = v_si13_pbcch;

  if( v_si13_pbcch )
  {
    cr_par->si13_pbcch.v_si13_location = si13_pbcch->v_si13_loc;

    if( si13_pbcch->v_si13_loc )
    {
      cr_par->si13_pbcch.si13_location = si13_pbcch->si13_loc;
    }
    else
    {
      cr_par->si13_pbcch.pbcch_location     =
        si13_pbcch->si13_pbcch_s1.pbcch_loc;
      cr_par->si13_pbcch.psi1_repeat_period =
        si13_pbcch->si13_pbcch_s1.psi1_rep_per + 1;
    }
  }
}/* grr_store_si13_pbcch_locaction */

/*
+------------------------------------------------------------------------------
| Function    : grr_restore_cs_param
+------------------------------------------------------------------------------
| Description : 
| Parameters  : 
+------------------------------------------------------------------------------
*/
GLOBAL void grr_restore_cs_param ( T_ncell_info *curr_info,
                                   T_ncell_info *prev_info,
                                   UBYTE         curr_idx )
{
  TRACE_FUNCTION( "grr_restore_cs_param" );

  curr_info->index = curr_idx;

  if( grr_is_pbcch_present( ) )
  {
    if( curr_info->cr_par.cr_par_1.cr_pow_par.gprs_rxlev_access_min EQ 
        GPRS_RXLEV_ACCESS_MIN_INVALID                                  )
    {
      if( prev_info NEQ NULL )
      {
        curr_info->cr_par.cr_par_1.cr_pow_par.gprs_rxlev_access_min =
          prev_info->cr_par.cr_par_1.cr_pow_par.gprs_rxlev_access_min;
      }
      else
      {
        curr_info->cr_par.cr_par_1.cr_pow_par.gprs_rxlev_access_min =
          psc_db->scell_par.cr_par_1.cr_pow_par.gprs_rxlev_access_min;
      }
    }

    if( curr_info->cr_par.cr_par_1.cr_pow_par.gprs_ms_txpwr_max_cch EQ 
        GPRS_MS_TXPWR_MAX_CCH_INVALID                                  )
    {
      if( prev_info NEQ NULL )
      {
        curr_info->cr_par.cr_par_1.cr_pow_par.gprs_ms_txpwr_max_cch =
          prev_info->cr_par.cr_par_1.cr_pow_par.gprs_ms_txpwr_max_cch;
      }
      else
      {
        curr_info->cr_par.cr_par_1.cr_pow_par.gprs_ms_txpwr_max_cch =
          psc_db->scell_par.cr_par_1.cr_pow_par.gprs_ms_txpwr_max_cch;
      }
    }

    if( curr_info->cr_par.cr_offset.gprs_temp_offset EQ 
        GPRS_TEMPORARY_OFFSET_INVALID                   )
    {
      if( prev_info NEQ NULL )
      {
        curr_info->cr_par.cr_offset.gprs_temp_offset =
          prev_info->cr_par.cr_offset.gprs_temp_offset;
      }
      else
      {
        TRACE_ERROR( "gprs_temp_offset not present in 1st NCELL");

        curr_info->cr_par.cr_offset.gprs_temp_offset =
          GPRS_TEMPORARY_OFFSET_00_DB;
      }
    }

    if( curr_info->cr_par.cr_offset.gprs_penalty_time EQ 
        GPRS_PENALTY_TIME_INVALID                        )
    {
      if( prev_info NEQ NULL )
      {
        curr_info->cr_par.cr_offset.gprs_penalty_time =
          prev_info->cr_par.cr_offset.gprs_penalty_time;
      }
      else
      {
        TRACE_ERROR( "gprs_penalty_time not present in 1st NCELL");

        curr_info->cr_par.cr_offset.gprs_penalty_time =
          GPRS_PENALTY_TIME_MAX;
      }
    }

    if( psc_db->scell_par.cr_par_1.v_hcs_par EQ FALSE )
    {
      /*
       * If the HCS struct is omitted for the serving cell,
       * HCS is not used and the HCS parameters for the other
       * cells shall be neglected i.e the HCS signal strength
       * threshold shall be set to infinity for all cells.
       */
      curr_info->cr_par.cr_par_1.v_hcs_par = FALSE;
    }
    else
    {
      if( curr_info->cr_par.cr_par_1.v_hcs_par EQ FALSE )
      {
        if( prev_info NEQ NULL )
        {
          curr_info->cr_par.cr_par_1.v_hcs_par = 
            prev_info->cr_par.cr_par_1.v_hcs_par;

          if( curr_info->cr_par.cr_par_1.hcs_par.gprs_prio_class EQ
              GPRS_PRIORITY_CLASS_INVALID                           )
          {
            curr_info->cr_par.cr_par_1.hcs_par.gprs_prio_class =
              prev_info->cr_par.cr_par_1.hcs_par.gprs_prio_class;
          }

          if( curr_info->cr_par.cr_par_1.hcs_par.gprs_hcs_thr EQ 
              GPRS_HCS_THR_INVALID                               )
          {
            curr_info->cr_par.cr_par_1.hcs_par.gprs_hcs_thr =
              prev_info->cr_par.cr_par_1.hcs_par.gprs_hcs_thr;
          }
        }
        else
        {
          curr_info->cr_par.cr_par_1.v_hcs_par = 
            psc_db->scell_par.cr_par_1.v_hcs_par;

          if( curr_info->cr_par.cr_par_1.hcs_par.gprs_prio_class EQ
              GPRS_PRIORITY_CLASS_INVALID                           )
          {
            curr_info->cr_par.cr_par_1.hcs_par.gprs_prio_class =
              psc_db->scell_par.cr_par_1.hcs_par.gprs_prio_class;
          }

          if( curr_info->cr_par.cr_par_1.hcs_par.gprs_hcs_thr EQ 
              GPRS_HCS_THR_INVALID                               )
          {
            curr_info->cr_par.cr_par_1.hcs_par.gprs_hcs_thr =
              psc_db->scell_par.cr_par_1.hcs_par.gprs_hcs_thr;
          }
        }
      }
    }
  }
}/* grr_restore_cs_param */



/*
+------------------------------------------------------------------------------
| Function    : grr_handle_ta
+------------------------------------------------------------------------------
| Description : This function handles the timing advance of the MS
| Parameters  : v_tav:    valid flag ta_value
|               tav:      ta value
|               v_ul_tai: valid flag dl ta_index
|               ul_tai:   dl ta index
|               ul_tatn:  dl ta timeslot number
|               v_dl_tai: valid flag dl ta_index
|               dl_tai:   dl ta index
|               dl_tatn:  dl ta timeslot number
|               ptr2ta:   pointer to the ta structue, which is passed to l1
+------------------------------------------------------------------------------
*/
GLOBAL void grr_handle_ta ( UBYTE v_tav,
                            UBYTE tav,
                            UBYTE v_ul_tai, 
                            UBYTE ul_tai,
                            UBYTE ul_tatn, 
                            UBYTE v_dl_tai, 
                            UBYTE dl_tai,
                            UBYTE dl_tatn, 
                            T_p_timing_advance *ptr2ta)
{
  BOOL use_dl_par = FALSE;
  TRACE_FUNCTION( "grr_handle_ta" );

  ptr2ta->ta_value             = 0xFF;
  ptr2ta->ta_index             = 0xFF;
  ptr2ta->tn                   = 0xFF;

  /*TRACE_EVENT_P1("grr_data->tbf_type: %d", grr_data->tbf_type);*/
  switch(grr_data->tbf_type)
  {
    case CGRLC_TBF_MODE_DL:
    case CGRLC_TBF_MODE_DL_UL:
      /*use DL TA parameters*/
      use_dl_par = TRUE;
      break;
    case CGRLC_TBF_MODE_NULL:
    case CGRLC_TBF_MODE_UL:
#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH
    case CGRLC_TBF_MODE_2PA:
#endif
    default:
      /*future use*/
      break;
  }
  /*
   * TA-Value, if present
   */
  if(v_tav) /* New TA value Received */
  { 
    /*  
    TRACE_EVENT("New TA value Received");
    */
    if(tav NEQ grr_data->ta_params.ta_value )
    {
      /*
       * inform grlc that new ta is received
       */

      PALLOC(cgrlc_ta_value_req, CGRLC_TA_VALUE_REQ);
      cgrlc_ta_value_req->ta_value = tav;
      PSEND(hCommGRLC, cgrlc_ta_value_req);
    }
    ptr2ta->ta_value             = tav;
    grr_data->ta_params.ta_value = tav;
    grr_data->ta_params.ta_valid = TRUE;
  }
  else if(grr_data->ta_params.ta_valid) /* use old TA value */
  {
    /*
    TRACE_EVENT("Use old TA value in IA or PUL on (P)AGCH");
    */
    ptr2ta->ta_value = grr_data->ta_params.ta_value;
  }
  else
  {
    /*TRACE_EVENT("No valid TA in neither in message nor stored TA: check TAI");*/
    grr_data->ta_params.ta_value = 0xFF;
    grr_data->ta_params.ta_valid = FALSE;
  }

  /*
   * If TAI present the MS shall use "continuos TA"
   */
  if(v_dl_tai EQ 0)
  {
    /* Reset the tai & ta_tn */
    if(grr_data->ta_params.dl_ta_i NEQ 0xFF)
    {
      TRACE_EVENT_P4("TA_INFO: Switch off DL CTA dl_tai=%d dl_ta_tn=%d ul_tai=%d, ul_ta_tn=%d",
      grr_data->ta_params.dl_ta_i,
      grr_data->ta_params.dl_ta_tn,
      grr_data->ta_params.ul_ta_i,
      grr_data->ta_params.ul_ta_tn);
    }
    grr_data->ta_params.dl_ta_i  = 0xFF;
    grr_data->ta_params.dl_ta_tn = 0xFF;
  }
  else if(v_dl_tai EQ 1)
  {
    /* TRACE_EVENT("DL TAI: cont TA: if UL TAI is also valid, we prefer to use DL TAI"); */
    grr_data->ta_params.dl_ta_i  = dl_tai;
    grr_data->ta_params.dl_ta_tn = dl_tatn;
    ptr2ta->ta_index             = dl_tai;
    ptr2ta->tn                   = dl_tatn;
  }

  if(v_ul_tai EQ 0)
  {
    /* Reset the tai & ta_tn */
    if(grr_data->ta_params.ul_ta_i NEQ 0xFF)
    {
      TRACE_EVENT_P7("TA_INFO: Switch off UL CTA ul_tai=%d ul_ta_tn=%d dl_tai=%d dl_ta_tn=%d v_dl_tai=%d new_dl_tai=%d new_dl_ta_tn=%d",
      grr_data->ta_params.ul_ta_i,
      grr_data->ta_params.ul_ta_tn,
      grr_data->ta_params.dl_ta_i,
      grr_data->ta_params.dl_ta_tn,
      v_dl_tai,
      dl_tai,
      dl_tatn);
    }
    grr_data->ta_params.ul_ta_i  = 0xFF;
    grr_data->ta_params.ul_ta_tn = 0xFF;

    if(use_dl_par AND grr_data->ta_params.dl_ta_i NEQ 0xFF)
    {
      ptr2ta->ta_index             = grr_data->ta_params.dl_ta_i;
      ptr2ta->tn                   = grr_data->ta_params.dl_ta_tn;
    }
  }
  else if(v_ul_tai EQ 1)
  {
    grr_data->ta_params.ul_ta_i  = ul_tai;
    grr_data->ta_params.ul_ta_tn = ul_tatn;
    if(use_dl_par AND grr_data->ta_params.dl_ta_i NEQ 0xFF)
    {
      /* TRACE_EVENT("Conc TBF: use DL TA for UL"); */
      ptr2ta->ta_index             = grr_data->ta_params.dl_ta_i;
      ptr2ta->tn                   = grr_data->ta_params.dl_ta_tn;
    }
    else
    {
      /* TRACE_EVENT("Single TBF or TBF_Type is not set to concurrent: UL TAI: cont TA"); */
      ptr2ta->ta_index             = ul_tai;
      ptr2ta->tn                   = ul_tatn;
    }
  }
  /*
   * store values ,which are passed to layer 1
   */
  grr_data->ta_params.l1_ta_value = ptr2ta->ta_value;
  grr_data->ta_params.l1_ta_i     = ptr2ta->ta_index;
  grr_data->ta_params.l1_ta_tn    = ptr2ta->tn;
/*

  {
    ULONG trace[4];

    trace[0]  = ul_tai   <<  0;
    trace[0] |= v_ul_tai <<  8;
    trace[0] |= tav      << 16;
    trace[0] |= v_tav    << 24;

    trace[1]  = dl_tatn  <<  0;
    trace[1] |= dl_tai   <<  8;
    trace[1] |= v_dl_tai << 16;
    trace[1] |= ul_tatn  << 24;

    trace[2]  = grr_data->ta_params.ul_ta_tn <<  0;
    trace[2] |= grr_data->ta_params.ul_ta_i  <<  8;
    trace[2] |= grr_data->ta_params.ta_value << 16;
    trace[2] |= grr_data->ta_params.ta_valid << 24;

    trace[3]  = grr_data->ta_params.l1_ta_i     <<  0;
    trace[3] |= grr_data->ta_params.l1_ta_value <<  8;
    trace[3] |= grr_data->ta_params.dl_ta_tn    << 16;
    trace[3] |= grr_data->ta_params.dl_ta_i     << 24;

    TRACE_EVENT_P5( "TA_PARAM_1: %08X%08X %08X%08X%02X",
                    trace[0], trace[1], trace[2], trace[3],
                    grr_data->ta_params.l1_ta_tn );
  }
*/
}/* grr_handle_ta */

/*---------------------- GET FROM PPC-----------------------------------------*/
/*
+------------------------------------------------------------------------------
| Function    : grr_decode_grr
+------------------------------------------------------------------------------
| Description : The function grr_decode_grr() calls the function ccd_decodeMsg.
|               After the call the decoded Message is in _decodeCtrlMsg.
|
| Parameters  : msg_ptr_i - pointer to buffer that should be decoded
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE grr_decode_grr (T_MSGBUF  *  msg_ptr_i)
{ 
  UBYTE result;
  UBYTE msg_type = msg_ptr_i->buf[0] >> 2;;

  TRACE_FUNCTION( "grr_decode_grr" );

  /*
   * Offset must be zero, else code to get msg_type is illegal
   */
  TRACE_ASSERT (msg_ptr_i->o_buf==0);

#ifdef _SIMULATION_
  /*
   * If one of the following asserts fail, you have to verify the message
   * decoders.
   */
#ifdef REL99
  TRACE_ASSERT (sizeof(T_D_DL_ASSIGN)   == 0x02E0); /*lint !e774*/
  TRACE_ASSERT (sizeof(T_D_UL_ASSIGN)   == 0x0410); /*lint !e774*/
  TRACE_ASSERT (sizeof(T_D_TS_RECONFIG) == 0x03D8); /*lint !e774*/
#else
  TRACE_ASSERT (sizeof(T_D_DL_ASSIGN)   == 0x024C); /*lint !e774*/
  TRACE_ASSERT (sizeof(T_D_UL_ASSIGN)   == 0x040C); /*lint !e774*/
  TRACE_ASSERT (sizeof(T_D_TS_RECONFIG) == 0x03D4); /*lint !e774*/
#endif
#endif


  switch (msg_type)
  {
    case D_DL_ASSIGN:
      result = grr_decode_dl_assignment (msg_ptr_i->buf, msg_ptr_i->o_buf, msg_ptr_i->l_buf);
      break;

    case D_UL_ASSIGN:
      result = grr_decode_ul_assignment (msg_ptr_i->buf, msg_ptr_i->o_buf, msg_ptr_i->l_buf);
      break;

    case D_TS_RECONFIG:
      result = grr_decode_ts_reconfig (msg_ptr_i->buf, msg_ptr_i->o_buf, msg_ptr_i->l_buf);
      break;
    case D_PDCH_RELEASE:
      result = grr_decode_pdch_release (msg_ptr_i->buf, msg_ptr_i->o_buf, msg_ptr_i->l_buf);
      break;
    case D_POLLING_REQ:
      result = grr_decode_polling_req (msg_ptr_i->buf, msg_ptr_i->o_buf, msg_ptr_i->l_buf);
      break;
    case D_TBF_RELEASE:
      result = grr_decode_tbf_release_req (msg_ptr_i->buf, msg_ptr_i->o_buf, msg_ptr_i->l_buf);
      break;
     
    default:
      result = ccd_decodeMsg (CCDENT_GRR, DOWNLINK, msg_ptr_i, _decodedMsg, NOT_PRESENT_8BIT);
      break;
  }


  if ( result EQ ccdError ) switch (msg_type)
  {
    case D_DL_ASSIGN:
    case D_UL_ASSIGN:
    case D_TS_RECONFIG:
      /* This should not be the final version of error handling */
      return DELETE_MESSAGE;

    default:
      return grr_ccd_error_handling( CCDENT_GRR );
  }

  return msg_type;

} /* grr_decode_grr() */


/*
+------------------------------------------------------------------------------
| Function    : grr_decode_rlcmac
+------------------------------------------------------------------------------
| Description : The function grr_decode_rlcmac() 
|
| Parameters  : ptr_msg_i     - pointer to rlcmac-ctrl message
|               ptr_header_i  - pointer to mac header of the rlc block
+------------------------------------------------------------------------------
*/
GLOBAL void grr_decode_rlcmac ( UBYTE * ptr_msg_i, T_D_HEADER * ptr_d_header_i )
{   
  UBYTE rrbp, sp, payload;
  TRACE_FUNCTION( "grr_decode_rlcmac" );
  /*MAC Header*/
  payload      = (ptr_msg_i[0] & 0xC0) >> 6;
  rrbp         = (ptr_msg_i[0] & 0x30) >> 4;
  sp           = (ptr_msg_i[0] & 0x08) >> 3;
  ptr_d_header_i->payload  = payload;
  /*if ctrl block with optional parameter*/
  if(payload EQ CTRL_BLK_OPT )
  {
    ptr_d_header_i->d_ctrl.rrbp         = rrbp;
    ptr_d_header_i->d_ctrl.sp           = sp;
    ptr_d_header_i->d_ctrl.rbsn         = (ptr_msg_i[1] & 0x80) >> 7;
    ptr_d_header_i->d_ctrl.rti          = (ptr_msg_i[1] & 0x7C) >> 2;
    ptr_d_header_i->d_ctrl.fs           = (ptr_msg_i[1] & 0x02) >> 1;
    ptr_d_header_i->d_ctrl.ac           = (ptr_msg_i[1] & 0x01);
    if(ptr_d_header_i->d_ctrl.ac EQ 1)
    {
      ptr_d_header_i->d_ctrl.msg_type     = ptr_msg_i[3] >> 2;
      ptr_d_header_i->d_ctrl.tfi          = (ptr_msg_i[2] & 0x3E) >> 1;
      ptr_d_header_i->d_ctrl.d            = (ptr_msg_i[2] & 0x01);
      ptr_d_header_i->ptr_block           = &ptr_msg_i[3];
    }
    else
    {
      ptr_d_header_i->d_ctrl.msg_type     = ptr_msg_i[2] >> 2;
      ptr_d_header_i->ptr_block           = &ptr_msg_i[2];
    }

    TRACE_EVENT_P4("optional header received: 0x%x 0x%x 0x%x 0x%x",ptr_msg_i[0],ptr_msg_i[1],ptr_msg_i[2],ptr_msg_i[3]);
  }
  else if(payload EQ CTRL_BLK_NO_OPT )
    /*if ctrl block with optional parameter*/
  {
    ptr_d_header_i->d_ctrl.msg_type     = ptr_msg_i[1] >> 2;
    ptr_d_header_i->d_ctrl.rrbp         = rrbp;
    ptr_d_header_i->d_ctrl.sp           = sp;
    ptr_d_header_i->ptr_block           = &ptr_msg_i[1];
  }
  else
  {
    TRACE_ERROR("unknown payload type");
    TRACE_EVENT_P5("pt=%d FIRST 5 BYTES: 0x%x 0x%x 0x%x 0x%x",payload,ptr_msg_i[0],ptr_msg_i[1],ptr_msg_i[2],ptr_msg_i[3]);
  }

} /* grr_decode_rlcmac() */



/*
+------------------------------------------------------------------------------
| Function    : grr_handle_rlcmac_header
+------------------------------------------------------------------------------
| Description : The function grr_handle_rlcmac_header() 
|
| Parameters  : mode_i - possible values: 
|                        PACKET_MODE_PIM/PACKET_MODE_PAM and 
|                         (that means message was received over MPHP)
|                        PACKET_MODE_PTM
|                         (that means message was received over RLCMAC)
|               remark: the reason for introduce mode_i is lost? 
|               ptr_header_i - pointer to mac header of the rlc block
|               fn_i - frame number
|               
+------------------------------------------------------------------------------
*/
GLOBAL T_MSGBUF * grr_handle_rlcmac_header ( T_PACKET_MODE   mode_i, 
                                             T_D_HEADER    * ptr_header_i,
                                             ULONG           fn_i )
{ 

  T_MSGBUF * result = (T_MSGBUF *)(& grr_data->ctrl_msg);

  UBYTE i;
  UBYTE frame_periods;

  TRACE_FUNCTION( "grr_handle_rlcmac_header" );

  if(ptr_header_i->payload EQ CTRL_BLK_NO_OPT)
  {
    /*
     * not segmented control block
     */
    result->l_buf = 22*8;
    result->o_buf = 0;
    memcpy(result->buf, ptr_header_i->ptr_block, (result->l_buf)/8);
    ptr_header_i->pctrl_ack = 3;
  } 
  else if (ptr_header_i->payload EQ CTRL_BLK_OPT)
  { 
    /*
     * segmented control block
     */
    if(ptr_header_i->d_ctrl.ac)
      result->l_buf = (22-2)*8;
    else
      result->l_buf = (22-1)*8;
    
    if(ptr_header_i->d_ctrl.fs AND !ptr_header_i->d_ctrl.rbsn)
    {
      result->o_buf  = 0;
      memcpy(result->buf, ptr_header_i->ptr_block, (result->l_buf)/8);
      ptr_header_i->pctrl_ack = 2;
      /*
      TRACE_EVENT("optional rlc mac header without segmentation");
      */
    }
    else if(ptr_header_i->d_ctrl.fs)
    {
      /*
       * check if the first part is received, otherwise delete
       */
      grr_clean_up_seg_ctrl_blk_tbl();
/*      for(i=grr_data->seg_ctrl_blk.next-1;i NEQ grr_data->seg_ctrl_blk.next;((i--)%8))*/
      for(i = 0;i < SEG_CTRL_BLOCK_SIZE ;i++)
      {
        if(ptr_header_i->d_ctrl.rti EQ grr_data->seg_ctrl_blk.blk[i].rti)
        { 
          /*
           * a part of the recently received control block is saved, 
           * reassabling is possible 
           */
          if(!(ptr_header_i->d_ctrl.rbsn))
          { /*
             * received part is the first part of the segmented block
             * copy recently received as first part
             */
            memcpy(result->buf, ptr_header_i->ptr_block, (result->l_buf)/8);
            /*
             * copy previous saved as second part 
             */
            memcpy(result->buf+(result->l_buf)/8,grr_data->seg_ctrl_blk.blk[i].ctrl_blk.buf, 
                                        (grr_data->seg_ctrl_blk.blk[i].ctrl_blk.l_buf)/8);
          }
          else
          { 
            /*
             * received part is the second part of the segmented block
             * copy saved part as first part
             */
            memcpy(result->buf, grr_data->seg_ctrl_blk.blk[i].ctrl_blk.buf, 
                          (grr_data->seg_ctrl_blk.blk[i].ctrl_blk.l_buf)/8);
            /*
             * copy recently received as second part
             */
            memcpy(result->buf+(grr_data->seg_ctrl_blk.blk[i].ctrl_blk.l_buf)/8, 
                                     ptr_header_i->ptr_block, (result->l_buf)/8);
          }
          result->l_buf += grr_data->seg_ctrl_blk.blk[i].ctrl_blk.l_buf;
          result->o_buf  = 0;
          ptr_header_i->pctrl_ack = 3;
          grr_data->seg_ctrl_blk.blk[i].rti = 0xFF;
          /*
           * break condition: saved part was found 
           */
          break; 
        }
        else
        {
          if(i EQ SEG_CTRL_BLOCK_SIZE)
          {
            result = NULL;  
            TRACE_ERROR("final segment but no identical rti values");
          }
        }
      }
    }
    else
    {
      /*
       * save the first part of a control block
       */
      if(0xff EQ grr_data->seg_ctrl_blk.next)
        grr_data->seg_ctrl_blk.next = 0; /* for safety only (former glumpshack) */
      if(0xFF NEQ grr_data->seg_ctrl_blk.blk[grr_data->seg_ctrl_blk.next].rti)
      {
        grr_clean_up_seg_ctrl_blk_tbl();
        grr_align_seg_ctrl_blk_nxt();
      }
      
      /*
       * calculate the timeout value for T3200 in untis of frames 
       */       
      if( mode_i                  EQ PACKET_MODE_PIM AND
          grr_is_non_drx_period( )           )
      {
        frame_periods = 4 * MAXIMUM( 1, psc_db->gprs_cell_opt.bs_cv_max );
      }
      else
      {
        USHORT drx_p;
        drx_p = meas_im_get_drx_period_frames( );
        frame_periods = MAXIMUM( 1,drx_p );
      }

      grr_data->seg_ctrl_blk.blk[grr_data->seg_ctrl_blk.next].rbsn  = 
                                         ptr_header_i->d_ctrl.rbsn;
      grr_data->seg_ctrl_blk.blk[grr_data->seg_ctrl_blk.next].rti   = 
                                         ptr_header_i->d_ctrl.rti;
      grr_data->seg_ctrl_blk.blk[grr_data->seg_ctrl_blk.next].T3200 = 
        ( fn_i + 4 * frame_periods ) % FN_MAX;
      grr_data->seg_ctrl_blk.blk[grr_data->seg_ctrl_blk.next].ctrl_blk.l_buf = 
                                                               result->l_buf;
      grr_data->seg_ctrl_blk.blk[grr_data->seg_ctrl_blk.next].ctrl_blk.o_buf = 0;
      memcpy(grr_data->seg_ctrl_blk.blk[grr_data->seg_ctrl_blk.next].ctrl_blk.buf, 
                                        ptr_header_i->ptr_block, (result->l_buf/8));
      
/*      (grr_data->seg_ctrl_blk.next++)%8; */
      grr_clean_up_seg_ctrl_blk_tbl();
      grr_align_seg_ctrl_blk_nxt();

      if(ptr_header_i->d_ctrl.rbsn)
        ptr_header_i->pctrl_ack = 1; 
      else
        ptr_header_i->pctrl_ack = 2; 
      result = NULL;
    }    
  }
  else
    {
      TRACE_ERROR(" payload type is not a control block ");
    }
  return(result);

} /* grr_handle_rlcmac_header() */


/*
+------------------------------------------------------------------------------
| Function    : grr_check_address
+------------------------------------------------------------------------------
| Description : The function grr_check_address() this function checks the 
|               message of the message in _decodeCtrlMsg. The Function returns 
|               TRUE if the address is correct.    
|
| Parameters  : msg_type_i - the airmessage type defined in M_GRR.val
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_check_address ( UBYTE msg_type_i,UBYTE tn_i )
{ 

  BOOL result = FALSE;
  TRACE_FUNCTION( "grr_check_address" );

  switch( msg_type_i )
    {
    case D_ACCESS_REJ_c:
      result = grr_check_add_reject(tn_i);
      break;

    case D_QUEUING_NOT_c:
      {
        MCAST(queuing_not,D_QUEUING_NOT);
        result = grr_check_request_reference(&(queuing_not->req_ref_p));
      }
      break;

    case D_TBF_RELEASE_c:
      {
        MCAST(tbf_release,D_TBF_RELEASE);
        result = grr_check_glob_tfi(&(tbf_release->glob_tfi),tn_i );
      }
      break;

    case D_TS_RECONFIG_c:
      {
        MCAST(d_ts_reconfig,D_TS_RECONFIG);
        result = grr_check_glob_tfi( &(d_ts_reconfig->glob_tfi),tn_i );
      }
      break;

    case D_PAGING_REQ_c:
      result = TRUE;
        /*grr_check_page_add();*/
      break;

    case D_UL_ACK_c:
      {
        MCAST(ul_ack,D_UL_ACK);
        if((grr_data->uplink_tbf.tfi EQ ul_ack->ul_tfi) AND
           ((0x80>>tn_i) & grr_data->uplink_tbf.ts_mask))
        {
          result = TRUE;
        }
        else
        {
          TRACE_EVENT_P6("ul_ack adress failed add_tfi=%d, ul_tfi=%d, || tn=%d ->mask=%x curr_mask=%x, st_mask=%x ",
                                        ul_ack->ul_tfi,
                                        grr_data->uplink_tbf.tfi,
                                        tn_i,
                                        0x80>>tn_i,
                                        grr_data->uplink_tbf.ts_mask,
                                        grr_data->uplink_tbf.ts_usage);

        }
      }
      break;

    case D_CELL_CHAN_ORDER_c:
      {
        MCAST(d_cell_chan_order,D_CELL_CHAN_ORDER);
        result = grr_check_add_1( &(d_cell_chan_order->add1),tn_i );
      }
      break;

    case D_MEAS_ORDER_c:
      {
        MCAST(d_meas_order,D_MEAS_ORDER);
        result = grr_check_add_1( &(d_meas_order->add1),tn_i );
      }
      break;

    case D_DL_ASSIGN_c:
      {
        MCAST(d_dl_assign,D_DL_ASSIGN);
        result = grr_check_add_1( &(d_dl_assign->add1),tn_i );
      }
      break;

    case D_POLLING_REQ_c:
      {
        MCAST(d_polling_req,D_POLLING_REQ);
        result = grr_check_add_2( &(d_polling_req->add2),tn_i );
      }
      break;

    case D_CTRL_PWR_TA_c:
      {
        MCAST(d_ctrl_pwr_ta,D_CTRL_PWR_TA);
        result = grr_check_add_4( &(d_ctrl_pwr_ta->add4),tn_i );
      }
      break;

    case D_UL_ASSIGN_c:
      {
        MCAST(d_ul_assign,D_UL_ASSIGN);
        result = grr_check_add_3( &(d_ul_assign->add3),tn_i );
      }
      break;

      /*
       * the following messages do not have a address field 
       * therefore the result is always TRUE
       */
    case PSI_1_c:            
    case PSI_2_c:                
    case PSI_3_c:               
    case PSI_3_BIS_c:
#if defined (REL99) AND defined (TI_PS_FF_EMR)
    case PSI_3_TER_c:
#endif
    case PSI_4_c:           
    case PSI_5_c:
#ifdef REL99
    case PSI_8_c:               
#endif
    case PSI_13_c:               
    case D_DL_DUMMY_c:   
    case D_PDCH_RELEASE_c:
    case D_PRACH_PAR_c:       
      result = TRUE;
      break;

    default:
      TRACE_ERROR("grr_check_address with invalid message type");
      break;
  } /* switch (msg_type_i) */
  
  return(result); 
  
} /* grr_check_address() */


/*
+------------------------------------------------------------------------------
| Function    : grr_increase_dsc
+------------------------------------------------------------------------------
| Description : The function grr_increase_dsc increases dsc by 1
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/          
GLOBAL void grr_increase_dsc ( void )
{
  TRACE_FUNCTION( "grr_increase_dsc" );
  
  grr_data->pg.dsc++;

  if(grr_data->pg.dsc > grr_data->pg.initial_dsc)
  {
    grr_data->pg.dsc = grr_data->pg.initial_dsc;
  }

  GRR_EM_SET_DSC_VAL(grr_data->pg.dsc);
  
#ifdef _SIMULATION_
  TRACE_EVENT_P1( "DSC: %d", grr_data->pg.dsc );
#endif /* #ifdef _SIMULATION_ */
}/* grr_increase_dsc*/

/*
+------------------------------------------------------------------------------
| Function    : grr_decrease_dsc
+------------------------------------------------------------------------------
| Description : The function grr_decrease_dsc decreases dsc by 4
|
| Parameters  : return BOOL: indicates whether downlink siganlling failure 
|               occured or not
|
+------------------------------------------------------------------------------
*/          
GLOBAL BOOL grr_decrease_dsc ( void )
{
  TRACE_FUNCTION( "grr_decrease_dsc" );
  
  if( grr_data->pg.dsc <= 4 )
  {
    grr_data->pg.dsc  = 0;
  }
  else
  {
    grr_data->pg.dsc -= 4;
  }

  GRR_EM_SET_DSC_VAL(grr_data->pg.dsc);

#ifdef _SIMULATION_
  TRACE_EVENT_P1( "DSC: %d", grr_data->pg.dsc );
#endif /* #ifdef _SIMULATION_ */

  return( grr_data->pg.dsc EQ 0 );
}/* grr_decrease_dsc*/

/*
+------------------------------------------------------------------------------
| Function    : grr_t_status
+------------------------------------------------------------------------------
| Description : This function returns the remaining time in milliseconds.
|               A value of 0L is returned in case the timer is not existing or
|               not running.
|
| Parameters  : t_index : timer index
|
+------------------------------------------------------------------------------
*/
GLOBAL T_TIME grr_t_status( USHORT t_index )
{
  T_TIME t_time = 0L;
  
  TRACE_FUNCTION( "grr_t_status" );

  vsi_t_status( GRR_handle, t_index, &t_time );

  return( t_time );
} /* grr_t_status */ 

/*
+------------------------------------------------------------------------------
| Function    : grr_get_nc_mval
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL T_NC_MVAL* grr_get_nc_mval ( USHORT arfcn, UBYTE bsic, UBYTE *idx )
{
  UBYTE      i;
  T_NC_MVAL *nc_mval = NULL;

  TRACE_FUNCTION( "grr_get_nc_mval" );

  for( i = 0; i < MAX_NR_OF_NC_MVAL AND nc_mval EQ NULL; i++ )
  {
    nc_mval = &grr_data->db.nc_mval_list.nc_mval[i];
    *idx    = i;

    if( bsic EQ RRGRR_INVALID_BSIC )
    {
      if( nc_mval->arfcn NEQ arfcn )
      {
        nc_mval = NULL;
      }
    }
    else
    {
      if( nc_mval->arfcn NEQ arfcn OR nc_mval->sync_info.bsic NEQ bsic )
      {
        nc_mval = NULL;
      }
    }
  }

  return( nc_mval );
} /* grr_get_nc_mval */ 

/*
+------------------------------------------------------------------------------
| Function    : grr_get_ncell_info
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL T_ncell_info* grr_get_ncell_info ( USHORT arfcn, UBYTE bsic )
{
  UBYTE         i;
  T_ncell_info *ncell_info = NULL;

  TRACE_FUNCTION( "grr_get_ncell_info" );

  for( i = 0; i < grr_data->db.nc_ref_lst.number AND ncell_info EQ NULL; i++ )
  {
    ncell_info = grr_data->db.nc_ref_lst.info[i];

    if( bsic EQ RRGRR_INVALID_BSIC )
    {
      if( ncell_info->arfcn NEQ arfcn )
      {
        ncell_info = NULL;
      }
    }
    else
    {
      if( ncell_info->arfcn NEQ arfcn OR ncell_info->bsic NEQ bsic )
      {
        ncell_info = NULL;
      }
    }
  }

  return( ncell_info );
} /* grr_get_ncell_info */ 

/*
+------------------------------------------------------------------------------
| Function    : grr_set_pbcch
+------------------------------------------------------------------------------
| Description : This function sets pbcch presence. It is no more handled 
|               in PSI only.
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_set_pbcch ( BOOL pbcch_presence )
{
  TRACE_FUNCTION( "grr_set_pbcch" );

  psc_db->pbcch.bcch.pbcch_present = pbcch_presence;

#if !defined (NTRACE)

  if( grr_data->cs.v_crp_trace EQ TRUE )
  {
    TRACE_EVENT_P3( "database: psc = %d, PBCCH presence: %d %d",
                    grr_get_db_num( psc_db ), 
                    grr_data->sc_db_1.pbcch.bcch.pbcch_present, 
                    grr_data->sc_db_2.pbcch.bcch.pbcch_present );
  }

#endif /* #if !defined (NTRACE) */

} /* grr_set_pbcch */

/*
+------------------------------------------------------------------------------
| Function    : grr_set_pg_nmo
+------------------------------------------------------------------------------
| Description : This function sets NMO for paging
|               If NMO II and PBCCH present, then assume paging coordination
|               is used. The MS will act as NMO I mobile with PBCCH
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_set_pg_nmo(void)
{
  if( psc_db->pbcch.bcch.pbcch_present
      AND 
      psc_db->cell_info_for_gmm.cell_info.net_mode EQ GMMRR_NET_MODE_II )
  {
    grr_data->pg.nmo = GMMRR_NET_MODE_I;
    TRACE_EVENT("Network is NMO II, but with PBCCH. The MS will act as NMO I (paging coordination)");
  }
  else
    grr_data->pg.nmo = psc_db->cell_info_for_gmm.cell_info.net_mode;
}/*grr_set_pg_nmo*/

/*
+------------------------------------------------------------------------------
| Function    : grr_set_freq_par
+------------------------------------------------------------------------------
| Description :
|
| Parameters  :
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_set_freq_par ( T_p_frequency_par *freq_par )
{
  TRACE_FUNCTION( "grr_set_freq_par" );

  freq_par->p_chan_sel = grr_data->tc.freq_set.freq_par.p_chan_sel;

  if( grr_data->tc.freq_set.freq_par.p_chan_sel.hopping )
  {
    freq_par->p_freq_list = grr_data->tc.freq_set.freq_par.p_freq_list;
  }
  else
  {
    memset( &freq_par->p_freq_list, 0, sizeof( freq_par->p_freq_list ) );
  }
} /* grr_set_freq_par */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_pccch_freq_par
+------------------------------------------------------------------------------
| Description :
|
| Parameters  :
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_get_pccch_freq_par ( UBYTE          pccch_group, 
                                     T_p_chan_sel  *chan_sel,
                                     T_p_freq_list *freq_list )
{
  BOOL result = FALSE;

  TRACE_FUNCTION( "grr_get_pccch_freq_par" );

  if( pccch_group > psc_db->paging_group.kc - 1 )
  {
    TRACE_ERROR( "pccch_group > psc_db->paging_group.kc - 1" );

    return( result );
  }

  if( psc_db->paging_group.pccch[pccch_group].is_static )
  {
    chan_sel->hopping       = 0;
    chan_sel->p_rf_ch.arfcn = psc_db->paging_group.pccch[pccch_group].arfcn;

    result = TRUE;
  }
  else
  {
    result = 
      grr_create_freq_list(  psc_db->paging_group.pccch[pccch_group].ma_num,
                             psc_db->paging_group.pccch[pccch_group].maio,
                             chan_sel,
                             freq_list );
  }

  return( result );
} /* grr_get_pccch_freq_par */

/*
+------------------------------------------------------------------------------
| Function    : grr_cgrlc_pwr_ctrl_cnf
+------------------------------------------------------------------------------
| Description : Handles the primitive CGRLC_PWR_CTRL_CNF
|
| Parameters  : cgrlc_pwr_ctrl_cnf - Ptr to primitive payload  
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_cgrlc_pwr_ctrl_cnf ( T_CGRLC_PWR_CTRL_CNF *cgrlc_pwr_ctrl_cnf )
{ 
  TRACE_FUNCTION( "grr_cgrlc_pwr_ctrl_cnf" );

  PFREE( cgrlc_pwr_ctrl_cnf );

} /* grr_cgrlc_pwr_ctrl_cnf() */

/*
+------------------------------------------------------------------------------
| Function    : grr_cgrlc_pwr_ctrl_req
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : void
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_cgrlc_pwr_ctrl_req( BOOL v_c_value )
{
  TRACE_FUNCTION( "grr_cgrlc_pwr_ctrl_req" );

  {
    PALLOC( cgrlc_pwr_ctrl_req, CGRLC_PWR_CTRL_REQ );

    grr_prcs_pwr_ctrl( &cgrlc_pwr_ctrl_req->pwr_ctrl, v_c_value );

    if( cgrlc_pwr_ctrl_req->pwr_ctrl.v_pwr_ctrl_param      EQ FALSE AND
        cgrlc_pwr_ctrl_req->pwr_ctrl.v_glbl_pwr_ctrl_param EQ FALSE AND
        cgrlc_pwr_ctrl_req->pwr_ctrl.v_freq_param          EQ FALSE AND
        cgrlc_pwr_ctrl_req->pwr_ctrl.v_c_value             EQ FALSE     )
    {
      PFREE( cgrlc_pwr_ctrl_req );
    }
    else
    {
      PSEND( hCommGRLC, cgrlc_pwr_ctrl_req );
    }
  }
} /* grr_cgrlc_pwr_ctrl_req() */

/*
+------------------------------------------------------------------------------
| Function    : grr_prcs_pwr_ctrl
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  :
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_prcs_pwr_ctrl ( T_CGRLC_pwr_ctrl *pwr_ctrl, BOOL v_c_value )
{
  USHORT pdch_arfcn;

  TRACE_FUNCTION( "grr_prcs_pwr_ctrl" );

  if( grr_data->tc.v_freq_set )
  {
    /*
     * Apply the ARFCN value obtained from the assignment message.
     *
     * When getting the ARFCN value, reconvert it to the absolute
     * ARFCN value, since grr_data->tc has L1 mapped ARFCN values.
     */
    if( grr_data->tc.freq_set.freq_par.p_chan_sel.hopping )
    {
      /* If hopping is enabled, then take the first ARFCN value from the assignment */
      pdch_arfcn = 
        grr_l1_arfcn_to_g23
          ( grr_data->tc.freq_set.freq_par.p_freq_list.p_rf_chan_no.p_radio_freq[0] );
    }
    else 
    {
      /* If hopping is disabled, then take the ARFCN value from the assignment */
      pdch_arfcn = 
        grr_l1_arfcn_to_g23
          ( grr_data->tc.freq_set.freq_par.p_chan_sel.p_rf_ch.arfcn );
    }
  }
  else
  {
    pdch_arfcn = psc_db->pbcch.bcch.arfcn;
  }
   
  if( grr_data->pwr_ctrl_valid_flags.v_pwr_ctrl_param )
  {
    T_CGRLC_pwr_ctrl_param *pwr_ctrl_param = &pwr_ctrl->pwr_ctrl_param;

    if( psc_db->v_pwr_par EQ TRUE AND psc_db->pwr_par.v_alpha EQ TRUE )
    {
      pwr_ctrl_param->alpha = psc_db->pwr_par.alpha;
    }
    else
    {
      pwr_ctrl_param->alpha = CGRLC_ALPHA_INVALID;
    }
        
    {
      UBYTE i;

      for( i = 0; i < CGRLC_MAX_TIMESLOTS; i++ )
      {
        if( psc_db->v_pwr_par                   EQ TRUE AND
            psc_db->pwr_par.gamma_tn[i].v_gamma EQ TRUE     )
        {
          pwr_ctrl_param->gamma_ch[i] = psc_db->pwr_par.gamma_tn[i].gamma;
        }
        else
        {
          pwr_ctrl_param->gamma_ch[i] = CGRLC_GAMMA_INVALID;
        }
      }
    }
  }

  if( grr_data->pwr_ctrl_valid_flags.v_glbl_pwr_ctrl_param )
  {
    T_CGRLC_glbl_pwr_ctrl_param *glbl_pwr_ctrl_param =
                                                &pwr_ctrl->glbl_pwr_ctrl_param;
    
    T_MS_PWR_CAP mspc;

    glbl_pwr_ctrl_param->alpha        = psc_db->g_pwr_par.alpha;
    glbl_pwr_ctrl_param->t_avg_t      = psc_db->g_pwr_par.t_avg_t;
    glbl_pwr_ctrl_param->pb           = psc_db->g_pwr_par.pb;
    glbl_pwr_ctrl_param->pc_meas_chan = psc_db->g_pwr_par.pc_meas_chan;
    glbl_pwr_ctrl_param->pwr_max      = grr_get_pms_max
                                          (  pdch_arfcn,
                                             grr_data->meas.pwr_offset,
                                             psc_db->scell_par.cr_par_1.cr_pow_par.gprs_ms_txpwr_max_cch,
                                            &mspc );
  }

  if( grr_data->pwr_ctrl_valid_flags.v_freq_param )
  {
    T_CGRLC_freq_param *freq = &pwr_ctrl->freq_param;

    T_MS_PWR_CAP mspc;

    grr_get_ms_pwr_cap(  pdch_arfcn, grr_data->meas.pwr_offset, &mspc );
    
    freq->bcch_arfcn   = grr_g23_arfcn_to_l1( psc_db->pbcch.bcch.arfcn );
    freq->pdch_hopping = ( grr_data->tc.v_freq_set                           AND 
                           grr_data->tc.freq_set.freq_par.p_chan_sel.hopping     );
    freq->pdch_band    = mspc.band_ind;
  }
      
  if( v_c_value )
  {
    if( grr_data->pwr_ctrl_valid_flags.v_c_value )
    {
      meas_c_get_c_value( &pwr_ctrl->c_value );
    }

    pwr_ctrl->v_c_value           = grr_data->pwr_ctrl_valid_flags.v_c_value;
    grr_data->pwr_ctrl_valid_flags.v_c_value           = FALSE;
  }
  else
  {
    pwr_ctrl->v_c_value           = v_c_value;
  }

  pwr_ctrl->v_pwr_ctrl_param      = grr_data->pwr_ctrl_valid_flags.v_pwr_ctrl_param;
  pwr_ctrl->v_glbl_pwr_ctrl_param = grr_data->pwr_ctrl_valid_flags.v_glbl_pwr_ctrl_param;
  pwr_ctrl->v_freq_param          = grr_data->pwr_ctrl_valid_flags.v_freq_param;

  grr_data->pwr_ctrl_valid_flags.v_pwr_ctrl_param      = FALSE;
  grr_data->pwr_ctrl_valid_flags.v_glbl_pwr_ctrl_param = FALSE;
  grr_data->pwr_ctrl_valid_flags.v_freq_param          = FALSE;

} /* grr_prcs_pwr_ctrl */

/*
+------------------------------------------------------------------------------
| Function    : grr_set_cell_info_service
+------------------------------------------------------------------------------
| Description :
|
| Parameters  :
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_set_cell_info_service( void )
{
  TRACE_FUNCTION( "grr_set_cell_info_service" );

  if     ( psc_db->cell_info_for_gmm.gprs_service  EQ GPRS_SERVICE_NONE       )
  {
    psc_db->cell_info_for_gmm.cell_info.service_state = GMMRR_SERVICE_NONE;
  }
  else if( psc_db->cell_info_for_gmm.gprs_service  EQ GPRS_SERVICE_FULL   AND
           psc_db->cell_info_for_gmm.access_status EQ GPRS_ACCESS_ALLOWED     )
  {
    psc_db->cell_info_for_gmm.cell_info.service_state = GMMRR_SERVICE_FULL;
  }
  else
  {
    psc_db->cell_info_for_gmm.cell_info.service_state = GMMRR_SERVICE_LIMITED;
  }
} /* grr_set_cell_info_service */

/*
+------------------------------------------------------------------------------
| Function    : grr_is_packet_idle_mode
+------------------------------------------------------------------------------
| Description :
|
| Parameters  :
|
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_is_packet_idle_mode( void )
{
  /*
   * The entity GRR as a whole is in packet idle mode in case the three state
   * machines below are in packet idle mode in detail.
   *
   * There are state transitions, in which one of these state machines is in
   * packet idle mode, but the others are in different states (e.g. during
   * processing of RRGRR_STOP_TASK_REQ/CNF or MPHP_ASSIGNMENT_REQ/CON). That's
   * why all three states shall be considered.
   */

  return( GET_STATE( CTRL_GLBL ) EQ GLBL_PCKT_MODE_IDLE AND
          GET_STATE( TC        ) EQ TC_PIM              AND 
          GET_STATE( CPAP      ) EQ CPAP_IDLE               );

} /* grr_is_packet_idle_mode */

/*
+------------------------------------------------------------------------------
| Function    : grr_clip_rxlev
+------------------------------------------------------------------------------
| Description : This function is used to clip received signal level values.
|
| Parameters  : clipp  - pointer to clipped received signal level values
|               rxlev  - pointer to received signal level values
|               number - number of received signal level values
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_clip_rxlev ( UBYTE *clipp, UBYTE *rxlev, UBYTE number )
{ 
  UBYTE i; /* used for counting */
  
  TRACE_FUNCTION( "grr_clip_rxlev" );

  for( i = 0; i < number; i++ )
  { 
    if( (signed char)( rxlev[i] ) <   CGRLC_RXLEV_MIN  AND
                       rxlev[i]   NEQ CGRLC_RXLEV_NONE     )
    {
      clipp[i] = CGRLC_RXLEV_MIN;
    }
    else if ( (signed char)( rxlev[i] ) > CGRLC_RXLEV_MAX )
    {
      clipp[i] = CGRLC_RXLEV_MAX;
    }
    else if( rxlev[i] EQ CGRLC_RXLEV_NONE )
    {
      clipp[i] = CGRLC_RXLEV_NONE;
    }
    else
    {
      clipp[i] = rxlev[i];
    }
  }
} /* grr_clip_rxlev() */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_pms_max
+------------------------------------------------------------------------------
| Description : This function is used to ...
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE grr_get_pms_max ( USHORT        arfcn,
                               UBYTE         pwr_offset,
                               UBYTE         gprs_ms_txpwr_max_cch,
                               T_MS_PWR_CAP *mspc                   )
{ 
  UBYTE pms_max; /* maximum output power applied by the MS */
  
  TRACE_FUNCTION( "grr_get_pms_max" ); 

  grr_get_ms_pwr_cap( arfcn, pwr_offset, mspc );

  pms_max = mspc->pwr_offset + mspc->p_control[gprs_ms_txpwr_max_cch];
  pms_max = MINIMUM( pms_max, mspc->p[mspc->ms_power] );

  return( pms_max );

} /* grr_get_pms_max() */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_ms_txpwr_max_cch
+------------------------------------------------------------------------------
| Description : ...
|
| Parameters  : ...
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE grr_get_ms_txpwr_max_cch ( USHORT arfcn,
                                        UBYTE  pwr_offset,
                                        UBYTE  gprs_ms_txpwr_max_cch )
{ 
  T_MS_PWR_CAP mspc;    /* MS power capabilities                  */
  UBYTE        pms_max; /* maximum output power applied by the MS */

  TRACE_FUNCTION( "grr_get_ms_txpwr_max_cch" );

  pms_max = grr_get_pms_max( arfcn, pwr_offset, gprs_ms_txpwr_max_cch, &mspc );

  return( grr_get_pcl( mspc.p_control, pms_max ) );

} /* grr_get_ms_txpwr_max_cch() */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_ms_pwr_cap
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_get_ms_pwr_cap ( USHORT        arfcn,
                                 UBYTE         pow_offset,
                                 T_MS_PWR_CAP *mspc        )
{ 
  TRACE_FUNCTION( "grr_get_ms_pwr_cap" );
  
  switch( std )
  {
    case STD_850:
      grr_get_ms_pwr_cap_gsm900
        ( grr_get_power_class( IDX_PWRCLASS_850 ), mspc );
      break;

    case STD_900:
    case STD_EGSM:
      grr_get_ms_pwr_cap_gsm900
        ( grr_get_power_class( IDX_PWRCLASS_900 ), mspc );
      break;

    case STD_1900:
      grr_get_ms_pwr_cap_pcs1900
        ( grr_get_power_class( IDX_PWRCLASS_1900 ), pow_offset, mspc );
      break;

    case STD_1800:
      grr_get_ms_pwr_cap_dcs1800
        ( grr_get_power_class( IDX_PWRCLASS_1800 ), pow_offset, mspc );
      break;

    case STD_DUAL:
      /*
       * For dualband mobiles the calculation depends on the channel number
       */
      if( arfcn < LOW_CHANNEL_1800 )
      {
        /*
         * All GSM 900
         */
        grr_get_ms_pwr_cap_gsm900
          ( grr_get_power_class( IDX_PWRCLASS_900 ), mspc );
      }
      else
      {
        /*
         * All DCS 1800 channels
         */
        grr_get_ms_pwr_cap_dcs1800
          ( grr_get_power_class( IDX_PWRCLASS_1800 ), pow_offset, mspc );
      }
      break;

    case STD_DUAL_EGSM:
      if( arfcn < LOW_CHANNEL_1800  OR
          arfcn > HIGH_CHANNEL_1800    )
      {
        /*
         * All GSM 900 and E-GSM channels
         */
        grr_get_ms_pwr_cap_gsm900
          ( grr_get_power_class( IDX_PWRCLASS_900 ), mspc );
      }
      else
      {
        /*
         * All DCS 1800 channels
         */
        grr_get_ms_pwr_cap_dcs1800
          ( grr_get_power_class( IDX_PWRCLASS_1800 ), pow_offset, mspc );
      }
      break;

    case STD_DUAL_US:
      if( arfcn < LOW_CHANNEL_1900 )
      {
        /*
         * All GSM 850 channels
         */
        grr_get_ms_pwr_cap_gsm900
          ( grr_get_power_class( IDX_PWRCLASS_850 ), mspc );
      }
      else
      {
        /*
         * All PCS 1900 channels
         */
        grr_get_ms_pwr_cap_pcs1900
          ( grr_get_power_class( IDX_PWRCLASS_1900 ), pow_offset, mspc );
      }
      break;

#ifdef TI_PS_FF_QUAD_BAND_SUPPORT
      case STD_850_1800:
      if( arfcn < LOW_CHANNEL_1800 )
      {
        /*
         * All GSM 850 channels
         */
        grr_get_ms_pwr_cap_gsm900
          ( grr_get_power_class( IDX_PWRCLASS_850 ), mspc );
      }
      else
      {
        /*
         * All DCS 1800 channels
         */
        grr_get_ms_pwr_cap_dcs1800
          ( grr_get_power_class( IDX_PWRCLASS_1800 ), pow_offset, mspc );
      }
      break;

      case STD_900_1900:
      if( arfcn >= LOW_CHANNEL_1900  AND
          arfcn <= HIGH_CHANNEL_1900 )
      {
        /*
         * All PCS 1900 channels
         */
        grr_get_ms_pwr_cap_pcs1900
          ( grr_get_power_class( IDX_PWRCLASS_1900 ), pow_offset, mspc );

      }
      else
      {
        /*
         * All GSM 900 and E-GSM channels
         */
        grr_get_ms_pwr_cap_gsm900
          ( grr_get_power_class( IDX_PWRCLASS_900 ), mspc );
      }
      break;
        
      case STD_850_900_1800:
      if( arfcn >= LOW_CHANNEL_1800  AND
          arfcn <= HIGH_CHANNEL_1800 )
      {
        /*
         * All DCS 1800 channels
         */
        grr_get_ms_pwr_cap_dcs1800
          ( grr_get_power_class( IDX_PWRCLASS_1800 ), pow_offset, mspc );

      }
      else
      {
        if((arfcn >= LOW_CHANNEL_850) AND (arfcn <= HIGH_CHANNEL_850))
        {
          /*
           * All GSM 850 channels
           */
          grr_get_ms_pwr_cap_gsm900
            ( grr_get_power_class( IDX_PWRCLASS_850 ), mspc );
        }
        else
        {
          /*
           * All GSM 900 and E-GSM channels
           */
          grr_get_ms_pwr_cap_gsm900
            ( grr_get_power_class( IDX_PWRCLASS_900 ), mspc );
        }
      }
      break;

      case STD_850_900_1900:
      if( arfcn >= LOW_CHANNEL_1900  AND
          arfcn <= HIGH_CHANNEL_1900 )
      {
        /*
         * All PCS 1900 channels
         */
        grr_get_ms_pwr_cap_pcs1900
          ( grr_get_power_class( IDX_PWRCLASS_1900 ), pow_offset, mspc );

      }
      else
      {
        if((arfcn >= LOW_CHANNEL_850) AND (arfcn <= HIGH_CHANNEL_850))
        {
          /*
           * All GSM 850 channels
           */
          grr_get_ms_pwr_cap_gsm900
            ( grr_get_power_class( IDX_PWRCLASS_850 ), mspc );
        }
        else
        {
          /*
           * All GSM 900 and E-GSM channels
           */
          grr_get_ms_pwr_cap_gsm900
            ( grr_get_power_class( IDX_PWRCLASS_900 ), mspc );
        }
      }
      break;

      default :
        TRACE_EVENT_P1 (" std : %d",std);
        break;
#endif
  }
} /* grr_get_ms_pwr_cap */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_ms_pwr_cap_gsm900
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_get_ms_pwr_cap_gsm900 ( UBYTE         rf_pow_cap,
                                        T_MS_PWR_CAP *mspc        )
{ 
  TRACE_FUNCTION( "grr_get_ms_pwr_cap_gsm900" );

  /*
   * The table for the power class conversion in GSM 900
   */
  mspc->p          = p_gsm;

  /*
   * The table for the GPRS_MAX_TXPWR_CCCH conversion in GSM 900
   */
  mspc->p_control  = p_control_gsm;

  /*
   * The MS power class is defined in classmark 2 of the non-volatile
   * memory data for GSM 900.
   */
  mspc->ms_power   = rf_pow_cap - 1;

  /*
   * For a power class 3 mobile in the DCS or PCS frequency 
   * standard an additional power offset can be defined
   *
   * Note: This parameter is only available for the serving cell
   *
   */
  mspc->pwr_offset = 0;

  /*
   * Maximum allowed output power in the cell
   */
  mspc->pwr_max    = p_control_gsm[MAX_PCL_GSM900];
   
  /*
   * Minimum required output power in the cell 
   */
  mspc->pwr_min    = p_control_gsm[MIN_PCL_GSM900];

  mspc->gamma_0    = GAMMA_0_GSM900;

  mspc->band_ind   = CGRLC_GSM_900;
} /* grr_get_ms_pwr_cap_gsm900 */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_ms_pwr_cap_dcs1800
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_get_ms_pwr_cap_dcs1800 ( UBYTE         rf_pow_cap,
                                         UBYTE         pow_offset,
                                         T_MS_PWR_CAP *mspc        )
{ 
  TRACE_FUNCTION( "grr_get_ms_pwr_cap_dcs1800" );

  mspc->p          = p_dcs;
  mspc->p_control  = p_control_dcs;
  mspc->ms_power   = rf_pow_cap - 1;
  mspc->pwr_offset = ( ( rf_pow_cap EQ POWER_CLASS_3 ) ? 2 * pow_offset : 0 );
  mspc->pwr_max    = p_control_dcs[MAX_PCL_DCS1800];
  mspc->pwr_min    = p_control_dcs[MIN_PCL_DCS1800];
  mspc->gamma_0    = GAMMA_0_DCS1800;
  mspc->band_ind   = CGRLC_DCS_1800;
} /* grr_get_ms_pwr_cap_dcs1800 */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_ms_pwr_cap_pcs1900
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_get_ms_pwr_cap_pcs1900 ( UBYTE         rf_pow_cap,
                                         UBYTE         pow_offset,
                                         T_MS_PWR_CAP *mspc        )
{ 
  TRACE_FUNCTION( "grr_get_ms_pwr_cap_pcs1900" );

  mspc->p          = p_pcs;
  mspc->p_control  = p_control_pcs;
  mspc->ms_power   = rf_pow_cap - 1;
  mspc->pwr_offset = ( ( rf_pow_cap EQ POWER_CLASS_3 ) ? 2 * pow_offset : 0 );
  mspc->pwr_max    = p_control_pcs[MAX_PCL_PCS1900];
  mspc->pwr_min    = p_control_pcs[MIN_PCL_PCS1900];
  mspc->gamma_0    = GAMMA_0_PCS1900;
  mspc->band_ind   = CGRLC_PCS_1900;
} /* grr_get_ms_pwr_cap_pcs1900 */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_power_class
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : 
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE grr_get_power_class ( UBYTE index )
{
  T_rf_cap *rf_cap      = rr_csf_get_rf_capability( );
  UBYTE     power_class;

  TRACE_FUNCTION( "grr_get_power_class" );

  if( rf_cap NEQ NULL )
  {
    power_class = rf_cap->rf_power.pow_class4[index].pow_class;
  }
  else
  {
    power_class = POWER_CLASS_1;

    TRACE_ERROR( "grr_get_power_class: RF capabilities invalid" );
  }

  return( power_class );

} /* grr_get_power_class */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_pcl
+------------------------------------------------------------------------------
| Description : This function is used to convert the nominal output power to 
|               the power control level
|
| Parameters  : p_ctrl - pointer to table of power control levels
|               nop    - nominal output power
|
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE grr_get_pcl ( UBYTE const *p_ctrl,
                           SHORT        nop )
{ 
  UBYTE pcl = 0; /* power control level */

  TRACE_FUNCTION( "grr_get_pcl" ); 

  /* get power control level */
  while( nop < (SHORT)p_ctrl[pcl] - 1 OR nop >= (SHORT)p_ctrl[pcl] + 1 ) pcl++;

  return( pcl );

} /* grr_get_pcl() */

/*
+------------------------------------------------------------------------------
| Function    : grr_validate_ma_num_in_freq_par
+------------------------------------------------------------------------------
| Description : Validates MA_NUM in indirect encoding.
|               This validation is required only when
|               freq parameters are received with indirect
|               encoding.
|               Change mark received with Frequency parameters is compared
|               with the stored change mark for PSI2/PSI13/SI13 to determine
|               if the mobile allocation stored in these messages could be used.
|
|               Frequency parameters received in an assignment message could refer
|               to GPRS mobile allocation received in a previous assignment message
|               by using MA_NUM = 15 in indirect encoding. Frequency parameters
|               received in non-assignment message( For example PSI 8 or PSI 14)
|               cannot refer to GPRS mobile received in a previous message.
|               This validation is done using the second parameter.
|
|               This function should be used before using the GPRS mobile allocation
|               referred in freq_par.
| Parameters  : freq_par - points to the frequency parameter structure
|               received in system information/some assignment message.
|
|               msg_type - identifies the type of message in which freq par
|                          was received. Two values are possible.
|                          GRR_FREQ_PARAM_RECEIVED_IN_ASSIGNMENT 0
|                          GRR_FREQ_PARAM_RECEIVED_IN_NON_ASSIGNMENT 1
| Return value : True - if validation sucessful.
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_validate_ma_num_in_freq_par(const T_freq_par *freq_par,UBYTE msg_type)
{
  BOOL result;

  TRACE_FUNCTION("grr_validate_ma_num_in_freq_par");

  if(MA_NUMBER_4_ASSIGNMENT EQ freq_par->indi_encod.ma_num)
    {
      if(GRR_FREQ_PARAM_RECEIVED_IN_ASSIGNMENT NEQ msg_type )
        {
          TRACE_ERROR("Frequency parameter in a non assignment message");
          TRACE_ERROR("cannot have ma_num==MA_NUMBER_4_ASSIGNMENT");
          result = FALSE;
        }
      else if( (MA_NUMBER_4_ASSIGNMENT EQ psc_db->gprs_ms_alloc_in_assignment.ma_num) AND
               (!freq_par->indi_encod.v_chamge_ma_sub)                )
      {
        result = TRUE;
      }
      else
      {
        TRACE_ERROR("mobile allocation in assignment wrong");
        result = FALSE;
      }
    }
    else if(MA_NUMBER_4_PSI13_OR_CELL_ALLOC EQ freq_par->indi_encod.ma_num)
    {
      if( ( (freq_par->indi_encod.v_chamge_ma_sub      ) AND
            (freq_par->indi_encod.chamge_ma_sub.cm1 EQ
             psc_db->psi13_params.si13_change_mark                 )
          ) OR
          ( (freq_par->indi_encod.chamge_ma_sub.v_cm2  ) AND
            (freq_par->indi_encod.chamge_ma_sub.cm2 EQ
             psc_db->psi13_params.si13_change_mark                 )
          ) OR
          (
            !freq_par->indi_encod.v_chamge_ma_sub     AND
            !freq_par->indi_encod.chamge_ma_sub.v_cm2
          ))
      {
        result = TRUE;
      }
      else
      {
        TRACE_ERROR("wrong si13 change mark value");
        result = FALSE;
      }
    }
    else
    {
      if( ( (freq_par->indi_encod.v_chamge_ma_sub      ) AND
            (freq_par->indi_encod.chamge_ma_sub.cm1 EQ
             psc_db->psi2_params.psi2_change_mark                  )
          ) OR
          ( (freq_par->indi_encod.chamge_ma_sub.v_cm2  ) AND
            (freq_par->indi_encod.chamge_ma_sub.cm2 EQ
             psc_db->psi2_params.psi2_change_mark                  )
          ) OR
          (
            !freq_par->indi_encod.v_chamge_ma_sub     AND
            !freq_par->indi_encod.chamge_ma_sub.v_cm2
          ))
      {
        result = TRUE;
      }
      else
      {
        TRACE_ERROR("wrong psi2 change mark value");
        TRACE_EVENT_P5("psi2cm:%d vcm1:%d cm1:%d vcm2:%d cm2:%d",
          psc_db->psi2_params.psi2_change_mark,
          freq_par->indi_encod.v_chamge_ma_sub,
          freq_par->indi_encod.chamge_ma_sub.cm1,
          freq_par->indi_encod.chamge_ma_sub.v_cm2,
          freq_par->indi_encod.chamge_ma_sub.cm2);
        result = FALSE;
      }
    }
    return result;
} /* grr_validate_ma_num_in_freq_par */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_gprs_ma
+------------------------------------------------------------------------------
| Description : ma_num identifies the GPRS mobile allocation received
|               in PSI 2, PSI 13 or the previous assignment message.
|               This function returns the matching pointer to the
|               GPRS Mobile allocation IE.
|
| Parameters  : ma_num - 0 to 13 - gprs mobile allocation received in PSI 2
|                             14 gprs mobile allocation received in Si13/PSI13
|                             15 GPRS mobile allocation received in previous
|                                assignment message.
| Return value : Pointer to appropriate GPRS MA stored in psc db.
+------------------------------------------------------------------------------
*/
GLOBAL T_gprs_ms_alloc_ie* grr_get_gprs_ma(UBYTE ma_num)
{
  USHORT n = 0;
  T_gprs_ms_alloc_ie *gp_ma = NULL;
  TRACE_FUNCTION( "grr_get_gprs_ma" );
  if(ma_num > MA_NUMBER_4_ASSIGNMENT)
  {
    TRACE_ERROR("ma_num > MA_NUMBER_4_ASSIGNMENT");
    return NULL;
  }

  /*
   * Get the GPRS Mobile Allocation IE corresponding to the ma_num
   */
  switch(ma_num)
  {
    /* MA_NUMBER used to reference a MA received in a previous assignent */
    case MA_NUMBER_4_ASSIGNMENT:
      if( psc_db->gprs_ms_alloc_in_assignment.ma_num NEQ NOT_SET )
      {
        gp_ma = &psc_db->gprs_ms_alloc_in_assignment.gprs_ms_alloc_ie;
      }
      break;

    /* MA_NUMBER used to reference a Mobile Allocation
     * (MA) received in PSI13, which may referenced from
     * an assignment message or which referes to the cell
     * allocation defined for the cell in SI1 or PSI2
     */
    case MA_NUMBER_4_PSI13_OR_CELL_ALLOC:

      /*lint -fallthrough*/

    /* GPRS Mobile Allocations received in PSI2 and/or PSI13 values 0...13 */
    default:
      for(n = 0; n < MAX_GPRS_MS_ALLOC; n++)
      {
        if( psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num EQ ma_num)
        {
          gp_ma = &psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie;
          break;
        }
      }
      break;
  }
   return gp_ma;
} /* grr_get_gprs_ma */

/*
+------------------------------------------------------------------------------
| Function    : grr_cnv_freq_para_in_assignment_direct_enc_2
+------------------------------------------------------------------------------
| Description : This function decodes the frequency parametes received
|               in direct encoding2 form. It constructs the Mobile allocation
|               list as required by TI L1 MPHP primitives.
|
| Parameters  :
|
| NOTE: THIS FUNCTION USES THE LOCAL TEMPORARY ARRAYS - _local_rfl_contents AND
|      _local_dummy_list. These are use by grr_cnv_freq_para_in_psi8_direct_enc_2()
|       also. These two functions are placed in the same object module to avoid
|       the need for two copies of temporary arrays.
+------------------------------------------------------------------------------
*/

GLOBAL BOOL grr_cnv_freq_para_in_assignment_direct_enc_2
             (T_p_frequency_par *frequency_par,T_freq_par *freq_par)
{
   TRACE_FUNCTION("grr_cnv_freq_para_in_assignment_direct_enc_2");
   /* decode and store rfl list */
    /* clean RFL content  */
    memset (&_local_rfl_contents, 0, sizeof(T_f_range));
    /* Length in bits */
    _local_rfl_contents.l_f = (freq_par->di_encod2.len_ma_list+3)*8;
    /* Copy RFL content bits into the structure */
    memcpy(_local_rfl_contents.b_f, freq_par->di_encod2.ma_list,
      freq_par->di_encod2.len_ma_list+3);

    /*
     * Use a function from RR
     * This function copies the frequencies into list. This function takes the arranging
     * of ARFCN into account cf. 12.10a GPRS Mobile Allocation in 04.60
     */
    for_create_channel_list (&_local_rfl_contents, &_local_dummy_list);

    memcpy(psc_db->rfl[MAX_RFL].list, _local_dummy_list.b_f,
      sizeof(psc_db->rfl[MAX_RFL].list));

/*    grr_create_channel_list(freq_par->di_encod2.ma_list, psc_db->rfl[MAX_RFL].list);*/

    psc_db->gprs_ms_alloc_in_assignment.gprs_ms_alloc_ie.hsn =
                                                      freq_par->di_encod2.hsn;
    psc_db->gprs_ms_alloc_in_assignment.gprs_ms_alloc_ie.v_rfl_num_list = TRUE;
    psc_db->gprs_ms_alloc_in_assignment.gprs_ms_alloc_ie.c_rfl_num_list = 1;
    psc_db->gprs_ms_alloc_in_assignment.gprs_ms_alloc_ie.v_ma_struct = FALSE;
    psc_db->gprs_ms_alloc_in_assignment.gprs_ms_alloc_ie.v_arfcn_index_list = FALSE;

    /* set up gprs_ms_alloc_in_assignment struct in database */
    psc_db->gprs_ms_alloc_in_assignment.ma_num = MA_NUMBER_4_ASSIGNMENT;
    psc_db->gprs_ms_alloc_in_assignment.gprs_ms_alloc_ie.rfl_num_list[0].rfl_num =
    psc_db->rfl[MAX_RFL].num                   = RFL_NUMBER_4_DIRECT_ENCODING_2;

    return(grr_create_freq_list(  psc_db->gprs_ms_alloc_in_assignment.ma_num,
                                  freq_par->di_encod2.maio,
                                  &frequency_par->p_chan_sel,
                                  &frequency_par->p_freq_list ));
}/* grr_cnv_freq_para_in_assignment_direct_enc_2 */

#ifdef REL99

/*
+------------------------------------------------------------------------------
| Function    : grr_cnv_freq_para_in_psi8_direct_enc_2
+------------------------------------------------------------------------------
| Description : This function decodes the Frequency parameters in direct encoding 2
|               The output of this function is in form which could be used by
|               MPH_* primitives in RR. This The mobile allocation list
|               generated by this function is different from the ones used by
|               MPHP_* primitives.
|               CBCH parameters are passed to RR and RR passes to ALR and ALR
|               converts these frequencies to TI L1 form and passes in MPHC_*
|               primitive to L1.
|               The caller of this function should make sure that the type of
|               encoding used in freq_par is of direct encoding 2.
| Parameters  : cbch_req - output.
|               freq_par - input
| NOTE: THIS FUNCTION USES THE LOCAL TEMPORARY ARRAYS - _local_rfl_contents AND
|       _local_dummy_list. These are use by grr_cnv_freq_para_in_assignment_direct_enc_2()
|       also.These two functions are placed in the same object module to avoid
|       the need for two copies of temporary arrays.
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_cnv_freq_para_in_psi8_direct_enc_2(T_cbch *cbch_req,const T_freq_par *freq_par)
{
    USHORT count = 0;
    TRACE_FUNCTION( "grr_cnv_freq_para_in_psi8_direct_enc_2");
    /* decode and store rfl list */
    /* clean RFL content  */
    memset (&_local_rfl_contents, 0, sizeof(T_f_range));
    /* Length in bits */
    _local_rfl_contents.l_f = (freq_par->di_encod2.len_ma_list+3)*8;
    /* Copy RFL content bits into the structure */
    memcpy(_local_rfl_contents.b_f, freq_par->di_encod2.ma_list,
      freq_par->di_encod2.len_ma_list+3);

    /*
     * Use a function from RR
     * This function copies the frequencies into list. This function takes the arranging
     * of ARFCN into account cf. 12.10a GPRS Mobile Allocation in 04.60
     */
    for_create_channel_list (&_local_rfl_contents, &_local_dummy_list);

    /* Local dummy list represents the mobile allocation.
     * This list need not be filtered with grr_ma_filter_list
     * as ALL arfcns in this list are part of mobile allocation.
     * But we need to validate this list.
     */
    srv_create_list(&_local_dummy_list,cbch_req->ma, 64 , TRUE ,0);

    if(!grr_validate_and_count_frequencies(cbch_req->ma,&count))
    {
      TRACE_ERROR( "grr_cnv_freq_para_in_psi8_direct_enc_2:validation failed/freq count zero" );
      return FALSE;
    }
    cbch_req->ma[count] = NOT_PRESENT_16BIT;
    cbch_req->maio = freq_par->di_encod2.maio;
    cbch_req->hsn = freq_par->di_encod2.hsn ;
    return TRUE;
}/* grr_cnv_freq_para_in_psi8_direct_enc_2 */
#endif

/*
+------------------------------------------------------------------------------
| Function    : grr_validate_and_count_frequencies
+------------------------------------------------------------------------------
| Description : This function ensures that all the frequencies in the list
|               are of same band. It returns the cout of frequencies in the list.
|               NOT_PRESENT_16BIT represents the end of list.
| Parameters  : Array representing the frequency list
|               ptr_cnt - output, returns the count.
| Return value :TRUE/FALSE
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_validate_and_count_frequencies(USHORT radio_freq_list[MPHP_NUMC_MA],USHORT* ptr_cnt)
{
  USHORT n = 0;
  TRACE_FUNCTION("grr_validate_and_count_frequencies");
  switch( std )
    {
      case STD_900: /* frequencies must between 1 and 124 */

       for(n=0, *ptr_cnt=0; n < 64; n++)
       {
         if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
           break;

         if(( radio_freq_list[n] >= LOW_CHANNEL_900 ) AND
            ( radio_freq_list[n] <= HIGH_CHANNEL_900))
         {
            (*ptr_cnt)++;
         }
         else
         {
           TRACE_EVENT_P1( "STD_900:Frequency %d not in the band!", radio_freq_list[n]);
           return FALSE;
         }
       }

        break;

      case STD_EGSM:

       for(n=0, *ptr_cnt=0; n < 64; n++)
       {
         if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
           break;

         if((radio_freq_list[n] <= HIGH_CHANNEL_900) OR
           ((radio_freq_list[n] >= LOW_CHANNEL_EGSM) AND
            (radio_freq_list[n] <= HIGH_CHANNEL_EGSM - 1)))
         {
           (*ptr_cnt)++;
         }
         else
         {
           TRACE_EVENT_P1( "STD_EGSM: Frequency %d not in the band!", radio_freq_list[n]);
           return FALSE;
         }
       }
        break;

      case STD_1900:

       for(n=0, *ptr_cnt=0; n < 64; n++)
       {
         if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
           break;

         if(( radio_freq_list[n] >= LOW_CHANNEL_1900 ) AND
            ( radio_freq_list[n] <= HIGH_CHANNEL_1900))
         {
            (*ptr_cnt)++;
         }
         else
         {
           TRACE_EVENT_P1( "STD_1900: Frequency %d not in the band!", radio_freq_list[n]);
           return FALSE;
         }
       }
        break;

      case STD_1800:

       for(n=0, *ptr_cnt=0; n < 64; n++)
       {
         if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
           break;

         if(( radio_freq_list[n] >= LOW_CHANNEL_1800 ) AND
           (  radio_freq_list[n] <= HIGH_CHANNEL_1800))
         {
           (*ptr_cnt)++;
         }
         else
         {
           TRACE_EVENT_P1( "STD_1800: Frequency %d not in the band!", radio_freq_list[n]);
           return FALSE;
         }
       }
       break;

      case STD_850:
       for(n=0, *ptr_cnt=0; n < 64; n++)
       {
         if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
           break;

         if(( radio_freq_list[n] >= LOW_CHANNEL_850 ) AND
            ( radio_freq_list[n] <= HIGH_CHANNEL_850))
         {
           (*ptr_cnt)++;
         }
         else
         {
           TRACE_EVENT_P1( "STD_850: Frequency %d not in the band!", radio_freq_list[n]);
           return FALSE;
         }
       }
       break;

      case STD_DUAL:

        if (( radio_freq_list[0] >= LOW_CHANNEL_900 ) AND
           (radio_freq_list[0] <= HIGH_CHANNEL_900))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if(( radio_freq_list[n] >= LOW_CHANNEL_900 ) AND
            (radio_freq_list[n] <= HIGH_CHANNEL_900))
            {
              *(ptr_cnt)+=1;
            }
            else
            {
              TRACE_EVENT_P1( "STD_DUAL: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
        if (( radio_freq_list[0] >= LOW_CHANNEL_1800 ) AND
           (radio_freq_list[0] <= HIGH_CHANNEL_1800))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if(( radio_freq_list[n] >= LOW_CHANNEL_1800 ) AND
               (radio_freq_list[n] <= HIGH_CHANNEL_1800))
            {
              *(ptr_cnt)+=1;
            }
            else
            {
              TRACE_EVENT_P1( "STD_DUAL: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
        {
              TRACE_EVENT_P1( "STD_DUAL: Frequency %d not in the band!", radio_freq_list[0]);
              return FALSE;
        }
        break;

      case STD_DUAL_EGSM:

         if((radio_freq_list[0] <= HIGH_CHANNEL_900) OR
           ((radio_freq_list[0] >= LOW_CHANNEL_EGSM) AND
           (radio_freq_list[0] <= HIGH_CHANNEL_EGSM - 1)))
         {
           for(n=0, *(ptr_cnt)=0; n < 64; n++)
           {
             if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
             break;

             if((radio_freq_list[n] <= HIGH_CHANNEL_900) OR
             ((radio_freq_list[n] >= LOW_CHANNEL_EGSM) AND
             (radio_freq_list[n] <= HIGH_CHANNEL_EGSM - 1)))
             {
               *(ptr_cnt)+=1;
             }
             else
             {
               TRACE_EVENT_P1( "STD_DUAL_EGSM: Frequency %d not in the band!", radio_freq_list[n]);
               return FALSE;
             }
           }
         }
         else
         if (( radio_freq_list[0] >= LOW_CHANNEL_1800 ) AND
           (radio_freq_list[0] <= HIGH_CHANNEL_1800))
         {
           for(n=0, *(ptr_cnt)=0; n < 64; n++)
           {
             if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
             break;

             if(( radio_freq_list[n] >= LOW_CHANNEL_1800 ) AND
             (radio_freq_list[n] <= HIGH_CHANNEL_1800))
             {
               *(ptr_cnt)+=1;
             }
             else
             {
              TRACE_EVENT_P1( "STD_DUAL_EGSM: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
             }
           }
         }
         else
         {
             TRACE_EVENT_P1( "STD_DUAL_EGSM: Frequency %d not in the band!", radio_freq_list[0]);
             return FALSE;
         }
         break;

      case STD_DUAL_US:
        if (( radio_freq_list[0] >= LOW_CHANNEL_850 ) AND
           (radio_freq_list[0] <= HIGH_CHANNEL_850))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if(( radio_freq_list[n] >= LOW_CHANNEL_850 ) AND
            (radio_freq_list[n] <= HIGH_CHANNEL_850))
            {
              *(ptr_cnt)+=1;
            }
            else
            {
              TRACE_EVENT_P1( "STD_DUAL_US: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
        if (( radio_freq_list[0] >= LOW_CHANNEL_1900 ) AND
           (radio_freq_list[0] <= HIGH_CHANNEL_1900))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if(( radio_freq_list[n] >= LOW_CHANNEL_1900 ) AND
               ( radio_freq_list[n] <= HIGH_CHANNEL_1900))
            {
              (*ptr_cnt)++;
            }
            else
            {
              TRACE_EVENT_P1( "STD_DUAL_US: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
        {
              TRACE_EVENT_P1( "STD_DUAL_US: Frequency %d not in the band!", radio_freq_list[0]);
              return FALSE;
        }
        break;

#ifdef TI_PS_FF_QUAD_BAND_SUPPORT
      case STD_850_1800:
        if (( radio_freq_list[0] >= LOW_CHANNEL_850 ) AND
            ( radio_freq_list[0] <= HIGH_CHANNEL_850))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if(( radio_freq_list[n] >= LOW_CHANNEL_850 ) AND
               ( radio_freq_list[n] <= HIGH_CHANNEL_850))
            {
              *(ptr_cnt)+=1;
            }
            else
            {
              TRACE_EVENT_P1( "STD_850_1800: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
        if (( radio_freq_list[0] >= LOW_CHANNEL_1800 ) AND
            ( radio_freq_list[0] <= HIGH_CHANNEL_1800))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if(( radio_freq_list[n] >= LOW_CHANNEL_1800 ) AND
               ( radio_freq_list[n] <= HIGH_CHANNEL_1800))
            {
              (*ptr_cnt)++;
            }
            else
            {
              TRACE_EVENT_P1( "STD_850_1800: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
        {
          TRACE_EVENT_P1( "STD_850_1800: Frequency %d not in the band!", radio_freq_list[0]);
          return FALSE;
        }
        break;

      case STD_900_1900:
         if((radio_freq_list[n] <= HIGH_CHANNEL_900) OR
           ((radio_freq_list[n] >= LOW_CHANNEL_EGSM) AND
            (radio_freq_list[n] <= HIGH_CHANNEL_EGSM - 1)))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if((radio_freq_list[n] <= HIGH_CHANNEL_900) OR
              ((radio_freq_list[n] >= LOW_CHANNEL_EGSM) AND
               (radio_freq_list[n] <= HIGH_CHANNEL_EGSM - 1)))
            {
              *(ptr_cnt)+=1;
            }
            else
            {
              TRACE_EVENT_P1( "STD_900_1900: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
        if (( radio_freq_list[0] >= LOW_CHANNEL_1900 ) AND
            ( radio_freq_list[0] <= HIGH_CHANNEL_1900))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if(( radio_freq_list[n] >= LOW_CHANNEL_1900 ) AND
               ( radio_freq_list[n] <= HIGH_CHANNEL_1900))
            {
              (*ptr_cnt)++;
            }
            else
            {
              TRACE_EVENT_P1( "STD_900_1900: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
        {
              TRACE_EVENT_P1( "STD_900_1900: Frequency %d not in the band!", radio_freq_list[0]);
              return FALSE;
        }
        break;
        
      case STD_850_900_1800:
        if (( radio_freq_list[0] >= LOW_CHANNEL_850 ) AND
            ( radio_freq_list[0] <= HIGH_CHANNEL_850))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if(( radio_freq_list[n] >= LOW_CHANNEL_850 ) AND
               ( radio_freq_list[n] <= HIGH_CHANNEL_850))
            {
              *(ptr_cnt)+=1;
            }
            else
            {
              TRACE_EVENT_P1( "STD_850_900_1800: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
         if((radio_freq_list[n] <= HIGH_CHANNEL_900) OR
           ((radio_freq_list[n] >= LOW_CHANNEL_EGSM) AND
            (radio_freq_list[n] <= HIGH_CHANNEL_EGSM - 1)))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if((radio_freq_list[n] <= HIGH_CHANNEL_900) OR
              ((radio_freq_list[n] >= LOW_CHANNEL_EGSM) AND
               (radio_freq_list[n] <= HIGH_CHANNEL_EGSM - 1)))
            {
              (*ptr_cnt)++;
            }
            else
            {
              TRACE_EVENT_P1( "STD_850_900_1800: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
        if (( radio_freq_list[0] >= LOW_CHANNEL_1800 ) AND
            ( radio_freq_list[0] <= HIGH_CHANNEL_1800))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if(( radio_freq_list[n] >= LOW_CHANNEL_1800 ) AND
               ( radio_freq_list[n] <= HIGH_CHANNEL_1800))
            {
              (*ptr_cnt)++;
            }
            else
            {
              TRACE_EVENT_P1( "STD_850_900_1800: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
        {
              TRACE_EVENT_P1( "STD_850_900_1800: Frequency %d not in the band!", radio_freq_list[0]);
              return FALSE;
        }
        break;

      case STD_850_900_1900:
        if (( radio_freq_list[0] >= LOW_CHANNEL_850 ) AND
            ( radio_freq_list[0] <= HIGH_CHANNEL_850))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if(( radio_freq_list[n] >= LOW_CHANNEL_850 ) AND
               ( radio_freq_list[n] <= HIGH_CHANNEL_850))
            {
              *(ptr_cnt)+=1;
            }
            else
            {
              TRACE_EVENT_P1( "STD_850_900_1900: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
         if((radio_freq_list[n] <= HIGH_CHANNEL_900) OR
           ((radio_freq_list[n] >= LOW_CHANNEL_EGSM) AND
            (radio_freq_list[n] <= HIGH_CHANNEL_EGSM - 1)))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if((radio_freq_list[n] <= HIGH_CHANNEL_900) OR
              ((radio_freq_list[n] >= LOW_CHANNEL_EGSM) AND
               (radio_freq_list[n] <= HIGH_CHANNEL_EGSM - 1)))
            {
              (*ptr_cnt)++;
            }
            else
            {
              TRACE_EVENT_P1( "STD_850_900_1900: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
        if (( radio_freq_list[0] >= LOW_CHANNEL_1900 ) AND
            ( radio_freq_list[0] <= HIGH_CHANNEL_1900))
        {
          for(n=0, *(ptr_cnt)=0; n < 64; n++)
          {
            if(radio_freq_list[n] EQ NOT_PRESENT_16BIT)
            break;

            if(( radio_freq_list[n] >= LOW_CHANNEL_1900 ) AND
               ( radio_freq_list[n] <= HIGH_CHANNEL_1900))
            {
              (*ptr_cnt)++;
            }
            else
            {
              TRACE_EVENT_P1( "STD_850_900_1900: Frequency %d not in the band!", radio_freq_list[n]);
              return FALSE;
            }
          }
        }
        else
        {
              TRACE_EVENT_P1( "STD_850_900_1900: Frequency %d not in the band!", radio_freq_list[0]);
              return FALSE;
        }
        break;
#endif

      default:
#ifdef TI_PS_FF_QUAD_BAND_SUPPORT
        TRACE_ASSERT( std EQ STD_850       OR
                      std EQ STD_900       OR
                      std EQ STD_EGSM      OR
                      std EQ STD_1900      OR
                      std EQ STD_1800      OR
                      std EQ STD_DUAL      OR
                      std EQ STD_DUAL_EGSM OR
                      std EQ STD_DUAL_US   OR  
                      std EQ STD_850_1800  OR 
                      std EQ STD_900_1900  OR 
                      std EQ STD_850_900_1800 OR 
                      std EQ STD_850_900_1900 );
#else
        TRACE_ASSERT( std EQ STD_850       OR
                      std EQ STD_900       OR
                      std EQ STD_EGSM      OR
                      std EQ STD_1900      OR
                      std EQ STD_1800      OR
                      std EQ STD_DUAL      OR
                      std EQ STD_DUAL_EGSM OR
                      std EQ STD_DUAL_US      );
#endif
        break;
    }

  memset(&radio_freq_list[n], 0, (128-2*n)); /*lint !e669*/
  /*set values back to zero, neeeded by windows test cases*/

  *(ptr_cnt) = MINIMUM( MPHP_NUMC_MA, *ptr_cnt );

  if( *ptr_cnt EQ 0 )
  {
    TRACE_ERROR( "grr_validate_and_count_frequencies: freq count EQ 0" );

    return FALSE;
  }
  return TRUE;
}/* grr_validate_and_count_frequencies */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_ref_list_or_cell_allocation
+------------------------------------------------------------------------------
| Description : Determining the frequency list to be used for a hopping channel
|               involvs following steps.
|               1. Determining the referenced set of reference frequency lists
|                  or cell allocation.( See 3GPP 04.60 12.10a)
|               2. Filtering this list based on MA_BITMAP and ARFCN index list.
|
|               This function performs the first step. ie it generates
|               the referenced set of referncelists or Cell allocation list
|               depending on the presence of RFL number list in
|               the GPRS Mobile allocation IE.
| Parameters  : list1 - output, This is list will hold the referenced set of
|               reference freq list or Cell allocation depending on the
|               contents of gp_ma passed.
|               gp_ma - pointer to gprs mobile allocation IE
|               ma_num - identifies the MA_NUM in freq parameters IE.
|                        3GPP 04.60 Sec 5.5.1.7
|
| Return value : TRUE/FALSE
+------------------------------------------------------------------------------
*/
GLOBAL BOOL grr_get_ref_list_or_cell_allocation(T_LIST *list1,const T_gprs_ms_alloc_ie *gp_ma,UBYTE ma_num)
{
  BOOL                pbcch_is_present = grr_is_pbcch_present( );
  /*
   * Check RFL number list. If NOT exists, use cell allocation (CA)
   */
  TRACE_FUNCTION(" grr_get_ref_list_or_cell_allocation ");
  if(!gp_ma->v_rfl_num_list)
  {
    /*
     * Use CA defined in PSI2 or in SI1 depending on the table below
     *
     *  Case | PBCCH   | PSI2     | RFL_NUMBERs | Action
     *       | present | complete | all found   |
     *  -----+---------+----------+-------------+-----------
     *
     * 0 <= MA_NUMBER <= 15
     *
     *  -----+---------+----------+-------------+-----------
     *    A  |    y    |    y     |      y      | Use CA PSI
     *  -----+---------+----------+-------------+-----------
     *    B  |    y    |    y     |      n      | Use CA SI
     *  -----+---------+----------+-------------+-----------
     *    C  |    y    |    n     |      x      | Use CA SI
     *  -----+---------+----------+-------------+-----------
     *    D  |    n    |    x     |      x      | Use CA SI
     *  -----+---------+----------+-------------+-----------
     *
     * y = yes, n = no, x = don't case
     *
     */
    if( pbcch_is_present                 EQ TRUE       AND
        psc_db->state_of_PSI[PSI2].state EQ RECEIPT_OK AND
        psc_db->v_cell_alloc             EQ TRUE           )
    {
      /*
       * Use CA in PSI2. RFLs define a CA.
       * If needed, we have to merge frequencies defined in different RFL's into one list
       */

      /* Implementation of case A and B */

      if( grr_get_psi_cell_alloc_list( list1 ) EQ FALSE )
      {
        /* Implementation of case B */

        TRACE_ERROR( "grr_create_freq_list: grr_get_psi_cell_alloc_list( ) EQ FALSE in case B" );

        grr_get_si_cell_alloc_list( list1 );
      }
    }
    else
    {
      /* Implementation of case C and D */

      if( pbcch_is_present EQ TRUE )
      {
        TRACE_EVENT( "grr_create_freq_list: PSI2 not OK in case C and D" );
      }

      grr_get_si_cell_alloc_list( list1 );
    }
  }
  else
  {
    /*
     * Use MA depending on the table below
     *
     * Case | PBCCH   | PSI2     | RFL_NUMBERs | 0 <= RFL_NUMBER <= 15 | RFL_NUMBER == 16 | Action
     *      | present | complete | all found   |                       |                  |
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *
     * 0 <= MA_NUMBER <= 13
     *
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   E  |    y    |    y     |      y      |           x           |         x        | Use list
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   F  |    y    |    y     |      n      |           x           |         x        | Reject list
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   G  |    y    |    n     |      x      |           x           |         x        | Reject list
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   H  |    n    |    x     |      x      |           x           |         x        | Reject list
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *
     * MA_NUMBER == 14
     *
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   I  |    y    |    y     |      y      |           x           |         x        | Use list
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   J  |    y    |    y     |      n      |           x           |         x        | Use CA PSI
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   K  |    y    |    n     |      x      |           x           |         x        | Use CA SI
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   L  |    n    |    x     |      x      |           x           |         x        | Use CA SI
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *
     * MA_NUMBER == 15
     *
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   M  |    y    |    y     |      y      |           x           |         x        | Use list
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   N  |    y    |    y     |      n      |           x           |         x        | Reject list
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   O  |    y    |    n     |      x      |           y           |         n        | Reject list
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   P  |    y    |    n     |      x      |           n           |         y        | Use list
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   Q  |    n    |    x     |      x      |           y           |         n        | Reject list
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *   R  |    n    |    x     |      x      |           n           |         y        | Use list
     * -----+---------+----------+-------------+-----------------------+------------------+------------
     *
     * y = yes, n = no, x = don't case
     *
     */

    /*
     * Use the defined RFL in GPRS MA
     * If needed, we have to merge frequencies defined in different RFL's into one list
     */
    if( ma_num EQ MA_NUMBER_4_ASSIGNMENT )
    {
      if( pbcch_is_present                 EQ TRUE       AND
          psc_db->state_of_PSI[PSI2].state EQ RECEIPT_OK     )
      {
        /* Implementation of case M and N */

        if( grr_get_ms_alloc_list( list1, gp_ma ) EQ FALSE )
        {
          /* Implementation of case N */

          TRACE_ERROR( "grr_create_freq_list: grr_get_ms_alloc_list( ) EQ FALSE in case N" );

          return FALSE;
        }
      }
      else
      {
        if( gp_ma->c_rfl_num_list          EQ 1                              AND
            gp_ma->rfl_num_list[0].rfl_num EQ RFL_NUMBER_4_DIRECT_ENCODING_2     )
        {
          /* Implementation of case P and R */

          if( grr_get_ms_alloc_list( list1, gp_ma ) EQ FALSE )
          {
            TRACE_ERROR( "grr_create_freq_list: grr_get_ms_alloc_list( ) EQ FALSE in case P and R" );

            return FALSE;
          }
        }
        else
        {
          /* Implementation of case O and Q */

          if( pbcch_is_present EQ TRUE )
          {
            TRACE_ERROR( "grr_create_freq_list: PSI2 not OK in case O and Q" );
          }
          else
          {
            TRACE_ERROR( "grr_create_freq_list: no PBCCH present and error in case O and Q" );
          }

          return FALSE;
        }
      }
    }
    else if( ma_num EQ MA_NUMBER_4_PSI13_OR_CELL_ALLOC )
    {
      if( pbcch_is_present                 EQ TRUE       AND
          psc_db->state_of_PSI[PSI2].state EQ RECEIPT_OK     )
      {
        /* Implementation of case I and J */

        if( grr_get_ms_alloc_list( list1, gp_ma ) EQ FALSE )
        {
          /* Implementation of case J */

          TRACE_ERROR( "grr_create_freq_list: grr_get_ms_alloc_list( ) EQ FALSE in case J" );

          if( grr_get_psi_cell_alloc_list( list1 ) EQ FALSE )
          {
            TRACE_ERROR( "grr_create_freq_list: grr_get_psi_cell_alloc_list( ) EQ FALSE in case J" );

            grr_get_si_cell_alloc_list( list1 );
          }
        }
      }
      else
      {
        /* Implementation of case K and L */

        if( pbcch_is_present EQ TRUE )
        {
          TRACE_ERROR( "grr_create_freq_list: PSI2 not OK in case K and L" );
        }

        grr_get_si_cell_alloc_list( list1 );
      }
    }
    else
    {
      if( pbcch_is_present                 EQ TRUE       AND
          psc_db->state_of_PSI[PSI2].state EQ RECEIPT_OK     )
      {
        /* Implementation of case E and F */

        if( grr_get_ms_alloc_list( list1, gp_ma ) EQ FALSE )
        {
          /* Implementation of case F */

          TRACE_ERROR( "grr_create_freq_list: grr_get_ms_alloc_list( ) EQ FALSE in case F" );

          return FALSE;
        }
      }
      else
      {
        /* Implementation of case G and H */

        if( pbcch_is_present EQ TRUE )
        {
          TRACE_ERROR( "grr_create_freq_list: PSI2 not OK in case G and H" );
        }

        return FALSE;
      }
    }
  }
  return TRUE;
}/* grr_get_ref_list_or_cell_allocation  */

#ifdef REL99
/*
+------------------------------------------------------------------------------
| Function    : grr_get_time_to_send_poll
+------------------------------------------------------------------------------
| Description : This function retrun the duration in milliseconds to transmit a 
|               poll.The basic for the calucation is based on RRBP obtained in 
|               the downlink message. The calculation is mentioned in the function.
| Parameters  : rrbp
|
+------------------------------------------------------------------------------
*/
GLOBAL T_TIME grr_get_time_to_send_poll(UBYTE rrbp)
{
   /*
   * This calculation is based on the following calculation
   * t_ms = (Number of frame to transmit Poll)*(Frame Duration in millseconds)
   * Number of frame to transmit Poll:- are 13,18,22,26 for rrbp 0,1,2,3 respectively
   * Frame Duration in millseconds:-is 4.615millseconds
   * eg . t_ms[0] = 13*4.615 =60,
   */
   T_TIME t_ms[] = {60, 83,102,120};
   return (t_ms[rrbp]);
}

#ifdef TI_PS_FF_EMR

/*
+------------------------------------------------------------------------------
| Function    : grr_init_enh_param
+------------------------------------------------------------------------------
| Description : This function is used to initialize ENH parameters
|
| Parameters  : param - pointer to ENH measurement parameter
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_init_enh_param( T_GRR_ENH_PARA *param, BOOL rep_prio_pres )
{ 
  TRACE_FUNCTION( "grr_init_enh_param" );
  
  param->idx        = NOT_SET;
  param->rept_type  = REPORT_TYPE_REP;
  if(rep_prio_pres)
  {
    param->gprs_rept_prio_desc.num_cells = 0;
  }
  
}/* grr_init_enh_param */

/*
+------------------------------------------------------------------------------
| Function    : grr_init_enh_cell_list
+------------------------------------------------------------------------------
| Description : This function is used to initialize ENH cell list
|
| Parameters  : Nil
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_init_enh_cell_list( void )
{ 
  TRACE_FUNCTION( "grr_init_enh_cell_list" );

  grr_data->db.cnt_enh_cell_list = 0;

  grr_data->db.sorted_enh_cell_list.num_valid = 0;

}/* grr_init_enh_cell_list */

/*
+------------------------------------------------------------------------------
| Function    : grr_prcs_enh_param_cw_temp
+------------------------------------------------------------------------------
| Description : This function is used to copy the enhanced parameters received 
|               in PSI5. Here it is copied into a temporary storage until all
|               the instances are properly received.
|
| Parameters  : db_enh  - ENH measurement parameter in the GRR database
|               air_enh - ENH measurement parameter of the air interface
|                         message
|               new_idx - sequence number of the message
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_prcs_enh_param_cw_temp ( T_GRR_ENH_PARA  *db_enh,
                                         T_enh_rep_param_struct *air_enh,
                                         UBYTE  new_idx )
{ 
  UBYTE n;
  
  TRACE_FUNCTION( "grr_prcs_enh_param_cw_temp" );

  if(db_enh->idx EQ NOT_SET)
  {
    /* Store default values for optional enhanced measurement paramaters */
    db_enh->ncc_permitted = NCC_PERMITTED_DEFAULT;
    db_enh->multiband_rep = GRR_MULTIBAND_REPORTING_0;
    db_enh->servingband_rep = SERVING_BAND_REPORTING_DEFAULT;
    db_enh->scale_order = SCALE_0dB;
    for(n = 0; n < MAX_NUM_BANDS; n++)
    {
      db_enh->enh_rep_data[n].rep_threshold = REP_THRESHOLD_DEF;
      db_enh->enh_rep_data[n].rep_offset = REP_OFFSET_0;
    }
  }    
  
  /* Update Enhanced Measurement parameters */
  db_enh->rept_type = air_enh->reporting_type;
  db_enh->rep_rate = air_enh->reporting_rate;
  db_enh->inv_bsic_enabled = air_enh->invalid_bsic_rep;
  
  if( (air_enh->v_ncc_permitted) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
  {
    db_enh->ncc_permitted = air_enh->ncc_permitted;
  }

  /* Update GPRS measurement parameters */
  if(air_enh->v_gprs_meas_par_report)
  {
    if( (air_enh->gprs_meas_par_report.v_multi_band_rep) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->multiband_rep = air_enh->gprs_meas_par_report.multi_band_rep;
    }

    if( (air_enh->gprs_meas_par_report.v_serv_cell_rep) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->servingband_rep = 
      air_enh->gprs_meas_par_report.serv_cell_rep;
    }

    if( (air_enh->gprs_meas_par_report.v_scale_ord) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->scale_order = 
      air_enh->gprs_meas_par_report.scale_ord;
    }

    if( (air_enh->gprs_meas_par_report.v_report_900_grr) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->enh_rep_data[0].rep_threshold = 
      air_enh->gprs_meas_par_report.report_900_grr.rep_thres_900;
      db_enh->enh_rep_data[0].rep_offset = 
      air_enh->gprs_meas_par_report.report_900_grr.rep_offset_900;
    }

    if( (air_enh->gprs_meas_par_report.v_report_1800_grr) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->enh_rep_data[1].rep_threshold = 
      air_enh->gprs_meas_par_report.report_1800_grr.rep_thres_1800;
      db_enh->enh_rep_data[1].rep_offset = 
      air_enh->gprs_meas_par_report.report_1800_grr.rep_offset_1800;
    }

    if( (air_enh->gprs_meas_par_report.v_report_400_grr) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->enh_rep_data[2].rep_threshold = 
      air_enh->gprs_meas_par_report.report_400_grr.rep_thres_400;
      db_enh->enh_rep_data[2].rep_offset = 
      air_enh->gprs_meas_par_report.report_400_grr.rep_offset_400;
    }

    if( (air_enh->gprs_meas_par_report.v_report_1900_grr) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->enh_rep_data[3].rep_threshold = 
      air_enh->gprs_meas_par_report.report_1900_grr.rep_thres_1900;
      db_enh->enh_rep_data[3].rep_offset = 
      air_enh->gprs_meas_par_report.report_1900_grr.rep_offset_1900;
    }

    if( (air_enh->gprs_meas_par_report.v_report_850_grr) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->enh_rep_data[4].rep_threshold = 
      air_enh->gprs_meas_par_report.report_850_grr.rep_thres_850;
      db_enh->enh_rep_data[4].rep_offset = 
      air_enh->gprs_meas_par_report.report_850_grr.rep_offset_850;
    }
  }    

  db_enh->idx = new_idx;
}/* grr_prcs_enh_param_cw_temp */

/*
+------------------------------------------------------------------------------
| Function    : grr_prcs_enh_param_pmo
+------------------------------------------------------------------------------
| Description : This function is used to copy temporarily the enhanced 
|               measurement parameters from PMO.
|
| Parameters  : db_enh  - ENH measurement parameter in the GRR database
|               air_enh - ENH measurement parameter of the air interface
|                         message
|               new_idx - sequence number of the message
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_prcs_enh_param_pmo ( T_GRR_ENH_PARA  *db_enh,
                                     T_enh_meas_param_pmo  *air_enh,  
                                     UBYTE  new_idx, UBYTE *pmo_ind )
{
  UBYTE n;
  UBYTE num_cells = db_enh->gprs_rept_prio_desc.num_cells;
  UBYTE number_cells = air_enh->gprs_rep_prio_cell_desc.number_cells;

  TRACE_FUNCTION( "grr_prcs_enh_param_pmo" );

  if(db_enh->idx EQ NOT_SET)
  {
    /* Store default values for optional enhanced measurement paramaters */
    db_enh->ncc_permitted = NCC_PERMITTED_DEFAULT;
    db_enh->multiband_rep = GRR_MULTIBAND_REPORTING_0;
    db_enh->servingband_rep = SERVING_BAND_REPORTING_DEFAULT;
    db_enh->scale_order = SCALE_0dB;
    for(n = 0; n < MAX_NUM_BANDS; n++)
    {
      db_enh->enh_rep_data[n].rep_threshold = REP_THRESHOLD_DEF;
      db_enh->enh_rep_data[n].rep_offset = REP_OFFSET_0;
    }
    for(n = 0; n < MAX_NR_OF_GSM_NC; n++)
    {
      db_enh->gprs_rept_prio_desc.rept_prio[n] = NORMAL_PRIO;
    }
  }    
  
  /* Update Enhanced Measurement parameters */
  
  *pmo_ind = air_enh->ba_psi3_str.pmo_ind_used;
  db_enh->rept_type = air_enh->reporting_type;
  db_enh->rep_rate = air_enh->reporting_rate;
  db_enh->inv_bsic_enabled = air_enh->invalid_bsic_rep;

  /* GPRS Report priority can be received in only one instance since start 
    index is not given for mapping to BA as in RTD and BSIC mapping in SI */
  if((air_enh->v_gprs_rep_prio_cell_desc) AND (number_cells NEQ 0))
  {
    if(number_cells > MAX_NR_OF_GSM_NC)
    {
      num_cells = MAX_NR_OF_GSM_NC;
    }
    else
    {
      num_cells = number_cells;
    }

    for(n = 0; n < num_cells; n++)
    {
      db_enh->gprs_rept_prio_desc.rept_prio[n] = 
        air_enh->gprs_rep_prio_cell_desc.rep_prio[n];
    }
  }

  /* Update GPRS measurement parameters */
  if(air_enh->v_gprs_meas_par_desc_meas)
  {
    if( (air_enh->gprs_meas_par_desc_meas.v_multi_band_rep) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->multiband_rep = 
        air_enh->gprs_meas_par_desc_meas.multi_band_rep;
    }

    if( (air_enh->gprs_meas_par_desc_meas.v_serv_cell_rep) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->servingband_rep = 
      air_enh->gprs_meas_par_desc_meas.serv_cell_rep;
    }

    db_enh->scale_order = air_enh->gprs_meas_par_desc_meas.scale_ord;

    if( (air_enh->gprs_meas_par_desc_meas.v_report_900_grr) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->enh_rep_data[0].rep_threshold = 
      air_enh->gprs_meas_par_desc_meas.report_900_grr.rep_thres_900;
      db_enh->enh_rep_data[0].rep_offset = 
      air_enh->gprs_meas_par_desc_meas.report_900_grr.rep_offset_900;
    }

    if( (air_enh->gprs_meas_par_desc_meas.v_report_1800_grr) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->enh_rep_data[1].rep_threshold = 
      air_enh->gprs_meas_par_desc_meas.report_1800_grr.rep_thres_1800;
      db_enh->enh_rep_data[1].rep_offset =
      air_enh->gprs_meas_par_desc_meas.report_1800_grr.rep_offset_1800;
    }

    if( (air_enh->gprs_meas_par_desc_meas.v_report_400_grr) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->enh_rep_data[2].rep_threshold = 
      air_enh->gprs_meas_par_desc_meas.report_400_grr.rep_thres_400;
      db_enh->enh_rep_data[2].rep_offset =
      air_enh->gprs_meas_par_desc_meas.report_400_grr.rep_offset_400;
    }

    if( (air_enh->gprs_meas_par_desc_meas.v_report_1900_grr) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->enh_rep_data[3].rep_threshold = 
      air_enh->gprs_meas_par_desc_meas.report_1900_grr.rep_thres_1900;
      db_enh->enh_rep_data[3].rep_offset =
      air_enh->gprs_meas_par_desc_meas.report_1900_grr.rep_offset_1900;
    }

    if( (air_enh->gprs_meas_par_desc_meas.v_report_850_grr) AND
      ((db_enh->idx EQ NOT_SET) OR (new_idx > db_enh->idx)) )
    {
      db_enh->enh_rep_data[4].rep_threshold = 
      air_enh->gprs_meas_par_desc_meas.report_850_grr.rep_thres_850;
      db_enh->enh_rep_data[4].rep_offset =
      air_enh->gprs_meas_par_desc_meas.report_850_grr.rep_offset_850;
    }
  }
  
  db_enh->idx = new_idx;
}/* grr_prcs_enh_param_pmo */

/*
+------------------------------------------------------------------------------
| Function    : grr_prcs_enh_param_pcco
+------------------------------------------------------------------------------
| Description : This function is used to copy the enhanced measurement 
|               parameters from PCCO.
|
| Parameters  : db      - Network directed cell database
|               air_enh - ENH measurement parameter of the air interface
|                         message
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_prcs_enh_param_pcco ( T_SC_DATABASE  *db,
                                      T_enh_meas_param_pcco *air_enh )
{
  UBYTE n;
  T_GRR_ENH_PARA *db_enh = &db->enh_ms;
  UBYTE max_num_ncells = db_enh->gprs_rept_prio_desc.num_cells;

  TRACE_FUNCTION( "grr_prcs_enh_param_pcco" );

  if(db_enh->idx EQ NOT_SET)
  {
    /* Store default values for optional enhanced measurement paramaters */
    db_enh->ncc_permitted = NCC_PERMITTED_DEFAULT;
    db_enh->multiband_rep = GRR_MULTIBAND_REPORTING_0;
    db_enh->servingband_rep = SERVING_BAND_REPORTING_DEFAULT;
    db_enh->scale_order = SCALE_0dB;
    for(n = 0; n < MAX_NUM_BANDS; n++)
    {
      db_enh->enh_rep_data[n].rep_threshold = REP_THRESHOLD_DEF;
      db_enh->enh_rep_data[n].rep_offset = REP_OFFSET_0;
    }
  }    
  
  /* Update Enhanced Measurement parameters */

  db->nc_ms.psi3_cm = air_enh->ba_psi3_str.psi3_cm;
  db->nc_ms.ba_ind  = air_enh->ba_psi3_str.ba_ind_used;  
  db->nc_ms.pmo_ind = air_enh->ba_psi3_str.pmo_ind_used;
  db_enh->rept_type = air_enh->reporting_type;
  db_enh->rep_rate = air_enh->reporting_rate;
  db_enh->inv_bsic_enabled = air_enh->invalid_bsic_rep;

  if((air_enh->v_gprs_rep_prio_cell_desc) AND 
  (air_enh->gprs_rep_prio_cell_desc.number_cells NEQ 0))
  {

    if(air_enh->gprs_rep_prio_cell_desc.number_cells > MAX_NR_OF_NCELL)
    {
      max_num_ncells = MAX_NR_OF_NCELL;
    }
    else
    {
      max_num_ncells = air_enh->gprs_rep_prio_cell_desc.number_cells;
    }
    
    for(n = 0; n < max_num_ncells; n++)
    {
      db_enh->gprs_rept_prio_desc.rept_prio[n] = 
      air_enh->gprs_rep_prio_cell_desc.rep_prio[n];
    }
    
  }
  /* Update GPRS measurement parameters */
  if(air_enh->v_gprs_meas_par_desc_meas)
  {
    if(air_enh->gprs_meas_par_desc_meas.v_multi_band_rep)
    {
      db_enh->multiband_rep = 
        air_enh->gprs_meas_par_desc_meas.multi_band_rep;
    }

    if(air_enh->gprs_meas_par_desc_meas.v_serv_cell_rep)
    {
      db_enh->servingband_rep = 
      air_enh->gprs_meas_par_desc_meas.serv_cell_rep;
    }

    db_enh->scale_order = air_enh->gprs_meas_par_desc_meas.scale_ord;

    if(air_enh->gprs_meas_par_desc_meas.v_report_900_grr)
    {
      db_enh->enh_rep_data[0].rep_threshold = 
      air_enh->gprs_meas_par_desc_meas.report_900_grr.rep_thres_900;
      db_enh->enh_rep_data[0].rep_offset = 
      air_enh->gprs_meas_par_desc_meas.report_900_grr.rep_offset_900;
    }

    if(air_enh->gprs_meas_par_desc_meas.v_report_1800_grr)
    {
      db_enh->enh_rep_data[1].rep_threshold = 
      air_enh->gprs_meas_par_desc_meas.report_1800_grr.rep_thres_1800;
      db_enh->enh_rep_data[1].rep_offset =
      air_enh->gprs_meas_par_desc_meas.report_1800_grr.rep_offset_1800;
    }

    if(air_enh->gprs_meas_par_desc_meas.v_report_400_grr)
    {
      db_enh->enh_rep_data[2].rep_threshold = 
      air_enh->gprs_meas_par_desc_meas.report_400_grr.rep_thres_400;
      db_enh->enh_rep_data[2].rep_offset =
      air_enh->gprs_meas_par_desc_meas.report_400_grr.rep_offset_400;
    }

    if(air_enh->gprs_meas_par_desc_meas.v_report_1900_grr)
    {
      db_enh->enh_rep_data[3].rep_threshold = 
      air_enh->gprs_meas_par_desc_meas.report_1900_grr.rep_thres_1900;
      db_enh->enh_rep_data[3].rep_offset =
      air_enh->gprs_meas_par_desc_meas.report_1900_grr.rep_offset_1900;
    }

    if(air_enh->gprs_meas_par_desc_meas.v_report_850_grr)
    {
      db_enh->enh_rep_data[4].rep_threshold = 
      air_enh->gprs_meas_par_desc_meas.report_850_grr.rep_thres_850;
      db_enh->enh_rep_data[4].rep_offset =
      air_enh->gprs_meas_par_desc_meas.report_850_grr.rep_offset_850;
    }
  }    

  db_enh->idx = 0;
}/* grr_prcs_enh_param_pcco */

/*
+------------------------------------------------------------------------------
| Function    : grr_copy_enh_and_nc_params_from_si2qtr
+------------------------------------------------------------------------------
| Description : This function is meant to copy the ENH and NC parameters that
|               are received by SI2 quater, when PBCCH is not present
|
| Parameters  : Pointer to RRGRR_SI2QUATER_IND message contents
|                
+------------------------------------------------------------------------------
*/
GLOBAL void grr_copy_enh_and_nc_params_from_si2qtr(T_RRGRR_SI2QUATER_IND 
                                                   *rrgrr_si2quater_ind)
{
  UBYTE n;
  T_enh_para_struct *enh_para_struct = 
    &(rrgrr_si2quater_ind->enh_para_struct);

  T_nc_para_struct *nc_para_struct = &(rrgrr_si2quater_ind->nc_para_struct);
  
  TRACE_FUNCTION( "grr_copy_enh_nc_params" );
  
  /* Copy Enhanced Measurement parameters only if report type indicates ENH */
  if(rrgrr_si2quater_ind->rep_type EQ ENHANCED_MEAS)
  {
    /* Copy GSM Neighbour Cell list, if present. Otherwise, only ENH params have 
       changed. Use old NC list and new ENH params */
    for(n = 0; n < enh_para_struct->num_valid_cells; n++)
    {
      /* Do not include the serving cell in the GSM Neighbour Cell list */
      if ( (enh_para_struct->enh_cell_list[n].arfcn EQ psc_db->pbcch.bcch.arfcn)
            AND 
           (enh_para_struct->enh_cell_list[n].bsic EQ psc_db->pbcch.bcch.bsic) )
      {
        continue;
      }
      psc_db->nc_ba_bcch_cw.info[n].index = n;
      psc_db->nc_ba_bcch_cw.info[n].arfcn = 
        enh_para_struct->enh_cell_list[n].arfcn;
      psc_db->nc_ba_bcch_cw.info[n].bsic = 
        enh_para_struct->enh_cell_list[n].bsic;
      psc_db->enh_cw.gprs_rept_prio_desc.rept_prio[n] =
        enh_para_struct->enh_cell_list[n].rep_priority;
    }

     psc_db->nc_ba_bcch_cw.number = n;
    
    /* Copy Enhanced Measurement parameters */
    psc_db->enh_cw.rept_type = rrgrr_si2quater_ind->rep_type;
    psc_db->enh_cw.rep_rate = enh_para_struct->rep_rate;
    psc_db->enh_cw.inv_bsic_enabled = enh_para_struct->inv_bsic_enabled;
    psc_db->enh_cw.ncc_permitted = enh_para_struct->ncc_permitted;
    psc_db->enh_cw.multiband_rep = enh_para_struct->multiband_rep;
    psc_db->enh_cw.servingband_rep = enh_para_struct->servingband_rep;
    psc_db->enh_cw.scale_order = enh_para_struct->scale_order;
    for(n = 0; n < MAX_NUM_BANDS; n++)
    {
      psc_db->enh_cw.enh_rep_data[n].rep_offset = 
        enh_para_struct->enh_rep_data[n].rep_offset;
      psc_db->enh_cw.enh_rep_data[n].rep_threshold = 
        enh_para_struct->enh_rep_data[n].rep_threshold;
    }
  }
  
  /* Copy NC Measurement parameters if received by SI2 quater */
  if(nc_para_struct->nco NEQ NC_EMPTY)
  {
    T_nc_meas_par nc_meas_par;
    
    nc_meas_par.ctrl_order = nc_para_struct->nco;
    nc_meas_par.v_nc_meas_per = nc_para_struct->is_valid;
    if(nc_meas_par.v_nc_meas_per)
    {
      nc_meas_par.nc_meas_per.non_drx_per = nc_para_struct->nc_non_drx;
      nc_meas_par.nc_meas_per.rep_per_i = nc_para_struct->nc_rep_per_i;
      nc_meas_par.nc_meas_per.rep_per_t = nc_para_struct->nc_rep_per_t;
    }
    
    grr_prcs_nc_param_struct ( &psc_db->nc_cw.param, &nc_meas_par, 0 );
  }

  cs_build_nc_ref_list( psc_db, FALSE );
  
  if( 
    psc_db->nc_cw.param.chng_mrk.prev        NEQ
    psc_db->nc_cw.param.chng_mrk.curr
    )
  {
    if( cs_is_meas_reporting( ) EQ FALSE )
    {
      cs_cancel_meas_report( );
    }
    
    cs_process_t3158( );
    
    psc_db->nc_cw.param.chng_mrk.prev = psc_db->nc_cw.param.chng_mrk.curr;
  }
} /* grr_copy_enh_and_nc_params_from_si2qtr */

/*
+------------------------------------------------------------------------------
| Function    : grr_get_psi3_cm
+------------------------------------------------------------------------------
| Description : This function returns the value of PSI3 change mark. The PSI3
|               change mark is received on PSI3, PSI3 bis and on optional 
|               PSI3 ter message
|
| Parameters  : Nil
|                
+------------------------------------------------------------------------------
*/
GLOBAL UBYTE grr_get_psi3_cm(void)
{
  UBYTE psi3_cm = NOT_SET;

  TRACE_FUNCTION("grr_get_psi3_cm");

  if(psc_db->psi3_params.psi3_change_mark EQ
     psc_db->psi3bis_params.psi3bis_change_mark) 
  {
    psi3_cm = psc_db->psi3_params.psi3_change_mark;
    
    if(psc_db->psi3ter_params.psi3ter_change_mark NEQ NOT_SET AND
      psc_db->psi3ter_params.psi3ter_change_mark NEQ psi3_cm)
    {
      psi3_cm = NOT_SET;
    }
  }
  return(psi3_cm);
} /* grr_get_psi3_cm */


/*
+------------------------------------------------------------------------------
| Function    : grr_init_ba_bcch_nc_list
+------------------------------------------------------------------------------
| Description : 
|
| Parameters  : list  - pointer to NC measurement list
|
+------------------------------------------------------------------------------
*/
GLOBAL void grr_init_ba_bcch_nc_list(T_SC_DATABASE *db)
{ 
  TRACE_FUNCTION( "grr_init_ba_bcch_nc_list" );
  
  db->nc_ba_bcch_cw.number = 0;
  db->ba_ind = 0; /* BA-IND of BA-BCCH */
}/* grr_init_ba_bcch_nc_list */

#endif 

#endif