FreeCalypso > hg > fc-magnetite
diff src/g23m-gprs/grlc/grlc_tmf.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_tmf.c Thu Oct 13 04:24:13 2016 +0000 @@ -0,0 +1,2878 @@ +/* ++----------------------------------------------------------------------------- +| 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 local functions for service TC of +| entity GRLC. ++----------------------------------------------------------------------------- +*/ + +#ifndef GRLC_TMF_C +#define GRLC_TMF_C +#endif + +#define ENTITY_GRLC + +/*==== INCLUDES =============================================================*/ + +#include <stdio.h> +#include <string.h> + +#include "typedefs.h" /* to get Condat data types */ +#include "vsi.h" /* to get a lot of macros */ +#include "macdef.h" +#include "gprs.h" +#include "gsm.h" /* to get a lot of macros */ +#include "ccdapi.h" /* to get CCD API */ +#include "cnf_grlc.h" /* to get cnf-definitions */ +#include "mon_grlc.h" /* to get mon-definitions */ +#include "prim.h" /* to get the definitions of used SAP and directions */ +#include "message.h" /* to get air message definitions */ +#include "grlc.h" /* to get the global entity definitions */ + +#include "grlc_f.h" /* to get Process GRLC global function definitions */ +#include "grlc_tmf.h" /* to get Service TM global function definitions */ +#include "grlc_tms.h" /* to get Service TM inter signal definitions */ +#include "grlc_rus.h" /* to get interface to service RU */ +#include "grlc_rds.h" /* to get interface to service RD */ +#include "grlc_gffs.h" +#include "grlc_meass.h" +#include "grlc_tpcs.h" +#include "cl_rlcmac.h" + +/*==== CONST ================================================================*/ +/* + * used in tm_compare_prim + */ +#define SAME_RLC_MODE 0 +#define DIFFERENT_RLC_MODE 1 + +#define PRIO_LOWER 0 +#define PRIO_SAME 1 +#define PRIO_HIGHER 2 + +#define THROUGHPUT_LOWER 0 +#define THROUGHPUT_SAME 1 +#define THROUGHPUT_HIGHER 2 + +#ifdef REL99 +#define SAME_PFI 0 +#define DIFF_PFI 1 +#endif + + + + +/*==== DIAGNOSTICS ==========================================================*/ + +/*==== LOCAL VARS ===========================================================*/ + + +/*==== PRIVATE FUNCTIONS ====================================================*/ + + +LOCAL void tm_close_gaps_in_ctrl_blk_seq( UBYTE index ); +/*==== PUBLIC FUNCTIONS =====================================================*/ + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_access_allowed ++------------------------------------------------------------------------------ +| Description : The function tm_access_allowed() this function checks wheather +| access is allowed or not. The return is TRUE if access +| is allowed. +| +| Parameters : radio_prrio - radio priority for current primitive +| ++------------------------------------------------------------------------------ +*/ +GLOBAL BOOL tm_access_allowed ( UBYTE radio_prio ) +{ + BOOL result = FALSE; + TRACE_FUNCTION( "tm_access_allowed" ); + + switch(grlc_data->uplink_tbf.ac_class) + { + case CGRLC_PCCCH_AC_ALLOWED: + result = TRUE; + break; + case CGRLC_PCCCH_AC_NOT_ALLOWED: + TRACE_EVENT(" grlc ACCESS NOT ALLOWED PBCCH:"); + break; + case CGRLC_CCCH_AC_NOT_ALLOWED: + TRACE_EVENT("grlc ACCESS NOT ALLOWED CCCH"); + break; + default: + if ( (radio_prio+3) <= grlc_data->uplink_tbf.ac_class) + result = TRUE; + else + TRACE_EVENT_P2("Radio prio to low : pdu_rp=%d net_rp=%d",radio_prio,grlc_data->uplink_tbf.ac_class); + break; + } + + + return(result); +} /* tm_access_allowed() */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_build_chan_req_des ++------------------------------------------------------------------------------ +| Description : The function builds a channel request description. It is called +| during re-allocation or during uplink allocation on +| a dowlink TBF. +| +| Parameters : out_i - Function have to write the channel request description +| at this address +| p_ptr_i - Pointer to primitive which causes the channel request +| description +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_build_chan_req_des ( T_chan_req_des * out_i,T_PRIM_QUEUE * p_ptr_i ) +{ + + UBYTE next; + + TRACE_FUNCTION( "tm_build_chan_req_des" ); + + grlc_data->uplink_tbf.ti = 0; /* no contention resolution needed */ + out_i->peak_thr_class = p_ptr_i->prim_ptr->grlc_qos.peak; + out_i->radio_prio = p_ptr_i->prim_ptr->radio_prio; + + /* + * set RLC-Mode and LLC-Mode + */ + out_i->llc_pdu_type = LLC_NOT_ACK; /* that means not acknowledged */ + if(p_ptr_i->prim_type EQ CGRLC_LLC_PRIM_TYPE_DATA_REQ) + { /* CGRLC_LLC_PRIM_TYPE_DATA_REQ */ + out_i->rlc_mode = RLC_ACK_MODE; /* that means RLC mode acknowledged */ + } + else + { /* CGRLC_LLC_PRIM_TYPE_UNITDATA_REQ */ + out_i->rlc_mode = RLC_UNACK_MODE; /* that means RLC mode not acknowledged */ + } + + next = p_ptr_i->next; + out_i->rlc_octet_cnt = p_ptr_i->prim_ptr->sdu.l_buf/8 +1; + while (next < PRIM_QUEUE_SIZE_TOTAL) + { + out_i->rlc_octet_cnt += + grlc_data->prim_queue[next].prim_ptr->sdu.l_buf/8 +1; + next = grlc_data->prim_queue[next].next; + } + + if (grlc_data->testmode.mode EQ CGRLC_LOOP) + { + out_i->rlc_octet_cnt = 0; + TRACE_EVENT("open-ended tbf for testmode B requested"); + } + return; + +} /* tm_build_chan_req_des */ + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_send_tbf_rel ++------------------------------------------------------------------------------ +| Description : The function tm_send_tbf_rel() builds CGRLC_TBF_REL_IND +| and send it. +| +| Parameters : TBP-Type - that have to be deleted +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_send_tbf_rel ( T_TBF_TYPE tbf_i ) +{ + PALLOC(cgrlc_tbf_rel_ind,CGRLC_TBF_REL_IND); + + TRACE_FUNCTION( "tm_send_tbf_rel" ); + + + if(grlc_data->uplink_tbf.ti) + cgrlc_tbf_rel_ind->tbf_rel_cause = CGRLC_TBF_REL_CR_FAILED; + else if (grlc_data->N3102 EQ 0) /* tbf error with cell reselction*/ + cgrlc_tbf_rel_ind->tbf_rel_cause = CGRLC_TBF_REL_WITH_CELL_RESELECT; + else + cgrlc_tbf_rel_ind->tbf_rel_cause = CGRLC_TBF_REL_NORMAL; /* Find condition for abnormal release */ + + grlc_data->uplink_tbf.ti = 0; + + /* + * indicate if testmode or tbf_type is released + */ + + if((tbf_i NEQ TBF_TYPE_DL) AND /* Testmode released only in case of uplink tbf release*/ + (grlc_test_mode_active())) + { + if (grlc_data->testmode.mode EQ CGRLC_TEST_RANDOM) + { + MFREE(grlc_data->testmode.ptr_test_data); + grlc_data->testmode.ptr_test_data = NULL; + } + grlc_data->testmode.mode = CGRLC_TEST_MODE_RELEASE; + cgrlc_tbf_rel_ind->tbf_rel_cause = CGRLC_TBF_REL_NORMAL; + } + +#if defined REL99 AND defined TI_PS_FF_TI_PS_FF_TBF_EST_PACCH + if (tbf_i EQ TBF_TYPE_TP_ACCESS AND + grlc_data->tm.pacch_prr_pca_sent) /*PRR/PCA sent as POLL (tbf on pacch)*/ + { + vsi_t_stop(GRLC_handle,T3168); + cgrlc_tbf_rel_ind->tbf_mode = CGRLC_TBF_MODE_UL; + grlc_data->tm.pacch_prr_pca_sent = FALSE; + sig_tm_gff_ul_deactivate(); + } + else +#endif + if (tbf_i EQ TBF_TYPE_UL) + { + cgrlc_tbf_rel_ind->tbf_mode = CGRLC_TBF_MODE_UL; + grlc_data->rel_type |= REL_TYPE_UL; + sig_tm_gff_ul_deactivate(); + } + else if (tbf_i EQ TBF_TYPE_DL) + { + cgrlc_tbf_rel_ind->tbf_mode = CGRLC_TBF_MODE_DL; + grlc_data->rel_type |= REL_TYPE_DL; + sig_tm_gff_dl_deactivate(); + cgrlc_tbf_rel_ind->dl_trans_id = grlc_data->downlink_tbf.trans_id; + } + else + { + cgrlc_tbf_rel_ind->tbf_mode = CGRLC_TBF_MODE_DL_UL; + grlc_data->rel_type = REL_TYPE_DL_UL; + cgrlc_tbf_rel_ind->dl_trans_id = grlc_data->downlink_tbf.trans_id; + sig_tm_gff_ul_deactivate(); + sig_tm_gff_dl_deactivate(); + } + + + /* + * \ tbf_i | UL DL CONC + * \ | + * \ | + * \ | + * tbf_type \ | + * -----------+----------- + * NULL | x x x + * UL | x - x + * DL | - x x + * CONC | - - x + * + * x means, that no more TBF is existing + * - means, that a TBF is still existing + */ + + if( tbf_i EQ TBF_TYPE_CONC OR + grlc_data->tbf_type EQ TBF_TYPE_NULL OR + grlc_data->tbf_type EQ tbf_i ) + { + cgrlc_tbf_rel_ind->v_c_value = TRUE; + + meas_grlc_c_get_c_value( &cgrlc_tbf_rel_ind->c_value ); + meas_c_restart( ); + + } + else + { + cgrlc_tbf_rel_ind->v_c_value = FALSE; + } + +#if defined (_TARGET_) + switch(cgrlc_tbf_rel_ind->tbf_mode) + { + case CGRLC_TBF_MODE_UL: +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH + case CGRLC_TBF_MODE_2PA: +#endif + + TRACE_EVENT_P4("UL_TBF_REL:nr_of_crc_errors= %ld ul_call_errors=%ld dl_call_errors=%ld rel_type=%d", + grlc_data->nr_of_crc_errors, + grlc_data->ul_call_errors, + grlc_data->dl_call_errors, + grlc_data->rel_type); + break; + case CGRLC_TBF_MODE_DL: + TRACE_EVENT_P4("DL_TBF_REL:nr_of_crc_errors= %ld ul_call_errors=%ld dl_call_errors=%ld rel_type=%d", + grlc_data->nr_of_crc_errors, + grlc_data->ul_call_errors, + grlc_data->dl_call_errors, + grlc_data->rel_type); + break; + case CGRLC_TBF_MODE_DL_UL: + TRACE_EVENT_P4("UL/DL_TBF_REL:nr_of_crc_errors= %ld ul_call_errors=%ld dl_call_errors=%ld rel_type=%d", + grlc_data->nr_of_crc_errors, + grlc_data->ul_call_errors, + grlc_data->dl_call_errors, + grlc_data->rel_type); + + break; + case CGRLC_TBF_MODE_TMA: + case CGRLC_TBF_MODE_TMB: + TRACE_EVENT_P3 ("Testmode TBF_REL:nr_of_crc_errors= %ld ul_call_errors=%ld dl_call_errors=%ld", + grlc_data->nr_of_crc_errors, + grlc_data->ul_call_errors, + grlc_data->dl_call_errors); + + break; + + } + if(grlc_data->ul_call_errors OR grlc_data->dl_call_errors) + { + TRACE_EVENT_P6("ul_fn_err=%ld,%ld,%ld//dl_fn_err=%ld,%ld,%ld", + grlc_data->ul_fn_errors[0], + grlc_data->ul_fn_errors[1], + grlc_data->ul_fn_errors[2], + grlc_data->dl_fn_errors[0], + grlc_data->dl_fn_errors[1], + grlc_data->dl_fn_errors[2]); + grlc_data->ul_call_errors = 0; + grlc_data->dl_call_errors = 0; + } + grlc_data->nr_of_crc_errors = 0; +#endif /* defined (_TARGET_) */ + + PSEND(hCommGRR,cgrlc_tbf_rel_ind); + +} /* tm_send_tbf_rel() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_abort_tbf ++------------------------------------------------------------------------------ +| Description : The function tm_abort_tbf() stops a TBF. +| +| Parameters : tbf_i - TBF type to abort +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_abort_tbf ( T_TBF_TYPE tbf_i ) +{ + /*SZML-TC/056*/ + + TRACE_FUNCTION( "tm_abort_tbf" ); + + switch( tbf_i ) + { + case TBF_TYPE_NULL: + TRACE_EVENT("NULL TBF active: check if tbf starting time is running"); + /*SZML-TC/093*/ + break; +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH + case TBF_TYPE_TP_ACCESS: + tm_send_tbf_rel(tbf_i); + tm_deactivate_tbf(tbf_i); + break; +#endif + case TBF_TYPE_UL: + tm_send_tbf_rel(tbf_i); + sig_tm_ru_abrel(1, FALSE); + tm_deactivate_tbf(tbf_i); + break; + case TBF_TYPE_DL: + tm_send_tbf_rel(tbf_i); + sig_tm_rd_abrel(1,FALSE); + tm_deactivate_tbf(tbf_i); + break; + case TBF_TYPE_CONC: + tm_send_tbf_rel(tbf_i); + sig_tm_ru_abrel(1, FALSE); + sig_tm_rd_abrel(1,FALSE); + tm_deactivate_tbf(tbf_i); + break; + default: + TRACE_ERROR ( "tm_abort_tbf: TBF type is invalid" ); + break; + } +} /* tm_abort_tbf() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_ini_realloc ++------------------------------------------------------------------------------ +| Description : The function tm_ini_realloc() do all action that are necessary +| to start a Resource Re-Allocation Procedure. +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_ini_realloc ( UBYTE start_of_new_tbf_i ) +{ + TRACE_FUNCTION( "tm_ini_realloc" ); + grlc_data->tm.start_of_new_tbf = start_of_new_tbf_i ; + + /*SZML-TC/058*/ + +} /* tm_ini_realloc() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_build_res_req ++------------------------------------------------------------------------------ +| Description : The function tm_build_res_req() builds Packet Resource Request. +| +| Parameters : reason_i - the reason for building that packet resouce +| reallocation +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_build_res_req (T_U_GRLC_RESOURCE_REQ *ptr2res_req, + T_REASON_BUILD reason_i) +{ + TRACE_FUNCTION( "tm_build_res_req" ); + + + memset(ptr2res_req,0,sizeof(T_U_GRLC_RESOURCE_REQ) ); + + + /* processing of messsage type */ + ptr2res_req->msg_type = U_GRLC_RESOURCE_REQ_c; + + /* processing of change mark */ + + if( grlc_data->tm.change_mark EQ NOT_SET ) + { + ptr2res_req->v_ma_ch_mark = 0; + } + else + { + ptr2res_req->v_ma_ch_mark = 1; + ptr2res_req->ma_ch_mark = grlc_data->tm.change_mark; + } + + if(reason_i EQ R_FIX_RE_ALLOC) + { + /* 1 - processing of ACCESS_TYPE */ + ptr2res_req->v_access_type = 0; + + /* 2 - processing of global TFI and TLLI */ + ptr2res_req->flag = 0; + ptr2res_req->v_glob_tfi = 1; + ptr2res_req->glob_tfi.flag = 0; + ptr2res_req->glob_tfi.v_ul_tfi = 1; + ptr2res_req->glob_tfi.ul_tfi = grlc_data->ul_tfi; + + /* 3 - processing of radio access capabilities */ + ptr2res_req->v_ra_cap = FALSE; + + /* 4 - processing of channel request description */ + tm_build_chan_req_des(&ptr2res_req->chan_req_des, + &grlc_data->prim_queue[grlc_data->prim_start_tbf]); + } + else if(reason_i EQ R_RE_ALLOC) + { + /* 1 - processing of ACCESS_TYPE */ + ptr2res_req->v_access_type = 0; + + /* 2 - processing of global TFI and TLLI */ + ptr2res_req->flag = 1; + ptr2res_req->v_glob_tfi = 0; + ptr2res_req->v_tlli_value = 1; + + grlc_set_buf_tlli( &ptr2res_req->tlli_value, grlc_data->uplink_tbf.tlli ); + + /* 3 - processing of radio access capabilities */ + ptr2res_req->v_ra_cap = FALSE; + + /* 4 - processing of channel request description */ + tm_build_chan_req_des(&ptr2res_req->chan_req_des, + &grlc_data->prim_queue[grlc_data->tm.start_of_new_tbf]); + } + else if(reason_i EQ R_BUILD_2PHASE_ACCESS) + { + /* 1 - processing of ACCESS_TYPE */ + ptr2res_req->v_access_type = 1; + ptr2res_req->access_type = TWO_PHASE; + + /* 2 - processing of global TFI and TLLI */ + ptr2res_req->flag = 1; + ptr2res_req->v_glob_tfi = 0; + ptr2res_req->v_tlli_value = 1; + + grlc_set_buf_tlli( &ptr2res_req->tlli_value, grlc_data->uplink_tbf.tlli ); + + /* 3 - processing of radio access capabilities */ + if( rr_csf_get_radio_access_capability( &ptr2res_req->ra_cap ) EQ 0 ) + { + ptr2res_req->v_ra_cap = TRUE; + } + else + { + ptr2res_req->v_ra_cap = FALSE; + + TRACE_ERROR( "tm_build_res_req: radio access capabilities invalid" ); + } + + /* 4 - processing of channel request description */ + tm_build_chan_req_des((T_chan_req_des *)(&ptr2res_req->chan_req_des), + &grlc_data->prim_queue[grlc_data->prim_start_tbf] ); + } + + /* 5 - processing of signal variance */ + ptr2res_req->signvar = meas_sv_get_value( ); + ptr2res_req->v_signvar = TRUE; + + /* 6 - processing of relative interference levels */ + meas_int_get_rel_i_level( &ptr2res_req->ilev ); + + /* 7 - processing of C value */ + ptr2res_req->c_value = meas_grlc_c_get_value( ); + +#ifdef REL99 + ptr2res_req->v_release_99_str_grlc_prr = TRUE; + + /* Workaround to avoid definition of EGPRS measurements info + * in grr.aim file. This will reduce the size of ccddata.lib + */ + ptr2res_req->release_99_str_grlc_prr.flag = 0; + ptr2res_req->release_99_str_grlc_prr.flag2 = 0; + + /* Flag PFI, shall only include if PFI and BSS R99 */ + if (grlc_data->nw_rel AND grlc_data->pfi_support) + { + ptr2res_req->release_99_str_grlc_prr.v_pfi = 1; + + if ( reason_i EQ R_RE_ALLOC ) + { + ptr2res_req->release_99_str_grlc_prr.pfi = + grlc_data->prim_queue[grlc_data->tm.start_of_new_tbf].prim_ptr->pkt_flow_id[0]; + } + else + { + ptr2res_req->release_99_str_grlc_prr.pfi = grlc_data->pfi_value; + } + } + else + { + ptr2res_req->release_99_str_grlc_prr.v_pfi = 0; + } + + ptr2res_req->release_99_str_grlc_prr.add_ms_rac = 0; + ptr2res_req->release_99_str_grlc_prr.retrans_of_prr = 0; +#endif + + +} /* tm_build_res_req() */ + + + + + + + + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_init_prim ++------------------------------------------------------------------------------ +| Description : The function tm_init_prim() initializes the primitive queue. + +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_init_prim ( void ) +{ + UBYTE i; + TRACE_FUNCTION( "tm_init_prim" ); + + + /* LLC PRIM QUEUE*/ + for (i=0;i<PRIM_QUEUE_SIZE;i++) + { + /* + * set next to the following entry + */ + grlc_data->prim_queue[i].next = i+1; + + /* + * and initialize the not used primitive entry + */ + 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; + } + + + /* + * last free entry points to 0xff + */ + grlc_data->prim_queue[PRIM_QUEUE_SIZE-1].next = 0xff; + + /* + * index 0 is the first free entry + */ + grlc_data->prim_start_free = 0; + + /* + * becauce there are no primitives in the tbf prim_start_tbf points to 0xff + */ + grlc_data->prim_start_tbf = 0xff; + + /* + * init because there are no primitives there is also no user data + */ + grlc_data->prim_user_data = 0; + + + /* init gmm prim queue*/ + + for (i=PRIM_QUEUE_SIZE; i<(PRIM_QUEUE_SIZE_TOTAL);i++) + { + grlc_data->prim_queue[i].next = i+1; + + 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->gmm_procedure_is_running = FALSE; + grlc_data->prim_queue[PRIM_QUEUE_SIZE_TOTAL-1].next = 0xff; + + + +} /* tm_init_prim() */ + + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_start_access ++------------------------------------------------------------------------------ +| Description : The function tm_start_access() prepares the TC data structure +| for a packet access procedure. +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_start_access ( void ) +{ + USHORT rlc_octetts; + + TRACE_FUNCTION( "tm_start_access" ); + + /* + * mark that first packet access in process + */ + + grlc_data->tm.n_res_req = 0; + +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH + grlc_data->tm.pacch_prr_pca_sent = FALSE; +#endif + + + grlc_data->tm.n_acc_req_procedures++; + + if(grlc_data->prim_start_tbf < PRIM_QUEUE_SIZE_TOTAL) + { + grlc_data->uplink_tbf.prio + = grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_ptr->radio_prio; + /* save prio for packet access request building */ + rlc_octetts = + grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_ptr->sdu.l_buf/8 +1; +#ifdef REL99 + if (grlc_data->pfi_support) + { + /* pfi will take 1 byte*/ + grlc_data->uplink_tbf.nr_blocks = ( rlc_octetts / 15 ) + 1; + grlc_data->pfi_value = + grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_ptr->pkt_flow_id[0]; + } + else +#endif + { /* last "+1" we need complete bytes/octetts */ + grlc_data->uplink_tbf.nr_blocks = ( rlc_octetts / 16 ) + 1; + } + + /*TRACE_EVENT_P1("tm_start_access: nr_block: %d", grlc_data->uplink_tbf.nr_blocks);*/ + /* 16 because 23(CS_1 length) -3(blockheader) -4(TLLI) = 16 octetts */ + /* last "+1" we need complete blocks */ + if(grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_type EQ CGRLC_LLC_PRIM_TYPE_UNITDATA_REQ ) + { + grlc_data->uplink_tbf.rlc_mode = CGRLC_RLC_MODE_UACK; + grlc_data->uplink_tbf.ti = 0; /* mark that contention resolution is not requested */ + } + else + { + grlc_data->uplink_tbf.rlc_mode = CGRLC_RLC_MODE_ACK; + grlc_data->uplink_tbf.ti = 1; /* mark that contention resulution is not yet done */ + } + /* + * estimate access_type + */ + if(grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_type EQ CGRLC_LLC_PRIM_TYPE_UNITDATA_REQ ) + { + grlc_data->uplink_tbf.access_type = CGRLC_AT_TWO_PHASE; + } + else if(grlc_data->uplink_tbf.access_type EQ CGRLC_AT_CELL_UPDATE) + { + TRACE_EVENT("CU WILL BE PERFORMED"); + } + else + { + switch(grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_ptr->cause) + { + case GRLC_DTACS_DEF: + if(grlc_data->uplink_tbf.nr_blocks <= 8) + { + grlc_data->uplink_tbf.access_type = CGRLC_AT_SHORT_ACCESS; + } + else + { + grlc_data->uplink_tbf.access_type = CGRLC_AT_ONE_PHASE; + } + break; + + case GRLC_DTACS_PAGE_RESPONSE: + grlc_data->uplink_tbf.access_type = CGRLC_AT_PAGE_RESPONSE; + break; + + case GRLC_DTACS_MOBILITY_MANAGEMENT: + grlc_data->uplink_tbf.access_type = CGRLC_AT_MM_PROCEDURE; + break; + case GRLC_DTACS_EMPTY_FRAME: + case GRLC_DTACS_CELL_NOTIFI_NULL_FRAME: + grlc_data->uplink_tbf.access_type = CGRLC_AT_CELL_UPDATE; + TRACE_EVENT("EMPTY FRAME for CU, but not requested by GMM"); + break; + + default: + grlc_data->uplink_tbf.access_type = CGRLC_AT_NULL; + break; + } + } + } + else + { + TRACE_ERROR("NO PRIM IN QUEUE in tm_start_access"); + } + + +} /* tm_start_access() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_data_req ++------------------------------------------------------------------------------ +| Description : The function tm_data_req() starts the process of queueing +| a primitive received from LLC +| +| Parameters : prime_tpye_i - primitiven type (PRIME_TYPE_UNITDATA or +| PRIME_TYPE_DATA) +| ptr2prim_i - address of the primitive to handle +| +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_data_req ( T_PRIM_TYPE prim_tpye_i, + T_GRLC_DATA_REQ * ptr2prim_i) +{ + UBYTE free_entry_count , position , new_prim ; + T_COMPARE_PRIM compare_result = C_PRIM_CONTINUE; + BOOL new_qos = FALSE; + + TRACE_FUNCTION( "tm_data_req" ); + + + /* + * get the index of next free prim queue entry + */ + free_entry_count = tm_prim_queue_get_free_count(); + + if (free_entry_count) + { + /* get first free entry from free list */ + new_prim = grlc_prim_get_first (&grlc_data->prim_start_free); + +#ifdef REL99 + /*SM currenlty give 0xFF , in case network does not assign PFI */ + if (ptr2prim_i->pkt_flow_id[0] EQ 0xFF) + { + ptr2prim_i->pkt_flow_id[0] = 0; + } +#endif + + grlc_data->prim_queue[new_prim ].prim_type = prim_tpye_i; + grlc_data->prim_queue[new_prim ].prim_ptr = ptr2prim_i; + + position = grlc_data->prim_start_tbf; + + do + { + if(position < PRIM_QUEUE_SIZE_TOTAL) /* this "if" make sure only valid llc_pdu + are used in comparision */ + { + + compare_result = tm_compare_prim(new_prim ,position ,&new_qos); + + /* + * position for new prim is found ! + */ + if(compare_result NEQ C_PRIM_CONTINUE) break; + + position = grlc_data->prim_queue[position ].next; + + } + else + { /* first prim in queue */ + compare_result = C_PRIM_NEW_TBF; + break; + } + + } while (1); + + + switch( compare_result ) + { + case C_PRIM_NEW_TBF: + grlc_data->prim_queue[new_prim ].start_new_tbf = 1; + break; + case C_PRIM_REALLOC_START: + { + T_U_GRLC_RESOURCE_REQ resource_req;/*lint !e813*/ + + tm_ini_realloc(new_prim); + tm_build_res_req( &resource_req, + R_RE_ALLOC ); + tm_store_ctrl_blk( CGRLC_BLK_OWNER_TM, ( void* )&resource_req ); + if (grlc_data->prim_queue[position].next NEQ 0xff)/*sec 8.1.1.1.2 para 10*/ + { + grlc_data->prim_queue[grlc_data->prim_queue[position].next].re_allocation = 1; + } + } + break; + case C_PRIM_REALLOC_SHORT: + { + T_U_GRLC_RESOURCE_REQ resource_req; /*lint !e813*/ + + tm_ini_realloc(new_prim); + tm_build_res_req( &resource_req, + R_FIX_RE_ALLOC ); + tm_store_ctrl_blk( CGRLC_BLK_OWNER_TM, ( void* )&resource_req ); + } + break; + + case C_PRIM_REALLOC_MARK: + grlc_data->prim_queue[new_prim ].re_allocation = 1; + break; + case C_PRIM_RLC_MODE_CHANGE: /*sec 8.1.1.1.2 para 5*/ + grlc_data->prim_queue[new_prim].start_new_tbf = 1; + grlc_data->prim_queue[grlc_data->prim_queue[position].next].start_new_tbf = 1; + break; + + } + + + if(position < PRIM_QUEUE_SIZE_TOTAL) + { + position = grlc_data->prim_queue[position].next; + } + /*This new QOS is for lower priority */ + if ( (position EQ 0xff) AND (new_qos EQ TRUE)) + { + grlc_data->prim_queue[new_prim].re_allocation = 1;/*8.1.1.1.2 para 10*/ + TRACE_EVENT_P2("reallocation set for llc pdu = %d ,priority =%d",new_prim,ptr2prim_i->radio_prio); + } + + grlc_prim_put(&grlc_data->prim_start_tbf,new_prim ,position ); + + /* + * update amount of buffered user data + */ + grlc_data->prim_user_data += BYTELEN(ptr2prim_i->sdu.l_buf); + + /* + * and check if the queue is now full + */ + free_entry_count--; + + if( (free_entry_count == 0) || (grlc_data->prim_user_data > grlc_data->tm.max_grlc_user_data ) ) + { + grlc_data->tm.send_grlc_ready_ind = PRIM_QUEUE_FULL; + } + } + else + { + TRACE_ERROR("Data-Request, but prim_queue full"); + /* + * This is an error of LLC. + * Therefore here is no special handling of this case + */ + PFREE(ptr2prim_i); + + } + +} /* tm_data_req() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_grlc_init ++------------------------------------------------------------------------------ +| Description : The function tm_grlc_init() initialize the TC data structure. +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_grlc_init ( void ) +{ + UBYTE i; + + TRACE_FUNCTION( "tm_grlc_init" ); + + /* + * set some values + */ + grlc_data->tm.disable_class = CGRLC_DISABLE_CLASS_CR; + grlc_data->tbf_type = TBF_TYPE_NULL; + grlc_data->rel_type = REL_TYPE_NULL; + grlc_data->tm.start_of_new_tbf = 0xff; + grlc_data->tm.send_grlc_ready_ind = SEND_A_GRLC_READY_IND; + + + grlc_data->tm.n_acc_req_procedures = 0; + grlc_data->tm.n_res_req = 0; +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH + grlc_data->tm.pacch_prr_pca_sent = FALSE; +#endif + + + /* initialize the relevant data for uplink control block */ + grlc_data->tm.ul_ctrl_blk.seq[0] = MAX_CTRL_BLK_NUM; + + for( i = 0; i < MAX_CTRL_BLK_NUM; i++ ) + { + grlc_data->tm.ul_ctrl_blk.blk[i].state = BLK_STATE_NONE; + grlc_data->tm.ul_ctrl_blk.blk[i].owner = CGRLC_BLK_OWNER_NONE; + } + + /* + * Initialise service name (uses define SERVICE_NAME_* in GRLC.H); + */ + + INIT_STATE(TM,TM_ACCESS_DISABLED); + /* + * initialize primitive queue + */ + tm_init_prim(); + + +} /* tm_grlc_init() */ + + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_prim_queue_get_free_count ++------------------------------------------------------------------------------ +| Description : This function returns the number of free +| entries in the primitive queue. +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL UBYTE tm_prim_queue_get_free_count ( void ) +{ + UBYTE i = grlc_data->prim_start_free; + UBYTE result = 0,j; + + TRACE_FUNCTION( "tm_prim_queue_get_free_count" ); + + + for(j=0;j<PRIM_QUEUE_SIZE_TOTAL;j++) + { + if (i NEQ 0xff) + { + result++; + i = grlc_data->prim_queue[i].next; + } + else + { + break; + } + } + if((grlc_data->grlc_data_req_cnt + result NEQ PRIM_QUEUE_SIZE )AND + !grlc_data->gmm_procedure_is_running) + { + TRACE_EVENT_P4("PST=%d PSF=%d PDU=%d FREE_CNT=%d: tm_prim_queue_get_free_count CHECK it" + ,grlc_data->prim_start_tbf + ,grlc_data->prim_start_free + ,grlc_data->grlc_data_req_cnt + ,result); + } + + return(result); + +} /* tm_prim_queue_get_free_count() */ + + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_compare_prim ++------------------------------------------------------------------------------ +| Description : The function tm_compare_prim() check wheather the pdu have to +| set at tis position or not. They function also estimate +| how to set this primitive (with new TBF, immediately +| re-allocation or re-allocation at next PDU-boundary) +| +| Parameters : new_prim_i - index of the new-primitive entry in prim_queue[] +| position_i - index of the preceding entry of the possible +| position of the new primitive ++------------------------------------------------------------------------------ +*/ +GLOBAL T_COMPARE_PRIM tm_compare_prim ( UBYTE new_prim_i, + UBYTE position_i, + BOOL *new_qos) +{ + BOOL rlc_mode; + UBYTE new_prio = PRIO_HIGHER; + UBYTE new_throughput = THROUGHPUT_HIGHER; +#ifdef REL99 + UBYTE new_pfi = SAME_PFI; +#endif + UBYTE pre_prim_index, post_prim_index, new_prim_index; + T_GRLC_UNITDATA_REQ * pre_prim_ptr, * new_prim_ptr, * post_prim_ptr; + T_COMPARE_PRIM result; + + TRACE_FUNCTION( "tm_compare_prim" ); + + + /* + * set all variables + */ + + pre_prim_index = position_i; + post_prim_index = grlc_data->prim_queue[position_i].next; + new_prim_index = new_prim_i; + + + /* + * GRLC_UNITDATA_REQ and T_GRLC_UNITDATA_REQ have the same layout!! + */ + pre_prim_ptr = (T_GRLC_UNITDATA_REQ *) grlc_data->prim_queue[pre_prim_index].prim_ptr; + post_prim_ptr = (T_GRLC_UNITDATA_REQ *) grlc_data->prim_queue[post_prim_index].prim_ptr; + new_prim_ptr = (T_GRLC_UNITDATA_REQ *) grlc_data->prim_queue[new_prim_index].prim_ptr; + + + + if(post_prim_index NEQ 0xff) + { +#ifdef REL99 + if (grlc_data->pfi_support AND + (post_prim_ptr->pkt_flow_id[0] NEQ new_prim_ptr->pkt_flow_id[0]) + ) + { + new_pfi = DIFF_PFI; + } +#endif + + /* + * last position in queue; the values at position 0xff in the prim_queue are invalid + * therefore they are here not set + */ + if(post_prim_ptr->radio_prio < new_prim_ptr->radio_prio ) + { + new_prio = PRIO_LOWER; + } + else if(post_prim_ptr->radio_prio EQ new_prim_ptr->radio_prio ) + { + new_prio = PRIO_SAME; + } + + if(post_prim_ptr->grlc_qos.peak > new_prim_ptr->grlc_qos.peak ) + { + new_throughput = THROUGHPUT_LOWER; + } + else if(post_prim_ptr->grlc_qos.peak EQ new_prim_ptr->grlc_qos.peak ) + { + new_throughput = THROUGHPUT_SAME; + } + } + +/* TRACE_EVENT_P2("np=%d np=%d",new_prio,new_throughput);*/ + + + /* + * evalute - wheather the primitive have to put at this position or not + * compare with "following primitive" + */ + + + if(post_prim_index EQ 0xff) + { /* + * because this is the last entry in prim_queue this + * primitive have to put at this position + */ + result = C_PRIM_PUT; + } + else + { + if (grlc_data->prim_queue[post_prim_index].rlc_status) + { /* + * it is forbidden to change position of + * primitives already in transmission + */ + result = C_PRIM_CONTINUE; + } + else if (grlc_data->prim_queue[post_prim_index].cv_status) + {/* + * it is forbidden to change position of primitives + * included in countdown procedure + */ + result = C_PRIM_CONTINUE; + } +#ifdef REL99 + else if (new_pfi EQ DIFF_PFI) + { + result = C_PRIM_PUT; + } +#endif + else if ( new_prio EQ PRIO_HIGHER) + { + result = C_PRIM_PUT; + } + else if ( (new_prio EQ PRIO_SAME) AND (new_throughput EQ THROUGHPUT_HIGHER) ) + { + result = C_PRIM_PUT; + } + else + { + result = C_PRIM_CONTINUE; + } + } + + /* + * evalute - type of "put" + * compare with "preceding primitive" + */ + + + /*TRACE_EVENT_P3("np=%d np=%d result=%d",new_prio,new_throughput,result);*/ + + + if(result EQ C_PRIM_PUT) + { + + /* + * set variables + */ + + + if(pre_prim_ptr->radio_prio < new_prim_ptr->radio_prio ) + { + new_prio = PRIO_LOWER; + *new_qos = TRUE; + } + else if(pre_prim_ptr->radio_prio EQ new_prim_ptr->radio_prio ) + { + new_prio = PRIO_SAME; + } + else + { + new_prio = PRIO_HIGHER; + } + + if(pre_prim_ptr->grlc_qos.peak > new_prim_ptr->grlc_qos.peak ) + { + new_throughput = THROUGHPUT_LOWER; + } + else if(pre_prim_ptr->grlc_qos.peak EQ new_prim_ptr->grlc_qos.peak ) + { + new_throughput = THROUGHPUT_SAME; + } + else + { + new_throughput = THROUGHPUT_HIGHER; + } + +#ifdef REL99 + if (grlc_data->pfi_support AND + (pre_prim_ptr->pkt_flow_id[0] NEQ new_prim_ptr->pkt_flow_id[0]) + ) + { + new_pfi = DIFF_PFI; + } + else + { + new_pfi = SAME_PFI; + } +#endif + + if ( grlc_data->prim_queue[pre_prim_index].prim_type EQ + grlc_data->prim_queue[new_prim_index].prim_type) + { + rlc_mode = SAME_RLC_MODE; + } + else + { + rlc_mode = DIFFERENT_RLC_MODE; + } + + + + + + /* + * evalution + */ + + + /* TRACE_EVENT_P4("result=%d,rlc_mode=%d,prio=%d,peak=%d",result,rlc_mode,new_prio,new_throughput);*/ + + if(rlc_mode EQ DIFFERENT_RLC_MODE) + { + + if (new_prio EQ PRIO_HIGHER AND post_prim_index NEQ 0xFF) + { + result = C_PRIM_RLC_MODE_CHANGE; + } + else + { + result = C_PRIM_NEW_TBF; + } + } + else if (grlc_data->prim_queue[pre_prim_index].cv_status) + { /* + * if count-down-procedure has started for this pdu, + * re-allocation is forbitten + */ + result = C_PRIM_NEW_TBF; + } +#ifdef REL99 + else if ( grlc_data->pfi_support AND + grlc_data->prim_queue[pre_prim_index].rlc_status AND + new_pfi EQ DIFF_PFI + ) + { + result = C_PRIM_REALLOC_START; + TRACE_EVENT_P3("C_PRIM_REALLOC_START: npfi = %d, rlc_st = %d pre_prim_i=%d" + ,new_prim_ptr->pkt_flow_id[0] + ,grlc_data->prim_queue[pre_prim_index].rlc_status + ,pre_prim_index); + + } +#endif + else if( (grlc_data->prim_queue[pre_prim_index].rlc_status) AND + ((new_prio EQ PRIO_HIGHER ) OR + ((new_throughput EQ THROUGHPUT_HIGHER ) AND (new_prio EQ PRIO_SAME )) + ) + ) + { /* + * C_PRIM_REALLOC_START only if the "pre-pdu" + * is in transmission + */ + TRACE_EVENT_P4("C_PRIM_REALLOC_START: ntp=%d np=%d rlc_st=%d pre_prim_i=%d" + ,new_throughput + ,new_prio + ,grlc_data->prim_queue[pre_prim_index].rlc_status + ,pre_prim_index); + result = C_PRIM_REALLOC_START; + } + else if( + (new_prio EQ PRIO_LOWER ) OR + ((new_throughput EQ THROUGHPUT_LOWER ) AND (new_prio EQ PRIO_SAME )) + ) + + { + result = C_PRIM_REALLOC_MARK; + TRACE_EVENT_P4("C_PRIM_REALLOC_MARK: ntp=%d np=%d rlc_st=%d pre_prim_i=%d" + ,new_throughput + ,new_prio + ,grlc_data->prim_queue[pre_prim_index].rlc_status + ,pre_prim_index); + } + else if (grlc_data->uplink_tbf.ac_class >= CGRLC_PCCCH_AC_NOT_ALLOWED AND /* if pbcch is present */ + grlc_data->uplink_tbf.access_type EQ CGRLC_AT_SHORT_ACCESS AND /* last acess type */ + grlc_data->tbf_type NEQ TBF_TYPE_DL) /* not required if acess is over existing downlink tbf*/ + { + /* if prevoious access type is short access, ms should send packet resource request*/ + result = C_PRIM_REALLOC_SHORT; + grlc_data->uplink_tbf.access_type = CGRLC_AT_ONE_PHASE; + TRACE_EVENT_P4("C_PRIM_REALLOC_SHORT: ntp=%d np=%d rlc_st=%d pre_prim_i=%d" + ,new_throughput + ,new_prio + ,grlc_data->prim_queue[pre_prim_index].rlc_status + ,pre_prim_index); + + } + } + + /* TRACE_EVENT_P4("np=%d np=%d rlc_mode=%d result=%d",new_prio,new_throughput,rlc_mode,result);*/ + + + return(result); + +} /* tm_compare_prim() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_send_grlc_ready_ind ++------------------------------------------------------------------------------ +| Description : This function sends the GRLC_READY_IND +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +LOCAL void tm_send_grlc_ready_ind ( void ) +{ + if(grlc_data->gmm_procedure_is_running) + { + PALLOC(grlc_suspend_ready_ind, GRLC_SUSPEND_READY_IND); + PSEND(hCommLLC, grlc_suspend_ready_ind); + } + else + { + PALLOC(grlc_ready_ind, GRLC_READY_IND); + PSEND(hCommLLC, grlc_ready_ind); + } +} /* tm_send_grlc_ready_ind() */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_handle_grlc_ready_ind ++------------------------------------------------------------------------------ +| Description : This function handles the sending of the GRLC_READY_IND. Call +| to this function in any of the following cases: +| +| - a GRLC_DATA_REQ was received +| - a GRLC_UNITDATA_REQ was received +| - a queued prim is deleted +| - the TM state is changed from TM_ACCESS_DISABLED or +| TM_ACCESS_PREPARED to another +| +| Parameters : none ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_handle_grlc_ready_ind ( void ) +{ + UBYTE state = GET_STATE( TM ); + + TRACE_FUNCTION( "tm_handle_grlc_ready_ind" ); + + if( state EQ TM_ACCESS_DISABLED OR + state EQ TM_ACCESS_PREPARED ) + { + TRACE_EVENT("TM_ACCESS_DISABLED/TM_ACCESS_PREPARED no ready ind"); + return; + } + + switch (grlc_data->tm.send_grlc_ready_ind) + { + case SEND_A_GRLC_READY_IND: + tm_send_grlc_ready_ind(); + grlc_data->tm.send_grlc_ready_ind = WAIT_FOR_LLC_DATA_REQ; + break; + + case PRIM_QUEUE_FULL: + /* + * Check if we have now enough space + */ + TRACE_EVENT_P3("PRIM_QUEUE_FULL prim_start_tbf=%d prim_start_free=%ld user_data=%ld", + grlc_data->prim_start_tbf, + grlc_data->prim_start_free, + grlc_data->prim_user_data); + if ( (tm_prim_queue_get_free_count() > 0) AND + (grlc_data->prim_user_data <= grlc_data->tm.max_grlc_user_data) ) + { + TRACE_EVENT("NOT PRIM_QUEUE_FULL !!!"); + tm_send_grlc_ready_ind(); + grlc_data->tm.send_grlc_ready_ind = WAIT_FOR_LLC_DATA_REQ; + } + break; + + case WAIT_FOR_LLC_DATA_REQ: + /* NO BREAK */ + default: + /* Nothing to do */ + break; + } + +} /* tm_handle_grlc_ready_ind() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_handle_error_ra ++------------------------------------------------------------------------------ +| Description : The function tm_handle_error_ra() handles actions related +| to errors that leads to randam access procedure +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_handle_error_ra ( void ) +{ + TRACE_FUNCTION( "tm_handle_error_ra" ); + + + /* + * - called in case of contention resulution failed in RU + * - t3168 expires contention resulution failed in 2P-Access + * - If the mobile station has been assigned more PDCHs than it supports according + * to its MS multislot class, the mobile station shall reinitiate the packet access + * procedure unless it has already been repeated 4 times. In that + * case, TBF failure has occurred. + */ + + + /* + * Kill TBF if running + */ + + TRACE_EVENT_P3("ERROR_RA: nacc: %d prim_start_tbf:%d t3164_cnt=%d" + ,grlc_data->tm.n_acc_req_procedures + ,grlc_data->prim_start_tbf + ,grlc_data->t3164_to_cnt); + + if(grlc_data->tbf_type NEQ CGRLC_TBF_MODE_NULL) + { + SET_STATE(TM,TM_WAIT_4_PIM); + } + else + { + SET_STATE(TM,TM_PIM); + sig_tm_ru_reset_poll_array(); + } + + tm_abort_tbf(grlc_data->tbf_type); + grlc_data->tm.n_res_req = 0; /* reset counter of resource requests during access */ + + if (grlc_data->N3102 EQ 0) + { + } + else if((grlc_data->tm.n_acc_req_procedures < 5) AND + (grlc_data->t3164_to_cnt < 4)) + { + } + else + { + grlc_data->t3164_to_cnt = 0; + grlc_data->tm.n_acc_req_procedures = 0; + tm_cgrlc_status_ind(CGRLC_TBF_ESTABLISHMENT_FAILURE); + grlc_delete_prim(); + tm_handle_grlc_ready_ind(); + } + + + +} /* tm_handle_error_ra() */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_activate_tbf ++------------------------------------------------------------------------------ +| Description : The function tm_activate_tbf() set the assigned TBF +| into the data structures +| +| Parameters : tbf_type_i - type of TBF to deactivate +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_activate_tbf ( T_TBF_TYPE tbf_type_i ) +{ + TRACE_FUNCTION( "tm_activate_tbf" ); + + /* + * Reset of n_acc_req_procedures because of the fact that number of + * access procedures during pacet access procedures must not considered in + * a error with random access occured during running TBF. + */ + /* grlc_data->tm.n_acc_req_procedures = 0;*/ + + switch( tbf_type_i ) + { + case TBF_TYPE_UL: + switch( grlc_data->tbf_type ) + { + case TBF_TYPE_DL: + grlc_data->tbf_type = TBF_TYPE_CONC; + break; + case TBF_TYPE_NULL: +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH + case TBF_TYPE_TP_ACCESS: +#endif + grlc_data->tbf_type = TBF_TYPE_UL; + break; + default: + break; + } + break; + case TBF_TYPE_DL: + switch( grlc_data->tbf_type ) + { + case TBF_TYPE_UL: + grlc_data->tbf_type = TBF_TYPE_CONC; + break; + case TBF_TYPE_NULL: + grlc_data->tbf_type = TBF_TYPE_DL; + break; + default: + break; + } + break; + case TBF_TYPE_CONC: + switch( grlc_data->tbf_type ) + { + case TBF_TYPE_UL: + case TBF_TYPE_DL: + case TBF_TYPE_CONC: + grlc_data->tbf_type = TBF_TYPE_CONC; + break; + default: + { + TRACE_ERROR("FATAL ERROR: tm_activate_tbf called with wrong tbf_type"); + } + break; + } + break; +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH + case TBF_TYPE_TP_ACCESS: + switch( grlc_data->tbf_type ) + { + case TBF_TYPE_NULL: + grlc_data->tbf_type = TBF_TYPE_TP_ACCESS; + break; + default: + { + TRACE_ERROR("FATAL ERROR: tm_activate_tbf called with wrong tbf_type"); + } + break; + } + break; +#endif + default: + { + TRACE_ERROR("FATAL ERROR: tm_activate_tbf called with wrong tbf_type"); + } + break; + } /* switch (tbf_type_i) */ + + +} /* tm_activate_tbf() */ + + +/* ++------------------------------------------------------------------------------ +| Function : tm_deactivate_tbf ++------------------------------------------------------------------------------ +| Description : The function tm_deactivate_tbf() removes a TBF logical from TM +| end estimates how to continue. +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_deactivate_tbf ( T_TBF_TYPE tbf_i ) +{ + TRACE_FUNCTION( "tm_deactivate_tbf" ); + + switch( grlc_data->tbf_type ) + { + + case TBF_TYPE_CONC: + switch( tbf_i ) + { + case TBF_TYPE_UL: + grlc_data->tbf_type = TBF_TYPE_DL; + break; + case TBF_TYPE_DL: + grlc_data->tbf_type = TBF_TYPE_UL; + break; + case TBF_TYPE_CONC: + grlc_data->tbf_type = TBF_TYPE_NULL; + break; + } + break; + + + + case TBF_TYPE_DL: + case TBF_TYPE_UL: + if(grlc_data->tbf_type EQ tbf_i) + { + grlc_data->tbf_type = TBF_TYPE_NULL; + } + else + { + TRACE_ERROR("requested release tbf type does not exist"); + TRACE_EVENT_P2("SNH: requested release tbf type does not exist tbf_i =%d tbf_ty=%d",tbf_i,grlc_data->tbf_type); + } + break; +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH + case TBF_TYPE_TP_ACCESS: + grlc_data->tbf_type = TBF_TYPE_NULL; + break; +#endif + default: + break; + } + +} /* tm_deactivate_tbf() */ + + + + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_delete_prim_queue ++------------------------------------------------------------------------------ +| Description : delete all pdus in the queue +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_delete_prim_queue( void) +{ + TRACE_FUNCTION( "tm_delete_prim_queue" ); + + do + { + grlc_delete_prim(); + + } while( (grlc_data->prim_start_tbf < PRIM_QUEUE_SIZE_TOTAL) AND + !grlc_data->prim_queue[grlc_data->prim_start_tbf].start_new_tbf ); + + tm_handle_grlc_ready_ind(); + +} /* tm_delete_prim_queue */ + + + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_queue_test_mode_prim() ++------------------------------------------------------------------------------ +| Description : The function puts a number of primitives +| in the primitive queue +| +| Parameters : pdu_num_i - number of primitives to queue +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_queue_test_mode_prim( UBYTE pdu_num_i ) +{ + UBYTE i = 0; + TRACE_FUNCTION( "tm_queue_test_mode_prim" ); + + + for (i=0; i<pdu_num_i; i++) + { + PALLOC_SDU(grlc_unitdata_req,GRLC_UNITDATA_REQ,(195*8)); + grlc_unitdata_req->sapi = GRLC_SAPI_TEST_MODE; + grlc_unitdata_req->tlli = grlc_data->uplink_tbf.tlli; + memset(&grlc_unitdata_req->grlc_qos,0,sizeof(T_GRLC_grlc_qos)); + grlc_unitdata_req->radio_prio=2; + grlc_unitdata_req->sdu.l_buf= 195*8; + grlc_unitdata_req->sdu.o_buf=0; + memset(grlc_unitdata_req->sdu.buf,0x0f,195); /*lint !e419*/ + PSEND(hCommGRLC,grlc_unitdata_req); + } + +} /* tm_queue_test_mode_prim */ + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_close_gaps_in_ctrl_blk_seq ++------------------------------------------------------------------------------ +| Description : The function tm_close_gaps_in_ctrl_blk_seq reorders the queue +| holding the order which is used to identify the next control +| block to sent. +| +| Parameters : index - at this index the reordering starts +| ++------------------------------------------------------------------------------ +*/ +LOCAL void tm_close_gaps_in_ctrl_blk_seq ( UBYTE index ) +{ + TRACE_FUNCTION( "tm_close_gaps_in_ctrl_blk_seq" ); + + while( index < MAX_CTRL_BLK_NUM AND + grlc_data->tm.ul_ctrl_blk.seq[index] NEQ MAX_CTRL_BLK_NUM ) + { + grlc_data->tm.ul_ctrl_blk.seq[index-1] = grlc_data->tm.ul_ctrl_blk.seq[index]; + + index++; + } + + grlc_data->tm.ul_ctrl_blk.seq[index-1] = MAX_CTRL_BLK_NUM; + +} /* tm_close_gaps_in_ctrl_blk_seq() */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_store_ctrl_blk ++------------------------------------------------------------------------------ +| Description : +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL BOOL tm_store_ctrl_blk ( T_BLK_OWNER blk_owner, void *blk_struct ) +{ + UBYTE i; /* used for counting */ + BOOL result = FALSE; /* indicates whether control block is */ + /* stored successfully or not */ + T_BLK_INDEX blk_index; /* index to the control block buffer */ + + TRACE_FUNCTION( "tm_store_ctrl_msg" ); + + /* + * we have to find a free buffer for the control block which is + * indicated by the index to the control block buffer + */ + blk_index = MAX_CTRL_BLK_NUM; + + switch( blk_owner ) + { + case( CGRLC_BLK_OWNER_CTRL ): + if( grlc_data->tm.ul_ctrl_blk.blk[BLK_INDEX_CTRL].state EQ BLK_STATE_NONE ) + { + blk_index = BLK_INDEX_CTRL; + } + break; + + case( CGRLC_BLK_OWNER_CS ): + if( grlc_data->tm.ul_ctrl_blk.blk[BLK_INDEX_CS].state EQ BLK_STATE_NONE ) + { + blk_index = BLK_INDEX_CS; + } + break; + + case( CGRLC_BLK_OWNER_TM ): + if( grlc_data->tm.ul_ctrl_blk.blk[BLK_INDEX_TM].state EQ BLK_STATE_NONE ) + { + blk_index = BLK_INDEX_TM; + } + break; + + case( CGRLC_BLK_OWNER_MEAS ): + + blk_index = BLK_INDEX_MEAS; + + while( blk_index < MAX_CTRL_BLK_NUM AND + grlc_data->tm.ul_ctrl_blk.blk[blk_index].state NEQ BLK_STATE_NONE ) + { + blk_index++; + } + break; + + default: + /* do nothing */ + break; + } + + /* + * check whether the control block buffer is free, + */ + if( blk_index < MAX_CTRL_BLK_NUM ) + { + /* + * check the queue holding the order which is used to identify the next + * control block to send + */ + i = 0; + + while( i < MAX_CTRL_BLK_NUM AND + grlc_data->tm.ul_ctrl_blk.seq[i] NEQ MAX_CTRL_BLK_NUM ) + { + i++; + } + + /* + * check whether there is a free entry in the order queue, + * in case the check fails, there is something wrong with the concept + */ + if( i < MAX_CTRL_BLK_NUM ) + { + /* + * store the control block data and state in the queues + */ + if(blk_owner EQ CGRLC_BLK_OWNER_TM) + { + grlc_encode_ul_ctrl_block + ( ( UBYTE* )&grlc_data->tm.ul_ctrl_blk.blk[blk_index].data[0], + ( UBYTE* )blk_struct ); + } + else + { + /* + * encoded control message received by higher layers + */ + memcpy(( UBYTE* )&grlc_data->tm.ul_ctrl_blk.blk[blk_index].data[0],( UBYTE* )blk_struct,BYTE_UL_CTRL_BLOCK); + } + + grlc_data->tm.ul_ctrl_blk.blk[blk_index].state = BLK_STATE_ALLOCATED; + grlc_data->tm.ul_ctrl_blk.blk[blk_index].owner = blk_owner; + grlc_data->tm.ul_ctrl_blk.seq[i] = blk_index; + + if( i < MAX_CTRL_BLK_NUM - 1 ) + { + grlc_data->tm.ul_ctrl_blk.seq[i+1] = MAX_CTRL_BLK_NUM; + } + + result = TRUE; + } + else + { + TRACE_ERROR( "tm_store_ctrl_blk: no free entry in queue found" ); + } + } + + if( result EQ FALSE ) + { + if( blk_owner EQ CGRLC_BLK_OWNER_MEAS ) + { + TRACE_EVENT( "tm_store_ctrl_blk: no table entry allocated" ); + } + else + { + TRACE_ERROR( "tm_store_ctrl_blk: no table entry allocated" ); + } + } + + return( result ); + +} /* tm_store_ctrl_blk() */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_cancel_ctrl_blk ++------------------------------------------------------------------------------ +| Description : +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL BOOL tm_cancel_ctrl_blk ( T_BLK_OWNER blk_owner ) +{ + BOOL result = FALSE; + UBYTE i = 0; + UBYTE blk_index = grlc_data->tm.ul_ctrl_blk.seq[i]; + + TRACE_FUNCTION( "tm_cancel_ctrl_blk" ); + + + while( blk_index NEQ MAX_CTRL_BLK_NUM AND + result EQ FALSE ) + { + if( grlc_data->tm.ul_ctrl_blk.blk[blk_index].owner EQ blk_owner AND + grlc_data->tm.ul_ctrl_blk.blk[blk_index].state EQ BLK_STATE_ALLOCATED ) + { + /* + * mark the entry in the queue as free + */ + grlc_data->tm.ul_ctrl_blk.blk[blk_index].state = BLK_STATE_NONE; + grlc_data->tm.ul_ctrl_blk.blk[blk_index].owner = CGRLC_BLK_OWNER_NONE; + + tm_close_gaps_in_ctrl_blk_seq( (UBYTE)( i + 1 ) ); + + result = TRUE; + } + + i++; + if( i < MAX_CTRL_BLK_NUM ) + { + blk_index = grlc_data->tm.ul_ctrl_blk.seq[i]; + } + else + { + blk_index = MAX_CTRL_BLK_NUM; + } + } + + if( result EQ FALSE ) + { + TRACE_EVENT( "tm_cancel_ctrl_blk: no block found" ); + } + + return( result ); + +} /* tm_cancel_ctrl_blk() */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_set_start_ctrl_blk ++------------------------------------------------------------------------------ +| Description : +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL UBYTE* tm_set_start_ctrl_blk ( UBYTE *index ) +{ + UBYTE i = 0; + T_BLK_INDEX blk_index = MAX_CTRL_BLK_NUM; + + TRACE_FUNCTION( "tm_set_start_ctrl_blk" ); + + while( i < MAX_CTRL_BLK_NUM AND + grlc_data->tm.ul_ctrl_blk.seq[i] NEQ MAX_CTRL_BLK_NUM AND + blk_index EQ MAX_CTRL_BLK_NUM ) + { + blk_index = grlc_data->tm.ul_ctrl_blk.seq[i]; + + if( grlc_data->tm.ul_ctrl_blk.blk[blk_index].state EQ BLK_STATE_ALLOCATED ) + { + grlc_data->tm.ul_ctrl_blk.blk[blk_index].state = BLK_STATE_SENT_REQ; + + /* + * the control block was encoded without having correct information + * about the value of the R bit. So we have to set the correct value now. + */ + grlc_data->tm.ul_ctrl_blk.blk[blk_index].data[0] = 0x40 | grlc_data->r_bit; + } + else + { + blk_index = MAX_CTRL_BLK_NUM; + } + + i++; + } + + *index = blk_index; + + return( blk_index EQ MAX_CTRL_BLK_NUM ? + NULL : grlc_data->tm.ul_ctrl_blk.blk[blk_index].data ); + +} /* tm_set_start_ctrl_blk() */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_set_stop_ctrl_blk ++------------------------------------------------------------------------------ +| Description : +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL T_BLK_INDEX tm_set_stop_ctrl_blk + ( BOOL is_tx_success, T_BLK_OWNER srch_owner, T_BLK_INDEX start_index ) +{ + T_BLK_INDEX blk_index = grlc_data->tm.ul_ctrl_blk.seq[start_index]; + T_BLK_INDEX nxt_index; + + TRACE_FUNCTION( "tm_set_stop_ctrl_blk" ); + + if( blk_index < MAX_CTRL_BLK_NUM ) + { + T_BLK_OWNER blk_owner = grlc_data->tm.ul_ctrl_blk.blk[blk_index].owner; + + if( srch_owner EQ CGRLC_BLK_OWNER_NONE OR + srch_owner EQ blk_owner ) + { + /* + * mark the entry in the queue as free + */ + grlc_data->tm.ul_ctrl_blk.blk[blk_index].state = BLK_STATE_NONE; + grlc_data->tm.ul_ctrl_blk.blk[blk_index].owner = CGRLC_BLK_OWNER_NONE; + + tm_close_gaps_in_ctrl_blk_seq( 1 ); + + nxt_index = start_index; + } + else + { + nxt_index = start_index + 1; + } + } + else + { + nxt_index = MAX_CTRL_BLK_NUM; + } + + return( nxt_index ); + +} /* tm_set_stop_ctrl_blk() */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_set_stop_tm_ctrl_blk ++------------------------------------------------------------------------------ +| Description : +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_set_stop_tm_ctrl_blk ( void ) +{ + T_BLK_INDEX start_index = 0; + + TRACE_FUNCTION( "tm_set_stop_tm_ctrl_blk" ); + + while + ( + ( start_index = tm_set_stop_ctrl_blk( FALSE, CGRLC_BLK_OWNER_TM, start_index ) ) + NEQ MAX_CTRL_BLK_NUM + ){}; +} /* tm_set_stop_tm_ctrl_blk() */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_set_stop_all_ctrl_blk ++------------------------------------------------------------------------------ +| Description : +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_set_stop_all_ctrl_blk ( void ) +{ + T_BLK_INDEX start_index = 0; + + TRACE_FUNCTION( "tm_set_stop_all_ctrl_blk" ); + + while + ( + ( start_index = tm_set_stop_ctrl_blk( FALSE, + CGRLC_BLK_OWNER_NONE, + start_index ) ) NEQ MAX_CTRL_BLK_NUM + ){}; +} /* tm_set_stop_all_ctrl_blk() */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_get_gmm_prim_queue ++------------------------------------------------------------------------------ +| Description : The function tm_get_gmm_prim_queue () .... +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_get_gmm_prim_queue ( void ) +{ + UBYTE i; + TRACE_FUNCTION( "tm_get_gmm_prim_queue " ); + + + + /* init gmm prim queue*/ + TRACE_EVENT_P4("GET GMM QUEUE: BEFORE ps=%d, pf=%d,sps=%d,spf=%d", + grlc_data->prim_start_tbf, + grlc_data->prim_start_free, + grlc_data->save_prim_start_tbf, + grlc_data->save_prim_start_free); + + /* + * Delte all GMM primitives in current llc queue, which are on the top. + */ + while((grlc_data->prim_start_tbf >= PRIM_QUEUE_SIZE) AND + (grlc_data->prim_start_tbf < PRIM_QUEUE_SIZE_TOTAL)) + { + grlc_delete_prim(); + } + + grlc_data->gmm_procedure_is_running = TRUE; + + if(grlc_data->prim_start_free EQ 0xFF) + { + TRACE_ERROR("PRIM_QUEUE FULL: RAU MAY BE SENT, NEXT DATA PRIM WILL BE DELETED "); + } + + for (i=PRIM_QUEUE_SIZE; i<(PRIM_QUEUE_SIZE_TOTAL);i++) + { + grlc_data->prim_queue[i].next = i+1; + + 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[PRIM_QUEUE_SIZE_TOTAL-1].next = 0xff; + + grlc_data->save_prim_start_tbf = grlc_data->prim_start_tbf; + grlc_data->save_prim_start_free = grlc_data->prim_start_free; + + grlc_data->prim_start_tbf = 0xFF; + grlc_data->prim_start_free = PRIM_QUEUE_SIZE; + grlc_data->prim_user_data = 0; + grlc_data->tm.send_grlc_ready_ind = SEND_A_GRLC_READY_IND; + + TRACE_EVENT_P4("GET GMM QUEUE: AFTER ps=%d, pf=%d,sps=%d,spf=%d", + grlc_data->prim_start_tbf, + grlc_data->prim_start_free, + grlc_data->save_prim_start_tbf, + grlc_data->save_prim_start_free); + + +} /* tm_get_gmm_prim_queue */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_get_llc_prim_queue ++------------------------------------------------------------------------------ +| Description : The function tm_get_llc_prim_queue () .... +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_get_llc_prim_queue ( void ) +{ + UBYTE i; + + TRACE_FUNCTION( "tm_get_llc_prim_queue " ); + + + TRACE_EVENT_P4("GET LLC QUEUE: BEFORE ps=%d, pf=%d,sps=%d,spf=%d", + grlc_data->prim_start_tbf, + grlc_data->prim_start_free, + grlc_data->save_prim_start_tbf, + grlc_data->save_prim_start_free); + + + if(grlc_data->prim_start_tbf < PRIM_QUEUE_SIZE_TOTAL) + { + /*finish gmm data and than resume with llc data*/ + i = grlc_data->prim_start_tbf; + while(grlc_data->prim_queue[i].next NEQ 0xFF) + { + i = grlc_data->prim_queue[i].next; + } + grlc_data->prim_queue[i].next = grlc_data->save_prim_start_tbf; + grlc_data->prim_queue[i].start_new_tbf = TRUE; + } + else + { + grlc_data->prim_start_tbf = grlc_data->save_prim_start_tbf; + } + grlc_data->prim_start_free = grlc_data->save_prim_start_free; + grlc_data->gmm_procedure_is_running = FALSE; + grlc_data->prim_user_data = 0; + i = grlc_data->prim_start_tbf; + while(i NEQ 0xFF) + { + grlc_data->prim_user_data += BYTELEN(grlc_data->prim_queue[i].prim_ptr->sdu.l_buf); + i = grlc_data->prim_queue[i].next; + } + + + TRACE_EVENT_P4("GET LLC QUEUE: AFTER ps=%d, pf=%d,sps=%d,spf=%d", + grlc_data->prim_start_tbf, + grlc_data->prim_start_free, + grlc_data->save_prim_start_tbf, + grlc_data->save_prim_start_free); + + + + +} /* tm_get_llc_prim_queue */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_ul_tbf_ind ++------------------------------------------------------------------------------ +| Description : The function tm_ul_tbf_ind () .... +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_ul_tbf_ind ( void ) +{ + TRACE_FUNCTION( "tm_ul_tbf_ind " ); + + + + switch(grlc_data->tbf_type) + { + case TBF_TYPE_NULL: + if( grlc_data->prim_start_tbf < PRIM_QUEUE_SIZE_TOTAL ) + { + PALLOC(cgrlc_ul_tbf_ind,CGRLC_UL_TBF_IND); /*T_CGRLC_UL_TBF_IND*/ + + tm_start_access(); + + cgrlc_ul_tbf_ind->access_type = grlc_data->uplink_tbf.access_type; + cgrlc_ul_tbf_ind->ra_prio = grlc_data->uplink_tbf.prio; + cgrlc_ul_tbf_ind->nr_blocks = grlc_data->uplink_tbf.nr_blocks; + cgrlc_ul_tbf_ind->llc_prim_type = grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_type; + cgrlc_ul_tbf_ind->rlc_oct_cnt = grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_ptr->sdu.l_buf/8 +1; + cgrlc_ul_tbf_ind->peak = grlc_data->prim_queue[grlc_data->prim_start_tbf].prim_ptr->grlc_qos.peak; +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH + cgrlc_ul_tbf_ind->tbf_est_pacch = FALSE; +#endif + + SET_STATE( TM, TM_PAM ); + PSEND(hCommGRR,cgrlc_ul_tbf_ind); + } + else + { + /* + * inform higher layers that no tbf is requested + */ + PALLOC(cgrlc_ul_tbf_ind,CGRLC_UL_TBF_IND); /*T_CGRLC_UL_TBF_IND*/ + cgrlc_ul_tbf_ind->access_type = CGRLC_AT_NULL; + cgrlc_ul_tbf_ind->ra_prio = 0xEE; + cgrlc_ul_tbf_ind->nr_blocks = 0xEE; + cgrlc_ul_tbf_ind->llc_prim_type = 0xEE; + cgrlc_ul_tbf_ind->peak = 0xEE; +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH + cgrlc_ul_tbf_ind->tbf_est_pacch = FALSE; +#endif + + + PSEND(hCommGRR,cgrlc_ul_tbf_ind); + /* + * delete control message queue + */ + tm_set_stop_all_ctrl_blk(); + } + tm_handle_grlc_ready_ind( ); + break; + case TBF_TYPE_DL: + if( (grlc_data->prim_start_tbf < PRIM_QUEUE_SIZE_TOTAL) AND (!grlc_data->tm.n_res_req)) + { + tm_start_access(); + tm_build_chan_req_des(&grlc_data->chan_req_des, + &grlc_data->prim_queue[grlc_data->prim_start_tbf]); + sig_tm_rd_ul_req(); + grlc_data->tm.n_res_req++; + } + break; + case TBF_TYPE_CONC: + case TBF_TYPE_UL: + break; + default: + TRACE_ERROR("unknown tbf type during uplink access"); + break; + } +} /* tm_ul_tbf_ind */ + + + + + + + + + + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_tfi_handling ++------------------------------------------------------------------------------ +| Description : The function tm_tfi_handling () handles modified tfi´s in +| case of starting time +| +| Parameters : start_fn_present: indicates if a starting time is present +| tbf_type : type of the current tbf +| ul_tfi : new assignend uplink tfi +| dl_tfi : new assignend downlink tfi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_tfi_handling (ULONG tbf_start,UBYTE tbf_type, UBYTE ul_tfi, UBYTE dl_tfi) +{ + + TRACE_FUNCTION( "tm_tfi_handling " ); + + + /*TRACE_EVENT_P6("TFI CHANGE: =tbf_type = %d\n fn= %ld \n new_Utfi=%d old_Utfi=%d \n new_Dtfi=%d old_Dtfi=%d" + ,tbf_type + ,tbf_start + ,ul_tfi + ,grlc_data->ul_tfi + ,dl_tfi + ,grlc_data->dl_tfi); + + */ + switch( tbf_type ) + { + case CGRLC_TBF_MODE_UL: + if((tbf_start NEQ CGRLC_STARTING_TIME_NOT_PRESENT) AND (ul_tfi NEQ grlc_data->ul_tfi)) /*lint !e650*/ + { + if(grlc_data->tfi_change EQ TFI_CHANGE_NULL) + grlc_data->tfi_change = TFI_CHANGE_UL; + else if(grlc_data->tfi_change EQ TFI_CHANGE_DL) + grlc_data->tfi_change = TFI_CHANGE_ALL; + grlc_data->start_fn_ul_tfi = ul_tfi; + grlc_data->ul_tbf_start_time = tbf_start; + TRACE_EVENT_P3("GRLC UL TFI CHANGE AFTER ST. TIME = %ld new_tfi=%d old_tfi=%d" + ,tbf_start + ,ul_tfi + ,grlc_data->ul_tfi); + } + else + { + if(grlc_data->tfi_change EQ TFI_CHANGE_UL) + grlc_data->tfi_change = TFI_CHANGE_NULL; + else if(grlc_data->tfi_change EQ TFI_CHANGE_ALL) + grlc_data->tfi_change = TFI_CHANGE_DL; + grlc_data->ul_tfi = ul_tfi; + grlc_data->start_fn_ul_tfi = 0xFF; + grlc_data->ul_tbf_start_time = CGRLC_STARTING_TIME_NOT_PRESENT; + } +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH + sig_tm_gff_ul_activate(GFF_ACTIVE); +#else + sig_tm_gff_ul_activate(); +#endif + break; + case CGRLC_TBF_MODE_DL: + if((tbf_start NEQ CGRLC_STARTING_TIME_NOT_PRESENT) AND (dl_tfi NEQ grlc_data->dl_tfi)) /*lint !e650*/ + { + if(grlc_data->tfi_change EQ TFI_CHANGE_NULL) + grlc_data->tfi_change = TFI_CHANGE_DL; + else if(grlc_data->tfi_change EQ TFI_CHANGE_UL) + grlc_data->tfi_change = TFI_CHANGE_ALL; + grlc_data->start_fn_dl_tfi = dl_tfi; + grlc_data->dl_tbf_start_time = tbf_start; + TRACE_EVENT_P3("GRLC DL TFI CHANGE AFTER ST. TIME =%ld new_tfi=%d old_tfi=%d" + ,tbf_start + ,dl_tfi + ,grlc_data->dl_tfi); + } + else + { + if(grlc_data->tfi_change EQ TFI_CHANGE_DL) + grlc_data->tfi_change = TFI_CHANGE_NULL; + else if(grlc_data->tfi_change EQ TFI_CHANGE_ALL) + grlc_data->tfi_change = TFI_CHANGE_UL; + grlc_data->dl_tfi = dl_tfi; + grlc_data->start_fn_dl_tfi = 0xFF; + grlc_data->dl_tbf_start_time = CGRLC_STARTING_TIME_NOT_PRESENT; + } + sig_tm_gff_dl_activate(); + break; +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH + case CGRLC_TBF_MODE_2PA: + sig_tm_gff_ul_activate(GFF_TWO_PHASE); + break; +#endif + + } + + + /*TRACE_EVENT_P1("TFI_CHANGE = %d",grlc_data->tfi_change );*/ + +} /* tm_tfi_handling () */ + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_cgrlc_status_ind ++------------------------------------------------------------------------------ +| Description : Handles the primitive CGRLC_STATUS_IND +| +| Parameters : cause - status cause, gmm is informed +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_cgrlc_status_ind ( UBYTE cause ) +{ + PALLOC(cgrlc_status_ind,CGRLC_STATUS_IND); + + TRACE_FUNCTION( "tm_cgrlc_status_ind" ); + + cgrlc_status_ind->failure = cause; + PSEND(hCommGMM,cgrlc_status_ind); + + TRACE_EVENT_P1("error cause = %ld",cause); + + +}/* tm_cgrlc_status_ind*/ + +/* ++------------------------------------------------------------------------------ +| Function : tm_handle_polling_bit ++------------------------------------------------------------------------------ +| Description : Handles the the polling in the immediate assignment (uplink or +| downlink) +| +| Parameters : st_fn - starting time +| tn - timeslot +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_handle_polling_bit ( ULONG st_fn, UBYTE tn ) +{ + + TRACE_FUNCTION( "tm_handle_polling_bit" ); + + + + grlc_data->next_poll_fn = st_fn; + grlc_data->ul_poll_pos_index = 0; + if(grlc_data->burst_type EQ 0) + { + grlc_send_access_burst( tn ); + } + else + { + grlc_send_normal_burst(grlc_set_packet_ctrl_ack(), NULL, tn); + } + + + +}/* tm_handle_polling_bit */ + + + +/* ++------------------------------------------------------------------------------ +| Function : tm_store_fa_bitmap ++------------------------------------------------------------------------------ +| Description : This function stores the allocation bitmap in +| case of fixed allocation +| +| Parameters : ptr2_fix_alloc - ptr to the fixed allocation struct +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_store_fa_bitmap (T_CGRLC_fix_alloc_struct * ptr2_fix_alloc) +{ + UBYTE i,j; + USHORT ul_res_sum = 0; + T_FA_ALLOC * ptr_fa_ctrl; + + TRACE_FUNCTION( "tm_store_fa_bitmap" ); + + + /* + * calculate uplink resources allocation + */ + + for(i=0;i<ptr2_fix_alloc->bitmap_len;i++) + { + if(ptr2_fix_alloc->bitmap_array[i]) + { + UBYTE mask = 0x80; + + for(j=0; j<=7; j++) + { + if(ptr2_fix_alloc->bitmap_array[i] & mask) + ul_res_sum++; + mask>>=1; + } + } + } + + + /* + * set fa_ctrl + */ + if(grlc_data->uplink_tbf.fa_manag.fa_type EQ FA_NO_CURRENT) + { + grlc_data->uplink_tbf.fa_manag.fa_type = FA_NO_NEXT; + ptr_fa_ctrl = &grlc_data->uplink_tbf.fa_manag.current_alloc; + ptr_fa_ctrl->alloc_start_fn = grlc_data->ul_tbf_start_time; + ptr_fa_ctrl->alloc_end_fn = ptr2_fix_alloc->end_fn; + } + else + { + grlc_data->uplink_tbf.fa_manag.fa_type = FA_BITMAP; + ptr_fa_ctrl = &grlc_data->uplink_tbf.fa_manag.next_alloc; + ptr_fa_ctrl->alloc_start_fn = grlc_data->ul_tbf_start_time; + + /* + * check conflict of end of current alloc and start of next alloc + */ + if( grlc_check_dist(grlc_data->uplink_tbf.fa_manag.current_alloc.alloc_end_fn, + grlc_data->uplink_tbf.fa_manag.next_alloc.alloc_start_fn,10000)) + { + ULONG delta_fn; + UBYTE idle_frames; + UBYTE iden_radio_blocks; + UBYTE ts_delet; + + delta_fn = grlc_data->uplink_tbf.fa_manag.current_alloc.alloc_end_fn - + grlc_data->uplink_tbf.fa_manag.next_alloc.alloc_start_fn; + idle_frames = (UBYTE)((delta_fn / 52) *4 + delta_fn % 4); + iden_radio_blocks = (UBYTE)((delta_fn - idle_frames) / 4 + 1); + + /* + * remove shared allocation from current allocation + */ + ts_delet = 0; + for(i=0;i<iden_radio_blocks;i++) + { + UBYTE pos; + pos = grlc_data->uplink_tbf.fa_manag.current_alloc.alloc.bitmap_len - i; + + /* + * calculate number of timeslots for current frame and delete them from resources + */ + if(grlc_data->uplink_tbf.fa_manag.current_alloc.alloc.bitmap_array[pos]) + { + UBYTE mask = 0x80; + + for(j=0; j<=7; j++) + { + if(ptr2_fix_alloc->bitmap_array[i] & mask) + ts_delet++; + mask>>=1; + } + } + grlc_data->uplink_tbf.fa_manag.current_alloc.alloc.bitmap_array[pos] = 0; + } + grlc_data->uplink_tbf.fa_manag.current_alloc.ul_res_sum -= ts_delet; + grlc_data->uplink_tbf.fa_manag.ul_res_sum -= ts_delet; + grlc_data->uplink_tbf.fa_manag.current_alloc.alloc.bitmap_len -= iden_radio_blocks; + grlc_data->uplink_tbf.fa_manag.current_alloc.alloc_end_fn = + grlc_data->uplink_tbf.fa_manag.current_alloc.alloc_end_fn - delta_fn; + } + } + grlc_data->uplink_tbf.fa_manag.ul_res_sum += ul_res_sum; + ptr_fa_ctrl->ul_res_sum = ul_res_sum; + /* + * store end of fixed allocation + */ + ptr_fa_ctrl->alloc_end_fn = ptr2_fix_alloc->end_fn; + + + tm_handle_final_alloc (ptr2_fix_alloc->final_alloc); + +} /* tm_store_fa_bitmap() */ + + +/* ++------------------------------------------------------------------------------ +| Function : tm_handle_final_alloc ++------------------------------------------------------------------------------ +| Description : This function handles the final allocation bit. +| +| Parameters : - +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_handle_final_alloc (UBYTE final_allocation) +{ + UBYTE next; + T_RLC_VALUES rlc_val; + USHORT rlc_data_size=0; + + TRACE_FUNCTION( "tm_handle_final_alloc" ); + + switch(grlc_data->uplink_tbf.cs_type) + { + case CS_1: + rlc_data_size = 20; + break; + case CS_2: + rlc_data_size = 30; + break; + case CS_3: + rlc_data_size = 36; + break; + case CS_4: + rlc_data_size = 50; + break; + default: + break; + } + if(grlc_data->prim_start_tbf < PRIM_QUEUE_SIZE_TOTAL AND + grlc_data->prim_queue[grlc_data->prim_start_tbf].rlc_status EQ FALSE ) + { + next = grlc_data->prim_queue[grlc_data->prim_start_tbf].next; + } + else + { + next = grlc_data->prim_start_tbf; + TRACE_EVENT_P3("PST=%d PSF=%d PDU=%d: tm_handle_final_alloc" + ,grlc_data->prim_start_tbf + ,grlc_data->prim_start_free + ,grlc_data->grlc_data_req_cnt); + + } + grlc_get_sdu_len_and_used_ts( &rlc_val); + grlc_data->uplink_tbf.fa_manag.tbf_oct_cnt = rlc_val.sdu_len; + grlc_data->uplink_tbf.fa_manag.ul_res_used = rlc_val.cnt_ts; + grlc_data->uplink_tbf.fa_manag.ul_res_remain = + grlc_data->uplink_tbf.fa_manag.ul_res_sum - grlc_data->uplink_tbf.fa_manag.ul_res_used; + grlc_data->uplink_tbf.fa_manag.tbf_oct_cap_remain = grlc_data->uplink_tbf.fa_manag.ul_res_remain * rlc_data_size; + + if(final_allocation) + { + /* + * last allocation of the tbf, it must end at the end of tbf. + * check if more data is in prim queue than available uplink resources. + * NO: nothing to do + * YES: reorganize prim queue(set start_new_tbf) and inform RU + */ + + + while((grlc_data->prim_queue[next].start_new_tbf EQ 0) AND + (next NEQ 0xFF) ) + { + if(grlc_data->uplink_tbf.fa_manag.tbf_oct_cap_remain < + (grlc_data->uplink_tbf.fa_manag.tbf_oct_cnt + grlc_data->prim_queue[next].prim_ptr->sdu.l_buf/8 + 1)) + { + /* + * find the end of the tbf. + */ + grlc_data->prim_queue[next].start_new_tbf = 1; + sig_tm_ru_queue_status(); + return; + } + grlc_data->uplink_tbf.fa_manag.tbf_oct_cnt += grlc_data->prim_queue[next].prim_ptr->sdu.l_buf/8; + grlc_data->uplink_tbf.fa_manag.tbf_oct_cnt++; /* for pdu boundaries */ + next = grlc_data->prim_queue[next].next; + } + } + else + { + /* + * not the last allocation + */ + while((grlc_data->prim_queue[next].start_new_tbf EQ 0) AND + (next NEQ 0xFF) ) + { + grlc_data->uplink_tbf.fa_manag.tbf_oct_cnt += grlc_data->prim_queue[next].prim_ptr->sdu.l_buf/8; + grlc_data->uplink_tbf.fa_manag.tbf_oct_cnt++; /* for pdu boundaries */ + next = grlc_data->prim_queue[next].next; + } + } + + +} /* tm_handle_final_alloc() */ + + +/* ++------------------------------------------------------------------------------ +| Function : tm_set_fa_bitmap ++------------------------------------------------------------------------------ +| Description : sets fixed allocation bitmap for requested allocation after +| receiving a repeat allocation with ts_override +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL USHORT tm_set_fa_bitmap( UBYTE ts_mask, T_FA_ALLOC* ptr_alloc) +{ + UBYTE i,j; + USHORT tx_slots; + TRACE_FUNCTION( "tm_set_fa_bitmap" ); + + if (ts_mask) + { + /* + * add new time slots to current allocation + */ + tx_slots = 0; + for(i=0;i<grlc_data->uplink_tbf.fa_manag.current_alloc.alloc.bitmap_len;i++) + { + ptr_alloc->alloc.bitmap_array[i] = grlc_data->uplink_tbf.fa_manag.current_alloc.alloc.bitmap_array[i] | ts_mask; + + if(ptr_alloc->alloc.bitmap_array[i]) + { + UBYTE mask = 0x80; + + for(j=0; j<=7; j++) + { + if(ptr_alloc->alloc.bitmap_array[i] & mask) + tx_slots++; + mask>>=1; + } + } + + + } + } + else + { + /* + * no new timeslot allocated + */ + tx_slots = grlc_data->uplink_tbf.fa_manag.current_alloc.ul_res_sum; + } + return (tx_slots); + +} /* tm_set_fa_bitmap() */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_handle_test_mode_cnf ++------------------------------------------------------------------------------ +| Description : +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_handle_test_mode_cnf ( BOOL v_test_mode_cnf ) +{ + TRACE_FUNCTION( "tm_handle_test_mode_cnf" ); + + if( v_test_mode_cnf EQ TRUE ) + { + PALLOC( cgrlc_test_mode_cnf, CGRLC_TEST_MODE_CNF ); + + grlc_data->testmode.mode = CGRLC_NO_TEST_MODE; + + PSEND( hCommGMM, cgrlc_test_mode_cnf ); + + tm_delete_prim_queue(); + /*inform grr that testmode is finished*/ + { + PALLOC(cgrlc_test_mode_ind,CGRLC_TEST_MODE_IND); /*T_CGRLC_TEST_MODE_IND*/ + cgrlc_test_mode_ind->test_mode_flag = CGRLC_NO_TEST_MODE; + PSEND(hCommGRR,cgrlc_test_mode_ind); + } + + } +} /* tm_handle_test_mode_cnf() */ + +/* ++------------------------------------------------------------------------------ +| Function : tm_prcs_pwr_ctrl ++------------------------------------------------------------------------------ +| Description : +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void tm_prcs_pwr_ctrl ( T_CGRLC_pwr_ctrl *pwr_ctrl ) +{ + TRACE_FUNCTION( "tm_prcs_pwr_ctrl" ); + + if( pwr_ctrl->v_pwr_ctrl_param ) + { + tpc_set_pwr_ctrl_param( &pwr_ctrl->pwr_ctrl_param ); + } + + if( pwr_ctrl->v_glbl_pwr_ctrl_param ) + { + tpc_set_glbl_pwr_ctrl_param( &pwr_ctrl->glbl_pwr_ctrl_param ); + } + + if( pwr_ctrl->v_freq_param ) + { + grlc_data->tm.freq_param = pwr_ctrl->freq_param; + } + + if( pwr_ctrl->v_c_value ) + { + meas_grlc_c_set_c_value( &pwr_ctrl->c_value ); + } + + sig_tm_tpc_update_pch( ); + + { + PALLOC( pwr_ctrl_cnf, CGRLC_PWR_CTRL_CNF ); + PSEND( hCommGRR, pwr_ctrl_cnf ); + } +} /* tm_prcs_pwr_ctrl() */ + + +#if defined REL99 AND defined TI_PS_FF_TBF_EST_PACCH +GLOBAL void tm_send_msg_directly_to_l1_queue (UBYTE * unencoded_msg) +{ + + TRACE_FUNCTION( "tm_send_msg_directly_to_l1_queue" ); + + /* Call function that formats ARAC message */ + + memset(&grlc_data->ru.ul_data[0], + 0, + sizeof(T_ul_data)); + + grlc_data->ru.ul_data[0].block_status = 2; + grlc_encode_ul_ctrl_block(( UBYTE* ) grlc_data->ru.ul_data[0].ul_block, + ( UBYTE* )unencoded_msg ); + +#ifdef _SIMULATION_ + { + PALLOC(mac_data_req,MAC_DATA_REQ); + memset(&(mac_data_req->ul_data), + 0, + sizeof(T_ul_data)); + memcpy(&(mac_data_req->ul_data), + &(grlc_data->ru.ul_data[0]), + sizeof(T_ul_data)); + PSEND(hCommL1,mac_data_req); + } +#else + /* No need to copy again */ +#endif /* ! _SIMULATION_ */ + + grlc_data->ru.ul_data[1].block_status = 0; + return; + +} + + +GLOBAL void tm_send_prr_2p_ptm ( void ) +{ + T_U_GRLC_RESOURCE_REQ resource_req; + + TRACE_FUNCTION( "tm_send_prr_2p_ptm" ); + + tm_build_res_req( &resource_req, R_BUILD_2PHASE_ACCESS); + + tm_send_msg_directly_to_l1_queue((UBYTE *)&resource_req); + + return; + +} +#endif