FreeCalypso > hg > fc-magnetite
view src/g23m-gprs/grr/grr_psif.c @ 555:6690ae453594
configs: hybrid-gpf renamed to hybrid-osl
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 19 Nov 2018 00:16:07 +0000 |
parents | 219afcfc6250 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GPRS (8441) | Modul : GRR +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : This module implements local functions for service PSI of | entity GRR. +----------------------------------------------------------------------------- */ #ifndef GRR_PSIF_C #define GRR_PSIF_C #endif #define ENTITY_GRR #ifdef _SIMULATION_ /* * Report warning 4005 as an error. * * There are identical macro definitons in the GRR message and the RRGRR SAP * document which should be aligned at all the time * (e.g. GPRS_RXLEV_ACCESS_MIN_INVALID, GPRS_MS_TXPWR_MAX_CCH, etc.) */ #pragma warning( error : 4005 ) #endif /* #ifdef _SIMULATION_ */ /*==== INCLUDES =============================================================*/ #include "typedefs.h" /* to get Condat data types */ #include "vsi.h" /* to get a lot of macros */ #include "macdef.h" #include "gprs.h" #include "gsm.h" /* to get a lot of macros */ #include "ccdapi.h" /* to get CCD API */ #include "cnf_grr.h" /* to get cnf-definitions */ #include "mon_grr.h" /* to get mon-definitions */ #include "prim.h" /* to get the definitions of used SAP and directions */ #include "message.h" #include "grr.h" /* to get the global entity definitions */ #include "grr_f.h" #include "grr_psif.h" /* */ #include "grr_ctrls.h" /* */ #include "grr_css.h" /* signals exchanged between PSI and CS*/ #include "grr_meass.h" /* signals exchanged between PSI and MEAS*/ #include <string.h> /* for memcpy */ #include <stdio.h> /* for memcpy */ #include "grr_em.h" /*for Engineering mode*/ /*==== DIAGNOSTICS ==========================================================*/ /*==== CONST ================================================================*/ #define PBCCH_NOT_PRESENT 0x0 /* PBCCH not present in the cell */ #define PBCCH_PRESENT 0x1 /* PBCCH present in the cell */ /*==== LOCAL VARS ===========================================================*/ LOCAL void psi_reset_psi_pos ( void ); #ifndef _TARGET_ LOCAL void psi_fill_rel_pos(UBYTE *src, UBYTE max_src, UBYTE *psi_nr, UBYTE *pos_array); #endif /*_TARGET_*/ /*==== PRIVATE FUNCTIONS ====================================================*/ LOCAL void psi_reset_complete_acq ( void ); LOCAL void psi_reset_psi1 (void ); LOCAL void psi_reset_psi2 (void ); LOCAL void psi_reset_psi3 (void ); LOCAL void psi_reset_psi3bis (void ); #if defined (REL99) AND defined (TI_PS_FF_EMR) LOCAL void psi_reset_psi3ter (void ); #endif LOCAL void psi_reset_psi4 (void ); LOCAL void psi_reset_psi5 (void ); #ifdef REL99 LOCAL void psi_reset_psi8 (void); #endif LOCAL void psi_reset_psi13 (void ); LOCAL void psi_init_states_of_psi ( void ); LOCAL void psi_init_rfl_psi2(void); LOCAL void psi_init_cell_alloc(void); LOCAL void psi_init_gprs_ms_alloc(BOOL psi2_only); LOCAL void psi_copy_si13_params(T_D_SYS_INFO_13* si13); LOCAL void psi_copy_psi13_params(T_PSI_13* psi13); LOCAL BOOL psi_check_change_field (UBYTE psi_change_field); LOCAL UBYTE psi_compare_change_mark(UBYTE received_change_mark, UBYTE stored_change_mark); LOCAL BOOL psi_is_pbcch_des_different(T_PSI_13* psi13); /* * Private functions for handling of PSI3 and PSI3BIS messages. * Reading of those messages in not ordered sequence. */ /* * Storing */ LOCAL UBYTE psi_store_ncell_param ( T_ncell_par *p_ncell_par, UBYTE c_ncell_par, UBYTE v_ncell_par, T_INFO_TYPE type, UBYTE instance ); LOCAL void psi_store_ncell_param2 ( T_PSI_3_BIS *psi3bis, UBYTE number ); LOCAL BOOL psi_store_cs_param2 ( T_NC_LIST *nc_list, T_ncell_par2_set *cs_par2, UBYTE instance, UBYTE *number, USHORT *freq, USHORT freq_diff, UBYTE same_ra_scell, UBYTE cell_ba, UBYTE bcc ); /* * Restoring */ LOCAL void psi_restore_ncell_param ( void ); #ifdef REL99 LOCAL void psi_update_bss_sgsn_rel ( T_D_SYS_INFO_13 *si13, BOOL pbcch_status ); #endif /*==== PUBLIC FUNCTIONS =====================================================*/ /* +------------------------------------------------------------------------------ | Function : psi_compare_change_mark() +------------------------------------------------------------------------------ | Description : The function psi_compare_change_mark() .... compares the change_mark values | and indicates the incrementatiton value | | Parameters : UBYTE received_change_mark, UBYTE stored_change_mark | +------------------------------------------------------------------------------ */ LOCAL UBYTE psi_compare_change_mark(UBYTE received_change_mark, UBYTE stored_change_mark) { UBYTE incremented_value = 0; if(received_change_mark NEQ stored_change_mark) { UBYTE dummy = (stored_change_mark + 1)%8; if(dummy EQ received_change_mark) incremented_value = 1; else incremented_value = 2; } return incremented_value; }/* psi_compare_change_mark*/ /* +------------------------------------------------------------------------------ | Function : psi_stop_psi_reading() +------------------------------------------------------------------------------ | Description : The function psi_stop_psi_reading() .... stops to read PSI messages | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_stop_psi_reading( ACQ_TYPE acq_type_in_idle) { TRACE_FUNCTION( "psi_stop_psi_reading" ); psc_db->acq_type = acq_type_in_idle; if(grr_is_pbcch_present()) { PALLOC(mphp_scell_pbcch_req, MPHP_SCELL_PBCCH_STOP_REQ); PSEND(hCommL1,mphp_scell_pbcch_req); } }/* psi_stop_psi_reading*/ /* +------------------------------------------------------------------------------ | Function : psi_check_acq_state +------------------------------------------------------------------------------ | Description : The function psi_check_acq_state() .... checks the state of the acquisition | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL T_ACQ_STATE_RET psi_check_acq_state ( void ) { UBYTE n; T_ACQ_STATE_RET return_val = ACQ_RUNNING; TRACE_FUNCTION( "psi_check_acq_state" ); switch(psc_db->acq_type) { case PARTIAL: return_val = ACQ_PART_OK; for(n = 0; n <MAX_PSI; n++) { if(psc_db->state_of_PSI[n].state EQ NEEDED) { /* * partial acquisition not completed */ return_val = ACQ_RUNNING; } } if(return_val EQ ACQ_PART_OK) { psi_stop_10sec(); /* partial acquisition completed */ psc_db->acq_type = NONE; /* e.g. wait 30 sec for reread PSI1*/ psc_db->psi1_params.first_psi1 = FALSE; #ifdef REL99 /* Partial acquisition is complete. Send CBCH info * to RR if needed. */ if(psc_db->send_cbch_info_ind) { sig_psi_ctrl_cbch_info_ind(); psc_db->send_cbch_info_ind = FALSE; } #endif } break; case COMPLETE: return_val = ACQ_COMP_OK; /* * Check whether reading process completed or not */ for(n = 0; n <MAX_PSI; n++) { if(psc_db->state_of_PSI[n].state EQ NEEDED) { /* * acquisition of some PSI not completed */ { if(n EQ 3) { TRACE_EVENT("acq. incomplete PSI3bis missing!"); } #if defined (REL99) AND defined (TI_PS_FF_EMR) else if(n EQ 4) { TRACE_EVENT("acq. incomplete PSI3ter missing!"); } else if(n EQ 7) { TRACE_EVENT("acq. incomplete PSI8 missing!"); } else { TRACE_EVENT_P1("acq. incomplete PSI%d missing!", ((n>3)?n-1:n+1)); } #else else { TRACE_EVENT_P1("acq. incomplete PSI%d missing!", ((n>3)?n:n+1)); } #endif } return_val = ACQ_RUNNING; break; /* break for loop*/ } } if(return_val EQ ACQ_COMP_OK) { /* * Start timer for 10 sec. if running */ TRACE_EVENT("Acq. complete"); vsi_t_stop(GRR_handle, T_COMP_PSI); psi_stop_10sec(); /* acquisition of all PSI completed */ psc_db->acq_type = NONE; /* e.g. wait 30 sec for reread PSI1*/ psc_db->psi1_params.first_psi1 = FALSE; } break; case PERIODICAL_PSI1_READING: psc_db->acq_type = NONE; /* e.g. wait 30 sec for reread PSI1*/ return_val = ACQ_PERIOD_OK; break; case FULL_PSI_IN_NEW_CELL: return_val = ACQ_NPSI_OK; psc_db->acq_type = NONE; /* e.g. wait 30 sec for reread PSI1*/ /* * E.g. read all PSI in the reselected cell * Check whether reading process completed or not */ for(n = 0; n <MAX_PSI; n++) { if(psc_db->state_of_PSI[n].state EQ NEEDED) { /* * acquisition of some PSI not completed */ return_val = ACQ_RUNNING; psc_db->acq_type = FULL_PSI_IN_NEW_CELL; break; /* break for loop*/ } } if(n>MAX_PSI) psc_db->psi1_params.first_psi1 = FALSE; break; case NONE: /* nothing to do: we may received a PSI message without sending a request * e.g. on PCCCH (PPCH: paging channel or paging group) */ break; default: break; } return return_val; } /* psi_check_acq_state() */ /* +------------------------------------------------------------------------------ | Function : psi_reset_complete_acq +------------------------------------------------------------------------------ | Description : The function psi_reset_complete_acq() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_reset_complete_acq ( void ) { TRACE_FUNCTION( "psi_reset_complete_acq" ); psc_db->acq_type = COMPLETE; psc_db->complete_acq.needed = TRUE; psc_db->complete_acq.psi1_ok = FALSE; psc_db->complete_acq.psi2_ok = FALSE; psc_db->complete_acq.made_at_least_one_attempt = FALSE; }/* psi_reset_complete_acq*/ /* +------------------------------------------------------------------------------ | Function : psi_reset_psi1 +------------------------------------------------------------------------------ | Description : The function psi_reset_psi1() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_reset_psi1 ( void ) { TRACE_FUNCTION( "psi_reset_psi1" ); psc_db->psi1_params.pbcch_change_mark = NOT_SET; psc_db->psi1_params.psi_change_field = NOT_SET; psc_db->psi1_params.psi_cnt_lr = 0; psc_db->psi1_params.psi_cnt_hr = 0; psc_db->psi1_params.psi1_repeat_period = NOT_SET; psc_db->psi1_params.first_psi1 = TRUE; }/* psi_reset_psi1*/ /* +------------------------------------------------------------------------------ | Function : psi_reset_psi2 +------------------------------------------------------------------------------ | Description : The function psi_reset_psi2() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_reset_psi2 ( void ) { UBYTE n; TRACE_FUNCTION( "psi_reset_psi2" ); /* reset psi2 parameters*/ psc_db->psi2_params.psi2_change_mark = NOT_SET; /*not set*/ psc_db->psi2_params.psi2_count = NOT_SET; /*not set*/ for(n = 0; n <MAX_NR_OF_INSTANCES_OF_PSI2 + 1; n++) psc_db->psi2_params.instances[n] = FALSE; #ifdef REL99 psc_db->v_add_psi = FALSE; #endif psi_init_rfl_psi2(); psi_init_cell_alloc(); psi_init_gprs_ms_alloc(TRUE); } /* psi_reset_psi2 */ /* +------------------------------------------------------------------------------ | Function : psi_reset_psi3 +------------------------------------------------------------------------------ | Description : The function psi_reset_psi3() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_reset_psi3 ( void ) { TRACE_FUNCTION( "psi_reset_psi3" ); /* reset psi3 parameters*/ psc_db->psi3_params.psi3_change_mark = NOT_SET; psc_db->psi3_params.psi3_bis_count = NOT_SET; #if defined (REL99) AND defined (TI_PS_FF_EMR) grr_init_nc_list( &psc_db->nc_cw.list ); #endif } /* psi_reset_psi3 */ /* +------------------------------------------------------------------------------ | Function : psi_reset_psi3bis +------------------------------------------------------------------------------ | Description : The function psi_reset_psi3bis() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_reset_psi3bis ( void ) { UBYTE n; TRACE_FUNCTION( "psi_reset_psi3bis" ); psc_db->psi3bis_params.psi3bis_change_mark = NOT_SET; psc_db->psi3bis_params.psi3bis_index = 0; for(n = 0; n <MAX_NR_OF_INSTANCES_OF_PSI3BIS + 1; n++) psc_db->psi3bis_params.instances[n] = FALSE; grr_init_nc_list( &psc_db->nc_cw.list ); } /* psi_reset_psi3bis */ #if defined (REL99) AND defined (TI_PS_FF_EMR) /* +------------------------------------------------------------------------------ | Function : psi_reset_psi3ter +------------------------------------------------------------------------------ | Description : The function psi_reset_psi3ter() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_reset_psi3ter ( void ) { UBYTE n; TRACE_FUNCTION( "psi_reset_psi3ter" ); psc_db->psi3ter_params.psi3ter_change_mark = NOT_SET; psc_db->psi3ter_params.prev_psi3ter_index = 0; psc_db->psi3ter_params.psi3ter_index = 0; for(n = 0; n <MAX_NR_OF_INSTANCES_OF_PSI3TER + 1; n++) psc_db->psi3ter_params.instances[n] = FALSE; psc_db->enh_cw.gprs_rept_prio_desc.num_cells = 0; #ifdef TI_PS_FF_RTD /* Rtd values has to be reset to not available */ for( n = 0; n < MAX_NR_OF_NCELL; n++ ) psc_db->rtd[n] = RTD_NOT_AVAILABLE; #endif /* #ifdef TI_PS_FF_RTD */ } /* psi_reset_psi3ter */ #endif /* +------------------------------------------------------------------------------ | Function : psi_reset_psi4 +------------------------------------------------------------------------------ | Description : The function psi_reset_psi4() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_reset_psi4 ( void ) { UBYTE n; TRACE_FUNCTION( "psi_reset_psi4" ); /* reset psi_reset_psi4 parameters*/ psc_db->psi4_params.psi4_index = 0; psc_db->psi4_params.psi4_change_mark = NOT_SET; for(n = 0; n <MAX_NR_OF_INSTANCES_OF_PSI4 + 1; n++) psc_db->psi4_params.instances[n] = FALSE; } /* psi_reset_psi4 */ /* +------------------------------------------------------------------------------ | Function : psi_reset_psi5 +------------------------------------------------------------------------------ | Description : The function psi_reset_psi5() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_reset_psi5 ( void ) { UBYTE i; TRACE_FUNCTION( "psi_reset_psi5" ); /* reset psi_reset_psi5 parameters*/ psc_db->psi5_params.psi5_index = 0; psc_db->psi5_params.psi5_change_mark = NOT_SET; for( i = 0; i < MAX_NR_OF_INSTANCES_OF_PSI5; i++ ) { psc_db->psi5_params.idx[i].start = RRGRR_INVALID_IDX; psc_db->psi5_params.idx[i].stop = RRGRR_INVALID_IDX; psc_db->psi5_params.instances[i] = FALSE; } /* * used for checking the consistency of PSI5. instances[0]: number of instances */ psc_db->psi5_params.instances[MAX_NR_OF_INSTANCES_OF_PSI5] = FALSE; grr_init_nc_param( &psc_db->nc_cw.param, TRUE ); grr_init_xmeas_struct( &psc_db->ext_psi5 ); #if defined (REL99) AND defined (TI_PS_FF_EMR) grr_init_enh_param(&psc_db->enh_cw, FALSE); grr_init_enh_param(&grr_data->psi.enh_param, FALSE); #endif } /* psi_reset_psi5 */ #ifdef REL99 /* +------------------------------------------------------------------------------ | Function : psi_reset_psi8 +------------------------------------------------------------------------------ | Description : The function psi_reset_psi8() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_reset_psi8 ( void ) { UBYTE n; TRACE_FUNCTION( "psi_reset_psi8" ); /* reset psi_reset_psi8 parameters*/ psc_db->psi8_params.psi8_index = 0; psc_db->psi8_params.psi8_change_mark = NOT_SET; for(n = 0; n <MAX_NR_OF_INSTANCES_OF_PSI8 + 1; n++) psc_db->psi8_params.instances[n] = FALSE; psc_db->send_cbch_info_ind = FALSE; psc_db->v_cbch_chan_desc = FALSE; } /* psi_reset_psi8 */ #endif /* +------------------------------------------------------------------------------ | Function : psi_reset_psi13 +------------------------------------------------------------------------------ | Description : The function psi_reset_psi13() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_reset_psi13 ( void ) { TRACE_FUNCTION( "psi_reset_psi13" ); grr_init_nc_param( &psc_db->nc_cw.param, TRUE ); } /* psi_reset_psi13 */ /* +------------------------------------------------------------------------------ | Function : psi_reset_all +------------------------------------------------------------------------------ | Description : The function psi_reset_all() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_reset_all ( void ) { TRACE_FUNCTION( "psi_reset_all" ); /* reset complete acq.*/ psi_reset_complete_acq(); /* reset PSI1 parameters */ psi_reset_psi1(); /* reset psi2 parameters*/ psi_reset_psi2(); /* reset psi3 parameters*/ psi_reset_psi3(); /* reset psi3bis parameters*/ psi_reset_psi3bis(); #if defined (REL99) AND defined (TI_PS_FF_EMR) /* reset psi3ter parameters*/ psi_reset_psi3ter(); #endif /* reset psi4 parameters*/ psi_reset_psi4(); /* reset psi5 parameters*/ psi_reset_psi5(); #ifdef REL99 /* reset psi8 parameters*/ psi_reset_psi8(); #endif /* reset psi13 parameters*/ psi_reset_psi13(); /* */ psc_db->send_psi_status = FALSE; /* init the states of the PSI parameters*/ psi_init_states_of_psi(); psi_reset_si_entries(); } /* psi_reset_all() */ /* +------------------------------------------------------------------------------ | Function : psi_stop_10sec +------------------------------------------------------------------------------ | Description : The function psi_stop_10sec() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_stop_10sec ( void ) { TRACE_FUNCTION( "psi_stop_10sec" ); vsi_t_stop(GRR_handle,T_10_SEC); } /* psi_stop_10sec() */ /* +------------------------------------------------------------------------------ | Function : psi_start_10sec +------------------------------------------------------------------------------ | Description : The function psi_start_10sec() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_start_10sec ( void ) { TRACE_FUNCTION( "psi_start_10sec" ); if(grr_data->psi.is_start_of_10_sec_allowed) vsi_t_start(GRR_handle,T_10_SEC, T_10_SEC_VALUE); } /* psi_start_10sec() */ /* +------------------------------------------------------------------------------ | Function : psi_partial_acq +------------------------------------------------------------------------------ | Description : The function psi_partial_acq() performs partial acquisition | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_partial_acq ( void ) { UBYTE psi_reading_type; UBYTE dummy=0; TRACE_FUNCTION( "psi_partial_acq" ); psi_reading_type = PSI_IN_HR_AND_LR; psc_db->acq_type = PARTIAL; if( psc_db->state_of_PSI[PSI2].state EQ NEEDED) { psi_reading_type = READ_PSI2; psi_reset_psi2(); dummy++; TRACE_EVENT("PSI 2 needed"); } if( psc_db->state_of_PSI[PSI3].state EQ NEEDED) { psi_reading_type = READ_PSI3_3BIS; psi_reset_psi3(); psi_reset_psi3bis(); #if defined (REL99) AND defined (TI_PS_FF_EMR) psi_reset_psi3ter(); #endif dummy++; #if defined (REL99) AND defined (TI_PS_FF_EMR) TRACE_EVENT("PSI3/3bis/3ter needed"); #else TRACE_EVENT("PSI3/3bis needed"); #endif } if( psc_db->state_of_PSI[PSI4].state EQ NEEDED) { psi_reading_type = READ_PSI4; psi_reset_psi4(); dummy++; TRACE_EVENT("PSI 4 needed"); } if( psc_db->state_of_PSI[PSI5].state EQ NEEDED) { psi_reading_type = READ_PSI5; psi_reset_psi5(); dummy++; TRACE_EVENT("PSI 5 needed"); } #ifdef REL99 if( psc_db->state_of_PSI[PSI8].state EQ NEEDED) { psi_reading_type = READ_PSI8; psi_reset_psi8(); dummy++; TRACE_EVENT("PSI 8 needed"); } #endif if(dummy > 1) psi_reading_type = PSI_IN_HR_AND_LR; psi_receive_psi(psi_reading_type); } /* psi_partial_acq() */ /* +------------------------------------------------------------------------------ | Function : psi_init_states_of_psi +------------------------------------------------------------------------------ | Description : The function psi_init_states_of_psi() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_init_states_of_psi ( void ) { psc_db->state_of_PSI[PSI1].state = NEEDED; psc_db->state_of_PSI[PSI2].state = NEEDED; psc_db->state_of_PSI[PSI3].state = NEEDED; psc_db->state_of_PSI[PSI3bis].state = NEEDED; #if defined (REL99) AND defined (TI_PS_FF_EMR) psc_db->state_of_PSI[PSI3ter].state = NEEDED; #endif psc_db->state_of_PSI[PSI4].state = NEEDED; psc_db->state_of_PSI[PSI5].state = NEEDED; #ifdef REL99 psc_db->state_of_PSI[PSI8].state = NEEDED; #endif psc_db->state_of_PSI[PSI13].state = NEEDED; }/* psi_init_states_of_psi() */ /* +------------------------------------------------------------------------------ | Function : psi_init_rfl_psi2 +------------------------------------------------------------------------------ | Description : The function psi_init_rfl_psi2() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_init_rfl_psi2(void) { UBYTE n; /* * please note that only the RFL_NUMBERs defined * in the PSI2 will be marked as invalid */ for (n = 0; n < MAX_RFL; n++) { psc_db->rfl[n].num = NOT_SET; } }/* psi_init_rfl_psi2() */ /* +------------------------------------------------------------------------------ | Function : psi_init_cell_alloc +------------------------------------------------------------------------------ | Description : The function psi_init_cell_alloc() .... | | Parameters : void | +------------------------------------------------------------------------------ */ LOCAL void psi_init_cell_alloc(void) { UBYTE n; /*TRACE_EVENT("psi_init_cell_alloc");*/ psc_db->v_cell_alloc = FALSE; for (n = 0; n < MAX_CELL_ALLOC; n++) psc_db->cell_alloc[n].rfl_num = NOT_SET; }/* psi_init_cell_alloc() */ /* +------------------------------------------------------------------------------ | Function : psi_init_gprs_ms_alloc +------------------------------------------------------------------------------ | Description : The function psi_init_gprs_ms_alloc() .... | | Parameters : BOOL psi2_only | +------------------------------------------------------------------------------ */ LOCAL void psi_init_gprs_ms_alloc(BOOL psi2_only) { UBYTE n; if(psi2_only) { TRACE_EVENT("remove only PSI2 entries in GPRS_MA"); } else { TRACE_EVENT("remove all entries in GPRS_MA"); } for (n = 0; n < MAX_GPRS_MS_ALLOC; n++) { if(psi2_only) { if( (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num NEQ MA_NUMBER_4_PSI13_OR_CELL_ALLOC ) AND /* ignore MA_NUMBER with 14 or 15: 0..13 in PSI2*/ (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num NEQ MA_NUMBER_4_ASSIGNMENT ) ) { psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num = NOT_SET; } } else { psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num = NOT_SET; } } /* * When deleting the MA defined in the assignment message, * the corresponding RFL list should be deleted, too. */ psc_db->gprs_ms_alloc_in_assignment.ma_num = NOT_SET; psc_db->rfl[MAX_RFL].num = NOT_SET; }/* psi_init_gprs_ms_alloc() */ /* +------------------------------------------------------------------------------ | Function : psi_init +------------------------------------------------------------------------------ | Description : The function psi_init() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_init ( void ) { TRACE_FUNCTION( "psi_init" ); psi_init_params(); psi_reset_psi_pos( ); INIT_STATE(PSI, PSI_NULL); } /* psi_init() */ /* +------------------------------------------------------------------------------ | Function : psi_complete_acq +------------------------------------------------------------------------------ | Description : The function psi_complete_acq() .... | | Parameters : UBYTE acq_type: COMPLETE (in serving cell) or FULL_PSI_IN_NEW_CELL | +------------------------------------------------------------------------------ */ GLOBAL void psi_complete_acq ( ACQ_TYPE acq_type ) { TRACE_FUNCTION( "psi_complete_acq" ); /* * Start timer for 10 sec. */ vsi_t_start(GRR_handle,T_COMP_PSI, T_10_SEC_VALUE); psi_receive_psi(READ_COMPLETE); psi_reset_all(); psc_db->acq_type = acq_type; psc_db->state_of_PSI[PSI13].state = RECEIPT_OK; /* we do not need to read PSI13 again*/ } /* psi_complete_acq() */ /* +------------------------------------------------------------------------------ | Function : psi_send_psi_status +------------------------------------------------------------------------------ | Description : The function psi_send_psi_status() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_send_psi_status (void ) { TRACE_FUNCTION( "psi_send_psi_status" ); /* SZML-PSI/003 */ } /* psi_send_psi_status() */ /* +------------------------------------------------------------------------------ | Function : psi_stop_30sec +------------------------------------------------------------------------------ | Description : The function psi_stop_30sec() .... | | Parameters : BOOL start_again: whether the timer should be started again or not | +------------------------------------------------------------------------------ */ GLOBAL void psi_stop_30sec (BOOL start_again ) { TRACE_FUNCTION( "psi_stop_30sec" ); vsi_t_stop(GRR_handle,T_30_SEC); if(start_again) { /* TRACE_EVENT("30 sec. running"); */ vsi_t_start(GRR_handle,T_30_SEC, T_30_SEC_VALUE); } else { TRACE_EVENT("30 sec. stopped"); } } /* psi_stop_30sec() */ /* +------------------------------------------------------------------------------ | Function : psi_start_30sec +------------------------------------------------------------------------------ | Description : The function psi_start_30sec() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_start_30sec (void ) { TRACE_FUNCTION( "psi_start_30sec" ); /* TRACE_EVENT("30 sec. running"); */ vsi_t_start(GRR_handle,T_30_SEC, T_30_SEC_VALUE); } /* psi_start_30sec() */ /* +------------------------------------------------------------------------------ | Function : psi_start_60sec +------------------------------------------------------------------------------ | Description : The function psi_start_60sec() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_start_60sec ( void ) { TRACE_FUNCTION( "psi_start_60sec" ); /* TRACE_EVENT("60 sec. running"); */ vsi_t_start(GRR_handle,T_60_SEC, T_60_SEC_VALUE); } /* psi_start_60sec() */ /* +------------------------------------------------------------------------------ | Function : psi_stop_60sec +------------------------------------------------------------------------------ | Description : The function psi_stop_60sec () .... | | Parameters : BOOL start_again | +------------------------------------------------------------------------------ */ GLOBAL void psi_stop_60sec ( BOOL start_again ) { TRACE_FUNCTION( "psi_stop_60sec " ); vsi_t_stop(GRR_handle,T_60_SEC); if(start_again) { /* TRACE_EVENT("60 sec. running"); */ vsi_t_start(GRR_handle,T_60_SEC, T_60_SEC_VALUE); } else { TRACE_EVENT("60 sec. stopped"); } } /* psi_stop_60sec () */ /* +------------------------------------------------------------------------------ | Function : psi_copy_ma_from_psi13 +------------------------------------------------------------------------------ | Description : The function psi_copy_ma_from_psi13() .... | | Parameters : T_gprs_ms_alloc* ms_alloc: pointer to T_gprs_ms_alloc | +------------------------------------------------------------------------------ */ LOCAL void psi_copy_ma_from_psi13(T_gprs_ms_alloc_ie* ms_alloc) { UBYTE n; MCAST(si13,D_SYS_INFO_13); /* T_D_SYS_INFO_13 */ TRACE_FUNCTION( "psi_copy_ma_from_psi13 " ); if(D_SYS_INFO_13 NEQ si13->msg_type) { /* PSI13 was received */ for(n = 0; n < MAX_GPRS_MS_ALLOC; n++) { if( (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num EQ MA_NUMBER_4_PSI13_OR_CELL_ALLOC) || (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num EQ NOT_SET) ) { psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num = MA_NUMBER_4_PSI13_OR_CELL_ALLOC; memcpy(&(psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie), ms_alloc, sizeof(T_gprs_ms_alloc_ie)); n = MAX_GPRS_MS_ALLOC; /* break for loop*/ } } } else { /* SI13 was received */ UBYTE i; T_gprs_ma *gprs_ma = (T_gprs_ma*)ms_alloc; for(n = 0; n < MAX_GPRS_MS_ALLOC; n++) { if( (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num EQ MA_NUMBER_4_PSI13_OR_CELL_ALLOC) || (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num EQ NOT_SET) ) { memset(&(psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie), 0, sizeof(T_gprs_ms_alloc_ie)); psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num = MA_NUMBER_4_PSI13_OR_CELL_ALLOC; psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.hsn = gprs_ma->hsn; if(gprs_ma->v_rfln) { psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.v_rfl_num_list = TRUE; psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.c_rfl_num_list = gprs_ma->c_rfln; for(i = 0;i < gprs_ma->c_rfln;i++) { psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.rfl_num_list[i].rfl_num = gprs_ma->rfln[i]; } } psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.flag = gprs_ma->hop; if(gprs_ma->hop) { if(gprs_ma->v_arfcn_idx) { psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.v_arfcn_index_list = TRUE; psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.c_arfcn_index_list = gprs_ma->c_arfcn_idx; for(i = 0;i < gprs_ma->c_arfcn_idx;i++) { psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.arfcn_index_list[i].arfcn_index = gprs_ma->arfcn_idx[i]; } } } else { psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.v_ma_struct = TRUE; psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.ma_struct.ma_len = gprs_ma->allo_len6; psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.ma_struct.c_ma_map = gprs_ma->c_allo_bmp6; for(i = 0;i < gprs_ma->c_allo_bmp6;i++) { psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie.ma_struct.ma_map[i] = gprs_ma->allo_bmp6[i]; } } break; } } } }/*psi_copy_ma_from_psi13*/ /* +------------------------------------------------------------------------------ | Function : psi_process_si13() +------------------------------------------------------------------------------ | Description : The function psi_process_si13().... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL T_SI13_RET psi_process_si13( T_D_SYS_INFO_13 *si13) { BOOL pbcch_was_present; T_SI13_RET ret_value = SI13_OK; #ifdef REL99 UBYTE current_nw_rel = psc_db->network_rel; #endif TRACE_FUNCTION( "psi_process_si13" ); if(!si13->si13_rest_oct.v_si13_info) { TRACE_ERROR( "No restoctects present in SI13: reread si13" ); ret_value = SI13_REREAD; } else { #ifdef REL99 /* Update the BSS release when the 1st SI13 message is received in case of * PBCCH's PRESENCE. * The correct BSS release will be updated after receiving PSIs */ if(si13->si13_rest_oct.si13_info.flag1) { /* PBCCH is present in the cell */ /* This is the 1st SI13 message */ if(psc_db->psi13_params.bcch_change_mark EQ NOT_SET) { /* Update the BSS and the SGSN releases */ psi_update_bss_sgsn_rel(si13, PBCCH_PRESENT); } } else { /* Update the BSS and SGSN releases every time the SI13 message is received * in case of PBCCH's ABSENCE. */ psi_update_bss_sgsn_rel(si13, PBCCH_NOT_PRESENT); if(psc_db->network_rel NEQ current_nw_rel) { TRACE_EVENT_P2("((SI13)BSS Network release changed from %d to %d <0 - REL_97, 1 - REL_99, 2 - REL_04>", current_nw_rel, psc_db->network_rel); } } #endif pbcch_was_present = grr_is_pbcch_present(); /* * Copy PBCCH or non PBCCH desc. and change field */ if( !pbcch_was_present AND si13->si13_rest_oct.si13_info.v_pbcch_des ) { /* No PBCCH description was present in the GPRS_DATA_BASE or PBCCH was released: * SI13 message contains PBCCH description, so we have to start a complete acq of * PSI messages. */ if(psc_db->psi13_params.bcch_change_mark EQ NOT_SET) { psi_copy_si13_params(si13); } psc_db->psi13_params.bcch_change_mark = si13->si13_rest_oct.si13_info.bcch_cm; ret_value = SI13_COMPLETE_PSI; } else { psi_copy_si13_params(si13); /* * There is no PBCCH description present in the SI13 message and there can be * no PBCCH description in the GPRS_DATA_BASE */ if(psc_db->psi13_params.bcch_change_mark NEQ NOT_SET) { /* * This is not the first SI13 message. * Check BCCH_CHANGE_MARK */ { UBYTE incremented_value = psi_compare_change_mark ( si13->si13_rest_oct.si13_info.bcch_cm, psc_db->psi13_params.bcch_change_mark ); if(incremented_value EQ 1) /*partial acq*/ { if(psi_is_update_needed(si13->si13_rest_oct.si13_info.si_cf)) { ret_value = SI13_PARTIAL_SI; } } else if(incremented_value > 1) /* incremented_value > 1: complete acq*/ { ret_value = SI13_COMPLETE_SI; } } } psc_db->psi13_params.bcch_change_mark = si13->si13_rest_oct.si13_info.bcch_cm; } } psc_db->state_of_PSI[PSI13].state = RECEIPT_OK; grr_set_pg_nmo(); TRACE_EVENT_P1("SI13 processed: %d", ret_value); return ret_value; } /* psi_process_si13() */ /* +------------------------------------------------------------------------------ | Function : psi_process_psi13 +------------------------------------------------------------------------------ | Description : The function psi_process_psi13() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL T_PSI13_RET psi_process_psi13 ( T_PSI_13 * psi13 ) { T_PSI13_RET ret_val = PSI13_OK; TRACE_FUNCTION( "psi_process_psi13" ); if(grr_is_pbcch_present()) { /* * PBCCH description already exists: we have to compare PBCCH parameters */ if(psi_is_pbcch_des_different(psi13)) { /* * PBCCH no longer available * or PBCCH description is differnt from the saved one in the MS */ if(psi13->flag) { ret_val = PSI13_COMPLETE_PSI; } else { ret_val = PSI13_PBCCH_RELEASED; } } else { /* * PBCCH description is the same * Copy at least SI13_CHANGE_MARK and GPRS Mobile Allocation */ psi_copy_psi13_params(psi13); #ifdef REL99 /* PSI13 message has been received when PBCCH is present. * CBCH information may have to be updated if hopping is * allowed. */ if(psc_db->v_cbch_chan_desc AND !psc_db->cbch_chan_desc.freq_par.v_arfcn) { sig_psi_ctrl_cbch_info_ind(); } #endif /* * Check BCCH_CHANGE_MARK */ { UBYTE incremented_value = psi_compare_change_mark(psi13->bcch_change_ma, psc_db->psi13_params.bcch_change_mark); psc_db->psi13_params.bcch_change_mark = psi13->bcch_change_ma; if(incremented_value EQ 1) /*partial acq*/ { if(psi_is_update_needed(psi13->si_change_ma)) { ret_val = PSI13_PARTIAL_SI; } } else if(incremented_value > 1) /* incremented_value > 1: complete acq*/ { ret_val = PSI13_COMPLETE_SI; } } } } else { /* * No PBCCH description present in the GPRS_DATA_BASE: * and we received a PSI13 in BCCH_TRANSFER state * So we have to check whether this message contains a * PBCCH description or not. If YES, complete acq. of PSI * messages should be started. If NO, BCCH_CHANGE_MARK should be compared */ if(psi13->flag) { ret_val = PSI13_PBCCH_ESTABLISHED; } else { /* * Copy PBCCH or non PBCCH desc. and change field */ psi_copy_psi13_params(psi13); { UBYTE incremented_value = psi_compare_change_mark(psi13->bcch_change_ma, psc_db->psi13_params.bcch_change_mark); psc_db->psi13_params.bcch_change_mark = psi13->bcch_change_ma; if(incremented_value EQ 1) /*partial acq*/ { if(psi_is_update_needed(psi13->si_change_ma)) { ret_val = PSI13_PARTIAL_SI; } } else if(incremented_value > 1) /* incremented_value > 1: complete acq*/ { ret_val = PSI13_COMPLETE_SI; } } } } #ifdef REL99 /* Update the SGSN release */ if (psi13->v_release_99_str_psi_13) { psc_db->sgsn_rel = psi13->release_99_str_psi_13.sgsnr ? PS_SGSN_99_ONWARDS : PS_SGSN_98_OLDER; /* Update the SGSN release in the Common library context */ cl_nwrl_set_sgsn_release(psc_db->sgsn_rel); } #endif psc_db->state_of_PSI[PSI13].state = RECEIPT_OK; grr_set_pg_nmo(); return ret_val; } /* psi_process_psi13() */ /* +------------------------------------------------------------------------------ | Function : psi_process_psi5 +------------------------------------------------------------------------------ | Description : The function psi_process_psi5() .... | | Parameters : T_PSI_5 *psi5 | +------------------------------------------------------------------------------ */ GLOBAL T_PSI5_RET psi_process_psi5 (T_PSI_5 *psi5 ) { BOOL is_psi5_ok; UBYTE n; BOOL cpy_prm_set; TRACE_FUNCTION( "psi_process_psi5" ); /* * Check consistency */ if(psc_db->psi5_params.psi5_change_mark EQ NOT_SET) { /* * Copy change mark etc. */ psc_db->psi5_params.psi5_change_mark = psi5->psi5_cm; psc_db->psi5_params.psi5_count = psi5->psi5_cnt; psc_db->psi5_params.instances[0] = psi5->psi5_cnt;/* number of instances */ } else { /* * There is a valid change mark present in the database * Check consistency of COUNT and INDEX */ if( (psc_db->psi5_params.psi5_count NEQ psi5->psi5_cnt) OR (psc_db->psi5_params.psi5_count < psi5->psi5_ind) OR (psc_db->psi5_params.psi5_change_mark NEQ psi5->psi5_cm) ) { /* * Error situation read a new PSI5 * The PSI5 change mark field is changed each time information has been updated * A new value indicates that the mobile * station shall re-read the information from the PSI5 */ TRACE_ERROR( "PSI5: inconsistent parameter" ); psc_db->is_ext_psi5_valid = FALSE; return PSI5_REREAD; } /* psi5_change_markhas not changed, i.e. * PSI5 message has not changed, we already have a consistent set, so we * do not have to read the PSI5 message */ if((psc_db->psi5_params.psi5_change_mark EQ psi5->psi5_cm) && (psc_db->state_of_PSI[PSI5].state EQ RECEIPT_OK)) { /* Message has not changed, we already have a consistent set, so we * do not have to read it */ TRACE_EVENT( "PSI5: message has not changed" ); return PSI5_OK; } } psc_db->psi5_params.psi5_index = psi5->psi5_ind; if( psc_db->psi5_params.instances[psi5->psi5_ind + 1] EQ FALSE ) { if( grr_data->nc2_on ) { if( psi5->v_nc_meas_par AND ( psc_db->nc_cw.param.idx EQ NOT_SET OR psc_db->nc_cw.param.idx < psi5->psi5_ind ) ) { /* * This is the first time that we want to save network controlled * measurement parameters or the last index for NC parameters were * not bigger than the currently received one. * * Maybe more than one instance of PSI5, store data in temporary location. */ grr_data->psi.v_nc_param = TRUE; grr_prcs_nc_param_struct ( &grr_data->psi.nc_param, &psi5->nc_meas_par, psi5->psi5_ind ); } if( psi5->v_xmeas_par ) { cpy_prm_set = ( psc_db->ext_psi5.idx EQ NOT_SET OR psc_db->ext_psi5.idx < psi5->psi5_ind ); grr_prcs_xmeas_struct ( &psc_db->ext_psi5, &psi5->xmeas_par, cpy_prm_set, psi5->psi5_ind, &psc_db->psi5_params.idx[psi5->psi5_ind].start, &psc_db->psi5_params.idx[psi5->psi5_ind].stop ); } #if defined (REL99) AND defined (TI_PS_FF_EMR) if(psi5->v_release_99_str_psi_5 AND psi5->release_99_str_psi_5.v_enh_rep_param_struct) { psc_db->psi5_params.v_enh_rep_param_struct = TRUE; grr_prcs_enh_param_cw_temp ( &grr_data->psi.enh_param, &psi5->release_99_str_psi_5.enh_rep_param_struct, psi5->psi5_ind ); } #endif } /* * check whether PSI5 has been received completely or not */ psc_db->psi5_params.instances[psi5->psi5_ind + 1] = TRUE; is_psi5_ok = TRUE; for(n = 0; n <= psc_db->psi5_params.instances[0]; n++ ) { if(!(psc_db->psi5_params.instances[n + 1])) { is_psi5_ok = FALSE;/* consistent set of PSI5 not complete */ break; } } TRACE_EVENT_P2( "PSI5: received with count = %d, index = %d ", psi5->psi5_cnt, psi5->psi5_ind); if(is_psi5_ok) { psc_db->state_of_PSI[PSI5].state = RECEIPT_OK; /* * the NC parameter are stored temporarily and * now transferred to final location */ if( grr_data->nc2_on ) { grr_prcs_nc_param_final ( &psc_db->nc_cw.param, &grr_data->psi.v_nc_param, &grr_data->psi.nc_param ); grr_sort_ext_lst_freq ( &psc_db->ext_psi5.em1.list, MAX_NR_OF_INSTANCES_OF_PSI5, &psc_db->psi5_params.idx[0] ); #if defined (REL99) AND defined (TI_PS_FF_EMR) if(rr_get_support_for_emr() AND psc_db->psi5_params.v_enh_rep_param_struct) { /* * the ENH parameter are stored temporarily and * now transferred to final location */ memcpy(&(psc_db->enh_cw), &(grr_data->psi.enh_param), sizeof(T_GRR_ENH_PARA)); } else { memset(&(psc_db->enh_cw), 0, sizeof(T_GRR_ENH_PARA)); psc_db->enh_cw.rept_type = REPORT_TYPE_REP; psc_db->psi5_params.v_enh_rep_param_struct = FALSE; } #endif /* * Inform MEAS that the Interference parameters are valid */ psc_db->is_ext_psi5_valid = TRUE; return PSI5_MEAS_PARAM_VALID; } } } else { TRACE_EVENT_P2( "PSI5: already received with count = %d, index = %d", psi5->psi5_cnt, psi5->psi5_ind ); } return PSI5_OK; } /* psi_process_psi5() */ /* +------------------------------------------------------------------------------ | Function : psi_process_psi4 +------------------------------------------------------------------------------ | Description : The function psi_process_psi4() .... | | Parameters : T_PSI_4 *psi4 | +------------------------------------------------------------------------------ */ GLOBAL T_PSI4_RET psi_process_psi4 (T_PSI_4 *psi4 ) { UBYTE i,m,n; BOOL is_psi4_ok; TRACE_FUNCTION( "psi_process_psi4" ); /* * Check consistency */ if(psc_db->psi4_params.psi4_change_mark EQ NOT_SET) { /* * Copy change mark etc. */ psc_db->psi4_params.psi4_change_mark = psi4->psi4_cm; psc_db->psi4_params.psi4_count = psi4->psi4_cnt; psc_db->psi4_params.instances[0] = psi4->psi4_cnt;/* number of instances */ } else { /* * There is a valid change mark present in the database * Check consistency of COUNT and INDEX */ if( (psc_db->psi4_params.psi4_count NEQ psi4->psi4_cnt) OR (psc_db->psi4_params.psi4_count < psi4->psi4_ind) OR (psc_db->psi4_params.psi4_change_mark NEQ psi4->psi4_cm) ) { /* * Error situation read a new PSI4 * The PSI4 change mark field is changed each time information has been updated * A new value indicates that the mobile * station shall re-read the information from the PSI4 */ TRACE_ERROR( "PSI4: inconsistent parameters" ); psc_db->number_of_valid_int_meas_channels = 0; return PSI4_REREAD; } /* psi4_change_markhas not changed, i.e. * PSI4 message has not changed, we already have a consistent set, so we * do not have to read the PSI4 message */ if((psc_db->psi4_params.psi4_change_mark EQ psi4->psi4_cm) && (psc_db->state_of_PSI[PSI4].state EQ RECEIPT_OK)) { /* Message has not changed, we already have a consistent set, so we * do not have to read it */ TRACE_EVENT( "PSI4: message has not changed" ); return PSI4_OK; } } psc_db->psi4_params.psi4_index = psi4->psi4_ind; if( psc_db->psi4_params.instances[psi4->psi4_ind + 1] EQ FALSE ) { /* * We assume that we receive PSI4 instances in the right order, * i.e. instance1, instance2, instance3, ..., instance8 * This is ETSI-Requirement 05.02 */ m = psc_db->number_of_valid_int_meas_channels; if(m < MAX_CHAN_IMEAS) { /* * copy first channel list in the current instance */ psc_db->int_meas_chan_list[m].v_arfcn = FALSE; psc_db->int_meas_chan_list[m].v_ma_num_maio = FALSE; if(psi4->chan_list_imeas.chan_group.v_arfcn) { psc_db->int_meas_chan_list[m].v_arfcn = TRUE; /* valid-flag for arfcn*/ psc_db->int_meas_chan_list[m].arfcn = psi4->chan_list_imeas.chan_group.arfcn; /* ARFCN*/ } else { psc_db->int_meas_chan_list[m].v_ma_num_maio = TRUE; psc_db->int_meas_chan_list[m].ma_num = psi4->chan_list_imeas.chan_group.ma_num_maio.ma_num; psc_db->int_meas_chan_list[m].maio = psi4->chan_list_imeas.chan_group.ma_num_maio.maio; } psc_db->int_meas_chan_list[m].ts_alloc = psi4->chan_list_imeas.chan_group.ts_alloc; m++; if(psi4->chan_list_imeas.v_chan_list2) { for(i=0; i < (psi4->chan_list_imeas.c_chan_list2) AND (m < MAX_CHAN_IMEAS); i++ ) { /* * copy remaining channel list in the current instance */ psc_db->int_meas_chan_list[m].v_arfcn = FALSE; psc_db->int_meas_chan_list[m].v_ma_num_maio = FALSE; if(psi4->chan_list_imeas.chan_list2[i].chan_group.v_arfcn) { psc_db->int_meas_chan_list[m].v_arfcn = TRUE; /* valid-flag for arfcn*/ psc_db->int_meas_chan_list[m].arfcn = psi4->chan_list_imeas.chan_list2[i].chan_group.arfcn; /* ARFCN*/ } else { psc_db->int_meas_chan_list[m].v_ma_num_maio = TRUE; psc_db->int_meas_chan_list[m].ma_num = psi4->chan_list_imeas.chan_list2[i].chan_group.ma_num_maio.ma_num; psc_db->int_meas_chan_list[m].maio = psi4->chan_list_imeas.chan_list2[i].chan_group.ma_num_maio.maio; } psc_db->int_meas_chan_list[m].ts_alloc = psi4->chan_list_imeas.chan_list2[i].chan_group.ts_alloc; m++; } } } else { TRACE_ERROR( "PSI4: list of INT meas. channels full" ); } psc_db->number_of_valid_int_meas_channels = m; /* * check whether PSI4 has been received completely or not */ psc_db->psi4_params.instances[psi4->psi4_ind + 1] = TRUE; is_psi4_ok = TRUE; for(n = 0; n <= psc_db->psi4_params.instances[0]; n++ ) { if(!(psc_db->psi4_params.instances[n + 1])) { is_psi4_ok = FALSE;/* consistent set of PSI4 not complete */ break; } } TRACE_EVENT_P2( "PSI4: received with count = %d, index = %d", psi4->psi4_cnt, psi4->psi4_ind ); if(is_psi4_ok) { psc_db->state_of_PSI[PSI4].state = RECEIPT_OK; return PSI4_INT_LIST_VALID; } } else { TRACE_EVENT_P2( "PSI4: already received with count = %d, index = %d", psi4->psi4_cnt, psi4->psi4_ind ); } return PSI4_OK; } /* psi_process_psi4() */ #if defined (REL99) AND defined (TI_PS_FF_EMR) /* +------------------------------------------------------------------------------ | Function : psi_process_psi3ter +------------------------------------------------------------------------------ | Description : The function psi_process_psi3ter() processes the IEs received | in PSI3 ter message | | Parameters : T_PSI_3_TER *psi3ter | +------------------------------------------------------------------------------ */ GLOBAL T_PSI3TER_RET psi_process_psi3ter (T_PSI_3_TER *psi3ter) { BOOL is_psi3ter_ok; #ifdef TI_PS_FF_RTD UBYTE n,rtd_index; #else UBYTE n; #endif /* #ifdef TI_PS_FF_RTD */ TRACE_FUNCTION( "psi_process_psi3ter" ); if(psc_db->psi3ter_params.psi3ter_change_mark EQ NOT_SET) { if( ( (psc_db->psi3_params.psi3_change_mark NEQ NOT_SET) AND (psi3ter->psi3_cm NEQ psc_db->psi3_params.psi3_change_mark) ) OR ( (psc_db->psi3bis_params.psi3bis_change_mark NEQ NOT_SET) AND (psi3ter->psi3_cm NEQ psc_db->psi3bis_params.psi3bis_change_mark) ) ) { /* * Error situation read new PSI3ter * The PSI3 change mark field is changed each time information has been updated * in any of the PSI3 to PSI3 ter messages. A new value indicates that the mobile * station shall re-read the information from the PSI3 to PSI3 ter messages. */ TRACE_ERROR( "PSI3ter: inconsistent change mark, read PSI3 to PSI3ter"); return PSI3TER_REREAD_PSI3_3BIS_3TER; } /* * Copy change mark etc. */ psc_db->psi3ter_params.psi3ter_change_mark = psi3ter->psi3_cm; psc_db->psi3ter_params.psi3ter_count = psi3ter->psi3ter_cnt; psc_db->psi3ter_params.instances[0] = psi3ter->psi3ter_cnt; /* number of instances */ } else /* * There is a valid change mark present in the database * Check consistency of COUNT and INDEX */ { if( (psc_db->psi3ter_params.psi3ter_change_mark NEQ psi3ter->psi3_cm) OR ( (psc_db->psi3_params.psi3_change_mark NEQ NOT_SET) AND (psc_db->psi3ter_params.psi3ter_change_mark NEQ psc_db->psi3_params.psi3_change_mark) ) OR ( (psc_db->psi3bis_params.psi3bis_change_mark NEQ NOT_SET) AND (psc_db->psi3ter_params.psi3ter_change_mark NEQ psc_db->psi3bis_params.psi3bis_change_mark) ) ) { /* * Error situation read new PSI3ter * The PSI3 change mark field is changed each time information has been updated * in any of the PSI3 to PSI3 ter messages. A new value indicates that the mobile * station shall re-read the information from the PSI3 to PSI3 ter messages. */ TRACE_ERROR( "PSI3ter: inconsistent change mark, read PSI3 to PSI3ter"); return PSI3TER_REREAD_PSI3_3BIS_3TER; } if( (psc_db->psi3ter_params.psi3ter_count NEQ psi3ter->psi3ter_cnt) OR (psc_db->psi3ter_params.psi3ter_count < psi3ter->psi3ter_ind) ) { TRACE_ERROR( "PSI3ter: inconsistent parameters, read PSI3ter"); return PSI3TER_REREAD_PSI3TER; } if((psc_db->psi3ter_params.psi3ter_change_mark EQ psi3ter->psi3_cm) AND (psc_db->state_of_PSI[PSI3ter].state EQ RECEIPT_OK)) { /* Message has not changed, we already have a consistent set, so we * do not have to read it */ TRACE_EVENT("PSI3ter: message has not changed"); return PSI3TER_OK; } } /* psi3ter_change_mark valid */ psc_db->psi3ter_params.psi3ter_index = psi3ter->psi3ter_ind; if( psc_db->psi3ter_params.instances[psi3ter->psi3ter_ind + 1] EQ FALSE ) { /* * Copy GPRS report priority parameters */ /* GPRS Report priority can be received in only one instance since start index is not given for mapping to BA as in RTD and BSIC mapping in SI */ if( (psi3ter->rtd_rep_prio_trnc_grp.v_gprs_rep_prio_cell_desc EQ TRUE) AND (psi3ter->rtd_rep_prio_trnc_grp.gprs_rep_prio_cell_desc.number_cells NEQ 0) ) { if(psi3ter->rtd_rep_prio_trnc_grp.gprs_rep_prio_cell_desc.number_cells > MAX_NR_OF_GSM_NC) { grr_data->psi.enh_param.gprs_rept_prio_desc.num_cells = MAX_NR_OF_GSM_NC; } else { grr_data->psi.enh_param.gprs_rept_prio_desc.num_cells = psi3ter->rtd_rep_prio_trnc_grp.gprs_rep_prio_cell_desc.number_cells; /* Set default report prio for the remaining cells upto max of 96 cells */ for(n = psi3ter->rtd_rep_prio_trnc_grp.gprs_rep_prio_cell_desc.number_cells; n < MAX_NR_OF_GSM_NC; n++) { grr_data->psi.enh_param.gprs_rept_prio_desc.rept_prio[n] = NORMAL_PRIO; } } for (n = 0; n < grr_data->psi.enh_param.gprs_rept_prio_desc.num_cells; n++) { grr_data->psi.enh_param.gprs_rept_prio_desc.rept_prio[n] = psi3ter->rtd_rep_prio_trnc_grp.gprs_rep_prio_cell_desc.rep_prio[n]; } } #ifdef TI_PS_FF_RTD /* Store the received RTD values into the temporary location */ if(psi3ter->rtd_rep_prio_trnc_grp.v_real_time_diff EQ TRUE) { if(psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.v_rtd_struct_6bit EQ TRUE) { if(psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_6bit.v_cell_index_start_rtd EQ TRUE) rtd_index = psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_6bit.cell_index_start_rtd; else rtd_index = RTD_DEFAULT_INDEX; if( rtd_index < MAX_NR_OF_NCELL ) { grr_data->psi.rtd[rtd_index] = psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_6bit.rtd6_struct.rtd_6bit; for(n=0;n<psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_6bit.c_rtd6_struct_opt_array AND rtd_index < MAX_NR_OF_NCELL - 1;n++) { rtd_index++; grr_data->psi.rtd[rtd_index] = psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_6bit.rtd6_struct_opt_array[n].rtd_6bit; } /*for*/ } /*if*/ } /*if*/ if(psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.v_rtd_struct_12bit EQ TRUE) { if(psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_12bit.v_cell_index_start_rtd EQ TRUE) rtd_index = psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_12bit.cell_index_start_rtd; else rtd_index = RTD_DEFAULT_INDEX; if( rtd_index < MAX_NR_OF_NCELL ) { grr_data->psi.rtd[rtd_index] = RTD_12BIT; grr_data->psi.rtd[rtd_index] |= psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_12bit.rtd12_struct.rtd_12bit; for(n=0;n<psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_12bit.c_rtd12_struct_opt_array AND rtd_index < MAX_NR_OF_NCELL - 1;n++) { rtd_index++; grr_data->psi.rtd[rtd_index] = RTD_12BIT; grr_data->psi.rtd[rtd_index] |= psi3ter->rtd_rep_prio_trnc_grp.real_time_diff.rtd_struct_12bit.rtd12_struct_opt_array[n].rtd_12bit; } /*for*/ }/*if*/ } /*if*/ } /*if*/ #endif /* #ifdef TI_PS_FF_RTD */ TRACE_EVENT_P2( "PSI3ter: received with count = %d, index = %d", psi3ter->psi3ter_cnt, psi3ter->psi3ter_ind ); /* * check whether PSI3TER has been received completely or not */ psc_db->psi3ter_params.instances[psi3ter->psi3ter_ind + 1] = TRUE; psc_db->psi3ter_params.prev_psi3ter_index = psc_db->psi3ter_params.psi3ter_index; is_psi3ter_ok = TRUE; for(n = 0; n <= psc_db->psi3ter_params.instances[0]; n++ ) { if(!(psc_db->psi3ter_params.instances[n + 1])) { is_psi3ter_ok = FALSE;/* consistent set of PSI3TER not complete */ break; } } if(is_psi3ter_ok) { psc_db->state_of_PSI[PSI3ter].state = RECEIPT_OK; /* Copy the GPRS priority information to permanent storage */ if(grr_data->psi.enh_param.gprs_rept_prio_desc.num_cells NEQ 0) { for(n = 0; n <= grr_data->psi.enh_param.gprs_rept_prio_desc.num_cells; n++) { psc_db->enh_cw.gprs_rept_prio_desc.rept_prio[n] = grr_data->psi.enh_param.gprs_rept_prio_desc.rept_prio[n]; } /* Initialize to 0 before receiving the next consistent set of PSI3 ter */ grr_data->psi.enh_param.gprs_rept_prio_desc.num_cells = 0; } else { /* Set report priority to NORMAL if not received */ for(n = 0; n < MAX_NR_OF_GSM_NC; n++) { psc_db->enh_cw.gprs_rept_prio_desc.rept_prio[n] = NORMAL_PRIO; } } #ifdef TI_PS_FF_RTD /* store the RTD values received in all instances of PSI3ter in permanent location */ memcpy(&psc_db->rtd,&grr_data->psi.rtd,MAX_NR_OF_NCELL*sizeof(T_RTD_VALUE)); /* reset the temporary storage to RTD value not available */ for( n = 0; n < MAX_NR_OF_NCELL; n++ ) grr_data->psi.rtd[n] = RTD_NOT_AVAILABLE; #endif /* #ifdef TI_PS_FF_RTD */ return PSI3TER_OK; } } else { TRACE_EVENT_P2( "PSI3ter: already received with count = %d, index = %d", psi3ter->psi3ter_cnt, psi3ter->psi3ter_ind ); } return PSI3TER_OK; } /* psi_process_psi3ter() */ #endif /* +------------------------------------------------------------------------------ | Function : psi_process_psi3bis +------------------------------------------------------------------------------ | Description : The function psi_process_psi3bis() .... | | Parameters : T_PSI_3_BIS *psi3bis | +------------------------------------------------------------------------------ */ GLOBAL T_PSI3BIS_RET psi_process_psi3bis (T_PSI_3_BIS *psi3bis) { BOOL is_psi3bis_ok; UBYTE n; TRACE_FUNCTION( "psi_process_psi3bis" ); /* * Each neighbour cell listed in PSI3 and in one or more instances * of PSI3bis is assigned an ascending index used for measurement reports. * The first neighbour cell in PSI3 has the lowest index (= 0), * and the last neighbour cell in the highest indexed PSI3bis message has * the highest index. The total number of neighbour cells in the BA-GPRS * shall not exceed 32. * If a mobile station receives more than 32 cells in the BA-GPRS, * only the 32 cells with the lowest indexes shall be considered. */ if(psc_db->psi3bis_params.psi3bis_change_mark EQ NOT_SET) { /* * Copy change mark etc. */ psc_db->psi3bis_params.psi3bis_change_mark = psi3bis->psi3_cm; psc_db->psi3bis_params.psi3bis_count = psi3bis->psi3bis_cnt; psc_db->psi3bis_params.instances[0] = psi3bis->psi3bis_cnt; /* number of instances */ } else { /* * There is a valid change mark present in the database * Check consistency of COUNT and INDEX */ if( (psc_db->psi3bis_params.psi3bis_count NEQ psi3bis->psi3bis_cnt) OR (psc_db->psi3bis_params.psi3bis_count < psi3bis->psi3bis_ind) OR (psc_db->psi3bis_params.psi3bis_change_mark NEQ psi3bis->psi3_cm) ) { /* * Error situation read a new PSI3bis * The PSI3 change mark field is changed each time information has been updated * in any of the PSI3 or PSI3 bis messages. A new value indicates that the mobile * station shall re-read the information from the PSI3 and all PSI3 bis messages. */ #if defined (REL99) AND defined (TI_PS_FF_EMR) TRACE_ERROR( "PSI3bis: inconsistent parameters, read PSI3 PSI3bis and PSI3ter"); return PSI3BIS_REREAD_PSI3_3BIS_3TER; #else TRACE_ERROR( "PSI3bis: inconsistent parameters, read PSI3 and PSI3bis"); return PSI3BIS_REREAD_PSI3_3BIS; #endif } if((psc_db->psi3bis_params.psi3bis_change_mark EQ psi3bis->psi3_cm) && (psc_db->state_of_PSI[PSI3bis].state EQ RECEIPT_OK)) { /* Message has not changed, we already have a consistent set, so we * do not have to read it */ TRACE_EVENT("PSI3bis: message has not changed"); return PSI3BIS_OK; } else if(psc_db->psi3bis_params.psi3bis_change_mark NEQ psi3bis->psi3_cm) { TRACE_ERROR("PSI3bis: message has changed"); return PSI3BIS_REREAD_PSI3BIS; } } /* psi3bis_change_mark valid */ psc_db->psi3bis_params.psi3bis_index = psi3bis->psi3bis_ind; if( psc_db->psi3bis_params.instances[psi3bis->psi3bis_ind + 1] EQ FALSE ) { UBYTE number; /* * Copy NCELL parameters */ number = psi_store_ncell_param( &psi3bis->ncell_par_trnc_grp.ncell_par[0], psi3bis->ncell_par_trnc_grp.c_ncell_par, psi3bis->ncell_par_trnc_grp.v_ncell_par, INFO_TYPE_PSI3BIS, psi3bis->psi3bis_ind ); /* * Copy NCELL parameters 2 */ psi_store_ncell_param2( psi3bis, number ); TRACE_EVENT_P2( "PSI3bis: received with count = %d, index = %d", psi3bis->psi3bis_cnt, psi3bis->psi3bis_ind ); /* * check whether PSI3BIS has been received completely or not */ psc_db->psi3bis_params.instances[psi3bis->psi3bis_ind + 1] = TRUE; is_psi3bis_ok = TRUE; for(n = 0; n <= psc_db->psi3bis_params.instances[0]; n++ ) { if(!(psc_db->psi3bis_params.instances[n + 1])) { is_psi3bis_ok = FALSE;/* consistent set of PSI3BIS not complete */ break; } } if(is_psi3bis_ok) { psc_db->state_of_PSI[PSI3bis].state = RECEIPT_OK; if( psc_db->state_of_PSI[PSI3].state EQ RECEIPT_OK ) { psi_restore_ncell_param( ); return PSI3BIS_NCELL_VALID; } else { return PSI3BIS_OK; } } } else { TRACE_EVENT_P2( "PSI3bis: already received with count = %d, index = %d", psi3bis->psi3bis_cnt, psi3bis->psi3bis_ind ); } return PSI3BIS_OK; } /* psi_process_psi3bis() */ /* +------------------------------------------------------------------------------ | Function : psi_process_psi3 +------------------------------------------------------------------------------ | Description : The function psi_process_psi3() .... | | Parameters : T_PSI_3 *psi3 | +------------------------------------------------------------------------------ */ GLOBAL T_PSI3_RET psi_process_psi3 (T_PSI_3 *psi3 ) { T_PSI3_RET return_val = PSI3_OK; TRACE_FUNCTION( "psi_process_psi3" ); /* * Check whether the cell has been barred or not. If YES, inform CTRL */ if(psi3->scell_par.cell_ba) { /*Barred*/ TRACE_EVENT( "PSI3: cell barred" ); GRR_EM_SET_CELL_BARRED; return PSI3_CELL_BARRED; } psc_db->state_of_PSI[PSI3].state = RECEIPT_OK; if(psc_db->psi3_params.psi3_change_mark NEQ NOT_SET) { /* compare change mark*/ if(psc_db->psi3_params.psi3_change_mark EQ psi3->psi3_cm) { /* * Information of the PSI3 PSI3ter messages have NOT been updated: return!! */ TRACE_EVENT( "PSI3: messages PSI3 and PSI3bis have not changed" ); return PSI3_OK; } /* * Information of the PSI3 message has been updated, so we have to re-read the parameters * * A new value indicates that the mobile station shall re-read the information from * the PSI3 - PSI3ter messages. */ /* * Set the change mark parameter of psi3bis to NOT_SET. This causes that the PSI3BIS and * PSI3 ter instances to be read again */ psc_db->psi3bis_params.psi3bis_change_mark = NOT_SET; psc_db->state_of_PSI[PSI3bis].state = NEEDED; #if defined (REL99) AND defined (TI_PS_FF_EMR) psc_db->psi3ter_params.psi3ter_change_mark = NOT_SET; if(psc_db->v_add_psi AND psc_db->add_psi.psi3ter_broadcast) { psc_db->state_of_PSI[PSI3ter].state = NEEDED; } else { psc_db->state_of_PSI[PSI3ter].state = NOT_SEND; } #endif /* * Set the consistent set parameters to FALSE */ psi_reset_psi3bis(); #if defined (REL99) AND defined (TI_PS_FF_EMR) psi_reset_psi3ter(); #endif /* This field is coded as the binary representation of the PSI3 bis index * (in the PSI3 bis message) for the last (highest indexed) individual PSI3 * bis message.Range: 0-15. */ psc_db->psi3_params.psi3_bis_count = psi3->psi3bis_cnt; /* * Ncell parameter are invalid. We have to inform MEAS-Service */ return_val = PSI3_NCELL_INVALID; } else { /* This is the first time that we have received a PSI3 message*/ psc_db->psi3_params.psi3_change_mark = psi3->psi3_cm; psc_db->psi3_params.psi3_bis_count = psi3->psi3bis_cnt; } /* copy Serving Cell parameters */ psc_db->scell_par.cell_ba = psi3->scell_par.cell_ba; psc_db->scell_par.exc_acc = psi3->scell_par.exc_acc; psc_db->scell_par.cr_par_1.cr_pow_par.gprs_rxlev_access_min = psi3->scell_par.gprs_rxlev_access_min; psc_db->scell_par.cr_par_1.cr_pow_par.gprs_ms_txpwr_max_cch = psi3->scell_par.txpwr_max_cch; grr_data->meas.pwr_offset = 0; psc_db->scell_par.cr_par_1.v_hcs_par = psi3->scell_par.v_hcs_par; psc_db->scell_par.cr_par_1.hcs_par = psi3->scell_par.hcs_par; psc_db->scell_par.multi_band_rep = psi3->scell_par.multi_band_rep; /*copy General Cell Selection parameter */ memcpy(&(psc_db->gen_cell_par), &(psi3->gen_cell_par),sizeof(T_gen_cell_par)); /* process default values for General Cell Selection parameter */ if( psc_db->gen_cell_par.v_t_resel EQ FALSE ) { psc_db->gen_cell_par.v_t_resel = TRUE; psc_db->gen_cell_par.t_resel = GRR_T_RESEL_DEFAULT; } if( psc_db->gen_cell_par.v_ra_re_hyst EQ FALSE ) { psc_db->gen_cell_par.v_ra_re_hyst = TRUE; psc_db->gen_cell_par.ra_re_hyst = psc_db->gen_cell_par.gprs_c_hyst; } /* copy Neighbor cell parameters*/ psi_store_ncell_param( &psi3->ncell_par[0], psi3->c_ncell_par, psi3->v_ncell_par, INFO_TYPE_PSI3, 0 ); if( psc_db->state_of_PSI[PSI3].state EQ RECEIPT_OK AND psc_db->state_of_PSI[PSI3bis].state EQ RECEIPT_OK ) { psi_restore_ncell_param( ); return_val = PSI3_NCELL_VALID; } TRACE_EVENT_P1( "PSI3: received with return value %d", return_val ); grr_data->pwr_ctrl_valid_flags.v_glbl_pwr_ctrl_param = TRUE; return return_val; } /* psi_process_psi3() */ /* +------------------------------------------------------------------------------ | Function : psi_copy_rfl +------------------------------------------------------------------------------ | Description : The function psi_copy_rfl() .... copy Reference Frequency List (RFL) | | Parameters : T_PSI_2 *psi2: pointer to PSI2 message | +------------------------------------------------------------------------------ */ LOCAL void psi_copy_rfl(T_PSI_2 *psi2) { UBYTE m, n; TRACE_FUNCTION( "psi_copy_rfl" ); for(m = 0; m < psi2->psi_2_trnc_grp.c_rfl; m++) { for(n = 0; n < MAX_RFL; n++) { if( (psi2->psi_2_trnc_grp.rfl[m].rfl_num EQ psc_db->rfl[n].num) OR (psc_db->rfl[n].num EQ NOT_SET) ) { psc_db->rfl[n].num = psi2->psi_2_trnc_grp.rfl[m].rfl_num; /* * This function copies the frequencies into list. This function takes the arranging * of ARFCN into account cf. 12.10a GPRS Mobile Allocation in 04.60 */ grr_create_channel_list (&psi2->psi_2_trnc_grp.rfl[m], psc_db->rfl[n].list); /* * Exit from the for loop */ n = MAX_RFL; } } } }/* psi_copy_rfl*/ /* +------------------------------------------------------------------------------ | Function : psi_copy_ma_from_psi2 +------------------------------------------------------------------------------ | Description : The function psi_copy_ma_from_psi2() .... copy GPRS Mobile Allocation (MA) | | Parameters : T_PSI_2 *psi2: pointer to PSI2 message | +------------------------------------------------------------------------------ */ LOCAL void psi_copy_ma_from_psi2(T_PSI_2 *psi2) { UBYTE m, n, copiedElements = 0; TRACE_FUNCTION( "psi_copy_ma_from_psi2" ); for(m = 0; m < psi2->psi_2_trnc_grp.c_gprs_ms_alloc; m++) { if((psi2->psi_2_trnc_grp.gprs_ms_alloc[m].ma_num != MA_NUMBER_4_PSI13_OR_CELL_ALLOC ) && /* ignore MA_NUMBER with 14 or 15: 0..13 in PSI2*/ (psi2->psi_2_trnc_grp.gprs_ms_alloc[m].ma_num != MA_NUMBER_4_ASSIGNMENT )) { for(n = 0; n < MAX_GPRS_MS_ALLOC; n++) { if( (psi2->psi_2_trnc_grp.gprs_ms_alloc[m].ma_num EQ psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num) || (psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num EQ NOT_SET) ) { psc_db->gprs_ms_alloc_in_psi2_psi13[n].ma_num = psi2->psi_2_trnc_grp.gprs_ms_alloc[m].ma_num; memcpy(&(psc_db->gprs_ms_alloc_in_psi2_psi13[n].gprs_ms_alloc_ie), &(psi2->psi_2_trnc_grp.gprs_ms_alloc[m].gprs_ms_alloc_ie), sizeof(T_gprs_ms_alloc_ie)); n = MAX_GPRS_MS_ALLOC; /* to break the for loop*/ copiedElements++; /* for debug*/ } } } } if(copiedElements < psi2->psi_2_trnc_grp.c_gprs_ms_alloc) { TRACE_ERROR("copiedElements < psi2->c_gprs_ms_alloc in" ); } }/* psi_copy_ma_from_psi2*/ /* +------------------------------------------------------------------------------ | Function : psi_copy_ca +------------------------------------------------------------------------------ | Description : The function psi_copy_ca() .... copy Cell Allocation (CA) | | Parameters : T_PSI_2 *psi2: pointer to PSI2 message | +------------------------------------------------------------------------------ */ LOCAL void psi_copy_ca(T_PSI_2 *psi2) { UBYTE m,n; TRACE_FUNCTION( "psi_copy_ca" ); /*TRACE_EVENT("psi_copy_ca"); TRACE_EVENT_P1("c_ca: %d", psi2->c_cell_alloc); */ for(m = 0; m < psi2->psi_2_trnc_grp.c_cell_alloc; m++) { for(n = 0; n < MAX_CELL_ALLOC; n++) { if( (psi2->psi_2_trnc_grp.cell_alloc[m].rfl_num EQ psc_db->cell_alloc[n].rfl_num) || (psc_db->cell_alloc[n].rfl_num EQ NOT_SET) ) { psc_db->cell_alloc[n].rfl_num = psi2->psi_2_trnc_grp.cell_alloc[m].rfl_num; n = MAX_CELL_ALLOC; } } psc_db->v_cell_alloc = TRUE; } }/* psi_copy_ca*/ /* +------------------------------------------------------------------------------ | Function : psi_copy_pccch +------------------------------------------------------------------------------ | Description : The function psi_copy_pccch() .... copy PCCCH Description | | Parameters : T_PSI_2 *psi2: pointer to PSI2 message | +------------------------------------------------------------------------------ */ LOCAL void psi_copy_pccch(T_PSI_2 *psi2) { UBYTE m, n, i, ii, j; TRACE_FUNCTION( "psi_copy_pccch" ); m = 0; for(n = 0; n < psi2->psi_2_trnc_grp.c_pccch_des; n++) { if(psi2->psi_2_trnc_grp.pccch_des[n].v_nh_pccch_c AND (m < MAX_PCCCH_DES)) { /* * Non hopping parameters */ for(j = 0; j < psi2->psi_2_trnc_grp.pccch_des[n].c_nh_pccch_c; j++) { ii = 128; for(i = 0; i < 8; i++) { if( ((psi2->psi_2_trnc_grp.pccch_des[n].nh_pccch_c[j].ts_alloc & ii ) EQ ii) ) /* to get the timeslot number */ { psc_db->paging_group.pccch[m].is_static = TRUE; psc_db->paging_group.pccch[m].tsc = psi2->psi_2_trnc_grp.pccch_des[n].tsc; psc_db->paging_group.pccch[m].arfcn = psi2->psi_2_trnc_grp.pccch_des[n].nh_pccch_c[j].arfcn; psc_db->paging_group.pccch[m].tn = i;/* timeslot number*/ m++; if( m >= MAX_PCCCH_DES ) break; } ii = ii/2; } } } if(psi2->psi_2_trnc_grp.pccch_des[n].v_ma_h_s1 AND (m < MAX_PCCCH_DES)) { /* * Hopping parameters */ for(j = 0; j < psi2->psi_2_trnc_grp.pccch_des[n].ma_h_s1.c_h_pccch_c; j++) { ii = 128; for(i = 0; i < 8; i++) { if( ((psi2->psi_2_trnc_grp.pccch_des[n].ma_h_s1.h_pccch_c[j].ts_alloc & ii ) EQ ii) ) /* to get the timeslot number */ { psc_db->paging_group.pccch[m].is_static = FALSE; psc_db->paging_group.pccch[m].ma_num = psi2->psi_2_trnc_grp.pccch_des[n].ma_h_s1.ma_num; psc_db->paging_group.pccch[m].tsc = psi2->psi_2_trnc_grp.pccch_des[n].tsc; psc_db->paging_group.pccch[m].maio = psi2->psi_2_trnc_grp.pccch_des[n].ma_h_s1.h_pccch_c[j].maio; psc_db->paging_group.pccch[m].tn = i;/* timeslot number*/ m++; if( m >= MAX_PCCCH_DES ) break; } ii = ii/2; } } } psc_db->paging_group.kc = m; /*number of timeslots carrying PCCCH*/ } }/* psi_copy_pccch*/ /* +------------------------------------------------------------------------------ | Function : psi_copy_cell_id +------------------------------------------------------------------------------ | Description : The function psi_copy_cell_id() .... | | Parameters : T_PSI_2 *psi2: pointer to PSI2 message strcuture | +------------------------------------------------------------------------------ */ LOCAL void psi_copy_cell_id(T_PSI_2 *psi2) { TRACE_FUNCTION( "psi_copy_cell_id" ); psc_db->cell_info_for_gmm.cell_info.cell_env.rai.plmn.v_plmn = TRUE; if( psi2->psi_2_trnc_grp.cell_id.loc_area_ident.c_mnc EQ 2 ) { /* Internally G23 uses always 3-digit-MNC */ psi2->psi_2_trnc_grp.cell_id.loc_area_ident.c_mnc = SIZE_MNC; psi2->psi_2_trnc_grp.cell_id.loc_area_ident.mnc[2] = 0xf; } memcpy( psc_db->cell_info_for_gmm.cell_info.cell_env.rai.plmn.mcc, psi2->psi_2_trnc_grp.cell_id.loc_area_ident.mcc, SIZE_MCC ); memcpy( psc_db->cell_info_for_gmm.cell_info.cell_env.rai.plmn.mnc, psi2->psi_2_trnc_grp.cell_id.loc_area_ident.mnc, SIZE_MNC ); psc_db->cell_info_for_gmm.cell_info.cell_env.rai.lac = psi2->psi_2_trnc_grp.cell_id.loc_area_ident.lac; psc_db->cell_info_for_gmm.cell_info.cell_env.rai.rac = psi2->psi_2_trnc_grp.cell_id.rac; psc_db->cell_info_for_gmm.cell_info.cell_env.cid = psi2->psi_2_trnc_grp.cell_id.cell_id_ie; }/* psi_copy_cell_id*/ /* +------------------------------------------------------------------------------ | Function : psi_copy_non_gprs_opt +------------------------------------------------------------------------------ | Description : The function psi_copy_non_gprs_opt() .... | | Parameters : T_PSI_2 *psi2: pointer to PSI2 message strcuture | +------------------------------------------------------------------------------ */ LOCAL void psi_copy_non_gprs_opt(T_PSI_2 *psi2) { TRACE_FUNCTION( "psi_copy_non_gprs_opt" ); psc_db->v_non_gprs_opt = TRUE; /* copy parameters*/ memcpy(&(psc_db->non_gprs_opt), &(psi2->psi_2_trnc_grp.non_gprs_opt), sizeof(T_non_gprs_opt)); }/* psi_copy_non_gprs_opt*/ /* +------------------------------------------------------------------------------ | Function : psi_process_psi2 +------------------------------------------------------------------------------ | Description : The function psi_process_psi2() .... | | Parameters : T_PSI_2 *psi2 | +------------------------------------------------------------------------------ */ GLOBAL T_PSI2_RET psi_process_psi2 (T_PSI_2 *psi2 ) { UBYTE n=0; TRACE_FUNCTION( "psi_process_psi2" ); if(psc_db->psi2_params.psi2_change_mark EQ NOT_SET) { /* This is the first PSI2 message*/ psc_db->psi2_params.psi2_change_mark = psi2->psi2_cm; psc_db->psi2_params.psi2_count = psi2->psi2_cnt; psc_db->psi2_params.instances[0] = psi2->psi2_cnt;/* number of instances */ } else { /* Check consistency of COUNT and INDEX*/ if( (psc_db->psi2_params.psi2_count NEQ psi2->psi2_cnt) OR (psc_db->psi2_params.psi2_count < psi2->psi2_ind) OR (psc_db->psi2_params.psi2_change_mark NEQ psi2->psi2_cm) ) { /* Error situation read a new PSI2*/ TRACE_EVENT( "PSI2: inconsistent parameters" ); return PSI2_REREAD; } /* There was a valid psi2_change_mark: compare change_mark values*/ if((psc_db->psi2_params.psi2_change_mark EQ psi2->psi2_cm) AND (psc_db->state_of_PSI[PSI2].state EQ RECEIPT_OK)) { /* PSI2 message has not changed, we already have a consistent set, so we * do not have to read the PSI2 message */ TRACE_EVENT( "PSI2: message has not changed" ); return PSI2_OK; } } /* psi2_change_mark set */ if( psc_db->psi2_params.instances[psi2->psi2_ind + 1] EQ FALSE ) { psc_db->psi2_params.instances[psi2->psi2_ind + 1] = TRUE; /*check consistency */ psc_db->complete_acq.psi2_ok = TRUE; for(n = 0; n <= psc_db->psi2_params.instances[0]; n++ ) { if(!(psc_db->psi2_params.instances[n + 1])) { psc_db->complete_acq.psi2_ok = FALSE;/* consistent set of PSI2 not complete */ break; } } psc_db->state_of_PSI[PSI2].state = (psc_db->complete_acq.psi2_ok) ? RECEIPT_OK : NEEDED; if(psi2->psi_2_trnc_grp.v_cell_id) { /* copy cell identification*/ psi_copy_cell_id(psi2); } if(psi2->psi_2_trnc_grp.v_non_gprs_opt) { /* copy non GPRS cell options*/ psi_copy_non_gprs_opt(psi2); } /* * copy Reference Frequency List (RFL) */ psi_copy_rfl(psi2); /* * copy Cell Allocation (CA) */ psi_copy_ca(psi2); /* * copy GPRS Mobile Allocation (MA) */ psi_copy_ma_from_psi2(psi2); /* * copy PCCCH Description */ psi_copy_pccch(psi2); #ifdef REL99 if(psi2->psi_2_trnc_grp.v_release_99_str_psi_2 AND psi2->psi_2_trnc_grp.release_99_str_psi_2.v_add_psi) { psc_db->add_psi = psi2->psi_2_trnc_grp.release_99_str_psi_2.add_psi; psc_db->v_add_psi = TRUE; if(!psi2->psi_2_trnc_grp.release_99_str_psi_2.add_psi.Psi8_broadcast) { psc_db->state_of_PSI[PSI8].state = NOT_SEND; psc_db->v_cbch_chan_desc = FALSE; /* as this is r-99 network, and PBCCH is present * CBCH info should be sent to RR. As psi8 is * not present, it will deactivated. */ psc_db->send_cbch_info_ind = TRUE; } /* Process psi3ter broadcast indicator */ if(!psi2->psi_2_trnc_grp.release_99_str_psi_2.add_psi.psi3ter_broadcast) { psc_db->state_of_PSI[PSI3ter].state = NOT_SEND; } } if(psc_db->state_of_PSI[PSI2].state EQ RECEIPT_OK) { /* A consistent set of PSI2 has been received. */ /* Additional PSI Messages information element is within truncation notation. If it wasn't received at all, then we should assume 0, hence mark PSI3 ter and PSI 8 as "NOT_SEND" */ if(!psc_db->v_add_psi) { psc_db->state_of_PSI[PSI8].state = NOT_SEND; psc_db->v_cbch_chan_desc = FALSE; if(psc_db->network_rel) { /* as this is r-99 network, and PBCCH is present * CBCH info should be sent to RR. As psi8 is * not present, it will deactivated. */ psc_db->send_cbch_info_ind = TRUE; } psc_db->state_of_PSI[PSI3ter].state = NOT_SEND; } /* PSI2 has got updated. CBCH channel description * could depend of PSI2 in case hopping is allowed */ if(psc_db->v_cbch_chan_desc AND !psc_db->cbch_chan_desc.freq_par.v_arfcn) { psc_db->send_cbch_info_ind = TRUE; } } #endif TRACE_EVENT_P2( "PSI2: received with count = %d, index = %d", psi2->psi2_cnt, psi2->psi2_ind ); } else { TRACE_EVENT_P2( "PSI2: already received with count = %d, index = %d", psi2->psi2_cnt, psi2->psi2_ind ); } return PSI2_OK; } /* psi_process_psi2() */ #ifdef REL99 /* +------------------------------------------------------------------------------ | Function : psi_process_psi8 +------------------------------------------------------------------------------ | Description : This function stores the contents of PSI 8 for further | processing. | In R-99, PSI8 contains CBCH configuration. If PSI8 is not | broadcast or if none of the instances of PSI8 contain | CBCH information, then SMSCB is not active in the cell. | | CBCH is handled in ALR entity and is configured through RR entity. | This message contains CBCH channel description. If cbch | channel description indicates hopping, then to decode | frequency parameters to extract the frequencies for mobile allocation, | prior receipt of PSI 2(all instances) and | optionally SI13 messages is essential. | Hence PSI 8 frequency parameters is not decoded here. It is | stored in psc data blase and is decoded before giving | RRGRR_CBCH_INFO_IND to RR entity. RRGRR sap messages are | sent from service CTRL. | Parameters : T_PSI_4 *psi4 | +------------------------------------------------------------------------------ */ GLOBAL T_PSI8_RET psi_process_psi8 (T_PSI_8 *psi8 ) { UBYTE n; BOOL is_psi8_ok; TRACE_FUNCTION( "psi_process_psi8" ); /* * Check consistency */ if(psc_db->psi8_params.psi8_change_mark EQ NOT_SET) { /* * Copy change mark etc. */ psc_db->psi8_params.psi8_change_mark = psi8->psi8_cm; psc_db->psi8_params.psi8_count = psi8->psi8_cnt; psc_db->psi8_params.instances[0] = psi8->psi8_cnt;/* number of instances */ psc_db->v_cbch_chan_desc = FALSE; } else { /* * There is a valid change mark present in the database * Check consistency of COUNT and INDEX */ if( (psc_db->psi8_params.psi8_count NEQ psi8->psi8_cnt) OR (psc_db->psi8_params.psi8_count < psi8->psi8_ind) OR (psc_db->psi8_params.psi8_change_mark NEQ psi8->psi8_cm) ) { /* * Error situation; read a new PSI4 * The PSI4 change mark field is changed each time information has been updated * A new value indicates that the mobile * station shall re-read the information from the PSI4 */ TRACE_ERROR( "PSI8: inconsistent parameters" ); psc_db->v_cbch_chan_desc = FALSE; return PSI8_REREAD; } /* psi8_change_markh as not changed, i.e. * PSI8 message has not changed, we already have a consistent set, so we * do not have to read the PSI4 message */ if((psc_db->psi8_params.psi8_change_mark EQ psi8->psi8_cm) && (psc_db->state_of_PSI[PSI8].state EQ RECEIPT_OK)) { /* Message has not changed, we already have a consistent set, so we * do not have to read it */ TRACE_EVENT( "PSI8: message has not changed" ); return PSI8_OK; } } psc_db->psi8_params.psi8_index = psi8->psi8_ind; if( psc_db->psi8_params.instances[psi8->psi8_ind + 1] EQ FALSE ) { /* Store CBCH channel description. To decode Frequency Parameters, * it is necessary to receive all instances of PSI2 message. * Hence defer decoding of hopping frequency list till * end of acquisition. */ if(psi8->v_cbch_chan_desc) { memcpy(&(psc_db->cbch_chan_desc),&(psi8->cbch_chan_desc),sizeof(T_cbch_chan_desc)); psc_db->v_cbch_chan_desc = TRUE; } /* * check whether PSI8 has been received completely or not */ psc_db->psi8_params.instances[psi8->psi8_ind + 1] = TRUE; is_psi8_ok = TRUE; for(n = 0; n <= psc_db->psi8_params.instances[0]; n++ ) { if(!(psc_db->psi8_params.instances[n + 1])) { is_psi8_ok = FALSE;/* consistent set of PSI8 not complete */ break; } } TRACE_EVENT_P2( "PSI8: received with count = %d, index = %d", psi8->psi8_cnt, psi8->psi8_ind ); if(is_psi8_ok) { if(psc_db->state_of_PSI[PSI8].state NEQ RECEIPT_OK) { /* A new copy of PSI8 has been received. * RRGRR_CBCH_INFO_IND has to be sent after * all instances of PSI2 have been received when * acquisition is PARTIAL, and in case of COMPLETE * acquisition after access to the cell is enabled. */ psc_db->state_of_PSI[PSI8].state = RECEIPT_OK; psc_db->send_cbch_info_ind = TRUE; return PSI8_OK; } } } else { TRACE_EVENT_P2( "PSI8: already received with count = %d, index = %d", psi8->psi8_cnt, psi8->psi8_ind ); } return PSI8_OK; } /* psi_process_psi8() */ #endif /* +------------------------------------------------------------------------------ | Function : psi_check_change_field +------------------------------------------------------------------------------ | Description : The function psi_check_change_field() .... | | Parameters : UBYTE psi_change_field; return TRUE: acq needed, FALSE: not needed | +------------------------------------------------------------------------------ */ LOCAL BOOL psi_check_change_field (UBYTE psi_change_field) { BOOL return_value = FALSE; TRACE_FUNCTION( "psi_check_change_field" ); switch(psi_change_field) { case UPDATE_UNS_PSI: /*Update of unspecified PSI message(s);*/ psc_db->state_of_PSI[PSI2].state = NEEDED; psc_db->state_of_PSI[PSI3].state = NEEDED; psc_db->state_of_PSI[PSI3bis].state = NEEDED; #if defined (REL99) AND defined (TI_PS_FF_EMR) psc_db->state_of_PSI[PSI3ter].state = NEEDED; #endif psc_db->state_of_PSI[PSI4].state = NEEDED; psc_db->state_of_PSI[PSI5].state = NEEDED; /*??*/ #ifdef REL99 /* It is necessary to set PSI 8 to needed here. In case * PSI 8 is not broadcast in the cell, this value \ * would be sent to NOT_SEND when PSI 2 is received */ psc_db->state_of_PSI[PSI8].state = NEEDED; #endif /*psc_db->state_of_PSI[13] = NEEDED;*/ return_value = TRUE; break; case UPDATE_UNKNOWN: /* Unknown*/ return_value = FALSE; break; case UPDATE_PSI2: /* PSI2 updated*/ psc_db->state_of_PSI[PSI2].state = NEEDED; return_value = TRUE; break; case UPDATE_PSI3: /* PSI3/PSI3bis/PSI3ter updated*/ psc_db->state_of_PSI[PSI3].state = NEEDED; psc_db->state_of_PSI[PSI3bis].state = NEEDED; #if defined (REL99) AND defined (TI_PS_FF_EMR) if(psc_db->v_add_psi AND psc_db->add_psi.psi3ter_broadcast) { psc_db->state_of_PSI[PSI3ter].state = NEEDED; } else { psc_db->state_of_PSI[PSI3ter].state = NOT_SEND; } #endif return_value = TRUE; break; case UPDATE_PSI4: /* PSI4 updated*/ psc_db->state_of_PSI[PSI4].state = NEEDED; return_value = TRUE; break; case UPDATE_PSI5: /* PSI5 updated*/ psc_db->state_of_PSI[PSI5].state = NEEDED; return_value = TRUE; break; #ifdef REL99 case UPDATE_PSI8: psc_db->state_of_PSI[PSI8].state = NEEDED; return_value = TRUE; break; #endif default: /* All other values shall be interpreted as 'Update of unknown SI message type'.*/ return_value = FALSE; break; } return return_value; } /* psi_check_change_field() */ /* +------------------------------------------------------------------------------ | Function : psi_process_psi1 +------------------------------------------------------------------------------ | Description : The function psi_process_psi1() .... | | Parameters : T_PSI_1 *psi1 | +------------------------------------------------------------------------------ */ GLOBAL T_PSI1_RET psi_process_psi1 (T_PSI_1 *psi1 ) { T_PSI1_RET return_val = PSI1_OK; #ifdef REL99 UBYTE current_nw_rel = psc_db->network_rel; #endif TRACE_FUNCTION( "psi_process_psi1" ); if(psi1->pccch_org_par.bs_pcc_rel) { /* * last PDCH carrying PCCCH and PBCCH will be released shortly, receive si13 */ return_val = PSI1_PBCCH_RELEASED; } else if( grr_is_pbcch_present( ) EQ FALSE ) { return_val = PSI1_PBCCH_ESTABLISHED; } else { psc_db->state_of_PSI[PSI1].state = RECEIPT_OK; psc_db->complete_acq.psi1_ok = TRUE; /*PSI1 has been received*/ /* copy repeat period*/ psc_db->psi1_params.psi1_repeat_period = psi1->psi1_rep_per + 1; /* copy repetition rates */ psc_db->psi1_params.psi_cnt_lr = psi1->psi_cnt_lr; if(psi1->v_psi_cnt_hr) { psc_db->psi1_params.psi_cnt_hr = psi1->psi_cnt_hr + 1; } else { psc_db->psi1_params.psi_cnt_hr = 0;/*default*/ } psc_db->psi1_params.psi_status_supported = (psi1->psi_status_ind EQ 1) ? TRUE : FALSE; psc_db->measurement_order = psi1->meas_order; /*PSI5 is present in the cell or not*/ if(!psc_db->measurement_order) psc_db->state_of_PSI[PSI5].state = RECEIPT_OK; /* Process PRACH parameters*/ psi_process_prach(&(psi1->prach_ctrl_par)); /*copy pccch org params*/ psc_db->pccch.bs_pcc_rel = psi1->pccch_org_par.bs_pcc_rel; psc_db->pccch.bs_pbcch_blks = psi1->pccch_org_par.bs_pbcch_blks; psc_db->pccch.bs_pag_blks = CLIP_BS_PAG_BLKS_RES( psi1->pccch_org_par.bs_pag_blks ); psc_db->pccch.bs_prach_blks = CLIP_BS_PRACH_BLKS( psi1->pccch_org_par.bs_prach_blks ); /*copy GPRS cell options*/ psc_db->v_gprs_cell_opt = TRUE; psc_db->cell_info_for_gmm.cell_info.net_mode = psi1->gprs_cell_opt.nmo; psc_db->gprs_cell_opt.nmo = psi1->gprs_cell_opt.nmo; psc_db->gprs_cell_opt.t3168 = psi1->gprs_cell_opt.t3168; psc_db->gprs_cell_opt.t3192 = psi1->gprs_cell_opt.t3192; psc_db->gprs_cell_opt.drx_t_max = psi1->gprs_cell_opt.drx_t_max; psc_db->gprs_cell_opt.ab_type = psi1->gprs_cell_opt.ab_type; psc_db->gprs_cell_opt.ctrl_ack_type = psi1->gprs_cell_opt.ctrl_ack_type; psc_db->gprs_cell_opt.bs_cv_max = psi1->gprs_cell_opt.bs_cv_max; memcpy(&(psc_db->gprs_cell_opt), &(psi1->gprs_cell_opt), sizeof(T_gprs_cell_opt)); /*if(psi1->gprs_cell_opt.v_pan_struct) { psc_db->gprs_cell_opt.pan_struct.inc = psi1->gprs_cell_opt.pan_struct.inc; psc_db->gprs_cell_opt.pan_struct.dec = psi1->gprs_cell_opt.pan_struct.dec; psc_db->gprs_cell_opt.pan_struct.pmax = ( psi1->gprs_cell_opt.pan_struct.pmax + 1 ) * 4; psc_db->gprs_cell_opt.v_pan_struct = 1; }*/ if(psi1->gprs_cell_opt.v_gprs_ext_bits) { memcpy(&(psc_db->gprs_cell_opt.gprs_ext_bits), &(psi1->gprs_cell_opt.gprs_ext_bits), sizeof(T_gprs_ext_bits)); psc_db->gprs_cell_opt.v_gprs_ext_bits = 1; } /*Global power control parameters*/ grr_store_g_pwr_par( &psi1->g_pwr_par ); /* check whether the PSI4 is broadcast or not*/ if(!psc_db->g_pwr_par.imeas_chan_list) psc_db->state_of_PSI[PSI4].state = RECEIPT_OK; TRACE_EVENT_P2( "PSI1: database change mark: %d, message change mark: %d", psc_db->psi1_params.pbcch_change_mark, psi1->pbcch_change_ma ); if(psc_db->psi1_params.first_psi1) { psc_db->psi1_params.pbcch_change_mark = psi1->pbcch_change_ma; /* set the new change mark value*/ } else { UBYTE incremented_value = psi_compare_change_mark(psi1->pbcch_change_ma, psc_db->psi1_params.pbcch_change_mark); psc_db->psi1_params.pbcch_change_mark = psi1->pbcch_change_ma; /* set the new change mark value*/ if(incremented_value EQ 1)/*partial acq*/ { if(psi_check_change_field(psi1->psi_change_field)) { return_val = PSI1_PARTIAL_ACQ; } } else if(incremented_value > 1) /* incremented_value more than 1: complete acq*/ { return_val = PSI1_COMPLETE_ACQ; } } #ifdef REL99 /* Update the BSS release from PSI1 instead of SI13, when PBCCH is present */ /* Update the SGSN release */ if (psi1->v_release_99_str_psi_1) { psc_db->network_rel = BSS_NW_REL_99; psc_db->sgsn_rel = psi1->release_99_str_psi_1.sgsnr ? PS_SGSN_99_ONWARDS : PS_SGSN_98_OLDER; #ifdef TI_PS_FF_QUAD_BAND_SUPPORT psc_db->band_indicator = psi1->release_99_str_psi_1.band_indicator; #endif } else { psc_db->sgsn_rel = PS_SGSN_98_OLDER; #ifdef TI_PS_FF_QUAD_BAND_SUPPORT psc_db->band_indicator = NOT_PRESENT_8BIT; #endif } #ifdef TI_PS_FF_QUAD_BAND_SUPPORT /* * Update std depending on the band indicator */ att_update_std_band_indicator ( psc_db->band_indicator ); #endif /* Please note that there is no check for (psi1->release_99 EQ FALSE) and * then setting the psc_db->network_rel to BSS_NW_REL_97 as sometimes the * the R99 or R4 network may not broadcast the optional R99 IEs. At that * time, the network release is assigned wrongly if the above check exists. */ if(psc_db->network_rel NEQ current_nw_rel) { TRACE_EVENT_P2("(PSI1)BSS Network release changed from %d to %d <0 - REL_97, 1 - REL_99, 2 - REL_04>", current_nw_rel, psc_db->network_rel); } /* Update the SGSN release in the Common library context */ cl_nwrl_set_sgsn_release(psc_db->sgsn_rel); #endif } TRACE_EVENT_P1( "PSI1: received with return value %d", return_val ); grr_set_pg_nmo(); return return_val; } /* psi_process_psi1() */ /* +------------------------------------------------------------------------------ | Function : psi_receive_psi +------------------------------------------------------------------------------ | Description : The function psi_receive_psi() .... | | Parameters : BOOL read_all | +------------------------------------------------------------------------------ */ GLOBAL void psi_receive_psi ( UBYTE psi_reading_type) { TRACE_FUNCTION( "psi_receive_psi" ); if(grr_data->psi.is_pbcch_req_allowed) { /* * Prepare MPHP_SCELL_PBCCH_REQ to receive psi */ PALLOC(mphp_scell_pbcch_req, MPHP_SCELL_PBCCH_REQ); psi_prepare_scell_pbcch_req(mphp_scell_pbcch_req, psi_reading_type); PSEND(hCommL1,mphp_scell_pbcch_req); grr_data->psi.is_pbcch_req_needed =FALSE; } else { TRACE_EVENT("PBCCH request needed after release of TBF, stop of RR tasks, etc."); grr_data->psi.is_pbcch_req_needed =TRUE; /* * store the reading_type in case of needed in/after release procedure */ grr_data->psi.reading_type=psi_reading_type; } } /* psi_receive_psi() */ /* +------------------------------------------------------------------------------ | Function : psi_process_prach +------------------------------------------------------------------------------ | Description : The function psi_process_prach() .... | | Parameters : T_prach_ctrl_par *prach: pointer to PRACH control parameters | +------------------------------------------------------------------------------ */ GLOBAL void psi_process_prach ( T_prach_ctrl_par *prach ) { TRACE_FUNCTION( "psi_process_prach" ); psc_db->v_prach = TRUE; memcpy(&(psc_db->prach), prach, sizeof(T_prach_ctrl_par)); TRACE_EVENT_P5("ac_class: %d max_ret %d %d %d %d", prach->ac_class, prach->max_retrans[0], prach->max_retrans[1], prach->max_retrans[2], prach->max_retrans[3]); TRACE_EVENT_P2("s_prach: %d tx_int:%d", prach->s_prach, prach->tx_int); if(prach->v_pers_lev) { TRACE_EVENT_P4("pers: %d %d %d %d", prach->pers_lev.plev[0], prach->pers_lev.plev[1], prach->pers_lev.plev[2], prach->pers_lev.plev[3]); } } /* psi_process_prach() */ /* +------------------------------------------------------------------------------ | Function : psi_reset_si_entries +------------------------------------------------------------------------------ | Description : The function psi_reset_si_entries() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_reset_si_entries ( void ) { TRACE_FUNCTION( "psi_reset_si_entries" ); psc_db->psi13_params.bcch_change_mark = NOT_SET; psc_db->psi13_params.si13_change_mark = NOT_SET; } /* psi_reset_si_entries() */ /* +------------------------------------------------------------------------------ | Function : psi_acq_state_of_si +------------------------------------------------------------------------------ | Description : The function psi_acq_state_of_si() .... | This function is ONLY called after processing SI13 message | Parameters : T_si_states si_states: contains the state of the SI messages | needed for checking for packet access allowance | +------------------------------------------------------------------------------ */ GLOBAL T_ACQ_STATE_RET psi_acq_state_of_si ( T_si_states si_states) { T_ACQ_STATE_RET ret_value = ACQ_RUNNING; TRACE_FUNCTION( "psi_acq_state_of_si" ); switch(psc_db->acq_type) { case PARTIAL: ret_value = ACQ_PART_OK; break; case COMPLETE: if((si_states.si3_state EQ SI3_RECEIVED) AND (si_states.si13_state EQ SI13_RECEIVED)) { if((si_states.si1_state EQ SI1_NOT_SEND) OR (si_states.si1_state EQ SI1_RECEIVED)) { ret_value = ACQ_COMP_OK; } } break; case PERIODICAL_SI13_READING: ret_value = ACQ_PERIOD_OK; break; default: break; } return ret_value; } /* psi_acq_state_of_si() */ /* +------------------------------------------------------------------------------ | Function : psi_is_update_needed +------------------------------------------------------------------------------ | Description : The function psi_is_update_needed() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL BOOL psi_is_update_needed ( UBYTE si_change_field ) { TRACE_FUNCTION( "psi_is_update_needed" ); switch(si_change_field) { case UNSPECIFIED_SI: case UPDATE_SI1: case UPDATE_SI2_SI2BIS_OR_SI2TER: case UPDATE_SI3_SI4_SI7_OR_SI8: case UPDATE_SI9: return TRUE; default: return FALSE; } } /* psi_is_update_needed() */ /* +------------------------------------------------------------------------------ | Function : psi_update_data_to_request +------------------------------------------------------------------------------ | Description : The function psi_update_data_to_request updates the static | and hopping frequencies and other parameters to request PSI | data. This function is called after receiving SI13 or PSI13 or PSI1 | | Parameters : UBYTE init_needed: checks whether initialization is needed or not | +------------------------------------------------------------------------------ */ GLOBAL void psi_update_data_to_request( UBYTE init_needed) { T_MPHP_SCELL_PBCCH_REQ *ptr_prim; TRACE_FUNCTION( "psi_update_data_to_request" ); ptr_prim = &psc_db->scell_pbcch; if(init_needed) { TRACE_EVENT("Init Needed"); memset(&psc_db->pccch, 0, sizeof(T_pccch_org_par)); /*initial*/ psc_db->psi1_params.psi_cnt_hr = 0; /* initial*/ psc_db->psi1_params.psi_cnt_lr = 0; /* initial*/ } /* * set values for mphp_scell_pbcch_req */ ptr_prim->pb = psc_db->pbcch.pbcch_des.pb; /*< Power reduction value */ ptr_prim->bs_pbcch_blks = psc_db->pccch.bs_pbcch_blks; /*< Number of PBCCH per multiframe */ ptr_prim->psi1_rep_period = psc_db->psi1_params.psi1_repeat_period; /*< PSI1 repeat period */ ptr_prim->p_ch_des.tsc = psc_db->pbcch.pbcch_des.tsc; /*< Training sequence code */ ptr_prim->p_ch_des.tn = psc_db->pbcch.pbcch_des.tn; /*< timeslot number */ if (psc_db->pbcch.pbcch_des.v_arfcn OR ( (psc_db->pbcch.pbcch_des.flag EQ 0) AND /* use bcch.arfcn*/ (psc_db->pbcch.pbcch_des.flag2 EQ 0) ) ) { ptr_prim->p_ch_des.p_chan_sel.hopping = 0; ptr_prim->p_ch_des.p_chan_sel.p_rf_ch.arfcn = (psc_db->pbcch.pbcch_des.v_arfcn ) ?grr_g23_arfcn_to_l1(psc_db->pbcch.pbcch_des.arfcn) :grr_g23_arfcn_to_l1(psc_db->pbcch.bcch.arfcn); TRACE_EVENT_P8("Up_s: pbcch:%d per:%d hr:%d lr:%d pb:%d tsc:%d tn:%d arfcn:%d", psc_db->pccch.bs_pbcch_blks, psc_db->psi1_params.psi1_repeat_period, psc_db->psi1_params.psi_cnt_hr, psc_db->psi1_params.psi_cnt_lr, psc_db->pbcch.pbcch_des.pb, psc_db->pbcch.pbcch_des.tsc, psc_db->pbcch.pbcch_des.tn, ptr_prim->p_ch_des.p_chan_sel.p_rf_ch.arfcn); } else { grr_create_freq_list( MA_NUMBER_4_PSI13_OR_CELL_ALLOC, psc_db->pbcch.pbcch_des.maio, &ptr_prim->p_ch_des.p_chan_sel, &ptr_prim->p_freq_list ); TRACE_EVENT_P8("Up_h1: pbcch:%d per:%d hr:%d lr:%d pb:%d tsc:%d tn:%d maio:%d", psc_db->pccch.bs_pbcch_blks, psc_db->psi1_params.psi1_repeat_period, psc_db->psi1_params.psi_cnt_hr, psc_db->psi1_params.psi_cnt_lr, psc_db->pbcch.pbcch_des.pb, psc_db->pbcch.pbcch_des.tsc, psc_db->pbcch.pbcch_des.tn, psc_db->pbcch.pbcch_des.maio); } } /* psi_update_data_to_request() */ /* +------------------------------------------------------------------------------ | Function : psi_is_access_class_changed +------------------------------------------------------------------------------ | Description : This function checks the access class control parameter and | return TRUE/FALSE value | | Parameters : void; return BOOL: TRUE: access class changed; FALSE: nothing has changed | +------------------------------------------------------------------------------ */ GLOBAL BOOL psi_is_access_class_changed(void) { USHORT dummy1, dummy2, access_changed; TRACE_FUNCTION("psi_is_access_class_changed"); access_changed = FALSE; /* check the access control class and inform the service: CTRL * check access class control for authorized classes 0 to 9 and * check access class control for authorized classes 11 to 15 and */ dummy1 = grr_data->ms.access_ctrl_class & 0x3FF; dummy2 = grr_data->ms.access_ctrl_class & 0xF800; if( ((dummy1 & ~psc_db->prach.ac_class) > 0) /* 0 to 9*/ OR ((dummy2 & ~psc_db->prach.ac_class) > 0) /* 11 to 15*/ ) { /* * The MS belongs to one of the authorized access classes */ if(psc_db->cell_info_for_gmm.access_status NEQ GPRS_ACCESS_ALLOWED) { /* * Access was NOT allowed, so we have to inform GMM */ access_changed = TRUE; psc_db->cell_info_for_gmm.access_status = GPRS_ACCESS_ALLOWED; } } else { /* * Access barred */ if(psc_db->cell_info_for_gmm.access_status NEQ GPRS_ACCESS_BARRED) { /* * Access was ALLOWED, so we have to inform GMM */ access_changed = TRUE; psc_db->cell_info_for_gmm.access_status = GPRS_ACCESS_BARRED; } } if( access_changed ) { TRACE_EVENT( "Access class changed" ); grr_set_cell_info_service( ); } return( access_changed ); }/* psi_is_access_class_changed*/ /* +------------------------------------------------------------------------------ | Function : psi_init_params +------------------------------------------------------------------------------ | Description : The function psi_init_params() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_init_params ( void ) { #if defined (TI_PS_FF_RTD) AND defined (REL99) UBYTE n; #endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */ TRACE_FUNCTION( "psi_init_params" ); grr_data->psi.is_pbcch_req_needed =FALSE; /*PBCCH req. waiting for perform*/ grr_data->psi.is_pbcch_req_allowed =TRUE; /*PBCCH req. allowed due to transition rules or not*/ #if defined (TI_PS_FF_RTD) AND defined (REL99) for( n = 0; n < MAX_NR_OF_NCELL; n++ ) grr_data->psi.rtd[n] = RTD_NOT_AVAILABLE; #endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */ psi_reset_all(); psi_init_rfl_psi2(); /* set the Reference Frequency List parameters to initial values */ psi_init_cell_alloc(); /* init cell allocation structure */ psi_init_gprs_ms_alloc(FALSE); /* init GPRS Mobile Allocations struct */ } /* psi_init_params() */ /* +------------------------------------------------------------------------------ | Function : psi_stop_timer +------------------------------------------------------------------------------ | Description : The function stops psi timers if they are running | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_stop_timer ( void ) { TRACE_FUNCTION( "psi_stop_timer" ); vsi_t_stop(GRR_handle,T_10_SEC); vsi_t_stop(GRR_handle,T_30_SEC); vsi_t_stop(GRR_handle,T_60_SEC); vsi_t_stop(GRR_handle,T_COMP_PSI); } /* psi_stop_timer() */ /* +------------------------------------------------------------------------------ | Function : psi_is_access_allowed +------------------------------------------------------------------------------ | Description : The function checks whether the access to the network is allowed | or not | | Parameters : BOOL: TRUE if access allowed, otherwise FALSE | +------------------------------------------------------------------------------ */ GLOBAL BOOL psi_is_access_allowed(void) { TRACE_FUNCTION("psi_is_access_allowed"); /* * Check whether access is enabled or not: Access is allowed * if PSI acquisition is completed or PSI1&PSI2 was read with * success AND psi status is suppoerted by the network */ #ifdef _SIMULATION_ if( psc_db->psi1_params.psi_status_supported AND psc_db->complete_acq.psi1_ok AND psc_db->complete_acq.psi2_ok ) return TRUE; #endif /* #ifdef _SIMULATION_ */ return FALSE; }/*psi_is_access_allowed */ /* +------------------------------------------------------------------------------ | Function : psi_reread_psi2 +------------------------------------------------------------------------------ | Description : The function starts the reading process of PSI2 | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_reread_psi2(void) { TRACE_FUNCTION("psi_reread_psi2"); psc_db->state_of_PSI[PSI2].state = NEEDED; psi_partial_acq(); psi_reset_psi2(); psi_start_10sec(); }/* psi_reread_psi2*/ /* +------------------------------------------------------------------------------ | Function : psi_reread_psi3_and_3bis +------------------------------------------------------------------------------ | Description : The function starts the reading process of PSI3 nad PSI3bis | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_reread_psi3_and_3bis(void) { TRACE_FUNCTION("psi_reread_psi3_and_3bis"); psc_db->state_of_PSI[PSI3bis].state = NEEDED; psc_db->state_of_PSI[PSI3].state = NEEDED; psi_partial_acq(); /* * Reset PSI3 and PSI3BIS paramter */ psi_reset_psi3bis(); psi_reset_psi3(); psi_start_10sec(); }/* psi_reread_psi3_and_3bis*/ /* +------------------------------------------------------------------------------ | Function : psi_reread_psi3bis +------------------------------------------------------------------------------ | Description : The function starts the reading process of PSI3bis | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_reread_psi3bis(void) { TRACE_FUNCTION("psi_reread_psi3bis"); /* * Message has changed, reset all values and read new consistent message set */ psc_db->state_of_PSI[PSI3bis].state = NEEDED; psi_partial_acq(); psi_reset_psi3bis(); psi_start_10sec(); }/* psi_reread_psi3bis*/ #if defined (REL99) AND defined (TI_PS_FF_EMR) /* +------------------------------------------------------------------------------ | Function : psi_reread_psi3ter +------------------------------------------------------------------------------ | Description : The function starts the reading process of PSI3ter | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_reread_psi3ter(void) { TRACE_FUNCTION("psi_reread_psi3ter"); /* * Message has changed, reset all values and read new consistent message set */ psc_db->state_of_PSI[PSI3ter].state = NEEDED; psi_partial_acq(); psi_reset_psi3ter(); psi_start_10sec(); }/* psi_reread_psi3ter*/ /* +------------------------------------------------------------------------------ | Function : psi_reread_psi3_3bis_3ter +------------------------------------------------------------------------------ | Description : The function starts the reading process of PSI3 to PSI3ter | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_reread_psi3_3bis_3ter(void) { TRACE_FUNCTION("psi_reread_psi3_3bis_3ter"); if(psc_db->v_add_psi AND psc_db->add_psi.psi3ter_broadcast) { psc_db->state_of_PSI[PSI3ter].state = NEEDED; } else { psc_db->state_of_PSI[PSI3ter].state = NOT_SEND; } psc_db->state_of_PSI[PSI3bis].state = NEEDED; psc_db->state_of_PSI[PSI3].state = NEEDED; psi_partial_acq(); /* * Reset PSI3 to PSI3ter parameters */ /* psi_reset_psi3quater(); */ psi_reset_psi3ter(); psi_reset_psi3bis(); psi_reset_psi3(); psi_start_10sec(); }/* psi_reread_psi3_3bis_3ter */ #endif /* +------------------------------------------------------------------------------ | Function : psi_reread_psi4 +------------------------------------------------------------------------------ | Description : The function starts the reading process of PSI4 | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_reread_psi4(void) { TRACE_FUNCTION("psi_reread_psi4"); psc_db->state_of_PSI[PSI4].state = NEEDED; psi_partial_acq(); /* * Reset PSI4 */ psi_reset_psi4(); psi_start_10sec(); }/* psi_reread_psi4*/ /* +------------------------------------------------------------------------------ | Function : psi_reread_psi5 +------------------------------------------------------------------------------ | Description : The function starts the reading process of PSI5 | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_reread_psi5(void) { TRACE_FUNCTION("psi_reread_psi5"); psc_db->state_of_PSI[PSI5].state = NEEDED; psi_partial_acq(); /* * Reset PSI5 */ psi_reset_psi5(); psi_start_10sec(); }/* psi_reread_psi5*/ #ifdef REL99 /* +------------------------------------------------------------------------------ | Function : psi_reread_psi8 +------------------------------------------------------------------------------ | Description : The function starts the reading process of PSI8 | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void psi_reread_psi8(void) { TRACE_FUNCTION("psi_reread_psi8"); psc_db->state_of_PSI[PSI8].state = NEEDED; psi_partial_acq(); /* * Reset PSI8 */ psi_reset_psi8(); psi_start_10sec(); }/* psi_reread_psi8*/ #endif /* +------------------------------------------------------------------------------ | Function : psi_handle_psi1 +------------------------------------------------------------------------------ | Description : The function handles PSI1 message on both PBCCH and PACCH channels | | Parameters : T_PSI_1* | +------------------------------------------------------------------------------ */ GLOBAL void psi_handle_psi1(T_PSI_1 * psi1) { TRACE_FUNCTION("psi_handle_psi1"); switch(psi_process_psi1(psi1)) { case PSI1_PBCCH_RELEASED: SET_STATE( PSI, PSI_NULL ); psi_initiate_pbcch_switching( PSI_DC_PBCCH_RELEASED ); return; /* sorry: dirty solution */ case PSI1_PBCCH_ESTABLISHED: SET_STATE( PSI, PSI_NULL ); psi_initiate_pbcch_switching( PSI_DC_PBCCH_ESTABLISHED ); return; /* sorry: another dirty solution */ case PSI1_OK: if( psc_db->measurement_order EQ FALSE ) { sig_psi_ctrl_meas_param_invalid_psi5( ); } /* update readin parameters of psi */ psi_update_data_to_request(INIT_NOT_NEEDED); /* * check the state of the acquisition */ switch(psi_check_acq_state()) { case ACQ_RUNNING: /* * Check whether access to the network is allowed or not, * in case of having complete acq */ if(psi_is_access_allowed() AND (psc_db->acq_type EQ COMPLETE)) { psc_db->psi1_params.first_psi1 = FALSE; psi_stop_psi_reading(NONE); psi_stop_10sec(); /* Stop this timer, if running */ #ifdef _SIMULATION_ vsi_t_stop(GRR_handle,T_COMP_PSI); #endif /* * restart 30 sec:e.g. wait 30 sec for reread PSI1 */ psi_stop_30sec(TRUE); /* * Access to the network is allowed */ psi_send_access_enable_if_needed(); } else if(psi_is_access_allowed() AND (psc_db->acq_type EQ FULL_PSI_IN_NEW_CELL)) { /* * Access to the new re-selected cell is allowed */ psc_db->psi1_params.first_psi1 = FALSE; psi_stop_psi_reading(NONE); /* * restart 30 sec:e.g. wait 30 sec for reread PSI1 */ psi_stop_30sec(TRUE); sig_psi_ctrl_ncell_psi_read( TRUE); } else { /* * Acq. is running, check whether we received the PSI1 message * for the first time or not. * if the PSI1 message is received for the first time, restart to read PBCCH blocks, * because of reading new parameters in PSI1 message,e.g. PCCCH parameters */ if( psc_db->psi1_params.first_psi1 AND ((psc_db->acq_type EQ COMPLETE) OR (psc_db->acq_type EQ FULL_PSI_IN_NEW_CELL)) ) { psi_stop_30sec(TRUE);/*restart 30 sec*/ psi_receive_psi(READ_COMPLETE); } } break; case ACQ_PART_OK: psi_stop_psi_reading(NONE); #ifdef _TARGET_ TRACE_EVENT("PSI1->NEW_PCCCH"); sig_psi_ctrl_new_pccch(); #if defined (REL99) AND defined (TI_PS_FF_EMR) psc_db->network_pg_mode = psi1->page_mode; #endif #endif break; case ACQ_COMP_OK: psi_stop_60sec(TRUE);/*restart 60 sec*/ psi_stop_30sec(TRUE);/*restart 30 sec*/ psi_stop_psi_reading(NONE); /* * Access to the network is allowed */ psi_send_access_enable_if_needed(); break; case ACQ_PERIOD_OK: /* * Periodical pSI1 reading is O.K. */ psi_stop_60sec(TRUE);/*restart 60 sec*/ psi_stop_30sec(TRUE);/*restart 30 sec*/ psi_stop_psi_reading(NONE); break; default: TRACE_ERROR("Unexpected acq_ret in PSI1"); break; }/* switch acq_state*/ break; case PSI1_COMPLETE_ACQ: psi_initiate_read_complete_psi( INIT_NOT_NEEDED ); break; case PSI1_PARTIAL_ACQ: /* update psi data*/ psi_stop_60sec(TRUE);/*restart 60 sec*/ psi_stop_30sec(TRUE);/*restart 30 sec*/ psi_update_data_to_request( INIT_NOT_NEEDED); psi_partial_acq(); /*TRACE_EVENT("Complete instead partial"); psi_receive_psi(READ_COMPLETE);*/ psc_db->send_psi_status = TRUE; /* this parameters has meaning if the network supports PSI STATUS */ psi_start_10sec(); break; }/* switch process_psi1*/ if(psi_is_access_class_changed() AND !psc_db->psi1_params.first_psi1) { /* * Implies the CTRL to send CELL_IND */ sig_psi_ctrl_access_changed(); } if(psc_db->acq_type NEQ COMPLETE) { psc_db->psi1_params.first_psi1 = FALSE; } }/* psi_handle_psi1*/ /* +------------------------------------------------------------------------------ | Function : psi_handle_psi2 +------------------------------------------------------------------------------ | Description : The function handles PSI2 message on both PBCCH and PACCH channels | | Parameters : T_PSI_2* | +------------------------------------------------------------------------------ */ GLOBAL void psi_handle_psi2(T_PSI_2 * psi2) { TRACE_FUNCTION("psi_handle_psi2"); switch(psi_process_psi2(psi2)) { case PSI2_OK: switch(psi_check_acq_state()) { case ACQ_RUNNING: /* * Check whether access to the network is allowed or not, * in case of having complete acq */ if(psi_is_access_allowed() AND (psc_db->acq_type EQ COMPLETE)) { psi_stop_psi_reading(NONE); psi_stop_10sec(); /* Stop this timer, if running */ #ifdef _SIMULATION_ vsi_t_stop(GRR_handle,T_COMP_PSI); #endif /* * Access to the network is allowed */ psi_send_access_enable_if_needed(); } else if(psi_is_access_allowed() AND (psc_db->acq_type EQ FULL_PSI_IN_NEW_CELL)) { /* * Access to the new re-selected cell is allowed */ psi_stop_psi_reading(NONE); sig_psi_ctrl_ncell_psi_read( TRUE ); } break; case ACQ_PART_OK: psi_stop_psi_reading(NONE); /* * TimeSlot number may have changed, so we have to restart PCCCH reading */ TRACE_EVENT("PSI2->NEW_PCCCH"); sig_psi_ctrl_new_pccch(); #if defined (REL99) AND defined (TI_PS_FF_EMR) psc_db->network_pg_mode = psi2->page_mode; #endif break; case ACQ_COMP_OK: psi_stop_psi_reading(NONE); /* * Access to the network is allowed */ psi_send_access_enable_if_needed(); break; default: TRACE_ERROR("Unexpected acq_ret in PSI2"); break; }/*switch check_acq*/ break; case PSI2_REREAD: /* * Error situation read a new PSI2 */ psi_reread_psi2(); break; } }/* psi_handle_psi2*/ /* +------------------------------------------------------------------------------ | Function : psi_handle_psi3 +------------------------------------------------------------------------------ | Description : The function handles PSI3 message on both PBCCH and PACCH channels | | Parameters : T_PSI_3* | +------------------------------------------------------------------------------ */ GLOBAL void psi_handle_psi3(T_PSI_3 * psi3) { TRACE_FUNCTION("psi_handle_psi3"); switch(psi_process_psi3(psi3)) { case PSI3_NCELL_VALID: /* * Inform MEAS that the NCELL parameters are valid */ sig_psi_ctrl_ncell_param_valid(); /*lint -fallthrough*/ case PSI3_OK: /* * check the acquisition state: it is only for having a complete set of information */ switch(psi_check_acq_state()) { case ACQ_RUNNING: /* * Nothing to do */ break; case ACQ_PART_OK: psi_stop_psi_reading(NONE); #ifdef _TARGET_ TRACE_EVENT("PSI3->NEW_PCCCH"); sig_psi_ctrl_new_pccch(); #if defined (REL99) AND defined (TI_PS_FF_EMR) psc_db->network_pg_mode = psi3->page_mode; #endif #endif break; case ACQ_COMP_OK: psi_stop_psi_reading(NONE); /* * Access to the network is allowed */ psi_send_access_enable_if_needed(); break; default: TRACE_ERROR("Unexpected acq_ret in PSI3"); break; }/*switch check_acq*/ break; case PSI3_NCELL_INVALID: grr_init_nc_list( &psc_db->nc_cw.list ); sig_psi_ctrl_ncell_param_invalid(); break; case PSI3_CELL_BARRED: sig_psi_ctrl_access_barred(); break; }/* switch psi_process_psi3*/ }/*psi_handle_psi3*/ /* +------------------------------------------------------------------------------ | Function : psi_handle_psi3bis +------------------------------------------------------------------------------ | Description : The function handles PSI3_BIS message on both PBCCH and PACCH channels | | Parameters : T_PSI_3_BIS* | +------------------------------------------------------------------------------ */ GLOBAL void psi_handle_psi3bis(T_PSI_3_BIS * psi3bis) { TRACE_FUNCTION("psi_handle_psi3bis"); switch(psi_process_psi3bis(psi3bis)) { case PSI3BIS_REREAD_PSI3BIS: psi_reread_psi3bis(); /* * Ncell parameter are invalid. We have to inform MEAS-Service */ grr_init_nc_list( &psc_db->nc_cw.list ); sig_psi_ctrl_ncell_param_invalid(); break; #if defined (REL99) AND defined (TI_PS_FF_EMR) case PSI3BIS_REREAD_PSI3_3BIS_3TER: psi_reread_psi3_3bis_3ter(); #else case PSI3BIS_REREAD_PSI3_3BIS: psi_reread_psi3_and_3bis(); #endif /* * Ncell parameter are invalid. We have to inform MEAS-Service */ grr_init_nc_list( &psc_db->nc_cw.list ); sig_psi_ctrl_ncell_param_invalid(); break; case PSI3BIS_NCELL_VALID: /* * Inform MEAS that the NCELL parameters are valid */ sig_psi_ctrl_ncell_param_valid(); /*lint -fallthrough*/ case PSI3BIS_OK: /* * check the acquisition state: it is only for having a complete set of information */ switch(psi_check_acq_state()) { case ACQ_RUNNING: /* * Nothing to do */ break; case ACQ_PART_OK: psi_stop_psi_reading(NONE); #ifdef _TARGET_ TRACE_EVENT("PSI3bis->NEW_PCCCH"); sig_psi_ctrl_new_pccch(); #if defined (REL99) AND defined (TI_PS_FF_EMR) psc_db->network_pg_mode = psi3bis->page_mode; #endif #endif break; case ACQ_COMP_OK: psi_stop_psi_reading(NONE); /* * Access to the network is allowed */ psi_send_access_enable_if_needed(); break; default: TRACE_ERROR("Unexpected acq_ret in PSI3bis"); break; }/*switch check_acq*/ break; }/* switch process_psi3bis*/ }/*psi_handle_psi3bis*/ #if defined (REL99) AND defined (TI_PS_FF_EMR) /* +------------------------------------------------------------------------------ | Function : psi_handle_psi3ter +------------------------------------------------------------------------------ | Description : The function handles PSI3_TER message on both PBCCH and PACCH channels | | Parameters : T_PSI_3_TER* | +------------------------------------------------------------------------------ */ GLOBAL void psi_handle_psi3ter(T_PSI_3_TER * psi3ter) { TRACE_FUNCTION("psi_handle_psi3ter"); switch(psi_process_psi3ter(psi3ter)) { case PSI3TER_REREAD_PSI3TER: psi_reread_psi3ter(); break; case PSI3TER_REREAD_PSI3_3BIS_3TER: psi_reread_psi3_3bis_3ter(); break; case PSI3TER_OK: /* * check the acquisition state: it is only for having a complete set of information */ switch(psi_check_acq_state()) { case ACQ_RUNNING: /* * Nothing to do */ break; case ACQ_PART_OK: psi_stop_psi_reading(NONE); #ifdef _TARGET_ TRACE_EVENT("PSI3ter->NEW_PCCCH"); sig_psi_ctrl_new_pccch(); psc_db->network_pg_mode = psi3ter->page_mode; #endif break; case ACQ_COMP_OK: psi_stop_psi_reading(NONE); /* * Access to the network is allowed */ psi_send_access_enable_if_needed(); break; default: TRACE_ERROR("Unexpected acq_ret in PSI3bis"); break; }/*switch check_acq*/ break; }/* switch process_psi3ter*/ }/*psi_handle_psi3ter*/ #endif /* +------------------------------------------------------------------------------ | Function : psi_handle_psi4 +------------------------------------------------------------------------------ | Description : The function handles PSI4 message on both PBCCH and PACCH channels | | Parameters : T_PSI_4* | +------------------------------------------------------------------------------ */ GLOBAL void psi_handle_psi4(T_PSI_4 * psi4) { TRACE_FUNCTION("psi_handle_psi4"); switch(psi_process_psi4(psi4)) { case PSI4_REREAD: psi_reread_psi4(); /* * Interference channel list is invalid. We have to inform MEAS-Service */ sig_psi_ctrl_int_list_invalid(); break; case PSI4_INT_LIST_VALID: /* * Inform MEAS that the Interference parameters are valid */ sig_psi_ctrl_int_list_valid(); /*lint -fallthrough*/ case PSI4_OK: /* * check the acquisition state: it is only for having a complete set of information */ switch(psi_check_acq_state()) { case ACQ_RUNNING: /* * Nothing to do */ break; case ACQ_PART_OK: psi_stop_psi_reading(NONE); #ifdef _TARGET_ TRACE_EVENT("PSI4->NEW_PCCCH"); sig_psi_ctrl_new_pccch(); #if defined (REL99) AND defined (TI_PS_FF_EMR) psc_db->network_pg_mode = psi4->page_mode; #endif #endif break; case ACQ_COMP_OK: psi_stop_psi_reading(NONE); /* * Access to the network is allowed */ psi_send_access_enable_if_needed(); break; default: TRACE_ERROR("Unexpected acq_ret in PSI4"); break; }/*switch check_acq*/ break; } }/* psi_handle_psi4*/ #ifdef REL99 /* +------------------------------------------------------------------------------ | Function : psi_handle_psi8 +------------------------------------------------------------------------------ | Description : The function handles PSI8 message on both PBCCH and PACCH channels | | Parameters : T_PSI_8* | +------------------------------------------------------------------------------ */ GLOBAL void psi_handle_psi8(T_PSI_8 * psi8) { TRACE_FUNCTION("psi_handle_psi8"); switch(psi_process_psi8(psi8)) { case PSI8_REREAD: psi_reread_psi8(); break; case PSI8_OK: /* * check the acquisition state: it is only for having a complete set of information */ switch(psi_check_acq_state()) { case ACQ_RUNNING: /* * Nothing to do */ break; case ACQ_PART_OK: psi_stop_psi_reading(NONE); #ifdef _TARGET_ TRACE_EVENT("PSI8->NEW_PCCCH"); sig_psi_ctrl_new_pccch(); psc_db->network_pg_mode = psi8->page_mode; #endif break; case ACQ_COMP_OK: psi_stop_psi_reading(NONE); /* * Access to the network is allowed */ psi_send_access_enable_if_needed(); break; default: TRACE_ERROR("Unexpected acq_ret in PSI8"); break; }/*switch check_acq*/ break; } }/* psi_handle_psi8*/ #endif /* +------------------------------------------------------------------------------ | Function : psi_copy_si13_params +------------------------------------------------------------------------------ | Description : The function copies si13 parameters into sc_db | | Parameters : T_D_SYS_INFO_13* | +------------------------------------------------------------------------------ */ LOCAL void psi_copy_si13_params(T_D_SYS_INFO_13* si13) { TRACE_FUNCTION("psi_copy_si13_params"); /* * Copy SI13_CHANGE_MARK and GPRS Mobile Allocation */ if(si13->si13_rest_oct.si13_info.flag) { psc_db->psi13_params.si13_change_mark = si13->si13_rest_oct.si13_info.si13_cm; psi_copy_ma_from_psi13((T_gprs_ms_alloc_ie*)&(si13->si13_rest_oct.si13_info.gprs_ma)); } grr_set_pbcch( si13->si13_rest_oct.si13_info.v_pbcch_des ); if(si13->si13_rest_oct.si13_info.v_pbcch_des) { /* * PBCCH description present in the SI13 message */ psc_db->psi1_params.psi1_repeat_period = si13->si13_rest_oct.si13_info.psi1_period + 1; /* pbcch description in database and in SI13 is different!!!*/ psc_db->pbcch.pbcch_des.pb = si13->si13_rest_oct.si13_info.pbcch_des.pb; psc_db->pbcch.pbcch_des.tsc = si13->si13_rest_oct.si13_info.pbcch_des.tsc; psc_db->pbcch.pbcch_des.tn = si13->si13_rest_oct.si13_info.pbcch_des.tn; if((si13->si13_rest_oct.si13_info.pbcch_des.flag EQ FALSE) AND (si13->si13_rest_oct.si13_info.pbcch_des.flag2 EQ FALSE)) { psc_db->pbcch.pbcch_des.flag = FALSE; } else { psc_db->pbcch.pbcch_des.flag = TRUE; } psc_db->pbcch.pbcch_des.v_arfcn = si13->si13_rest_oct.si13_info.pbcch_des.v_arfcn; psc_db->pbcch.pbcch_des.arfcn = si13->si13_rest_oct.si13_info.pbcch_des.arfcn; psc_db->pbcch.pbcch_des.v_maio = si13->si13_rest_oct.si13_info.pbcch_des.v_maio; psc_db->pbcch.pbcch_des.maio = si13->si13_rest_oct.si13_info.pbcch_des.maio; } else { /* * No PBCCH description present in the SI13 message */ /* * Copy non PBCCH parameters: RAC, SPGC_CCCH_SUP, PRIORITY_ACCESS_THR, * NETWORK_CONTROL_ORDER */ /* Set RAC value */ psc_db->cell_info_for_gmm.cell_info.cell_env.rai.rac = si13->si13_rest_oct.si13_info.rac; psc_db->net_ctrl.spgc_ccch_supp.nw_supp = si13->si13_rest_oct.si13_info.spgc; psc_db->net_ctrl.priority_access_thr = si13->si13_rest_oct.si13_info.prio_acc_thr; /* * Copy NC measurement parameter */ { T_nc_meas_par nc_meas_par; nc_meas_par.ctrl_order = si13->si13_rest_oct.si13_info.nco; nc_meas_par.v_nc_meas_per = FALSE; /* * SI13 doesnt carry the nc meas parameters. So we should not reset/change the * parameters after receiving every SI13 periodic reading. */ if( (nc_meas_par.ctrl_order EQ NCMEAS_NC2) OR (nc_meas_par.ctrl_order EQ NCMEAS_NC1) ) { if ( (psc_db->nc_cw.param.rep_per_i NEQ NC_REP_PER_I_DEFAULT ) AND (psc_db->nc_cw.param.rep_per_t NEQ NC_REP_PER_T_DEFAULT) AND (psc_db->nc_cw.param.non_drx_per NEQ NC_NON_DRX_PER_DEFAULT) AND (psc_db->nc_cw.param.ctrl_order NEQ NC_NC0) AND (psc_db->nc_cw.param.idx NEQ NOT_SET) ) { nc_meas_par.nc_meas_per.non_drx_per = psc_db->nc_cw.param.non_drx_per; nc_meas_par.nc_meas_per.rep_per_i = psc_db->nc_cw.param.rep_per_i ; nc_meas_par.nc_meas_per.rep_per_t = psc_db->nc_cw.param.rep_per_t; nc_meas_par.v_nc_meas_per = TRUE; } } /* * Only one instance of SI13, store data in final location. */ grr_prcs_nc_param_struct ( &psc_db->nc_cw.param, &nc_meas_par, 0 ); } /* * Copy GPRS cell options */ psc_db->v_gprs_cell_opt = TRUE; /* * SZML-PSI/001 */ memcpy(&(psc_db->gprs_cell_opt), &(si13->si13_rest_oct.si13_info.gprs_cell_opt), sizeof(T_gprs_cell_opt)); if(si13->si13_rest_oct.si13_info.gprs_cell_opt.nmo EQ GMMRR_NET_MODE_III) { TRACE_EVENT("NMO III in network ----> GMMRR_NET_MODE_II"); psc_db->cell_info_for_gmm.cell_info.net_mode = GMMRR_NET_MODE_II; } else { psc_db->cell_info_for_gmm.cell_info.net_mode = si13->si13_rest_oct.si13_info.gprs_cell_opt.nmo; } /* * Copy power control parameters */ { T_si13_info *si13_info = &si13->si13_rest_oct.si13_info; psc_db->v_g_pwr_par = TRUE; psc_db->g_pwr_par.alpha = CLIP_ALPHA( si13_info->alpha ); psc_db->g_pwr_par.t_avg_w = CLIP_T_AVG( si13_info->t_avg_w ); psc_db->g_pwr_par.t_avg_t = CLIP_T_AVG( si13_info->t_avg_t ); psc_db->g_pwr_par.pb = 0; psc_db->g_pwr_par.pc_meas_chan = si13_info->pc_meas_chan; psc_db->g_pwr_par.imeas_chan_list = FALSE; psc_db->g_pwr_par.n_avg_i = si13_info->n_avg_i; grr_data->pwr_ctrl_valid_flags.v_glbl_pwr_ctrl_param = TRUE; } } }/* psi_copy_si13_params */ /* +------------------------------------------------------------------------------ | Function : psi_is_pbcch_des_different +------------------------------------------------------------------------------ | Description : The function checks whether PBCCH description of the received | PSI13 message is different from the stored one | | Parameters : T_PSI_13*; TRUE: If desc. are different FALSE: same | +------------------------------------------------------------------------------ */ LOCAL BOOL psi_is_pbcch_des_different(T_PSI_13* psi13) { TRACE_FUNCTION("psi_is_pbcch_des_different"); if(!psi13->flag) /* No PBCCH description present: PBCCH no longer available*/ return TRUE; /* compare PBCCH descriptions*/ if((psc_db->pbcch.pbcch_des.pb EQ psi13->psi1_pbcch_info.pbcch_des.pb) AND (psc_db->pbcch.pbcch_des.tsc EQ psi13->psi1_pbcch_info.pbcch_des.tsc) AND (psc_db->pbcch.pbcch_des.tn EQ psi13->psi1_pbcch_info.pbcch_des.tn)) { /* compare BCCH carrier-flag, if exists*/ if(psc_db->pbcch.pbcch_des.flag NEQ psi13->psi1_pbcch_info.pbcch_des.flag) return TRUE; /* compare non-hopping carrier, if exists: ARFCN*/ if( (psc_db->pbcch.pbcch_des.v_arfcn NEQ psi13->psi1_pbcch_info.pbcch_des.v_arfcn) OR (psc_db->pbcch.pbcch_des.arfcn NEQ psi13->psi1_pbcch_info.pbcch_des.arfcn) ) return TRUE; /* Compare hopping carrier, if exists: MAIO*/ if( (psc_db->pbcch.pbcch_des.v_maio NEQ psi13->psi1_pbcch_info.pbcch_des.v_maio) OR (psc_db->pbcch.pbcch_des.maio NEQ psi13->psi1_pbcch_info.pbcch_des.maio) ) return TRUE; } else { return TRUE; } return FALSE; }/* psi_is_pbcch_des_different*/ /* +------------------------------------------------------------------------------ | Function : psi_copy_psi13_params +------------------------------------------------------------------------------ | Description : The function copies psi13 parameters into sc_db | | Parameters : T_PSI_13* | +------------------------------------------------------------------------------ */ LOCAL void psi_copy_psi13_params(T_PSI_13* psi13) { TRACE_FUNCTION("psi_copy_psi13_params"); /* * Handle SI13_CHANGE_MARK and GPRS Mobile Allocation */ if(psi13->v_si13_cm_gprs_alloc) { psc_db->psi13_params.si13_change_mark = psi13->si13_cm_gprs_alloc.si13_cm; psi_copy_ma_from_psi13(&(psi13->si13_cm_gprs_alloc.gprs_ms_alloc_ie)); } grr_set_pbcch( psi13->flag ); if(psi13->flag) { /* * PBCCH description present in the PSI13 message */ psc_db->psi1_params.psi1_repeat_period = psi13->psi1_pbcch_info.psi1_rep_per + 1; memcpy(&(psc_db->pbcch.pbcch_des), &(psi13->psi1_pbcch_info.pbcch_des), sizeof(T_pbcch_des)); } else { /* * No PBCCH description present in the PSI13 message */ /* * Copy non PBCCH parameters: RAC, SPGC_CCCH_SUP, PRIORITY_ACCESS_THR */ /* Set RAC value */ psc_db->cell_info_for_gmm.cell_info.cell_env.rai.rac = psi13->pbcch_n_pres.rac; psc_db->net_ctrl.spgc_ccch_supp.nw_supp = psi13->pbcch_n_pres.spgc_ccch_sup; psc_db->net_ctrl.priority_access_thr = psi13->pbcch_n_pres.prio_acc_thr; /* * Copy NC measurement parameter */ { T_nc_meas_par nc_meas_par; nc_meas_par.ctrl_order = psi13->pbcch_n_pres.ctrl_order; nc_meas_par.v_nc_meas_per = FALSE; /* * Only one instance of PSI13, store data in final location. */ grr_prcs_nc_param_struct ( &psc_db->nc_cw.param, &nc_meas_par, 0 ); } /* * Copy GPRS cell options */ psc_db->v_gprs_cell_opt = TRUE; /* * SZML-PSI/002 */ memcpy(&(psc_db->gprs_cell_opt), &(psi13->pbcch_n_pres.gprs_cell_opt), sizeof(T_gprs_cell_opt)); psc_db->cell_info_for_gmm.cell_info.net_mode = psi13->pbcch_n_pres.gprs_cell_opt.nmo; /* * Copy power control parameters */ { T_psi13_pwr_par *pwr_par = &psi13->pbcch_n_pres.psi13_pwr_par; psc_db->v_g_pwr_par = TRUE; psc_db->g_pwr_par.alpha = CLIP_ALPHA( pwr_par->alpha); psc_db->g_pwr_par.t_avg_w = CLIP_T_AVG( pwr_par->t_avg_w ); psc_db->g_pwr_par.t_avg_t = CLIP_T_AVG( pwr_par->t_avg_t ); psc_db->g_pwr_par.pb = 0; psc_db->g_pwr_par.pc_meas_chan = pwr_par->pc_meas_chan; psc_db->g_pwr_par.imeas_chan_list = FALSE; psc_db->g_pwr_par.n_avg_i = pwr_par->n_avg_i; grr_data->pwr_ctrl_valid_flags.v_glbl_pwr_ctrl_param = TRUE; } } } /* psi_copy_psi13_params */ /* +------------------------------------------------------------------------------ | Function : psi_send_access_enable_if_needed +------------------------------------------------------------------------------ | Description : The function sends signal to CTRL to indicate that the access | is enabled | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void psi_send_access_enable_if_needed() { TRACE_FUNCTION("psi_send_access_enable_if_needed"); if(!psc_db->is_access_enabled) { psc_db->is_access_enabled = TRUE; sig_psi_ctrl_access_enabled( ); } #ifdef _TARGET_ else if(grr_is_pbcch_present()) { /* * Inform CTRL about new pccch, if there is a new one exists. * It may be the PBCCH and/or PCCCH description has been * changed, so that PCCCH reading should be started again. * If not this is not a big problem. This is done to avoid * saving PCCCH description in database to compare whether * it has been changed or not. */ TRACE_EVENT("Access enabled, PCCCH may have changed"); sig_psi_ctrl_new_pccch(); } #endif /* _TARGET_ */ #ifdef REL99 TRACE_EVENT_P2 ("pbbch %d, cbch_info %d", grr_is_pbcch_present(), psc_db->send_cbch_info_ind); if(grr_is_pbcch_present() AND psc_db->send_cbch_info_ind) { sig_psi_ctrl_cbch_info_ind(); psc_db->send_cbch_info_ind = FALSE; } #endif }/*psi_send_access_enable_if_needed */ /* +------------------------------------------------------------------------------ | Function : psi_initiate_read_complete_si +------------------------------------------------------------------------------ | Description : | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void psi_initiate_read_complete_si ( void ) { TRACE_FUNCTION( "psi_initiate_read_complete_si" ); psi_stop_60sec( TRUE ); psi_stop_30sec( TRUE ); sig_psi_ctrl_access_disabled( PSI_DC_OTHER ); } /* psi_initiate_read_complete_si */ /* +------------------------------------------------------------------------------ | Function : psi_initiate_read_complete_psi +------------------------------------------------------------------------------ | Description : | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void psi_initiate_read_complete_psi ( UBYTE init_needed ) { TRACE_FUNCTION( "psi_initiate_read_complete_psi" ); TRACE_EVENT( "PBCCH present" ); psi_stop_60sec( TRUE ); psi_stop_30sec( TRUE ); psi_update_data_to_request( init_needed ); sig_psi_ctrl_access_disabled( PSI_DC_READ_PSI ); } /* psi_initiate_read_complete_psi */ /* +------------------------------------------------------------------------------ | Function : psi_initiate_pbcch_switching +------------------------------------------------------------------------------ | Description : | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void psi_initiate_pbcch_switching ( T_PSI_DISABLE_CAUSE dc ) { TRACE_FUNCTION( "psi_initiate_pbcch_switching" ); if( psc_db->acq_type NEQ NONE ) { psi_stop_psi_reading(NONE); } sig_psi_ctrl_access_disabled( dc ); psi_stop_timer(); psi_init_params(); grr_set_pbcch( FALSE ); } /* psi_initiate_pbcch_switching */ /* +------------------------------------------------------------------------------ | Function : psi_store_ncell_param +------------------------------------------------------------------------------ | Description : | Parameters : +------------------------------------------------------------------------------ */ LOCAL UBYTE psi_store_ncell_param ( T_ncell_par *p_ncell_par, UBYTE c_ncell_par, UBYTE v_ncell_par, T_INFO_TYPE type, UBYTE instance ) { UBYTE i, j; UBYTE number = 0; USHORT last_freq; TRACE_FUNCTION( "psi_store_ncell_param" ); if( !v_ncell_par ) { switch ( type ) { case( INFO_TYPE_PSI3 ): TRACE_EVENT( "No ncell parameters in PSI3" ); break; case( INFO_TYPE_PSI3BIS ): TRACE_EVENT( "No ncell parameters in PSI3BIS" ); break; default: TRACE_EVENT( "Unexpected neighbour cell information source" ); break; } return( number ); /* no ncell parameters */ } switch ( type ) { case( INFO_TYPE_PSI3 ): case( INFO_TYPE_PSI3BIS ): break; default: TRACE_EVENT( "Unexpected neighbour cell information source" ); return( number ); } for( i = 0; i < c_ncell_par; i++ ) { last_freq = 0; if( grr_store_cs_param ( &psc_db->nc_cw.list, TRUE, &p_ncell_par[i].cs_par, type, instance, &number, &last_freq, p_ncell_par[i].start_freq, p_ncell_par[i].bsic ) EQ FALSE ) { TRACE_EVENT( "psi_store_ncell_param: NC_CW list full" ); return( number ); } for( j = 0; j < p_ncell_par[i].n_rest; j++ ) { if( grr_store_cs_param ( &psc_db->nc_cw.list, TRUE, &p_ncell_par[i].ncell_par_rest[j].cs_par, type, instance, &number, &last_freq, p_ncell_par[i].ncell_par_rest[j].freq_diff_struct.freq_diff, p_ncell_par[i].ncell_par_rest[j].bsic ) EQ FALSE ) { TRACE_EVENT( "psi_store_ncell_param: NC_CW list full" ); return( number ); } } } return( number ); }/* psi_store_ncell_param */ /* +------------------------------------------------------------------------------ | Function : psi_store_ncell_param2 +------------------------------------------------------------------------------ | Description : | Parameters : +------------------------------------------------------------------------------ */ LOCAL void psi_store_ncell_param2 ( T_PSI_3_BIS *psi3bis, UBYTE number ) { T_ncell_par2_s1 *p_sub_1; T_ncell_par2_s2 *p_sub_2; USHORT last_freq; UBYTE i, j, cell_params_ptr, x, y, n; TRACE_FUNCTION( "psi_store_ncell_param2" ); if( !psi3bis->ncell_par_trnc_grp.v_ncell_par2 ) { return; } for( i = 0; i < psi3bis->ncell_par_trnc_grp.c_ncell_par2; i++ ) { for( n = 0; n < psi3bis->ncell_par_trnc_grp.ncell_par2[i].c_ncell_par2_des; n++ ) { cell_params_ptr = psi3bis->ncell_par_trnc_grp.ncell_par2[i].ncell_par2_des[n].para_ptr; if( cell_params_ptr > psi3bis->ncell_par_trnc_grp.ncell_par2[i].c_ncell_par2_set ) { TRACE_ERROR( "cell_params_ptr > psi3bis->ncell_par2[i].c_ncell_par2_set" ); return; } for( j = 0; j < psi3bis->ncell_par_trnc_grp.ncell_par2[i].ncell_par2_des[n].c_ncell_par2_s1; j++ ) { last_freq = 0; p_sub_1 = &psi3bis->ncell_par_trnc_grp.ncell_par2[i].ncell_par2_des[n].ncell_par2_s1[j]; if( psi_store_cs_param2 ( &psc_db->nc_cw.list, &psi3bis->ncell_par_trnc_grp.ncell_par2[i].ncell_par2_set[cell_params_ptr], psi3bis->psi3bis_ind, &number, &last_freq, p_sub_1->start_freq, p_sub_1->same_ra_scell, p_sub_1->cell_ba, p_sub_1->bcc ) EQ FALSE ) { TRACE_EVENT( "psi_store_ncell_param2: NC_CW list full" ); return; } if( p_sub_1->n_r_cells NEQ 0 ) { y = p_sub_1->c_ncell_par2_s2; for( x = 0; x < y; x++ ) { p_sub_2 = &p_sub_1->ncell_par2_s2[x]; if( psi_store_cs_param2 ( &psc_db->nc_cw.list, &psi3bis->ncell_par_trnc_grp.ncell_par2[i].ncell_par2_set[cell_params_ptr], psi3bis->psi3bis_ind, &number, &last_freq, p_sub_2->freq_diff_struct.freq_diff, p_sub_2->same_ra_scell, p_sub_2->cell_ba, p_sub_2->bcc ) EQ FALSE ) { TRACE_EVENT( "psi_store_ncell_param2: NC_CW list full" ); return; } } } } } } } /* psi_store_ncell_param2 */ /* +------------------------------------------------------------------------------ | Function : psi_store_cs_param2 +------------------------------------------------------------------------------ | Description : | Parameters : +------------------------------------------------------------------------------ */ LOCAL BOOL psi_store_cs_param2 ( T_NC_LIST *nc_list, T_ncell_par2_set *cs_par2, UBYTE instance, UBYTE *number, USHORT *freq, USHORT freq_diff, UBYTE same_ra_scell, UBYTE cell_ba, UBYTE bcc ) { T_INFO_SRC info_src = 0; T_ncell_info *ncell_info; TRACE_FUNCTION( "psi_store_cs_param2" ); NC_SET_TYPE ( info_src, INFO_TYPE_PSI3BIS ); NC_SET_INSTANCE( info_src, instance ); NC_SET_NUMBER ( info_src, *number ); ncell_info = grr_get_next_ncell_param( MAX_NR_OF_NCELL, nc_list, info_src ); if( ncell_info EQ NULL ) { return( FALSE ); } number++; nc_list->number++; *freq = ( *freq + freq_diff ) % 1024; ncell_info->info_src = info_src; ncell_info->arfcn = *freq; if( cs_par2->v_ncc ) { ncell_info->bsic = bcc | ( cs_par2->ncc << 3 ); } else { ncell_info->bsic = bcc | ( psc_db->pbcch.bcch.bsic & BSIC_NCC_MASK ); } ncell_info->v_cr_par = TRUE; ncell_info->cr_par.same_ra_scell = same_ra_scell; ncell_info->cr_par.exc_acc = cs_par2->exc_acc; ncell_info->cr_par.cell_ba = cell_ba; #if !defined (NTRACE) if( grr_data->cs.v_crp_trace EQ TRUE ) { TRACE_EVENT_P2( "psi_store_cs_param2: cell barred status %d %d", ncell_info->arfcn, ncell_info->cr_par.cell_ba ); } #endif /* #if !defined (NTRACE) */ SET_GPRS_RXLEV_ACCESS_MIN ( ncell_info->cr_par.cr_par_1.cr_pow_par.gprs_rxlev_access_min, cs_par2->v_gprs_rxlev_access_min, cs_par2->gprs_rxlev_access_min ); SET_GPRS_MS_TXPWR_MAX_CCH ( ncell_info->cr_par.cr_par_1.cr_pow_par.gprs_ms_txpwr_max_cch, cs_par2->v_txpwr_max_cch, cs_par2->txpwr_max_cch ); SET_GPRS_TEMP_OFFSET ( ncell_info->cr_par.cr_offset.gprs_temp_offset, TRUE, cs_par2->gprs_temp_offset ); SET_GPRS_PENALTY_TIME ( ncell_info->cr_par.cr_offset.gprs_penalty_time, TRUE, cs_par2->gprs_penalty_time ); SET_GPRS_RESEL_OFF ( ncell_info->cr_par.gprs_resel_off, TRUE, cs_par2->gprs_resel_off ); ncell_info->cr_par.cr_par_1.v_hcs_par = ( cs_par2->v_gprs_hcs_thr AND cs_par2->v_gprs_prio_class ); SET_GPRS_HCS_THR ( ncell_info->cr_par.cr_par_1.hcs_par.gprs_hcs_thr, cs_par2->v_gprs_hcs_thr, cs_par2->gprs_hcs_thr ); SET_GPRS_PRIO_CLASS ( ncell_info->cr_par.cr_par_1.hcs_par.gprs_prio_class, cs_par2->v_gprs_prio_class, cs_par2->gprs_prio_class ); grr_store_si13_pbcch_location( &ncell_info->cr_par, cs_par2->v_si13_pbcch, &cs_par2->si13_pbcch ); return( TRUE ); }/* psi_store_cs_param2 */ /* +------------------------------------------------------------------------------ | Function : psi_restore_ncell_param +------------------------------------------------------------------------------ | Description : | Parameters : +------------------------------------------------------------------------------ */ LOCAL void psi_restore_ncell_param ( void ) { UBYTE idx_curr = 0; T_ncell_info *info_prev = NULL; T_ncell_info *info_curr; T_INFO_SRC info_src = 0; TRACE_FUNCTION( "psi_restore_ncell_param" ); /* update change mark value */ psc_db->nc_cw.list.chng_mrk.curr++; while( ( info_curr = grr_get_next_bigger_ncell_param ( &psc_db->nc_cw.list, info_src ) ) NEQ NULL ) { grr_restore_cs_param( info_curr, info_prev, idx_curr ); info_src = info_curr->info_src; info_prev = info_curr; idx_curr++; } }/* psi_restore_ncell_param */ /* +------------------------------------------------------------------------------ | Function : psi_prepare_scell_pbcch_req +------------------------------------------------------------------------------ | Description : The function psi_prepare_scell_pbcch_req() prepares the mphp_ | scell_pbcch_req | | Parameters : T_MPHP_SCELL_PBCCH_REQ *mphp_scell_pbcch_req | UBYTE psi_reading_type | +------------------------------------------------------------------------------ */ GLOBAL void psi_prepare_scell_pbcch_req(T_MPHP_SCELL_PBCCH_REQ *mphp_scell_pbcch_req, UBYTE psi_reading_type) { #ifndef _TARGET_ UBYTE i, j; #endif /* #ifndef _TARGET_ */ UBYTE hr, lr, *psi_nr; UBYTE *pos_array; TRACE_FUNCTION( "psi_prepare_scell_pbcch_req" ); memcpy(mphp_scell_pbcch_req,&psc_db->scell_pbcch,sizeof(T_MPHP_SCELL_PBCCH_REQ)); psi_nr = &mphp_scell_pbcch_req->psi_nr; pos_array = mphp_scell_pbcch_req->relative_pos_array; *psi_nr = 0; memset(pos_array, 0, MAX_RELATIVE_POS); hr = psc_db->psi1_params.psi_cnt_hr; lr = psc_db->psi1_params.psi_cnt_lr; TRACE_EVENT_P1("psi_reading_type:%d", psi_reading_type); switch(psi_reading_type) { case READ_COMPLETE: /* attempt to receive messages shall be made each time * the message is scheduled on the broadcast channel. */ mphp_scell_pbcch_req->psi_nr = 0;/*read all PSI in all PBCCH*/ /* * mphp_scell_pbcch_req->relative_pos_array has no meaning, * if we want to receive all PSI */ psi_reset_psi_pos(); break; case READ_PSI1_IN_PSI1_REPEAT_PERIODS: /* attempt to receive PSI1 each time * the message is scheduled on the broadcast channel * with psi1_repeat_periods (only once in a multiframe, e.g. in PBCCH->B0) */ /* mphp_scell_pbcch_req->relative_pos_array will contain only one element, * because of mphp_scell_pbcch_req.psi_nr = 1 */ mphp_scell_pbcch_req->psi_nr = 1; /*Read PSI1 only in BO in psi1 repeat period */ mphp_scell_pbcch_req->relative_pos_array[0] = 0; break; case PSI_IN_HR: /* PSI in high repetition rate*/ if(!hr) /* no HR */ { TRACE_ERROR("no HR, read all"); mphp_scell_pbcch_req->psi_nr = 0;/*read all PSI in all PBCCH*/ } else { #ifdef _TARGET_ mphp_scell_pbcch_req->psi_nr = 0; #else mphp_scell_pbcch_req->psi_nr = 0; i = (mphp_scell_pbcch_req->bs_pbcch_blks > 0) ? 1 : 0; while(hr > 0) { mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr] = i + hr; if(mphp_scell_pbcch_req->psi_nr EQ 19) break;/* break condition*/ mphp_scell_pbcch_req->psi_nr++; hr--; } #endif } break; case PSI_IN_LR: /* PSI in low repetition rate */ if(!lr) /* no LR */ { TRACE_ERROR("no LR, read all"); mphp_scell_pbcch_req->psi_nr = 0;/*read all PSI in all PBCCH*/ } else { #ifdef _TARGET_ mphp_scell_pbcch_req->psi_nr = 0; #else mphp_scell_pbcch_req->psi_nr = 0; i = (mphp_scell_pbcch_req->bs_pbcch_blks > 0) ? 1 : 0; while(lr > 0) { mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr] = i + hr + lr; if(mphp_scell_pbcch_req->psi_nr EQ 19) break;/* break condition*/ mphp_scell_pbcch_req->psi_nr++; lr--; } #endif } break; case PSI_IN_HR_AND_LR: /* PSI in high and low repetition rate*/ if(!(lr + hr)) /* no LR+HR */ { TRACE_ERROR("no HR+LR, read all"); mphp_scell_pbcch_req->psi_nr = 0;/*read all PSI in all PBCCH*/ } else { #ifdef _TARGET_ mphp_scell_pbcch_req->psi_nr = 0; #else mphp_scell_pbcch_req->psi_nr = 0; i = (mphp_scell_pbcch_req->bs_pbcch_blks > 0) ? 2 : 1; for(j=0; j<(lr + hr);j++) { mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr] = i + j; if(mphp_scell_pbcch_req->psi_nr EQ 19) break;/* break condition*/ mphp_scell_pbcch_req->psi_nr++; } #endif } break; case READ_PSI1_AND_IN_HR: /* PSI in high repetition rate and PSI1*/ #ifdef _TARGET_ mphp_scell_pbcch_req->psi_nr = 0; #else mphp_scell_pbcch_req->psi_nr = 0; mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr++] = 0; i = (mphp_scell_pbcch_req->bs_pbcch_blks > 0) ? 1 : 0; if(i EQ 1) { mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr++] = 1; } while(hr > 0) { mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr] = i + hr; if(mphp_scell_pbcch_req->psi_nr EQ 19) break;/* break condition*/ mphp_scell_pbcch_req->psi_nr++; hr--; } #endif break; case READ_PSI1_AND_IN_LR:/* PSI in low repetition rate and PSI1*/ #ifdef _TARGET_ mphp_scell_pbcch_req->psi_nr = 0; #else mphp_scell_pbcch_req->psi_nr = 0; mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr++] = 0; i = (mphp_scell_pbcch_req->bs_pbcch_blks > 0) ? 1 : 0; if(i EQ 1) { mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr++] = 1; } while(lr > 0) { mphp_scell_pbcch_req->relative_pos_array[mphp_scell_pbcch_req->psi_nr] = i + hr + lr; if(mphp_scell_pbcch_req->psi_nr EQ 19) break;/* break condition*/ mphp_scell_pbcch_req->psi_nr++; lr--; } #endif break; case READ_PSI2: #ifdef _TARGET_ mphp_scell_pbcch_req->psi_nr = 0; #else psi_fill_rel_pos(grr_data->psi.psi2_pos, MAX_NR_OF_INSTANCES_OF_PSI2, psi_nr, pos_array); #endif break; #if defined (REL99) AND defined (TI_PS_FF_EMR) case READ_PSI3TER: case READ_PSI3_3BIS_3TER: #endif case READ_PSI3_3BIS: #if defined (REL99) AND defined (TI_PS_FF_EMR) case READ_PSI3BIS: #endif #ifdef _TARGET_ mphp_scell_pbcch_req->psi_nr = 0; #else #if defined (REL99) AND defined (TI_PS_FF_EMR) psi_fill_rel_pos(grr_data->psi.psi3_set_pos, MAX_NR_OF_INSTANCES_OF_PSI3TER + MAX_NR_OF_INSTANCES_OF_PSI3 + MAX_NR_OF_INSTANCES_OF_PSI3BIS, psi_nr, pos_array); #else psi_fill_rel_pos(grr_data->psi.psi3bis_pos, MAX_NR_OF_INSTANCES_OF_PSI3 + MAX_NR_OF_INSTANCES_OF_PSI3BIS, psi_nr, pos_array); #endif /* #ifdef REL99 AND TI_PS_FF_EMR */ #endif /* ifdef _TARGET_ */ break; case READ_PSI4: #ifdef _TARGET_ mphp_scell_pbcch_req->psi_nr = 0; #else psi_fill_rel_pos(grr_data->psi.psi4_pos, MAX_NR_OF_INSTANCES_OF_PSI4, psi_nr, pos_array); #endif break; case READ_PSI5: #ifdef _TARGET_ mphp_scell_pbcch_req->psi_nr = 0; #else psi_fill_rel_pos(grr_data->psi.psi5_pos, MAX_NR_OF_INSTANCES_OF_PSI5, psi_nr, pos_array); #endif break; #ifdef REL99 case READ_PSI8: #ifdef _TARGET_ mphp_scell_pbcch_req->psi_nr = 0; #else psi_fill_rel_pos(grr_data->psi.psi8_pos, MAX_NR_OF_INSTANCES_OF_PSI8, psi_nr, pos_array); #endif break; #endif default: TRACE_ERROR ("default in psi_prepare_scell_pbcch_req"); break; } TRACE_EVENT_P7("psi_nr:%d blks:%d pb:%d per:%d pos[0]:%d pos[1]:%d pos[2]:%d", mphp_scell_pbcch_req->psi_nr, mphp_scell_pbcch_req->bs_pbcch_blks, mphp_scell_pbcch_req->pb, mphp_scell_pbcch_req->psi1_rep_period, mphp_scell_pbcch_req->relative_pos_array[0], mphp_scell_pbcch_req->relative_pos_array[1], mphp_scell_pbcch_req->relative_pos_array[2]); TRACE_EVENT_P4("tn:%d tsc:%d hop:%d arfcn:%d", mphp_scell_pbcch_req->p_ch_des.tn, mphp_scell_pbcch_req->p_ch_des.tsc, mphp_scell_pbcch_req->p_ch_des.p_chan_sel.hopping, mphp_scell_pbcch_req->p_ch_des.p_chan_sel.p_rf_ch.arfcn); TRACE_EVENT_P5("f_cnt:%d f1:%d f2:%d f3:%d f4:%d", mphp_scell_pbcch_req->p_freq_list.p_rf_chan_cnt, mphp_scell_pbcch_req->p_freq_list.p_rf_chan_no.p_radio_freq[0], mphp_scell_pbcch_req->p_freq_list.p_rf_chan_no.p_radio_freq[1], mphp_scell_pbcch_req->p_freq_list.p_rf_chan_no.p_radio_freq[2], mphp_scell_pbcch_req->p_freq_list.p_rf_chan_no.p_radio_freq[3]); } /* psi_prepare_scell_pbcch_req */ /* +------------------------------------------------------------------------------ | Function : psi_store_rel_pos +------------------------------------------------------------------------------ | Description : The function psi_store_rel_pos () .stores the values relative | position for each PSI message | Parameters : dest: destination array; rel_pos: relative position; max_dest: | MAX size OF dest array | +------------------------------------------------------------------------------ */ GLOBAL void psi_store_rel_pos(UBYTE *dest, UBYTE rel_pos, UBYTE max_dest) { UBYTE i; TRACE_FUNCTION("psi_store_rel_pos"); for ( i = 0; i < max_dest; i++) { if(dest[i] EQ 0xFF) { dest[i] = rel_pos; break; } } }/*psi_store_rel_pos*/ #ifndef _TARGET_ /* +------------------------------------------------------------------------------ | Function : psi_fill_rel_pos +------------------------------------------------------------------------------ | Description : The function psi_fill_rel_pos () .fills the relative position | array and sets the psi_number | Parameters : src: array containing rel positions; max_src: MAX size of src | psi_nr: ptr to psi_number; pos_array: ptr to position_array | +------------------------------------------------------------------------------ */ LOCAL void psi_fill_rel_pos(UBYTE *src, UBYTE max_src, UBYTE *psi_nr, UBYTE *pos_array) { UBYTE i; TRACE_FUNCTION("psi_fill_rel_pos"); for(i = 0; i<max_src; i++) { if(src[i] NEQ 0xff) { pos_array[(*psi_nr)] = src[i]; (*psi_nr)++; } } }/*psi_fill_rel_pos*/ #endif /*_TARGET_*/ /* +------------------------------------------------------------------------------ | Function : psi_reset_psi_pos +------------------------------------------------------------------------------ | Description : The function spsi_reset_psi_pos () .... | | Parameters : - | +------------------------------------------------------------------------------ */ LOCAL void psi_reset_psi_pos ( void ) { TRACE_FUNCTION( "psi_reset_psi_pos " ); memset(grr_data->psi.psi2_pos, 0xFF, MAX_NR_OF_INSTANCES_OF_PSI2); #if defined (REL99) AND defined (TI_PS_FF_EMR) memset(grr_data->psi.psi3_set_pos, 0xFF, MAX_NR_OF_INSTANCES_OF_PSI3TER +MAX_NR_OF_INSTANCES_OF_PSI3BIS+MAX_NR_OF_INSTANCES_OF_PSI3); #else memset(grr_data->psi.psi3bis_pos, 0xFF, MAX_NR_OF_INSTANCES_OF_PSI3BIS+MAX_NR_OF_INSTANCES_OF_PSI3); #endif memset(grr_data->psi.psi4_pos, 0xFF, MAX_NR_OF_INSTANCES_OF_PSI4); memset(grr_data->psi.psi5_pos, 0xFF, MAX_NR_OF_INSTANCES_OF_PSI5); #ifdef REL99 memset(grr_data->psi.psi8_pos, 0xFF, MAX_NR_OF_INSTANCES_OF_PSI8); #endif } /* psi_reset_psi_pos () */ #ifdef REL99 /* +------------------------------------------------------------------------------ | Function : psi_update_bss_sgsn_rel +------------------------------------------------------------------------------ | Description : The function psi_update_bss_sgsn_rel () updates BSS and SGSN | releases during the processing of SI13 message. | | Parameters : SI13 message, status of PBCCH presence in the cell | +------------------------------------------------------------------------------ */ LOCAL void psi_update_bss_sgsn_rel ( T_D_SYS_INFO_13 *si13, BOOL pbcch_status ) { TRACE_FUNCTION( "psi_update_bss_sgsn_rel " ); /* Update the BSS release */ if (si13->si13_rest_oct.si13_info.v_sgsnr) { psc_db->network_rel = BSS_NW_REL_99; psc_db->sgsn_rel = si13->si13_rest_oct.si13_info.sgsnr ? PS_SGSN_99_ONWARDS : PS_SGSN_98_OLDER; } else { psc_db->network_rel = BSS_NW_REL_97; if(pbcch_status EQ PBCCH_NOT_PRESENT) { psc_db->sgsn_rel = PS_SGSN_98_OLDER; } else { psc_db->sgsn_rel = PS_SGSN_UNKNOWN; } } /* Update the SGSN release in the Common library context */ cl_nwrl_set_sgsn_release(psc_db->sgsn_rel); } /* psi_update_bss_sgsn_rel () */ #endif