FreeCalypso > hg > freecalypso-sw
view gsm-fw/g23m-gsm/rr/rr_cs.c @ 815:15cf4a8961d0
aci: sap_dti.c and sap_em.c done
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Sun, 05 Apr 2015 08:17:09 +0000 |
parents | 458366ab2d6d |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : | Modul : +----------------------------------------------------------------------------- | 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 defines the functions for Cell Selection | capability of Radio Resource. +----------------------------------------------------------------------------- */ #ifndef RR_CS_C #define RR_CS_C #include "config.h" #include "fixedconf.h" #include "condat-features.h" #define ENTITY_RR /*==== INCLUDES ===================================================*/ #include <string.h> #include <stdlib.h> #include <stddef.h> /* offsetof */ #include "typedefs.h" #include "pcm.h" #include "pconst.cdg" #include "mconst.cdg" #include "message.h" #include "ccdapi.h" #include "vsi.h" #include "custom.h" #include "gsm.h" #include "prim.h" #include "cnf_rr.h" #include "tok.h" #include "rr.h" /*==== EXPORT =====================================================*/ /*==== PRIVATE ====================================================*/ static void cs_remove_co_chan (USHORT arfcn, USHORT co_arfcn); static void cs_remove_co_channels (USHORT arfcn); static UBYTE cs_check_channel (USHORT arfcn); static BOOL cs_sync_next_bsic (void); /*==== VARIABLES ==================================================*/ EXTERN UBYTE test_house; /*==== FUNCTIONS ==================================================*/ LOCAL void cs_add_current_network_to_found_list (); LOCAL BOOL cs_check_black_list_criteria(U8 region, U16 arfcn, U8 rxlev); LOCAL BOOL cs_is_in_black_list(U8 region, U16 arfcn); LOCAL BOOL cs_is_in_white_list(U8 region, U16 arfcn); LOCAL U8 cs_get_sync_fail_counter(U8 region, U16 arfcn); LOCAL void cs_reset_sync_fail_counter(U8 region, U16 arfcn); LOCAL void cs_inc_sync_fail_counter(U8 region, U16 arfcn); LOCAL void cs_use_white_list_info(U8 num_of_chan); #ifdef TI_PS_FF_QUAD_BAND_SUPPORT LOCAL UBYTE cs_update_std_ffs (UBYTE new_std); #else LOCAL UBYTE get_band_index(USHORT arfcn); #endif /* * ------------------------------------------------------------------- * Procedures * ------------------------------------------------------------------- */ /* * The cell selection process bases on attributes for each channel * of the power campaign. This attributes are defined by a bitmap * * Bit 1 0 priority * --------------------------------- * 0 0 low priority * 0 1 mid priority * 1 0 high priority * 1 1 reserved * * The selection of a cell for synchronisation depends on * the priority and the fieldstrength. It will be the cell * selected, which is not checked yet, has the highest * priority and the highest fieldstrength. * * Bit 2 reserved * * Bit 3 checked flag * --------------------------------- * 0 cell is not checked * 1 cell is checked * * The flag indicates whether a cell is already checked or not. * * Bit 4 detected flag * --------------------------------- * 0 bcch is not detected * 1 bcch is checked * * The flag indicates whether a BCCH is detected or not. * * Bit 5 emergency cell flag * --------------------------------- * 0 emergency services possible * 1 emergency services not possible * * The flag indicates whether emergency services are possible or not. * * Bit 6 low priority cell flag * --------------------------------- * 0 no low priority cell * 1 low priority cell * * The flag indicates whether a cell has a low priority or not. * * Bit 8 BCCH info list flag * --------------------------------- * 0 not member of the BCCH info list * 1 member of the BCCH info list * * The flag indicates whether a cell is member of the BCCH information * list or not. */ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_init_process | +--------------------------------------------------------------------+ PURPOSE : Initialisation of the cell selection process. Called from 'pei_init' exclusively and rr_deactivate. */ GLOBAL void cs_init_process (void) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cs_init_process()"); /* * set the state and clear all variables. */ SET_STATE (STATE_CELL_SEL, CS_NULL); memset (&rr_data->cs_data, 0, sizeof (&rr_data->cs_data)); rr_data->cs_data.arfcn_sc = NOT_PRESENT_16BIT; rr_data->cs_data.arfcn_cr = NOT_PRESENT_16BIT; /* CSI-LLD section:4.1.1.11 */ rr_data->cs_data.initial_plmn_search = INITIAL_PLMN_SEARCH_NOT_ACTIVE; /* In all simulation testcases written prior to cell selection * improvements feature, US_BIT and STD values were not set in * the ARFCN field */ #if !defined (_SIMULATION_) rr_data->cs_data.region = NOT_PRESENT_8BIT; #endif rr_data->cs_data.white_list.last_sc_arfcn = NOT_PRESENT_16BIT; rr_data->cs_data.white_list.region = NOT_PRESENT_8BIT; TRACE_EVENT_P1("white_list_region %d", rr_data->cs_data.white_list.region); rr_data->start_cell_reselection = TRUE; TRACE_EVENT_P1("start_cell_reselection %d", rr_data->start_cell_reselection); /* Dynamic configuration parameters */ rr_data->dyn_config.bl_cs_en = TRUE; rr_data->dyn_config.tfast_cs_val = TFAST_CS_VALUE; rr_data->dyn_config.tnormal_cs_val = TNORMAL_CS_VALUE; rr_data->dyn_config.lim_ser_nps_delay= DELAY_NON_PAR_SEARCH_LIM_SER; #if defined(_SIMULATION_FFS_) rr_csf_ffs_init(); #endif } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_set_bcch_info | +--------------------------------------------------------------------+ PURPOSE : The function merges bcch information from SIM to White list database CSI-LLD - 4.1.2.2.1 */ GLOBAL void cs_set_bcch_info (T_bcch_info * sim_bcch_info) { GET_INSTANCE_DATA; T_LIST tmp_list; BUF_neigh_cell_desc cd; TRACE_FUNCTION ("cs_set_bcch_info()"); /* Check for availability of sim_bcch_info data */ if(cs_check_region(rr_data->cs_data.white_list.region) AND (sim_bcch_info NEQ NULL)) { if(sim_bcch_info->v_bcch) { /* Store the sim_bcch_info data to white_list structure */ memcpy(cd.b_neigh_cell_desc,sim_bcch_info->bcch,BA_BITMAP_SIZE); cd.o_neigh_cell_desc = 0; cd.l_neigh_cell_desc = NCELL_DESC_BIT_LEN; /* Merge BCCH info into white list */ for_create_channel_list((T_f_range *)&cd,&tmp_list); srv_merge_list(&rr_data->cs_data.white_list.list,&tmp_list); } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_clear_white_list | +--------------------------------------------------------------------+ PURPOSE : The function clears the bcch information (neigbour cell description) of sys info 2, 2bis and 2ter stored in RAM and FFS. CSI-LLD - 4.1.2.2.6 */ GLOBAL void cs_clear_white_list(U8 clr_bcch_info) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cs_clear_white_list()"); if (clr_bcch_info & CLR_WHITE_LIST_SIM) { dat_send_bcchinfo_mm (NULL); TRACE_EVENT ("White List: SIM cleared"); } if (clr_bcch_info & CLR_WHITE_LIST_RAM) { rr_data->cs_data.arfcn_sc = NOT_PRESENT_16BIT; rr_data->cs_data.arfcn_cr = NOT_PRESENT_16BIT; memset(&rr_data->cs_data.white_list, 0 , sizeof(T_CS_WHITE_LIST)); rr_data->cs_data.white_list.last_sc_arfcn = NOT_PRESENT_16BIT; rr_data->cs_data.white_list.region = NOT_PRESENT_8BIT; TRACE_EVENT ("White List: RAM cleared"); } #if defined (_SIMULATION_FFS_) if (clr_bcch_info & CLR_WHITE_LIST_FFS) { T_CS_WHITE_LIST white_list; memset(&white_list,0,sizeof(T_CS_WHITE_LIST)); rr_data->cs_data.white_list.region = NOT_PRESENT_8BIT; rr_data->cs_data.white_list.last_sc_arfcn = NOT_PRESENT_16BIT; rr_csf_write_white_list(&white_list); TRACE_EVENT ("White List: FFS cleared"); } #endif /* _SIMULATION_FFS_ */ } #if defined (_SIMULATION_FFS_) /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_store_white_list | +--------------------------------------------------------------------+ PURPOSE : The function stores while list information to FFS. CSI-LLD - 4.1.2.2.3 */ GLOBAL void cs_store_white_list (void) { GET_INSTANCE_DATA; /* Store the white List to FFS */ rr_csf_write_white_list(&rr_data->cs_data.white_list); } #endif /*_SIMULATION_FFS_*/ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_use_white_list_info | +--------------------------------------------------------------------+ PURPOSE : The function uses the stored white list information and increases the priority of these channels. CSI-LLD - 4.1.2.2.8 */ LOCAL void cs_use_white_list_info(U8 num_of_chan) { GET_INSTANCE_DATA; U8 i, priority; TRACE_FUNCTION ("cs_use_white_list_info()"); /* Boot Time: If white list is invalidated by the second activate_req, * decrease priority of white list carriers in power_cnf */ priority = (cs_check_region(rr_data->cs_data.white_list.region)) ? CS_HIGH_PRIORITY : CS_LOW_PRIORITY ; for (i=0;i<num_of_chan;i++) { /* * Power cnf always contains White list carriers at the top */ rr_data->cs_data.attributes [i] = priority; TRACE_EVENT_P3 ("Whie List: change prio of [%d]%u to 0x%02x", rr_data->cs_data.arfcn[i]&ARFCN_MASK, i, rr_data->cs_data.attributes [i]); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_set_all | +--------------------------------------------------------------------+ PURPOSE : The function clears all attributes and all stored BCCH information. */ GLOBAL void cs_set_all (void) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cs_set_all()"); /* * clear all attributes */ memset (&rr_data->cs_data.attributes, 0, sizeof (rr_data->cs_data.attributes)); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_set_freq_band | +--------------------------------------------------------------------+ PURPOSE : This function sets the frequency band bit mask. */ GLOBAL UBYTE cs_get_freq_band (UBYTE pch_interrupt) { UBYTE freq_bands; rr_csf_get_freq_bands (&freq_bands); if (!pch_interrupt) { /* * Power measurements without PCH interruption => PLMN search * ---------------------------------------------------------- * In this case we use the found and set value of 'std' for the frequency * area to mask out not available frequencies from 'freq_bands'. * Use only frequencies of the current area. */ switch (std) { case STD_900: freq_bands &= BAND_GSM_900; break; case STD_EGSM: freq_bands &= BAND_E_GSM; /* BAND_GSM_900|BAND_E_GSM */ break; case STD_1900: freq_bands &= BAND_PCS_1900; break; case STD_1800: freq_bands &= BAND_DCS_1800; break; case STD_DUAL: freq_bands &= BAND_DUAL; /* BAND_GSM_900|BAND_DCS_1800 */ break; case STD_DUAL_EGSM: freq_bands &= BAND_DUAL_EXT; /* BAND_GSM_900|BAND_E_GSM|BAND_DCS_1800 */ break; case STD_850: freq_bands &= BAND_GSM_850; break; case STD_DUAL_US: freq_bands &= BAND_DUAL_US; /* BAND_GSM_850|BAND_PCS_1900 */ break; #ifdef TI_PS_FF_QUAD_BAND_SUPPORT case STD_850_1800: freq_bands &= BAND_850_1800; /* BAND_GSM_850|BAND_DCS_1800 */ break; case STD_900_1900: freq_bands &= BAND_900_1900; /* BAND_E_GSM|BAND_PCS_1900 */ break; case STD_850_900_1800: freq_bands &= BAND_850_900_1800; /* BAND_E_GSM|BAND_GSM_850|BAND_DCS_1800 */ break; case STD_850_900_1900: freq_bands &= BAND_850_900_1900; /* BAND_GSM_850|BAND_E_GSM|BAND_PCS_1900 */ break; #endif } } return freq_bands; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : get_band_index | +--------------------------------------------------------------------+ PURPOSE : The function extracts the frequency band index from the given 'arfcn' parameter. */ #ifdef TI_PS_FF_QUAD_BAND_SUPPORT GLOBAL UBYTE cs_get_band_index (USHORT arfcn) #else GLOBAL UBYTE get_band_index (USHORT arfcn) #endif { UBYTE local_std = STD_GET_FROM_ARFCN(arfcn); UBYTE sc_band; if(local_std EQ STD_NOT_PRESENT) { /* Parallel search case */ #ifdef TI_PS_FF_QUAD_BAND_SUPPORT local_std = std; #else local_std = std_bands[std-1]; #endif } switch (local_std) { case STD_900: sc_band = B_GSM_900; break; case STD_EGSM: sc_band = B_E_GSM; break; case STD_1800: sc_band = B_DCS_1800; break; case STD_1900: sc_band = B_PCS_1900; break; case STD_850: sc_band = B_GSM_850; break; case STD_DUAL: if (arfcn >= LOW_CHANNEL_1800) sc_band = B_DCS_1800; else sc_band = B_GSM_900; break; case STD_DUAL_EGSM: if (arfcn >= LOW_CHANNEL_EGSM) sc_band = B_E_GSM; else if (arfcn >= LOW_CHANNEL_1800) sc_band = B_DCS_1800; else if (arfcn EQ CHANNEL_0) sc_band = B_E_GSM; else sc_band = B_GSM_900; break; case STD_DUAL_US: if (arfcn >= LOW_CHANNEL_1900) sc_band = B_PCS_1900; else sc_band = B_GSM_850; break; #ifdef TI_PS_FF_QUAD_BAND_SUPPORT case STD_850_1800: if (arfcn >= LOW_CHANNEL_1800) sc_band = B_DCS_1800; else sc_band = B_GSM_850; break; case STD_900_1900: if (arfcn >= LOW_CHANNEL_EGSM) sc_band = B_E_GSM; else if (arfcn >= LOW_CHANNEL_1900) sc_band = B_PCS_1900; else if (arfcn EQ CHANNEL_0) sc_band = B_E_GSM; else sc_band = B_GSM_900; break; case STD_850_900_1800: if (arfcn >= LOW_CHANNEL_EGSM) sc_band = B_E_GSM; else if (arfcn >= LOW_CHANNEL_1800) sc_band = B_DCS_1800; else if (arfcn EQ CHANNEL_0) sc_band = B_E_GSM; else if (arfcn >= LOW_CHANNEL_850) sc_band = B_GSM_850; else sc_band = B_GSM_900; break; case STD_850_900_1900: if (arfcn >= LOW_CHANNEL_EGSM) sc_band = B_E_GSM; else if (arfcn >= LOW_CHANNEL_1900) sc_band = B_PCS_1900; else if (arfcn EQ CHANNEL_0) sc_band = B_E_GSM; else if (arfcn >= LOW_CHANNEL_850) sc_band = B_GSM_850; else sc_band = B_GSM_900; break; #endif default: sc_band = MAX_NUM_BANDS; break; } /* this trace causes a lot of trace load; switch on only if needed TRACE_EVENT_P3 (" [%u] std=%02x, sc_band=%02x", arfcn&ARFCN_MASK, local_std, sc_band); */ return sc_band; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_start_scan | +--------------------------------------------------------------------+ PURPOSE : This function starts the scanning. The power measurements are triggered. Power measurements means that layer 1 performs fieldstrength measurements on all carriers and sends a list of the best to RR back for FB/SB scanning and BCCH reading. There are two variants: with or without paging channel (PCH) interruption. If RR is already in idle mode, scanning without PCH interruption is performed, that means the MS is pageable during that time. */ GLOBAL void cs_start_scan () { GET_INSTANCE_DATA; U16 arfcn; U8 i=0; U8 region; PALLOC (mph_power_req, MPH_POWER_REQ);/* T_MPH_POWER_REQ */ TRACE_FUNCTION ("cs_start_scan()"); memset(mph_power_req,0,sizeof(T_MPH_POWER_REQ )); TIMERSTOP (TREG); rr_data->cs_data.act_index = NOT_PRESENT_8BIT; switch (GET_STATE (STATE_CELL_SEL)) { case CS_NULL: case CS_NULL_ACTIVE: /* * start power measurements with PCH interruption */ mph_power_req->pch_interrupt = PCH_INTERRUPT; rr_data->first_meas_received = FALSE; rr_data->resel_pending = FALSE; rr_data->c_ncell_bcch = NOT_INITIALISED; rr_data->cs_data.all_freq_area = FALSE; /* In all simulation testcases written prior to cell selection * improvements feature, US_BIT and STD values were not set in * the ARFCN field */ #if !defined (_SIMULATION_) rr_data->cs_data.region = NOT_PRESENT_8BIT; #endif dat_att_null (); SET_STATE (STATE_CELL_SEL, CS_NULL_ACTIVE); /* stop possibly parallel search and allow start of cell reselection */ att_notify_stop_plmn_search (FALSE); break; case CS_IDLE: case CS_IDLE_ACTIVE: /* * start power measurements without PCH interruption. */ mph_power_req->pch_interrupt = NO_PCH_INTERRUPT; SET_STATE (STATE_CELL_SEL, CS_IDLE_ACTIVE); /* indicate suspend state of nc monitoring in lower layer */ rr_data->start_cell_reselection = FALSE; TRACE_EVENT_P1("start_cell_reselection %d", rr_data->start_cell_reselection); break; default: break; } #ifndef TI_PS_FF_QUAD_BAND_SUPPORT mph_power_req->freq_bands = cs_get_freq_band (mph_power_req->pch_interrupt); #endif /* CSI-LLD : 4.1.3.4.1.4 */ /* Set the new search mode */ mph_power_req->search_mode = CS_GET_CURRENT_SEARCH_MODE; /* Set Lower Rxlev threshold */ memcpy( mph_power_req->lower_rxlevel_threshold, rr_data->dyn_config.lower_rxlev_thr, MAX_NUM_BANDS*sizeof(UBYTE)); /* Copy the black list information */ for(i=0;i<MAX_REGIONS;i++) { srv_copy_list ((T_LIST *)&mph_power_req->black_list.list[i], &rr_data->cs_data.black_list.list[i],sizeof(T_LIST)); } /* In case of Black List search, include "grey" carriers also * in the Black list while sending to ALR */ if(CS_GET_CURRENT_SEARCH_MODE EQ BLACK_LIST_SEARCH_MODE) { TRACE_EVENT(" Black_List_Search_Started"); #ifdef TI_PS_FF_QUAD_BAND_SUPPORT mph_power_req->freq_bands = cs_get_freq_band (FALSE); #endif region = rr_data->cs_data.region; #ifdef TI_PS_FF_QUAD_BAND_SUPPORT if (region EQ BOTH_REGIONS) { for (i=0; i<MAX_REGIONS; i++) { for(arfcn=CHANNEL_0;arfcn<CHANNEL_0_INTERNAL;arfcn++) { /* Since Black List search is always a parallel search, "grey" carriers * belonging to the current region only have to be added */ if(cs_get_sync_fail_counter(i,arfcn)) srv_set_channel((T_LIST*)&mph_power_req->black_list.list[i],arfcn); } } } else { #endif for(arfcn=CHANNEL_0;arfcn<CHANNEL_0_INTERNAL;arfcn++) { /* Since Black List search is always a parallel search, "grey" carriers * belonging to the current region only have to be added */ if(cs_get_sync_fail_counter(region,arfcn)) srv_set_channel((T_LIST*)&mph_power_req->black_list.list[region],arfcn); } #ifdef TI_PS_FF_QUAD_BAND_SUPPORT } #endif } else { #ifdef TI_PS_FF_QUAD_BAND_SUPPORT mph_power_req->freq_bands = cs_get_freq_band (TRUE); #endif TRACE_EVENT_P9 ( "White List:[%d]Reg,[%d]Arfcn, MCC/MNC r=%x%x%x/%x%x%x/%d", rr_data->cs_data.white_list.region, rr_data->cs_data.white_list.last_sc_arfcn, rr_data->cs_data.white_list.last_sc_lac.mcc[0], rr_data->cs_data.white_list.last_sc_lac.mcc[1], rr_data->cs_data.white_list.last_sc_lac.mcc[2], rr_data->cs_data.white_list.last_sc_lac.mnc[0], rr_data->cs_data.white_list.last_sc_lac.mnc[1], rr_data->cs_data.white_list.last_sc_lac.mnc[2], rr_data->cs_data.white_list.last_sc_lac.lac); /* Copy white list information * White list cannot be used, when the region it belongs to, is not known * or its PLMN ID does not match with the requested PLMN */ if((!cs_check_region(rr_data->cs_data.white_list.region)) OR ((rr_data->ms_data.req_mm_service NEQ FUNC_PLMN_SRCH) AND (GET_STATE(STATE_ATT) NEQ ATT_CS_INIT)) OR ((rr_data->ms_data.req_mm_service EQ FUNC_PLMN_SRCH) AND (!dat_plmn_equal_req(rr_data->cs_data.white_list.last_sc_lac.mcc, rr_data->cs_data.white_list.last_sc_lac.mnc, rr_data->ms_data.plmn.mcc, rr_data->ms_data.plmn.mnc)))) { TRACE_EVENT("White List is not used"); } else { /* Copy the white list information */ srv_copy_list((T_LIST*)&mph_power_req->white_list.list, &rr_data->cs_data.white_list.list,sizeof (T_LIST)); /* Set the region */ mph_power_req->white_list.region = rr_data->cs_data.white_list.region; /* White list is valid */ mph_power_req->white_list.white_list_valid = TRUE; } } /* Handle the search mode timers based on the new search mode */ cs_handle_search_mode_timer(CS_GET_CURRENT_SEARCH_MODE); /* * reset the time for net search to finish * a PLMN available search during 35 seconds. */ if( rr_data->ms_data.req_mm_service EQ FUNC_NET_SRCH_BY_MMI) TIMERSTART(T_PLMN_SEARCH, T_PLMN_SEARCH_VALUE); /* * start power measurements in layer 1. */ TRACE_EVENT_P2 ("cs_start_scan(): freq_bands=%02x Search Mode = %d", mph_power_req->freq_bands,mph_power_req->search_mode); PSENDX (PL, mph_power_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_start_sync | +--------------------------------------------------------------------+ PURPOSE : Start the synchronisation to FB/SB without power measurements. Synchronisation to the frequency correction burst (FB) followed by a synchronisation to the synchron burst (SB) is carried out by layer 1. It means that the MS is synchronised to the base station and then able to read the BCCH to check the cell. */ GLOBAL void cs_start_sync (void) { GET_INSTANCE_DATA; UBYTE i; TRACE_FUNCTION ("cs_start_sync()"); /* While scanning for limited service, we scan all carriers */ if((CS_GET_PREVIOUS_SEARCH_MODE NEQ FAST_SEARCH_MODE) AND (rr_data->cs_data.scan_mode EQ CS_SECOND_SCAN)) { for (i=0;i<rr_data->cs_data.max_arfcn;i++) /* * reset check bit for all channels */ rr_data->cs_data.attributes[i] &= CS_NON_CHECKED_BITS; } if (cs_sync_next_bsic () EQ FALSE) { /* * indicate the end of scanning to attachment process */ TIMERSTOP(T_PLMN_SEARCH); att_no_bsic_ind (); } else { /* * Another FB/SB scan is requested */ SET_STATE (STATE_CELL_SEL, CS_IDLE_ACTIVE); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_del_list | +--------------------------------------------------------------------+ PURPOSE : A list of carriers (neighbourcell list) is used to speed up the cell selection process. All members of the list and the list of the power campaign are set to low priority. */ GLOBAL void cs_del_list (T_LIST *list) { GET_INSTANCE_DATA; UBYTE i; TRACE_FUNCTION ("cs_del_list()"); /* * for all cells of the power campaign list */ for (i=0;i<rr_data->cs_data.max_arfcn;i++) { /* * if they are member of the given list and not just checked */ if (srv_get_channel (list, (USHORT)(rr_data->cs_data.arfcn[i]&ARFCN_MASK)) AND rr_data->cs_data.act_index NEQ i) { /* * set to low priority */ rr_data->cs_data.attributes [i] &= CS_SET_TO_LOW_PRIORITY; /*TRACE_EVENT_P1("[%u] del from list",rr_data->cs_data.arfcn[i]);*/ } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_set_list | +--------------------------------------------------------------------+ PURPOSE : A list of carriers (neighbourcell list) is used to speed up the cell selection process. All members of the list and the list of the power campaign are set to high priority. */ GLOBAL void cs_set_list (T_LIST *list) { GET_INSTANCE_DATA; UBYTE i; TRACE_FUNCTION ("cs_set_list()"); /* * Not in the test house */ if (rr_data->cell_test_operation OR dat_test_sim_available ()) return; /* * for all channels in the power campaign list */ for (i=0;i<rr_data->cs_data.max_arfcn;i++) { /* * if they are also member of the given list */ if (srv_get_channel (list, (USHORT)(rr_data->cs_data.arfcn[i]&ARFCN_MASK))) { /* * set to high priority */ rr_data->cs_data.attributes [i] &= CS_SET_TO_LOW_PRIORITY; rr_data->cs_data.attributes [i] += CS_HIGH_PRIORITY; } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_def_list | +--------------------------------------------------------------------+ PURPOSE : Checks whether a member of the list has the requested attributes (e.g. emergency or low priority cell) */ GLOBAL UBYTE cs_def_list (UBYTE attribute) { GET_INSTANCE_DATA; UBYTE i; UBYTE result = FALSE; TRACE_FUNCTION ("cs_def_list()"); /* * for all channels of the power campaign list */ for (i=0;i<rr_data->cs_data.max_arfcn;i++) { /* * check only cells which have high/mid priority */ if ((rr_data->cs_data.attributes [i] & CS_CHECK_FLAG) EQ 0 AND (rr_data->cs_data.attributes [i] & CS_PRIORITY) NEQ 0) /* * channel is not checked yet, so it is possible that * the channel has this attribute */ { rr_data->cs_data.attributes [i] = CS_MID_PRIORITY; result = TRUE; } /* * check the attribute of the cell. If an attribute * like emergency or low priority cell is set, the channel * has been checked. */ if (rr_data->cs_data.attributes[i] & attribute) { /* * channel has this attribute, then set priority to high */ rr_data->cs_data.attributes [i] &= CS_SET_TO_LOW_PRIORITY; rr_data->cs_data.attributes [i] += CS_HIGH_PRIORITY; /* reset check bit for this channel */ rr_data->cs_data.attributes[i] &= CS_NON_CHECKED_BITS; result = TRUE; } } return result; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_sync_next | +--------------------------------------------------------------------+ PURPOSE : The function starts the next FB/SB synchronisation request. It selects the channel with the highest priority and field- strength which is not checked yet. */ GLOBAL BOOL cs_sync_next (void) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cs_sync_next()"); /* * no further channel is possible */ if (cs_sync_next_bsic () EQ FALSE) { /* * stop any timer which controls cell selection */ TIMERSTOP (T_RESELECT); SET_STATE (STATE_CELL_SEL, CS_IDLE); /* * indicate end of search to attachment process */ TIMERSTOP(T_PLMN_SEARCH); att_no_bsic_ind (); return FALSE; } return TRUE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_sync_next_bsic | +--------------------------------------------------------------------+ PURPOSE : The function looks for the next candidate for a FB/SB sync request. The channel is not checked yet, has the highest priority and the highest fieldstrength. Return TRUE if another MPH_BSIC_REQ is sent. */ static BOOL cs_sync_next_bsic (void) { GET_INSTANCE_DATA; UBYTE i; UBYTE x = NOT_PRESENT_8BIT; TRACE_FUNCTION ("cs_sync_next_bsic()"); /* * try to use 'found channel' from previous cell selection */ if( rr_data->found_channel NEQ NOT_PRESENT_16BIT ) { for ( i = 0; i < rr_data->cs_data.max_arfcn; i++ ) { if ( ((rr_data->cs_data.arfcn[i] & ARFCN_MASK) EQ (rr_data->found_channel & ARFCN_MASK)) AND ((rr_data->cs_data.arfcn[i] & US_BIT) EQ (rr_data->found_channel & US_BIT)) AND (rr_data->cs_data.attributes[i] & CS_CHECK_FLAG) EQ 0) { TRACE_EVENT ( "rr_found_channel in CS_DATA" ); rr_data->found_channel = NOT_PRESENT_16BIT; x = i; break; } } } /* * for all channels of the power campaign list */ if ( x EQ NOT_PRESENT_8BIT ) { for ( i=0; i < rr_data->cs_data.max_arfcn; i++ ) { if ((rr_data->cs_data.attributes[i] & CS_CHECK_FLAG) EQ 0) { /* * channel is not checked yet */ if (x EQ NOT_PRESENT_8BIT) { /* * first channel which is not checked yet */ x = i; /* High priority cell. Start sync */ if((rr_data->cs_data.attributes[i] & CS_PRIORITY) EQ CS_HIGH_PRIORITY) break; } else { if ((rr_data->cs_data.attributes[i] & CS_PRIORITY) > (rr_data->cs_data.attributes[x] & CS_PRIORITY)) { /* * new channel has higher priority */ x = i; } } } /* CS_CHECK FLAG */ } /* i < max_arfcn */ } /* x NEQ NOT_PRESENT_8BIT */ if (x NEQ NOT_PRESENT_8BIT) { rr_data->cs_data.act_index = x; if ((rr_data->ms_data.rr_service NEQ NO_SERVICE) AND (rr_data->cs_data.arfcn[x] EQ rr_data->nc_data[SC_INDEX].arfcn)) { /* * Synchronization request for serving cell. * No need to send MPH_BSIC_REQ as we are already synchronized to * serving cell, instead fake MPH_BSIC_CNF. */ PALLOC (mph_bsic_cnf, MPH_BSIC_CNF); /* T_MPH_BSIC_CNF */ mph_bsic_cnf->arfcn = rr_data->cs_data.arfcn[x]; mph_bsic_cnf->bsic = rr_data->nc_data[SC_INDEX].bsic; mph_bsic_cnf->cs = CS_NO_ERROR; if (srv_store_prim ((T_PRIM *)D2P(mph_bsic_cnf))) { TRACE_EVENT ("Shortcut for sync to SC taken"); USE_STORED_ENTRIES(); return TRUE; } else { /* In the unlikely event that we could not store the primitive */ PFREE (mph_bsic_cnf); } } else { /* *start BSIC Reading;For fast search, the first scan is only on reasonably strong carriers.i.e carrires with rxlev>MEDIUM_RXLEV_THRESHOLD *This is as per the cell selection improvements document. Hence dont send BSIC request on white listed low power carrires for first scan. *(OMAPS00109145)*/ if( (rr_data->cs_data.previous_search_mode EQ FAST_SEARCH_MODE) AND (rr_data->cs_data.scan_mode NEQ CS_SECOND_SCAN) AND ( rr_data->cs_data.rxlev[x]<MEDIUM_RXLEV_THRESHOLD)) return FALSE; else { PALLOC (mph_bsic_req, MPH_BSIC_REQ); mph_bsic_req->arfcn = rr_data->cs_data.arfcn[x]; TRACE_EVENT_P3 ("BSIC REQ[%u]%u a=0x%x", rr_data->cs_data.arfcn[x] & ARFCN_MASK, x, rr_data->cs_data.attributes[x]); PSENDX (PL, mph_bsic_req); } return TRUE; } } else return FALSE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_set_null | +--------------------------------------------------------------------+ PURPOSE : Initialize the cell selection process. */ GLOBAL void cs_set_null (void) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cs_set_null()"); SET_STATE (STATE_CELL_SEL, CS_NULL); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_set_stop_active | +--------------------------------------------------------------------+ PURPOSE : The function resets the state of the cell selection process to an non-active state. */ GLOBAL void cs_set_stop_active (void) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cs_set_stop_active()"); switch (GET_STATE(STATE_CELL_SEL)) { case CS_NULL: case CS_NULL_ACTIVE: SET_STATE (STATE_CELL_SEL, CS_NULL); break; case CS_IDLE: case CS_IDLE_ACTIVE: SET_STATE (STATE_CELL_SEL, CS_IDLE); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_set_attributes | +--------------------------------------------------------------------+ PURPOSE : The function sets an attribute for a channel (e.g. emergency or low priority cell). */ GLOBAL void cs_set_attributes (UBYTE attribute, USHORT arfcn) { GET_INSTANCE_DATA; UBYTE i; TRACE_FUNCTION ("cs_set_attributes()"); /* * for all channels of the power campaign list */ for (i=0;i<rr_data->cs_data.max_arfcn;i++) { /* * if it is the given channel number, set the attributes. */ if ((rr_data->cs_data.arfcn[i]&ARFCN_MASK) EQ arfcn) rr_data->cs_data.attributes [i] |= attribute; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_set_rxlev | +--------------------------------------------------------------------+ PURPOSE : Updating of a fieldstrength value in the list of the power campaign. */ GLOBAL void cs_set_rxlev (UBYTE rxlev, USHORT arfcn) { GET_INSTANCE_DATA; UBYTE i; TRACE_FUNCTION ("cs_set_rxlev()"); /* * for all channels in the power campaign list */ for (i=0;i<rr_data->cs_data.max_arfcn;i++) { /* * if it is the given channel number, update the fieldstrength. */ if ((rr_data->cs_data.arfcn[i]&ARFCN_MASK) EQ arfcn) rr_data->cs_data.rxlev [i] = rxlev; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_clear_attributes | +--------------------------------------------------------------------+ PURPOSE : The function clears an attribute for a channel (e.g. emergency or low priority cell). */ GLOBAL void cs_clear_attributes (UBYTE attribute, USHORT arfcn) { GET_INSTANCE_DATA; UBYTE i; TRACE_FUNCTION ("cs_clear_attributes()"); /* * for all channels in the power campaign list */ for (i=0;i<rr_data->cs_data.max_arfcn;i++) { /* * if it is the given channel number, clear the attributes. */ if ((rr_data->cs_data.arfcn[i]&ARFCN_MASK) EQ arfcn) rr_data->cs_data.attributes [i] &= ~attribute; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_mph_power_cnf | +--------------------------------------------------------------------+ PURPOSE : The result of a power request to layer 1. Layer 1 returns a list of up to 40 GSM 900 + 40 DCS 1800 channels to RR. */ GLOBAL void cs_mph_power_cnf (T_MPH_POWER_CNF * mph_power_cnf) { GET_INSTANCE_DATA; UBYTE i,j,rxlev; USHORT mask = 0xFFFF; /* no mask */ U8 x; BOOL copy = TRUE; TRACE_FUNCTION ("cs_mph_power_cnf()"); if(GET_STATE(STATE_ATT) EQ ATT_CS_INIT ) { if( !srv_store_prim ((T_PRIM *)D2P(mph_power_cnf)) ) { /* * primitive storing failed */ PFREE (mph_power_cnf); SET_STATE(STATE_CELL_SEL, CS_NULL); SET_STATE(STATE_ATT, ATT_NULL); } else { /* * Boot Time: Do not store primitive for more than 10 s in case * of quick registration. If the second activate_req does not * come before this time move to ATT_NULL. * The T_RESELECT timer is used for a different purpose here. */ TIMERSTART(T_RESELECT, TRESELECT_VALUE); } return; } TRACE_EVENT_P1 ("mph_power_cnf: %u freq.", mph_power_cnf->num_of_chan); for (i = 0; i < mph_power_cnf->num_of_chan; i++) { TRACE_EVENT_P3("[%4u] std=%u rx_lev=%2u", mph_power_cnf->arfcn[i]&ARFCN_MASK, STD_GET_FROM_ARFCN(mph_power_cnf->arfcn[i]), mph_power_cnf->rx_lev[i]); } /* Remove the inactive carriers from Black List */ if((CS_GET_CURRENT_SEARCH_MODE EQ BLACK_LIST_SEARCH_MODE) OR (mph_power_cnf->num_of_chan)) { /* In case of "Full", "Normal" and "Fast" search modes, remove * inactive carriers from Black List, only when there is atleast * one strong carrier in that area */ cs_rem_inactive_carriers_from_bl(mph_power_cnf); } if(CS_GET_CURRENT_SEARCH_MODE NEQ BLACK_LIST_SEARCH_MODE) { /* Update previous search mode */ CS_SET_PREVIOUS_SEARCH_MODE(CS_GET_CURRENT_SEARCH_MODE); switch (GET_STATE(STATE_CELL_SEL)) { case CS_IDLE_ACTIVE: /* We will start parallel scan in 2 cases 1. After HPLMN timer expiry 2. After TREG timer expiry In these both cases don't mask out std and US_BIT */ #ifndef TI_PS_FF_QUAD_BAND_SUPPORT mask = ARFCN_MASK; /* for parallel search mask out 'std' and US_BIT. */ #endif /*lint -fallthrough*/ case CS_NULL_ACTIVE: /* * copy channel list from layer 1, set the number * of entries in the list */ rr_data->cs_data.max_arfcn = mph_power_cnf->num_of_chan; /* * for all channels coming from layer 1 */ for (i=0,j=0;i<mph_power_cnf->num_of_chan;i++) { #ifdef TI_PS_FF_QUAD_BAND_SUPPORT x = cs_get_band_index(mph_power_cnf->arfcn[i]); #else x = get_band_index(mph_power_cnf->arfcn[i]); #endif /* for OMAPS00109145, in which the I-Sample is not camping on to the agilent ,once down link failure is occured on current cell and at power levels < -100dB, this is because in the fast search mode we are not considering the low rxlev carriers. So this modification is required in order to come back to the network even after a down link failure has happened and if another BCCH carrer of less power become active and available for the mobile to camp */ rxlev = rr_data->dyn_config.lower_rxlev_thr[x]; copy = TRUE; if((i >= mph_power_cnf->num_of_white_list_chan) AND (mph_power_cnf->rx_lev[i] < rxlev)) { copy = FALSE; } /* * check against band restrictions */ if (copy AND cs_check_channel ((USHORT)(mph_power_cnf->arfcn[i]&ARFCN_MASK))) { #ifdef TI_PS_FF_QUAD_BAND_SUPPORT /* For parallel search mask serving cell */ if ((GET_STATE(STATE_CELL_SEL) EQ CS_IDLE_ACTIVE) AND (rr_data->nc_data[SC_INDEX].arfcn EQ (mph_power_cnf->arfcn[i]&ARFCN_MASK))) rr_data->cs_data.arfcn[j] = mph_power_cnf->arfcn[i]&ARFCN_MASK; else #endif rr_data->cs_data.arfcn[j] = mph_power_cnf->arfcn[i]&mask; rr_data->cs_data.rxlev[j] = mph_power_cnf->rx_lev[i]; /* * set initial to middle priority */ rr_data->cs_data.attributes [j++] = CS_MID_PRIORITY; } else { /* * a cell is not copied due to band restrictions */ rr_data->cs_data.max_arfcn--; } } TRACE_EVENT_P2("No_chan > [%d]min_rxlev copied:%d",rxlev,rr_data->cs_data.max_arfcn); /* Increase the priority of white list carriers */ if(rr_data->cs_data.max_arfcn ) cs_use_white_list_info(mph_power_cnf->num_of_white_list_chan); /* * add actual PLMN to the found list, if available */ if (rr_data->ms_data.req_mm_service EQ FUNC_NET_SRCH_BY_MMI AND GET_STATE(STATE_ATT) EQ ATT_IDLE AND (!rr_data->net_lost)) cs_add_current_network_to_found_list (); /* * Select channel with the highest fieldstrength and priority * and start BSIC scanning, else send signal that no further * channel is available */ if (cs_sync_next_bsic () EQ FALSE) { SET_STATE (STATE_CELL_SEL, CS_IDLE); TIMERSTOP(T_PLMN_SEARCH); att_no_bsic_ind (); } else { SET_STATE (STATE_CELL_SEL, CS_IDLE_ACTIVE); } /* * CS power measurements may be used to reorder arfcns'n in * MPH_NEIGHBOURCELL_REQ while TCSVALID is running */ TIMERSTART(TCSVALID, THIRTY_SEC); break; } } /* NEQ black list search */ else { /* Stop the parallel PLMN search */ att_notify_stop_plmn_search(FALSE); SET_STATE (STATE_CELL_SEL, CS_IDLE); /* Black list search is a temporary search. It is not used * in deciding the next search. Hence we need to update current search * mode when Black List search is over */ CS_SET_CURRENT_SEARCH_MODE(CS_GET_PREVIOUS_SEARCH_MODE); } /* Black list search */ PFREE (mph_power_cnf); srv_use_stored_prim (); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_mph_bsic_cnf | +--------------------------------------------------------------------+ PURPOSE : The response of a FB/SB synchronisation request from layer 1. */ GLOBAL void cs_mph_bsic_cnf (T_MPH_BSIC_CNF * mph_bsic_cnf) { GET_INSTANCE_DATA; U8 local_region; U16 local_arfcn; TRACE_FUNCTION ("cs_mph_bsic_cnf()"); switch (GET_STATE (STATE_CELL_SEL)) { case CS_IDLE_ACTIVE: if (mph_bsic_cnf->cs EQ CS_NO_ERROR) { UBYTE new_std = STD_GET_FROM_ARFCN(mph_bsic_cnf->arfcn); /* * FB / SB is decoded, cell has the attributes * BCCH detected and checked */ /* * reset std from the current MPH_BSIC_CNF(only if it is non-zero) */ TRACE_EVENT_P2("reset std: new_std = %d, old_std = %d", new_std, std); if(new_std) { #ifdef TI_PS_FF_QUAD_BAND_SUPPORT UBYTE new_region; std = cs_update_std_ffs (new_std); new_region = srv_get_region_from_std(std); TRACE_EVENT_P1("update std: new_std = %d", std); #else UBYTE new_region = srv_get_region_from_std(new_std); std = new_std; #endif /* Both American and European bands are detected in the current * region. Following TREG timer expiry in Limited Service state, * non-parallel search will be issued * CSI-LLD section:4.3 */ if(rr_data->cs_data.region NEQ NOT_PRESENT_8BIT) { if(rr_data->cs_data.region NEQ new_region) { rr_data->cs_data.all_freq_area = TRUE; TRACE_EVENT("all_freq_area : 1"); } } /* CSI-LLD section:4.1.1.3.12 * This stores region in rr_data base by extracting from std */ rr_data->cs_data.region = new_region; } /* * remove co channels */ if (test_house EQ FALSE) cs_remove_co_channels ((USHORT)(mph_bsic_cnf->arfcn&ARFCN_MASK)); rr_data->cs_data.attributes [rr_data->cs_data.act_index] |= (CS_CHECK_FLAG | CS_BCCH_READ); /* CSI-LLD section:4.1.1.11 * Synchronisation succeeded. Remove the carrier from black list */ cs_del_from_black_list(rr_data->cs_data.region, (U16)(mph_bsic_cnf->arfcn&ARFCN_MASK)); att_bsic_ind ((USHORT)(mph_bsic_cnf->arfcn&ARFCN_MASK), rr_data->cs_data.rxlev [rr_data->cs_data.act_index], mph_bsic_cnf->bsic); } else { /* * FB / SB is not decoded, cell has the attributes * BCCH not detected and checked */ rr_data->cs_data.attributes [rr_data->cs_data.act_index] |= CS_CHECK_FLAG; /* Extract region information */ local_arfcn = rr_data->cs_data.arfcn[rr_data->cs_data.act_index]; if(STD_GET_FROM_ARFCN(local_arfcn) NEQ STD_NOT_PRESENT) { /* During Non-Parallel search, region information is available * in ARFCN */ local_region = CS_GET_REGION_FROM_FREQ(local_arfcn); } else { /* Parallel search case */ local_region = srv_get_region_from_std(std); #ifdef TI_PS_FF_QUAD_BAND_SUPPORT if (local_region EQ BOTH_REGIONS) local_region = srv_get_region_from_std_arfcn (std, local_arfcn); #endif } /* CSI-LLD section:4.1.1.6 * Sync failed. Add the carrier to Black list */ cs_add_to_black_list(local_region, (U16)(local_arfcn), rr_data->cs_data.rxlev[rr_data->cs_data.act_index]); /* CSI-LLD section:4.1.1.11 * Set the BLACK LIST attribute flag for this carrier */ if(rr_data->cs_data.initial_plmn_search EQ INITIAL_PLMN_SEARCH_ACTIVE) { CS_SET_BLACK_LIST_FLAG(rr_data->cs_data.act_index); } if (cs_sync_next_bsic () EQ FALSE) { TIMERSTOP(T_PLMN_SEARCH); SET_STATE (STATE_CELL_SEL, CS_IDLE); att_no_bsic_ind (); /* stop in RR */ } } break; #ifdef GPRS case CS_CCO: SET_STATE (STATE_CELL_SEL, CS_IDLE); if (rr_data->gprs_data.cr_pbcch_active OR rr_data->gprs_data.cr_pcco_active) { /* * a Packet Cell Change Order for a cell which * is not in the BA list has been requested by the NW */ if (mph_bsic_cnf->cs EQ CS_NO_ERROR AND (mph_bsic_cnf->arfcn&ARFCN_MASK) EQ rr_data->gprs_data.arfcn AND mph_bsic_cnf->bsic EQ rr_data->gprs_data.bsic ) { /* * PL successfuly sycnhronized to the cell * now RR will do a normal Cell Reselection */ memset (&rr_data->nc_data[CR_INDEX], 0, sizeof (T_NC_DATA)); rr_data->nc_data[CR_INDEX].arfcn = mph_bsic_cnf->arfcn&ARFCN_MASK; rr_data->nc_data[CR_INDEX].bsic = mph_bsic_cnf->bsic; /* CSI-LLD section:4.1.1.11 * Synchronisation succeeded. Remove the carrier from black list */ cs_del_from_black_list(rr_data->cs_data.region, (U16)(mph_bsic_cnf->arfcn&ARFCN_MASK)); if( rr_data->gprs_data.cr_pbcch_active ) att_start_cell_reselection_pbcch(MODE_CELL_RESELECTION); else { att_init_cell_selection(CELL_RESELECTION, RR_ORIGINATED); rr_data->dyn_config.fcr = 0; rr_data->dyn_config.scr = 0; rr_data->bcch_error = 0; rr_data->pag_rec = FALSE; srv_clear_stored_prim (MPH_PAGING_IND); gprs_init_data_cr(); dat_att_null(); SET_STATE (STATE_ATT, ATT_CS3); att_build_idle_req (CR_INDEX, MODE_CELL_RESELECTION); } } else { /* * PL did not sycnhronize to the cell * inform GRR and wait for a CR_REQ(CR_REQ) with * the old cell and return to it */ PALLOC(gprs_ind, RRGRR_GPRS_SI13_IND); rr_data->gprs_data.cr_pbcch_active = FALSE; gprs_ind->cause = GPRS_CELL_NOT_SUITABLE; gprs_ind->serving_cell_info.bcch_arfcn = rr_data->gprs_data.arfcn; gprs_ind->serving_cell_info.bcch_bsic = rr_data->gprs_data.bsic; TRACE_EVENT_P4 ("cs=%u C[%d] bsic=%u #%u", gprs_ind->cause, gprs_ind->serving_cell_info.bcch_arfcn, gprs_ind->serving_cell_info.bcch_bsic, __LINE__); PSENDX(GRR, gprs_ind); /* wait for CR_REQ for old cell */ } } else if (mph_bsic_cnf->cs EQ CS_NO_ERROR AND (mph_bsic_cnf->arfcn&ARFCN_MASK) EQ rr_data->gprs_data.arfcn AND mph_bsic_cnf->bsic EQ rr_data->gprs_data.bsic ) { rr_data->gprs_data.tbf_est = TBF_EST_CCO; rr_data->nc_data[CR_INDEX].arfcn = rr_data->gprs_data.arfcn; rr_data->nc_data[CR_INDEX].rxlev = 0; rr_data->nc_data[CR_INDEX].bsic = rr_data->gprs_data.bsic; att_init_cr_data(); TIMERSTART (T_RESELECT, TRESELECT_VALUE); rr_data->nc_data[CR_INDEX].bcch_error = 0; srv_clear_list (&rr_data->cr_data.cd.ncell_list); SET_STATE (STATE_ATT, ATT_CS2); /* CSI-LLD section:4.1.1.11 * Synchronisation succeeded. Remove the carrier from black list */ cs_del_from_black_list(rr_data->cs_data.region, (U16)(mph_bsic_cnf->arfcn&ARFCN_MASK)); /* wait for System Information Messages */ } else /* initiate switch back to old cell */ { dat_code_mph_old_chan_req(); PFREE ( rr_data->gprs_data.dl_data_ind ); rr_data->gprs_data.dl_data_ind = NULL; rr_data->gprs_data.reconn_cause = RRC_PROT_UNSPECIFIED; rr_data->gprs_data.cco_need_reconnect_cnf = FALSE; SET_STATE (STATE_DAT, DAT_CCO_3); } break; case CS_XMEAS: /* enter result in rr_data->gprs_data.rrgrr_ext_meas_cnf, call att_ext_meas_next_bsic */ { UBYTE bsic = mph_bsic_cnf->bsic; T_GPRS_DATA *gprs_data = &rr_data->gprs_data; T_RRGRR_EXT_MEAS_REQ *rrgrr_ext_meas_req = gprs_data->rrgrr_ext_meas_req; if ( rrgrr_ext_meas_req->report_type EQ REP_TYPE_1 OR /* "6 strongest carriers independent of BSIC decoding or not" */ rrgrr_ext_meas_req->report_type EQ REP_TYPE_2 AND /* "BSICs for 6 carriers with decoded BSIC with allowed NCC" */ mph_bsic_cnf->cs EQ CS_NO_ERROR AND (rrgrr_ext_meas_req->ncc_permitted & (1 << ((bsic>>3) & 0x07)))) /* check for "NCC allowed" */ { T_RRGRR_EXT_MEAS_CNF *rrgrr_ext_meas_cnf = gprs_data->rrgrr_ext_meas_cnf; T_MPH_EXT_MEAS_CNF *mph_ext_meas_cnf = gprs_data->mph_ext_meas_cnf; UBYTE n = gprs_data->mph_ext_meas_num; USHORT arfcn = mph_ext_meas_cnf->arfcn[n]; UBYTE rx_lev = mph_ext_meas_cnf->rx_lev[n]; UBYTE idx = rr_ext_meas_idx ( arfcn ); UBYTE k = rrgrr_ext_meas_cnf->c_xmeas_res++; T_xmeas_res *xmeas_res = &rrgrr_ext_meas_cnf-> xmeas_res[k]; /* * Function att_ext_meas_next_bsic checks for the maximum number of elements in the * array rrgrr_ext_meas_cnf->xmeas_res. Therefore this check is not performed here. */ xmeas_res->arfcn_idx.arfcn = arfcn; xmeas_res->arfcn_idx.idx = idx; xmeas_res->rxlev = rx_lev; if (mph_bsic_cnf->cs EQ CS_NO_ERROR) xmeas_res->bsic = bsic; else xmeas_res->bsic = RRGRR_INVALID_BSIC; } } rr_data->gprs_data.mph_ext_meas_num++; att_ext_meas_next_bsic(); break; #endif default: break; } PFREE (mph_bsic_cnf); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_get_channel_from_found_list | +--------------------------------------------------------------------+ PURPOSE : If a network available list was created in former times (found_plmn / found_channel) and one of this networks is requested, the associated channel is stored to give it high priority to speed up cell selection. */ GLOBAL void cs_get_channel_from_found_list () { GET_INSTANCE_DATA; UBYTE i; T_FOUND_ELEMENT * found; TRACE_FUNCTION ("cs_get_channel_from_found_list()"); /* * initialise the local variable */ rr_data->found_channel = NOT_PRESENT_16BIT; /* * for all PLMNs stored in the found list */ found = &rr_data->sc_data.found[0]; for (i=0; i<rr_data->sc_data.found_entries; i++, found++) { /* * if the network in the found list is equal to the PLMN requested by MM, * set the found channel */ /* Implements Measure#32: Row 124 */ att_print_mcc_mnc(found->arfcn, found->plmn.mcc, found->plmn.mnc, S2I_STRING("list")); if (dat_plmn_equal_req (found->plmn.mcc, found->plmn.mnc, rr_data->ms_data.plmn.mcc, rr_data->ms_data.plmn.mnc)) { rr_data->found_channel = found->arfcn; /* Embed region information in the found channel arfcn */ if(found->region EQ AMERICAN_REGION) rr_data->found_channel |= US_BIT; /* Implements Measure#32: Row 125 */ att_print_mcc_mnc(found->arfcn, found->plmn.mcc, found->plmn.mnc, S2I_STRING("found_channel")); return; } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_clear_channel_from_found_list | +--------------------------------------------------------------------+ PURPOSE : If a network available list was created in former times (found_plmn / rr_found_channel) and one of this networks is requested, the associated channel is stored to give it high priority to speed up cell selection. This function clear the stored data if a network or limited search is started. */ GLOBAL void cs_clear_channel_from_found_list (void) { GET_INSTANCE_DATA; /* * initialize the found channel number */ rr_data->found_channel = NOT_PRESENT_16BIT; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_remove_co_channels | +--------------------------------------------------------------------+ PURPOSE : If a channel x fails and the channels x-1 and x+1 have a fieldstrength difference greater 9 dB, it is not necessary to try on this cells. Sense of this is to speed up search. */ static void cs_remove_co_channels (USHORT arfcn) { /* * depending on the channel number. Some extra cases * for channel numbers on the boarders of the frequency Band */ switch (arfcn) { case CHANNEL_0: /* * E-GSM channel 0 has no co-channels */ break; /* * all LOW channel boarders */ case LOW_CHANNEL_850: case LOW_CHANNEL_900: case LOW_CHANNEL_1800: case LOW_CHANNEL_EGSM: cs_remove_co_chan (arfcn, (USHORT)(arfcn+1)); break; /* * all HIGH channel boarders */ case HIGH_CHANNEL_1900: if (std NEQ STD_1900 AND std NEQ STD_DUAL_US) { cs_remove_co_chan (arfcn, (USHORT)(arfcn+1));/* DCS 1800 */ } /*lint -fallthrough*/ case HIGH_CHANNEL_850: case HIGH_CHANNEL_900: case HIGH_CHANNEL_1800: case HIGH_CHANNEL_EGSM-1: cs_remove_co_chan (arfcn, (USHORT)(arfcn-1)); break; default: /* * all other channels inside the frequency bands */ cs_remove_co_chan (arfcn, (USHORT)(arfcn+1)); cs_remove_co_chan (arfcn, (USHORT)(arfcn-1)); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_remove_co_chan | +--------------------------------------------------------------------+ PURPOSE : if co_chan - chan has a fieldstrength difference greater 9 dBm, remove the channel. */ static void cs_remove_co_chan (USHORT arfcn, USHORT co_arfcn) { GET_INSTANCE_DATA; UBYTE index_arfcn = NOT_PRESENT_8BIT; UBYTE index_co_arfcn = NOT_PRESENT_8BIT; UBYTE i; SHORT rxlev_arfcn; SHORT rxlev_co_arfcn; USHORT *p_arfcn; TRACE_FUNCTION ("cs_remove_co_chan()"); /* * calculate the index in the power campaign list * for the channel */ p_arfcn = rr_data->cs_data.arfcn; for (i=0; i<rr_data->cs_data.max_arfcn; i++) { if (arfcn EQ (p_arfcn[i]&ARFCN_MASK)) { index_arfcn = i; break; } } /* * if the channel is not inside the list, * then nothing is to compare else get the * fieldstrength. */ if (index_arfcn EQ NOT_PRESENT_8BIT) return; /* * calculate the index in the power campaign list * for the co-channel */ for (i=0;i<rr_data->cs_data.max_arfcn;i++) { if (co_arfcn EQ (p_arfcn[i]&ARFCN_MASK)) { index_co_arfcn = i; break; } } /* * if the co-channel is not inside the list, * then nothing is to compare else get the * fieldstrength. */ if (index_co_arfcn EQ NOT_PRESENT_8BIT) return; rxlev_arfcn = (SHORT)rr_data->cs_data.rxlev [index_arfcn]; rxlev_co_arfcn = (SHORT)rr_data->cs_data.rxlev [index_co_arfcn]; /* * if the difference is > 9 dBm, * set to low priority. */ if ((rxlev_arfcn - rxlev_co_arfcn) > 9) { rr_data->cs_data.attributes [index_co_arfcn] &= CS_SET_TO_LOW_PRIORITY; } } /* +---------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_add_current_network .... | +---------------------------------------------------------------------+ PURPOSE : Adds the current PLMN to the found list if available. */ LOCAL void cs_add_current_network_to_found_list (void) { GET_INSTANCE_DATA; T_loc_area_ident *lai = &rr_data->nc_data[SC_INDEX].lai; TRACE_FUNCTION ("cs_add_current_network_to_found_list()"); switch (rr_data->ms_data.rr_service) { case LIMITED_SERVICE: case FULL_SERVICE: /* * The mobile was in full service * Add this PLMN to the list of found PLMN * and clean power measurement list. */ if (! att_plmn_in_found_list (lai->mcc, lai->mnc) AND rr_data->sc_data.found_entries < MAX_PLMN) { att_save_found_plmn ( &rr_data->sc_data.found[rr_data->sc_data.found_entries], lai->mcc, lai->mnc, rr_data->nc_data[SC_INDEX].arfcn, rr_data->nc_data[SC_INDEX].rxlev, lai->lac, 0); rr_data->sc_data.found_entries++; } /* * Consider only high priority cells to speed up search */ cs_del_list (&rr_data->sc_data.cd.ncell_list); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_check_channel | +--------------------------------------------------------------------+ PURPOSE : Depending on the settings (default, GSM 900, DCS 1800) all non-interesting channels are removed. */ static UBYTE cs_check_channel (USHORT arfcn) { GET_INSTANCE_DATA; /* * TRACE_FUNCTION ("cs_check_channel") */ { switch (rr_data->dyn_config.set_band) { case 0: /* * default behaviour */ return TRUE; case 1: /* * set to GSM 900 */ /* if (arfcn <= LOW_CHANNEL_900 OR arfcn >= HIGH_CHANNEL_900) */ if (INRANGE(LOW_CHANNEL_900,arfcn,HIGH_CHANNEL_900)) return FALSE; else return TRUE; case 2: /* * set to DCS 1800 */ /* if (arfcn >= LOW_CHANNEL_1800 AND arfcn <= HIGH_CHANNEL_1800) */ if (INRANGE(LOW_CHANNEL_1800,arfcn,HIGH_CHANNEL_1800)) return TRUE; else return FALSE; } } return TRUE; } /* +----------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_check_region | +----------------------------------------------------------------------+ PURPOSE : This routine validates the region Cell Selection Improvements-LLD section:4.1.1.2 */ GLOBAL BOOL cs_check_region(U8 region) { #ifdef TI_PS_FF_QUAD_BAND_SUPPORT if((region EQ EUROPEAN_REGION) OR (region EQ AMERICAN_REGION) OR (region EQ BOTH_REGIONS)) #else if((region EQ EUROPEAN_REGION) OR (region EQ AMERICAN_REGION)) #endif { return TRUE; } else { TRACE_ERROR("Invalid region"); return FALSE; } } /* +----------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_validate_arfcn_index | +----------------------------------------------------------------------+ PURPOSE : This routine validates the ARFCN index Cell Selection Improvements-LLD section:4.1.1.2 */ GLOBAL BOOL cs_check_arfcn_range(U16 arfcn) { if(arfcn EQ CHANNEL_0) arfcn = CHANNEL_0_INTERNAL; if((arfcn > CHANNEL_0) AND (arfcn <= CHANNEL_0_INTERNAL)) { return TRUE; } else { TRACE_ERROR("Invalid ARFCN"); return FALSE; } } /* +----------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_inc_sync_fail_counter | +----------------------------------------------------------------------+ PURPOSE : This routine increments the sync fail counter value for GSM carrier. Seperate counters are maintained for European and American regions.The size of SFC counter is 4 bits. As a result two carriers are accommodated in one byte. This function first converts the ARFCN range from 1-1023 to 0-511 format and increments the SFC accordingly. The SFC format is shown below CSI-LLD section:4.1.1.5.9 ------------------------------------------ | Index | MSB 4 bits | LSB 4 bits | ------------------------------------------ | 0 | ARFCN : 2 | ARFCN : 1 | ------------------------------------------ | 1 | ARFCN : 4 | ARFCN 3 | ------------------------------------------ | - | - | - | ------------------------------------------ | - | - | - | ------------------------------------------ | 510 | ARFCN : 1022 | ARFCN: 1021 | ------------------------------------------ | 511 | ARFCN : 0 | ARFCN :1023 | ----------------------------------------- ARFCN: 0 = CHANNEL_0_INTERNAL */ LOCAL void cs_inc_sync_fail_counter(U8 region, U16 arfcn) { GET_INSTANCE_DATA; U16 index=0; U8 inc = 0; if(!cs_check_region(region)) return; if(!cs_check_arfcn_range((U16)(arfcn & ARFCN_MASK))) return; if(arfcn EQ CHANNEL_0) arfcn = CHANNEL_0_INTERNAL; /* Convert ARFCN range to 0-511 from 1-1023 range */ index = ((arfcn & ARFCN_MASK) -1) >> 1; if(arfcn & 0x01) { /* Increment LSB 4 bits for odd ARFCN */ inc = 0x01; } else { /* Increment MSB 4 bits for even ARFCN */ inc = 0x10; } /* Increment the synchronisation counter */ rr_data->cs_data.black_list.sfc[region][index] += inc; TRACE_EVENT_P3("[%d]Reg,[%d]Arfcn, SFC = 0x%x", region, arfcn, rr_data->cs_data.black_list.sfc[region][index]); } /* +----------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_reset_sync_fail_counter | +----------------------------------------------------------------------+ PURPOSE : This routine resets the synchronisation fail counter value of GSM carrier. Seperate counters are maintained for European and American regions.The size of SFC counter is 4 bits. As a result two carriers are accommodated in one byte. This function first converts the ARFCN range from 1-1023 to 0-511 format and increments the SFC accordingly.The SFC format is shown below CSI-LLD section:4.1.1.5.10 ------------------------------------------ | Index | MSB 4 bits | LSB 4 bits | ------------------------------------------ | 0 | ARFCN : 2 | ARFCN : 1 | ------------------------------------------ | 1 | ARFCN : 4 | ARFCN 3 | ------------------------------------------ | - | - | - | ------------------------------------------ | - | - | - | ------------------------------------------ | 510 | ARFCN : 1022 | ARFCN: 1021 | ------------------------------------------ | 511 | ARFCN : 0 | ARFCN :1023 | ----------------------------------------- ARFCN: 0 = CHANNEL_0_INTERNAL */ LOCAL void cs_reset_sync_fail_counter(U8 region, U16 arfcn) { GET_INSTANCE_DATA; USHORT index=0; if(!cs_check_region(region)) return; if(!cs_check_arfcn_range((U16)(arfcn & ARFCN_MASK))) return; if(arfcn EQ CHANNEL_0) arfcn = CHANNEL_0_INTERNAL; /* Convert ARFCN range to 0-511 from 1-1023 range */ index = ((arfcn & ARFCN_MASK) -1) >> 1; if(arfcn & 0x01) { /* Reset LSB 4 bits for odd ARFCN */ rr_data->cs_data.black_list.sfc[region][index] &=0xf0; } else { /* Reset MSB 4 bits for even ARFCN */ rr_data->cs_data.black_list.sfc[region][index] &=0x0f; } TRACE_EVENT_P2("SFC reset for [%d]Reg,[%d]Arfcn",region,arfcn); } /* +----------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_get_sync_fail_counter | +----------------------------------------------------------------------+ PURPOSE : This function returns the SFC counter of GSM carriers Seperate counters are maintained for European and American regions.The size of SFC counter is 4 bits. As a result two carriers are accommodated in one byte. This function first converts the ARFCN range from 1-1023 to 0-511 format and increments the SFC accordingly.The SFC format is shown below CSI-LLD section:4.1.1.5.11 ------------------------------------------ | Index | MSB 4 bits | LSB 4 bits | ------------------------------------------ | 0 | ARFCN : 2 | ARFCN : 1 | ------------------------------------------ | 1 | ARFCN : 4 | ARFCN 3 | ------------------------------------------ | - | - | - | ------------------------------------------ | - | - | - | ------------------------------------------ | 510 | ARFCN : 1022 | ARFCN: 1021 | ------------------------------------------ | 511 | ARFCN : 0 | ARFCN :1023 | ----------------------------------------- ARFCN: 0 = CHANNEL_0_INTERNAL */ LOCAL U8 cs_get_sync_fail_counter(U8 region, U16 arfcn) { GET_INSTANCE_DATA; USHORT index=0; UBYTE sfc_count=0; if(!cs_check_region(region)) return sfc_count; if(!cs_check_arfcn_range((U16)(arfcn & ARFCN_MASK))) return sfc_count; if(arfcn EQ CHANNEL_0) arfcn = CHANNEL_0_INTERNAL; /* Convert to 0-511 range from 1-1024 range */ index = ((arfcn & ARFCN_MASK) -1) >> 1; if(arfcn & 0x01) { /* obtain LSB 4 bits for odd ARFCN */ sfc_count = (rr_data->cs_data.black_list.sfc[region][index] & 0x0f); } else { /* obtain MSB 4 bits for even ARFCN */ sfc_count = (rr_data->cs_data.black_list.sfc[region][index] & 0xf0) >> 4; } return sfc_count; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_add_to_black_list | +--------------------------------------------------------------------+ PURPOSE : This function is used to add GSM channels to "Black List". The function checks the "Black List" criteria before adding it to the list. This function is called whenever MS fails to synchronize to a GSM channel. CSI-LLD section:4.1.1.5.5 */ GLOBAL void cs_add_to_black_list(U8 region, U16 arfcn, U8 rxlev) { GET_INSTANCE_DATA; U16 local_arfcn = arfcn & ARFCN_MASK; TRACE_FUNCTION("cs_add_to_black_list()"); /* "Region" and "arfcn" are used to index "Black List" database * Check whether they are within proper range */ if(!cs_check_region(region)) return; if(!cs_check_arfcn_range(local_arfcn)) return; /* Check Black List criteria */ if(cs_check_black_list_criteria(region,arfcn,rxlev)) { /* Add the channel to Black List */ srv_set_channel(&rr_data->cs_data.black_list.list[region],local_arfcn); /* Reset the sync fail counter for this channel. So that when this * carrier is removed from BL(BA_MA list), counter will start from zero * again */ cs_reset_sync_fail_counter(region, local_arfcn); TRACE_EVENT_P2("[%d]Reg[%d]Arfcn added to BL",region,local_arfcn); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_del_from_black_list | +--------------------------------------------------------------------+ PURPOSE : This routine removes the arfcn from black list and resets the sync fail counter for that arfcn CSI-LLD section:4.1.1.5.6 */ GLOBAL void cs_del_from_black_list(U8 region, U16 arfcn) { GET_INSTANCE_DATA; USHORT local_arfcn = arfcn & ARFCN_MASK; #ifdef TI_PS_FF_QUAD_BAND_SUPPORT UBYTE i; #endif TRACE_FUNCTION("cs_del_from_black_list()"); /* "Region" and "arfcn" are used to index "Black List" database * Check whether they are within proper range */ if(!cs_check_region(region)) return; if(!cs_check_arfcn_range(local_arfcn)) return; #ifdef TI_PS_FF_QUAD_BAND_SUPPORT if (region EQ BOTH_REGIONS) { for (i=0; i<MAX_REGIONS; i++) { if(srv_get_channel(&rr_data->cs_data.black_list.list[i],local_arfcn)) { /* Remove the channel from Black List */ srv_unset_channel(&rr_data->cs_data.black_list.list[i],local_arfcn); /* Reset the sync fail counter for this channel */ cs_reset_sync_fail_counter(i, local_arfcn); TRACE_EVENT_P2("ARFCN:%d Region:%d deleted from BL",local_arfcn,i); } } } else { #endif if(srv_get_channel(&rr_data->cs_data.black_list.list[region],local_arfcn)) { /* Remove the channel from Black List */ srv_unset_channel(&rr_data->cs_data.black_list.list[region],local_arfcn); /* Reset the sync fail counter for this channel */ cs_reset_sync_fail_counter(region, local_arfcn); TRACE_EVENT_P2("ARFCN:%d Region:%d deleted from BL",local_arfcn,region); } #ifdef TI_PS_FF_QUAD_BAND_SUPPORT } #endif } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_clear_black_list | +--------------------------------------------------------------------+ PURPOSE : This function is used to clear "Black List" database. The function clears the "Black List" database from 1) Only RAM 2) Only FFS 3) Both RAM and FFS. This function is called in the following cases 1) In response to "ERASE_BL" dynamic configuration command 2) After Initial PLMN search based on its outcome CSI-LLD section:4.1.1.5.1 */ GLOBAL void cs_clear_black_list(U8 erase_type) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cs_clear_black_list()"); /* clear Black List from RAM */ if(erase_type & CLR_BLACK_LIST_RAM) { memset(&rr_data->cs_data.black_list,0,sizeof(T_CS_BLACK_LIST)); TRACE_EVENT ("Black List: RAM cleared"); } /* Clear Black List from FFS */ #if defined(_SIMULATION_FFS_) if(erase_type & CLR_BLACK_LIST_FFS) { T_LIST local_black_list[MAX_REGIONS]; memset(&local_black_list[0],0,MAX_REGIONS*sizeof(T_LIST)); rr_csf_write_black_list(&local_black_list[0]); TRACE_EVENT ("Black List: FFS cleared"); } #endif } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_remove_BA_MA_from_black_list| +--------------------------------------------------------------------+ PURPOSE : This function is used to remove the GSM channels present in MA and BA lists from the "Black List". The function deletes these channels from the "Black List" and also resets their SFC counter to zero. This function is called whenever MS receives BA and MA list information in any RR message. CSI-LLD section:4.1.1.5.7 */ GLOBAL void cs_remove_BA_MA_from_black_list(U8 region, T_LIST *source_list) { GET_INSTANCE_DATA; TRACE_FUNCTION("cs_remove_BA_MA_from_black_list()"); /* "Region" is to index "Black List" database * Check whether it is within proper range */ if(!cs_check_region(region)) return; if(source_list NEQ NULL) { #ifdef TI_PS_FF_QUAD_BAND_SUPPORT if (region EQ BOTH_REGIONS) { cs_remove_BA_MA_from_black_list(EUROPEAN_REGION,source_list); cs_remove_BA_MA_from_black_list(AMERICAN_REGION,source_list); } else #endif srv_unmask_list(&rr_data->cs_data.black_list.list[region],source_list); TRACE_EVENT("BL updated with BA/MA/Inactive carrier list"); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_rem_inactive_carriers_from_bl| +--------------------------------------------------------------------+ PURPOSE : This function is used to remove the inactive carriers from the "Black List". This is done whenever the mobile changes LA/RA Cell Selection Improvements-LLD section:4.1.1.3.4 */ GLOBAL void cs_rem_inactive_carriers_from_bl(T_MPH_POWER_CNF *mph_power_cnf) { TRACE_FUNCTION("cs_remove_inactive_from_black_list"); /* Remove the inactive carriers from Black list for European region */ cs_remove_BA_MA_from_black_list(EUROPEAN_REGION, (T_LIST *)&mph_power_cnf->inactive_carrier_list.list[EUROPEAN_REGION]); /* Remove the inactive carriers from Black list for American region */ cs_remove_BA_MA_from_black_list(AMERICAN_REGION, (T_LIST *)&mph_power_cnf->inactive_carrier_list.list[AMERICAN_REGION]); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_is_in_black_list | +--------------------------------------------------------------------+ PURPOSE : This routine checks whether a carrier is already part of Black list or not CSI-LLD section:4.1.1.5.12 */ LOCAL BOOL cs_is_in_black_list(U8 region, U16 arfcn) { GET_INSTANCE_DATA; U8 status; status = srv_get_channel((T_LIST*)&rr_data->cs_data.black_list.list[region], (USHORT)arfcn & ARFCN_MASK); TRACE_EVENT_P3("[%d]Reg[%d]Arfcn, BL status:%d",region,arfcn,status); return status; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_is_in_white_list | +--------------------------------------------------------------------+ PURPOSE : This routine checks whether a carrier is part of White list or not CSI-LLD section:4.1.2.2.7 */ LOCAL BOOL cs_is_in_white_list(U8 region, U16 arfcn) { GET_INSTANCE_DATA; U8 status = FALSE; #ifdef TI_PS_FF_QUAD_BAND_SUPPORT if((rr_data->cs_data.white_list.region EQ BOTH_REGIONS) OR (region EQ rr_data->cs_data.white_list.region)) #else if(region EQ rr_data->cs_data.white_list.region) #endif { status = srv_get_channel(&rr_data->cs_data.white_list.list, ((U16)arfcn & ARFCN_MASK)); } TRACE_EVENT_P3("[%d]Reg[%d]Arfcn, WL status:%d", region,arfcn,status); return status; } /* +---------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_check_black_list_criteria| +---------------------------------------------------------------------+ PURPOSE : This function checks the criteria for adding a GSM channel to "Black List". GSM channels are added to "Black List" only after they satisfy this criteria. CSI-LLD section:4.1.1.5.13 */ LOCAL BOOL cs_check_black_list_criteria(U8 region,U16 arfcn,U8 rxlev) { GET_INSTANCE_DATA; UBYTE band_index; U16 local_arfcn = arfcn&ARFCN_MASK; TRACE_FUNCTION("cs_check_black_list_criteria()"); /* Check if the carrier is already present in the black list */ if(cs_is_in_black_list(region, local_arfcn)) return FALSE; /* Check if the carrier is present in White List */ if(cs_is_in_white_list(region, local_arfcn)) return FALSE; #ifdef TI_PS_FF_QUAD_BAND_SUPPORT band_index = cs_get_band_index(arfcn); #else band_index = get_band_index(arfcn); #endif /* RxLev of carrier is above upper threshold. Add the carrier * to Black List immediately */ if(rxlev >= rr_data->dyn_config.upper_rxlev_thr[band_index]) { return TRUE; } /* Reasonably strong carrier. Add to Black List only if its sync fail * counter criteria is satisfied */ if((rxlev >= rr_data->dyn_config.medium_rxlev_thr[band_index]) AND (rxlev < rr_data->dyn_config.upper_rxlev_thr[band_index])) { cs_inc_sync_fail_counter(region, local_arfcn); if(cs_get_sync_fail_counter(region, local_arfcn) >= MAX_SYNC_FAILURES) { return TRUE; } } return FALSE; } /* +----------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_update_black_list | +----------------------------------------------------------------+ PURPOSE : This function is used to update "Black List" database after initial PLMN search.It first clears the current "Black list" database from RAM and then adds some cells to "Black List" according to the current attrib-utes array values(BLACK_LIST_FLAG) of the Initial PLMN selection process. This function is called un-der the following cases 1.MS enters Limited or No service after Initial PLMN search 2.MS enters Full service in a different Location area from where it is switched off after initial PLMN search CSI-LLD section:4.1.1.5.8 */ GLOBAL void cs_update_black_list(void) { GET_INSTANCE_DATA; U8 update_black_list = FALSE; U8 i, region; TRACE_FUNCTION("cs_update_black_list()"); /* If the outcome of first FUNC_PLMN_SEARCH is not full service. * Erase the Black List */ if((rr_data->ms_data.req_mm_service EQ FUNC_PLMN_SRCH AND rr_data->ms_data.rr_service NEQ FULL_SERVICE)) { update_black_list = TRUE; } TRACE_EVENT_P8 ( "Old [%d]SC MCC/MNC r=%x%x%x/%x%x%x/%d", rr_data->cs_data.white_list.last_sc_arfcn, rr_data->cs_data.white_list.last_sc_lac.mcc[0], rr_data->cs_data.white_list.last_sc_lac.mcc[1], rr_data->cs_data.white_list.last_sc_lac.mcc[2], rr_data->cs_data.white_list.last_sc_lac.mnc[0], rr_data->cs_data.white_list.last_sc_lac.mnc[1], rr_data->cs_data.white_list.last_sc_lac.mnc[2], rr_data->cs_data.white_list.last_sc_lac.lac); TRACE_EVENT_P8 ( "New [%d]SC MCC/MNC r=%x%x%x/%x%x%x/%d", rr_data->nc_data[SC_INDEX].arfcn, rr_data->nc_data[SC_INDEX].lai.mcc[0], rr_data->nc_data[SC_INDEX].lai.mcc[1], rr_data->nc_data[SC_INDEX].lai.mcc[2], rr_data->nc_data[SC_INDEX].lai.mnc[0], rr_data->nc_data[SC_INDEX].lai.mnc[1], rr_data->nc_data[SC_INDEX].lai.mnc[2], rr_data->nc_data[SC_INDEX].lai.lac); /* If the current serving cell belongs to a different Location area. * Erase the Black List */ if((rr_data->ms_data.rr_service EQ FULL_SERVICE) AND ((rr_data->cs_data.white_list.last_sc_arfcn EQ NOT_PRESENT_16BIT) OR (!dat_plmn_equal_req(rr_data->cs_data.white_list.last_sc_lac.mcc, rr_data->cs_data.white_list.last_sc_lac.mnc, rr_data->nc_data[SC_INDEX].lai.mcc, rr_data->nc_data[SC_INDEX].lai.mnc)) OR (rr_data->cs_data.white_list.last_sc_lac.lac NEQ rr_data->nc_data[SC_INDEX].lai.lac))) { update_black_list = TRUE; } if(update_black_list) { /* Erase the current Black List */ cs_clear_black_list(CLR_BLACK_LIST_RAM); for(i=0;i<rr_data->cs_data.max_arfcn;i++) { if(CS_GET_BLACK_LIST_FLAG(i)) { /* Obtain the region */ region = CS_GET_REGION_FROM_FREQ(rr_data->cs_data.arfcn[i]); cs_add_to_black_list(region, (USHORT)(rr_data->cs_data.arfcn[i]), rr_data->cs_data.rxlev[i]); } } /* i < max_arfcn */ TRACE_EVENT("BL updated after inital PLMN search"); } } /* +----------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_store_black_list | +----------------------------------------------------------------------+ PURPOSE : This is a wrapper function for storing "Black List" information to FFS . This in turn calls rr_csf_write_black_list( ) to store "Black List" to FFS. This function is called during power off. CSI-LLD section:4.1.1.5.2 */ GLOBAL void cs_store_black_list(void) { GET_INSTANCE_DATA; #if defined(_SIMULATION_FFS_) rr_csf_write_black_list(&rr_data->cs_data.black_list.list[0]); #endif } /* +----------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_get_new_search_mode | +----------------------------------------------------------------------+ PURPOSE : This routine returns the new search mode depending on the timer active and the previous search mode CSI-LLD section:4.1.3.4.1.1 */ GLOBAL U8 cs_get_new_search_mode(void) { GET_INSTANCE_DATA; TRACE_FUNCTION("cs_get_new_search_mode()"); if(IS_TIMER_ACTIVE(T_FAST_CS)) { /* Fast search timer is active */ return FAST_SEARCH_MODE; } if(IS_TIMER_ACTIVE(T_NORMAL_CS)) { /* Normal search timer is active */ return NORMAL_SEARCH_MODE; } TRACE_EVENT_P1("Previous Search Mode : %d", rr_data->cs_data.previous_search_mode); if((rr_data->cs_data.previous_search_mode EQ FULL_SEARCH_MODE) OR (rr_data->cs_data.previous_search_mode EQ FAST_SEARCH_MODE)) { return NORMAL_SEARCH_MODE; } if(rr_data->cs_data.previous_search_mode EQ NORMAL_SEARCH_MODE) { return FULL_SEARCH_MODE; } return FULL_SEARCH_MODE; } /* +----------------------------------------------------------------------+ | PROJECT : GSM-PS (8403) MODULE : RR_CS | | STATE : code ROUTINE : cs_handle_search_mode_timer | +----------------------------------------------------------------------+ PURPOSE : This routine handles the timers for the new search modes CSI-LLD section:4.1.3.4.1.2 */ GLOBAL void cs_handle_search_mode_timer(U8 search_mode) { GET_INSTANCE_DATA; TRACE_FUNCTION("cs_handle_search_mode_timer()"); if((search_mode EQ FAST_SEARCH_MODE) AND (rr_data->dyn_config.tfast_cs_val)) { if(!IS_TIMER_ACTIVE(T_FAST_CS)) { TIMERSTART (T_FAST_CS,rr_data->dyn_config.tfast_cs_val); } } if((search_mode EQ NORMAL_SEARCH_MODE) AND (rr_data->dyn_config.tnormal_cs_val)) { if(!IS_TIMER_ACTIVE(T_NORMAL_CS)) { TIMERSTART (T_NORMAL_CS, rr_data->dyn_config.tnormal_cs_val); } } if(search_mode EQ FULL_SEARCH_MODE) { if(rr_data->sc_data.mm_started EQ MM_ORIGINATED AND rr_data->ms_data.req_mm_service NEQ FUNC_NET_SRCH_BY_MMI) { TIMERSTOP(T_FAST_CS); TIMERSTOP(T_NORMAL_CS); } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_CS | | STATE : code ROUTINE : cs_update_std_ffs | +--------------------------------------------------------------------+ PURPOSE : This function updates the std value depending upon the frequency band support by MS. Frequncy band support is available in the FFS. */ #ifdef TI_PS_FF_QUAD_BAND_SUPPORT LOCAL UBYTE cs_update_std_ffs (UBYTE new_std) { UBYTE freq_bands; rr_csf_get_freq_bands (&freq_bands); switch (new_std) { case STD_DUAL_EGSM: if ((freq_bands & BAND_GSM_850) EQ BAND_GSM_850) { return STD_850_900_1800; } break; case STD_DUAL_US: if ((freq_bands & BAND_GSM_900) EQ BAND_GSM_900) { return STD_850_900_1900; } break; default: TRACE_EVENT_P1 ("wrong std for updation using FFS %x", new_std); } return new_std; } #endif #endif