FreeCalypso > hg > fc-selenite
view src/g23m-gprs/grlc/grlc_tmf.c @ 158:8fe0cde2fd79
doc/Compiling: update for SE J100 target and fc-host-tools-r10
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 17 Mar 2019 07:20:28 +0000 |
parents | d393cd9bb723 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GPRS (8441) | Modul : GRLC +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : This module implements 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