FreeCalypso > hg > fc-magnetite
diff src/g23m-gprs/grr/grr_f.c @ 183:219afcfc6250
src/g23m-gprs: initial import from TCS3.2/LoCosto
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 13 Oct 2016 04:24:13 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/g23m-gprs/grr/grr_f.c Thu Oct 13 04:24:13 2016 +0000 @@ -0,0 +1,9768 @@ +/* ++----------------------------------------------------------------------------- +| 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 +