FreeCalypso > hg > fc-magnetite
diff src/g23m-gprs/grlc/grlc_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/grlc/grlc_f.c Thu Oct 13 04:24:13 2016 +0000 @@ -0,0 +1,2394 @@ +/* ++----------------------------------------------------------------------------- +| Project : GPRS (8441) +| Modul : GRLC ++----------------------------------------------------------------------------- +| Copyright 2002 Texas Instruments Berlin, AG +| All rights reserved. +| +| This file is confidential and a trade secret of Texas +| Instruments Berlin, AG +| The receipt of or possession of this file does not convey +| any rights to reproduce or disclose its contents or to +| manufacture, use, or sell anything it may describe, in +| whole, or in part, without the specific written consent of +| Texas Instruments Berlin, AG. ++----------------------------------------------------------------------------- +| Purpose: This module implements global functions for GRLC ++----------------------------------------------------------------------------- +*/ + +#ifndef GRLC_F_C +#define GRLC_F_C +#endif + +#define ENTITY_GRLC + + +/*==== 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_grlc.h" /* to get cnf-definitions */ +#include "mon_grlc.h" /* to get mon-definitions */ +#include "prim.h" /* to get the definitions of used SAP and directions */ +#include "message.h" /* to get message describtion */ +#include "pcm.h" + +#include "grlc.h" /* to get the global entity definitions */ + +#include "grlc_f.h" /* to check own definitions */ +#include "grlc_tmf.h" /* to get definition of tm_grlc_init() */ +#include "grlc_gfff.h" /* to get definition of gff_init() */ +#include "grlc_rdf.h" /* to get definition of rd_init() */ +#include "grlc_ruf.h" /* to get definition of ru_init() */ +#include "grlc_rus.h" +#include "grlc_rds.h" +#include "grlc_tms.h" +#include "grlc_tpcs.h" +#include "grlc_meass.h" +#include "cl_rlcmac.h" + +/*==== CONST ================================================================*/ + +/*==== DIAGNOSTICS ==========================================================*/ + +/*==== LOCAL VARS ===========================================================*/ + +/*==== GLOBAL VARS ===========================================================*/ +/*==== LOCAL MACROS =========================================================*/ + + +/*==== FUNCTIONS PROTOTYPES =================================================*/ + +LOCAL void grlc_encode_dl_acknack ( UBYTE * ptr_out ); + +LOCAL void grlc_encode_ul_dummy ( UBYTE * ptr_out ); + +LOCAL void grlc_encode_pca ( UBYTE * ptr_out ); + +LOCAL UBYTE grlc_decode_ul_acknack ( UBYTE * ptr_blk ); + +LOCAL UBYTE grlc_ccd_error_handling ( UBYTE entity_i ); + +LOCAL USHORT grlc_convert_11bit_2_etsi ( USHORT eleven_bit ); + +/*==== FUNCTIONS ============================================================*/ +/* ++------------------------------------------------------------------------------ +| Function : grlc_encode_dl_acknack ++------------------------------------------------------------------------------ +| Description : The function grlc_encode_dl_acknack() encodes the packet downlink +| ack/nack block without CCD +| +| Parameters : *ptr_out_i- ptr to the buffer where the air message will be placed +| +| ++------------------------------------------------------------------------------ +*/ +LOCAL void grlc_encode_dl_acknack ( UBYTE * ptr_out) +{ + MCAST (u_dl_ack,U_GRLC_DL_ACK); /* T_U_GRLC_DL_ACK */ + + UBYTE i=0, bit=0,byte,bit_in_byte,j; + + TRACE_FUNCTION( "grlc_encode_dl_acknack" ); + + /******************* mandatory elements ****************************/ + + /* MESSAGE TYPE 6 bit */ + ptr_out[0] = u_dl_ack->msg_type << 2; + bit +=6; + /* DL TFI 5 bit */ + ptr_out[0] |= (u_dl_ack->dl_tfi >> 3) & 0x03; + ptr_out[1] = (u_dl_ack->dl_tfi << 5); + bit +=5; + /* ACK NACK DESCRIPTION */ + /* final ack indication 1 bit */ + ptr_out[1] |= (u_dl_ack->ack_nack_des.f_ack_ind << 4); + bit +=1; + /* ssn 7 bit */ + ptr_out[1] |= (u_dl_ack->ack_nack_des.ssn >> 3); + ptr_out[2] = (u_dl_ack->ack_nack_des.ssn << 5); + bit +=7; + for (i=0;i<64; i++) + { + byte = bit / 8; /* byte pos */ + bit_in_byte = bit % 8; /* rel bit pos in the current byte */ + ptr_out[byte] |= u_dl_ack->ack_nack_des.rbb[i] << (7-bit_in_byte); + bit +=1; + } + /* CHANNEL REQUEST DESCRIPTION */ + /* valid flag*/ + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= u_dl_ack->v_chan_req_des << (7-bit_in_byte); + bit +=1; + if(u_dl_ack->v_chan_req_des) + { + /* peak_thr_class */ + for(i=0;i<4;i++) + { + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= (u_dl_ack->chan_req_des.peak_thr_class >> (3-i)) << (7-bit_in_byte); + bit +=1; + } + /* radio prio */ + for(i=0;i<2;i++) + { + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= (u_dl_ack->chan_req_des.radio_prio >> (1-i)) << (7-bit_in_byte); + bit +=1; + } + /* rlc_mode*/ + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= (u_dl_ack->chan_req_des.rlc_mode) << (7-bit_in_byte); + bit +=1; + /* llc pdu type*/ + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= (u_dl_ack->chan_req_des.llc_pdu_type) << (7-bit_in_byte); + bit +=1; + /* rlc_oct_cnt */ + for(i=0;i<16;i++) + { + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= (u_dl_ack->chan_req_des.rlc_octet_cnt >> (15-i)) << (7-bit_in_byte); + bit +=1; + } + } + /* CHANNEL QUALITY REPORT */ + /* c_value */ + for(i=0;i<6;i++) + { + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= (u_dl_ack->chan_qual_rep.c_value >> (5-i)) << (7-bit_in_byte); + bit +=1; + } + /* rxqual */ + for(i=0;i<3;i++) + { + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= (u_dl_ack->chan_qual_rep.rxqual >> (2-i)) << (7-bit_in_byte); + bit +=1; + } + /* signvar */ + for(i=0;i<6;i++) + { + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= (u_dl_ack->chan_qual_rep.signvar >> (5-i)) << (7-bit_in_byte); + bit +=1; + } + /* c_value */ + for(j=0;j<8;j++) + { + UBYTE flag,value; + + switch(j) + { + case 0: + flag = u_dl_ack->chan_qual_rep.ilev.v_ilev0; + value = u_dl_ack->chan_qual_rep.ilev.ilev0; + break; + case 1: + flag = u_dl_ack->chan_qual_rep.ilev.v_ilev1; + value = u_dl_ack->chan_qual_rep.ilev.ilev1; + break; + case 2: + flag = u_dl_ack->chan_qual_rep.ilev.v_ilev2; + value = u_dl_ack->chan_qual_rep.ilev.ilev2; + break; + case 3: + flag = u_dl_ack->chan_qual_rep.ilev.v_ilev3; + value = u_dl_ack->chan_qual_rep.ilev.ilev3; + break; + case 4: + flag = u_dl_ack->chan_qual_rep.ilev.v_ilev4; + value = u_dl_ack->chan_qual_rep.ilev.ilev4; + break; + case 5: + flag = u_dl_ack->chan_qual_rep.ilev.v_ilev5; + value = u_dl_ack->chan_qual_rep.ilev.ilev5; + break; + case 6: + flag = u_dl_ack->chan_qual_rep.ilev.v_ilev6; + value = u_dl_ack->chan_qual_rep.ilev.ilev6; + break; + case 7: + flag = u_dl_ack->chan_qual_rep.ilev.v_ilev7; + value = u_dl_ack->chan_qual_rep.ilev.ilev7; + break; + default: + TRACE_EVENT_P1("no valid j=%d value during grlc_encode_dl_acknack should not appear ",j); + flag = 0; + value = 0; + break; + } + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= (flag) << (7-bit_in_byte); + bit +=1; + if(flag) + { + for(i=0;i<4;i++) + { + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= (value >> (3-i)) << (7-bit_in_byte); + bit +=1; + } + } + } + + /* RELEASE 99*/ +#ifdef REL99 + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= u_dl_ack->v_release_99_str_u_grlc_dl_ack << (7-bit_in_byte); + bit +=1; + + if(u_dl_ack->v_release_99_str_u_grlc_dl_ack) + { + byte = bit / 8; + bit_in_byte = bit % 8; + + if(u_dl_ack->release_99_str_u_grlc_dl_ack.v_pfi) + { + ptr_out[byte] |= u_dl_ack->release_99_str_u_grlc_dl_ack.v_pfi << (7-bit_in_byte); + bit +=1; + for(i=0;i<6;i++) + { + byte = bit / 8; + bit_in_byte = bit % 8; + ptr_out[byte] |= (u_dl_ack->release_99_str_u_grlc_dl_ack.pfi >> (6-i)) << (7-bit_in_byte); + bit +=1; + } + + } + else + { + ptr_out[byte] |= u_dl_ack->release_99_str_u_grlc_dl_ack.v_pfi << (7-bit_in_byte); + bit +=1; + } + } + + bit++; +#endif + + /* SPARE PADDINGS */ + byte = bit / 8; + bit_in_byte = bit % 8; + + if(bit_in_byte < 7) + { + UBYTE mask; + + mask= 0xff >> (bit_in_byte); + mask &= 0x2B; + ptr_out[byte] |= mask; + } + for(i=byte;i<22;i++) + { + byte++; + ptr_out[byte] = 0x2B; + + } +} /* grlc_encode_dl_acknack() */ + +/* ++------------------------------------------------------------------------------ +| Function : grlc_encode_ul_dummy ++------------------------------------------------------------------------------ +| Description : The function grlc_encode_ul_dummy() encodes the packet uplink +| dummy block without CCD +| +| Parameters : *ptr_out_i- ptr to the buffer where the air message will be placed +| +| ++------------------------------------------------------------------------------ +*/ +LOCAL void grlc_encode_ul_dummy ( UBYTE * ptr_out) +{ + MCAST (ul_dummy,U_GRLC_UL_DUMMY); /* T_U_GRLC_UL_DUMMY */ + + UBYTE i; + + TRACE_FUNCTION( "grlc_encode_ul_dummy" ); + + /******************* mandatory elements ****************************/ + + ptr_out[0] = ul_dummy->msg_type << 2; + ptr_out[0] |= (UBYTE) (grlc_data->uplink_tbf.tlli >> 30); /* 1100 0000 0000 0000 0000 0000 0000 0000 */ + ptr_out[1] = (UBYTE) ((grlc_data->uplink_tbf.tlli & 0x3FC00000) >> 22); /* 0011 1111 1100 0000 0000 0000 0000 0000 */ + ptr_out[2] = (UBYTE) ((grlc_data->uplink_tbf.tlli & 0x003FC000) >> 14); /* 0000 0000 0011 1111 1100 0000 0000 0000 */ + ptr_out[3] = (UBYTE) ((grlc_data->uplink_tbf.tlli & 0x00003FC0) >> 6); /* 0000 0000 0000 0000 0011 1111 1100 0000 */ + ptr_out[4] = (UBYTE) ((grlc_data->uplink_tbf.tlli & 0x0000003F) << 2); /* 0000 0000 0000 0000 0000 0000 0011 1111 */ + ptr_out[4] |= 0x01; /* spare paddings */ + + for(i=5;i<22;i++) + ptr_out[i] = 0x2B; +} /* grlc_encode_ul_dummy() */ + +/* ++------------------------------------------------------------------------------ +| Function : grlc_encode_pca ++------------------------------------------------------------------------------ +| Description : The function grlc_encode_pca() encodes the packet control +| acknowledgement block without CCD +| +| Parameters : *ptr_out_i- ptr to the buffer where the air message will be placed +| +| ++------------------------------------------------------------------------------ +*/ +LOCAL void grlc_encode_pca ( UBYTE * ptr_out) +{ + MCAST(u_ctrl_ack,U_GRLC_CTRL_ACK); /* T_U_GRLC_CTRL_ACK */ + + UBYTE i; + + TRACE_FUNCTION( "grlc_encode_pca" ); + + /******************* mandatory elements ****************************/ + + ptr_out[0] = u_ctrl_ack->msg_type << 2; + ptr_out[0] |= (UBYTE) (grlc_data->uplink_tbf.tlli >> 30); /* 1100 0000 0000 0000 0000 0000 0000 0000 */ + ptr_out[1] = (UBYTE) ((grlc_data->uplink_tbf.tlli & 0x3FC00000) >> 22); /* 0011 1111 1100 0000 0000 0000 0000 0000 */ + ptr_out[2] = (UBYTE) ((grlc_data->uplink_tbf.tlli & 0x003FC000) >> 14); /* 0000 0000 0011 1111 1100 0000 0000 0000 */ + ptr_out[3] = (UBYTE) ((grlc_data->uplink_tbf.tlli & 0x00003FC0) >> 6); /* 0000 0000 0000 0000 0011 1111 1100 0000 */ + ptr_out[4] = (UBYTE) ((grlc_data->uplink_tbf.tlli & 0x0000003F) << 2); /* 0000 0000 0000 0000 0000 0000 0011 1111 */ + ptr_out[4] |= u_ctrl_ack->pctrl_ack & 0x03; + + for(i=5;i<22;i++) + ptr_out[i] = 0x2B; +} /* grlc_encode_pca() */ +/* ++------------------------------------------------------------------------------ +| Function : grlc_decode_ul_acknack ++------------------------------------------------------------------------------ +| Description : The function grlc_decode_ul_acknack() decodes the packet uplink +| ack/nack without CCD +| +| Parameters : *ptr_blk- ptr to the air message +| +| Return value: returns decode status of air message:ccdOK,ccdWarning,ccdError +| ++------------------------------------------------------------------------------ +*/ +LOCAL UBYTE grlc_decode_ul_acknack ( UBYTE *ptr_blk ) +{ + MCAST(d_ul_ack,D_GRLC_UL_ACK);/* T_D_GRLC_UL_ACK */ + + UBYTE i,j,k; + UBYTE bit_pos; +#ifdef REL99 + UBYTE flag; +#endif + + UBYTE result =ccdOK; + + TRACE_FUNCTION( "grlc_decode_ul_acknack" ); + + /******************* mandatory elements ****************************/ + + d_ul_ack->msg_type = (ptr_blk[0] & 0xFC) >> 2 ; + d_ul_ack->page_mode = ptr_blk[0] & 0x03; + + if((ptr_blk[1] & 0xC0)) /* distrubiton part error check */ + { + TRACE_ERROR("P UL ACK: DISTRUBITION PART ERROR"); + TRACE_EVENT_P2("P UL ACK: DISTRUBITION PART ERROR byte = 0x2%x res = 0x%2x",ptr_blk[1] ,ptr_blk[1] & 0xC0); + return ccdError; + } + d_ul_ack->ul_tfi = (ptr_blk[1] & 0x3E) >> 1; + + if((ptr_blk[1] & 0x01)) /* message escape bit check */ + { +#ifdef REL99 + d_ul_ack->egprs_flag = TRUE; +#endif + TRACE_ERROR("P UL ACK: MESSAGE ESCAPE ERROR"); + TRACE_EVENT_P2("P UL ACK: MESSAGE ESCAPE ERROR byte = 0x2%x res = 0x%2x",ptr_blk[1] ,ptr_blk[1] & 0x01); + return ccdError; + } + + d_ul_ack->v_gprs_ul_ack_nack_info = TRUE; + + d_ul_ack->gprs_ul_ack_nack_info.chan_coding_cmd = (ptr_blk[2] & 0xC0) >> 6; + +#ifdef _SIMULATION_ + TRACE_EVENT_P2("tfi=%d ch_c_cmd=%d",d_ul_ack->ul_tfi,d_ul_ack->gprs_ul_ack_nack_info.chan_coding_cmd); +#endif /* _SIMULATION_ */ + /******************* Ack/Nack description ****************************/ + d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.f_ack_ind = (ptr_blk[2] & 0x20) >> 5; + d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.ssn = (ptr_blk[2] << 2) & 0x7C; + d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.ssn |= (ptr_blk[3] >> 6) & 0x03; + + j= 3; /* inital byte of rbb field */ + k= 2; /* inital bit of rbb field */ + + for(i=0; i< 64;i++) + { + d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.rbb[i] = (ptr_blk[j] & (0x80>>k)) >> (7-k); + k++; + if(k EQ 8) + { + k=0; + j++; + } + } +#ifdef _SIMULATION_ + TRACE_EVENT_P2("fai=%d ssn=%d",d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.f_ack_ind,d_ul_ack->gprs_ul_ack_nack_info.ack_nack_des.ssn); +#endif /* _SIMULATION_ */ + + bit_pos = 91; /* abs bit position */ + + /******************* contention resolution tlli ***********************/ + + j = bit_pos / 8; /* byte pos */ + k = bit_pos % 8; /* rel bit pos */ + + d_ul_ack->gprs_ul_ack_nack_info.v_cr_tlli = (ptr_blk[j] >> (8-k)) & 0x01; + + bit_pos++; + + if(d_ul_ack->gprs_ul_ack_nack_info.v_cr_tlli) + { + d_ul_ack->gprs_ul_ack_nack_info.cr_tlli.l_cr_tlli = 32; + d_ul_ack->gprs_ul_ack_nack_info.cr_tlli.o_cr_tlli = 3; + d_ul_ack->gprs_ul_ack_nack_info.cr_tlli.b_cr_tlli[0] = ptr_blk[j]; + d_ul_ack->gprs_ul_ack_nack_info.cr_tlli.b_cr_tlli[1] = ptr_blk[j+1]; + d_ul_ack->gprs_ul_ack_nack_info.cr_tlli.b_cr_tlli[2] = ptr_blk[j+2]; + d_ul_ack->gprs_ul_ack_nack_info.cr_tlli.b_cr_tlli[3] = ptr_blk[j+3]; + d_ul_ack->gprs_ul_ack_nack_info.cr_tlli.b_cr_tlli[4] = ptr_blk[j+4]; + bit_pos+=32; + } + +#ifdef REL99 + /******************* packet timing advance ****************************/ + j = bit_pos / 8; /* byte pos */ + k = bit_pos % 8; /* rel bit pos */ + flag = (ptr_blk[j] >> (8-k)) & 0x01; + bit_pos++; + if(flag) + { + } + /******************* power control params ****************************/ + j = bit_pos / 8; /* byte pos */ + k = bit_pos % 8; /* rel bit pos */ + flag = (ptr_blk[j] >> (8-k)) & 0x01; + bit_pos++; + if(flag) + { + } + /******************* Extension bits ****************************/ + j = bit_pos / 8; /* byte pos */ + k = bit_pos % 8; /* rel bit pos */ + flag = (ptr_blk[j] >> (8-k)) & 0x01; + bit_pos++; + if(flag) + { + } + /******************* Fixed Alloc ****************************/ + j = bit_pos / 8; /* byte pos */ + k = bit_pos % 8; /* rel bit pos */ + flag = (ptr_blk[j] >> (8-k)) & 0x01; + bit_pos++; + if(flag) + { + } + /******************* R99 FLAG ****************************/ + j = bit_pos / 8; /* byte pos */ + k = bit_pos % 8; /* rel bit pos */ + bit_pos++; + d_ul_ack->gprs_ul_ack_nack_info.v_release_99_str_d_ul_ack = (ptr_blk[j] >> (8-k)) & 0x01; + /******************* Extended PTA ****************************/ + j = bit_pos / 8; /* byte pos */ + k = bit_pos % 8; /* rel bit pos */ + flag = (ptr_blk[j] >> (8-k)) & 0x01; + bit_pos++; + if(flag) + { + } + /**********************************************************************/ + j = bit_pos / 8; /* byte pos */ + k = bit_pos % 8; /* rel bit pos */ + d_ul_ack->gprs_ul_ack_nack_info.release_99_str_d_ul_ack.tbf_est = (ptr_blk[j] >> (8-k)) & 0x01; + +#endif + + return(result); + +} /* grlc_decode_ul_acknack() */ + +/* ++------------------------------------------------------------------------------ +| Function : grlc_ccd_error_handling ++------------------------------------------------------------------------------ +| Description : The function grlc_ccd_error_handling() ... +| +| Parameters : entity_i - the CCD was called for this entity +| ++------------------------------------------------------------------------------ +*/ +LOCAL UBYTE grlc_ccd_error_handling ( UBYTE entity_i ) +{ + UBYTE result = DELETE_MESSAGE; + USHORT parlist [MAX_ERR_PAR]; + UBYTE first_error; + + TRACE_FUNCTION( "grlc_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_GRLC_UL_ACK); + result = ptr->msg_type; + } + break; + + default: + /* SZML-GLBL/010 */ + TRACE_ERROR( "Ctrl-Message will be deleted" ); + break; + } + + return(result); + +} /* grlc_ccd_error_handling() */ + + +/*==== PUBLIC FUNCTIONS =====================================================*/ + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_buffer2ulong ++------------------------------------------------------------------------------ +| Description : The function grlc_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 grlc_buffer2ulong ( BUF_cr_tlli *tlli) +{ + ULONG ul; + + UBYTE l, dummy; + USHORT i, ii; + UBYTE off1, off2; + + TRACE_FUNCTION( "grlc_buffer2ulong "); + + ul= 0; + + l = (UBYTE)tlli->l_cr_tlli; + + off1 = tlli->o_cr_tlli / 8; + off2 = tlli->o_cr_tlli % 8; + + dummy = 0; + dummy = tlli->b_cr_tlli[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 = tlli->b_cr_tlli[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 |= tlli->b_cr_tlli[off1]; + l -= 8; + if(l EQ 0) + return ul; + } + } + while(TRUE); +} + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_delete_prim ++------------------------------------------------------------------------------ +| Description : The function grlc_delete_prim() deletes the primitive that is +| pointed by the grlc_data->prim_start_tbf and sets the +| grlc_data->prim_start_tbf to the next entry in the tbf list. +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_delete_prim ( void ) +{ + TRACE_FUNCTION( "grlc_delete_prim" ); + + /* + * access type is reseted + */ + grlc_data->uplink_tbf.access_type = CGRLC_AT_NULL; + + if(grlc_data->prim_start_tbf < PRIM_QUEUE_SIZE_TOTAL) + { + UBYTE i; + + /* + * get first entry from tbf list + */ + i = grlc_prim_get_first (&grlc_data->prim_start_tbf); + + + if(i >= PRIM_QUEUE_SIZE) + { + TRACE_EVENT_P5("delete prim VOR i=%d ps=%d, pf=%d,sps=%d,spf=%d", + i, + grlc_data->prim_start_tbf, + grlc_data->prim_start_free, + grlc_data->save_prim_start_tbf, + grlc_data->save_prim_start_free); + } + + /* + * estimate new user data amount in queue + */ + grlc_data->prim_user_data -= BYTELEN(grlc_data->prim_queue[i].prim_ptr->sdu.l_buf); + + /* + * free primitive before reset old primitive entry + */ + PFREE ( grlc_data->prim_queue[i].prim_ptr ); + + /* + * reset old primitive + */ + grlc_data->prim_queue[i].prim_ptr = NULL; + grlc_data->prim_queue[i].prim_type = CGRLC_LLC_PRIM_TYPE_NULL; + grlc_data->prim_queue[i].cv_status = FALSE; + grlc_data->prim_queue[i].rlc_status = FALSE; + grlc_data->prim_queue[i].re_allocation = FALSE; + grlc_data->prim_queue[i].start_new_tbf = FALSE; + grlc_data->prim_queue[i].last_bsn = 0xff; + grlc_data->prim_queue[i].previous = 0xff; + + /* + * put new entry at the end of free list + */ + + if(i < PRIM_QUEUE_SIZE) + { + grlc_prim_put(&grlc_data->prim_start_free,i,END_OF_LIST); + } + else if(grlc_data->gmm_procedure_is_running) + { + grlc_prim_put(&grlc_data->prim_start_free,i,END_OF_LIST); + TRACE_EVENT_P5("delete prim %d AFTER PST=%d, PSF=%d,spst=%d,spsf=%d", + i, + grlc_data->prim_start_tbf, + grlc_data->prim_start_free, + grlc_data->save_prim_start_tbf, + grlc_data->save_prim_start_free); + } + + /* + * update LLC flow control state + */ + if ((grlc_data->tm.send_grlc_ready_ind EQ PRIM_QUEUE_FULL) AND /* PRIM QUEUE IS FULL */ + ( + (!grlc_data->gmm_procedure_is_running AND (i < PRIM_QUEUE_SIZE)) OR /* LLC QUEUE IS ACTIVE, PDU FROM LLC QUEUE DELETED */ + (grlc_data->gmm_procedure_is_running AND !(i < PRIM_QUEUE_SIZE)))) /* GMM QUEUE IS ACTIVE, PDU FROM GMM QUEUE DELETED */ + { + TRACE_EVENT_P3("Flow control activated gmm_q=%d,i=%d,ready=%d",grlc_data->gmm_procedure_is_running,i,grlc_data->tm.send_grlc_ready_ind); + grlc_data->tm.send_grlc_ready_ind = SEND_A_GRLC_READY_IND; + } + + grlc_data->grlc_data_req_cnt--; + } + else + { + TRACE_EVENT_P3("PST=%d PSF=%d PDU=%d: grlc_delete_prim" + ,grlc_data->prim_start_tbf + ,grlc_data->prim_start_free + ,grlc_data->grlc_data_req_cnt); + return; + } + + +} /* grlc_delete_prim() */ + + + + + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_calc_new_poll_pos ++------------------------------------------------------------------------------ +| Description : The function grlc_calc_new_poll_pos() calculates the fn of the +| new poll position +| +| Parameters : fn_i - framenumber +| rrbp_i - relative position +| ++------------------------------------------------------------------------------ +*/ +GLOBAL ULONG grlc_calc_new_poll_pos ( ULONG fn_i, UBYTE rrbp_i ) +{ + ULONG result=0; + TRACE_FUNCTION( "grlc_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; + +} /* grlc_calc_new_poll_pos() */ + + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_get_new_poll_index ++------------------------------------------------------------------------------ +| Description : The function grlc_get_new_poll_index() +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +LOCAL UBYTE grlc_get_new_poll_index ( UBYTE * ptr_list_start_i ) +{ + UBYTE result; + TRACE_FUNCTION( "grlc_get_new_poll_index" ); + + result = *ptr_list_start_i; + /* set to new first entry */ + if (result NEQ 0xFF) + { + *ptr_list_start_i = grlc_data->next_poll_array[*ptr_list_start_i].next; + /* remove first entry from list */ + grlc_data->next_poll_array[result].next = 0xff; + } + else + { + TRACE_EVENT ("Poll array is full"); + } + + return(result); + +} /* grlc_get_new_poll_index() */ + + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_save_poll_pos ++------------------------------------------------------------------------------ +| Description : The function grlc_save_poll_pos() +| +| Parameters : fn_i - framenumber +| tn_i - timeslot number +| rrbp_i - fn of the poll block| +| poll_type_i - kind of dl data +| pctrl_ack_i - packet control ack value, needed fo p ctr ack msg +| +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_save_poll_pos ( ULONG fn_i, USHORT tn_i, UBYTE rrbp_i, UBYTE poll_type_i,UBYTE pctrl_ack_i) +{ + ULONG new_poll_pos; + UBYTE i, next, help_index; + + TRACE_FUNCTION( "grlc_save_poll_pos" ); + + if( tn_i >= POLL_TYPE_ARRAY_SIZE ) + { + TRACE_EVENT_P5( "grlc_save_poll_pos: fn = %d, tn = %d, rrbp = %d, poll_type = %d, pctrl_ack = %d", + fn_i, tn_i, rrbp_i, poll_type_i, pctrl_ack_i ); + + return; + } + + if(0xFF NEQ rrbp_i) + { + new_poll_pos = grlc_calc_new_poll_pos(fn_i, rrbp_i); + } + else + { + new_poll_pos = fn_i; + } + + /*TRACE_EVENT_P6("SAVE BEF: fn_i= %ld,rrbp=%ld,new_poll_pos=%ld, poll_type=%d,ps=%d ps_fn=%ld", + fn_i, + rrbp_i, + new_poll_pos, + poll_type_i, + grlc_data->poll_start_tbf, + grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn); + + */ + /* delete the poll position when it is older than 26 frames */ + while( grlc_data->poll_start_tbf NEQ 0xFF AND + grlc_check_dist(new_poll_pos, + grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn, 26) EQ FALSE) + { + /* move the expired poll position to the list of unused entries */ + TRACE_EVENT_P1("Remove expired poll at pst=%d",grlc_data->poll_start_tbf); + help_index = grlc_data->poll_start_tbf; + grlc_data->poll_start_tbf = grlc_data->next_poll_array[help_index].next; + grlc_data->next_poll_array[help_index].next = grlc_data->poll_start_free; + grlc_data->poll_start_free = help_index; + + /* clear the poll position */ + grlc_data->next_poll_array[help_index].fn = 0xFFFFFFFF; + grlc_data->next_poll_array[help_index].cnt = 0; + + for( i = 0; i < POLL_TYPE_ARRAY_SIZE; i++ ) + { + grlc_data->next_poll_array[help_index].poll_type[i] = CGRLC_POLL_NONE; + } + } + + next = 0xFF; + help_index = grlc_data->poll_start_tbf; + + + /* + * find the position of the new fn + */ + + while( help_index NEQ 0xFF ) + { + if( grlc_data->next_poll_array[help_index].fn EQ new_poll_pos ) + { + next = help_index; + help_index = 0xFF; + } + else if( grlc_check_dist( new_poll_pos, grlc_data->next_poll_array[help_index].fn, 26 ) ) + { + next = help_index; + help_index = grlc_data->next_poll_array[help_index].next; + } + else + { + help_index = 0xFF; + } + } + + /* + * new_poll_pos is present in the poll array + */ + if( next NEQ 0xFF AND + grlc_data->next_poll_array[next].fn EQ new_poll_pos AND + grlc_data->next_poll_array[next].poll_type[tn_i] EQ CGRLC_POLL_NONE ) + { + /* + * no collision + */ + grlc_data->next_poll_array[next].poll_type[tn_i] = poll_type_i; + grlc_data->next_poll_array[next].cnt++; + grlc_data->next_poll_array[next].ctrl_ack = pctrl_ack_i; + } + else if( next NEQ 0xFF AND + grlc_data->next_poll_array[next].fn EQ new_poll_pos ) + + { + /* + * collision detected, if both pos were received with data blocks, the sent + * RLC/MAC block otherwise send packet control ack. + */ + if ((poll_type_i NEQ CGRLC_POLL_DATA) + OR + (grlc_data->next_poll_array[next].poll_type[tn_i] NEQ CGRLC_POLL_DATA)) + { + grlc_data->next_poll_array[next].poll_type[tn_i] = CGRLC_POLL_COLLISION; + TRACE_EVENT("collision detected: pca will sent"); + } + else + { + TRACE_EVENT("collision detected: rlc/mac will be sent"); + } + if(pctrl_ack_i NEQ 3) + grlc_data->next_poll_array[next].ctrl_ack = pctrl_ack_i; + } + else + { + /* + * fn does not exist in the poll list, included in poll list + * + * get new free index from the free list + */ + i = grlc_get_new_poll_index(&(grlc_data->poll_start_free)); + if( i EQ 0xFF ) + { + TRACE_EVENT ("Poll array is full"); /*This should not happen */ + return; + } + + grlc_data->next_poll_array[i].cnt = 1; + grlc_data->next_poll_array[i].fn = new_poll_pos; + grlc_data->next_poll_array[i].poll_type[tn_i] = poll_type_i; + grlc_data->next_poll_array[i].ctrl_ack = pctrl_ack_i; + + if( next EQ 0xFF ) + { + /* + * first entry in poll array + */ + grlc_data->next_poll_array[i].next = grlc_data->poll_start_tbf; + grlc_data->poll_start_tbf = i; + } + else if( next < NEXT_POLL_ARRAY_SIZE ) + { + /* + * include in description list, is not first element + */ + grlc_data->next_poll_array[i].next = grlc_data->next_poll_array[next].next; + grlc_data->next_poll_array[next].next = i; + } + else + { + TRACE_ASSERT( next < NEXT_POLL_ARRAY_SIZE ); + } + } + + + /*TRACE_EVENT_P6("SAVE AFTER: fn_i= %ld,rrbp=%ld,new_poll_pos=%ld, poll_type=%d,ps=%d ps_fn=%ld", + fn_i, + rrbp_i, + new_poll_pos, + poll_type_i, + grlc_data->poll_start_tbf, + grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn); + */ + +} /* grlc_save_poll_pos() */ + + + + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_encode_ctrl ++------------------------------------------------------------------------------ +| Description : The function grlc_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 grlc_encode_ctrl ( UBYTE * ptr_in_i, + T_MSGBUF * ptr_out_i, + UBYTE r_bit_i) +{ + TRACE_FUNCTION( "grlc_encode_ctrl" ); + + ptr_out_i->buf[0] = 0x40 | r_bit_i; + ptr_out_i->o_buf = BIT_UL_CTRL_BLOCK_MAC_HEADER; + ptr_out_i->l_buf = BIT_UL_CTRL_BLOCK_CONTENTS; + + + if(!grlc_data->grlc_wo_ccd) + { + ccd_codeMsg ( CCDENT_GRLC, + UPLINK, + ptr_out_i, + ptr_in_i, + NOT_PRESENT_8BIT); + } + else + { + switch(ptr_in_i[0]) /* msg_type */ + { + case U_GRLC_UL_DUMMY_c: + grlc_encode_ul_dummy(&ptr_out_i->buf[1]); + break; + case U_GRLC_CTRL_ACK_c: + grlc_encode_pca(&ptr_out_i->buf[1]); + break; + case U_GRLC_DL_ACK_c: + memset(&ptr_out_i->buf[1],0,22); /*lint !e419*/ + grlc_encode_dl_acknack(&ptr_out_i->buf[1]); + break; + default: + ccd_codeMsg ( CCDENT_GRLC, + UPLINK, + ptr_out_i, + ptr_in_i, + NOT_PRESENT_8BIT); + break; + } + } + ptr_out_i->l_buf += ptr_out_i->o_buf; + ptr_out_i->o_buf = 0; + +} /* grlc_encode_ctrl() */ + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_init ++------------------------------------------------------------------------------ +| Description : The function grlc_init initializes the entity GRLC +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_init ( void ) +{ + TRACE_FUNCTION( "grlc_init" ); + + /* initialize all GRLC data */ + grlc_data = &grlc_data_base; + memset( grlc_data, 0, sizeof( T_GRLC_DATA ) ); + + grlc_data->grlc_data_req_cnt = 0; + grlc_data->testmode.mode = CGRLC_NO_TEST_MODE; + + grlc_data->meas.sq_restart = TRUE; + + /* + * call of service init functions + */ + tm_grlc_init(); + rd_init(); + ru_init(); + meas_grlc_init(); + tpc_grlc_init(); + gff_init(); + + ccd_register(CCD_REENTRANT); + +#ifdef _SIMULATION_ + /* + * to make sure that the structure definitions of T_GRLC_DATA_REQ and + * T_GRLC_UNITDATA_REQ have the same layout. + */ + { + T_GRLC_DATA_REQ * ptr_grlc_data_req = (T_GRLC_DATA_REQ *)_decodedMsg; + T_GRLC_UNITDATA_REQ * ptr_grlc_unitdata_req = (T_GRLC_UNITDATA_REQ *)_decodedMsg; + + if( &(ptr_grlc_data_req->grlc_qos) NEQ &(ptr_grlc_unitdata_req->grlc_qos) AND + &(ptr_grlc_data_req->radio_prio) NEQ &(ptr_grlc_unitdata_req->radio_prio) AND + &(ptr_grlc_data_req->sdu) NEQ &(ptr_grlc_unitdata_req->sdu) AND + &(ptr_grlc_data_req->tlli) NEQ &(ptr_grlc_unitdata_req->tlli) ) + { + /* + * In this case the primitive handling will not work correctly!!! + */ + TRACE_ERROR("Fatal ERROR: T_GRLC_UNITDATA_REQ and T_GRLC_DATA_REQ are not equal!!"); + } + } /* _SIMULATION_ */ +#endif + + grlc_data->t3164_to_cnt = 0; + grlc_data->ul_tfi_changed = FALSE; + grlc_data->uplink_tbf.access_type = CGRLC_AT_NULL; /* NO CELL UPDATE NEED */ + grlc_data->grlc_wo_ccd = 0; /* as default ccd used for air message handling */ + + /* + * Ready Timer state initialization + */ +#ifdef FF_GRLC_4_TWO_2_ONE + grlc_data->ready_timer.handling = READY_TIMER_HANDLING_ENABLED; +#else + grlc_data->ready_timer.handling = READY_TIMER_HANDLING_DISABLED; +#endif + + grlc_data->ready_timer.state = STANDBY_STATE; + grlc_data->ready_timer.value = CGRLC_T3314_DEFAULT; + +} /* grlc_init() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_prim_put ++------------------------------------------------------------------------------ +| Description : The function grlc_prim_put() put a Element (object_i) behind +| pos_i in the prim_queue. +| +| Parameters : list_start_i - address of the list should be manipulted +| object_i - index of element that should be added to the list +| pos_i - index of the position behind that the object +| should be added +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_prim_put(UBYTE * list_start_i, UBYTE object_i, UBYTE pos_i) +{ + TRACE_FUNCTION( "grlc_prim_put" ); + + if(* list_start_i EQ 0xff) + { /* no elements in the list */ + * list_start_i = object_i; + } + else + { /* elements in the list */ + UBYTE i = * list_start_i; + UBYTE j; + BOOL put= FALSE; + + /* + * SZML-GLBL/004 + */ + for(j=0;j<PRIM_QUEUE_SIZE_TOTAL;j++) + { + if (grlc_data->prim_queue[i].next NEQ pos_i) + { + i = grlc_data->prim_queue[i].next; + } + else + { + /* + * put new object at pos_i of queue + */ + put = TRUE; + grlc_data->prim_queue[object_i].next = grlc_data->prim_queue[i].next; + grlc_data->prim_queue[i].next = object_i; + break; + } + } + if(!put) + TRACE_EVENT_P3("PST=%d PSF=%d PDU=%d: grlc_prim_put failed" + ,grlc_data->prim_start_tbf + ,grlc_data->prim_start_free + ,grlc_data->grlc_data_req_cnt); + + } +} /* grlc_prim_put() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_prim_get_first ++------------------------------------------------------------------------------ +| Description : The function grlc_prim_get_first() removes the first element +| and returns the index of the first element. +| +| Parameters : list_start_i - address of the list that should be used +| ++------------------------------------------------------------------------------ +*/ +GLOBAL UBYTE grlc_prim_get_first(UBYTE * list_start_i) +{ + UBYTE result; + TRACE_FUNCTION( "grlc_prim_get_first" ); + + result = *list_start_i; + + /* + * set to new first entry + */ + *list_start_i = grlc_data->prim_queue[*list_start_i].next; + + /* + * remove first entry from list + */ + grlc_data->prim_queue[result].next = 0xff; + + return(result); + +} /* grlc_prim_get_first() */ + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_set_packet_ctrl_ack ++------------------------------------------------------------------------------ +| Description : The function grlc_set_packet_ctrl_ack() | +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL UBYTE * grlc_set_packet_ctrl_ack(void) +{ + MCAST(u_ctrl_ack,U_GRLC_CTRL_ACK); + UBYTE * result; + TRACE_FUNCTION( "grlc_set_packet_ctrl_ack" ); + + u_ctrl_ack->msg_type = U_GRLC_CTRL_ACK_c; + + grlc_set_buf_tlli( &u_ctrl_ack->tlli_value, grlc_data->uplink_tbf.tlli ); + + if(grlc_data->poll_start_tbf NEQ 0xFF) + u_ctrl_ack->pctrl_ack = grlc_data->next_poll_array[grlc_data->poll_start_tbf].ctrl_ack; + else /* response to IA poll */ + u_ctrl_ack->pctrl_ack = 3; + + result = _decodedMsg; + + return(result); + +} /* grlc_set_packet_ctrl_ack() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_send_access_burst ++------------------------------------------------------------------------------ +| Description : The function grlc_send_access_burst() sents the poll as +| four access burst type +| +| Parameters : tn_i : timeslot where the access burst shall send +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_send_access_burst(UBYTE tn_i) +{ + TRACE_FUNCTION( "grlc_send_access_burst" ); + + + + if(grlc_data->poll_start_tbf NEQ 0xFF) + { + grlc_data->next_poll_array[grlc_data->poll_start_tbf].cnt--; + grlc_data->next_poll_array[grlc_data->poll_start_tbf].poll_type[tn_i] = CGRLC_POLL_NONE; + grlc_data->next_poll_fn = grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn; + } + grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].tn = tn_i; + if(grlc_data->ab_type EQ CGRLC_AB_11_BIT) + { + /*11 bit access burst*/ + USHORT elevenBit = 0x07E4+grlc_data->next_poll_array[grlc_data->poll_start_tbf].ctrl_ack; + grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].block_status = 8; + grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].ul_block[0] = grlc_convert_11bit_2_etsi(elevenBit); + /* + TRACE_EVENT_P2("PCA AB_11_BIT sent fn_i= %ld PRACH11: %d" + ,grlc_data->next_poll_fn + ,grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].ul_block[0]); + */ + } + else + { + /*8 bit access burst*/ + grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].block_status = 7; + grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].ul_block[0] = (0x7C+grlc_data->next_poll_array[grlc_data->poll_start_tbf].ctrl_ack); + /* + TRACE_EVENT_P1 ("PCA 8 bit access burst sent fn_i= %ld ",grlc_data->next_poll_fn); + */ + } + +#ifdef _SIMULATION_ + { + PALLOC(mac_poll_req,MAC_POLL_REQ); + memset(mac_poll_req,0, + sizeof(T_MAC_POLL_REQ)); + memcpy(&(mac_poll_req->ul_poll_resp), + &(grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index]), + sizeof(T_ul_poll_resp)); + PSEND(hCommL1,mac_poll_req); + } +#else /* #ifdef _SIMULATION_ */ + { + TRACE_MEMORY_PRIM ( hCommGRLC, hCommL1, MAC_POLL_REQ, + &grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index], + sizeof(T_ul_poll_resp) ); + } +#endif /* #ifdef _SIMULATION_ */ + + TRACE_BINDUMP + ( hCommGRLC, TC_USER4, + cl_rlcmac_get_msg_name( U_MSG_TYPE_CHANNEL_REQ_c, RLC_MAC_ROUTE_UL ), + grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].ul_block, + RLC_MAC_MAX_LEN_CHANNEL_REQ ); /*lint !e569*/ + + grlc_data->ul_poll_pos_index++; + /* + * next poll block invalid + */ + grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].block_status = 0; + + +} /* grlc_send_access_burst() */ + +/* ++------------------------------------------------------------------------------ +| Function : grlc_send_normal_burst ++------------------------------------------------------------------------------ +| Description : The function grlc_send_normal_burst() sents the poll as +| normal burst type +| +| Parameters : ptr_block_i : ptr to the ctrl message +| Parameters : tn_i : timeslot where the access burst shall send +| Parameters : r_bit_i : r bit needed for the mac header +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_send_normal_burst + (UBYTE * struct_data, UBYTE * encoded_data, UBYTE tn_i) +{ + + TRACE_FUNCTION( "grlc_send_normal_burst" ); + + if( (grlc_data->poll_start_tbf NEQ 0xFF) AND + (grlc_data->ta_value EQ 0xFF) ) + { + TRACE_EVENT_P2("No TA VALUE IN GRLC --> NB POLL NOT SENT ta=%d poll_st_tbf=%d" + ,grlc_data->ta_value + ,grlc_data->poll_start_tbf); + + TRACE_ERROR("No TA VALUE IN GRLC --> NB POLL NOT SENT"); + + grlc_data->next_poll_array[grlc_data->poll_start_tbf].cnt--; + grlc_data->next_poll_array[grlc_data->poll_start_tbf].poll_type[tn_i] = CGRLC_POLL_NONE; + return; + } + + /* + * either encoded data or structured data are passed by reference + */ + + + if( struct_data NEQ NULL ) + { + grlc_encode_ul_ctrl_block( ( UBYTE* )grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].ul_block, struct_data ); + } + else if( encoded_data NEQ NULL ) + { + memcpy( ( UBYTE* )grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].ul_block, + encoded_data, + BYTE_UL_CTRL_BLOCK ); + } + else + { + TRACE_ERROR( "grlc_send_normal_burst: no data available" ); + } + + grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].tn = tn_i; + grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].block_status = 3; + + if(grlc_data->poll_start_tbf NEQ 0xFF) + { + grlc_data->next_poll_array[grlc_data->poll_start_tbf].cnt--; + grlc_data->next_poll_array[grlc_data->poll_start_tbf].poll_type[tn_i] = CGRLC_POLL_NONE; + grlc_data->next_poll_fn = grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn; + } + +#ifdef _SIMULATION_ + { + PALLOC(mac_poll_req,MAC_POLL_REQ); + memset(mac_poll_req,0, + sizeof(T_MAC_POLL_REQ)); + memcpy(&(mac_poll_req->ul_poll_resp), + &(grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index]), + sizeof(T_ul_poll_resp)); + PSEND(hCommL1,mac_poll_req); + } +#else /* #ifdef _SIMULATION_ */ + { + TRACE_MEMORY_PRIM ( hCommGRLC, hCommL1, MAC_POLL_REQ, + &grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index], + sizeof(T_ul_poll_resp) ); + } +#endif /* #ifdef _SIMULATION_ */ + + { + UBYTE* ul_block = ( UBYTE* )grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].ul_block; + + TRACE_BINDUMP( hCommGRLC, TC_USER4, + cl_rlcmac_get_msg_name + ( ( UBYTE )( ul_block[1] >> 2 ), RLC_MAC_ROUTE_UL ), + ul_block, MAX_L2_FRAME_SIZE ); /*lint !e569*/ + } + + grlc_data->ul_poll_pos_index++; + /* + * next poll block invalid + */ + grlc_data->ul_poll_resp[grlc_data->ul_poll_pos_index].block_status = 0; + + /* + TRACE_EVENT_P1 ("Normal burst sent at fn_i= %ld ",grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn); + */ +} /* grlc_send_normal_burst() */ + +/* ++------------------------------------------------------------------------------ +| Function : grlc_del_sent_poll ++------------------------------------------------------------------------------ +| Description : The function grlc_del_sent_poll() deletes the poll pos which was +| sent to L1 +| +| Parameters + +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_del_sent_poll(void ) +{ + UBYTE help_index; + UBYTE next_index; + + TRACE_FUNCTION( "grlc_del_sent_poll" ); + + + if( grlc_data->next_poll_array[grlc_data->poll_start_tbf].cnt EQ 0 ) + { + help_index = grlc_data->poll_start_tbf; + grlc_data->poll_start_tbf = grlc_data->next_poll_array[grlc_data->poll_start_tbf].next; + next_index = grlc_data->poll_start_free; + while(grlc_data->next_poll_array[next_index].next NEQ 0xFF) + { + next_index = grlc_data->next_poll_array[next_index].next; + } + grlc_data->next_poll_array[next_index].next = help_index; + grlc_data->next_poll_array[help_index].next = 0xFF; + } + + + +} /* grlc_del_sent_poll() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_decode_tbf_start_rel +|------------------------------------------------------------------------------ +| Description : The function grlc_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 grlc_decode_tbf_start_rel(ULONG start_fn, USHORT rel_pos) +{ + ULONG result; + + TRACE_FUNCTION( "grlc_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; +} /* grlc_decode_tbf_start_rel */ + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_get_sdu_len_and_used_ts ++------------------------------------------------------------------------------ +| Description : +| +| Parameters : * sdu_len - len of the current sdu in progress +| * used_ul_resources - used uplink resources in fixed alloc mode +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_get_sdu_len_and_used_ts ( T_RLC_VALUES * values ) +{ + TRACE_FUNCTION( "grlc_get_sdu_len_and_used_ts" ); + + switch( GET_STATE( RU ) ) + { + case RU_NULL: + values->sdu_len = grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_ptr->sdu.l_buf/8; + values->cnt_ts = 0; + break; + default: + values->sdu_len = grlc_data->ru.sdu_len; + values->cnt_ts = grlc_data->ru.cnt_ts; + break; + } + /* grlc_get_sdu_len_and_used_ts() */ +} + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_check_dist ++------------------------------------------------------------------------------ +| Description : The function grlc_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 grlc_check_dist ( ULONG high_i, ULONG low_i, ULONG dist_i) +{ + BOOL result = FALSE; + ULONG real_dist; + + TRACE_FUNCTION( "grlc_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; +} /* grlc_check_dist() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_handle_poll_pos ++------------------------------------------------------------------------------ +| Description : The function grlc_handle_poll_pos() +| +| Parameters : - ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_handle_poll_pos (ULONG current_fn) +{ + UBYTE help_index; + UBYTE next_index; + TRACE_FUNCTION( "grlc_handle_poll_pos" ); + + while ( (grlc_data->poll_start_tbf NEQ 0xFF) AND + (grlc_check_dist(current_fn,grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn,26)) AND + (current_fn NEQ grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn)) + { + TRACE_EVENT_P4("current_fn= %ld missed poll_fn=%ld ps_tbf=%d cnt=%d", + current_fn, + grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn, + grlc_data->poll_start_tbf, + grlc_data->next_poll_array[grlc_data->poll_start_tbf].cnt); + /* + * delete elememnt from tbf_list if all pollType = POLL_NONE, and add to free list + */ + grlc_data->missed_poll_fn = grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn; + grlc_data->next_poll_array[grlc_data->poll_start_tbf].cnt = 0; + help_index = grlc_data->poll_start_tbf; + grlc_data->poll_start_tbf = grlc_data->next_poll_array[grlc_data->poll_start_tbf].next; + next_index = grlc_data->poll_start_free; + while(grlc_data->next_poll_array[next_index].next NEQ 0xFF) + { + next_index = grlc_data->next_poll_array[next_index].next; + } + grlc_data->next_poll_array[next_index].next = help_index; + grlc_data->next_poll_array[help_index ].next = 0xFF; + TRACE_ERROR( "Poll Position missed" ); + } +} /* grlc_handle_poll_pos() */ + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_send_rem_poll_pos ++------------------------------------------------------------------------------ +| Description : The function grlc_send_rem_poll_pos() +| +| Parameters : - ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_send_rem_poll_pos (ULONG current_fn) +{ + ULONG delta_fn = 0; + UBYTE *ptr_block=NULL; + + + TRACE_FUNCTION( "grlc_send_rem_poll_pos" ); + + if (grlc_data->poll_start_tbf EQ 0xFF) + return; + + + +#ifdef _TARGET_ + delta_fn = grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn; + if(current_fn EQ FN_MAX-5) + delta_fn += 5; + else + delta_fn -= current_fn; +#endif + +#ifdef _SIMULATION_ + if(current_fn EQ grlc_data->next_poll_array[grlc_data->poll_start_tbf].fn) + delta_fn = 4; + else + delta_fn = 0; +#endif + + + if( (delta_fn EQ 4) OR + (delta_fn EQ 5) ) + { + UBYTE tn=0; + UBYTE index; + while(grlc_data->next_poll_array[grlc_data->poll_start_tbf].cnt + AND (tn < 8)) + { + switch(grlc_data->next_poll_array[grlc_data->poll_start_tbf].poll_type[tn]) + { + case CGRLC_POLL_CTRL: + case CGRLC_POLL_UACK: + case CGRLC_POLL_COLLISION: + if(grlc_data->burst_type EQ CGRLC_BURST_TYPE_NB) + { + ptr_block = grlc_set_packet_ctrl_ack(); + grlc_send_normal_burst(ptr_block, NULL, tn); + } + else + grlc_send_access_burst(tn); + break; + case CGRLC_POLL_RES_AB: + grlc_send_access_burst(tn); + break; + case CGRLC_POLL_RES_NB: + ptr_block = grlc_set_packet_ctrl_ack(); + grlc_send_normal_burst(ptr_block, NULL, tn); + break; + case CGRLC_POLL_DATA: + if( grlc_data->tbf_type EQ TBF_TYPE_UL ) + { + /* + * no downlink active , send ctrl block or pca + */ + if( tm_get_num_ctrl_blck( ) NEQ 0 ) + { + ptr_block = tm_get_ctrl_blk( &index, TRUE ); + grlc_send_normal_burst(NULL, ptr_block, tn); + grlc_data->rd.next_poll_block = NEXT_POLL_BLOCK_DL_DATA; + } + else if(grlc_data->burst_type EQ CGRLC_BURST_TYPE_NB) + { + ptr_block = grlc_set_packet_ctrl_ack(); + grlc_send_normal_burst(ptr_block, NULL, tn); + } + else + grlc_send_access_burst(tn); + } + break; +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH + case CGRLC_POLL_RE_ASS: /* TBF re assignment on PACCH */ + + if(grlc_data->burst_type EQ CGRLC_BURST_TYPE_NB) + { + T_U_GRLC_RESOURCE_REQ resource_req; + + tm_build_res_req( &resource_req,R_BUILD_2PHASE_ACCESS); + grlc_send_normal_burst((UBYTE *)&resource_req, NULL, tn); + } + else /* PCA CTRL ACK 00 */ + { + grlc_data->next_poll_array[grlc_data->poll_start_tbf].ctrl_ack = 0; + grlc_send_access_burst(tn); + } + + break; +#endif + } + tn++; + } + grlc_del_sent_poll(); + } +}/* grlc_send_rem_poll_pos() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_test_mode_active ++------------------------------------------------------------------------------ +| Description : This functions returns 0 if the GPRS test mode is not activated. +| Otherwise a value greater then 0. +| +| Parameters : no parameters +| ++------------------------------------------------------------------------------ +*/ + +GLOBAL UBYTE grlc_test_mode_active () +{ + if(grlc_data->testmode.mode NEQ CGRLC_NO_TEST_MODE) + return TRUE; + else + return FALSE; + +}/* grlc_test_mode_active*/ + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_prbs ++------------------------------------------------------------------------------ +| Description : +| This function generates a pseodo random bis sequence. +| The implementation is related to CCITT O.151 Okt. 92 chapter 2.1 . +| +| This functions generates the next length_i bytes of a 32767-bit +| pseudo-random test sequence if action_i is set to COMPUTE_DATA +| and writes the data at address ptr_i. +| +| The function stores the position where it stops to calculate. +| In case of action_i EQ INITIALIZE the function erase his history. +| On its next call the function continues with its intial values +| +| Parameters : UBYTE action_i (INITIALIZE or COMPUTE_DATA) +| and only +| UBYTE length_i (number of data bytes which shall callculated and copied) +| UBYTE * out_i (location where this dada have to be placed, only valid) +| ++------------------------------------------------------------------------------ +*/ + +GLOBAL void grlc_prbs(UBYTE action_i, UBYTE length_i, UBYTE * ptr_i) +{ + TRACE_FUNCTION( "grlc_prbs" ); + + switch(action_i) + { + case INITIALIZE: + +#define FEED_BACK_MASK 0x6000 + /* + * 14th and 15 stage will be feeded back + */ + + + /* + * Initialize the prbs generation + * + * This value is the value of the shift register 8 cycles + * before shift register value 0x7fff + */ + grlc_data->testmode.prbs_shift_reg = 0x55ff; + break; + case COMPUTE_DATA: + { + /* + * get prbs computing values + */ + USHORT i,reg = grlc_data->testmode.prbs_shift_reg; + + UBYTE * out_ptr = ptr_i; + + for(i=0; i < (8 * length_i); i++) + { + /* + * write a byte in output if neccessary + */ + if(i % 8 EQ 0) + { + *out_ptr++ = (UBYTE)(0x00ff®); + } + + + { + USHORT temp = reg & FEED_BACK_MASK; + /* + * shift the register and but new data in + */ + reg = reg << 1; + if ( (temp EQ FEED_BACK_MASK) OR (temp EQ 0) ) + { + /* + * put a "0" in + */; + } + else + { + /* + * put a "1" in + */ + reg +=1; + } + } /* for(i=0; i < (8 * length_i); i++) */ + } + /* + * store prbs computing values + */ + grlc_data->testmode.prbs_shift_reg = reg; + } + break; + + default: + break; + } + + return; + +}/*grlc_prbs*/ + + + + + + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_trace_tbf_par ++------------------------------------------------------------------------------ +| Description : +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_trace_tbf_par ( UBYTE tbf_index ) +{ + TRACE_FUNCTION( "grlc_trace_tbf_par" ); + + TRACE_EVENT_P9("tbf_type=%d;start_fn=%ld (%ld);end_fn=%ld(%ld);rlc_oct_cnt=%d; pdu_cnt=%ld;vs_vr=%d;va_vq=%d ", + grlc_data->tbf_ctrl[tbf_index].tbf_type, + grlc_data->tbf_ctrl[tbf_index].start_fn, + grlc_data->tbf_ctrl[tbf_index].start_fn%42432, + grlc_data->tbf_ctrl[tbf_index].end_fn, + grlc_data->tbf_ctrl[tbf_index].end_fn%42432, + grlc_data->tbf_ctrl[tbf_index].rlc_oct_cnt, + grlc_data->tbf_ctrl[tbf_index].pdu_cnt, + grlc_data->tbf_ctrl[tbf_index].vs_vr, + grlc_data->tbf_ctrl[tbf_index].va_vq); + + TRACE_EVENT_P9("cnt_ts=%d;ack_cnt=%d;fbi=%d;ret_bsn=%d;N_ACC=%d,tlli=%lx rem_ul_data=%d,PST=%d,PSF=%d", + grlc_data->tbf_ctrl[tbf_index].cnt_ts, + grlc_data->tbf_ctrl[tbf_index].ack_cnt, + grlc_data->tbf_ctrl[tbf_index].fbi, + grlc_data->tbf_ctrl[tbf_index].ret_bsn, + grlc_data->tm.n_acc_req_procedures, + grlc_data->uplink_tbf.tlli, + grlc_data->grlc_data_req_cnt, + grlc_data->prim_start_tbf, + grlc_data->prim_start_free); + +} /* grlc_trace_tbf_par */ + + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_set_buf_tlli ++------------------------------------------------------------------------------ +| Description : The function grlc_set_buf_tlli() fills the TLLI buffer. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_set_buf_tlli ( BUF_tlli_value *buf_tlli_o, ULONG tlli_i ) +{ + TRACE_FUNCTION( "grlc_set_buf_tlli" ); + + grlc_set_tlli( &buf_tlli_o->l_tlli_value, + &buf_tlli_o->o_tlli_value, + &buf_tlli_o->b_tlli_value[0], + tlli_i ); + +} /* grlc_set_buf_tlli */ + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_set_tlli ++------------------------------------------------------------------------------ +| Description : The function grlc_set_tlli() fills the TLLI buffer. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_set_tlli + ( USHORT *l_tlli, USHORT *o_tlli, UBYTE *b_tlli, ULONG tlli ) +{ + TRACE_FUNCTION( "grlc_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; + +} /* grlc_set_tlli */ + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_encode_ul_ctrl_block ++------------------------------------------------------------------------------ +| Description : +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_encode_ul_ctrl_block ( UBYTE *ul_ctrl_block, + UBYTE *ul_ctrl_data ) +{ + T_CTRLBUF enc_block; + + TRACE_FUNCTION( "grlc_encode_ul_ctrl_block" ); + + grlc_encode_ctrl( ul_ctrl_data, ( T_MSGBUF* )&enc_block , grlc_data->r_bit ); + memcpy( ul_ctrl_block, enc_block.buf, BYTELEN( enc_block.l_buf ) ); + +} /* grlc_encode_ul_ctrl_block */ + + + + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_check_if_tbf_start_is_elapsed ++------------------------------------------------------------------------------ +| Description : The function grlc_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 grlc_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( "grlc_check_if_tbf_start_is_elapsed" ); + + /* + * handle maximum distance for tbf starting time + */ + + if(start_fn EQ CGRLC_STARTING_TIME_NOT_PRESENT) /*lint !e650*/ + { + 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; +} /* grlc_check_if_tbf_start_is_elapsed() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_decode_grlc ++------------------------------------------------------------------------------ +| Description : The function grlc_decode_grlc() 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 grlc_decode_grlc (T_MSGBUF * msg_ptr_i) +{ + UBYTE result; + UBYTE msg_type = msg_ptr_i->buf[0] >> 2;; + + TRACE_FUNCTION( "grlc_decode_grlc" ); + + /* + * Offset must be zero, else code to get msg_type is illegal + */ + TRACE_ASSERT (msg_ptr_i->o_buf==0); + + + + switch (msg_type) + { + case D_UL_ACK: + if(!grlc_data->grlc_wo_ccd) + { + result = ccd_decodeMsg (CCDENT_GRLC, DOWNLINK, msg_ptr_i, _decodedMsg, NOT_PRESENT_8BIT); + } + else + { + result = grlc_decode_ul_acknack(msg_ptr_i->buf); + } + break; + default: + TRACE_ERROR(" not Packet ul ack decoded: should nor happen "); + result = DELETE_MESSAGE; + break; + } + + + if ( result EQ ccdError ) + { + return grlc_ccd_error_handling( CCDENT_GRLC ); + } + + return msg_type; + +} /* grlc_decode_grlc() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : grlc_activate_tfi ++------------------------------------------------------------------------------ +| Description : +| grlc_activate_tfi modifies tfi´s if tbf starting time is reached +| +| +| Parameters : fn_i is the current framenuber in tbf mode +| ++------------------------------------------------------------------------------ +*/ + +GLOBAL void grlc_activate_tfi (ULONG fn_i) +{ + + TRACE_FUNCTION( "grlc_activate_tfi" ); + + + /* 1. check if starting time is reached */ + switch(grlc_data->tfi_change) + { + case TFI_CHANGE_UL: + if(grlc_check_if_tbf_start_is_elapsed ( grlc_data->ul_tbf_start_time, ((fn_i+5)%FN_MAX))) + { + grlc_data->tfi_change = TFI_CHANGE_NULL; + grlc_data->ul_tfi = grlc_data->start_fn_ul_tfi; + grlc_data->start_fn_ul_tfi = 0xFF; + TRACE_EVENT_P2("UL TFI CHANGE St reached st_fn=%ld c_fn=%ld",grlc_data->ul_tbf_start_time,fn_i ); + grlc_data->ul_tbf_start_time = CGRLC_STARTING_TIME_NOT_PRESENT; + grlc_data->tbf_ctrl[grlc_data->ul_index].tfi = grlc_data->ul_tfi; + grlc_data->ul_tfi_changed = TRUE; + } + break; + case TFI_CHANGE_DL: + if(grlc_check_if_tbf_start_is_elapsed ( grlc_data->dl_tbf_start_time, fn_i)) + { + grlc_data->tfi_change = TFI_CHANGE_NULL; + grlc_data->dl_tfi = grlc_data->start_fn_dl_tfi; + grlc_data->start_fn_dl_tfi = 0xFF; + TRACE_EVENT_P2("DL TFI CHANGE St reached st_fn=%ld c_fn=%ld",grlc_data->dl_tbf_start_time,fn_i ); + grlc_data->dl_tbf_start_time = CGRLC_STARTING_TIME_NOT_PRESENT; + grlc_data->tbf_ctrl[grlc_data->dl_index].tfi = grlc_data->dl_tfi; + } + break; + case TFI_CHANGE_ALL: + if(grlc_check_if_tbf_start_is_elapsed ( grlc_data->ul_tbf_start_time, ((fn_i+5)%FN_MAX))) + { + grlc_data->tfi_change = TFI_CHANGE_DL; + grlc_data->ul_tfi = grlc_data->start_fn_ul_tfi; + grlc_data->start_fn_ul_tfi = 0xFF; + TRACE_EVENT_P2("UL TFI CHANGE(ALL) St reached st_fn=%ld c_fn=%ld",grlc_data->ul_tbf_start_time,fn_i ); + grlc_data->ul_tbf_start_time = CGRLC_STARTING_TIME_NOT_PRESENT; + grlc_data->tbf_ctrl[grlc_data->ul_index].tfi = grlc_data->ul_tfi; + grlc_data->tbf_ctrl[grlc_data->dl_index].tfi = grlc_data->dl_tfi; + grlc_data->ul_tfi_changed = TRUE; + } + if(grlc_check_if_tbf_start_is_elapsed ( grlc_data->dl_tbf_start_time, fn_i)) + { + if (grlc_data->tfi_change EQ TFI_CHANGE_DL) + grlc_data->tfi_change = TFI_CHANGE_NULL; + else + grlc_data->tfi_change = TFI_CHANGE_UL; + grlc_data->dl_tfi = grlc_data->start_fn_dl_tfi; + grlc_data->start_fn_dl_tfi = 0xFF; + TRACE_EVENT_P2("DL TFI CHANGE(ALL) St reached st_fn=%ld c_fn=%ld",grlc_data->dl_tbf_start_time,fn_i ); + grlc_data->dl_tbf_start_time = CGRLC_STARTING_TIME_NOT_PRESENT; + } + break; + } +} + +/* ++------------------------------------------------------------------------------ +| Function : grlc_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 grlc_t_status( USHORT t_index ) +{ + T_TIME t_time = 0L; + + TRACE_FUNCTION( "grlc_t_status" ); + + vsi_t_status( GRLC_handle, t_index, &t_time ); + + return( t_time ); +} /* grlc_t_status */ + +/* ++------------------------------------------------------------------------------ +| Function : grlc_enter_standby_state ++------------------------------------------------------------------------------ +| Description : This function is called in case the STANDBY state should be +| entered. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_enter_standby_state ( void ) +{ + TRACE_FUNCTION( "grlc_enter_standby_state" ); + + if( grlc_data->ready_timer.handling EQ READY_TIMER_HANDLING_ENABLED ) + { + if( grlc_data->ready_timer.state EQ READY_STATE ) + { + /* The ready_timer.state is set to STANDBY_STATE just in case we are not already in this state. + The CGRLC_STANDBY_STATE_IND primitives are sent if we move from READY_STATE to STANDBY_STATE only. + */ + if( grlc_data->ready_timer.value NEQ CGRLC_DEACTIVATED ) + { + /* If the timer T3314 expires while we are in READY_STATE but the timer is deactivated then + the transition to STANDBY_STATE will never occur + */ + /* If the primitive CGRLC_FORCE_TO_STANDBY_REQ is received when we are in Ready State but + the timer is deactivated then the transition to STANDBY_STATE will never occur + */ + grlc_data->ready_timer.state = STANDBY_STATE; + vsi_t_stop( GRLC_handle, T3314 ); + + { + PALLOC(cgrlc_standby_state_ind,CGRLC_STANDBY_STATE_IND); /* T_CGRLC_STANDBY_STATE_IND sent to GMM */ + PSEND(hCommGMM,cgrlc_standby_state_ind); + } + + { + PALLOC(cgrlc_standby_state_ind,CGRLC_STANDBY_STATE_IND); /* T_CGRLC_STANDBY_STATE_IND sent to GRR */ + PSEND(hCommGRR,cgrlc_standby_state_ind); + } + } + else + { + TRACE_EVENT( "grlc_enter_standby_state: MS enters STANDBY state while T3314 is deactivated" ); + } + } + else + { + TRACE_EVENT( "grlc_enter_standby_state: MS is already in STANDBY state" ); + } + } +} /* grlc_enter_standby_state */ + +/* ++------------------------------------------------------------------------------ +| Function : grlc_enter_ready_state ++------------------------------------------------------------------------------ +| Description : This function is called in case the READY state should be +| entered. +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void grlc_enter_ready_state ( void ) +{ + TRACE_FUNCTION( "grlc_enter_ready_state" ); + + if (grlc_data->ready_timer.state EQ STANDBY_STATE) + { + /* The ready_timer.state is set to READY_STATE just in case we are not already in this state. + The CGRLC_READY_STATE_IND primitives are sent only if we move from STANDBY_STATE to READY_STATE */ + + /* If we receive the primitive CGRLC_READY_TIMER_CONFIG_REQ with timer value CGRLC_DEACTIVATED when + we are in CGRLC_STANDBY, the state will immediately switch to READY and the CGRLC_READY_STATE_IND + primitives will be sent */ + grlc_data->ready_timer.state = READY_STATE; + + { + PALLOC(cgrlc_ready_state_ind,CGRLC_READY_STATE_IND); /* T_CGRLC_READY_STATE_IND sent to GMM */ + PSEND(hCommGMM,cgrlc_ready_state_ind); + } + + { + PALLOC(cgrlc_ready_state_ind,CGRLC_READY_STATE_IND); /* T_CGRLC_READY_STATE_IND sent to GRR */ + PSEND(hCommGRR,cgrlc_ready_state_ind); + } + } + else + { + TRACE_EVENT( "grlc_enter_ready_state: MS is already in READY state" ); + } +} /* grlc_enter_ready_state */ +/* ++------------------------------------------------------------------------------ +| Function : grlc_convert_11bit_2_etsi ++------------------------------------------------------------------------------ +| Description : Converts the 11 bit access burst value into ETSI format +| +| Parameters : In: eleven bit value +| Out: converted eleven bit +| ++------------------------------------------------------------------------------ +*/ +LOCAL USHORT grlc_convert_11bit_2_etsi ( USHORT eleven_bit ) +{ + USHORT etsi11bit; + USHORT dummy1 = 0, dummy2 = 0; + + TRACE_FUNCTION( "grlc_convert_11bit_2_etsi" ); + + /* + * 11 Bit access burst + * b: bit + * b10 b9 b8 b7 b6 b5 b4 b3 b2 b1 b0 + * should be sent to the network -according 04.60 and 0404- in the + * following 16-bit format: + * 0 0 0 0 0 b2 b1 b0 b10 b9 b8 b7 b6 b5 b4 b3 + */ + + /* + * get b2 b1 b0 + */ + dummy1 = 0x0007 & eleven_bit; + + /* + * shift it 8 bits to left + */ + dummy1 = ( dummy1 << 8 ); + + /* + * get b10 b9 b8 b7 b6 b5 b4 b3 + */ + dummy2 = 0xFFF8 & eleven_bit; + + /* + * shift it 3 bits to right + */ + dummy2 = ( dummy2 >> 3 ); + + /* + * compose dummy1 and dummy2 to the target 16-bit format + */ + etsi11bit = dummy1 | dummy2; + + return etsi11bit; + +} /* grlc_convert_11bit_2_etsi() */