FreeCalypso > hg > freecalypso-sw
diff gsm-fw/g23m-gsm/rr/rr_attf.c @ 673:2f7df7a314f8
gsm-fw/g23m-gsm subtree: initial import from LoCosto source
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 28 Sep 2014 23:20:04 +0000 |
parents | |
children | a6f45d948d22 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/g23m-gsm/rr/rr_attf.c Sun Sep 28 23:20:04 2014 +0000 @@ -0,0 +1,9502 @@ +/* ++----------------------------------------------------------------------------- +| 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 the attachment +| capability of the module Radio Resource. ++----------------------------------------------------------------------------- +*/ + +#ifndef RR_ATTF_C +#define RR_ATTF_C + +#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" +#include "rr_em.h" +#include "cl_shrd.h" + +#if defined (_SIMULATION_) +#include <stdio.h> +#endif + + +/*==== EXPORT =====================================================*/ + +/*==== PRIVATE =====================================================*/ +LOCAL void rr_unpack_plmn (T_plmn *plmn, const UBYTE *packed, USHORT index); +/* OMAPS00085607 - N950 Memory Optimization */ +LOCAL void start_treg_timer(void); +#define TWO 2 + + +static void att_build_back_from_dedicated (void); +static void att_calculate_c2 (UBYTE index); +static SHORT att_calculate_c2_diff (UBYTE index); +static UBYTE att_calculate_digits (UBYTE *digits); + + +static BOOL att_cell_in_data_structures (T_MPH_MEASUREMENT_IND *report, + UBYTE index); +static UBYTE att_cell_in_measure_report (T_MPH_MEASUREMENT_IND *report, + UBYTE index); +static void att_check_2ter_read (UBYTE index); +static BOOL att_check_cell (void); +LOCAL UBYTE att_get_txpwr_max_cch (UBYTE index); +static void att_clear_forb_list (int list_type); +static void att_clear_parallel_search (void); +static void att_code_prr_mm_info (T_mm_info *mm_info); +static void att_copy_c2_parameter (T_C2_PARAMETER *c2_par, + T_si3_rest_oct *rest_oct ); +static void att_copy_c2_parameter_si3 (UBYTE index, + T_si3_rest_oct *rest_oct); +static void att_copy_found_plmn (T_FOUND_LIST * list, + USHORT n_in_source_85_dBm, + USHORT i_in_copy); +static void att_copy_rach_parameter (UBYTE index, + T_rach_ctrl *rach, + UBYTE indicate_changes); +static UBYTE att_get_highest_c2_index (void); +static UBYTE att_get_next_highest_c2_idx(UBYTE old_index); +static UBYTE att_get_next_highest_c2_val(void); +static UBYTE att_get_func (void); +static UBYTE att_get_next_highest_rx (void); +static void att_insert_cell_in_data (T_MPH_MEASUREMENT_IND *report, + UBYTE index); +static void att_order_plmns (void); +static USHORT att_number_of_plmns_greater_85_dBm (void); +static void att_copy_plmns_lower_or_equal_85_dBm (T_FOUND_LIST * list, USHORT i_in_copy); +static BOOL att_priority_check (void); +static void att_reorder_mph_ncell_req (T_MPH_NEIGHBOURCELL_REQ* + mph_ncell_req); +static void att_search_cell (void); +static void att_select_cell_dedicated (void); +static void att_try_old_cell (void); +static void att_print_selection_type (UBYTE selection_type); +/* Implements Measure#32: Row 36, 39 and 40 */ +static void att_print_op (T_op *op, + T_S2I_STRING titel); +static void att_begin_cs (UBYTE req_mm_service); + +#if defined (REL99) && defined (TI_PS_FF_EMR) +static void att_check_for_si5ter_and_enhpara (UBYTE old_index); +#endif + + + + +LOCAL void att_copy_sys_info_2bis_2ter_par(UBYTE index, T_SI_TYPE si_type, + T_LIST *new_2_bis_ter_list, + BUF_neigh_cell_desc *neigh_cell_desc, + UBYTE indicate_changes); + +/*==== VARIABLES ==================================================*/ +GLOBAL UBYTE test_house = FALSE; + +/*==== MACROS =====================================================*/ + +#if !defined (NTRACE) + +#define TRACE_C1(index)\ + TRACE_EVENT_P4 ("[%u]i%u C1=%-2d rxlev=%u",\ + rr_data->nc_data[index].arfcn,index,\ + rr_data->nc_data[index].c1,\ + rr_data->nc_data[index].rxlev) + +#define TRACE_C2(index)\ + TRACE_EVENT_P3 ("[%u]i%u C2=%-2d AT=%d",\ + rr_data->nc_data[index].arfcn,index,\ + rr_data->nc_data[index].c2,\ + rr_data->nc_data[index].avail_time) + +#define TRACE_C1_C2(index)\ + TRACE_EVENT_P6 ("[%u]i%u C1=%-2d C2=%-2d rxlev=%-2u AT=%d",\ + rr_data->nc_data[index].arfcn,index,\ + rr_data->nc_data[index].c1,\ + rr_data->nc_data[index].c2,\ + rr_data->nc_data[index].rxlev,\ + rr_data->nc_data[index].avail_time) + +#define TRACE_SELECTION_TYPE(type) att_print_selection_type(type) + +/* Implements Measure#32: Row 36, 39 and 40 */ +#define TRACE_OP_TYPE(op,titel) att_print_op (op, S2I_STRING(titel)) + +#else /* !NTRACE */ + +#define TRACE_C1(i) +#define TRACE_C2(i) +#define TRACE_C1_C2(i) +#define TRACE_SELECTION_TYPE(type) +#define TRACE_OP_TYPE(op,titel) + +#endif /* !NTRACE */ + +/*==== FUNCTIONS ==================================================*/ + +/* + * ------------------------------------------------------------------- + * Procedures + * ------------------------------------------------------------------- + */ +/* Implements Measure#32: Row 60 */ +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_print_forb_list ++--------------------------------------------------------------------+ + + PURPOSE : After a successful location updating request MM informs + RR about this. If the location area information is stored + inside of one of the forbidden location area lists this + information must be updated. In this function, the entry + is deleted from the given forbidden list. + +*/ + +LOCAL void att_print_forb_list ( int list_type, + const T_plmn * plmn, + USHORT lac, + unsigned int index, + BOOL to_delete) +{ + if(list_type EQ FORBIDDEN_LIST_NORMAL) + { + if(to_delete EQ FALSE) + { + TRACE_EVENT_P1 ( "ADD FORB LIST %u:", index); + } + else + { + TRACE_EVENT_P1 ( "DEL FORB LIST %u:", index); + } + } + else + { + if(to_delete EQ FALSE) + { + TRACE_EVENT_P1 ( "ADD FORB LIST %u:", index); + } + else + { + TRACE_EVENT_P1 ( "DEL ROAM FORB LIST %u:", index); + } + } + TRACE_EVENT_P7 ( " MCC/MNC=%x%x%x/%x%x%x LAC=%x", + plmn->mcc[0], + plmn->mcc[1], + plmn->mcc[2], + plmn->mnc[0], + plmn->mnc[1], + plmn->mnc[2], + lac); +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_add_to_forb_list | ++--------------------------------------------------------------------+ + + PURPOSE : RR stores a list of forbidden location area codes. After + a specific location updating reject cause this information + will be given by MM with a RR_SYNC_REQ. The check against + forbidden location areas is part of the cell selection and + cell reselection process. + +*/ + +GLOBAL void att_add_to_forb_list (int list_type, + const T_plmn *plmn, + USHORT lac) +{ + GET_INSTANCE_DATA; + int i; + T_loc_area_ident *forb_list; + + if (list_type EQ FORBIDDEN_LIST_NORMAL) + forb_list = &rr_data->ms_data.forb_lac_list[0]; + else + forb_list = &rr_data->ms_data.roam_forb_lac_list[0]; + + TRACE_FUNCTION ("att_add_to_forb_list()"); + + for (i = 0; i < MAX_LAI; i++) + { + /* + * Check whether the location area code is already stored. In + * this case it is not necessary to store it again + */ + if ((lac EQ forb_list[i].lac) AND + dat_plmn_equal_req (plmn->mcc, plmn->mnc, + forb_list[i].mcc, forb_list[i].mnc)) + break; + } + + if (i EQ MAX_LAI) + { + /* + * Location Area Code is not stored yet. Look for a free entry + * and store the location area code. + */ + for (i = 0; i < MAX_LAI; i++) + { + if (forb_list[i].lac EQ NOT_PRESENT_16BIT) + { + memcpy (forb_list[i].mcc, plmn->mcc, SIZE_MCC); + memcpy (forb_list[i].mnc, plmn->mnc, SIZE_MNC); + forb_list[i].lac = lac; + break; + } + } + + if (i EQ MAX_LAI) + { + /* + * all entries are used. Then delete the first (and oldest) one, + * move each entry and store the new one in the last position. + */ + memmove (&forb_list[0], &forb_list[1], + sizeof (T_loc_area_ident) * (MAX_LAI-1)); + memcpy (forb_list[MAX_LAI-1].mcc, plmn->mcc, SIZE_MCC); + memcpy (forb_list[MAX_LAI-1].mnc, plmn->mnc, SIZE_MNC); + forb_list[MAX_LAI-1].lac = lac; + i--; + } + } + +/* Implements Measure#32: Row 4 */ + att_print_forb_list ( list_type, plmn, lac, i, FALSE); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_analyze_measure_report | ++--------------------------------------------------------------------+ + + PURPOSE : After reception of a MPH_MEASUREMENT_IND from layer 1 the + channels are analyzed for a cell reselection decision. + +*/ + +GLOBAL void att_analyze_measure_report (T_MPH_MEASUREMENT_IND *report) +{ + GET_INSTANCE_DATA; + UBYTE i = 0; + + TRACE_FUNCTION ("att_analyze_measure_report()"); + + /* + * The variable no_reselect controls the condition not to perform a + * new cell reselection due to C2(NC) > C2(SC) after a cell reselection + * for 15 seconds + */ + + /* + * The fieldtest has shown, that sometimes the serving cell was also reported + * as a neighbourcell. This function removes double entries + */ + att_remove_multiple_channels (); + + /* + * All possible neighbourcells plus the serving cell are checked. + */ + for (i = 0; i < 6; i++) + { + /* + * The tnnn variable controls the condition that a cell is barred for five seconds + * for cell reselection purposes after a random access failure. + */ + /* + * check the status of a cell using the data stored in RR for neighbour- and serving + * cell. + */ + switch (rr_data->nc_data[i].bcch_status) + { + case EMPTY: + /* + * RR has nothing stored in this area. So there is nothing to do. + */ + break; + + case DECODED: + /* + * In this area RR has stored Data for a neighbourcell. The status is decoded, + * that means RR has received a system information 3,4,7 or 8 to calculate + * the cell reselection criterion C2. + * + * Now it is checked against the incoming measurement report. + */ + switch (att_cell_in_measure_report (report, i)) + { + case CELL_IS_INSERTED: + /* + * The cell is still included in the measurement report, that means + * it is one of the six strongest carrier and layer 1 is synchronized + * to the cell. + * + * The time how long the cell is already synchronized is stored up to + * a period of 700 seconds. This informatin is used for the calculation + * of the cell reselection criterion C2 which may has a time dependent + * factor. In fact the frames of layer 1 are counted. + */ + if (rr_data->nc_data[i].avail_time < PERIOD_700_SEC) + rr_data->nc_data[i].avail_time += rr_data->ms_data.fn_offset; + break; + + case BSIC_HAS_CHANGED: + /* + * The cell is still included in the measurement report, but layer1 + * has detected a change of the BSIC during re-synchronisation on the + * SB channel. So the stored information for calculation of C2 is useless + * and the status and the avail time is cleared. + */ + + rr_data->nc_data[i].bcch_status = NON_DECODED; + rr_data->nc_data[i].avail_time = 0; + break; + + case CELL_IS_NOT_INSERTED: + /* + * The cell is not longer included. The area in RR is released. + */ + rr_data->nc_data[i].bcch_status = EMPTY; + break; + } + break; + + case NON_DECODED: + /* + * RR has already stored this cell in its data, but has not received + * the needed information for calculation of cell reselection criterion C2. + * + * Now it is checked against the incoming measurement report. + */ + switch (att_cell_in_measure_report (report, i)) + { + case CELL_IS_INSERTED: + /* + * The cell is still included. For later calculation of the cell + * reselection criterion C2 the time is counted for which the cell + * is synchronized. + */ + if (rr_data->nc_data[i].avail_time < PERIOD_700_SEC) + rr_data->nc_data[i].avail_time += rr_data->ms_data.fn_offset; + break; + + case BSIC_HAS_CHANGED: + /* + * The layer 1 indicated that the BSIC has changed during re-synchronisation + * to the SB channel. The status will not change, but the avail time is + * resetted. + */ + rr_data->nc_data[i].avail_time = 0; + break; + + case CELL_IS_NOT_INSERTED: + /* + * Layer 1 indicates that the cell is not longer one of the six strongest or + * that the synchronisation has been lost. The storage area in RR is released. + */ + rr_data->nc_data[i].bcch_status = EMPTY; + rr_data->nc_data[i].avail_time = 0; + break; + } + break; + } + } + + /* + * store the Fieldstrength of the serving cell and update the information + * of the power campaign. + */ + rr_data->nc_data[SC_INDEX].rxlev = report->rx_lev_full; + cs_set_rxlev (report->rx_lev_full, rr_data->nc_data[SC_INDEX].arfcn); + + if (rr_data->nc_data[SC_INDEX].rxlev > + rr_data->lup_rxlev + 10) + { + /* + * A fieldstrength jump more then 10 dBm has been detected. This can be the + * trigger for MM to restart a location updating request if needed. It indicates + * for example that the mobile has left a tunnel area without coverage. + * + * This is not used by MM if a test SIM is inserted. It is an improvement for + * the field beside the GSM specifications. + */ + PALLOC (sync, RR_SYNC_IND); + + sync->ciph = NOT_PRESENT_8BIT; + sync->chm.ch_mode = NOT_PRESENT_8BIT; + sync->synccs = SYNCCS_LUP_RETRY; + sync->mm_info.valid = FALSE; + sync->bcch_info.v_bcch = FALSE; + + PSENDX (MM, sync); + + /* + * Store the new value to avoid multiple signalling of the fieldstrength jump + */ + rr_data->lup_rxlev = rr_data->nc_data[SC_INDEX].rxlev; + } + + /* + * Now look for all neighbourcells in the measurement report if they are new. + */ + for (i = 0; i < report->ncells.no_of_ncells; i++) + { + cs_set_rxlev (report->ncells.rx_lev[i], report->ncells.arfcn[i]); + /* + * If a channel is not inside the RR data structure, insert the cell + */ + if (! att_cell_in_data_structures (report, i)) + att_insert_cell_in_data (report, i); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_bcch_status_to_decoded | ++--------------------------------------------------------------------+ + + PURPOSE : After reception of the system information type 3,4,7 or 8 + the status of a cell changes from NON_DECODED to DECODED + and it is possible to calculate the cell reselection + criterion C2. + +*/ + +GLOBAL void att_bcch_status_to_decoded (UBYTE index) +{ + GET_INSTANCE_DATA; + TRACE_EVENT_P2 ("[%u]%u att_bcch_status_to_decoded()", rr_data->nc_data[index].arfcn, index); + + rr_data->nc_data[index].bcch_status = DECODED; + rr_data->nc_data[index].bcch_counter = 0; + rr_data->nc_data[index].c1_counter = 0; + #ifdef GPRS + if( rr_data->gprs_data.use_c31 NEQ TRUE ) + { + #endif + + if ((rr_data->c_ncell_bcch > 0) AND (rr_data->c_ncell_bcch NEQ NOT_INITIALISED)) + rr_data->c_ncell_bcch--; + + if (rr_data->resel_pending) + { + if (rr_data->c_ncell_bcch EQ 0) + { + SET_STATE (STATE_ATT, ATT_CON_EST); +#ifdef GPRS + att_start_cell_reselection_gprs(CELL_RESELECTION_RACH); +#else + att_start_cell_reselection(CELL_RESELECTION_RACH); +#endif + rr_data->resel_pending = FALSE; + rr_data->c_ncell_bcch = NOT_INITIALISED; + } + } + else + { + att_calculate_c2 (index); + } +#ifdef GPRS + } + else + { + if( rr_data->nc_data[index].v_cr_par EQ CR_PAR_INVALID ) + { + att_convert_idle_c31_cr(index); + } + else + { + TRACE_EVENT_P2(" arfcn %d, index = %d has valid CR_ PAR", rr_data->nc_data[index].arfcn, index); + } + } + #endif +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_bits_to_byte | ++--------------------------------------------------------------------+ + + PURPOSE : The function is used to calculate the positions of 1-bits + into a byte array. This is needed for calculation of a + frequency hopping list for a mobile allocation. The input + parameter are the bitmap and the size of the bitmap in bytes. + The result is a byte array containing the positions of 1-bits + followed by an end identifier NOT_PRESENT_8BIT (0xFF). The + maximum size of the incoming array is 32 bytes. + + Example: a mobile allocation looks like this: + + 0x42 = 0b01000010 -> bit 15 14 13 12 11 10 9 8 + 0x81 = 0b10000001 -> bit 7 6 5 4 3 2 1 0 + + The size of the input array is 2 and the output is: + + 1,8,10,15,0xFF (starting with position 1 in bit 0) + +*/ + +GLOBAL void att_bits_to_byte (UBYTE * num, + UBYTE size, + UBYTE * bits) +{ + SHORT ix; + UBYTE bit; + UBYTE buf_ix; + + TRACE_FUNCTION ("att_bits_to_byte()"); + + /* + * For all bytes in the input field + */ + for (ix = 0; ix < size; ix++) + { + buf_ix = bits[size-1-ix]; + + /* + * for each bit inside this byte + */ + bit = 0; + while (8 > bit) + { + if (buf_ix & (1 << bit)) + { + /* + * If bit is set, store the position in the output field + */ + *num++ = ((USHORT)ix << 3) + bit + 1; + } + bit++; + } + } + /* + * add the end identifier + */ + *num = NOT_PRESENT_8BIT; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_build_cbch | ++--------------------------------------------------------------------+ + + PURPOSE : configure at the end of the cell selection the CBCH channel + in layer 1. The CBCH channel is optional defined in system + information type 4. + When the cell has PBCCH and it is a Release-99 cell, + the CBCH configuration should be taken from gprs database. + This information is provided by GRR through RRGRR_CBCH_INFO_IND. + CBCH channel configuration is received on PBCCH on PSI8. +*/ + +#ifdef REL99 +LOCAL void att_build_cbch (void) +#else +GLOBAL void att_build_cbch (void) +#endif +{/*lint -e813 supress info of length of T_LIST*/ + GET_INSTANCE_DATA; + T_LIST hop_list; + PALLOC (cbch_req, MPH_CBCH_REQ); + + TRACE_FUNCTION ("att_build_cbch()"); + + /* + * Initialize the primitive to layer 1 + */ + memset (cbch_req, 0, sizeof (T_MPH_CBCH_REQ)); + if (rr_data->ms_data.rr_service EQ FULL_SERVICE) + { + /* + * CBCH is activated only if RR is in full service + */ + if (rr_data->sc_data.cd.cbch_chan_desc_avail NEQ NO_CONTENT ) + { + /* + * If a CBCH channel description has been received with + * system information tpye 4, activate the channel in layer 1. + */ + cbch_req->cbch.stat = STAT_ACT; + cbch_req->cbch.ch = rr_data->sc_data.cd.cbch_chan_desc.chan_type; + cbch_req->cbch.tn = rr_data->sc_data.cd.cbch_chan_desc.tn; + cbch_req->cbch.tsc = rr_data->sc_data.cd.cbch_chan_desc.tsc; + cbch_req->cbch.h = rr_data->sc_data.cd.cbch_chan_desc.hop; + + switch (cbch_req->cbch.h) + { + case H_NO: + /* + * CBCH does not use frequency hopping, then configure simply the + * channel number + */ + cbch_req->cbch.arfcn = rr_data->sc_data.cd.cbch_chan_desc.arfcn; + break; + + case H_FREQ: + /* + * CBCH uses frequency hopping, then configure MAIO and HSN + * and create a frequency hopping list from the cell channel + * description in system information 1 and the mobile allocation + * in system information 4. + */ + cbch_req->cbch.maio = rr_data->sc_data.cd.cbch_chan_desc.maio; + cbch_req->cbch.hsn = rr_data->sc_data.cd.cbch_chan_desc.hsn; + srv_create_chan_mob_alloc (&rr_data->sc_data.cd.cell_chan_desc, + &hop_list, + rr_data->sc_data.cd.cbch_mob_alloc); + + /* CSI-LLD section:4.1.1.11 + * This function Updates the black list with the MA list received + * in the CBCH allocation + */ + cs_remove_BA_MA_from_black_list(rr_data->cs_data.region,&hop_list); + + srv_create_list (&hop_list, cbch_req->cbch.ma, MAX_MA_CHANNELS, TRUE, + 0); + break; + } + } + else + /* + * In all other cases configure layer 1 without CBCH. + */ + cbch_req->cbch.stat = STAT_INACT; + } + + PSENDX (PL, cbch_req); +} + +#ifdef REL99 +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_config_cbch | ++--------------------------------------------------------------------+ + + PURPOSE : The following conditions have to be satisfied for + configuring CBCH. + 1. Full service should have been enabled. + 2. Mobile should be in idle/packet mode. + This function checks these conditions before configuring + CBCH. If function is called during packet transfer mode, + a flag in GPRS data is set signalling that this function + should be called again after entering idle mode. +*/ +GLOBAL void att_config_cbch (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_config_cbch()"); + /* + * CBCH is activated only if RR is in full service + */ + if ((rr_data->ms_data.rr_service EQ FULL_SERVICE) ) + { +#ifdef GPRS + /* check if mobile is in PTM */ + if(!dat_gprs_cell_in_ptm()) + { + /* mobile is NOT in packet transfer mode */ + + if(!att_gprs_cell_has_pbcch() OR !att_gprs_get_nw_release()) + { + /* This cell does not have pbcch, + * OR this is a R - 98 or lower cell. + * hence take info stored in SI 4 + */ +#endif /* GPRS */ + att_build_cbch(); +#ifdef GPRS + } + else + { + /* This Cell has PBCCH and also this is Release-99 cell. + * Configure ALR if CBCH info is available form GRR. + */ + if(rr_data->gprs_data.cbch_psi_valid) + { + PALLOC (cbch_req, MPH_CBCH_REQ); + memcpy(&(cbch_req->cbch), + &(rr_data->gprs_data.cbch_psi8), + sizeof(T_cbch)); + PSENDX (PL, cbch_req); + } + /*else wait till CBCH info is received from GRR */ + } + rr_data->gprs_data.cbch_info_rxvd_in_ptm = FALSE; + } + else + { + rr_data->gprs_data.cbch_info_rxvd_in_ptm = TRUE; + } +#endif /* GPRS */ + } + else + { +#ifdef GPRS + if(!dat_gprs_cell_in_ptm()) +#endif /* GPRS */ + { + PALLOC (cbch_req, MPH_CBCH_REQ); + memset (cbch_req, 0, sizeof (T_MPH_CBCH_REQ)); + cbch_req->cbch.stat = STAT_INACT; + PSENDX (PL, cbch_req); + } + } +} +#endif + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_build_classmark_req | ++--------------------------------------------------------------------+ + + PURPOSE : Configure at the end of the cell selection the classmark of + the mobile to layer 1. This information is used by layer 1 + for random access. + +*/ + +GLOBAL void att_build_classmark_req (void) +{ + GET_INSTANCE_DATA; + PALLOC (classmark_req, MPH_CLASSMARK_REQ); + + TRACE_FUNCTION ("att_build_classmark_req()"); + +#if defined (_SIMULATION_) + /* + * In the windows simulation it is necessary to read the data + * from the non-volantile memory (PCM) again. + */ + rr_csf_check_rfcap (FALSE); +#endif + + if((std EQ STD_DUAL) OR (std EQ STD_DUAL_EGSM)) + { + classmark_req->classmark.pclass = rr_data->ms_data.rf_cap.rf_power.pow_class4[IDX_PWRCLASS_900].pow_class-1; + classmark_req->classmark.pclass2 = rr_data->ms_data.rf_cap.rf_power.pow_class4[IDX_PWRCLASS_1800].pow_class-1; + } + else if(std EQ STD_DUAL_US) + { + classmark_req->classmark.pclass = rr_data->ms_data.rf_cap.rf_power.pow_class4[IDX_PWRCLASS_850].pow_class-1; + classmark_req->classmark.pclass2 = rr_data->ms_data.rf_cap.rf_power.pow_class4[IDX_PWRCLASS_1900].pow_class-1; + } + else + { + /* + * In single bands only one power class is forwarded to layer 1. + */ +#ifdef GPRS + +#ifdef REL99 + classmark_req->classmark.pclass = rr_data->ms_data.ra_cap.ra_cap_values.acc_cap.pow_class-1; +#else + classmark_req->classmark.pclass = rr_data->ms_data.ra_cap.acc_cap.pow_class-1; +#endif + +#else + if (std EQ STD_1900) + { + classmark_req->classmark.pclass = rr_data->ms_data.classmark3.pcs1900_cap-1; + } + else if (std EQ STD_850) + { + classmark_req->classmark.pclass = rr_data->ms_data.classmark3.gsm850_cap-1; + } + else + { + classmark_req->classmark.pclass = rr_data->ms_data.classmark3.radio_cap_1-1; + } +#endif + classmark_req->classmark.pclass2= 0; + } + PSENDX (PL, classmark_req ); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_build_idle_req | ++--------------------------------------------------------------------+ + + PURPOSE : The function is used to configure the idle mode in layer 1. + Two modes are possible: cell selection and cell reselection. + In cell selection mode RR has all information to perform + a complete layer 1 configuration. In cell reselection mode + layer 1 is configured only as much as needed and it is + expected that layer 1 goes in paging reorganization mode + to catch all pagings and BCCH messages. +*/ + +GLOBAL void att_build_idle_req (UBYTE index, + UBYTE mode) +{ + GET_INSTANCE_DATA; + T_CELL_DATA *cd; + PALLOC (idle_req, MPH_IDLE_REQ); + + TRACE_FUNCTION ("att_build_idle_req()"); + + /* + * configure the mode of layer 1 (cell selection or cell reselection + */ + idle_req->mod = mode; + + /* + * set the pointer to the correct data + * serving cell or one of the neighbourcells. + */ + if (index EQ SC_INDEX) + { + cd = &rr_data->sc_data.cd; +#if defined (REL99) && defined (TI_PS_FF_EMR) + idle_req->si2quater_status = cd->si2quater_status; + idle_req->si2quater_pos = cd->si2quater_pos; + + if ( (mode EQ MODE_CELL_SELECTION ) AND + (cd->si2quater_status EQ SI2QUATER_CONFIGURE) AND + ((rr_data->sc_data.cd.sys_info_read & (ALL_SYS_INFO_READ | SYS_INFO_2QUATER_READ)) EQ ALL_SYS_INFO_READ)) + rr_data->sc_data.cd.si2quater_status = SI2QUATER_ACQ_PENDING; +#endif + } + else + { +#if defined (REL99) && defined (TI_PS_FF_EMR) + idle_req->si2quater_status = SI2QUATER_ABSENT; +#endif + cd = &rr_data->cr_data.cd; + } + + /* + * look to the reached service of RR + */ + switch (rr_data->ms_data.rr_service) + { + case LIMITED_SERVICE: + /* + * In limited mode no pagings are possible. To save + * power the minimum number of measurements (equal + * to a long paging period) is configured. + * The other parameters are independent from BCCH or + * SIM card, because paging is not possible. + */ + idle_req->pg = 0; + idle_req->tn = 0; + idle_req->ncc_permitted = NOT_PRESENT_8BIT; + idle_req->dlt = 10; /* for bs_pa_mfmrs = 9 */ + idle_req->bs_pa_mfrms = 7; /* for bs_pa_mfmrs = 9 */ + break; + + case FULL_SERVICE: + /* + * The MS is in full service. In this case the paging + * block must be correctly from the SIM and the BCCH + * data. + */ + idle_req->pg = dat_calc_paging_group (index); + idle_req->tn = dat_calc_tn (index); + + /* + * The NCC permitted check in layer 1 is used to + * avoid synchronisation to cells of other networks. + */ +#ifdef GPRS + if(mode NEQ MODE_CELL_RESELECTION AND + mode NEQ MODE_CELL_RESELECTION_SYNC_ONLY) +#else + if (mode NEQ MODE_CELL_RESELECTION) +#endif + idle_req->ncc_permitted = cd->ncc_permitted; + else + idle_req->ncc_permitted = NOT_PRESENT_8BIT; + + idle_req->dlt = dat_calc_downlink_timeout (index); + idle_req->bs_pa_mfrms = rr_data->nc_data[index].control_descr.bs_pa_mfrms; + break; + } + idle_req->arfcn = rr_data->nc_data[index].arfcn; + + /* XXX + * use ext_bcch for forwarding bsic, this solves + * fieldtest problem of mismatch of BSICs. + */ + idle_req->ext_bcch = rr_data->nc_data[index].bsic; + + idle_req->comb_ccch = rr_data->nc_data[index].control_descr.ccch_conf EQ COMB_CCCH_COMB; + idle_req->bs_ag_blocks_res = + rr_data->nc_data[index].control_descr.bs_ag_blks_res; + + idle_req->power = att_get_txpwr_max_cch (index); + + idle_req->reorg_only = NORMAL_PGM; + idle_req->gprs_support = NOT_PRESENT_8BIT; +#if defined FF_EOTD +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + idle_req->eotd_avail = (std EQ STD_1900 OR std EQ STD_850 OR std EQ STD_DUAL_US OR std EQ STD_850_1800 OR std EQ STD_850_900_1800 OR std EQ STD_850_900_1900); +#else + idle_req->eotd_avail = (std EQ STD_1900 OR std EQ STD_850 OR std EQ STD_DUAL_US); +#endif +#else + idle_req->eotd_avail = 0; +#endif + +#ifdef GPRS + att_gprs_idle_req(idle_req); +#endif + + EM_IDLE_MODE; + +#if defined(_SIMULATION_) + switch (idle_req->mod) + { + case MODE_CELL_SELECTION : /* 0x0 cell selection */ + TRACE_EVENT_WIN ("MODE_CELL_SELECTION"); + break; + case MODE_CELL_RESELECTION : /* 0x1 cell reselection */ + TRACE_EVENT_WIN ("MODE_CELL_RESELECTION"); + break; +#if defined(MODE_BACK_FROM_DEDICATED) + case MODE_BACK_FROM_DEDICATED : /* 0x2 back from dedicated */ + TRACE_EVENT_WIN ("MODE_BACK_FROM_DEDICATED"); + break; +#endif /* MODE_BACK_FROM_DEDICATED */ + case MODE_IMM_ASSIGN : /* 0x3 immediate assignment */ + TRACE_EVENT_WIN ("MODE_IMM_ASSIGN"); + break; + case MODE_CHAN_ASSIGN : /* 0x4 channel assignment */ + TRACE_EVENT_WIN ("MODE_CHAN_ASSIGN"); + break; + case MODE_ASYNC_HANDOVER : /* 0x5 asynchronous handover */ + TRACE_EVENT_WIN ("MODE_ASYNC_HANDOVER"); + break; + case MODE_SYNC_HANDOVER : /* 0x6 synchronous handover */ + TRACE_EVENT_WIN ("MODE_SYNC_HANDOVER"); + break; + case MODE_PRE_SYNC_HANDOVER : /* 0x7 pre synchronous handover */ + TRACE_EVENT_WIN ("MODE_PRE_SYNC_HANDOVER"); + break; + case MODE_PSEUDO_SYNC_HANDOVER: /* 0x8 pseudo synchronous handover */ + TRACE_EVENT_WIN ("MODE_PSEUDO_SYNC_HANDOVER"); + break; + case MODE_SYS_INFO_CHANGE : /* 0x9 sys info has changed */ + TRACE_EVENT_WIN ("MODE_SYS_INFO_CHANGE"); + break; + case MODE_PACKET_TRANSFER : /* 0xa enter packet transfer mode */ + TRACE_EVENT_WIN ("MODE_PACKET_TRANSFER"); + break; + case MODE_PDCH_ASSIGN : /* 0xb PDCH assignment */ + TRACE_EVENT_WIN ("MODE_PDCH_ASSIGN"); + break; + case MODE_CELL_CHANGE_ORDER : /* 0xc Network controlled Cell Change */ + TRACE_EVENT_WIN ("MODE_CELL_CHANGE_ORDER"); + break; + case MODE_CELL_RESELECTION_SYNC_ONLY: /* 0xc Network controlled Cell Change */ + TRACE_EVENT_WIN ("MODE_CR_SYNC_ONLY"); + break; + case MODE_CONFIG_PL: /* PBCCH */ + TRACE_EVENT_WIN ("MODE_CONFIG_PL"); + break; + default: + TRACE_EVENT_WIN_P1 ("idle_req mode %d unknown!", idle_req->mod); + break; + } +#endif /* _SIMULATION_ */ + if ((mode EQ MODE_CELL_SELECTION) AND + (rr_data->ms_data.rr_service EQ FULL_SERVICE) AND + (rr_data->cs_data.act_index NEQ NOT_PRESENT_8BIT)) + { + rr_data->cs_data.act_index = NOT_PRESENT_8BIT; + rr_csf_fit_capability (); +#if !defined(NTRACE) + rr_csf_trace_power (); +#endif /* !NTRACE */ + } + PSENDX (PL, idle_req); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_calculate_c1 | ++--------------------------------------------------------------------+ + + PURPOSE : The function calculates the path loss criterion C1 for + cell selection and cell reselection purposes. + + REFERENCE: GSM 5.08, chapter 6.4 Criteria for cell selection and reselection + +*/ + +/* + * The following tables define conversion for the power in dBm depending + * on the frequency band (GSM, DCS or PCS) and the power class (1 to 5). + */ + +/*lint -esym(765,p_dcs) | external could be made static | used by GRR */ +/*lint -esym(765,p_pcs) | external could be made static | used by GRR */ +/*lint -esym(765,p_gsm) | external could be made static | used by GRR */ +/*lint -esym(765,p_control_dcs) | external could be made static | used by GRR */ +/*lint -esym(765,p_control_pcs) | external could be made static | used by GRR */ +/*lint -esym(765,p_control_gsm) | external could be made static | used by GRR */ +const SHORT p_dcs [MAX_CLASSES] = { P_CLASS_1_1800, + P_CLASS_2_1800, + P_CLASS_3_1800, + P_CLASS_3_1800, + P_CLASS_3_1800 }; + + +const SHORT p_pcs [MAX_CLASSES] = { P_CLASS_1_1900, + P_CLASS_2_1900, + P_CLASS_3_1900, + P_CLASS_3_1900, + P_CLASS_3_1900 }; + +const SHORT p_gsm [MAX_CLASSES] = { P_CLASS_2_900, + P_CLASS_2_900, + P_CLASS_3_900, + P_CLASS_4_900, + P_CLASS_5_900 }; + + +/* + * The following tables converts the air-interface coding of + * the system information parameter MAX_TXPWR_CCCH to a value + * in dBm depending on the frequency standard (GSM, DCS or PCS). + */ +const UBYTE p_control_gsm [32] = +{ 39, /* 0 -> 39 dBm */ + 39, /* 1 -> 39 dBm */ + 39, /* 2 -> 39 dBm */ + 37, /* 3 -> 37 dBm */ + 35, /* 4 -> 35 dBm */ + 33, /* 5 -> 33 dBm */ + 31, /* 6 -> 31 dBm */ + 29, /* 7 -> 29 dBm */ + 27, /* 8 -> 27 dBm */ + 25, /* 9 -> 25 dBm */ + 23, /* 10 -> 23 dBm */ + 21, /* 11 -> 21 dBm */ + 19, /* 12 -> 19 dBm */ + 17, /* 13 -> 17 dBm */ + 15, /* 14 -> 15 dBm */ + 13, /* 15 -> 13 dBm */ + 11, /* 16 -> 11 dBm */ + 9, /* 17 -> 9 dBm */ + 7, /* 18 -> 7 dBm */ + 5, /* 19 -> 5 dBm */ + 5, /* 20 -> 5 dBm */ + 5, /* 21 -> 5 dBm */ + 5, /* 22 -> 5 dBm */ + 5, /* 23 -> 5 dBm */ + 5, /* 24 -> 5 dBm */ + 5, /* 25 -> 5 dBm */ + 5, /* 26 -> 5 dBm */ + 5, /* 27 -> 5 dBm */ + 5, /* 28 -> 5 dBm */ + 5, /* 29 -> 5 dBm */ + 5, /* 30 -> 5 dBm */ + 5 /* 31 -> 5 dBm */ +}; + +const UBYTE p_control_dcs [32] = +{ 30, /* 0 -> 30 dBm */ + 28, /* 1 -> 28 dBm */ + 26, /* 2 -> 26 dBm */ + 24, /* 3 -> 24 dBm */ + 22, /* 4 -> 22 dBm */ + 20, /* 5 -> 20 dBm */ + 18, /* 6 -> 18 dBm */ + 16, /* 7 -> 16 dBm */ + 14, /* 8 -> 14 dBm */ + 12, /* 9 -> 12 dBm */ + 10, /* 10 -> 10 dBm */ + 8, /* 11 -> 8 dBm */ + 6, /* 12 -> 6 dBm */ + 4, /* 13 -> 4 dBm */ + 2, /* 14 -> 2 dBm */ + 0, /* 15 -> 0 dBm */ + 0, /* 16 -> 0 dBm */ + 0, /* 17 -> 0 dBm */ + 0, /* 18 -> 0 dBm */ + 0, /* 19 -> 0 dBm */ + 0, /* 20 -> 0 dBm */ + 0, /* 21 -> 0 dBm */ + 0, /* 22 -> 0 dBm */ + 0, /* 23 -> 0 dBm */ + 0, /* 24 -> 0 dBm */ + 0, /* 25 -> 0 dBm */ + 0, /* 26 -> 0 dBm */ + 0, /* 27 -> 0 dBm */ + 0, /* 28 -> 0 dBm */ + 36, /* 29 -> 36 dBm */ + 34, /* 30 -> 34 dBm */ + 32 /* 31 -> 32 dBm */ +}; + +const UBYTE p_control_pcs [32] = +{ 30, /* 0 -> 30 dBm */ + 28, /* 1 -> 28 dBm */ + 26, /* 2 -> 26 dBm */ + 24, /* 3 -> 24 dBm */ + 22, /* 4 -> 22 dBm */ + 20, /* 5 -> 20 dBm */ + 18, /* 6 -> 18 dBm */ + 16, /* 7 -> 16 dBm */ + 14, /* 8 -> 14 dBm */ + 12, /* 9 -> 12 dBm */ + 10, /* 10 -> 10 dBm */ + 8, /* 11 -> 8 dBm */ + 6, /* 12 -> 6 dBm */ + 4, /* 13 -> 4 dBm */ + 2, /* 14 -> 2 dBm */ + 0, /* 15 -> 0 dBm */ + 0, /* 16 -> 0 dBm */ + 0, /* 17 -> 0 dBm */ + 0, /* 18 -> 0 dBm */ + 0, /* 19 -> 0 dBm */ + 0, /* 20 -> 0 dBm */ + 0, /* 21 -> 0 dBm */ + 33, /* 22 -> 33 dBm */ + 33, /* 23 -> 33 dBm */ + 33, /* 24 -> 33 dBm */ + 33, /* 25 -> 33 dBm */ + 33, /* 26 -> 33 dBm */ + 33, /* 27 -> 33 dBm */ + 33, /* 28 -> 33 dBm */ + 33, /* 29 -> 33 dBm */ + 33, /* 30 -> 33 dBm */ + 32 /* 31 -> 32 dBm */ +}; +/*lint +e765 / used by GRR */ + +GLOBAL void att_calculate_c1 (UBYTE index) +{ + GET_INSTANCE_DATA; + SHORT a; + SHORT b; + const SHORT *p; + const UBYTE *p_control; + SHORT power_offset = 0; + UBYTE ms_power; + SHORT offset; + + TRACE_FUNCTION ("att_calculate_c1()"); + + ms_power = att_get_power (); + switch (std) + { + case STD_900: + case STD_EGSM: + case STD_850: + /* + * The table for the power class conversion is GSM 900, E-GSM or GSM 850 + */ + p = p_gsm; + /* + * The table for the MAX_TXPWR_CCCH conversion is GSM 900, E-GSM or GSM 850 + */ + p_control = p_control_gsm; + /* + * The gsm_offset parameter can be set by a dynamic configuration command + * and is not used. + */ + offset = rr_data->dyn_config.gsm_offset; + break; + + case STD_1900: + p = p_pcs; + p_control = p_control_pcs; + + /* + * The dcs_offset parameter can be set by a dynamic configuration command + * and is not used. + */ + offset = rr_data->dyn_config.dcs_offset; + break; + + case STD_1800: + p = p_dcs; + p_control = p_control_dcs; + + /* Ref 04.18 Section 10.5.2.35 + * Rest Octets IE includes parameters which are used by the mobile station + * for cell selection and reselection purposes. It may also include the + * POWER OFFSET parameter used by DCS 1800 Class 3 MS. + */ + + if (ms_power EQ 0x02 AND + rr_data->nc_data[index].c2_par.power_off_ind) + { + power_offset = rr_data->nc_data[index].c2_par.power_off << 1; + } + + offset = rr_data->dyn_config.dcs_offset; + break; + + case STD_DUAL: + case STD_DUAL_EGSM: + /* + * For dualband mobiles the calculation depends on the channel number + */ + if (INRANGE(LOW_CHANNEL_1800,rr_data->nc_data[index].arfcn,HIGH_CHANNEL_1800)) + { + /* + * All DCS 1800 channels + */ + p = p_dcs; + p_control = p_control_dcs; + + /* Ref 04.18 Section 10.5.2.35 */ + if (ms_power EQ 0x02 AND + rr_data->nc_data[index].c2_par.power_off_ind) + { + power_offset = rr_data->nc_data[index].c2_par.power_off << 1; + } + + offset = rr_data->dyn_config.dcs_offset; + } + else + { + /* + * All GSM 900 and E-GSM channels + */ + p = p_gsm; + p_control = p_control_gsm; + offset = rr_data->dyn_config.gsm_offset; + } + break; + + case STD_DUAL_US: + if (rr_data->nc_data[index].arfcn < LOW_CHANNEL_1900) + { + /* + * Then it is a GSM 850 channel + */ + p = p_gsm; + p_control = p_control_gsm; + offset = rr_data->dyn_config.gsm_offset; + } + else + { + /* + * else it is a PCS 1900 channel + */ + p = p_pcs; + p_control = p_control_pcs; + + offset = rr_data->dyn_config.dcs_offset; + } + break; + +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + case STD_850_1800: + case STD_850_900_1800: + if (INRANGE(LOW_CHANNEL_1800,rr_data->nc_data[index].arfcn,HIGH_CHANNEL_1800)) + { + /* + * Then it is a DCS 1800 channel + */ + p = p_dcs; + p_control = p_control_dcs; + + if (ms_power EQ 0x02 AND + rr_data->nc_data[index].c2_par.power_off_ind) + { + power_offset = rr_data->nc_data[index].c2_par.power_off << 1; + } + + offset = rr_data->dyn_config.dcs_offset; + } + else + { + /* + * Else it is a GSM 900 and E-GSM or GSM 850 channel + */ + p = p_gsm; + p_control = p_control_gsm; + offset = rr_data->dyn_config.gsm_offset; + } + break; + + case STD_900_1900: + case STD_850_900_1900: + /* + * For dualband mobiles the calculation depends on the channel number + */ + if (INRANGE(LOW_CHANNEL_1900,rr_data->nc_data[index].arfcn,HIGH_CHANNEL_1900)) + { + /* + * All PCS 1900 channels + */ + p = p_pcs; + p_control = p_control_pcs; + + offset = rr_data->dyn_config.dcs_offset; + } + else + { + /* + * All GSM 900 and E-GSM or GSM 850 channels + */ + p = p_gsm; + p_control = p_control_gsm; + offset = rr_data->dyn_config.gsm_offset; + } + break; +#endif + + default: + /* + * Just for LINT + */ + rr_data->nc_data[index].c1 = 0; + return; + } + + /* + * Parameter A indicates the difference between current fieldstrength and + * the minimum expected from the infrastructure. It indicates how good is the + * receiving part. + */ +#ifdef GPRS + if(rr_data->gprs_data.use_c31) + { + a = (SHORT) rr_data->nc_data[index].rxlev - + (SHORT) rr_data->nc_data[index].cr_par.gprs_rxlev_access_min; + } + else + { +#endif + a = (SHORT) rr_data->nc_data[index].rxlev - + (SHORT) rr_data->nc_data[index].select_para.rxlev_access_min; +#ifdef GPRS + } +#endif + + /* + * Parameter B indicates the difference between the maximum sending power + * expected by the infrastructure and the maximum power which is possible by + * the mobile. In the formula the maximum of B and zero is taking in account. + * If B is negative, the MS has enough power to reach the base station, + * because it has more power than expected and it will not have any affect + * in the C1 calculation. If B is positive, the MS will send with less power + * than expected by the infrastructure. Then this difference is subtracted + * from A. The maximum power is expected at the boarder of the cell. If the + * mobile is nearer to the base station, a lower power is needed. On the + * other hand will the mobile receive the base station with a higher + * fieldstrength as on the boarder. So this surplus compensates the lower + * sending capabilities. + */ + +#ifdef GPRS + if(rr_data->gprs_data.use_c31) + { + b = p_control [rr_data->nc_data[index].cr_par.gprs_ms_txpwr_max_cch] - p[ms_power]; + } + else + { +#endif + b = p_control [rr_data->nc_data[index].select_para.ms_txpwr_max_cch] + + power_offset - p[ms_power]; +#ifdef GPRS + } +#endif + + /* + * The resulting path loss criterion is C1 = A - MAX (B,0) + * + * An additional C1_offset and offset is not really used. This values can + * be configured and may compensate RF problems. + */ + rr_data->nc_data[index].c1 = a - att_max (b, 0) + rr_data->c1_offset + + offset; + + /* + * To avoid too many reselection the C1 of a neighbourcell is decreased, + * that means beside the GSM specifications a threshold value is introduced. + * If a test SIM card is inserted, this is not used. + */ + if (index NEQ SC_INDEX AND index NEQ CR_INDEX AND !dat_test_sim_available()) + rr_data->nc_data[index].c1 -= TWO; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_calculate_c2 | ++--------------------------------------------------------------------+ + + PURPOSE : The reselection criterion C2 is used for cell reselection + only and is defined by: + + C2 = C1 + CELL_RESELECT_OFFSET - + TEMPORARY OFFSET * H(PENALTY_TIME - T) + + for PENALTY_TIME <> 11111 + + C2 = C1 - CELL_RESELECT_OFFSET + + for PENALTY_TIME = 11111 + + where + + For non-serving cells: + + H(x) = 0 for x < 0 + + = 1 for x = 0 + + For serving cells: + + H(x) = 0 + + T is a timer implemented for each cell in the list of strongest carriers. + T shall be started from zero at the time the cell is placed by the MS on the + list of strongest carriers, except when the previous serving cell is placed + on the list of strongest carriers at cell reselection. In this, case, + T shall be set to the value of PENALTY_TIME (i.e. expired). + CELL_RESELECT_OFFSET applies an offset to the C2 reselection criterion for that cell. + + NOTE: CELL_RESELECT_OFFSET may be used to give different priorities to different + bands when multiband operation is used. + + TEMPORARY_OFFSET applies a negative offset to C2 for the duration of PENALTY_TIME + after the timer T has started for that cell. + + PENALTY_TIME is the duration for which TEMPORARY_OFFSET applies The all ones bit + pattern on the PENALTY_TIME parameter is reserved to change the sign of + CELL_RESELECT_OFFSET and the value of TEMPORARY_OFFSET is ignored as indicated + by the equation defining C2. + + CELL_RESELECT_OFFSET, TEMPORARY_OFFSET, PENALTY_TIME and CELL_BAR_QUALIFY are + optionally broadcast on the BCCH of the cell. If not broadcast, the default values + are CELL_BAR_QUALIFY = 0, and C2 = C1. The use of C2 is described in GSM 03.22. + + These parameters are used to ensure that the MS is camped on the cell with which it + has the highest probability of successful communication on uplink and downlink. + + REFERENCE: GSM 5.08, chapter 6.4 Criteria for cell selection and reselection + +*/ + +static void att_calculate_c2 (UBYTE index) +{ + GET_INSTANCE_DATA; + USHORT h; + T_NC_DATA *rrd; + + TRACE_FUNCTION ("att_calculate_c2()"); + + /* + * get a pointer to the data of the cell + */ + rrd = &rr_data->nc_data[index]; + + /* + * Calculate C1 as a base if no C2 parameters are available + */ + att_calculate_c1 (index); + + if ( rrd->c2_par.param_ind EQ 0 ) + { + /* + * C2 is equal C1 if no C2 parameters are available. + */ + rrd->c2 = rrd->c1; + TRACE_C1_C2(index); + return; + } + + /* + * Special case penalty time = 0b11111 + */ + if (rrd->c2_par.penalty_time EQ 31) + { + rrd->c2 = rrd->c1 - 2 * rrd->c2_par.cell_reselect_offset; + TRACE_C1_C2(index); + return; + } + + /* + * Calculate x for H(x) and set H(x) + */ + if ((USHORT)((rrd->c2_par.penalty_time + 1) * 20) >= + (USHORT)(rrd->avail_time/PERIOD_1_SEC)) + h = 1; + else + h = 0; + + /* + * for the serving cells H(x) us ever zero. + */ + if (index EQ SC_INDEX) + h = 0; + + /* + * Calculate C2 using the formula + */ + rrd->c2 = rrd->c1 + 2 * rrd->c2_par.cell_reselect_offset - + 10 * rrd->c2_par.temp_offset * h; + if (h EQ 1 AND rrd->c2_par.temp_offset EQ 7) + { + /* + * temp offset = 7 means C2 = - infinite + */ + rrd->c2 = -127; + } + + TRACE_C1_C2(index); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_calculate_c2_diff | ++--------------------------------------------------------------------+ + + PURPOSE : For cell reselection decision the C2 difference between + a neighbourcell and the serving cell is calculated. This + function shall be called only if both cells are in a + different location area. + + If no SIM card is inserted (that means limited service) + the threshold value is not taken in account. This is + beside the GSM specifications and shall ensure a better + coverage of the mobile. It leads not to more signalling + on the air-interface. + + REFERENCE: GSM 5.08, chapter 6.6.2 Path loss criteria and timings for + cell re-selection + +*/ + +static SHORT att_calculate_c2_diff (UBYTE index) +{ + GET_INSTANCE_DATA; + SHORT delta; + + TRACE_FUNCTION ("att_calculate_c2_diff()"); + + /* + * calculate delta + */ + delta = rr_data->nc_data[index].c2 - rr_data->nc_data[SC_INDEX].c2; + + /* According to 3GPP 05.08 Sec 6.8 MS is supposed to use ZERO for + * CELL_RESELECT_HYSTERESIS when in Limited service. + * c) The MS shall perform cell reselection at least among the cells of + * the PLMN of the cell on which the MS has camped, according to the + * algorithm of 3GPP TS 03.22, except that a zero value of + * CELL_RESELECT_HYSTERESIS shall be used. + */ + + if ((rr_data->ms_data.imsi_available) AND + (rr_data->ms_data.rr_service NEQ LIMITED_SERVICE)) + delta -= 2*rr_data->nc_data[SC_INDEX].select_para.cell_resel_hyst; + + /* + * return the difference + */ + return delta; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_calculate_digits | ++--------------------------------------------------------------------+ + + PURPOSE : The function calculates the number of the digits in a + mobile identity infoelement. The input parameter contains + one BCD digit in each field entry. + +*/ + +static UBYTE att_calculate_digits (UBYTE *digits) +{ + UBYTE i = 0; + + TRACE_FUNCTION ("att_calculate_digits()"); + + /* + * Check whether the end is detected + */ + while (digits[i] < 0x0A AND i < 16) + i++; + + return i; +} + + + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_cell_barred_status_cr_no_cr | ++--------------------------------------------------------------------+ + + PURPOSE : Checks whether a cell is barred or not for cell reselection + purposes. + + CELL_BAR QUALIFY CELL_BAR ACCESS CS priority Status for CR + 0 0 normal normal + 0 1 barred barred + 1 0 low normal (see note 2) + 1 1 low normal (see note 2) + + If all the following conditions are met, then the "Cell selection priority" + and the "Status for cell reselection" shall be set to normal: + + - the cell belongs to the MS HPLMN; + - the MS is in cell test operation mode; + - the CELL_BAR_ACCESS is set to "1"; + - the CELL_BAR_QUALIFY is set to "0"; + - the Access Control class 15 is barred. + + NOTE 1: A low priority cell is only selected if there are no + suitable cells + of normal priority (see GSM 03.22). + NOTE 2: Two identical semantics are used for cross phase + compatibility reasons. + This allows an operator to declare a cell always as a low + priority one for a phase 2 MS, but keeps the opportunity + for an operator to decide wether a phase 1 MS is permitted + to camp on such a cell or not. + + REFERENCE: GSM 5.08, chapter 9, table 1a + + +*/ +GLOBAL BOOL att_cell_barred_status_cr_no_cr (UBYTE index) +{ + GET_INSTANCE_DATA; + + TRACE_FUNCTION ("att_cell_barred_status_cr_no_cr()"); + + TRACE_EVENT_P5 ("[%u]%u cbq=%u cba=%u access class=%04x", + rr_data->nc_data[index].arfcn, + index, + rr_data->nc_data[index].c2_par.cbq, + rr_data->nc_data[index].rach.cell_bar_access, + rr_data->nc_data[index].rach.ac); + + /* + * check first the special case + */ + if (dat_hplmn (rr_data->nc_data[index].lai.mcc, + rr_data->nc_data[index].lai.mnc) AND + rr_data->cell_test_operation AND + rr_data->nc_data[index].c2_par.cbq EQ 0 AND + rr_data->nc_data[index].rach.cell_bar_access EQ 1) + { + /* + * access class 15 is set + */ + if (rr_data->nc_data[index].rach.ac & 0x8000) + return FALSE; + } + + /* + * the cell reselection status is normal. According + * to the table above the cell is only barred if + * the cell bar qualifier is set to 0 and the + * cell bar access is set to 1. + */ + if((rr_data->nc_data[index].rach.cell_bar_access EQ BARRED_YES) AND + rr_data->nc_data[index].c2_par.cbq EQ CBQ_NO) + return TRUE; + else + return FALSE; + + +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_cell_in_data_structures| ++--------------------------------------------------------------------+ + + PURPOSE : After reception of new measurement values from layer 1 + this function checks whether a neighbourcell indicated + with the parameter index is stored inside the RR + storage area. + +*/ + +static BOOL att_cell_in_data_structures (T_MPH_MEASUREMENT_IND *report, + UBYTE index) +{ + GET_INSTANCE_DATA; + USHORT i; + + TRACE_FUNCTION ("att_cell_in_data_structures()"); + + /* + * check for all areas + */ + for (i = 0; i < 6; i++) + { + /* + * If a cell is stored in the data area + */ + if (rr_data->nc_data[i].bcch_status NEQ EMPTY) + { + /* + * check the channel number + */ + if (rr_data->nc_data[i].arfcn EQ report->ncells.arfcn[index]) + return TRUE; + } + } + return FALSE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_remove_multiple_channels | ++--------------------------------------------------------------------+ + + PURPOSE : During fieldtests it had happens that the measurements from + layer 1 may contain the serving cell as a neighbourcell + (which is possible during connection and can be forwarded + to RR after connection). This leads to double stored data + in RR. + +*/ + +GLOBAL void att_remove_multiple_channels (void) +{ + GET_INSTANCE_DATA; + USHORT i; + + TRACE_FUNCTION ("att_remove_multiple_channels()"); + + /* + * For all neighbourcells in the measurement report + */ + for (i = 0; i < 6; i++) + { + if (rr_data->nc_data[i].arfcn EQ rr_data->nc_data[SC_INDEX].arfcn) + { + /* + * If the neighbourcell channel number is equal to the serving + * cell, clear the whole storage area. + */ + rr_data->nc_data[i].arfcn = 0; + rr_data->nc_data[i].bcch_status = EMPTY; + } + } +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_cell_in_measure_report | ++--------------------------------------------------------------------+ + + PURPOSE : The function checks whether a cell in the RR storage + area is still in a new measurement report and returns + one of the three possibilities: + + CELL_IS_INSERTED the cell is inside with the same BSIC + BSIC_HAS_CHANGED the cell is inside, but the BSIC has changed + CELL_IS_NOT_INSERTED the cell is not longer inside. + +*/ + +static UBYTE att_cell_in_measure_report (T_MPH_MEASUREMENT_IND *report, + UBYTE index) +{ + GET_INSTANCE_DATA; + UBYTE i; + UBYTE bsic; + + TRACE_FUNCTION ("att_cell_in_measure_report()"); + + /* + * check all neighbourcells in the measurent report + */ + for (i = 0; i < report->ncells.no_of_ncells; i++) + { + /* + * Check first the channel number + */ + if (rr_data->nc_data[index].arfcn EQ report->ncells.arfcn[i]) + { + /* + * Update fieldstrength value in the RR storage area + */ + rr_data->nc_data[index].rxlev = report->ncells.rx_lev[i]; + + /* + * Check whether the BSIC has been changed. Layer 1 sends an + * 8 bit value, but only the lower 6 bits are significant. + */ + bsic = rr_data->nc_data[index].bsic & 0x3F; + if (bsic EQ (report->ncells.bsic[i] & 0x3F)) + return CELL_IS_INSERTED; + else + { + /* + * If it is a changed BSIC, update the value in the RR storage area. + */ + rr_data->nc_data[index].bsic = report->ncells.bsic[i] & 0x3F; + return BSIC_HAS_CHANGED; + } + } + } + /* + * Not found + */ + return CELL_IS_NOT_INSERTED; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_bcch_carrier_cco | ++--------------------------------------------------------------------+ + + PURPOSE : During a Cell Change Order procedure: + After reception of all needed system information messages + a carrier is checked for cell selection purposes. + +*/ + +#ifdef GPRS +LOCAL void att_check_bcch_carrier_cco (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_check_bcch_carrier_cco()"); + + dat_rrgrr_data_ind (rr_data->gprs_data.dl_data_ind); + rr_data->gprs_data.dl_data_ind = NULL; + att_build_idle_req (CR_INDEX, MODE_CELL_SELECTION); + SET_STATE (STATE_ATT, ATT_IDLE); + dat_att_cell_selected(); + if (att_gprs_is_avail()) + { + att_signal_gprs_support(); + } + att_start_registration_timer (); +} +#endif + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_bcch_carrier_si | ++--------------------------------------------------------------------+ + + PURPOSE : After reception of all needed system information messages + a carrier is checked for cell selection purposes. + Perform the check on the presence of the SIs. + +*/ + +GLOBAL void att_check_bcch_carrier_si (void) +{ + GET_INSTANCE_DATA; + if (rr_data->cr_data.cd.sys_info_read EQ ALL_SYS_INFO_READ) + { + att_check_bcch_carrier (); + } +} + +GLOBAL void att_store_plmn_in_found_list (T_loc_area_ident *lai) +{ + GET_INSTANCE_DATA; + T_FOUND_ELEMENT *found; + +/* Implements RR Clone findings #8 */ + BOOL cell_ok = !att_cell_barred_status_cr_no_cr(CR_INDEX) AND + (rr_data->nc_data[CR_INDEX].c1 > 0) AND + att_priority_check (); + + + + if ( (found = att_plmn_in_found_list (lai->mcc, lai->mnc)) NEQ NULL ) + { + if ( found->cell_ok EQ 0 AND /* old cell did not allow access */ + cell_ok NEQ 0 ) /* new cell does allow access */ + { + ; /* a better cell has been found */ + } + else + { + found = NULL; + } + } + else + if ( rr_data->sc_data.found_entries < MAX_PLMN AND att_check_network(lai) ) + { + found = &rr_data->sc_data.found[rr_data->sc_data.found_entries]; + rr_data->sc_data.found_entries++; + } + else + { + TRACE_EVENT ("cannot store PLMN" ); + } + + if ( found ) + { + att_save_found_plmn ( + found, + lai->mcc, lai->mnc, + rr_data->nc_data[CR_INDEX].arfcn, + rr_data->nc_data[CR_INDEX].rxlev, lai->lac, (UBYTE)cell_ok); + } +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_bcch_carrier | ++--------------------------------------------------------------------+ + + PURPOSE : After reception of all needed system information messages + a carrier is checked for cell selection purposes. + +*/ + +GLOBAL void att_check_bcch_carrier (void) +{ + GET_INSTANCE_DATA; + T_loc_area_ident * lai; + BOOL plmn_ok = FALSE; + BOOL cell_ok,prio_ok; + UBYTE tried_to_reach_full_try_limited = (rr_data->cs_data.scan_mode EQ CS_SECOND_SCAN); + + TRACE_FUNCTION ("att_check_bcch_carrier()"); + + /* + * stop the timer which controls the reception of + * all system information messages during cell selection. + */ + TIMERSTOP (T_RESELECT); + + /* + * If procedure RR Network Controlled Cell Change Order + * is running then call a different function and return. + */ +#ifdef GPRS + if ( rr_data->gprs_data.tbf_est EQ TBF_EST_CCO ) + { + att_check_bcch_carrier_cco(); + return; + } +#endif + + lai = &rr_data->nc_data[CR_INDEX].lai; + + /* + * calculate the path loss criterion + */ + att_calculate_c1 (CR_INDEX); + TRACE_C1(CR_INDEX); + + /* + * the check depends on the service which has been requested + * by RR. This can be the same as the service requested by MM, + */ + switch (rr_data->ms_data.req_mm_service) + { + case FUNC_PLMN_SRCH: + /* + * For full service the mobile country code and the mobile network code + * must match with the PLMN identification requested by MM. + */ + plmn_ok = dat_plmn_equal_req (lai->mcc, + lai->mnc, + rr_data->ms_data.plmn.mcc, + rr_data->ms_data.plmn.mnc); + + TRACE_EVENT_P6 ( "MCC/MNC r=%x%x%x/%x%x%x", + rr_data->ms_data.plmn.mcc[0], + rr_data->ms_data.plmn.mcc[1], + rr_data->ms_data.plmn.mcc[2], + rr_data->ms_data.plmn.mnc[0], + rr_data->ms_data.plmn.mnc[1], + rr_data->ms_data.plmn.mnc[2]); + TRACE_EVENT_P7 ( "MCC/MNC i=%x%x%x/%x%x%x %s", + lai->mcc[0], + lai->mcc[1], + lai->mcc[2], + lai->mnc[0], + lai->mnc[1], + lai->mnc[2], + plmn_ok?"OK":""); + + + if (!plmn_ok AND + (GET_STATE(STATE_ATT) EQ ATT_CS2) AND + (rr_data->ms_data.rr_service EQ LIMITED_SERVICE OR + rr_data->ms_data.rr_service EQ NO_SERVICE) AND + (rr_data->cs_data.check_hplmn EQ TRUE) AND + (((rr_data->ms_data.operation_mode >> SHIFT_FOR_SEARCH_OFFSET) & 1) EQ M_AUTO)) + { + /* Compare with HPLMN */ + if (rr_data->ms_data.imsi_available) + { + plmn_ok = dat_plmn_equal_req (lai->mcc, + lai->mnc, + &rr_data->ms_data.imsi.ident_dig[0], + &rr_data->ms_data.imsi.ident_dig[3]); + if (plmn_ok) + { + TRACE_EVENT ("HPLMN Matched"); + } + } + /* compare with AHPLMN */ + if(!plmn_ok AND rr_data->ms_data.ahplmn.v_plmn EQ TRUE) + { + plmn_ok = dat_plmn_equal_req (lai->mcc, + lai->mnc, + rr_data->ms_data.ahplmn.mcc, + rr_data->ms_data.ahplmn.mnc); + if (plmn_ok) + { + TRACE_EVENT ("AHPLMN Matched"); + } + } + /* Compare with LRPLMN */ + if (!plmn_ok AND rr_data->cs_data.last_reg_plmn.v_plmn EQ V_PLMN_PRES) + { + plmn_ok = dat_plmn_equal_req (lai->mcc, + lai->mnc, + rr_data->cs_data.last_reg_plmn.mcc, + rr_data->cs_data.last_reg_plmn.mnc); + if (plmn_ok) + { + TRACE_EVENT ("LRPLMN Matched"); + } + } + /* Compare with Last Serving Cell PLMN from White List */ + if ((!plmn_ok) AND (rr_data->sc_data.mm_started EQ RR_ORIGINATED) AND + (rr_data->ms_data.plmn.v_plmn EQ V_PLMN_PRES)) + { + plmn_ok = dat_plmn_equal_req (lai->mcc, + lai->mnc, + rr_data->cs_data.white_list.last_sc_lac.mcc, + rr_data->cs_data.white_list.last_sc_lac.mnc); + if (plmn_ok) + { + TRACE_EVENT ("White List PLMN Matched"); + } + } + } + + if (plmn_ok) + tried_to_reach_full_try_limited = FALSE; + /*lint -fallthrough*/ + + case FUNC_LIM_SERV_ST_SRCH: + if((rr_data->ms_data.req_mm_service EQ FUNC_LIM_SERV_ST_SRCH) OR + tried_to_reach_full_try_limited) + { + /* + * The mobile shall reach limited service. This is the case + * if no full service is possible or no SIM card is inserted. + * + * The network check is in principle ever true. The function + * att_check_network realises a SW shielding to reject public + * networks in final type approvals. + * + * The criterion for the cell checking is a non-barred cell and + * a positive path loss criterion. + */ + plmn_ok = att_check_network (lai); +/* Implements RR Clone findings #8 */ + cell_ok = !att_cell_barred_status_cr_no_cr (CR_INDEX) AND + (rr_data->nc_data[CR_INDEX].c1 > 0); + + } + else + { + /* + * Full service is requested. + * + * First store PLMN of the cell in the PLMN found list + * if the list is not stored yet and not full. SW shielding + * is taking into account for FTA purposes. + * + * If the cell selection fails and no carrier was suitable, + * at least a list of the found channels is available. + */ + if(dat_forb_lai_check (CR_INDEX)) + { + att_store_plmn_in_found_list (lai); + } + else + { + TRACE_EVENT ("Do not store Forbidden LAI PLMN in the found PLMN list"); + } + + /* + * The requirements for the cell are: it must be a non-barred cell, + * it must have a positive path loss criterion. The cell shall not + * be inside of a forbidden location area and it must be a high priority + * cell if it is the first scan first attempt. + */ +/* Implements RR Clone findings #8 */ + cell_ok = !att_cell_barred_status_cr_no_cr (CR_INDEX) AND + (rr_data->nc_data[CR_INDEX].c1 > 0); + + + prio_ok = att_priority_check (); + + TRACE_EVENT_P1 ( "cell_ok = %d", cell_ok); + + TRACE_EVENT_P1 ( "prio_ok = %d", prio_ok); + /* + * if the network and cell are okay, but the priority check fails, + * this cell is a low priority cell and can be checked in the + * first scan second attempt. + */ + if (plmn_ok AND cell_ok AND !prio_ok) + cs_set_attributes (LOW_PRIORITY_CELL, + rr_data->nc_data[CR_INDEX].arfcn); + + /* + * if the bcch carrier is not suitable for full service, + * but suitable for limited service, try it + * for emergency services in the second attempt. + * priority check is not required for emergency cells + */ + if (cell_ok AND !plmn_ok) + cs_set_attributes (EMERGENCY_CELL, + rr_data->nc_data[CR_INDEX].arfcn); + + /* Update the cell_ok flag with with priority check flag */ + if(cell_ok) + cell_ok = prio_ok; + + /* Checking access class and the list for cause #12 for */ + /* selection of the cell to camp on may not meet the */ + /* requirements of GSM 03.22 subclause 3.5.3, 3.5.4. */ + /* However, it is perfectly correct to consider the */ + /* forbidden location areas for roaming list here. */ + + + /* + * If cell selection has been launched by MM in manual mode + * we don't check against the forbidden location area lists. + * This is to allow the user to select a network manually + * which is a member of a forbidden list. + * Maybe the distinction manual/automatic is not worth the + * effort, as in contradiction to the forbidden list for + * cause #11 the user can get rid of the forbidden lists for + * cause #12 and #13 either by a power cycle or by simply + * waiting some hours. + */ + if (!rr_data->sc_data.mm_started OR + ((rr_data->ms_data.operation_mode >> SHIFT_FOR_SEARCH_OFFSET) & 1) EQ M_AUTO) + { + /* + * RR started cell selection, or MM started but in automatic + * so ensure no barred LA is entered. + */ + if (cell_ok) + { + cell_ok = (dat_forb_lai_check (CR_INDEX) AND + dat_roam_forb_lai_check (CR_INDEX)); + + /* Candidate for Limited service */ + if(!cell_ok) + cs_set_attributes (EMERGENCY_CELL, + rr_data->nc_data[CR_INDEX].arfcn); + } + } + + #if defined (_SIMULATION_) + { + /* + * Trace output for cell selection analysis + */ +/* Implements RR Clone findings #8 */ + BOOL cb_stat = att_cell_barred_status_cr_no_cr (CR_INDEX); + + BOOL for_lai = dat_forb_lai_check (CR_INDEX); + BOOL prio = att_priority_check(); + TRACE_EVENT_WIN_P1 ( "CB_STAT = %d", cb_stat); + TRACE_EVENT_WIN_P1 ( "C1 = %d", rr_data->nc_data[CR_INDEX].c1); + TRACE_EVENT_WIN_P1 ( "FOR_LAI = %d", for_lai); + TRACE_EVENT_WIN_P1 ( "PRIO = %d", prio); + } + #endif /* _SIMULATION_ */ + } + break; + + default: + /* + * MM has requested the list of the available PLMNs. The algorithm + * for this is to indicate all carriers as "not suitable" for cell + * selection. As a result the list of the available PLMNs is build + * after scanning all carriers. + * + * First step is to store PLMN in plmn found list if the PLMN is not + * stored yet and the list is not full. SW shielding is used for + * FTA purposes. + */ + att_store_plmn_in_found_list (lai); + + /* + * Define the channel as a candidate for limited service. + */ + cs_set_attributes (EMERGENCY_CELL, + rr_data->nc_data[CR_INDEX].arfcn); + + /* + * Remove all channels of the neighbourcell list from the power campaign + * list. If the configuration of the network is sensible, this cell will + * contain also channels of the same network. So it is not necessary to + * scan this channels. The available PLMN list is the same, it consumes + * only time. + */ + cs_del_list (&rr_data->cr_data.cd.ncell_list); + plmn_ok = FALSE; + cell_ok = FALSE; + + /* + * start synchronisation attempt to the next cell + */ + memset (&rr_data->nc_data[CR_INDEX], 0, sizeof (T_NC_DATA)); + + if (rr_data->ms_data.rr_service EQ NO_SERVICE) + { + SET_STATE (STATE_ATT, ATT_CS1); + } + srv_clear_list (&rr_data->cr_data.cd.ncell_list); + cs_sync_next (); + return; + } + + if( (!tried_to_reach_full_try_limited) AND (rr_data->cs_data.scan_mode EQ CS_SECOND_SCAN)) + { + if(!cell_ok) + { + /* + * plmn is OK, cell is not OK for full service + * however cell may be OK for limited service + */ + tried_to_reach_full_try_limited = TRUE; +/* Implements RR Clone findings #8 */ + cell_ok = !att_cell_barred_status_cr_no_cr (CR_INDEX) AND + (rr_data->nc_data[CR_INDEX].c1 > 0); + + } + } + + /* + * Trace output for cell selection analysis + */ + TRACE_EVENT_P1 ( "req.service = %s", _rr_str_FUNC[rr_data->ms_data.req_mm_service]); + TRACE_EVENT_P1 ( "plmn_ok = %d", plmn_ok ); + TRACE_EVENT_P1 ( "cell_ok = %d", cell_ok); + + /* + * checking of the requirements has been done. The result + * is defined by plmn_ok and cell_ok. + */ + if (plmn_ok AND cell_ok) + { + /* + * Network and Cell are okay. Just use the cell + * set RR service according to the checked service + */ + /* If the MS reselects back onto the same SC and T3122 is still running, it should */ + /* be left running. If a new cell is selected, this timer should be stopped. */ + + if( rr_data->nc_data[SC_INDEX].arfcn NEQ rr_data->nc_data[CR_INDEX].arfcn) + { + TIMERSTOP(T3122); + } + + if (rr_data->ms_data.req_mm_service EQ FUNC_LIM_SERV_ST_SRCH OR + (tried_to_reach_full_try_limited)) + { + rr_data->ms_data.rr_service = LIMITED_SERVICE; + } + else + { + rr_data->ms_data.rr_service = FULL_SERVICE; + } + + TRACE_EVENT_P4 ("NEW SC [%d]->[%d] (rMM=%s RRs=%s)", + rr_data->nc_data[SC_INDEX].arfcn, + rr_data->nc_data[CR_INDEX].arfcn, + _rr_str_FUNC[rr_data->ms_data.req_mm_service], + _rr_str_SERVICE[rr_data->ms_data.rr_service]); + + /* + * set the result in the CR_INDEX area and copy then all + * stuff to the SC_INDEX area. + */ + rr_data->nc_data[CR_INDEX].bcch_status = DECODED; + rr_data->nc_data[CR_INDEX].bcch_counter = 0; + rr_data->nc_data[CR_INDEX].c1_counter = 0; + att_copy_cr_data (); + memcpy (&rr_data->sc_data.cd, &rr_data->cr_data.cd, + sizeof (T_CELL_DATA)); + rr_data->nc_data[CR_INDEX].arfcn = NOT_PRESENT_16BIT; +#if defined (REL99) && defined (TI_PS_FF_EMR) + rr_data->sc_data.ba_index = rr_data->cr_data.ba_index; + rr_data->cr_data.ba_index = NOT_PRESENT_8BIT; +#endif + + /* CSI-LLD section:4.1.1.10 + * This function updates the black list after the first successful + * FUNC_PLMN_SEARCH + */ + if(rr_data->cs_data.initial_plmn_search EQ INITIAL_PLMN_SEARCH_ACTIVE) + { + cs_update_black_list(); + rr_data->cs_data.initial_plmn_search = INITIAL_PLMN_SEARCH_DONE; + } + + /* Full service reached. Perform all necessary tasks */ + if(rr_data->ms_data.rr_service EQ FULL_SERVICE) + { + att_full_service_found(); + } + + /* + * Indicate the result of cell selection to MM + */ + if (tried_to_reach_full_try_limited) + { + /* + * The result is not what MM has requested. + * E.g. MM has requested full service, but RR has + * reached only limited service. In this case + * MM gets the list of the available PLMNs and may + * select on of the networks for a new attempt in + * case of automatic registration. + */ + att_copy_old_lai_rac(CR_INDEX); +#if 0 + memcpy (&rr_data->old_lai, &rr_data->nc_data[CR_INDEX].lai, + sizeof(T_loc_area_ident)); + rr_data->old_cell_id = rr_data->nc_data[CR_INDEX].cell_id; +#endif + +#ifdef GPRS + if(att_gprs_is_avail()) + { /* we have GPRS and have reached limited service */ + cs_set_stop_active(); + if(att_gprs_cell_has_pbcch()) + { + att_gprs_stop_pl(); + } + else + { + att_set_pl_in_idle_mode (); + } + att_signal_gprs_support(); + /* and wait for CR_REQ(CR_COMPLETE) from GRR */ + } + else + { +#endif + /* + * Configure layer 1 + */ + att_set_pl_in_idle_mode (); + + /* + * Indicated the data transfer process that the MS is attached. + */ + dat_att_cell_selected (); + + SET_STATE (STATE_ATT, ATT_IDLE); + cs_set_stop_active(); + + att_code_rr_abort_ind (RRCS_ABORT_CEL_SEL_FAIL); + att_start_registration_timer (); + att_mph_identity_req (); + srv_use_stored_prim (); +#ifdef GPRS + } +#endif + + } + else + { + /* + * the cell selection was successful. The counter + * for failed registration attempts is resetted and + * MM is informed. + */ + + rr_data->ms_data.reg_counter = 0; +#ifdef GPRS + if(! att_gprs_is_avail()) + { +#endif + + /* + * Configure layer 1 + */ + att_set_pl_in_idle_mode (); + /* + * Indicated the data transfer process that the MS is attached. + */ + dat_att_cell_selected (); + SET_STATE (STATE_ATT, ATT_IDLE); + cs_set_stop_active(); + + /* inform GRR if we have GPRS support */ +#ifdef GPRS + if(att_gprs_is_avail()) + { + att_signal_gprs_support(); + } +#endif + /* Inform MM */ + if (rr_data->sc_data.mm_started) + att_code_rr_act_cnf (); + else + att_code_rr_act_ind (); + + srv_use_stored_prim (); + att_start_registration_timer (); + att_mph_identity_req (); + +#ifdef GPRS + } + else + { /* we have GPRS and have reached full service */ + cs_set_stop_active(); + if(att_gprs_cell_has_pbcch()) + { + att_gprs_stop_pl(); + } + else + { + att_set_pl_in_idle_mode (); + } + att_signal_gprs_support(); + /* and wait for CR_REQ(CR_COMPLETE) from GRR */ + } +#endif + /* This flag will help to identify whether cell reselection following + * TRESELECT expiry waiting for SI2TER is successfull or not + */ + rr_data->cr_treselect_exp = TRUE; + } + return; + } + + /* + * BCCH carrier check has failed + * Either cell_ok or plmn_ok is FALSE or both. + */ + + if(plmn_ok EQ FALSE) + { + /* + * PLMN is not okay, but the cell + */ + if (rr_data->ms_data.imsi_available AND + (dat_test_sim_available () EQ FALSE)) + { + /* + * with SIM card, that means full service. + * "delete neighbourcells", that means give all + * neighbourcells a low priority in scanning. + * + * It is assumed that this cell will fail also + * because they are also member of the wrong network. + * + * This is not done during FTA campaign. + */ + cs_del_list (&rr_data->cr_data.cd.ncell_list); + } + } + + if(plmn_ok AND + cell_ok EQ FALSE) + { + /* + * plmn okay but not the cell + */ + if (rr_data->ms_data.imsi_available AND + dat_test_sim_available() EQ FALSE) + { + /* + * with SIM card, that means full service. + * "set neighbourcells", that means give all + * neighbourcells a higher priority in scanning. + * Not done during FTA campaign + */ + cs_set_list (&rr_data->cr_data.cd.ncell_list); + } + } + + /* + * start synchronisation attempt to the next cell + */ + memset (&rr_data->nc_data[CR_INDEX], 0, sizeof (T_NC_DATA)); + + /* + * After BCCH Reading if the requested service is not found, + * before sending BSIC_REQ RR has to be moved to ATT_CS1. + */ + + if(rr_data->ms_data.rr_service EQ NO_SERVICE OR + GET_STATE(STATE_ATT) EQ ATT_CS2) + { + SET_STATE (STATE_ATT, ATT_CS1); + } + + srv_clear_list (&rr_data->cr_data.cd.ncell_list); +#ifdef GPRS + if(GET_STATE(STATE_ATT) NEQ ATT_IDLE) + gprs_init_data_cr(); +#endif + cs_sync_next (); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_fplmn_cell | ++--------------------------------------------------------------------+ + + PURPOSE : If the mobile is in limited service, but MM has requested + full service, RR starts after timeout of the registration + timer new attempts to reach full service. After reading + system information message 3 or 4 of the candidate, this + function is called, to check whether the cell fullfills + the requirements for a full service cell. In this case + a cell reselection is started to read the whole BCCH to + configure layer 1. + +*/ + +GLOBAL void att_check_fplmn_cell (void) +{ + GET_INSTANCE_DATA; + UBYTE cell_ok; + UBYTE plmn_ok; + T_loc_area_ident * lai = &rr_data->nc_data[CR_INDEX].lai; + + TRACE_FUNCTION ("att_check_fplmn_cell()"); + + /* + * Calculate the path loss criterion + */ + att_calculate_c1 (CR_INDEX); + TRACE_C1(CR_INDEX); + + /* + * check that the cell is not barred and has a positive path loss + * criterion. + */ +/* Implements RR Clone findings #8 */ + cell_ok = (!att_cell_barred_status_cr_no_cr (CR_INDEX) AND + (rr_data->nc_data[CR_INDEX].c1 > 0)AND dat_roam_forb_lai_check (CR_INDEX)); +; + + /* + * check whether the PLMN identification is equal to the PLMN which has + * been requested by MM. + */ + plmn_ok = dat_plmn_equal_req (lai->mcc, + lai->mnc, + rr_data->ms_data.plmn.mcc, + rr_data->ms_data.plmn.mnc); + + /* + * stop of T_RESELECT. This timer controls the reception of the initial + * system information message. + */ + TIMERSTOP (T_RESELECT); + + /* + * store PLMN in plmn found list to provide this information to MM + * at the end of a failed registration attempt. + */ + if(dat_forb_lai_check (CR_INDEX)) + { + att_store_plmn_in_found_list (lai); + } + else + { + TRACE_EVENT ("Do not store Forbidden LAI PLMN in the found PLMN list"); + } + + if (plmn_ok) + { + if (cell_ok) + { + /* + * Enable nc monitoring to resume in lower layer + * when recovering full service + */ + att_notify_stop_plmn_search (FALSE); + + /* + * cell and PLMN are okay, then start cell reselection to read + * the complete BCCH to configure layer 1. + */ +/*XY:n inform GRR, and wait for CR_RSP */ +#ifdef GPRS + att_start_cell_reselection_gprs (CELL_RESELECTION_CR); +#else + att_start_cell_reselection (CELL_RESELECTION_CR); +#endif + return; + } + } + + if (cell_ok) + { + /* + * PLMN is not okay, but the cell + * + * "delete neighbourcells", that means give all + * neighbourcells a low priority in scanning. + */ + if (dat_test_sim_available () EQ FALSE) + cs_del_list (&rr_data->cr_data.cd.ncell_list); + } + else + { + /* + * PLMN okay but not the cell + * + * "set neighbourcells", that means give all + * neighbourcells a higher priority in scanning. + */ + if (dat_test_sim_available () EQ FALSE) + { + if (plmn_ok) + /* + * with SIM card, that means full service. + * "set neighbourcells", that means give all + * neighbourcells a higher priority in scanning. + */ + cs_set_list (&rr_data->cr_data.cd.ncell_list); + else + /* + * with SIM card, that means full service. + * "delete neighbourcells", that means give all + * neighbourcells a low priority in scanning. + * + * It is assumed that this cell will fail also + * because they are also member of the wrong network. + * + * This is not done during FTA campaign. + */ + cs_del_list (&rr_data->cr_data.cd.ncell_list); + } + } + + /* + * start synchronisation attempt to the next cell + */ + memset (&rr_data->nc_data[CR_INDEX], 0, sizeof (T_NC_DATA)); + cs_sync_next (); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_cell | ++--------------------------------------------------------------------+ + + PURPOSE : if a cell reselection decision has been taken, this function + looks for a candidate for cell reselection taking in account + several requirements. The reselect_index stores the index + of the RR storage area for the neighbourcell. The return + value indicates whether a cell has been found or not. + +*/ + +static BOOL att_check_cell (void) +{ + GET_INSTANCE_DATA; + BOOL cell_ok = FALSE; + + TRACE_FUNCTION ("att_check_cell()"); + + /* + * while no suitable candidate has been found, + * but still possible cells available. + */ + while (rr_data->reselect_index NEQ NO_AVAILABLE AND ! cell_ok) + { + /* + * calculate the cell reselection criterion C2 for the candidate + */ + att_calculate_c2 (rr_data->reselect_index); + + /* + * check the cell requirements: + * 1. check the cell barred status (if shall be non-barred) + * 2. the cell shall be not temporarily excluded (tnnn e.g. after random access + * failure). + * 3. the cell must have a positive cell reselection criterion C2. + */ + +/* Implements RR Clone findings #8 */ + cell_ok = (! att_cell_barred_status_cr_no_cr (rr_data->reselect_index) AND + ! is_tnnn (rr_data->reselect_index) AND + rr_data->nc_data[rr_data->reselect_index].c2 > 0); + + /* + * Forbidden LA for roaming shall be tested there in case a C2-base cell + * reselection has been triggered on a cell candidate belonging to a + * valid LA but unsuccesfull. Then RR will continue cell reselection + * with the next candidate that might be part of a forbidden LAC. + * Should be trapped by att_check_neighbourcell() at the end of the + * CS3 session... but it skips one CR and secures the process. + * Question : should this test be bypassed if MM requested limited + * service ?? + */ + + if (rr_data->ms_data.rr_service EQ FULL_SERVICE) + { + if (cell_ok) + cell_ok = dat_roam_forb_lai_check (rr_data->reselect_index); + } + + if (cell_ok) + { + /* + * suitable cell has been found + */ + TRACE_EVENT ("use neighbour cell"); + + /* + * after random access failure we found another cell, + * that means, we will process a normal cell reselection + * and will not come back directly to idle mode if the + * cell reselection fails for the new cell. + */ + if (rr_data->sc_data.selection_type EQ CELL_RESELECTION_RACH) + { + rr_data->sc_data.selection_type = CELL_RESELECTION; + #ifdef GPRS + rr_data->gprs_data.use_c31 = FALSE; + #endif + } + + /* + * configure layer 1 for cell reselection + */ + TRACE_EVENT_P2 ("config L1 for CR [%d]->[%d]", + rr_data->nc_data[SC_INDEX].arfcn, + rr_data->nc_data[rr_data->reselect_index].arfcn); + + #ifdef GPRS + rr_data->gprs_data.ready_state = FALSE; /* Standby */ + #endif + + att_start_cr_in_pl(rr_data->reselect_index); + } + else + { + /* + * cell is not suitable. Look for another cell. + */ + rr_data->reselect_index = + att_get_next_highest_c2_idx (rr_data->reselect_index); + } + } + + /* + * return whether a cell has been found or not. + */ + return cell_ok; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_clean_buf | ++--------------------------------------------------------------------+ + + PURPOSE : trigger cleaning of the SI buffers indicated by si_to_clean + +*/ +void att_clean_buf (USHORT si_to_clean) +{ + PALLOC(clean_buf, MPH_CLEAN_BUF_REQ); + clean_buf->si_to_clean = si_to_clean; + PSENDX(PL, clean_buf); +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_start_cr_in_pl | ++--------------------------------------------------------------------+ + + PURPOSE : trigger CR in PL and init some necessary parameters + +*/ +void att_start_cr_in_pl(UBYTE index) +{ + GET_INSTANCE_DATA; + att_init_pl_status (); + att_build_idle_req (index, MODE_CELL_RESELECTION); + + /* + * Clean the CR_INDEX storage area in RR to get the complete + * BCCH of the new cell + */ + att_init_cr_data(); + memcpy (&rr_data->nc_data[CR_INDEX], + &rr_data->nc_data[index], + sizeof (T_NC_DATA)); + srv_clear_list (&rr_data->cr_data.cd.ncell_list); + SET_STATE (STATE_ATT, ATT_CS3); + rr_data->bcch_error = 0; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_stop_dedicated | ++--------------------------------------------------------------------+ + + PURPOSE : Send primitive MPH_STOP_DEDICATED_REQ + +*/ +GLOBAL void att_stop_dedicated(void) +{ + PALLOC(mph_stop_dedi, MPH_STOP_DEDICATED_REQ); + PSENDX(PL, mph_stop_dedi); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_leave_dedicated | ++--------------------------------------------------------------------+ + + PURPOSE : Decide if we do a CR or return to idle directly + +*/ +GLOBAL void att_leave_dedicated(void) +{ + GET_INSTANCE_DATA; + if (IS_TIMER_ACTIVE(T_DEDICATED_MODE)) + { /* spent less than 30 seconds in dedicated mode */ + TIMERSTOP(T_DEDICATED_MODE); + } + else + { /* spent at least 30 seconds in dedicated mode */ + rr_data->mode_after_dedi = MODE_CELL_RESELECTION; + } + + if((rr_data->mode_after_dedi EQ MODE_CELL_SELECTION) AND + (rr_data->sc_data.selection_type NEQ BACK_FROM_DEDICATED_RLF)) /*does not seem correct!!!*/ + { + /* + * go back directly to the old cell after dedicated + * mode if we were in dedicated mode shorter than 30 seconds + * and have not made a handover in dedicated mode + */ +#ifdef GPRS + if(GPRS_SUSPENDED_BCCH EQ GET_STATE(STATE_GPRS)) + { + SET_STATE(STATE_GPRS,GPRS_PIM_BCCH); + } + else if(GPRS_SUSPENDED_PBCCH EQ GET_STATE(STATE_GPRS)) + { + SET_STATE(STATE_GPRS,GPRS_PIM_PBCCH); + } +#endif + att_return_to_idle(); + + /* + * restore the neighbour cell list which was valid + * in idle mode (derived from SI 2x) + * Note: SI 5x may contain other neighbour cells than SI 2x + */ + memcpy(&rr_data->sc_data.cd.ncell_list, + &rr_data->sc_data.ncell_list_idle, + sizeof(T_LIST)); + + /* + * restore the sys_info_read bitmap if we are going + * directly to idle + */ + rr_data->sc_data.cd.sys_info_read = ALL_SYS_INFO_READ; + + if (rr_data->repeat_est) + { + rr_data->repeat_est = FALSE; + dat_start_immediate_assign (rr_data->ms_data.establish_cause); + } + else + { +#ifdef GPRS + if(!att_gprs_cell_has_pbcch()) +#endif + att_code_mph_ncell_req(SC_INDEX); + } + + /* After Dedicated mode lass than 30 seconds for a Location Area Update or + * routing Area update. + * start black list search to look for inactive carriers + * Cell-Selection Improvement LLD - 4.1.4.3 + */ + if((rr_data->ms_data.establish_cause EQ ESTCS_SERV_REQ_BY_MM) AND + (rr_data->cs_data.black_list_search_pending EQ TRUE)) + { + + TRACE_EVENT("black_list_search_pending : 1"); + + rr_data->cs_data.black_list_search_pending = FALSE; + + if(cs_check_region(rr_data->cs_data.region)) + { + /* Do not start Black list search,when Black list database is empty */ +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + if (rr_data->cs_data.region EQ BOTH_REGIONS) + { + if(srv_is_list_set(&rr_data->cs_data.black_list.list[EUROPEAN_REGION]) OR + srv_is_list_set(&rr_data->cs_data.black_list.list[AMERICAN_REGION])) + { + att_start_cell_selection(RR_ORIGINATED,CS_PARALLEL,BLACK_LIST_SEARCH_MODE); + } + else + { + TRACE_EVENT("Black List empty"); + } + } + else + { +#endif + if(srv_is_list_set( + &rr_data->cs_data.black_list.list[rr_data->cs_data.region])) + { + att_start_cell_selection(RR_ORIGINATED,CS_PARALLEL,BLACK_LIST_SEARCH_MODE); + } + else + { + TRACE_EVENT("Black List empty"); + } +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + } +#endif + } + } + } + else + { +#ifdef GPRS + att_start_cell_reselection_gprs(BACK_FROM_DEDICATED); +#else + att_start_cell_reselection(BACK_FROM_DEDICATED); +#endif + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_leave_dat_imm_ass | ++--------------------------------------------------------------------+ + + PURPOSE : return to idle mode directly and clean up + immediate assignment procedure + +*/ +GLOBAL void att_leave_dat_imm_ass(void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_leave_dat_imm_ass()"); + +#ifdef GPRS + if(GPRS_SUSPENDED_BCCH EQ GET_STATE(STATE_GPRS)) + { + SET_STATE(STATE_GPRS,GPRS_PIM_BCCH); + } + else if(GPRS_SUSPENDED_PBCCH EQ GET_STATE(STATE_GPRS)) + { + SET_STATE(STATE_GPRS,GPRS_PIM_PBCCH); + } +#endif + + att_return_to_idle(); + + rr_data->repeat_est = FALSE; + +#ifdef GPRS + if(!att_gprs_cell_has_pbcch()) +#endif + att_code_mph_ncell_req(SC_INDEX); + + /* + * start black list search to look for inactive carriers + * Cell-Selection Improvement LLD - 4.1.4.3 + */ + if((rr_data->ms_data.establish_cause EQ ESTCS_SERV_REQ_BY_MM) AND + (rr_data->cs_data.black_list_search_pending EQ TRUE)) + { + + TRACE_EVENT("black_list_search_pending : 1"); + + rr_data->cs_data.black_list_search_pending = FALSE; + + if(cs_check_region(rr_data->cs_data.region)) + { + /* Do not start Black list search,when Black list database is empty */ +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + if (rr_data->cs_data.region EQ BOTH_REGIONS) + { + if(srv_is_list_set(&rr_data->cs_data.black_list.list[EUROPEAN_REGION]) OR + srv_is_list_set(&rr_data->cs_data.black_list.list[AMERICAN_REGION])) + { + att_start_cell_selection(RR_ORIGINATED,CS_PARALLEL,BLACK_LIST_SEARCH_MODE); + } + else + { + TRACE_EVENT("Black List empty"); + } + } + else + { +#endif + if(srv_is_list_set(&rr_data->cs_data.black_list.list[rr_data->cs_data.region])) + { + att_start_cell_selection(RR_ORIGINATED,CS_PARALLEL,BLACK_LIST_SEARCH_MODE); + } + else + { + TRACE_EVENT("Black List empty"); + } +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + } +#endif + } + } +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_select_cell_dedicated | ++--------------------------------------------------------------------+ + + PURPOSE : The function selects a cell for cell reselection after + coming back from a dedicated connected (normal release + or radio link failure. + +*/ + +static void att_select_cell_dedicated (void) +{ + GET_INSTANCE_DATA; + U8 search_mode; + + TRACE_FUNCTION ("att_select_cell_dedicated()"); + + if (rr_data->reselect_index NEQ NO_AVAILABLE) + { + TRACE_EVENT_P3 ("[%u] new CS/CR (mode=%u, sel.type=%d)", + rr_data->nc_data[rr_data->reselect_index].arfcn, + rr_data->mode_after_dedi, rr_data->sc_data.selection_type); + + /* + * A cell has been found for coming back from dedicated mode. + * Configure layer 1 for cell reselection. + */ + att_start_cr_in_pl(rr_data->reselect_index); + } + else + { + /* + * no suitable cell is available + */ + if (rr_data->sc_data.selection_type EQ BACK_FROM_DEDICATED_RLF) + { + /* + * In case of coming back after radio link failure + * the old cell shall be used only if no other cell + * is suitable. So the selection type is changed to + * "normal" comeback from dedicated mode. MM is informed + * that no reestablishment is possible and a cell is + * searched again inclusive the old serving cell. + */ + rr_data->sc_data.selection_type = BACK_FROM_DEDICATED; + dat_code_reestablishment_fail (); + TIMERSTART (T_RESELECT, TRESELECT_VALUE); + att_search_cell (); + } + else + { + /* Cell Selection Improvements-LLD section:4.1.3.9 */ + if((rr_data->net_lost) AND (rr_data->ms_data.req_mm_service EQ FUNC_PLMN_SRCH)) + { + /* Radio Link failure in dedicated state and cell reselection failed. + * Start Fast search + */ + search_mode = FAST_SEARCH_MODE; + } + else + { + /* Normal return from dedicated mode, cell reselection failed + * Start Normal search + */ + search_mode = NORMAL_SEARCH_MODE; + } + + /* + * there is no candidate for coming back. So a cell + * selection is started from RR. + */ + /* XY:n inform GRR, and wait for CR_RSP */ +#ifdef GPRS + att_start_cell_selection_gprs (RR_ORIGINATED,search_mode); +#else + att_start_cell_selection (RR_ORIGINATED, CS_NOT_PARALLEL,search_mode); +#endif + } + } + //rr_data->mode_after_dedi = MODE_CELL_SELECTION; /* reset mode */ +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_neighbourcell | ++--------------------------------------------------------------------+ + + PURPOSE : The function checks a cell after cell reselection. + +*/ + +GLOBAL void att_check_neighbourcell (void) +{ + GET_INSTANCE_DATA; + BOOL cell_ok; + T_loc_area_ident * lai = &rr_data->nc_data[CR_INDEX].lai; + + TRACE_FUNCTION ("att_check_neighbourcell()"); + +#ifdef GPRS + if(att_gprs_check_ncell()) + return; +#endif + /* + * Calculate the cell reselection criterion C2 or C31/C32. + */ + #ifdef GPRS + if( rr_data->gprs_data.use_c31) + { + att_calculate_c31_c32(CR_INDEX); + +/* Implements RR Clone findings #8 */ + cell_ok = (!att_cell_barred_status_cr_no_cr (CR_INDEX) AND + att_check_c31_criterion(CR_INDEX) ); + } + else + { + #endif + att_calculate_c2 (CR_INDEX); + /* + * Check the cell. It shall not be barred and must have + * a positive cell reselection criterion C2. + */ + +/* Implements RR Clone findings #8 */ + cell_ok = ! att_cell_barred_status_cr_no_cr (CR_INDEX) AND + rr_data->nc_data[CR_INDEX].c2 > 0; + + + #ifdef GPRS + } + #endif + + /* + * the cell can be rejected by the SW shielding function. + * This has only an affect during type approval. + */ + if (cell_ok) + cell_ok = att_check_network (lai); + + /* + * Check against the list of forbidden location areas for roaming, + * but only if MM requested full service and we are still searching + * for full service. Do not prevent limited service reselection. + */ + if (cell_ok AND + (rr_data->cs_data.scan_mode NEQ CS_SECOND_SCAN) AND + (rr_data->ms_data.req_mm_service EQ FUNC_PLMN_SRCH)) + { + cell_ok = dat_roam_forb_lai_check (CR_INDEX); + } + + /* + * Additional tests are performed depending on the cell + * reselection type. + */ + TRACE_SELECTION_TYPE (rr_data->sc_data.selection_type); + switch (rr_data->sc_data.selection_type) + { + case CELL_RESELECTION_CR: + /* + * The MS was in idle mode and the check is + * 1. from limited service to full service or + * 2. from full service (VPLMN) to full service (HPLMN) + * + * The resulting RR service is set only if the cell is okay. + */ + if (cell_ok) + { + if (rr_data->ms_data.req_mm_service EQ FUNC_LIM_SERV_ST_SRCH OR + rr_data->cs_data.scan_mode EQ CS_SECOND_SCAN) + { + rr_data->ms_data.rr_service = LIMITED_SERVICE; + } + else + { + cell_ok = dat_plmn_equal_req(lai->mcc, lai->mnc, + rr_data->ms_data.plmn.mcc, + rr_data->ms_data.plmn.mnc); + if (cell_ok) + rr_data->ms_data.rr_service = FULL_SERVICE; + else + rr_data->ms_data.rr_service = LIMITED_SERVICE; + } + } + break; + + case CELL_SELECTION: + case CELL_RESELECTION: + case CELL_RESELECTION_NC: + case CELL_RESELECTION_RACH: + if(cell_ok) + { + /* + * 2 checks to be made + * + * - In case of FULL SERVICE additionally the PLMN is checked + * + * - We are in LIMITED service. + * If the req_mm_service is FUNC_LIM_SERV_ST_SRCH we + * will stay in LIMITED. + * If we are in limited because of forbidden LAI we enter FULL SERVICE. + */ + if(rr_data->ms_data.rr_service EQ FULL_SERVICE) + { + cell_ok = dat_plmn_equal_req (lai->mcc, + lai->mnc, + rr_data->ms_data.plmn.mcc, + rr_data->ms_data.plmn.mnc); + } + else if((rr_data->ms_data.rr_service EQ LIMITED_SERVICE) AND + (rr_data->ms_data.req_mm_service NEQ FUNC_LIM_SERV_ST_SRCH) AND + dat_plmn_equal_req (lai->mcc, + lai->mnc, + rr_data->ms_data.plmn.mcc, + rr_data->ms_data.plmn.mnc) ) + { + rr_data->ms_data.rr_service = FULL_SERVICE; + } + + } + break; + + case BACK_FROM_DEDICATED: + case BACK_FROM_DEDICATED_RLF: + /* The mobile is trying to select a cell after coming back from dedicated + * state. The cell is selected only if it belongs to the previously selected + * PLMN + */ + if(cell_ok) + { + /* While selecting a cell after an emergency call, we need not check the + * PLMN ID of the cell */ + if(rr_data->ms_data.rr_service EQ FULL_SERVICE) + { + cell_ok = dat_plmn_equal_req (lai->mcc, + lai->mnc, + rr_data->ms_data.plmn.mcc, + rr_data->ms_data.plmn.mnc); + } + + TRACE_EVENT_P6 ("B_F_D New PLMN : MCC=%X%X%X MNC=%X%X%X", + lai->mcc[0], + lai->mcc[1], + lai->mcc[2], + lai->mnc[0], + lai->mnc[1], + lai->mnc[2]); + TRACE_EVENT_P6 ("B_F_D Old PLMN : MCC=%X%X%X MNC=%X%X%X", + rr_data->ms_data.plmn.mcc[0], + rr_data->ms_data.plmn.mcc[1], + rr_data->ms_data.plmn.mcc[2], + rr_data->ms_data.plmn.mnc[0], + rr_data->ms_data.plmn.mnc[1], + rr_data->ms_data.plmn.mnc[2]); + } + if(rr_data->sc_data.selection_type EQ BACK_FROM_DEDICATED) + break; + + /* + * in case of call reestablishment check also call reestablishment flag + */ + if (cell_ok) + { + if (rr_data->nc_data[CR_INDEX].rach.re NEQ REESTAB_YES) + cell_ok = FALSE; + } + break; + } + + /* + * the requirement check is finished + */ + if (cell_ok) + { + TRACE_EVENT_P2 ("NEW SC [%d]->[%d]", + rr_data->nc_data[SC_INDEX].arfcn, + rr_data->nc_data[CR_INDEX].arfcn); + + /* + * Stop T_RESELECT, which controls the reception of the complete BCCH + * during Cell Reselection. + */ + TIMERSTOP (T_RESELECT); + + + /* T3122 controls after how long the MS is able to attempt access back to the */ + /* cell from which it received a IMM ASSGN REJ. This no longer applies after a */ + /* cell reselection onto a new cell. */ + + TIMERSTOP(T3122); + + + /* + * copy all data from the SC_INDEX storage area to the neighbourcell area. + * copy all data from the CR_INDEX storage area to the SC_INDEX area. + * old serving cell data index is stored in old_serving_cell. + */ + att_copy_cr_data (); + + memcpy (&rr_data->sc_data.cd, &rr_data->cr_data.cd, + sizeof (T_CELL_DATA)); + + if(rr_data->ms_data.rr_service EQ FULL_SERVICE) + { + att_full_service_found(); + } + + rr_data->nc_data[CR_INDEX].arfcn = NOT_PRESENT_16BIT; + /* + * GSM 5.08, chapter 6.4: + * + * T is a timer implemented for each cell in the list of strongest + * carriers. + * T shall be started from zero at the time the cell is placed by the MS on + * the list of strongest carriers, except when the previous serving cell is + * placed on the list of strongest carriers at cell reselection. In this + * case, T shall be set to the value of PENALTY_TIME (i.e. expired). + */ + switch (rr_data->sc_data.selection_type) + { + case CELL_RESELECTION: + case CELL_RESELECTION_NC: + case CELL_RESELECTION_RACH: + /* + * set the avail time of the old serving cell to PENALTY_TIME. + */ + if (rr_data->old_serving_cell < SC_INDEX) + rr_data->nc_data[rr_data->old_serving_cell].avail_time = + rr_data->nc_data[rr_data->old_serving_cell].c2_par.penalty_time; + break; + + default: + break; + } + + + /* + * set a barrier of 15 seconds for the next cell reselection + * if it was a cell reselection due to C2(NC) > C2(SC) + */ + if (rr_data->sc_data.selection_type EQ CELL_RESELECTION_NC) + TIMERSTART (T_NO_RESELECT, THIRTY_SEC/2); + +#ifdef GPRS + if(! att_gprs_is_avail()) + { +#endif + + /* + * configure layer 1 + */ + att_remove_bad_rr_data_ncells(); + att_set_pl_in_idle_mode (); + + /* + * inform data transfer process that the cell is attached. + */ + dat_att_cell_selected (); + + /* + * inform MM about new cell + */ + if (rr_data->sc_data.mm_started) + att_code_rr_act_cnf (); + else + att_code_rr_act_ind (); + + SET_STATE (STATE_ATT, ATT_IDLE); + srv_use_stored_prim (); + /* + * Start registration timer if needed + */ + att_start_registration_timer (); + /* + * if the cell reselection has been started after a dedicated connection + * attempt with failed SABM / UA content a second attempt is started + * immediately. + */ + if (rr_data->repeat_est) + { + rr_data->repeat_est = FALSE; + dat_start_immediate_assign (rr_data->ms_data.establish_cause); + } +#ifdef GPRS + } + else + { + if(rr_data->ms_data.rr_service NEQ FULL_SERVICE) + { + if(att_gprs_cell_has_pbcch()) + { + /* set to PIM_BCCH if the cell hs a PBCCH but we + * only have limited service + */ + SET_STATE(STATE_GPRS, GPRS_PIM_BCCH); + } + } + + if(att_gprs_cell_has_pbcch()) + { + att_gprs_stop_pl(); + } + else + { + att_remove_bad_rr_data_ncells(); + att_set_pl_in_idle_mode (); + } + /* inform GRR if we have GPRS support */ + att_signal_gprs_support(); + /* and wait for CR_REQ(CR_COMPLETE) from GRR */ + } +#endif + } + else + { + /* + * the cell reselection failed for this channel and is continued + * with the next candidate. + */ + TRACE_EVENT_P1 ("[%u] CR failed", rr_data->nc_data[CR_INDEX].arfcn); + rr_data->pag_rec = FALSE; + srv_clear_stored_prim (MPH_PAGING_IND); + att_continue_cell_reselect (); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_neighbourcell_si_reestab | ++--------------------------------------------------------------------+ + + PURPOSE : This function checks if revelant sys info is present is ATT_CS3 state. + Special case : Sys Info 2Ter is not needed if we have a pending call re-establishment + +*/ + +GLOBAL void att_check_neighbourcell_si_reestab (void) +{ + GET_INSTANCE_DATA; + /* + * Sometimes the network indicates SI2Ter but never sends it. + * If we have a call re-establishment pending, then we must not wait + * for SI2Ter. + */ + if( (rr_data->cr_data.cd.sys_info_read EQ ALL_SYS_INFO_READ) + OR + ( (rr_data->cr_data.cd.sys_info_read EQ SYS_INFO_EXCEPT_2TER) AND + (rr_data->sc_data.selection_type EQ BACK_FROM_DEDICATED_RLF)) + ) + { + att_check_neighbourcell (); + } + + /* + * In case of Radio Link Failure, check cell for call + * re-establishment capability. + */ + if (rr_data->sc_data.selection_type EQ BACK_FROM_DEDICATED_RLF) + att_check_reestablishment(); + +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_reestablishment | ++--------------------------------------------------------------------+ + + PURPOSE : The function checks whether a cell has no call re-establishment + capability. In this case the cell reselection is resumed + with the next cell. + +*/ + +GLOBAL void att_check_reestablishment (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_check_reestablishment()"); + + if (rr_data->nc_data[CR_INDEX].rach.re NEQ REESTAB_YES) + { + /* + * the cell reselection failed for this channel and is continued + * with the next candidate due to no call re-establishment + * capability. + */ + TRACE_EVENT_P2 ("[%u]7 (BCCH-St=%u) have no call re-establishment capability", + rr_data->nc_data[CR_INDEX].arfcn, rr_data->nc_data[CR_INDEX].bcch_status); + + rr_data->pag_rec = FALSE; + srv_clear_stored_prim (MPH_PAGING_IND); + att_continue_cell_reselect (); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_reselect_decision| ++--------------------------------------------------------------------+ + + PURPOSE : After reception of measurement values from layer 1 in + idle mode the cell reselection decision is done by this + function. It checks the measurement related criterions + for cell reselection. The flag start_now indicates + whether only the decision is taken or the cell reselection + is started immediately. It is senseful to delay a cell + reselection during a PLMN available search triggered by MM. + +*/ + +GLOBAL void att_check_reselect_decision (UBYTE start_now) +{ + GET_INSTANCE_DATA; + UBYTE i; + SHORT delta; + + TRACE_FUNCTION ("att_check_reselect_decision()"); + #ifdef GPRS + TRACE_EVENT_P2("check_reselect: start_cell_reselection=%u calc %s", + rr_data->start_cell_reselection, rr_data->gprs_data.use_c31 ? "C31,C32":"C2"); + #endif + /* + * Calculate for all synchronized neighbourcells, which have + * decoded the system information messages for calculation C2, + * and for the serving cell the cell reselection criterion C2. + */ + for (i = 0; i < 7; i++) + { + if (rr_data->nc_data[i].bcch_status EQ DECODED) + { + #ifdef GPRS + if( rr_data->gprs_data.use_c31) + att_calculate_c31_c32(i); + else + #endif + att_calculate_c2 (i); + } + else if (rr_data->nc_data[i].bcch_status NEQ EMPTY AND + rr_data->nc_data[i].arfcn NEQ NOT_PRESENT_16BIT ) + { + TRACE_EVENT_P2("[%u]i%u no C2 (SIs missing)", + rr_data->nc_data[i].arfcn,i); + } + } + + /* + * Check C1 serving cell < 0 for more then 5 seconds + * The c1_counter counts the number of reports where + * this criterion has passed. + */ + if (rr_data->nc_data[SC_INDEX].c1 < 0) + { + /* + * if c1_counter has a value of at least 1 it had happened + * for at least two successive reports, that means more + * then five seconds. + */ + if ( (rr_data->nc_data[SC_INDEX].c1_counter > 0) + #ifdef GPRS + OR + (rr_data->gprs_data.use_c31) + #endif + ) + { + /* + * reset the counter and start ! + */ + rr_data->nc_data[SC_INDEX].c1_counter = 0; +#ifdef GPRS + /* check if we can do a cell reselection */ + if(!is_nc2_used()) + { +#endif + if (start_now ) + { +/*XY:n inform GRR, and wait for CR_RSP */ +#ifdef GPRS + att_start_cell_reselection_gprs (CELL_RESELECTION); +#else + att_start_cell_reselection (CELL_RESELECTION); +#endif + } +#ifdef GPRS + } +#endif + return; + } + else + { + /* + * the criterion has passed the first time, so + * increase the counter and wait for the next measurement value. + */ + rr_data->nc_data[SC_INDEX].c1_counter++; +#if defined(_SIMULATION_) + TRACE_EVENT_WIN_P1 ("CR SC delayed (%d)", rr_data->nc_data[SC_INDEX].c1_counter); +#endif + } + } + else + { + /* + * The C1 of the serving cell is positive, so clear the c1_counter. + */ + rr_data->nc_data[SC_INDEX].c1_counter = 0; +#if defined(_SIMULATION_) + TRACE_EVENT_WIN_P1 ("CR SC c1_counter=%d", rr_data->nc_data[SC_INDEX].c1_counter); +#endif + } + /* + * check if C31\C32 based reselection is required + */ + #ifdef GPRS + if( rr_data->gprs_data.use_c31 ) + { + att_check_c31_reselect_decision(start_now); + return; + } + #endif + /* + * Check C2(NC) > C2(SC) for all neighbourcells + */ + for (i = 0; i < 6; i++) + { + /* + * If data is stored for this neighbourcell + */ + if (rr_data->nc_data[i].bcch_status EQ DECODED) + { +/* + TRACE_EVENT_P2 ("COMPARE NC[%d]-SC[%d]", + rr_data->nc_data[i].arfcn, + rr_data->nc_data[SC_INDEX].arfcn); +*/ +#ifdef GPRS + /* + * check if the location area has changed + * or the routing area if the scell supports GPRS + */ + { + BOOL la_same, ra_same; + + if (dat_plmn_equal_req (rr_data->nc_data[i].lai.mcc, + rr_data->nc_data[i].lai.mnc, + rr_data->nc_data[SC_INDEX].lai.mcc, + rr_data->nc_data[SC_INDEX].lai.mnc) + AND + rr_data->nc_data[i].lai.lac EQ + rr_data->nc_data[SC_INDEX].lai.lac) + la_same = TRUE; + else + la_same = FALSE; + /* + * If gprs is not available do not care about the routing area + * + */ + if(att_gprs_is_avail()) + { + if(rr_data->nc_data[i].rac EQ NOT_PRESENT_8BIT OR + rr_data->nc_data[i].rac EQ rr_data->nc_data[SC_INDEX].rac) + { + ra_same = TRUE; + } + else + { + ra_same = FALSE; + } + } + else + { + ra_same = TRUE; + } + + if(la_same AND ra_same AND !rr_data->gprs_data.ready_state) +#else /* GPRS */ + if (dat_plmn_equal_req (rr_data->nc_data[i].lai.mcc, + rr_data->nc_data[i].lai.mnc, + rr_data->nc_data[SC_INDEX].lai.mcc, + rr_data->nc_data[SC_INDEX].lai.mnc) + AND + rr_data->nc_data[i].lai.lac EQ + rr_data->nc_data[SC_INDEX].lai.lac) +#endif /* GPRS */ + { + /* + * If it is in the same location area as the serving cell, + * the delta is simply the difference of both cell reselection + * criterion values C2. + */ + TRACE_EVENT_P3 ("NC[%d]i%u-SC[%d] same LAI", + rr_data->nc_data[i].arfcn,i, + rr_data->nc_data[SC_INDEX].arfcn); + + delta = rr_data->nc_data[i].c2 - + rr_data->nc_data[SC_INDEX].c2; + + /* + * 3GPP TS 05.08, section 6.6.2: + * in case of a cell reselection occurring within the previous 15 seconds + * in which case the C2 value for the new cell shall exceed the C2 value + * of the serving cell by at least 5 dB for a period of 5 seconds + */ + + if ( IS_TIMER_ACTIVE (T_NO_RESELECT) ) + { + delta -= 5; + } + else + { + /* When C2(NC)==C2(SC) i.e. delta=0, an invalid cell reselection gets triggered below. + * 'delta' needs to be adjusted to prevent this happening. The '=' in the '>=' + * condition below only applies when T_NO_RESELECT timer is active and + * c2_corr has been decremented by 5 (above statement) + */ + if(delta EQ 0 ) + { + delta = -1; + } + } + } + else + { + /* + * If both are member of different location areas, a threshold + * value CELL_RESELECTION_HYSTERESE is taken in account. + */ + TRACE_EVENT_P3 ("NC[%d]i%u-SC[%d] different LAI", + rr_data->nc_data[i].arfcn,i, + rr_data->nc_data[SC_INDEX].arfcn); + + delta = att_calculate_c2_diff (i); + } +#ifdef GPRS + } +#endif + /* + * Check cell barred status before going + * into Cell Reselection state. + * This will actually also be checked again + * in att_check_cell but the CRH value will + * not be used for subsequent ncells leading + * to false CR's. We check it here + * to use CRH for the next cell if needed. + */ +/* Implements RR Clone findings #8 */ + if(att_cell_barred_status_cr_no_cr(i)) + delta = -1; + + /* + * Do not trigger a cell reselection decision on meas. report + * receipt if the cell belong to a LA not allowed for roaming. + * According to 3.22 chapter 3.5.4 cell reselection on a + * forbidden LA for regional provision of service is allowed. + */ + if (rr_data->ms_data.rr_service EQ FULL_SERVICE) + { + if (!dat_roam_forb_lai_check(i)) + delta = -1; + } + +#if defined(_SIMULATION_) + TRACE_EVENT_WIN_P1 ("delta=%d", delta); +#endif + if(delta == 0) TRACE_EVENT("No reselection delta == 0"); + if (delta > 0) + { + /* + * The condition C2(NC) > C2(SC) is fulfilled. + */ + if (rr_data->nc_data[i].c1_counter > 0) + { + /* + * the conditions is fulfilled at least two times ( > 5 seconds) + * and there is no barrier to start the cell + * reselection. + */ +#ifdef GPRS + /* check if we can do a cell reselection */ + if(!is_nc2_used()) + { +#endif + if (start_now) + { + rr_data->nc_data[i].c1_counter = 0; +/*XY:n inform GRR, and wait for CR_RSP */ +#ifdef GPRS + att_start_cell_reselection_gprs(CELL_RESELECTION_NC); +#else + att_start_cell_reselection (CELL_RESELECTION_NC); +#endif + } +#ifdef GPRS + } +#endif + return; + } + else + { + /* + * The condition has passed the first time or is delayed + * by the barrier to perform a cell reselection due to this reasons + * not faster then in periods of 15 seconds. + */ + rr_data->nc_data[i].c1_counter++; + TRACE_EVENT_P3 ("NC[%u]i%u CR delayed (%d)", + rr_data->nc_data[i].arfcn,i,rr_data->nc_data[i].c1_counter); + } + } + else + { + /* + * the condition is not fullfilled and the counter is resetted. + */ + rr_data->nc_data[i].c1_counter = 0; + } + } + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_barred_status_in_idle| ++--------------------------------------------------------------------+ + + PURPOSE : + +*/ + +GLOBAL void att_check_barred_status_in_idle (void) +{ + TRACE_FUNCTION ("att_check_barred_status_in_idle()"); + + /* + * check whether serving cell is barred + */ +/*XY:n inform GRR, and wait for CR_RSP */ + +/* Implements RR Clone findings #8 */ + if (att_cell_barred_status_cr_no_cr (SC_INDEX) EQ TRUE) + { + +#ifdef GPRS + att_start_cell_reselection_gprs (CELL_RESELECTION); +#else + att_start_cell_reselection (CELL_RESELECTION); +#endif + } +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_clear_forb_list | ++--------------------------------------------------------------------+ + + PURPOSE : RR stores some forbidden lists. This function clears + the given forbidden list. + +*/ + +static void att_clear_forb_list (int list_type) +{ + GET_INSTANCE_DATA; + int i; + T_loc_area_ident *forb_list; + + TRACE_FUNCTION ("att_clear_forb_list()"); + + if (list_type EQ FORBIDDEN_LIST_NORMAL) + forb_list = &rr_data->ms_data.forb_lac_list[0]; + else + forb_list = &rr_data->ms_data.roam_forb_lac_list[0]; + +/* Implements Measure#32: Row 29 */ + if(list_type EQ FORBIDDEN_LIST_NORMAL) + { + TRACE_EVENT ( "CLEAR FORB LIST"); + } + else + { + TRACE_EVENT ( "CLEAR ROAM FORB LIST"); + } + + + for (i = 0; i < MAX_LAI; i++) + { + memset (forb_list[i].mcc, NOT_PRESENT_8BIT, SIZE_MCC); + memset (forb_list[i].mnc, NOT_PRESENT_8BIT, SIZE_MNC); + forb_list[i].lac = NOT_PRESENT_16BIT; + } +} + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_clear_registration_data| ++--------------------------------------------------------------------+ + + PURPOSE : The function is called after reception of RR_SYNC_REQ, + which is sent by MM after some Location Updating Reject + causes which indicate that the IMSI is invalid, paging + shall be suppressed and RR shall enter only a limited mode. + +*/ + +GLOBAL void att_clear_registration_data (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_clear_registration_data()"); + + TRACE_EVENT ("CLEAR registration data (IMSI, MCC, MNC)"); + + /* + * Clear the IMSI related data and enter the + * limited mode. + */ + rr_data->ms_data.operation_mode = 0; + att_clear_parallel_search (); + rr_data->ms_data.current_plmn_search_type = FUNC_LIM_SERV_ST_SRCH; + rr_data->ms_data.imsi_available = FALSE; + rr_data->ms_data.plmn.mcc[0] = NOT_PRESENT_8BIT; + rr_data->ms_data.plmn.mnc[0] = NOT_PRESENT_8BIT; + rr_data->ms_data.v_eq_plmn = FALSE; + + /*we only have limited service*/ + rr_data->ms_data.rr_service = LIMITED_SERVICE; + rr_data->ms_data.req_mm_service = FUNC_LIM_SERV_ST_SRCH; + + TRACE_EVENT_P3 ("att_clear_registration_data: current=%s, service:rMM=%s RRs=%s", + _rr_str_FUNC[rr_data->ms_data.current_plmn_search_type], + _rr_str_FUNC[rr_data->ms_data.req_mm_service], + _rr_str_SERVICE[rr_data->ms_data.rr_service]); + + /* + * clear TMSI and ciphering data + */ + att_clear_reg_without_imsi (); + att_set_rr_service_info(); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_clear_reg_without_imsi | ++--------------------------------------------------------------------+ + + PURPOSE : After some location updating reject causes MM informs RR + that the TMSI and the ciphering data are invalid. + +*/ + +GLOBAL void att_clear_reg_without_imsi (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_clear_reg_without_imsi()"); + + /* + * clear TMSI + */ + rr_data->ms_data.tmsi_available = FALSE; + rr_data->ms_data.tmsi_binary = 0; + + /* + * clear ciphering data + */ + rr_data->ms_data.cksn = CKSN_NOT_PRES; + memset (rr_data->ms_data.kc, NOT_PRESENT_8BIT, KC_STRING_SIZE); + memset (rr_data->ms_data.new_kc, NOT_PRESENT_8BIT, KC_STRING_SIZE); + + /* + * update the identities in layer 1. + */ + att_mph_identity_req (); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_reorder_mph_ncell_req | ++--------------------------------------------------------------------+ + + PURPOSE : reorders a neighbourcell list for layer 1 to make sure + that the strongest neighbour cells are the first ones + in the list and are therefore measured first by layer 1 +*/ + +static void att_reorder_mph_ncell_req (T_MPH_NEIGHBOURCELL_REQ * mph_ncell_req) +{ + GET_INSTANCE_DATA; +#define MAX_STRONGEST 6 /* MAX_STRONGEST must be at least 6 but up to 8 makes sense */ + UBYTE i_nc, + i_nc1, + c_str_nc = 0, + c_str_cs = 0, + is_old = !IS_TIMER_ACTIVE(TCSVALID), + is_inserted, i, j; + SHORT arfcn, + rxlev, + str_arfcn[MAX_STRONGEST], + str_rxlev[MAX_STRONGEST]; + +#if defined(_SIMULATION_) + TRACE_EVENT_WIN_P6("ncell_req arfcns:%4d %4d %4d %4d %4d %4d", + mph_ncell_req->arfcn[0] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[0] : -1, + mph_ncell_req->arfcn[1] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[1] : -1, + mph_ncell_req->arfcn[2] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[2] : -1, + mph_ncell_req->arfcn[3] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[3] : -1, + mph_ncell_req->arfcn[4] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[4] : -1, + mph_ncell_req->arfcn[5] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[5] : -1); +#endif + + memset (str_arfcn, -1, sizeof str_arfcn); /* for easier debugging */ + memset (str_rxlev, -1, sizeof str_rxlev); + + /* + * search for the strongest neighbourcells and collect them in + * the arrays str_arfcn/str_rxlev. An arfcn found in the nc_data + * is always stored before an arfcn found in the cs_data. The reason + * is that the nc_data are almost younger and probably more important be + * and there may big differences between the rxlev values for the + * same arfcn delevered by MPHC_RXLEV_IND and by MPHC_RXLEV_PERIODIC_IND + */ + for (i_nc = 0; i_nc < MAX_NEIGHBOURCELLS AND + mph_ncell_req->arfcn[i_nc] NEQ NOT_PRESENT_16BIT; i_nc++) + { + arfcn = mph_ncell_req->arfcn[i_nc]; + + if (arfcn EQ rr_data->nc_data[SC_INDEX].arfcn) + continue; /* processing neighbour cell list in *mph_ncell_req */ + + /* + * for all channels of stored neighbour cell data + */ + is_inserted = FALSE; + for (i_nc1 = 0; i_nc1 < 6; i_nc1++) + { + if (arfcn EQ rr_data->nc_data[i_nc1].arfcn) + { + if (rr_data->nc_data[i_nc1].bcch_status NEQ EMPTY) + { + rxlev = rr_data->nc_data[i_nc1].rxlev; + is_inserted = TRUE; /* avoid double inserting */ + for (i = c_str_nc; i > 0 AND rxlev > str_rxlev[i-1]; i--) + ; /* search for the place to insert */ + if (i EQ c_str_nc AND c_str_nc >= MAX_STRONGEST) + break; /* not strong enough */ + j = (c_str_cs >= MAX_STRONGEST) ? MAX_STRONGEST-1 : c_str_cs; + for ( ; j > i; j--) + { /* make place for current entry */ + str_rxlev[j] = str_rxlev[j-1]; + str_arfcn[j] = str_arfcn[j-1]; + } + str_arfcn[i] = arfcn; + str_rxlev[i] = rxlev; + /* if (c_str_nc < MAX_STRONGEST) needed if MAX_STRONGEST < 6 */ + c_str_nc++; + if (c_str_cs < MAX_STRONGEST) + c_str_cs++; + } + break; /* scanning stored neighbour cell data */ + } + } /* for: stored neighbour cell data */ + + if (is_old OR is_inserted) + continue; /* CS measurements are too old */ + + /* + * for all channels of the power campaign list + */ + for (i_nc1 = 0; i_nc1 < rr_data->cs_data.max_arfcn; i_nc1++) + { + if (arfcn EQ rr_data->cs_data.arfcn[i_nc1]) + { + rxlev = rr_data->cs_data.rxlev[i_nc1]; + for (i = c_str_cs; i > c_str_nc AND rxlev > str_rxlev[i-1]; i--) + ; /* search for the place to insert */ + if (i EQ c_str_cs AND c_str_cs >= MAX_STRONGEST) + break; /* not strong enough */ + j = (c_str_cs >= MAX_STRONGEST) ? MAX_STRONGEST-1 : c_str_cs; + for (; j > i; j--) + { /* make place for current entry */ + str_rxlev[j] = str_rxlev[j-1]; + str_arfcn[j] = str_arfcn[j-1]; + } + str_arfcn[i] = arfcn; + str_rxlev[i] = rxlev; + if (c_str_cs < MAX_STRONGEST) + c_str_cs++; + break; /* scanning power campaign list */ + } + } /* for: power campaign list */ + } /* for: mph_ncell_req->arfcn */ + + TRACE_EVENT_P7("c_str_nc=%u arfcn:%4d %4d %4d %4d %4d %4d", + c_str_nc, str_arfcn[0], str_arfcn[1], str_arfcn[2], + str_arfcn[3], str_arfcn[4], str_arfcn[5]); + TRACE_EVENT_P7("c_str_cs=%u rxlev:%4d %4d %4d %4d %4d %4d", + c_str_cs, str_rxlev[0], str_rxlev[1], str_rxlev[2], + str_rxlev[3], str_rxlev[4], str_rxlev[5]); + /* now reorder the arfcn's in the primitive */ + for (i_nc1 = 0; i_nc1 < c_str_cs; i_nc1++) + { + for (i_nc = 0; i_nc < MAX_NEIGHBOURCELLS AND + mph_ncell_req->arfcn[i_nc] NEQ NOT_PRESENT_16BIT; i_nc++) + { + if (str_arfcn[i_nc1] EQ mph_ncell_req->arfcn[i_nc]) + { /* swap */ + arfcn = mph_ncell_req->arfcn[i_nc1]; + mph_ncell_req->arfcn[i_nc1] = mph_ncell_req->arfcn[i_nc]; + mph_ncell_req->arfcn[i_nc] = arfcn; + break; + } + } /* for: mph_ncell_req->arfcn */ + } /* for: str_arfcn */ + TRACE_EVENT_P6("strongest arfcns:%4d %4d %4d %4d %4d %4d", + mph_ncell_req->arfcn[0] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[0] : -1, + mph_ncell_req->arfcn[1] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[1] : -1, + mph_ncell_req->arfcn[2] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[2] : -1, + mph_ncell_req->arfcn[3] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[3] : -1, + mph_ncell_req->arfcn[4] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[4] : -1, + mph_ncell_req->arfcn[5] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[5] : -1); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_remove_bad_ncell | ++--------------------------------------------------------------------+ + + PURPOSE : removes outdated ncells from RR store. + +*/ + +GLOBAL void att_remove_bad_rr_data_ncells() +{ + GET_INSTANCE_DATA; + T_CELL_DATA * cd; + UBYTE i_nc, index; + UBYTE found; + USHORT act_ncell_list [MAX_NEIGHBOURCELLS]; + /* + * get the pointer to the correct list. + */ + + cd = &rr_data->sc_data.cd; + memset (act_ncell_list, 0xFF, 2*MAX_NEIGHBOURCELLS); + srv_create_list (&cd->ncell_list, act_ncell_list, MAX_NEIGHBOURCELLS, FALSE, 0); + + for( index = 0; index < SC_INDEX; index++) + { + TRACE_EVENT_P3("[%u]i%u bcch_status=%u", rr_data->nc_data[index].arfcn, + index, rr_data->nc_data[index].bcch_status); + if( rr_data->nc_data[index].bcch_status NEQ EMPTY ) + { + found = FALSE; + for( i_nc = 0; act_ncell_list[i_nc] NEQ NOT_PRESENT_16BIT ; i_nc++) + { + if( rr_data->nc_data[index].arfcn EQ act_ncell_list[i_nc] ) + { + found = TRUE; + break; + } + } + if( ! found ) + { + TRACE_EVENT_P1(" Removing bad ncell [%u]", rr_data->nc_data[index].arfcn ); + rr_data->nc_data[index].bcch_status = EMPTY; + rr_data->nc_data[index].arfcn = 0; + rr_data->nc_data[index].avail_time = 0; + } + } + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_code_mph_ncell_req | ++--------------------------------------------------------------------+ + + PURPOSE : build a neighbourcell list for layer 1 in idle mode. + +*/ + +GLOBAL void att_code_mph_ncell_req (UBYTE index) +{ + GET_INSTANCE_DATA; + T_CELL_DATA * cd; + + PALLOC (mph_ncell_req, MPH_NEIGHBOURCELL_REQ); + + TRACE_FUNCTION ("att_code_mph_ncell_req()"); + + /* + * get the pointer to the correct list. + */ + if (index EQ SC_INDEX) + cd = &rr_data->sc_data.cd; + else + cd = &rr_data->cr_data.cd; + + + cs_remove_BA_MA_from_black_list(rr_data->cs_data.region,&cd->ncell_list); + + /* + * use neighbour cell list from system info 2/2bis/2ter + */ + memset (mph_ncell_req->arfcn, 0xFF, 2*MAX_NEIGHBOURCELLS); + srv_create_list (&cd->ncell_list, + mph_ncell_req->arfcn, MAX_NEIGHBOURCELLS, FALSE, + 0); + memcpy (rr_data->act_ncell_list, mph_ncell_req->arfcn, + sizeof (rr_data->act_ncell_list)); + +#if defined(_SIMULATION_) + TRACE_EVENT_WIN_P6("ncell_req arfcns:%4d %4d %4d %4d %4d %4d", + mph_ncell_req->arfcn[0] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[0] : -1, + mph_ncell_req->arfcn[1] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[1] : -1, + mph_ncell_req->arfcn[2] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[2] : -1, + mph_ncell_req->arfcn[3] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[3] : -1, + mph_ncell_req->arfcn[4] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[4] : -1, + mph_ncell_req->arfcn[5] NEQ NOT_PRESENT_16BIT ? + mph_ncell_req->arfcn[5] : -1); +#endif + + /* + * set the multiband parameter + */ + mph_ncell_req->multi_band = rr_data->ncell_mb; +#ifdef GPRS + mph_ncell_req->sync_only = NORMAL_BA; +#endif + /* + * check the list against band restrictions. + */ + srv_remove_frequencies_in_array (&mph_ncell_req->arfcn[0]); + + att_reorder_mph_ncell_req(mph_ncell_req); + /* + * send the list to layer 1 + */ + PSENDX (PL, mph_ncell_req); +#if defined (REL99) && defined (TI_PS_FF_EMR) + for_check_and_configure_si2quater(index); +#endif + +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_code_mph_ncell_req_dedicated | ++--------------------------------------------------------------------+ + + PURPOSE : builds a neighbourcell list for layer 1 in dedicated mode. + +*/ + +GLOBAL void att_code_mph_ncell_req_dedicated (void) +{ + GET_INSTANCE_DATA; + UBYTE start_index = 0; + UBYTE old_index; + + if ( rr_data->emo_arfcn EQ NULL ) + { +#if defined (REL99) && defined (TI_PS_FF_EMR) + USHORT si_read = (USHORT) (SYS_INFO_5_READ | SYS_INFO_5BIS_READ); + + rr_data->sc_data.ba_list_ded = FALSE; + if ( (rr_data->sc_data.cd.sys_info_read & si_read ) EQ si_read ) + { + rr_data->sc_data.ba_list_ded = TRUE; + rr_data->sc_data.ba_list_idle = FALSE; + old_index = rr_data->sc_data.ba_index; + rr_data->sc_data.ba_index = rr_data->sc_data.new_ba_index; + } + else if (rr_data->sc_data.ba_list_idle EQ TRUE) + return; +#endif + { + PALLOC (mph_ncell_req, MPH_NEIGHBOURCELL_REQ); + + /* + * initialise data structures, + * clear ncell list to layer 1, + * set multiband parameter. + */ + memset (mph_ncell_req->arfcn, 0xFF, 2*MAX_NEIGHBOURCELLS); + mph_ncell_req->multi_band = rr_data->ncell_mb; + + /* + * fill system info 5 and 5bis + */ + if (rr_data->sc_data.cd.sys_info_read & (SYS_INFO_5_READ | SYS_INFO_5BIS_READ)) + start_index = srv_create_list (&rr_data->sc_data.cd.ncell_list, + mph_ncell_req->arfcn, + MAX_NEIGHBOURCELLS, + FALSE, + 0); + /* + * fill system info 5ter + */ + if (rr_data->sc_data.cd.sys_info_read & SYS_INFO_5TER_READ) + srv_create_list (&rr_data->sc_data.five_ter_list, + mph_ncell_req->arfcn, + MAX_NEIGHBOURCELLS, + FALSE, + start_index); + /* + * Copy complete list for position detection for uplink + * measurement reports. + */ + memcpy (rr_data->act_ncell_list, mph_ncell_req->arfcn, + sizeof (rr_data->act_ncell_list)); + + /* + * check against band restrictions + */ + srv_remove_frequencies_in_array (&mph_ncell_req->arfcn[0]); + + /* + * send list to layer 1. + */ + PSENDX (PL, mph_ncell_req); + } +#if defined (REL99) && defined (TI_PS_FF_EMR) + if (rr_data->sc_data.ba_list_ded NEQ TRUE ) + return; + att_check_for_si5ter_and_enhpara(old_index); +#endif + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_code_prr_mm_info | ++--------------------------------------------------------------------+ + + PURPOSE : provide MM at the end of cell selection or cell reselection + with MM relevant data from the BCCH channel. These + informations are: + + IMSI attach / detach + Call Reestablishment capability + Base Station Identification Code + Periodic Location Updating Time T3212 + and whether the MS camps in a forbidden location area. + +*/ + +static void att_code_prr_mm_info (T_mm_info *mm_info) +{ + GET_INSTANCE_DATA; + T_NC_DATA *rrd = &rr_data->nc_data[SC_INDEX]; + + TRACE_FUNCTION ("att_code_prr_mm_info()"); + + mm_info->valid = TRUE; + mm_info->att = rrd->control_descr.att; + mm_info->re = rrd->rach.re; + mm_info->ncc = (rrd->bsic >> 3) & 7; + mm_info->bcc = rrd->bsic & 7; + mm_info->t3212 = rrd->control_descr.t3212; + mm_info->la = (!(dat_forb_lai_check (SC_INDEX) AND + dat_roam_forb_lai_check (SC_INDEX))); + + /* + * Parameter band needs a dummy value, otherwise component tests of RR + * fail due to lack of ability of TAP + */ + mm_info->band = BND_DMY_VAL; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_code_rr_abort_ind | ++--------------------------------------------------------------------+ + + PURPOSE : Indication of a failed cell selection or cell reselection + to MM. + +*/ +GLOBAL void att_code_rr_abort_ind_original (T_RR_DATA *rr_dat, USHORT cause) +{ + GET_INSTANCE_DATA; + int i; + PALLOC (abort_ind, RR_ABORT_IND);/* T_RR_ABORT_IND */ + + TRACE_FUNCTION ("att_code_rr_abort_ind()"); + + memset (abort_ind, 0, sizeof (*abort_ind)); + + /* + * Indicates the end of a plmn available search + */ + if (rr_dat->ms_data.req_mm_service EQ FUNC_NET_SRCH_BY_MMI) + { + /* this sets the state of CS */ + cs_set_stop_active(); + } + + TIMERSTOP(TABORT); + /* + * Set the parameters for MM, especially the requested service + * from MM and the real reached service of RR. + */ + abort_ind->op.v_op = 1; + abort_ind->op.ts = (rr_dat->ms_data.operation_mode >> SHIFT_FOR_SIM_TYPE) & 1; + abort_ind->op.m = (rr_dat->ms_data.operation_mode >> SHIFT_FOR_SEARCH_OFFSET) & 1; + abort_ind->op.sim_ins = (rr_dat->ms_data.operation_mode >> SHIFT_FOR_SIM_INSERTED) & 1; + abort_ind->op.func = rr_dat->ms_data.req_mm_service; + abort_ind->op.service = rr_dat->ms_data.rr_service; + abort_ind->cause = cause; + + if(rr_dat->ms_data.rr_service EQ NO_SERVICE) + att_notify_stop_plmn_search (TRUE); + else + att_notify_stop_plmn_search (FALSE); + + /* + * resume normal RR operation and update the previous + * requested MM and RR services + */ + att_clear_parallel_search (); + + rr_dat->ms_data.req_mm_service = att_get_func (); + rr_data->cs_data.scan_mode = CS_NO_SCAN; + TRACE_EVENT_P1 ("cause=%x", cause); + + if (cause EQ RRCS_ABORT_CEL_SEL_FAIL) + { +#ifdef GPRS + if (abort_ind->op.func NEQ FUNC_NET_SRCH_BY_MMI AND + abort_ind->op.service EQ NO_SERVICE AND + att_gprs_is_avail()) + { + att_signal_gprs_support(); + } +#endif + + /* + * If the abort cause is cell selection failed + * add the list of available PLMNs. + */ + att_order_plmns (); + abort_ind->plmn_avail = rr_dat->sc_data.found_entries; + for (i=0; i < rr_dat->sc_data.found_entries; i++) + { + T_FOUND_ELEMENT *pfound = &rr_dat->sc_data.found[i]; + + abort_ind->plmn[i] = pfound->plmn; + abort_ind->rxlevel[i] = pfound->rxlev; + abort_ind->lac_list[i] =pfound->lac; //LOL 02.01.2003: added for EONS support + + TRACE_EVENT_P9 ("RR_ABORT_IND: [%u] MCC/MNC=%x%x%x/%x%x%x lac=%04x rx=%u", + pfound->arfcn, + pfound->plmn.mcc[0], + pfound->plmn.mcc[1], + pfound->plmn.mcc[2], + pfound->plmn.mnc[0], + pfound->plmn.mnc[1], + pfound->plmn.mnc[2], + pfound->lac, + pfound->rxlev); + } + + EM_NET_SEARCH_PASSED; + } + else + { + /* + * else clear this area of the primitive. + */ + abort_ind->plmn_avail = 0; + memset (abort_ind->plmn, 0, sizeof (abort_ind->plmn)); + memset (abort_ind->rxlevel, 0, sizeof (abort_ind->rxlevel)); + + EM_NET_SEARCH_FAILED; + } + + /* + * Set mobile RF capability for MM messages + */ + if (rr_dat->ms_data.rr_service EQ NO_SERVICE) + abort_ind->power = 0; + else + abort_ind->power = att_get_power(); + + if ((rr_data->ms_data.req_mm_service NEQ FUNC_NET_SRCH_BY_MMI) AND + (cause EQ RRCS_ABORT_CEL_SEL_FAIL)) + att_set_rr_service_info(); + + TRACE_OP_TYPE (&abort_ind->op, "RR_ABORT_IND"); + PSENDX (MM, abort_ind); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_order_plmns | ++--------------------------------------------------------------------+ + + PURPOSE : The function orders the found PLMNs after the following + criterions: + + all PLMNs with a fieldstrength greater then -85 dBm are + ordered randomly. This is 50 percent of the requirement + regarding GSM 3.22, chapter 4.4.3.1. MM checks then + the HPLMN condition and the preferred PLMN condition. + +*/ + +static void att_order_plmns (void) +{ + GET_INSTANCE_DATA; + USHORT nr; + USHORT i; + /* + * allocate dynamic memory to build a copy + * of the list which is ordered randomly + */ + T_FOUND_LIST * list; + + TRACE_FUNCTION ("att_order_plmns()"); + + /* + * initialize the copy + */ + MALLOC (list, sizeof (T_FOUND_LIST)); + memset (list, 0, sizeof (T_FOUND_LIST)); + + /* + * get the number of PLMNs which have a fieldstrength + * greater then -85 dBm. + */ + i=0; + while ((nr = att_number_of_plmns_greater_85_dBm()) NEQ 0 ) + { + /* + * get a value in the range 0..nr-1 + * i.e. select a PLMN greater -85 randomly + */ + nr = dat_random (nr); + + /* + * copy the nr-th plmn and indicate it in the source + * as copied. + */ + att_copy_found_plmn (list, nr, i); + + /* + * increment the number of copied networks. + */ + i++; + } + + /* + * copy all networks with a fieldstrength lower or equal -85 dBm. + */ + att_copy_plmns_lower_or_equal_85_dBm (list, i); + + /* + * copy back the randomly sorted list + */ + for (i=0; i < MAX_PLMN; i++) + rr_data->sc_data.found[i] = list->element[i]; + + /* + * de-allocate the dynamic memory + */ + MFREE (list); +} + +/* ++-----------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_number_of_plmns_greater_85_dBm | ++-----------------------------------------------------------------------+ + + PURPOSE : The function calculates the number of available PLMNs with a + fieldstrength higher then -85 dBm. + +*/ + +static USHORT att_number_of_plmns_greater_85_dBm (void) +{ + GET_INSTANCE_DATA; + USHORT nr = 0; + USHORT i; + + for (i=0; i< rr_data->sc_data.found_entries;i++) + { + if (rr_data->sc_data.found[i].plmn.v_plmn EQ V_PLMN_PRES) + { + if (rr_data->sc_data.found[i].rxlev > 25) + { + /* + * -85 dBm = -110 + 25 ! + * + * increment the number of found plmns. + */ + nr++; + } + } + } + + /* + * return the number of PLMNs with a fieldstrength greater than -85 dBm + */ + return nr; +} + +/* ++-----------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_found_plmn | ++-----------------------------------------------------------------------+ + + PURPOSE : The function copies the n-th plmn with a fieldstrength + higher then -85 dBm in the found plmn copy. + +*/ + +static void att_copy_found_plmn (T_FOUND_LIST * list, + USHORT n_in_source_85_dBm, + USHORT i_in_copy) +{ + GET_INSTANCE_DATA; + USHORT x_in_source_85_dBm = 0; + USHORT i_in_source = 0; + T_FOUND_ELEMENT *in_source; + + in_source = &rr_data->sc_data.found[0]; + for (i_in_source=0; i_in_source< rr_data->sc_data.found_entries; + i_in_source++, in_source++) + { + if ((in_source->plmn.v_plmn EQ V_PLMN_PRES) AND (in_source->rxlev > 25)) + { + /* + * -85 dBm = -110 + 25 ! + * + * increment the number of found plmns. + */ + if (x_in_source_85_dBm EQ n_in_source_85_dBm) + { + /* + * n-th PLMN with fieldstrength greater -85 dBm found + */ + list->element[i_in_copy] = *in_source; + i_in_copy ++; + in_source->plmn.v_plmn = V_PLMN_NOT_PRES; + return; + } + else + x_in_source_85_dBm++; + } + } +} + +/* ++-------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_plmns_lower_or_equal_85_dBm | ++-------------------------------------------------------------------------+ + + PURPOSE : The function copies the remaining networks with a fieldstrength + lower or equal -85 dBm in the found plmn copy. + +*/ + +static void att_copy_plmns_lower_or_equal_85_dBm (T_FOUND_LIST * list, + USHORT i_in_copy) +{ + GET_INSTANCE_DATA; + USHORT i_in_source; + T_FOUND_ELEMENT * in_source = &rr_data->sc_data.found[0]; + + for (i_in_source=0; i_in_source< rr_data->sc_data.found_entries; + i_in_source++, in_source++) + { + if (in_source->plmn.v_plmn EQ V_PLMN_PRES) + { + /* + * PLMN with fieldstrength less or equal -85 dBm found + */ + list->element[i_in_copy] = *in_source; + i_in_copy ++; + } + } +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_code_net_lost | ++--------------------------------------------------------------------+ + + PURPOSE : + +*/ + +GLOBAL void att_code_net_lost (void) +{ + GET_INSTANCE_DATA; + PALLOC (abort_ind, RR_ABORT_IND); + + TRACE_FUNCTION ("att_code_net_lost()"); + + srv_clear_stored_prim (RR_ESTABLISH_REQ); + + abort_ind->op.v_op = 1; + abort_ind->op.ts = (rr_data->ms_data.operation_mode >> SHIFT_FOR_SIM_TYPE) & 1; + abort_ind->op.m = (rr_data->ms_data.operation_mode >> SHIFT_FOR_SEARCH_OFFSET) & 1; + abort_ind->op.sim_ins = (rr_data->ms_data.operation_mode >> SHIFT_FOR_SIM_INSERTED) & 1; + abort_ind->op.func = rr_data->ms_data.req_mm_service; + abort_ind->op.service = NO_SERVICE; + + abort_ind->cause = RRCS_ABORT_CEL_SEL_FAIL; + + abort_ind->plmn_avail = 0; + memset (abort_ind->plmn, 0, sizeof(abort_ind->plmn)); + memset (abort_ind->rxlevel, 0, sizeof (abort_ind->rxlevel)); + + TRACE_OP_TYPE (&abort_ind->op, "RR_ABORT_IND"); + PSENDX (MM, abort_ind); + + rr_data->old_lai.lac = 0xFFFF; +#ifdef GPRS + rr_data->old_rac = NOT_PRESENT_8BIT; +#endif +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_code_rr_act_cnf | ++--------------------------------------------------------------------+ + + PURPOSE : The function indicates a successful end of cell selection. + The cell selection was initiated by MM. + +*/ + +GLOBAL void att_code_rr_act_cnf (void) +{ + GET_INSTANCE_DATA; + T_NC_DATA * rrd = &rr_data->nc_data[SC_INDEX]; + + PALLOC (rr_activate_cnf, RR_ACTIVATE_CNF); + + TRACE_FUNCTION ("att_code_rr_act_cnf()"); + + TRACE_EVENT ("cell selection"); + + + rr_data->net_lost = FALSE; + + TIMERSTOP(TABORT); + + /* + * indicate the requested MM service and the reached RR service + * to MM. + */ + rr_activate_cnf->op.v_op = 1; + rr_activate_cnf->op.ts = (rr_data->ms_data.operation_mode >> SHIFT_FOR_SIM_TYPE) & 1; + rr_activate_cnf->op.m = (rr_data->ms_data.operation_mode >> SHIFT_FOR_SEARCH_OFFSET) & 1; + rr_activate_cnf->op.sim_ins = (rr_data->ms_data.operation_mode >> SHIFT_FOR_SIM_INSERTED) & 1; + rr_activate_cnf->op.func = rr_data->ms_data.req_mm_service; + rr_activate_cnf->op.service = rr_data->ms_data.rr_service; + + TRACE_EVENT_P9 ("RR_ACTIVATE_CNF[%u]: rMM=%s RRs=%s MCC/MNC=%x%x%x/%x%x%x", + rrd->arfcn, + _rr_str_FUNC[rr_data->ms_data.req_mm_service], + _rr_str_SERVICE[rr_data->ms_data.rr_service], + rrd->lai.mcc[0], + rrd->lai.mcc[1], + rrd->lai.mcc[2], + rrd->lai.mnc[0], + rrd->lai.mnc[1], + rrd->lai.mnc[2]); + + if(GET_STATE(STATE_ATT) EQ ATT_CS_INIT ) + { /*Boot Time: Indicate only the start of power scan to MM*/ + memset( &rr_activate_cnf->mm_info, 0, sizeof(rr_activate_cnf->mm_info)); + memset( &rr_activate_cnf->plmn, 0, sizeof(rr_activate_cnf->plmn)); + rr_activate_cnf->lac = NOT_PRESENT_16BIT; + rr_activate_cnf->cid = NOT_PRESENT_16BIT; + rr_activate_cnf->gprs_indication = NOT_PRESENT_8BIT; + rr_activate_cnf->power = NOT_PRESENT_8BIT; + } + else + { + /* + * stop possibly parallel PLMN search + */ + att_notify_stop_plmn_search (FALSE); + + /* + * resume normal RR operation and update the previous + * requested MM and RR services + */ + att_clear_parallel_search (); + rr_data->ms_data.req_mm_service = att_get_func (); + rr_data->cs_data.scan_mode = CS_NO_SCAN; + + + if (rr_data->ms_data.req_mm_service NEQ rr_activate_cnf->op.func) + { + TRACE_EVENT_P2 ("rMM=%s RRs=%s resume normal RR operation", + _rr_str_FUNC[rr_data->ms_data.req_mm_service], + _rr_str_SERVICE[rr_data->ms_data.rr_service]); + } + TRACE_OP_TYPE (&rr_activate_cnf->op, "RR_ACTIVATE_CNF"); + + /* + * indicate the relevant BCCH parameter to MM + */ + att_code_prr_mm_info (&rr_activate_cnf->mm_info); + + /* + * indicate the PLMN, Location Area and Cell Identity to NN + */ + rr_activate_cnf->plmn.v_plmn = V_PLMN_PRES; + memcpy (rr_activate_cnf->plmn.mcc, rrd->lai.mcc, SIZE_MCC); + memcpy (rr_activate_cnf->plmn.mnc, rrd->lai.mnc, SIZE_MNC); + +#if defined(_SIMULATION_) +/* Implements Measure#32: Row 40 */ + att_print_mcc_mnc(rrd->arfcn, rrd->lai.mcc, rrd->lai.mnc, S2I_STRING("RR_ACTIVATE_CNF")); +#endif + + rr_activate_cnf->lac = rrd->lai.lac; + rr_activate_cnf->cid = rrd->cell_id; + + EM_PLMN_SRCH_PASSED; + + /* + * store the current location area and cell id to avoid + * double signalling to MM + */ + att_copy_old_lai_rac(SC_INDEX); +#if 0 + memcpy (&rr_data->old_lai, &rr_data->nc_data[SC_INDEX].lai, + sizeof(T_loc_area_ident)); + rr_data->old_cell_id = rr_data->nc_data[SC_INDEX].cell_id; +#endif + +#ifdef GPRS + /* + * indicates whether gprs operation is provided by the cell + */ + /* MS Patch: CQ 24473 */ + rr_activate_cnf->gprs_indication = (rr_data->nc_data[SC_INDEX].rac NEQ + NOT_PRESENT_8BIT); + +#else + rr_activate_cnf->gprs_indication = FALSE; +#endif + + /* + * set the power class needed for some MM messages depending + * on the frequency standard and the channel number + */ + rr_activate_cnf->power = att_get_power(); + + /* + * Display the Signal bar after camping on a cell with Full service + */ +#ifdef FF_PS_RSSI + RX_SetValue (rr_data->nc_data[SC_INDEX].rxlev, + RX_QUAL_UNAVAILABLE, + rr_data->nc_data[SC_INDEX].select_para.rxlev_access_min); +#else + RX_SetValue (rr_data->nc_data[SC_INDEX].rxlev); +#endif + att_set_rr_service_info(); + } + + PSENDX (MM, rr_activate_cnf); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_code_rr_act_ind | ++--------------------------------------------------------------------+ + + PURPOSE : The function indicates a successful end of RR originated + cell selection or a successful end of cell reselection. + +*/ + +GLOBAL void att_code_rr_act_ind (void) +{ + GET_INSTANCE_DATA; + T_NC_DATA * rrd = &rr_data->nc_data[SC_INDEX]; + + TRACE_FUNCTION ("att_code_rr_act_ind()"); + + TRACE_EVENT ("cell reselection"); + + rr_data->net_lost = FALSE; + + TIMERSTOP (TABORT); + + /* It is expected that this works, but this means that */ + /* the la-field in T_mm_info is superflous. This is also */ + /* true with some other variables in T_mm_info. */ + + /* + * Special case if we have reselected on a cell belonging to a forbidden + * location area in FS : it should not be possible on a LAC barred with a + * LU_REJ(#13) ie roaming not allowed but can happen with a LAC barred + * for regional provision of service ie LU_REJ(#12). + * Then a RR_ABORT_IND is sent to MM to switch the entity into limited + * service even if RR is happy with full service. An empty list of + * available PLMN is reported so that no PLMN selection is triggered + * by MM if MS is in automatic mode. + */ + if (rr_data->ms_data.rr_service EQ FULL_SERVICE) + { + if (!(dat_forb_lai_check (SC_INDEX) AND + dat_roam_forb_lai_check (SC_INDEX))) + { + /* + * store the current location area and cell id to notify MM + * when we are back in service + */ + att_copy_old_lai_rac(SC_INDEX); +#if 0 + memcpy (&rr_data->old_lai, &rr_data->nc_data[SC_INDEX].lai, + sizeof(T_loc_area_ident)); + rr_data->old_cell_id = rr_data->nc_data[SC_INDEX].cell_id; +#endif + + /* + * Indicate limited service, no PLMN available to MM + */ + rr_data->sc_data.found_entries = 0; + rr_data->ms_data.rr_service = LIMITED_SERVICE; + att_code_rr_abort_ind (RRCS_ABORT_CEL_SEL_FAIL); + rr_data->ms_data.rr_service = FULL_SERVICE; + + return; + } + } + + /* Set the black list search flag, whenever the location area or + * routing area changes, so that black list search is started + * after location/routing area update + */ + if(rr_data->dyn_config.bl_cs_en) + { + if((!dat_plmn_equal_req (rrd->lai.mcc, rrd->lai.mnc, + rr_data->old_lai.mcc, rr_data->old_lai.mnc)) + OR + (rrd->lai.lac NEQ rr_data->old_lai.lac )) + { + /* Location area has changed. This flag shall be used to start black + * list search after location area update + */ + rr_data->cs_data.black_list_search_pending = TRUE; + } +#ifdef GPRS + if(att_gprs_is_avail() AND (GET_STATE(STATE_GPRS) EQ GPRS_PIM_BCCH)) + { + if((rrd->rac NEQ NOT_PRESENT_8BIT) AND (rrd->rac NEQ rr_data->old_rac)) + { + /* Routing area has changed. This flag shall be used to start black + * list search after routing area update in PIM_BCCH state + */ + rr_data->cs_data.black_list_search_pending = TRUE; + } + } +#endif + + if(rr_data->cs_data.black_list_search_pending) + TRACE_EVENT("black_list_search_pending : 1"); + } + + /* + * check the current location area identification and cell identity + * against the last signalled one to MM. If it is not the same + * a signalling with RR_ACTIVATE_IND is needed + */ + if (!dat_plmn_equal_req (rrd->lai.mcc, rrd->lai.mnc, + rr_data->old_lai.mcc, rr_data->old_lai.mnc) + OR + rrd->lai.lac NEQ rr_data->old_lai.lac + OR + rrd->cell_id NEQ rr_data->old_cell_id) + { + PALLOC (rr_activate_ind, RR_ACTIVATE_IND); + + /* + * A cell change has occurred. So a running Immediate assignment reject + * timer is stopped. + */ + /* If the MS reselects back onto the same SC (ARFCN) and T3122 is still + running, it should be left running. If a new cell is selected, this timer + should is stopped. MM is not informed, because it have already received a + RR_ABORT_IND and left its state.*/ + + TIMERSTOP (T3122); + + + + /* + * indicate the requested MM service and the reached RR service + * to MM. + */ + rr_activate_ind->op.v_op = 1; + rr_activate_ind->op.ts = (rr_data->ms_data.operation_mode >> SHIFT_FOR_SIM_TYPE) & 1; + rr_activate_ind->op.m = (rr_data->ms_data.operation_mode >> SHIFT_FOR_SEARCH_OFFSET) & 1; + rr_activate_ind->op.sim_ins = (rr_data->ms_data.operation_mode >> SHIFT_FOR_SIM_INSERTED) & 1; + if (rr_data->ms_data.req_mm_service EQ FUNC_NET_SRCH_BY_MMI) + rr_activate_ind->op.func = FUNC_PLMN_SRCH; + else + rr_activate_ind->op.func = rr_data->ms_data.req_mm_service; + rr_activate_ind->op.service = rr_data->ms_data.rr_service; + + TRACE_OP_TYPE (&rr_activate_ind->op, "RR_ACTIVATE_IND"); + + /* + * stop possibly parallel PLMN search + */ + att_notify_stop_plmn_search (FALSE); + + /* + * resume normal RR operation and update the previous + * requested MM and RR services + */ + att_clear_parallel_search(); + rr_data->ms_data.req_mm_service = att_get_func (); + rr_data->cs_data.scan_mode = CS_NO_SCAN; + + + /* + * indicate the relevant BCCH parameter to MM + */ + att_code_prr_mm_info (&rr_activate_ind->mm_info); + + /* + * indicate the PLMN, Location Area and Cell Identity to NN + */ + rr_activate_ind->plmn.v_plmn = V_PLMN_PRES; + memcpy (rr_activate_ind->plmn.mcc, rrd->lai.mcc, SIZE_MCC); + memcpy (rr_activate_ind->plmn.mnc, rrd->lai.mnc, SIZE_MNC); +#if defined(_SIMULATION_) +/* Implements Measure#32: Row 40 */ + att_print_mcc_mnc(rrd->arfcn, rrd->lai.mcc, rrd->lai.mnc, S2I_STRING("RR_ACTIVATE_IND")); +#endif + rr_activate_ind->lac = rrd->lai.lac; + rr_activate_ind->cid = rrd->cell_id; + + /* + * store the current location area and cell id to avoid + * double signalling to MM + */ + att_copy_old_lai_rac(SC_INDEX); +#if 0 + memcpy (&rr_data->old_lai, &rr_data->nc_data[SC_INDEX].lai, + sizeof(T_loc_area_ident)); + rr_data->old_cell_id = rr_data->nc_data[SC_INDEX].cell_id; +#endif + +#ifdef GPRS + /* + * indicates whether gprs operation is provided by the cell + */ + /* MS Patch: CQ 24473 */ + rr_activate_ind->gprs_indication = (rr_data->nc_data[SC_INDEX].rac NEQ + NOT_PRESENT_8BIT); + +#else + rr_activate_ind->gprs_indication = FALSE; +#endif + + /* + * set the power class needed for some MM messages depending + * on the frequency standard and the channel number + */ + rr_activate_ind->power = att_get_power(); + /* + * Limited to full service reselection + * TMSI/IMSI data to be refreshed in TIL otherwise no paging possible + */ + att_mph_identity_req(); + + EM_CELL_RESEL_FINISHED; + + EM_FMM_RESEL_END_IND; + + PSENDX (MM, rr_activate_ind); + } + else + { + /* + * indicate changed imsi attach status or + * changed periodic location updating time to MM + * if it has changed, else it is only signalled to MM. + */ + PALLOC (sync, RR_SYNC_IND); + + att_code_prr_mm_info (&sync->mm_info); + sync->ciph = NOT_PRESENT_8BIT; + sync->chm.ch_mode = NOT_PRESENT_8BIT; + + switch (rr_data->sc_data.selection_type) + { + case CELL_SELECTION: + case CELL_RESELECTION: + case CELL_RESELECTION_NC: + case CELL_RESELECTION_RACH: + case CELL_RESELECTION_CR: + /* + * cell reselection in idle mode + */ + sync->synccs = SYNCCS_IDLE_SELECTION; + break; + default: + /* + * cell reselection after dedicated mode + */ + sync->synccs = SYNCCS_BACK_FROM_DEDICATED; + break; + } + + sync->bcch_info.v_bcch = FALSE; + PSENDX (MM, sync); + EM_FMM_RESEL_END_IND; + } + att_set_rr_service_info(); +} + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_get_power | ++--------------------------------------------------------------------+ + + PURPOSE : get the power class needed for some MM messages depending + on the frequency standard and the channel number of the + serving cell. + +*/ + +GLOBAL UBYTE att_get_power (void) +{ + GET_INSTANCE_DATA; + UBYTE power = 0; + UBYTE power_idx = (UBYTE)-1; + + TRACE_FUNCTION ("att_get_power()"); + + /* new method, use directly the rf capabilities */ + /* coding of power class according to classmark 3 [1..5] */ + switch (std) + { + case STD_900: + case STD_EGSM: + power_idx = IDX_PWRCLASS_900; + break; + case STD_1800: + power_idx = IDX_PWRCLASS_1800; + break; + + case STD_DUAL: + case STD_DUAL_EGSM: + if (INRANGE(LOW_CHANNEL_1800,rr_data->nc_data[SC_INDEX].arfcn,HIGH_CHANNEL_1800)) + power_idx = IDX_PWRCLASS_1800; + else + power_idx = IDX_PWRCLASS_900; + break; + + case STD_1900: + power_idx = IDX_PWRCLASS_1900; + break; + + case STD_850: + power_idx = IDX_PWRCLASS_850; + break; + + case STD_DUAL_US: + if (rr_data->nc_data[SC_INDEX].arfcn < LOW_CHANNEL_1900) + power_idx = IDX_PWRCLASS_850; + else + power_idx = IDX_PWRCLASS_1900; + break; + +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + case STD_850_1800: + if (INRANGE(LOW_CHANNEL_1800,rr_data->nc_data[SC_INDEX].arfcn,HIGH_CHANNEL_1800)) + power_idx = IDX_PWRCLASS_1800; + else + power_idx = IDX_PWRCLASS_850; + break; + + case STD_900_1900: + if (INRANGE(LOW_CHANNEL_1900,rr_data->nc_data[SC_INDEX].arfcn,HIGH_CHANNEL_1900)) + power_idx = IDX_PWRCLASS_1900; + else + power_idx = IDX_PWRCLASS_900; + break; + + case STD_850_900_1800: + if (INRANGE(LOW_CHANNEL_1800,rr_data->nc_data[SC_INDEX].arfcn,HIGH_CHANNEL_1800)) + power_idx = IDX_PWRCLASS_1800; + else if (INRANGE(LOW_CHANNEL_850,rr_data->nc_data[SC_INDEX].arfcn,HIGH_CHANNEL_850)) + power_idx = IDX_PWRCLASS_850; + else + power_idx = IDX_PWRCLASS_900; + break; + + case STD_850_900_1900: + if (INRANGE(LOW_CHANNEL_1900,rr_data->nc_data[SC_INDEX].arfcn,HIGH_CHANNEL_1900)) + power_idx = IDX_PWRCLASS_1900; + else if (INRANGE(LOW_CHANNEL_850,rr_data->nc_data[SC_INDEX].arfcn,HIGH_CHANNEL_850)) + power_idx = IDX_PWRCLASS_850; + else + power_idx = IDX_PWRCLASS_900; + break; +#endif + } + + if (power_idx NEQ (UBYTE)-1) + power = rr_data->ms_data.rf_cap.rf_power.pow_class4[power_idx].pow_class; + else + power = 0; + + /* + TRACE_EVENT_P3 ("power=%u(new), idx=%d, std=%u", power, power_idx, std); + */ + + if (power) + power--; /* coding of power class according to classmark 1 and 2 [0..4] */ + + return power; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_continue_cell_reselect | ++--------------------------------------------------------------------+ + + PURPOSE : A cell reselection candidate has failed. Inside this function + the next one is searched. + +*/ + +GLOBAL void att_continue_cell_reselect (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_continue_cell_reselect()"); + + switch (rr_data->sc_data.selection_type) + { + case BACK_FROM_DEDICATED: + case BACK_FROM_DEDICATED_RLF: + /* + * After a dedicated connection + */ + rr_data->reselect_index = + att_get_next_highest_c2_idx (rr_data->reselect_index); + att_select_cell_dedicated (); + break; + + default: + /* + * In idle mode + */ + #ifdef GPRS + if( rr_data->gprs_data.use_c31) + { + rr_data->reselect_index = att_get_next_best_c32_index(TRUE); + if (! att_check_cell_c31()) + att_try_old_cell(); + } + else + { + #endif + rr_data->reselect_index = + att_get_next_highest_c2_idx (rr_data->reselect_index); + /* + * If no other cell is available, try the old one + */ + if (! att_check_cell ()) + { + TRACE_EVENT ("no further cell found -> try old one"); + att_try_old_cell (); + } + else + { + TRACE_EVENT_P2 ("try next cell [%u]i%u", + rr_data->nc_data[rr_data->reselect_index].arfcn, + rr_data->reselect_index); + } + + + + #ifdef GPRS + } + #endif + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_rach_parameter | ++--------------------------------------------------------------------+ + + PURPOSE : After reception of system information message 1 to 4 in + idle mode or cell selection / reselection the RACH parameters + are stored. The flag indicate_changes defines whether + changes in the RACH parameter shall be forwarded to MM + (in idle mode for serving cell) or not (any other cases). + +*/ + +static void att_copy_rach_parameter (UBYTE index, + T_rach_ctrl *rach, + UBYTE indicate_changes) +{ + GET_INSTANCE_DATA; + T_NC_DATA *rrd = &rr_data->nc_data[index]; + + TRACE_FUNCTION ("att_copy_rach_parameter()"); + + if (index EQ SC_INDEX AND + indicate_changes) + { + /* + * compare only for serving cell + */ + if (rrd->rach.re NEQ rach->re) + { + /* + * change of reestablishment flag indicate to MM + */ + PALLOC (sync, RR_SYNC_IND); + rrd->rach.re = rach->re; + + att_code_prr_mm_info (&sync->mm_info); + sync->ciph = NOT_PRESENT_8BIT; + sync->chm.ch_mode = NOT_PRESENT_8BIT; + sync->synccs = SYNCCS_SYS_INFO_CHANGE; + memset(&sync->bcch_info, 0, sizeof(T_bcch_info)); + sync->bcch_info.v_bcch = FALSE; + PSENDX (MM, sync); + } + + if (rrd->rach.ac NEQ rach->ac) + { + /* + * change of access classes indicate to MM + */ + PALLOC (sync, RR_SYNC_IND); + + sync->ciph = NOT_PRESENT_8BIT; + sync->chm.ch_mode = NOT_PRESENT_8BIT; + sync->synccs = SYNCCS_ACC_CLS_CHA; + memset(&sync->mm_info, 0, sizeof(T_mm_info)); + sync->mm_info.valid = FALSE; + memset(&sync->bcch_info, 0, sizeof(T_bcch_info)); + sync->bcch_info.v_bcch = FALSE; + PSENDX (MM, sync); + } + } + + rrd->rach = *rach; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_sys_info_1_par | ++--------------------------------------------------------------------+ + + PURPOSE : copy the relevant system information type 1 parameter after + reception in idle mode or during cell selection or cell + reselection. + +*/ + +GLOBAL void att_copy_sys_info_1_par (UBYTE index, + T_D_SYS_INFO_1 *sys_info_1, + T_LIST *cell_chan_desc) +{ + GET_INSTANCE_DATA; + T_CELL_DATA * cd; + UBYTE indicate_changes = index EQ SC_INDEX; + + switch (index) + { + case SC_INDEX: + case CR_INDEX: + /* + * set pointer to data + */ + if (index EQ SC_INDEX) + cd = &rr_data->sc_data.cd; + else + cd = &rr_data->cr_data.cd; + + /* + * If a cell channel description is not stored for + * this cell or the new cell channel description is + * different, store the new one. + */ + if (cd->v_cell_chan_desc EQ NO_CONTENT OR + srv_compare_list (&cd->cell_chan_desc, + cell_chan_desc) EQ FALSE) + { + srv_copy_list (&cd->cell_chan_desc, + cell_chan_desc, + sizeof (T_LIST)); + + cd->v_cell_chan_desc = WITH_CHANGED_CONTENT; + if((indicate_changes) AND (GET_STATE(STATE_ATT) EQ ATT_IDLE) + AND ( rr_data->sc_data.cd.cbch_chan_desc.hop EQ H_FREQ) ) + { +#ifdef REL99 + att_config_cbch(); +#else + att_build_cbch(); +#endif + } + } + /* Get the band indicator value from SI1 message */ +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + cd->band_indicator = sys_info_1->si1_rest_oct.band_indicator; + if (index EQ SC_INDEX) + { + att_update_std_band_indicator (cd->band_indicator); + } +#endif + break; + } + + att_copy_rach_parameter (index, &sys_info_1->rach_ctrl, indicate_changes); + + /* + * Indicate that the system information type 1 message has been read. + */ + att_set_sys_info_read (SYS_INFO_1_READ, index); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_sys_info_2bis_par | ++--------------------------------------------------------------------+ + + PURPOSE : copy the relevant system information type 2bis parameter after + reception in idle mode (in this case changes are to detect) + or during cell selection or cell reselection. + +*/ + +GLOBAL void att_copy_sys_info_2bis_par (UBYTE index, + T_D_SYS_INFO_2BIS *sys_info_2bis, + T_LIST *new_2bis_list, + UBYTE ncell_ext, + UBYTE indicate_changes) +{ +/* Implements RR Clone findings #3 */ + + TRACE_FUNCTION ("att_copy_sys_info_2bis_par()"); + + +/* Implements RR Clone findings #3 */ + att_copy_sys_info_2bis_2ter_par(index, SI_TYPE_2BIS, new_2bis_list, + &sys_info_2bis->neigh_cell_desc, + indicate_changes); + + + + att_copy_rach_parameter (index, &sys_info_2bis->rach_ctrl, indicate_changes); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_sys_info_2_par | ++--------------------------------------------------------------------+ + + PURPOSE : copy the relevant system information type 2 parameter after + reception in idle mode (in this case changes are to detect) + or during cell selection or cell reselection. + +*/ + +GLOBAL void att_copy_sys_info_2_par (UBYTE index, + T_D_SYS_INFO_2 *sys_info_2, + T_LIST *new_2_list, + UBYTE ncell_ext, + UBYTE indicate_changes) +{ + GET_INSTANCE_DATA; + T_LIST new_list; + T_CELL_DATA *cd; + BOOL modified = FALSE; + + TRACE_FUNCTION ("att_copy_sys_info_2_par()"); + + switch (index) + { + case SC_INDEX: + case CR_INDEX: + if (index EQ SC_INDEX) + { + cd = &rr_data->sc_data.cd; + if ((cd->sys_info_read & SYS_INFO_2_READ) EQ SYS_INFO_2_READ) + { + srv_copy_list (&cd->ncell_list, new_2_list, sizeof (T_LIST)); + att_clean_buf ((USHORT)(IND_SI_2BIS | IND_SI_2TER)); + cd->sys_info_read &= ~(SYS_INFO_2BIS_READ | SYS_INFO_2TER_READ); + att_check_2ter_read (index); + } + else + srv_merge_list (&cd->ncell_list, new_2_list); + + if( cd->ncell_ext NEQ ncell_ext ) + { + PALLOC (mph_sync_req, MPH_SYNC_REQ); + mph_sync_req->cs = CS_SYS_INFO_2BIS_SUPPORT_CHANGED; + PSENDX (PL, mph_sync_req); + cd->ncell_ext = ncell_ext; + } + modified = TRUE; +#ifdef GPRS + rr_data->gprs_data.ba_bcch_modified= FALSE; +#endif + } + else + { + cd = &rr_data->cr_data.cd; + /* + * merge 2 list with the old neighbour cell list + */ + srv_copy_list (&new_list, &cd->ncell_list, + sizeof (T_LIST)); + srv_merge_list (&new_list, new_2_list); + + if (srv_compare_list (&cd->ncell_list, &new_list) EQ FALSE) + { + /* + * both lists are different + */ + srv_copy_list (&cd->ncell_list, &new_list, sizeof (T_LIST)); + modified = TRUE; + } + cd->ncell_ext = ncell_ext; + } + + /* CSI-LLD section:4.1.1.11 + * This function Updates the black list with the BA list received in si2 + */ + cs_remove_BA_MA_from_black_list(rr_data->cs_data.region,&cd->ncell_list); + + dat_store_neigh_cell_desc (SYS_INFO_2_MSG, index, + &sys_info_2->neigh_cell_desc,&cd->ncell_list); + /* + * Indicate that the system information type 2 message has been read + * and if applicable the system information type 2bis is not needed to read. + */ + att_set_sys_info_read (SYS_INFO_2_READ, index); + if (ncell_ext EQ 0) + att_set_sys_info_read (SYS_INFO_2BIS_READ, index); + /* + * forward new neighbour cell list to layer 1 if + * changes shall be indicated + */ + if (modified AND indicate_changes) + { + att_code_mph_ncell_req (index); + } + + /* + * copy ncc permitted field + */ + cd->ncc_permitted = sys_info_2->ncc_permit; + break; + } + att_copy_rach_parameter (index, &sys_info_2->rach_ctrl, indicate_changes); + +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_sys_info_2ter_par | ++--------------------------------------------------------------------+ + + PURPOSE : copy the relevant system information type 2ter parameter after + reception in idle mode or during cell selection or cell + reselection. + +*/ +GLOBAL void att_copy_sys_info_2ter_par (UBYTE index, + T_D_SYS_INFO_2TER *sys_info_2ter, + T_LIST *new_2ter_list, + UBYTE indicate_changes) +{ + + /* Implements RR Clone findings #3 */ + + TRACE_FUNCTION ("att_copy_sys_info_2ter_par()"); + +/* Implements RR Clone findings #8 */ + att_copy_sys_info_2bis_2ter_par(index, SI_TYPE_2TER, new_2ter_list, + &sys_info_2ter->neigh_cell_desc, + indicate_changes); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_2ter_read | ++--------------------------------------------------------------------+ + + PURPOSE : checks whether to wait for SI_2ter. +*/ + +static void att_check_2ter_read (UBYTE index) +{ + GET_INSTANCE_DATA; + if (rr_data->nc_data[index].c2_par.two_ter EQ FALSE) + att_set_sys_info_read (SYS_INFO_2TER_READ, index); + + /* + * only in dualband standards 2ter is taken in account + * in single bands it is ignored. + */ + switch (std) + { + case STD_900: + case STD_EGSM: + case STD_1800: + case STD_850: + case STD_1900: + att_set_sys_info_read (SYS_INFO_2TER_READ, index); + break; + default: + break; + } +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_sys_info_3_par | ++--------------------------------------------------------------------+ + + PURPOSE : copy the relevant system information type 3 parameter after + reception in idle mode or during cell selection or cell + reselection. +*/ + +/* + * conversion from air interface coding for DTX usage to internal + * notation + */ +static const UBYTE dtx_bcch [3] = { DTX_USED, DTX_USED, DTX_NOT_USED }; + + +GLOBAL void att_copy_sys_info_3_par (UBYTE index, + T_D_SYS_INFO_3 *sys_info_3, + UBYTE indicate_changes) +{ + GET_INSTANCE_DATA; + T_NC_DATA * rrd = &rr_data->nc_data[index]; + UBYTE lai_changed = FALSE; + UBYTE control_changed_mm = FALSE; + UBYTE control_changed_l1 = FALSE; + TRACE_FUNCTION ("att_copy_sys_info_3_par()"); + +#if defined(_SIMULATION_) + TRACE_EVENT_WIN_P7 ( "MCC o/i[%d]= %x%x%x/%x%x%x", + ((int)rrd->arfcn), + rrd->lai.mcc[0], + rrd->lai.mcc[1], + rrd->lai.mcc[2], + sys_info_3->loc_area_ident.mcc[0], + sys_info_3->loc_area_ident.mcc[1], + sys_info_3->loc_area_ident.mcc[2]); + TRACE_EVENT_WIN_P7 ( "MNC o/i[%d]= %x%x%x/%x%x%x", + ((int)rrd->arfcn), + rrd->lai.mnc[0], + rrd->lai.mnc[1], + rrd->lai.mnc[2], + sys_info_3->loc_area_ident.mnc[0], + sys_info_3->loc_area_ident.mnc[1], + sys_info_3->loc_area_ident.mnc[2]); +#endif + + if (index EQ SC_INDEX) + { + /* + * compare only for serving cell + * + * check location area information and cell id + */ + if (rrd->cell_id NEQ sys_info_3->cell_ident) + lai_changed = TRUE; + rrd->cell_id = sys_info_3->cell_ident; + + if (!dat_plmn_equal_req (sys_info_3->loc_area_ident.mcc, + sys_info_3->loc_area_ident.mnc, + rrd->lai.mcc, + rrd->lai.mnc)) + lai_changed = TRUE; + if (rrd->lai.lac NEQ sys_info_3->loc_area_ident.lac) + lai_changed = TRUE; +#if defined(_SIMULATION_) + TRACE_EVENT_WIN_P3 ( "LAI[%d] changed=%d indicate_changes=%d", + rr_data->nc_data[index].arfcn, lai_changed, indicate_changes); +#endif + + if (lai_changed AND indicate_changes) + { + /* + * If a change of location area code is detected, + * signal this as a cell reselection to MM to force + * a location updating. + */ + att_reset_old_lai_rac(); + memcpy (&rrd->lai, &sys_info_3->loc_area_ident, + sizeof (T_loc_area_ident)); + att_code_rr_act_ind (); +#ifdef GPRS + if (att_gprs_is_avail()) + { +/*XY: inform GRR, and don't wait for CR_RSP */ + att_rrgrr_cr_ind(CR_ABNORMAL); + /* + * we are in the process of acquiring SIs because GRR + * has requested it. We have to set the sys_info_read bitmap + * to complete. in order to send a GPRS_SI13_IND to GRR below. + * The missing SIs which RR requested will still arrive from ALR + * so it does not matter that we reset the bitmap now. + */ + att_set_sys_info_read(ALL_SYS_INFO_READ, SC_INDEX); + rr_data->gprs_data.start_proc = START_PROC_NOTHING; + att_signal_gprs_support(); + } +#endif + } + + /* + * check imsi attach status and + * periodic location update time + */ + if ((rrd->control_descr.att NEQ sys_info_3->ctrl_chan_desc.att + OR + rrd->control_descr.t3212 NEQ sys_info_3->ctrl_chan_desc.t3212) + AND + indicate_changes) + control_changed_mm = TRUE; + + /* + * check control channel description + */ + if (rrd->control_descr.bs_ag_blks_res NEQ + sys_info_3->ctrl_chan_desc.bs_ag_blks_res) + control_changed_l1 = TRUE; + if (rrd->control_descr.ccch_conf NEQ + sys_info_3->ctrl_chan_desc.ccch_conf) + control_changed_l1 = TRUE; + if (rrd->control_descr.bs_pa_mfrms NEQ + sys_info_3->ctrl_chan_desc.bs_pa_mfrms) + control_changed_l1 = TRUE; + + /* + * check cell selection parameters + */ + if (rrd->select_para.ms_txpwr_max_cch NEQ + sys_info_3->cell_select.ms_txpwr_max_cch) + { + control_changed_l1 = TRUE; + TRACE_EVENT_P2("txpwr_max_cch changed from %d -> %d in SI3", rrd->select_para.ms_txpwr_max_cch, + sys_info_3->cell_select.ms_txpwr_max_cch); + } + } + + /* + * store location information and control channel description + */ + rrd->cell_id = sys_info_3->cell_ident; +#ifdef REL99 + rrd->mscr_flag = sys_info_3->ctrl_chan_desc.mscr; +#endif + memcpy (&rrd->lai, &sys_info_3->loc_area_ident, + sizeof (T_loc_area_ident)); + memcpy (&rrd->control_descr, &sys_info_3->ctrl_chan_desc, + sizeof (T_ctrl_chan_desc)); + + if (control_changed_mm) + { + /* + * indicate changed imsi attach status or + * changed periodic location updating time to MM + */ + PALLOC (sync, RR_SYNC_IND); + + att_code_prr_mm_info (&sync->mm_info); + sync->ciph = NOT_PRESENT_8BIT; + sync->chm.ch_mode = NOT_PRESENT_8BIT; + sync->synccs = SYNCCS_SYS_INFO_CHANGE; + sync->bcch_info.v_bcch = FALSE; + PSENDX (MM, sync); + } + + /* + * store the system information type 3 message parameter. + */ + switch (index) + { + case SC_INDEX: + rr_data->sc_data.cd.cell_options.pow_ctrl = + sys_info_3->cell_opt_bcch.pow_ctrl; + rr_data->sc_data.cd.cell_options.rlt = + sys_info_3->cell_opt_bcch.rlt; + rr_data->sc_data.cd.dtx = + dtx_bcch [sys_info_3->cell_opt_bcch.dtx_b]; + rr_data->sc_data.cd.dtx_half = + rr_data->sc_data.cd.dtx_full = + rr_data->sc_data.cd.dtx; +#if defined (REL99) && defined (TI_PS_FF_EMR) + /*The SI-2quater information that we store is useful for monitoring appropriate + BCCH periodically: no need to change status in re-acquisition*/ + if ( sys_info_3->si3_rest_oct.v_si2quater_ind ) + { + if ( rr_data->sc_data.cd.si2quater_status EQ SI2QUATER_ABSENT) + rr_data->sc_data.cd.si2quater_status = SI2QUATER_CONFIGURE; + rr_data->sc_data.cd.si2quater_pos = sys_info_3->si3_rest_oct.si2quater_ind.si2quater_pos; + } +#endif + break; + + case CR_INDEX: + rr_data->cr_data.cd.cell_options.pow_ctrl = + sys_info_3->cell_opt_bcch.pow_ctrl; + rr_data->cr_data.cd.cell_options.rlt = + sys_info_3->cell_opt_bcch.rlt; + rr_data->cr_data.cd.dtx = + dtx_bcch [sys_info_3->cell_opt_bcch.dtx_b]; + rr_data->cr_data.cd.dtx_half = + rr_data->cr_data.cd.dtx_full = + rr_data->cr_data.cd.dtx; +#if defined (REL99) && defined (TI_PS_FF_EMR) + /*The SI-2quater information that we store is used only if this cell is selected + In case of serving cell, this information should be useful for monitoring appropriate + BCCH periodically*/ + rr_data->cr_data.cd.si2quater_status = SI2QUATER_ABSENT; + if ( sys_info_3->si3_rest_oct.v_si2quater_ind ) + { + rr_data->cr_data.cd.si2quater_status = SI2QUATER_CONFIGURE; + rr_data->cr_data.cd.si2quater_pos = sys_info_3->si3_rest_oct.si2quater_ind.si2quater_pos; + } +#endif + break; + } + + memcpy (&rrd->select_para, &sys_info_3->cell_select, + sizeof (T_cell_select)); + att_copy_rach_parameter (index, &sys_info_3->rach_ctrl, + indicate_changes); + + + att_copy_c2_parameter_si3 (index, &sys_info_3->si3_rest_oct); + + att_set_sys_info_read (SYS_INFO_3_READ, index); + att_check_2ter_read (index); + + if (control_changed_l1 AND indicate_changes) + { + /* + * forward changed control channel description + * to layer 1 + */ + att_build_idle_req (SC_INDEX, MODE_SYS_INFO_CHANGE); +#ifdef REL99 + att_config_cbch (); +#else + att_build_cbch(); +#endif + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_sys_info_4_par | ++--------------------------------------------------------------------+ + + PURPOSE : copy the relevant system information type 4 parameter after + reception in idle mode or during cell selection or cell + reselection. +*/ + +GLOBAL void att_copy_sys_info_4_par (UBYTE index, + T_D_SYS_INFO_4 *sys_info_4, + UBYTE indicate_changes) +{ + GET_INSTANCE_DATA; + T_NC_DATA * rrd = &rr_data->nc_data[index]; + UBYTE lai_changed = FALSE; + UBYTE control_changed_l1 = FALSE; + T_CELL_DATA * cd; + + TRACE_FUNCTION ("att_copy_sys_info_4_par()"); + + switch (index) + { + case SC_INDEX: + case CR_INDEX: + /* + * set pointer to data + */ + if (index EQ SC_INDEX) + cd = &rr_data->sc_data.cd; + else + cd = &rr_data->cr_data.cd; + + if (index EQ SC_INDEX) + { + /* + * compare only for serving cell + * + * check location information + */ + if (!dat_plmn_equal_req (sys_info_4->loc_area_ident.mcc, + sys_info_4->loc_area_ident.mnc, + rrd->lai.mcc, + rrd->lai.mnc)) + lai_changed = TRUE; + if (rrd->lai.lac NEQ sys_info_4->loc_area_ident.lac) + lai_changed = TRUE; + + if (lai_changed AND indicate_changes) + { + /* + * If a change of location area code is detected, + * signal this as a cell reselection to MM to force + * a location updating. + */ + att_reset_old_lai_rac(); + memcpy (&rrd->lai, &sys_info_4->loc_area_ident, + sizeof (T_loc_area_ident)); + att_code_rr_act_ind (); +#ifdef GPRS + if (att_gprs_is_avail()) + { +/*XY: inform GRR, and don't wait for CR_RSP */ + att_rrgrr_cr_ind(CR_ABNORMAL); + /* + * we are in the process of acquiring SIs because GRR + * has requested it. We have to set the sys_info_read bitmap + * to complete. in order to send a GPRS_SI13_IND to GRR below. + * The missing SIs which RR requested will still arrive from ALR + * so it does not matter that we reset the bitmap now. + */ + att_set_sys_info_read(ALL_SYS_INFO_READ, SC_INDEX); + rr_data->gprs_data.start_proc = START_PROC_NOTHING; + att_signal_gprs_support(); + } +#endif + } + + /* + * check cell selection parameters + */ + if (rrd->select_para.ms_txpwr_max_cch NEQ + sys_info_4->cell_select.ms_txpwr_max_cch) + { + control_changed_l1 = TRUE; + TRACE_EVENT_P2("txpwr_max_cch changed from %d -> %d in SI4", rrd->select_para.ms_txpwr_max_cch, + sys_info_4->cell_select.ms_txpwr_max_cch); + } + } + + if (sys_info_4->v_chan_desc) + { + /* + * the message contains a CBCH channel description. + */ + if(memcmp(&cd->cbch_chan_desc,&sys_info_4->chan_desc, sizeof (T_chan_desc)) NEQ 0) + { + memcpy (&cd->cbch_chan_desc, &sys_info_4->chan_desc, sizeof (T_chan_desc)); + cd->cbch_chan_desc_avail = WITH_CONTENT; + att_bits_to_byte (cd->cbch_mob_alloc, + sys_info_4->mob_alloc.c_mac, + sys_info_4->mob_alloc.mac); + if( (index EQ SC_INDEX) AND ( GET_STATE(STATE_ATT) EQ ATT_IDLE)) +#ifdef REL99 + att_config_cbch(); +#else + att_build_cbch(); +#endif + } + } + else + { + memset (&cd->cbch_chan_desc, 0, sizeof (T_chan_desc)); + if( cd->cbch_chan_desc_avail NEQ NO_CONTENT) + { + cd->cbch_chan_desc_avail = NO_CONTENT; + if( (index EQ SC_INDEX) AND ( GET_STATE(STATE_ATT) EQ ATT_IDLE)) +#ifdef REL99 + att_config_cbch(); +#else + att_build_cbch(); +#endif + } + } + + /* + * set system information bits + */ + att_set_sys_info_read (SYS_INFO_4_READ, index); + break; + default: + break; + } + + /* + * copy the parameters + */ + rrd->v_acs = sys_info_4->cell_select.acs; /* use of sys info 7&8 */ + rrd->lai = sys_info_4->loc_area_ident; + rrd->select_para = sys_info_4->cell_select; + att_copy_rach_parameter (index, &sys_info_4->rach_ctrl, indicate_changes); + + if (control_changed_l1 AND indicate_changes) + { + /* + * forward changed control channel description + * to layer 1 + */ + att_build_idle_req (SC_INDEX, MODE_SYS_INFO_CHANGE); + att_build_cbch (); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_sys_info_7_8_par | ++--------------------------------------------------------------------+ + + PURPOSE : copy the relevant system information type 7 and 8 + parameter after reception in idle mode for neighbourcells. + The messages are only expected if system information + message 4 does not contain the C2 parameter due to a big + CBCH channel description and system information + message 3 is hidden by the own paging block. + +*/ + +GLOBAL void att_copy_sys_info_7_8_par (UBYTE index, + T_D_SYS_INFO_8 *sys_info_8) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_copy_sys_info_7_8_par()"); + + /* + * system info 4 does not contain enough information + */ + if (rr_data->nc_data[index].v_acs) + att_copy_c2_parameter_si4 (index, (T_si4_rest_oct *)&sys_info_8->si8_rest_oct); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_c2_parameter | ++--------------------------------------------------------------------+ + + PURPOSE : Rest Octets of System Information Type 3/4/7/8 are decoded + to get the C2 parameter for cell reselection. +*/ + +static void att_copy_c2_parameter (T_C2_PARAMETER *c2_par, + T_si3_rest_oct *rest_oct ) +{ + TRACE_FUNCTION ("att_copy_c2_parameter()"); + + /* Optional selection parameters */ + if(rest_oct->v_opt_sel_par) + { + c2_par->param_ind = TRUE; + c2_par->cbq = rest_oct->opt_sel_par.cell_bar_qual; + c2_par->cell_reselect_offset = rest_oct->opt_sel_par.cell_resel_offs; + c2_par->temp_offset = rest_oct->opt_sel_par.temp_offs; + c2_par->penalty_time = rest_oct->opt_sel_par.penalty_time; + } + else + { + c2_par->param_ind = FALSE; + c2_par->cbq = 0; + c2_par->cell_reselect_offset = 0; + c2_par->temp_offset = 0; + c2_par->penalty_time = 0; + } + + /* Optional Power Offset */ + if(rest_oct->v_pow_offs) + { + c2_par->power_off_ind = TRUE; + c2_par->power_off = rest_oct->pow_offs; + } + else + { + c2_par->power_off_ind = FALSE; + c2_par->power_off = 0; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_c2_parameter_si3 | ++--------------------------------------------------------------------+ + + PURPOSE : rest octets of system information 3 are decoded + to get the C2 parameter for cell reselection. +*/ + +static void att_copy_c2_parameter_si3 (UBYTE index, + T_si3_rest_oct *rest_oct) +{ + GET_INSTANCE_DATA; + T_NC_DATA * nc = &rr_data->nc_data[index]; + T_C2_PARAMETER * c2_par = &nc->c2_par; + + TRACE_FUNCTION ("att_copy_c2_parameter_si3()"); + + att_copy_c2_parameter (c2_par, rest_oct); + + if(index EQ SC_INDEX AND + c2_par->two_ter NEQ rest_oct->v_si2ter_ind) + { + PALLOC (mph_sync_req, MPH_SYNC_REQ); + mph_sync_req->cs = CS_SYS_INFO_2TER_SUPPORT_CHANGED; + PSENDX (PL, mph_sync_req); + } + /* System Information 2ter Indicator */ + if (rest_oct->v_si2ter_ind) + { + c2_par->two_ter = TRUE; + } + else + { + c2_par->two_ter = FALSE; + } + + /* Early Classmark Sending Control */ + if (rest_oct->v_es_ind_tag) + { + c2_par->ecsc = TRUE; + } + else + { + c2_par->ecsc = FALSE; + } + +#ifdef GPRS + if (rest_oct->v_gprs_indic) + nc->rac = rest_oct->gprs_indic.ra_color; + else + nc->rac = NOT_PRESENT_8BIT; +#endif +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_c2_parameter_si4 | ++--------------------------------------------------------------------+ + + PURPOSE : Rrest Octets of System Information Type 4 are decoded + to get the C2 parameter for cell reselection. + +*/ + +GLOBAL void att_copy_c2_parameter_si4 (UBYTE index, + T_si4_rest_oct *rest_oct) +{ + GET_INSTANCE_DATA; + T_NC_DATA * nc = &rr_data->nc_data[index]; + T_C2_PARAMETER * c2_par = &nc->c2_par; + + TRACE_FUNCTION ("att_copy_c2_parameter_si4()"); + + att_copy_c2_parameter (c2_par, (T_si3_rest_oct *)rest_oct); + +#ifdef GPRS + if (rest_oct->v_gprs_indic) + nc->rac = rest_oct->gprs_indic.ra_color; + else + nc->rac = NOT_PRESENT_8BIT; +#endif +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_get_highest_c2_index | ++--------------------------------------------------------------------+ + + PURPOSE : If a cell reselection shall be performed, a ranking + of the available candidates is done. Depending on the + calculated C2 values a C2-Index is used (because more + than one cell can have the same C2-value or the value + changes during cell reselection). This function looks + for the cell with the highest c2 index. + +*/ + +static UBYTE att_get_highest_c2_index (void) +{ + GET_INSTANCE_DATA; + UBYTE max_result = SC_INDEX; + UBYTE next_result; + UBYTE result; + UBYTE i; + + TRACE_FUNCTION ("att_get_highest_c2_index()"); + + switch (rr_data->sc_data.selection_type) + { + case BACK_FROM_DEDICATED: + case BACK_FROM_DEDICATED_RLF: + /* + * prepare cell reselection list + */ + for (i = 0; i < 7; i++) + { + rr_data->nc_data[i].c2_used = FALSE; + if (rr_data->nc_data[i].bcch_status NEQ EMPTY) + if (rr_data->nc_data[i].rxlev > rr_data->nc_data[max_result].rxlev) + max_result = i; + } + + if (rr_data->sc_data.selection_type EQ BACK_FROM_DEDICATED) + { + /* + * In case of normal release start with serving cell + */ + rr_data->nc_data[SC_INDEX].c2_used = TRUE; + max_result = SC_INDEX; + rr_data->ms_data.c2_tab[SC_INDEX] = MAX_C2; + result = SC_INDEX; + } + else + { + /* + * In case of call re-establishment start with highest fieldstrength + */ + rr_data->nc_data[max_result].c2_used = TRUE; + rr_data->ms_data.c2_tab[max_result] = MAX_C2; + result = max_result; + } + /* + * Fill with the rest of neighbourcells + */ + while ((next_result = att_get_next_highest_rx ()) + NEQ NO_AVAILABLE) + { + rr_data->ms_data.c2_tab[next_result] = + rr_data->ms_data.c2_tab[result] - 1; + result = next_result; + } + break; + + case CELL_RESELECTION_CR: + /* + * Start with CR cell (from idle mode to another cell) + */ + rr_data->nc_data[CR_INDEX].c2_used = TRUE; + max_result = CR_INDEX; + result = max_result; + rr_data->ms_data.c2_tab[CR_INDEX] = MAX_C2; + /* + * Fill with the rest of neighbourcells + */ + while ((next_result = att_get_next_highest_rx ()) + NEQ NO_AVAILABLE) + { + rr_data->ms_data.c2_tab[next_result] = + rr_data->ms_data.c2_tab[result] - 1; + result = next_result; + } + break; + + default: + /* + * Normal Cell reselection + * + * use a corrected C2 value for calculation, + * because for cell reselection due to C2(NC) > C2(SC) a + * threshold value must be taken in account if serving + * and neighbourcell are members of different location areas. + */ + att_calculate_c2 (SC_INDEX); + rr_data->nc_data[SC_INDEX].c2_corr = rr_data->nc_data[SC_INDEX].c2; + + /* + * Calculate the corrected C2 values for all available neighbourcells. + */ + for (i = 0; i < 6; i++) + { + if (rr_data->nc_data[i].bcch_status EQ DECODED) + { + att_calculate_c2 (i); + rr_data->nc_data[i].c2_corr = rr_data->nc_data[i].c2; + + /* + * Take the cell reselection hysterese threshold value in + * account, if there are different location areas, + * a cell reselection due to C2(NC) > C2(SC) + */ +#ifdef GPRS + /* + * check if the location area has changed + * or the routing area if the scell supports GPRS + */ + { + BOOL la_changed, ra_changed; + + if (!dat_plmn_equal_req (rr_data->nc_data[i].lai.mcc, + rr_data->nc_data[i].lai.mnc, + rr_data->nc_data[SC_INDEX].lai.mcc, + rr_data->nc_data[SC_INDEX].lai.mnc) + OR + rr_data->nc_data[i].lai.lac NEQ + rr_data->nc_data[SC_INDEX].lai.lac) + la_changed = TRUE; + else + la_changed = FALSE; + + if(att_gprs_is_avail()) + { + if(rr_data->nc_data[i].rac NEQ + rr_data->nc_data[SC_INDEX].rac) + ra_changed = TRUE; + else + ra_changed = FALSE; + } + else + { + ra_changed = FALSE; + } + + if(la_changed OR ra_changed OR rr_data->gprs_data.ready_state) +#else + if (!dat_plmn_equal_req (rr_data->nc_data[i].lai.mcc, + rr_data->nc_data[i].lai.mnc, + rr_data->nc_data[SC_INDEX].lai.mcc, + rr_data->nc_data[SC_INDEX].lai.mnc) + OR + rr_data->nc_data[i].lai.lac NEQ + rr_data->nc_data[SC_INDEX].lai.lac) +#endif + { + if ((rr_data->ms_data.imsi_available) AND + (rr_data->ms_data.rr_service NEQ LIMITED_SERVICE) AND + (rr_data->sc_data.selection_type EQ CELL_RESELECTION_NC)) + { + rr_data->nc_data[i].c2_corr -= + 2*rr_data->nc_data[SC_INDEX].select_para.cell_resel_hyst; + } + } + else + { + /* + * in case of a cell reselection occurring within the previous 15 seconds + * in which case the C2 value for the new cell shall exceed the C2 value + * of the serving cell by at least 5 dB for a period of 5 seconds + */ + + if ( IS_TIMER_ACTIVE (T_NO_RESELECT) ) + { + rr_data->nc_data[i].c2_corr -= 5; + } + else + { + /* If the C2(NC)=C2(SC), this will get mis-interpreted in the check below + * c2_corr must be adjusted to make this condition false. The '=' in the '>=' + * condition below only applies when T_NO_RESELECT timer is active and + * c2_corr has been decremented by 5 (above statement) + */ + if( rr_data->nc_data[i].c2_corr EQ rr_data->nc_data[max_result].c2_corr) + { + rr_data->nc_data[i].c2_corr -= 1; + } + } + } +#ifdef GPRS + } +#endif + } + } + + /* + * Now find the the highest one + */ + for (i = 0; i < 7; i++) + { + rr_data->nc_data[i].c2_used = FALSE; + if (rr_data->nc_data[i].bcch_status EQ DECODED) + { + if (rr_data->nc_data[i].c2_corr >= + rr_data->nc_data[max_result].c2_corr) + max_result = i; + } + } + + result = max_result; + + rr_data->nc_data[result].c2_used = TRUE; + rr_data->ms_data.c2_tab[result] = MAX_C2; + + /* + * make the ranking for the other cells. + */ + while ((next_result = att_get_next_highest_c2_val ()) + NEQ NO_AVAILABLE) + { + rr_data->ms_data.c2_tab[next_result] = + rr_data->ms_data.c2_tab[result] - 1; + result = next_result; + } + break; + } + + /* + * return the index of the highest C2. + */ + return max_result; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_get_next_highest_c2_idx| ++--------------------------------------------------------------------+ + + PURPOSE : During the ranking of the cell reselection list this + function searches for the cell with the next highest c2 index. + +*/ + +static UBYTE att_get_next_highest_c2_idx (UBYTE old_index) +{ + GET_INSTANCE_DATA; + UBYTE new_index = NO_AVAILABLE; + UBYTE i; + + TRACE_FUNCTION ("att_get_next_highest_c2_idx()"); + + /* + * depending on the cell reselection type + */ + switch (rr_data->sc_data.selection_type) + { + case BACK_FROM_DEDICATED: + case BACK_FROM_DEDICATED_RLF: + /* + * check all cells + */ + for (i = 0; i <= SC_INDEX; i++) + { + /* + * If cell is available and is not selected yet + */ + if (rr_data->nc_data[i].bcch_status NEQ EMPTY AND + rr_data->ms_data.c2_tab[i] NEQ MAX_C2) + { + /* + * it is the first candidate, then select it + */ + if (new_index EQ NO_AVAILABLE) + new_index = i; + else + { + /* + * else take the one with the higher C2 + */ + if (rr_data->ms_data.c2_tab[i] > + rr_data->ms_data.c2_tab[new_index]) + new_index = i; + } + } + } + + /* + * If a new cell is found, mark this cell as selected + * for the next round + */ + if (new_index NEQ NO_AVAILABLE) + rr_data->ms_data.c2_tab[new_index] = MAX_C2; + break; + + default: + /* + * all other cell reselections + */ + for (i = 0; i <= SC_INDEX; i++) + { + if (rr_data->nc_data[i].bcch_status EQ DECODED) + { + if (old_index NEQ i) + { + if (new_index EQ NO_AVAILABLE) + { + if (rr_data->ms_data.c2_tab[i] < + rr_data->ms_data.c2_tab[old_index]) + { + new_index = i; + } + } + else + { + if (rr_data->ms_data.c2_tab[i] > + rr_data->ms_data.c2_tab[new_index] AND + rr_data->ms_data.c2_tab[i] < + rr_data->ms_data.c2_tab[old_index]) + { + new_index = i; + } + } + } + } + } + break; + } + return new_index; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_get_next_highest_c2_val| ++--------------------------------------------------------------------+ + + PURPOSE : During the ranking of the cell reselection list this + function searches for the cell with the next highest c2 value. + +*/ + +static UBYTE att_get_next_highest_c2_val (void) +{ + GET_INSTANCE_DATA; + UBYTE new_index = NO_AVAILABLE; + UBYTE i; + + TRACE_FUNCTION ("att_get_next_highest_c2_val()"); + + /* + * look for all cells inclusive the serving cell + */ + for (i = 0; i < 7; i++) + { + /* + * the cell must have read the system infos to calculate c2. + */ + if (rr_data->nc_data[i].bcch_status EQ DECODED) + { + /* + * if not ranked yet + */ + if (rr_data->nc_data[i].c2_used EQ FALSE) + { + /* + * if no cell is selected yet, + * then select this one. + */ + if (new_index EQ NO_AVAILABLE) + { + new_index = i; + } + else + { + /* + * the corrected c2 value must be higher + * then the selected one. + */ + if (rr_data->nc_data[i].c2_corr > + rr_data->nc_data[new_index].c2_corr) + { + new_index = i; + } + } + } + } + } + + /* + * a cell has been selected, then mark this cell + * to be not selected the next time. + */ + if (new_index NEQ NO_AVAILABLE) + { + rr_data->nc_data[new_index].c2_used = TRUE; + } + + /* + * return the selected cell index + */ + return new_index; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_get_next_highest_rx | ++--------------------------------------------------------------------+ + + PURPOSE : During the ranking of the cell reselection list this + function searches for the cell with the next highest rx value. + +*/ + +static UBYTE att_get_next_highest_rx (void) +{ + GET_INSTANCE_DATA; + UBYTE new_index = NO_AVAILABLE; + UBYTE i; + + TRACE_FUNCTION ("att_get_next_highest_rx()"); + + /* + * for all neighbourcells and the serving cell + */ + for (i = 0; i < 7; i++) + { + /* + * if something is stored for this index + * that means at least MS is synchronized. + */ + if (rr_data->nc_data[i].bcch_status NEQ EMPTY) + { + /* + * the cell has not been ranked + */ + if (rr_data->nc_data[i].c2_used EQ FALSE) + { + /* + * if it is the first cell in this attempt, + * then select it. + */ + if (new_index EQ NO_AVAILABLE) + { + new_index = i; + } + else + { + /* + * to select the cell it must have a higher + * fieldstrength + */ + if (rr_data->nc_data[i].rxlev > + rr_data->nc_data[new_index].rxlev) + { + new_index = i; + } + } + } + } + } + + /* + * A cell has been selected, then mark it as + * ranked to avoid selection in the next attempt. + */ + if (new_index NEQ NO_AVAILABLE) + { + rr_data->nc_data[new_index].c2_used = TRUE; + } + + /* + * return the index of the selected cell. + */ + return new_index; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_handle_rr_act_req | ++--------------------------------------------------------------------+ + + PURPOSE : MM requests with the primitive RR_ACTIVATE_REQ one of the + following procedures: + + 1. Full Service - search for a specific PLMN + 2. Limited Service - search for a cell for limited service + 3. PLMN Search - request the PLMN available list. + +*/ + +GLOBAL void att_handle_rr_act_req (UBYTE initial_act, + T_RR_ACTIVATE_REQ *rr_activate_req) +{ + GET_INSTANCE_DATA; + UBYTE count = 0; + TRACE_FUNCTION ("att_handle_rr_act_req()"); + + /* + * stop time control for an ongoing cell reselection + */ + TIMERSTOP (T_RESELECT); + TIMERSTOP (TABORT); + + rr_data->net_lost = FALSE; + + if (initial_act) + { + /* + * read ms data from e2prom + */ + att_clear_parallel_search(); + rr_csf_ms_cap (); + rr_csf_check_rfcap (FALSE); + rr_csf_read_imei (&rr_data->ms_data.imei); + rr_data->ms_data.rr_service = NO_SERVICE; /* set initial to no service */ + } + + for(count=0;count<MAX_MCC_SHIELD;count++) + { + TRACE_EVENT_P3 ( "Current software shielded MCC are =%d%d%d", + rr_data->dyn_config.mcc_shield.mcc[count][0], + rr_data->dyn_config.mcc_shield.mcc[count][1], + rr_data->dyn_config.mcc_shield.mcc[count][2]); + } + + /* + * store EPLMN list, if available, for use in cell selection/reselection. + */ + att_copy_eplmn_list(&rr_activate_req->eq_plmn_list); + + /* + * store operation mode data + */ + rr_data->ms_data.operation_mode = + (rr_activate_req->op.ts << 7) + + (rr_activate_req->op.m << 6) + + (rr_activate_req->op.sim_ins << 5); + + /* + * some optimisations must be removed for the FTA campaign. + */ + if (dat_test_sim_available() EQ TRUE) + test_house = TRUE; + + att_set_func (rr_activate_req->op.func); + /* + * start cell selection procedure + */ + rr_data->ms_data.req_mm_service = att_get_func (); + + TRACE_EVENT_P6 ("RR_ACTIVATE_REQ: %s func op=%s %scurrent=%s rMM=%s RRs=%s", + initial_act ? "initial" : "", + _rr_str_FUNC[rr_activate_req->op.func], + _rr_str_PARFUNC[rr_data->ms_data.parallel_net_plmn_search_type], + _rr_str_FUNC[rr_data->ms_data.current_plmn_search_type], + _rr_str_FUNC[rr_data->ms_data.req_mm_service], + _rr_str_SERVICE[rr_data->ms_data.rr_service]); + + switch (rr_data->ms_data.req_mm_service) + { + case FUNC_LIM_SERV_ST_SRCH: +#ifdef GPRS + att_set_gprs_indication(rr_activate_req->gprs_indication); +#endif + rr_data->c1_offset = C1_OFFSET; + + att_begin_cs(FUNC_LIM_SERV_ST_SRCH); + break; + + case FUNC_NET_SRCH_BY_MMI: + /* + * clear found_channel parameter from previous search + */ + switch(GET_STATE(STATE_ATT)) + { + case ATT_IDLE: + case ATT_CON_EST: + /* Cell Selection Improvements-LLD section:4.1.3.9 */ + att_start_cell_selection(MM_ORIGINATED, CS_PARALLEL,FULL_SEARCH_MODE); + break; + + default: + att_begin_cs(FUNC_NET_SRCH_BY_MMI); + break; + } + EM_NET_SEARCH_STARTED; + break; + + case FUNC_PLMN_SRCH: + /* + * copy full service parameter from SIM + */ +#ifdef GPRS + att_set_gprs_indication (rr_activate_req->gprs_indication); +#endif + if (rr_data->ms_data.rr_service NEQ NO_SERVICE) + cs_clear_attributes (CHECKED_FLAG, rr_data->nc_data[SC_INDEX].arfcn); + +/* Implements Measure#32: Row 52,53 */ + att_print_mcc_mnc (NOT_PRESENT_16BIT, rr_data->ms_data.plmn.mcc, + rr_data->ms_data.plmn.mnc, S2I_STRING("old_req_plmn")); + att_print_mcc_mnc (NOT_PRESENT_16BIT, rr_activate_req->plmn.mcc, + rr_activate_req->plmn.mnc, S2I_STRING("new_req_plmn")); + + memcpy (&rr_data->ms_data.plmn, &rr_activate_req->plmn, sizeof (T_plmn)); + rr_data->ms_data.cksn = rr_activate_req->cksn; + memcpy (rr_data->ms_data.new_kc, &rr_activate_req->kcv.kc, KC_STRING_SIZE); + rr_data->ms_data.access_classes = rr_activate_req->accc; + +#if defined(_SIMULATION_) +/* Implements Measure#32: Row 52 */ + att_print_mcc_mnc(rr_data->nc_data[SC_INDEX].arfcn, + rr_data->ms_data.plmn.mcc, rr_data->ms_data.plmn.mnc, S2I_STRING("req")); +#endif + + /* + * copy IMSI if available + */ + if (rr_activate_req->imsi_struct.id_type EQ TYPE_IMSI) + { + memset (&rr_data->ms_data.imsi, 0, sizeof (rr_data->ms_data.imsi)); + rr_data->ms_data.imsi_available = TRUE; + rr_data->ms_data.imsi.ident_type = TYPE_IMSI; + rr_data->ms_data.imsi.v_ident_dig = TRUE; + rr_data->ms_data.imsi.c_ident_dig = + att_calculate_digits (rr_activate_req->imsi_struct.id); + rr_data->ms_data.imsi.odd_even = + rr_data->ms_data.imsi.c_ident_dig & 1; + memcpy (rr_data->ms_data.imsi.ident_dig, rr_activate_req->imsi_struct.id, 16); + } + else + rr_data->ms_data.imsi_available = FALSE; + + /* + * copy TMSI if available + */ + if (rr_activate_req->tmsi_struct.id_type EQ TYPE_TMSI) + { + rr_data->ms_data.tmsi_available = TRUE; + rr_data->ms_data.tmsi_binary = rr_activate_req->tmsi_struct.tmsi_dig; + } + else + rr_data->ms_data.tmsi_available = FALSE; + + if (dat_test_sim_available()) + rr_data->c1_offset = 0; + else + rr_data->c1_offset = C1_OFFSET; + + /* CSI-LLD section:4.1.1.11 + * First FUNC_PLMN_SEARCH + */ + if(rr_data->cs_data.initial_plmn_search EQ INITIAL_PLMN_SEARCH_NOT_ACTIVE) + { + rr_data->cs_data.initial_plmn_search = INITIAL_PLMN_SEARCH_ACTIVE; + } + + cs_set_bcch_info(&rr_activate_req->bcch_info); + + att_begin_cs(FUNC_PLMN_SRCH); + EM_PLMN_SRCH_STARTED; + break; + + case FUNC_ST_PWR_SCAN: + SET_STATE(STATE_ATT, ATT_CS_INIT ); + att_start_cell_selection(MM_ORIGINATED, CS_NOT_PARALLEL,FULL_SEARCH_MODE); + break; + } + + PFREE (rr_activate_req); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_begin_cs | ++--------------------------------------------------------------------+ + + PURPOSE : This function initializes a cell selection or starts BCCH + reading depending on the ATT state on an RR_ACTIVATE_REQ +*/ + +static void att_begin_cs (UBYTE req_mm_service) +{ + GET_INSTANCE_DATA; + if(GET_STATE(STATE_ATT) EQ ATT_CS_INIT ) + { + SET_STATE(STATE_ATT, ATT_CS1 ); /*Boot Time*/ + + /* Boot Time Performance Enhancement: + * Start the TABORT timer on receiving the second activate_req + */ + tstart_tabort(TABORT_VALUE); + + /* Invalidate whitelist if its PLMN ID does not match + * with the requested PLMN + */ + if((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))) + { + rr_data->cs_data.white_list.region = NOT_PRESENT_8BIT; + } + if( srv_check_stored_prim(MPH_POWER_CNF)) + { + srv_use_stored_prim(); + } + /* + * reset the time for net search to finish + * a PLMN available search during 60 seconds. + */ + if( req_mm_service EQ FUNC_NET_SRCH_BY_MMI) + TIMERSTART(T_PLMN_SEARCH, T_PLMN_SEARCH_VALUE); + } + else + { + /* Cell Selection Improvements-LLD section:4.1.3.9 */ + att_start_cell_selection(MM_ORIGINATED, CS_NOT_PARALLEL,FULL_SEARCH_MODE); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_increase_power_on_time | ++--------------------------------------------------------------------+ + + PURPOSE : A requirement in GSM 5.08 indicates that the list of + forbidden location areas must be cleared all 12 hours. + Therefore this counters power_on_low and power_on_high + are used. They are triggered by the periodic measurement + reports in idle mode. + +*/ + +GLOBAL void att_increase_power_on_time (USHORT inc) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_increase_power_on_time()"); + + /* + * increment power_on_low + */ + rr_data->power_on_low += inc; + if (rr_data->power_on_low >= 60) + { + /* if it is more then 60 seconds, + * increment power_on_high = minutes + */ + rr_data->power_on_low = 0; + rr_data->power_on_high++; + if (rr_data->power_on_high >= 720) + { + /* + * after 12 hours = 720 minutes clear all forbidden location area lists + */ + rr_data->power_on_low = 0; + rr_data->power_on_high = 0; + att_clear_forb_list (FORBIDDEN_LIST_NORMAL); + att_clear_forb_list (FORBIDDEN_LIST_ROAMING); + } + } +} + + +#if defined (TI_PS_FF_RTD) AND defined (REL99) +LOCAL void att_init_rtd_data(T_rr_enh_para *p_cur) +{ + UBYTE j,k; + TRACE_FUNCTION ("att_init_rtd_data"); + +for(j = 0;j < MAX_NR_OF_NCELL; j++ ) + { + p_cur->enh_para.enh_cell_list[j].v_rtd = FALSE; + for(k = 0;k < MAX_NUM_OF_RTD_VALUES; k++) + p_cur->enh_para.enh_cell_list[j].rtd[k]= RTD_NOT_AVAILABLE; + p_cur->enh_para.enh_cell_list[j].c_rtd = 0; + }/*for*/ +return; +} +#endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */ + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_init_cell_selection | ++--------------------------------------------------------------------+ + + PURPOSE : The function initializes some variables needed for control + of cell selection and cell reselection. + +*/ + +GLOBAL void att_init_cell_selection (UBYTE selection, + BOOL initiator) +{ + GET_INSTANCE_DATA; +#if defined (TI_PS_FF_RTD) AND defined (REL99) + T_rr_enh_para *p_cur = &rr_data->sc_data.emr_data_current; +#endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */ + + TRACE_FUNCTION ("att_init_cell_selection()"); + + TRACE_EVENT_P2 ("init CELL_%sSELECTION %s_ORIGINATED", + (selection EQ CELL_SELECTION) ? "" : "RE", + (initiator EQ MM_ORIGINATED) ? "MM" : "RR" ); + + /* + * store type of selection and the initiator (RR or MM). + */ + rr_data->sc_data.selection_type = selection; + rr_data->sc_data.mm_started = initiator; + + /* + * clear the list of the found PLMNs + */ + rr_data->sc_data.found_entries = 0; + + /* + * clear the bitmap indicating whether all system information + * messages are read. + */ + att_init_cr_data(); + +#if defined (TI_PS_FF_RTD) AND defined (REL99) + att_init_rtd_data(p_cur); +#endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */ + + + /* + * reset multiband parameter + */ + rr_data->ncell_mb = 0; + + if (GET_STATE (STATE_ATT) EQ ATT_CS2 OR GET_STATE (STATE_ATT) EQ ATT_CS3) + { + rr_data->nc_data[SC_INDEX].lai.mcc[0] = NOT_PRESENT_8BIT; + rr_data->nc_data[SC_INDEX].lai.mnc[0] = NOT_PRESENT_8BIT; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_init_gsm_data | ++--------------------------------------------------------------------+ + + PURPOSE : Intialize all gsm specific variables of RR. + +*/ + +GLOBAL void att_init_gsm_data (void) +{ + GET_INSTANCE_DATA; + SHORT i; + UBYTE save; + UBYTE gprs_ms, cmsp; + BOOL ms_configured, cmsp_configured; + +#if defined (TI_PS_FF_RTD) AND defined (REL99) + T_rr_enh_para *p_cur = &rr_data->sc_data.emr_data_current; +#endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */ + + + TRACE_FUNCTION ("att_init_gsm_data()"); + + save = rr_data->dyn_config.no_sys_time; + + /* save configured GPRS multislot class */ + ms_configured = rr_data->ms_data.multislot_class_configured; + gprs_ms = rr_data->ms_data.rf_cap.rf_ms.gprs_ms_class; + dat_emo_stop ( FALSE ); + + /* save configured CMSP bit */ + cmsp_configured = rr_data->ms_data.cmsp_configured; + cmsp = rr_data->ms_data.rf_cap.cmsp; + + /* + * clar all RR data with the default value + */ + memset (rr_data, 0, sizeof (T_RR_DATA)); + + /* + * some parameters have a different default value + */ + rr_data->lup_rxlev = 63; + rr_data->dyn_config.no_sys_time = save; + rr_data->ms_data.cksn = CKSN_NOT_PRES; + + /* restore configured GPRS multislot class */ + if (ms_configured) + { + rr_data->ms_data.multislot_class_configured = TRUE; + rr_data->ms_data.rf_cap.rf_ms.gprs_ms_class = gprs_ms; + TRACE_EVENT_P1 ("'gprs_ms_class' configured to a value of %d", gprs_ms); + } + + /* restore configured CMSP bit */ + if (cmsp_configured) + { + rr_data->ms_data.cmsp_configured = TRUE; + rr_data->ms_data.rf_cap.cmsp= cmsp; + TRACE_EVENT_P1 ("'cmsp' configured to a value of %d", cmsp); + } +#if defined (REL99) AND defined (TI_PS_FF_EMR) AND defined (GPRS) + rr_data->ms_data.enable_ps_emr = TRUE; +#endif + for (i = 0; i < 8; i++) + { + rr_data->nc_data[i].lai.mcc[0] = NOT_PRESENT_8BIT; + rr_data->nc_data[i].lai.mnc[0] = NOT_PRESENT_8BIT; + } +#if defined (REL99) && defined (TI_PS_FF_EMR) + /*Default initializations for EMR*/ + memset (rr_data->sc_data.rep_count, NOT_PRESENT_8BIT, MAX_NEIGHBOURCELLS); + for_set_default_emr_data(&rr_data->sc_data.emr_data_current); + for_set_default_emr_data(&rr_data->sc_data.emr_data_temp); + rr_data->sc_data.enh_para_status = ENH_PARA_INVALID_STATE; + rr_data->sc_data.ba_list_ded = rr_data->sc_data.ba_list_idle = FALSE; + rr_data->sc_data.ba_index = NOT_PRESENT_8BIT; +#endif +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + rr_data->sc_data.cd.band_indicator = NOT_PRESENT_8BIT; + rr_data->cr_data.cd.band_indicator = NOT_PRESENT_8BIT; +#endif + +#if defined (TI_PS_FF_RTD) AND defined (REL99) + att_init_rtd_data(p_cur); +#endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */ + + /* + * clear the forbidden lists + */ + att_clear_forb_list (FORBIDDEN_LIST_NORMAL); + att_clear_forb_list (FORBIDDEN_LIST_ROAMING); + + /* + * indicate all RR timer as not running + */ + memset (rr_data->t_running, 0, sizeof (rr_data->t_running)); + rr_data->t_expire[T3110] = tim_t3110; + rr_data->t_expire[T3122] = tim_t3122; + rr_data->t_expire[T3126] = tim_t3126; + rr_data->t_expire[TREG] = tim_treg; + rr_data->t_expire[T_RESELECT] = tim_treselect; + rr_data->t_expire[TIM_EXT_MEAS] = tim_ext_meas; + rr_data->t_expire[T_NO_RESELECT] = NULL; + rr_data->t_expire[TCSVALID] = NULL; + rr_data->t_expire[TABORT] = tim_tabort; + rr_data->t_expire[T_PLMN_SEARCH] = tim_plmn_search_expiry; + rr_data->t_expire[T_FAST_CS] = tim_tfast_cs; + rr_data->t_expire[T_NORMAL_CS] = tim_tnormal_cs; + + rr_data->net_lost = FALSE; + + + #if defined FF_EOTD + rr_data->t_expire[TAPDU] = tim_apdu; + #endif /* FF_EOTD */ + rr_data->t_expire[TNNN] = tim_tnnn; + rr_data->t_expire[T_DEDICATED_MODE] = NULL; + rr_data->treg_pending = FALSE; + + rr_data->old_serving_cell = NOT_PRESENT_8BIT; + rr_data->ms_data.rr_service = NO_SERVICE; + + /* tch loop "open" */ + rr_data->tch_loop_subch = NOT_PRESENT_8BIT; + +#if defined FF_EOTD + rr_data->eotd_req_id = NOT_PRESENT_16BIT; +#endif /* FF_EOTD */ + +#ifdef _SIMULATION_ + { + int i=0; + for (;i<NUM_OF_RR_TIMERS;i++) + { + #ifdef OPTION_TIMER + /* vsi_t_config is removed in latest GPF */ + #endif + } + } +#endif +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_init_pl_status | ++--------------------------------------------------------------------+ + + PURPOSE : the function clear the cell channel description list + of the serving cell. + +*/ + +GLOBAL void att_init_pl_status (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_init_pl_status()"); + + rr_data->sc_data.cd.v_cell_chan_desc = NO_CONTENT; + srv_clear_list (&rr_data->sc_data.cd.cell_chan_desc); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_insert_cell_in_data | ++--------------------------------------------------------------------+ + + PURPOSE : During the analysis of an incoming measurement report a + new cell has been detected. The data of this cell are + stored in RR. + +*/ + +static void att_insert_cell_in_data (T_MPH_MEASUREMENT_IND *report, + UBYTE index) +{ + GET_INSTANCE_DATA; + UBYTE i; + T_NC_DATA * rrd; + + TRACE_FUNCTION ("att_insert_cell_in_data()"); + + /* + * search for a free entry in the RR storage area. + */ + for (i = 0; i < 6; i++) + if (rr_data->nc_data[i].bcch_status EQ EMPTY) + break; + + if (i < 6) + { + /* + * RR will ever find a free area, because all + * cells which are not longer in the measurement + * report, are removed from the RR storage. + * The if-condition is only for security reasons + * + * Store the data from the measurement report and + * wait for the system information messages. + */ + rrd = &rr_data->nc_data[i]; + rrd->bsic = report->ncells.bsic[index]; + rrd->arfcn = report->ncells.arfcn[index]; + rrd->rxlev = report->ncells.rx_lev[index]; + rrd->bcch_status = NON_DECODED; + rrd->avail_time = 0; + #ifdef GPRS + if( rr_data->gprs_data.use_c31 ) + att_insert_c31_cr_data_in_cell(i); + #endif + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_max | ++--------------------------------------------------------------------+ + + PURPOSE : The function calculates the maximum from two values a and b. + +*/ + +GLOBAL SHORT att_max (SHORT a, + SHORT b) +{ + TRACE_FUNCTION ("att_max()"); + + return ((a > b) ? a : b); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_plmn_in_found_list | ++--------------------------------------------------------------------+ + + PURPOSE : The function checks whether a PLMN identification is already + stored in the found list or not during cell selection / cell + reselection. + +*/ + +GLOBAL T_FOUND_ELEMENT *att_plmn_in_found_list (UBYTE *mcc, UBYTE *mnc) +{ + GET_INSTANCE_DATA; + T_FOUND_ELEMENT *result = NULL; + int i; + T_FOUND_ELEMENT *found; + + TRACE_FUNCTION ("att_plmn_in_found_list()"); + + /* + * look for all entries, which are already stored + */ + /*att_print_mcc_mnc(0, mcc, mnc, "compare with");*/ + found = &rr_data->sc_data.found[0]; + for (i = 0; i < rr_data->sc_data.found_entries; i++, found++) + { + /* + * compare mobile country code and mobile network code. + */ + /*att_print_mcc_mnc(found->arfcn, found->plmn.mcc, found->plmn.mnc, "list");*/ + if (dat_plmn_equal_req (mcc, mnc, + found->plmn.mcc, found->plmn.mnc)) + { + result = found; + /*att_print_mcc_mnc(found->arfcn, mcc, mnc, "found");*/ + break; + } + } + + /* + * return the result of the compare. + */ + return result; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_save_found_plmn | ++--------------------------------------------------------------------+ + + PURPOSE : The function set all list elements of a found PLMN. + It marks the element as present (V_PLMN_PRES) + +*/ + +GLOBAL void att_save_found_plmn (T_FOUND_ELEMENT *element, UBYTE mcc[], UBYTE mnc[], + USHORT arfcn, UBYTE rxlev, USHORT lac, UBYTE cell_ok) +{ + GET_INSTANCE_DATA; + element->plmn.v_plmn = V_PLMN_PRES; + memcpy (element->plmn.mcc, mcc, SIZE_MCC); + memcpy (element->plmn.mnc, mnc, SIZE_MNC); + element->arfcn = arfcn; + element->rxlev = rxlev; + element->lac = lac; /* LOL 02.01.2003: added for EONS support */ + element->cell_ok = cell_ok; +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + if (rr_data->cs_data.region EQ BOTH_REGIONS) + { + element->region = srv_get_region_from_std_arfcn (std, arfcn); + } + else + { +#endif + element->region = rr_data->cs_data.region; +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + } +#endif + + TRACE_EVENT_P9 ("[%u] save new PLMN (%x%x%x %x%x%x) region=%d, entries=%u", + arfcn, mcc[0], mcc[1], mcc[2], mnc[0], mnc[1], mnc[2],element->region, + rr_data->sc_data.found_entries+1); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_priority_check | ++--------------------------------------------------------------------+ + + PURPOSE : The function checks the priority of a cell during cell + selection. It must be differed between first and second + attempt. + + During the first attempt it will be differed between + low and high (or normal) priority. + + In the first attempt the cell bar qualifier is used to + differ between low and high priority. Beside this there + is an exception defined in GSM 5.08 chapter 9. + + In the second attempt the priority check is ever successful. + +*/ + +static BOOL att_priority_check (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_priority_check()"); + + /* + * During the First Scan second attempt and second scan the priority + * check is ever successful. + */ + if((rr_data->cs_data.scan_mode EQ CS_FIRST_SCAN_SECOND_ATTEMPT) OR + (rr_data->cs_data.scan_mode EQ CS_SECOND_SCAN)) + { + return TRUE; + } + + /* + * Exception condition handling according GSM 5.08, chapter 9 + */ + if (dat_hplmn (rr_data->nc_data[CR_INDEX].lai.mcc, + rr_data->nc_data[CR_INDEX].lai.mnc) AND + rr_data->cell_test_operation AND + rr_data->nc_data[CR_INDEX].c2_par.cbq EQ 0 AND + rr_data->nc_data[CR_INDEX].rach.cell_bar_access EQ 1 AND + (rr_data->nc_data[CR_INDEX].rach.ac & 0x8000) NEQ 0) + return TRUE; + + /* + * Else the cell bar qualifier indicates the priority + */ + if (rr_data->nc_data[CR_INDEX].c2_par.cbq) + return FALSE; + else + return TRUE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_remove_bad_ncell | ++--------------------------------------------------------------------+ + + PURPOSE : During fieldtest sometimes a neighbourcell in the + measurement report was equal to a neighbourcell. This + function deletes neighbourcell data if the channel is + equal to the serving cell. + +*/ + +GLOBAL void att_remove_bad_ncell (T_MPH_MEASUREMENT_IND *report) +{ + GET_INSTANCE_DATA; + SHORT i = 0; + SHORT j; + T_ncells *pncells = &report->ncells; + TRACE_FUNCTION ("att_remove_bad_ncell()"); + + /* + * for all neighbourcells in the measurement report. + */ + while (i < pncells->no_of_ncells) + { + /* + * Do nothing if the channel number is different from + * the serving cell. + */ + if (pncells->arfcn[i] NEQ rr_data->nc_data[SC_INDEX].arfcn) + i++; + else + { + /* + * else overwrite this entry by moving the rest one index + */ + for (j = i + 1; j < pncells->no_of_ncells; j++) + { + pncells->arfcn[j-1] = pncells->arfcn[j]; + pncells->rx_lev[j-1] = pncells->rx_lev[j]; + pncells->bsic[j-1] = pncells->bsic[j]; + pncells->time_alignmt[j-1] = pncells->time_alignmt[j]; + pncells->frame_offset[j-1] = pncells->frame_offset[j]; + } + + /* + * clean the last entry + */ + pncells->bsic[j-1] = 0; + pncells->arfcn[j-1] = 0; + pncells->rx_lev[j-1] = 0; + pncells->time_alignmt[j-1] = 0; + pncells->frame_offset[j-1] = 0; + pncells->no_of_ncells--; + } + } +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_allow_lai_in_list | ++--------------------------------------------------------------------+ + + PURPOSE : After a successful location updating request MM informs + RR about this. If the location area information is stored + inside of one of the forbidden location area lists this + information must be updated. In this function, the entry + is deleted from the given forbidden list. + +*/ + +LOCAL void att_allow_lai_in_list (int list_type, + const T_plmn * plmn, + USHORT lac) +{ + GET_INSTANCE_DATA; + unsigned int i; + T_loc_area_ident *forb_list; + + if (list_type EQ FORBIDDEN_LIST_NORMAL) + forb_list = &rr_data->ms_data.forb_lac_list[0]; + else + forb_list = &rr_data->ms_data.roam_forb_lac_list[0]; + + TRACE_FUNCTION ("att_allow_lai_in_list()"); + + for (i = 0; i < (MAX_LAI-1); i++) + { + if ((lac EQ forb_list[i].lac) AND + dat_plmn_equal_req (plmn->mcc, plmn->mnc, + forb_list[i].mcc, forb_list[i].mnc)) + { + /* + * if the location area code is stored, overwrite this information + * and fill the last issue with a default value + */ +/* Implements Measure#32: Row 60 */ + att_print_forb_list ( list_type, plmn, lac, i, TRUE); + + memmove (&forb_list[i], &forb_list[i + 1], + (MAX_LAI - i - 1) * sizeof (T_loc_area_ident)); + forb_list[MAX_LAI - 1].lac = NOT_PRESENT_16BIT; + memset (forb_list[MAX_LAI - 1].mcc, NOT_PRESENT_8BIT, SIZE_MCC); + memset (forb_list[MAX_LAI - 1].mnc, NOT_PRESENT_8BIT, SIZE_MNC); + } + } +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_rem_lai_from_forb_list | ++--------------------------------------------------------------------+ + + PURPOSE : After a successful location updating request MM informs + RR about this. If the location area information is stored + inside of one of the forbidden location area lists this + information must be updated. In this function, the entry + is deleted from all forbidden lists. + +*/ + +GLOBAL void att_rem_lai_from_forb_list (const T_plmn * plmn, + USHORT lac) +{ + TRACE_FUNCTION ("att_rem_lai_from_forb_list()"); + + att_allow_lai_in_list (FORBIDDEN_LIST_NORMAL, plmn, lac); + att_allow_lai_in_list (FORBIDDEN_LIST_ROAMING, plmn, lac); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_search_cell | ++--------------------------------------------------------------------+ + + PURPOSE : This function searches for a cell for cell reselection. + +*/ + +static void att_search_cell (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_search_cell()"); +#if defined(_SIMULATION_) + TRACE_SELECTION_TYPE (rr_data->sc_data.selection_type); +#endif /* _SIMULATION_ */ + + /* + * depending on the cell reselection mode. + */ + switch (rr_data->sc_data.selection_type) + { + case BACK_FROM_DEDICATED: + case BACK_FROM_DEDICATED_RLF: + /* + * back from dedicated use the fieldstrength of the + * cells as the criterion + */ + rr_data->reselect_index = att_get_highest_c2_index (); + att_select_cell_dedicated (); + break; + + case CELL_RESELECTION: + case CELL_RESELECTION_NC: + #ifdef GPRS + if( rr_data->gprs_data.use_c31 ) + { + SHORT i; + TRACE_EVENT ("c32 used in att_search_cell"); + for( i = 0; i < 6; i++ ) + rr_data->nc_data[i].c32_used = FALSE; + + rr_data->ms_data.old_cell_tried = FALSE; + + rr_data->reselect_index = att_get_next_best_c32_index (FALSE); + + /* + * if no suitable cell is available + * try the old cell again. + */ + if (! att_check_cell_c31 ()) + att_try_old_cell (); + + break; + } + #endif + /*lint -fallthrough*/ + default: + /* + * cell reselection in idle mode, use the cell + * reselection criterion C2. + */ + rr_data->ms_data.old_cell_tried = FALSE; + rr_data->reselect_index = att_get_highest_c2_index (); + + /* + * if no suitable cell is available + * try the old cell again. + */ + if (! att_check_cell ()) + att_try_old_cell (); + break; + } + EM_FMM_RESEL_START_IND; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_set_pl_in_idle_mode | ++--------------------------------------------------------------------+ + + PURPOSE : The function configures the idle mode at the end of + cell selection and cell reselection. + +*/ + +GLOBAL void att_set_pl_in_idle_mode (void) +{ +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + GET_INSTANCE_DATA; +#endif + TRACE_FUNCTION ("att_set_pl_in_idle_mode()"); + /* Update std value depending upon the band indicator value */ +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + att_update_std_band_indicator (rr_data->sc_data.cd.band_indicator); +#endif + /* + * forward classmark information to layer 1 for random access procedure + */ + att_build_classmark_req (); + + /* + * configure the idle mode (paging group etc.) + */ + att_build_idle_req (SC_INDEX, MODE_CELL_SELECTION); + + /* + * configure the CBCH channel + */ +#ifdef REL99 + att_config_cbch (); +#else + att_build_cbch(); +#endif + + /* + * configure the neighbourcell list + */ + att_code_mph_ncell_req (SC_INDEX); + + /* + * store the neighbourcell information in PCM and the SIM card. + */ +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_set_sys_info_read | ++--------------------------------------------------------------------+ + + PURPOSE : The decision whether all system information messages are + read during cell selection / cell reselection is done with + this function. The variable sys_info_read is organized as + a bitmap. Each system information message belongs to one + bit of the bitmap. + +*/ + +GLOBAL void att_set_sys_info_read (USHORT mess_bit, UBYTE index) +{ + GET_INSTANCE_DATA; + T_CELL_DATA * cd; + USHORT si; + + TRACE_FUNCTION ("att_set_sys_info_read()"); + + /* + * set pointer to data + */ + if (index EQ SC_INDEX) + cd = &rr_data->sc_data.cd; + else if (index EQ CR_INDEX) + cd = &rr_data->cr_data.cd; + else + { + TRACE_EVENT ("unexpected index in att_set_sys_info_read()"); + return; + } + + /* + * set the bit of the bitmap according to the message type. + */ + cd->sys_info_read |= mess_bit; + +#if !defined(NTRACE) + si = cd->sys_info_read; +/* if (GET_STATE (STATE_ATT) EQ ATT_CS2) comment out just for debugging */ + { + if (si EQ ALL_SYS_INFO_READ) + { + TRACE_EVENT ("SI complete"); + } + else + { +#ifdef GPRS + TRACE_EVENT_P9 ( "await SI%s%s%s%s%s%s%s (%x) for %s", + (si & SYS_INFO_1_READ ) ? "" : " 1" , + (si & SYS_INFO_2_READ ) ? "" : " 2" , + (si & SYS_INFO_2BIS_READ) ? "" : " 2bis", + (si & SYS_INFO_3_READ ) ? "" : " 3" , + (si & SYS_INFO_4_READ ) ? "" : " 4" , + (si & SYS_INFO_2TER_READ) ? "" : " 2ter", + (si & SYS_INFO_13_READ ) ? "" : " 13", + si, + (index EQ SC_INDEX ) ? "SC_INDEX" : "CR_INDEX"); +#else + TRACE_EVENT_P8 ( "await SI%s%s%s%s%s%s (%x) for %s", + (si & SYS_INFO_1_READ ) ? "" : " 1" , + (si & SYS_INFO_2_READ ) ? "" : " 2" , + (si & SYS_INFO_2BIS_READ) ? "" : " 2bis", + (si & SYS_INFO_3_READ ) ? "" : " 3" , + (si & SYS_INFO_4_READ ) ? "" : " 4" , + (si & SYS_INFO_2TER_READ) ? "" : " 2ter", + si, + (index EQ SC_INDEX ) ? "SC_INDEX" : "CR_INDEX"); +#endif + } + } +#endif /* !NTRACE */ +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_start_cell_reselection | ++--------------------------------------------------------------------+ + + PURPOSE : The function is called at the beginning of a cell + reselection. + +*/ + +GLOBAL void att_start_cell_reselection (UBYTE mode) +{ + GET_INSTANCE_DATA; +#ifdef GPRS + T_GPRS_DATA *gprs_data = &rr_data->gprs_data; +#endif + + TRACE_FUNCTION ("att_start_cell_reselection()"); + + if( mode EQ BACK_FROM_DEDICATED_RLF) + { + /* + * Allow 20 seconds for call re-establishment + * In case of data link failure + */ + tstart_tabort(2 * TABORT_VALUE); + } + else + { + tstart_tabort(TABORT_VALUE); + } + +#ifdef GPRS + if ( gprs_data->rrgrr_ext_meas_req NEQ NULL ) + { + /* + * Save the request to perform Cell Reselection. + * Then stop the Ext Meas procedure. + * At the very end of the Ext Meas continue with CR. + */ + gprs_data->ext_meas_ctrl |= EXT_MEAS_START_CR; + rr_data->sc_data.selection_type = mode; + att_rrgrr_ext_meas_stop_req(NULL); + return; + } +#endif + + /* + * intialise some variables + */ + 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); + + /* + * MM has initiated GPRS Activation. While waiting for SI13 a local reselection + * is triggered in RR because of a better neighbour cell. Since MM initiated GPRS + * is pending; RR should respond by RR_ACTIVATE_CNF and not by RR_ACTIVATE_IND. + */ +#ifdef GPRS + if ( GET_STATE(STATE_GPRS) EQ GPRS_ACTIVATED AND + rr_data->sc_data.mm_started EQ MM_ORIGINATED AND + rr_data->sc_data.selection_type EQ CELL_RESELECTION_ON_GPRS_ACT) + { + att_init_cell_selection (mode, MM_ORIGINATED); + } + else +#endif + { + att_init_cell_selection (mode, RR_ORIGINATED); + } + dat_att_null(); +#ifdef GPRS + gprs_init_data_cr(); +#endif + /* + * stop any reselection related timer. + */ + if (rr_data->sc_data.selection_type EQ BACK_FROM_DEDICATED_RLF) + { + /* + * according GSM 5.08, chapter 6.7.2 call re-establishment + * shall be finished latest during 20 seconds (=2*normal + * cell reselection time). + */ + TIMERSTART (T_RESELECT, 2*TRESELECT_VALUE); + } + else + { + TIMERSTART (T_RESELECT, TRESELECT_VALUE); + } + + /* + * depending on the cell reselection type + */ + switch (rr_data->sc_data.selection_type) + { + case CELL_RESELECTION: + case CELL_RESELECTION_RACH: + /* + * exclude serving cell for five seconds + */ + set_tnnn (SC_INDEX, 5*ONE_SEC); + break; + case BACK_FROM_DEDICATED: + case BACK_FROM_DEDICATED_RLF: + /* + * remove serving cell from neighbourcell results + */ + att_remove_bad_ncell (&rr_data->ms_data.measurement_report); + att_build_back_from_dedicated (); + break; + case CELL_RESELECTION_CR: + /* + * check cell to get back in full service + */ + break; + } + + EM_CELL_RESEL_STARTED; + /* + * find a suitable cell for cell reselection + */ + att_search_cell (); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_start_cell_selection | ++--------------------------------------------------------------------+ + + PURPOSE : The function is called at the beginning of a cell selection. +*/ + +GLOBAL void att_start_cell_selection (BOOL originator, BOOL parallel, + U8 search_mode) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("att_start_cell_selection()"); + + + TRACE_EVENT_P2 ("START %sparallel CELL SELECTION %s_ORIGINATED", + parallel?"":"not ", + originator?"MM":"RR"); + + tstart_tabort(TABORT_VALUE); + + rr_data->net_lost = FALSE; + rr_data->cs_data.black_list_search_pending = FALSE; + + EM_CELL_SELECTION; + + /* Set the current search mode */ + CS_SET_CURRENT_SEARCH_MODE(search_mode); + + /* + * initialize some variables + */ + /* found channel handling */ + if(originator EQ MM_ORIGINATED) + { + if(rr_data->ms_data.req_mm_service EQ FUNC_PLMN_SRCH) + cs_get_channel_from_found_list (); + else + cs_clear_channel_from_found_list(); + } + + att_init_cell_selection (CELL_SELECTION, originator); + + /* Reset scan mode */ + rr_data->cs_data.scan_mode = CS_FIRST_SCAN_FIRST_ATTEMPT; + + /* + * init process and start power measurements + */ + #ifdef GPRS + rr_data->gprs_data.use_c31 = FALSE; + #endif + if(!parallel) + { + memset (rr_data->nc_data, 0, 6*sizeof (T_NC_DATA)); + cs_set_null (); + } + cs_set_all (); + + /* + * Why should a RR caused cell selection forego the helpfully information + * of the neighbor cell description of the last serving cell to speed up + * the selection of the new cell? + * But it is appropriate only for non PARALLEL search! + * Therefore we collect first the (at cs_data) stored cell discription + * and merge it into a channel list (cs_data.bcch_info). As second step + * we use this list to level up the priority of the matching cells after + * the scan execution (cs_mph_power_cnf). + */ + +#ifdef GPRS + if(att_gprs_is_avail() AND !parallel) + gprs_init_data_cr(); +#endif + + /* Cell Selection Improvements-LLD section:4.1.3.4.1.3 + * This function updates the new search mode based on the current + * dynamic search mode configuration + */ + att_check_dynamic_search_mode_config(); + + cs_start_scan (); + + if(!parallel) + { + if( GET_STATE(STATE_ATT) EQ ATT_CS_INIT ) + { + att_code_rr_act_cnf(); + } + else + { + SET_STATE (STATE_ATT, ATT_CS1); + } + dat_att_null(); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_try_old_cell | ++--------------------------------------------------------------------+ + + PURPOSE : if no suitable cell has been found during cell reselection + the old serving cell is tried. + +*/ + +static void att_try_old_cell (void) +{ + GET_INSTANCE_DATA; + UBYTE search_mode =0; + TRACE_FUNCTION ("att_try_old_cell()"); + + /* + * check whether the old serving cell is possible + */ + + if (rr_data->nc_data[SC_INDEX].arfcn EQ rr_data->nc_data[CR_INDEX].arfcn) + rr_data->ms_data.old_cell_tried = TRUE; + +/* Implements RR Clone findings #8 */ + if (! att_cell_barred_status_cr_no_cr (SC_INDEX) AND + ! is_tnnn (SC_INDEX) AND + rr_data->nc_data[SC_INDEX].c1 > 0 AND + rr_data->ms_data.old_cell_tried EQ FALSE) + + { + if (rr_data->sc_data.selection_type EQ CELL_RESELECTION_RACH) + { + /* + * go direct back to the old cell after random access failure + */ + att_return_to_idle(); + } + else + { + /* + * serving cell is possible. Configure layer 1 + * to start cell reselection + */ + rr_data->ms_data.old_cell_tried = TRUE; + att_start_cr_in_pl(SC_INDEX); + } + } + else + { + /* + * old serving cell is not possible. Then start + * cell selection for recovering. + */ + /* Refer Cell Selection Improvements-LLD section:4.1.3.9 */ + if(rr_data->ms_data.rr_service EQ FULL_SERVICE) + { + /* RR is in full service and in ATT_IDLE state. Cell reselection started + * and failed. Start Fast search + */ + search_mode = FAST_SEARCH_MODE; + } + else + { + if((rr_data->ms_data.rr_service EQ LIMITED_SERVICE) AND + (rr_data->ms_data.req_mm_service EQ FUNC_PLMN_SRCH)) + { + /* RR is in Limited service and in ATT_IDLE state. The requested service + * by MM is Full service. Cell reselection started and failed. + * Obtain new search mode based on the current search mode. + */ + search_mode = cs_get_new_search_mode(); + } + else + { + /* RR is in Limited service and in ATT_IDLE state. The requested service + * by MM is Limited service. Cell reselection started and failed. + * Start Normal search + */ + search_mode = NORMAL_SEARCH_MODE; + } + } + + /* XY:n don't inform GRR , and don't call start_cs_gprs !!! + * we can go here after sending a CR_IND but not being in CS3 + */ + att_start_cell_selection (RR_ORIGINATED, CS_NOT_PARALLEL,search_mode); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_mph_identity_req | ++--------------------------------------------------------------------+ + + PURPOSE : Forwards the mobile identities to Layer 1. + +*/ + +GLOBAL void att_mph_identity_req (void) +{ + GET_INSTANCE_DATA; + PALLOC (mph_identity_req, MPH_IDENTITY_REQ); + + TRACE_FUNCTION ("att_mph_identity_req()"); + + memset (mph_identity_req, 0, sizeof (T_MPH_IDENTITY_REQ)); + + switch (rr_data->ms_data.rr_service) + { + case FULL_SERVICE: + /* + * identities are only forwarded in full service + */ + if (rr_data->ms_data.imsi_available) + { + /* + * fill in the international mobile identity, if available + */ + mph_identity_req->mid.len_imsi = rr_data->ms_data.imsi.c_ident_dig; + memcpy (mph_identity_req->mid.imsi, rr_data->ms_data.imsi.ident_dig, + mph_identity_req->mid.len_imsi); + } + + if (rr_data->ms_data.tmsi_available) + { + /* + * fill in the temporary mobile identity, if available + */ + mph_identity_req->mid.v_tmsi = TRUE; + mph_identity_req->mid.tmsi = rr_data->ms_data.tmsi_binary; + } + break; + } +#ifdef GPRS + if (rr_data->gprs_data.gprs_indic) + { + att_add_ptmsi (mph_identity_req); + { + PALLOC(ms_id, RRGRR_MS_ID_IND); + ms_id->tmsi = rr_data->ms_data.tmsi_binary; + PSENDX(GRR, ms_id); + } + } +#endif + + /* + * send the valid identities to layer 1. + */ + PSENDX (PL, mph_identity_req); + +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_start_registration_timer | ++--------------------------------------------------------------------+ + + PURPOSE : Checks whether to start, to stop or to let run the + registration timer depending on the requested service by MM + and the actual RR service. + +*/ + +/* + * Time tables with increasing periods depending on the registration attempt + */ +#ifdef TI_PS_FF_AT_P_CMD_CTREG +/* Initialize the table with default values + * All the values are in secs / 10 format + * Ex: T_TEN_SEC = 10 Sec / 10 + */ +const UBYTE no_service_mode_time [25] = +{ T_TEN_SEC, T_TEN_SEC, T_TEN_SEC, T_TEN_SEC, + T_TWENTY_SEC, T_TWENTY_SEC, T_TWENTY_SEC, T_TWENTY_SEC, T_TWENTY_SEC, + T_THIRTY_SEC, T_THIRTY_SEC, T_THIRTY_SEC, T_THIRTY_SEC, T_THIRTY_SEC, + T_SIXTY_SEC, T_SIXTY_SEC, T_SIXTY_SEC, T_SIXTY_SEC, T_SIXTY_SEC, + T_TWO_MIN, T_TWO_MIN, T_TWO_MIN, T_TWO_MIN, T_TWO_MIN, + T_SIX_MIN +}; +#else +const T_TIME no_service_mode_time [25] = +{ TEN_SEC, TEN_SEC, TEN_SEC, TEN_SEC, + TWENTY_SEC, TWENTY_SEC, TWENTY_SEC, TWENTY_SEC, TWENTY_SEC, + THIRTY_SEC, THIRTY_SEC, THIRTY_SEC, THIRTY_SEC, THIRTY_SEC, + SIXTY_SEC, SIXTY_SEC, SIXTY_SEC, SIXTY_SEC, SIXTY_SEC, + TWO_MIN, TWO_MIN, TWO_MIN, TWO_MIN, TWO_MIN, + SIX_MIN +}; +#endif /* TI_PS_FF_AT_P_CMD_CTREG */ + +#ifdef TI_PS_FF_AT_P_CMD_CTREG +const UBYTE lim_service_mode_time [25] = +{ T_TEN_SEC, T_TEN_SEC, T_TEN_SEC, T_TEN_SEC, + T_TWENTY_SEC, T_TWENTY_SEC, T_TWENTY_SEC, T_TWENTY_SEC, T_TWENTY_SEC, + T_THIRTY_SEC, T_THIRTY_SEC, T_THIRTY_SEC, T_THIRTY_SEC, T_THIRTY_SEC, + T_SIXTY_SEC, T_SIXTY_SEC, T_SIXTY_SEC, T_SIXTY_SEC, T_SIXTY_SEC, + T_TWO_MIN, T_TWO_MIN, T_TWO_MIN, T_TWO_MIN, T_TWO_MIN, + T_SIX_MIN +}; +#else +const T_TIME lim_service_mode_time [25] = +{ TEN_SEC, TEN_SEC, TEN_SEC, TEN_SEC, + TWENTY_SEC, TWENTY_SEC, TWENTY_SEC, TWENTY_SEC, TWENTY_SEC, + THIRTY_SEC, THIRTY_SEC, THIRTY_SEC, THIRTY_SEC, THIRTY_SEC, + SIXTY_SEC, SIXTY_SEC, SIXTY_SEC, SIXTY_SEC, SIXTY_SEC, + TWO_MIN, TWO_MIN, TWO_MIN, TWO_MIN, TWO_MIN, + SIX_MIN +}; +#endif /* TI_PS_FF_AT_P_CMD_CTREG */ + +#ifdef TI_PS_FF_AT_P_CMD_CTREG +/* + * Function used to convert the user given TREG timer values in secs to ms + * Ex: User value TREG value + * 0 1 Sec + * 1 10 Sec + * 2 20 Sec etc + */ +T_TIME cast2T_Time(UBYTE tab_val) +{ + return (tab_val)? tab_val*10000: 1000; +} +#endif /* TI_PS_FF_AT_P_CMD_CTREG */ + +GLOBAL void att_start_registration_timer (void) +{ + GET_INSTANCE_DATA; + T_TIME status = 0L; + +#ifdef TI_PS_FF_AT_P_CMD_CTREG + BOOL ret; + UBYTE tab_val; +#endif /* TI_PS_FF_AT_P_CMD_CTREG */ + + TRACE_FUNCTION ("att_start_registration_timer()"); + + /* + * is there a TREG expiry which couldn't be handled yet + * so restart TREG with a short time + */ + if (rr_data->treg_pending) + { + TIMERSTART (TREG, ONE_SEC); + rr_data->treg_pending = FALSE; + return; + } + /* + * preparation to avoid the change of a running TREG + */ + TIMER_STATUS (rr_handle, TREG, &status); + /* + * depending on the current service of RR + */ + switch (rr_data->ms_data.rr_service) + { + case NO_SERVICE: + /* + * RR has no service, so it will try to come back + * to limited or full service after timeout + * set fieldstrength to 0. + */ +#ifdef FF_PS_RSSI + RX_SetValue ( 0, RX_QUAL_UNAVAILABLE, RX_ACCE_UNAVAILABLE); +#else + RX_SetValue (0); +#endif + cs_set_all (); + if (status) + return; + + if (!IS_TIMER_ACTIVE(TREG)) + { +#ifdef TI_PS_HCOMM_CHANGE + PSIGNAL (_hCommDL, DL_TRACE_REQ, NULL); +#else + PSIGNAL (hCommDL, DL_TRACE_REQ, NULL); +#endif /* TI_PS_HCOMM_CHANGE */ + } +#ifdef TI_PS_FF_AT_P_CMD_CTREG + ret = cl_shrd_get_treg(RR_MOD_NOSERVICE_TIME, + rr_data->ms_data.reg_counter, + &tab_val); + TRACE_EVENT_P1("Reading of the TREG value is %s",ret? "SUCCESS":"FAILURE"); + if (!ret) + { + /* Use default on failure */ + tab_val = no_service_mode_time [rr_data->ms_data.reg_counter]; + } + if (rr_data->ms_data.reg_counter < 24) + { + rr_data->ms_data.reg_counter++; + } + TIMERSTART (TREG, cast2T_Time(tab_val)); +#else + if (rr_data->ms_data.reg_counter < 24) + { + TIMERSTART (TREG, no_service_mode_time [rr_data->ms_data.reg_counter++]); + } + else + { + TIMERSTART (TREG, no_service_mode_time [24]); + } +#endif /* TI_PS_FF_AT_P_CMD_CTREG */ + break; + case LIMITED_SERVICE: + /* + * RR has limited service + * The timer is only started if MM has requested Full Service. + */ + if (rr_data->ms_data.req_mm_service EQ FUNC_PLMN_SRCH) + { + cs_set_all (); + if (status) + return; +#ifdef TI_PS_FF_AT_P_CMD_CTREG + ret = cl_shrd_get_treg(RR_MOD_LIMSERVICE_TIME, + rr_data->ms_data.reg_counter, + &tab_val); + TRACE_EVENT_P1("Reading of the TREG value is %s",ret? "SUCCESS":"FAILURE"); + if (!ret) + { + /* Use default on failure */ + tab_val = lim_service_mode_time [rr_data->ms_data.reg_counter]; + } + if (rr_data->ms_data.reg_counter < 24) + { + rr_data->ms_data.reg_counter++; + } + TIMERSTART (TREG, cast2T_Time(tab_val)); +#else + if (rr_data->ms_data.reg_counter < 24) + { + TIMERSTART (TREG, lim_service_mode_time [rr_data->ms_data.reg_counter++]); + } + else + { + TIMERSTART (TREG, lim_service_mode_time [24]); + } +#endif /* TI_PS_FF_AT_P_CMD_CTREG */ + } + break; + case FULL_SERVICE: + /* + * In full service mode, the timer is not started. + */ + TIMERSTOP (TREG); + break; + } +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_set_func | ++--------------------------------------------------------------------+ + + PURPOSE : Sets the requested MM functionality. If MM requests a + PLMN available search (FUNC_NET_SRCH_BY_MMI) the current + search request must be stored until the PLMN available + search has been finished. + +*/ + +GLOBAL void att_set_func (UBYTE func) +{ + GET_INSTANCE_DATA; + +#if !defined(NTRACE) + TRACE_EVENT_P5 ("att_set_func: func op=%s %scurrent=%s, service:rMM=%s RRs=%s", + _rr_str_FUNC[func], + _rr_str_PARFUNC[rr_data->ms_data.parallel_net_plmn_search_type], + _rr_str_FUNC[rr_data->ms_data.current_plmn_search_type], + _rr_str_FUNC[rr_data->ms_data.req_mm_service], + _rr_str_SERVICE[rr_data->ms_data.rr_service]); + + if ((func EQ FUNC_NET_SRCH_BY_MMI) AND + (func NEQ rr_data->ms_data.parallel_net_plmn_search_type)) + { + TRACE_EVENT_P2 ("att_set_func: NEW %scurrent=%s", + _rr_str_PARFUNC[func], + _rr_str_FUNC[rr_data->ms_data.current_plmn_search_type]); + } + else if ((func NEQ rr_data->ms_data.current_plmn_search_type) OR + (rr_data->ms_data.parallel_net_plmn_search_type NEQ 0)) + { + TRACE_EVENT_P1 ("att_set_func: NEW current=%s", _rr_str_FUNC[func]); + } +#endif /* !NTRACE */ + + switch (func) + { + case FUNC_LIM_SERV_ST_SRCH: + case FUNC_PLMN_SRCH: + case FUNC_ST_PWR_SCAN: + rr_data->ms_data.parallel_net_plmn_search_type = 0; + rr_data->ms_data.current_plmn_search_type = func; + break; + + case FUNC_NET_SRCH_BY_MMI: + rr_data->ms_data.parallel_net_plmn_search_type = func; + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_get_func | ++--------------------------------------------------------------------+ + + PURPOSE : Requests the MM functionality. If a temporary PLMN available + search request is active (temp_func = FUNC_NET_SRCH_BY_MMI) + this function is returned, else the last one which was + requested by MMI. + +*/ + +static UBYTE att_get_func (void) +{ + GET_INSTANCE_DATA; + switch (rr_data->ms_data.parallel_net_plmn_search_type) + { + case FUNC_NET_SRCH_BY_MMI: + return (rr_data->ms_data.parallel_net_plmn_search_type); + + default: + return (rr_data->ms_data.current_plmn_search_type); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_clear_parallel_search | ++--------------------------------------------------------------------+ + + PURPOSE : Resets the temporary requested MM functionality. + +*/ + +static void att_clear_parallel_search (void) +{ + GET_INSTANCE_DATA; + rr_data->ms_data.parallel_net_plmn_search_type = 0; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_init_cr_data | ++--------------------------------------------------------------------+ + + PURPOSE : The CR index contains the whole data of the new cell. + It is cleared prior to cell reselection +*/ + +GLOBAL void att_init_cr_data (void) +{ + GET_INSTANCE_DATA; + /* + * clear sys info bitmap + */ + rr_data->cr_data.cd.sys_info_read = NO_SYS_INFO_READ; + + /* + * reset BA list from SI 2, 2Bis and 2Ter + */ + memset(&rr_data->cr_data.cr_white_list, 0 , sizeof(T_CR_WHITE_LIST)); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_cr_data | ++--------------------------------------------------------------------+ + + PURPOSE : The CR index contains the whole data of the new cell. + It shall replace the content of the old serving cell. + The content of the old serving cell is copied to the + column of the new cell (in the neighbour cell area). The + status is set to DECODED. + +*/ + +GLOBAL void att_copy_cr_data (void) +{ + GET_INSTANCE_DATA; + UBYTE i; + + /* + * look for all neighbourcells. + */ + for (i=0;i<6;i++) + if (rr_data->nc_data[CR_INDEX].arfcn EQ rr_data->nc_data[i].arfcn) + { + /* + * channel found, then update neighbourcell + */ + memcpy (&rr_data->nc_data[i], &rr_data->nc_data[SC_INDEX], + sizeof (T_NC_DATA)); + rr_data->nc_data[i].bcch_status = DECODED; + rr_data->old_serving_cell = i; + break; + } + + /* + * update SC_INDEX column. + */ + memcpy (&rr_data->nc_data[SC_INDEX], &rr_data->nc_data[CR_INDEX], + sizeof (T_NC_DATA)); + /* + * implementation problem: must be set for RR originated search + * e.g. limited to full service + */ + rr_data->nc_data[SC_INDEX].bcch_status = DECODED; + + /* + * fit classmarks depend on the values of 'std' and the new serving cell + */ + rr_csf_fit_capability (); +#if defined (REL99) && defined (TI_PS_FF_EMR) + /*When there's no SI-2quater in the reselected cell and in the current + cell the reporting is of enhanced type, we can no longer use these + enhanced parameters. */ + /*Reset EMR data and indicate the same to GRR and ALR*/ + if ( rr_data->sc_data.emr_data_current.is_data_valid EQ TRUE ) + { + memset (rr_data->sc_data.rep_count, NOT_PRESENT_8BIT, MAX_NEIGHBOURCELLS); + for_set_default_emr_data(&rr_data->sc_data.emr_data_current); + for_send_enh_para(&rr_data->sc_data.emr_data_current); + } +#endif +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_eplmn_list | ++--------------------------------------------------------------------+ + + PURPOSE : This function copies the EPLMN list to rr_data global area + +*/ + +GLOBAL void att_copy_eplmn_list (T_eq_plmn_list *eq_plmn_list) +{ + GET_INSTANCE_DATA; + UBYTE i; + + /* List only copied if valid and PLMNs greater than 1 (HPLMN included) + else EPLMN list is marked as invalid */ + if(eq_plmn_list->v_eq_plmn) + { + for(i=0;i<RR_EPLMNLIST_SIZE;i++) + { + T_plmn local_copy; + rr_unpack_plmn(&local_copy, eq_plmn_list->eq_plmn, i); + rr_data->ms_data.eq_plmn_list[i] = local_copy; /*Struct copy*/ + } + + rr_data->ms_data.v_eq_plmn = TRUE; + } + else + { + rr_data->ms_data.v_eq_plmn = FALSE; + memset(&rr_data->ms_data.eq_plmn_list, 0xFF, SIZE_EPLMN); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : rr_unpack_plmn | ++--------------------------------------------------------------------+ + + PURPOSE : Unpacks a PLMN from compressed form to uncompressed form. + +*/ + +LOCAL void rr_unpack_plmn (T_plmn *plmn, const UBYTE *packed, USHORT index) +{ + index *= UBYTES_PER_PLMN; + plmn->mcc[0] = packed[index] & 0x0f; + plmn->mcc[1] = packed[index] >> 4; + index++; + plmn->mcc[2] = packed[index] & 0x0f; + plmn->mnc[2] = packed[index] >> 4; + index++; + plmn->mnc[0] = packed[index] & 0x0f; + plmn->mnc[1] = packed[index] >> 4; + index++; + if ((plmn->mcc[0] & 0x0F) EQ 0x0F) + plmn->v_plmn = V_PLMN_NOT_PRES; + else + plmn->v_plmn = V_PLMN_PRES; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_build_back_from_dedicated | ++--------------------------------------------------------------------+ + + PURPOSE : A list is build containing the serving cell followed by + the synchronized neighbourcells in decreasing fieldstrenght. + In case of call re-establishment the serving cell is not used. + The list controls the cell reselection after dedicated mode. + +*/ + +static void att_build_back_from_dedicated (void) +{ + GET_INSTANCE_DATA; + UBYTE i; + T_NC_DATA * rrd; + + /* + * update the neighbourcell entries + */ + for (i=0;i<6;i++) + { + /* + * clear the data for this neighbourcell + */ + memset (&rr_data->nc_data[i], 0, sizeof (T_NC_DATA)); + rrd = &rr_data->nc_data[i]; + if (rr_data->ms_data.measurement_report.ncells.no_of_ncells > i) + { + /* + * if neighbourcell data is available in the measurement report + * copy the data. + */ + rrd->bsic = rr_data->ms_data.measurement_report.ncells.bsic[i]; + rrd->arfcn = rr_data->ms_data.measurement_report.ncells.arfcn[i]; + rrd->rxlev = rr_data->ms_data.measurement_report.ncells.rx_lev[i]; + rrd->bcch_status = NON_DECODED; + rrd->avail_time = 0; + } + else + rrd->bcch_status = EMPTY; + } + + /* + * update the serving cell fieldstrength data. + * It is important to make distinction between rxlev of the traffic channel and of the BCCH channel + * for C1 and C2 calculations + */ + rr_data->nc_data[SC_INDEX].rxlev = rr_data->ms_data.measurement_report.bcch_rxlev_of_sc; + + /* + * implementation problem: must be set to have a defined status. + */ + rr_data->nc_data[SC_INDEX].bcch_status = DECODED; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_network | ++--------------------------------------------------------------------+ + + PURPOSE : This function is a SW shield for the FTA campaign. Due + to bad cables and public networks with high fieldstrength + some FTA testcases (especially MM testcases with limited + services) fails on our Anite System. To avoid this these + function is a SW shield, excluding all german networks. + + This function must be adapted for other countries if needed. + +*/ + +GLOBAL UBYTE att_check_network (T_loc_area_ident * lai) +{ + GET_INSTANCE_DATA; + UBYTE count=0; + /* + * if a test SIM is inserted and "Software Shielding" is enabled then check mcc value with stored mcc value + * (durig dynamic configuration command shield).The network exists in the list updated using dynamic + * configauration command SHIELD then return FALSE. + */ + if ((test_house EQ TRUE) AND (rr_data->dyn_config.mcc_shield.enabled EQ TRUE)) + { + for(count=0;count< MAX_MCC_SHIELD;count++) + { + if (lai->mcc[0] EQ rr_data->dyn_config.mcc_shield.mcc[count][0] AND + lai->mcc[1] EQ rr_data->dyn_config.mcc_shield.mcc[count][1] AND + lai->mcc[2] EQ rr_data->dyn_config.mcc_shield.mcc[count][2] ) + { + TRACE_EVENT ("att_check_network() returns FALSE"); + return FALSE; + } + } + } + return TRUE; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_return_to_idle | ++--------------------------------------------------------------------+ + + PURPOSE : The functions configures PL for idle mode without going + through a complete cell reselection. + +*/ + +GLOBAL void att_return_to_idle (void) +{ + GET_INSTANCE_DATA; + + TIMERSTOP (T_RESELECT); + /* + * configure layer 1 + */ +#ifdef GPRS + if(att_gprs_cell_has_pbcch()) + { + att_gprs_stop_pl(); + } + else + { +#endif + att_build_idle_req (SC_INDEX, MODE_CELL_SELECTION); +#ifdef GPRS + } +#endif + + SET_STATE (STATE_ATT, ATT_IDLE); + dat_att_cell_selected(); + srv_use_stored_prim (); +#ifdef REL99 +#ifdef GPRS + /* RR is returning to idle mode. If cbch info was received + * during transfer mode, send it now. + */ + if(rr_data->gprs_data.cbch_info_rxvd_in_ptm) + { + rr_data->gprs_data.cbch_info_rxvd_in_ptm = FALSE; + att_config_cbch(); + } +#endif +#endif + /* + * Start registration timer if needed + */ + att_start_registration_timer (); + + rr_data->bcch_error = 0; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_notify_stop_plmn_search | ++--------------------------------------------------------------------+ + + PURPOSE : Network search has to be aborted in lower layer so that + NC monitoring can be resumed when going back to idle mode. +*/ + +GLOBAL void att_notify_stop_plmn_search (UBYTE deactivate_pl) +{ + GET_INSTANCE_DATA; + UCHAR state = GET_STATE (STATE_ATT); + + TRACE_EVENT_P1("att_notify_stop_plmn_search - %x", rr_data->start_cell_reselection); + + if ( rr_data->ms_data.req_mm_service EQ FUNC_NET_SRCH_BY_MMI OR + (rr_data->ms_data.rr_service EQ LIMITED_SERVICE AND !rr_data->start_cell_reselection) OR + (rr_data->ms_data.rr_service EQ NO_SERVICE AND !rr_data->start_cell_reselection) OR + state EQ ATT_CS1 OR + state EQ ATT_CS2 OR + CS_GET_CURRENT_SEARCH_MODE EQ BLACK_LIST_SEARCH_MODE) + { + PALLOC (mph_sync_req, MPH_SYNC_REQ); + + if(deactivate_pl) + mph_sync_req->cs = CS_STOP_PLMN_SEARCH_AND_DEACTIVATE; + else + mph_sync_req->cs = CS_STOP_PLMN_SEARCH; + + PSENDX (PL, mph_sync_req); + + rr_data->start_cell_reselection = TRUE; + + TRACE_EVENT_P1("Start_cell_reselection %d",rr_data->start_cell_reselection); + + } +} + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_reset_old_lai | ++--------------------------------------------------------------------+ + + PURPOSE : This function is used to reset old lai parameters +*/ + +GLOBAL void att_reset_old_lai_rac () +{ + GET_INSTANCE_DATA; + rr_data->old_cell_id = NOT_PRESENT_16BIT; +#ifdef GPRS + rr_data->old_rac = NOT_PRESENT_8BIT; +#endif + memset (&rr_data->old_lai, NOT_PRESENT_8BIT, sizeof(T_loc_area_ident)); + +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_copy_old_lai_rac | ++--------------------------------------------------------------------+ + + PURPOSE : This function is used to copy old lai and rac parameters +*/ + +GLOBAL void att_copy_old_lai_rac (U8 index) +{ + GET_INSTANCE_DATA; + memcpy (&rr_data->old_lai, &rr_data->nc_data[index].lai, + sizeof(T_loc_area_ident)); + rr_data->old_cell_id = rr_data->nc_data[index].cell_id; +#ifdef GPRS + rr_data->old_rac = rr_data->nc_data[index].rac; +#endif +} + +/* ++--------------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_check_dynamic_search_mode_config | ++--------------------------------------------------------------------------------+ + + PURPOSE : This function updates the new search mode based on the current + dynamic search mode configuration + CSI-LLD section:4.1.3.4.1.8 +*/ + +GLOBAL void att_check_dynamic_search_mode_config(void) +{ + GET_INSTANCE_DATA; + U8 new_mode = CS_GET_CURRENT_SEARCH_MODE; + + TRACE_FUNCTION("att_check_dynamic_search_mode_config()"); + + TRACE_EVENT_P1("New Search Mode : %d", CS_GET_CURRENT_SEARCH_MODE); + + if(new_mode EQ FAST_SEARCH_MODE AND !rr_data->dyn_config.tfast_cs_val) + { + /* If Fast search is disabled, use Normal search */ + new_mode = NORMAL_SEARCH_MODE; + + TRACE_EVENT("Fast Search is disabled"); + } + + if(new_mode EQ NORMAL_SEARCH_MODE AND !rr_data->dyn_config.tnormal_cs_val) + { + /* If Normal search is disabled, use Full search */ + new_mode = FULL_SEARCH_MODE; + + TRACE_EVENT("Normal Search is disabled"); + } + + if(new_mode NEQ CS_GET_CURRENT_SEARCH_MODE) + TRACE_EVENT_P1("Allowed Search Mode : %d", new_mode); + + CS_SET_CURRENT_SEARCH_MODE(new_mode); + +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_get_txpwr_max_cch | ++--------------------------------------------------------------------+ + + PURPOSE : This function is used to calculate the MAX power used on CCH +*/ + +LOCAL UBYTE att_get_txpwr_max_cch (UBYTE index) +{ + GET_INSTANCE_DATA; + UBYTE max_cch = rr_data->nc_data[index].select_para.ms_txpwr_max_cch; + UBYTE dbm_value; + + TRACE_FUNCTION("att_get_txpwr_max_cch()"); + + switch(std) + { + case STD_1800: + case STD_DUAL_EGSM: + case STD_DUAL: +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT + case STD_850_1800: + case STD_850_900_1800: +#endif + /* Ref 04.18 Section 10.5.2.35 + * Rest Octets IE includes parameters which are used by the mobile station + * for cell selection and reselection purposes. It may also include the + * POWER OFFSET parameter used by DCS 1800 Class 3 MS. + */ + if (INRANGE(LOW_CHANNEL_1800,rr_data->nc_data[index].arfcn,HIGH_CHANNEL_1800)) + { + /* DCS 1800 */ + if (att_get_power() EQ 0x02 AND + rr_data->nc_data[index].c2_par.power_off_ind) + { + TRACE_EVENT(" IDLE_REQ :DCS_PCLASS3"); + /* Class 3 & Valid Power offset */ + dbm_value = p_control_dcs[max_cch] + + (rr_data->nc_data[index].c2_par.power_off << 1); + + /* dbm value is more than 36 return the max cch power level as 29 */ + if(dbm_value > 36) return 29; + + if(dbm_value NEQ 0) + { + /* map the calculated dbm value to power control value + * Specification : 0505 Section : 4.1.1 + */ + max_cch = (30 - dbm_value) >= 0 ? + (30 - dbm_value) >> 1 : + (31 - ((dbm_value - 32) >> 1)); + } + } /* if att_get_power */ + } /* if INRANGE */ + break; + default : + break; + } /* switch std */ + return max_cch; +} + + + +#if !defined(NTRACE) +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_print_mcc_mnc | ++--------------------------------------------------------------------+ + + PURPOSE : Outputs to trace mcc and mnc arrays + +*/ +/* Implements Measure#32: Row 52,53, 124 & 125 */ +GLOBAL void att_print_mcc_mnc (USHORT arfcn, UBYTE *mcc, UBYTE *mnc, T_S2I_STRING titel) +{ + TRACE_EVENT_P8 ( "[%d] MCC=%x%x%x MNC=%x%x%x %s", + ((int)arfcn), mcc[0], mcc[1], mcc[2], mnc[0], mnc[1], mnc[2], + S2I_STRING(titel)); /* A valid string is expected */ +} + +LOCAL void att_print_selection_type (UBYTE selection_type) +{ + GET_INSTANCE_DATA; + switch (rr_data->sc_data.selection_type) + { + case CELL_SELECTION: + TRACE_EVENT_WIN ("selection_type=CELL_SELECTION"); + break; + case CELL_RESELECTION: + TRACE_EVENT_WIN ("selection_type=CELL_RESELECTION"); + break; + case BACK_FROM_DEDICATED: + TRACE_EVENT_WIN ("selection_type=BACK_FROM_DEDICATED"); + break; + case CELL_RESELECTION_NC: + TRACE_EVENT_WIN ("selection_type=CELL_RESELECTION_NC"); + break; + case BACK_FROM_DEDICATED_RLF: + TRACE_EVENT_WIN ("selection_type=BACK_FROM_DEDICATED_RLF"); + break; + case CELL_RESELECTION_RACH: + TRACE_EVENT_WIN ("selection_type=CELL_RESELECTION_RACH"); + break; + case CELL_RESELECTION_CR: + TRACE_EVENT_WIN ("selection_type=CELL_RESELECTION_CR"); + break; + } +} + +/* Implements Measure#32: Row 36, 39 and 40 */ +LOCAL void att_print_op (T_op *op, T_S2I_STRING titel) +{ + T_S2I_STRING sim, mode; + if (op->v_op) + { + sim = op->sim_ins ? (op->ts ? S2I_STRING("TEST") : S2I_STRING("NORMAL")) : S2I_STRING("NO"); + mode = op->m ? S2I_STRING("MAN") : S2I_STRING("AUTO"); + + TRACE_EVENT_P5 ("%s: SIM=%s mode=%s func=%s service=%s", + S2I_STRING(titel), + S2I_STRING(sim), + S2I_STRING(mode), + S2I_STRING(_rr_str_FUNC[op->func]), + S2I_STRING(_rr_str_SERVICE[op->service])); + } +} +#endif /* !NTRACE */ + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_set_rr_service_info | ++--------------------------------------------------------------------+ + + PURPOSE : Copies the RR related service info(service,PLMN,lac,cell_id) +*/ + +GLOBAL void att_set_rr_service_info (void) +{ + GET_INSTANCE_DATA; + + T_LOC_INFO loc_info; + loc_info.service_mode = rr_data->ms_data.rr_service; + if(rr_data->ms_data.rr_service NEQ NO_SERVICE) + { + loc_info.lac = rr_data->nc_data[SC_INDEX].lai.lac; + loc_info.cell_id = rr_data->nc_data[SC_INDEX].cell_id; + memcpy (loc_info.mcc,rr_data->nc_data[SC_INDEX].lai.mcc,SIZE_MCC); + memcpy (loc_info.mnc,rr_data->nc_data[SC_INDEX].lai.mnc,SIZE_MNC); + } + cl_shrd_set_loc(&loc_info); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_set_tim_advance_info | ++--------------------------------------------------------------------+ + + PURPOSE : Copies the Timing Advance info.ME_STATUS is presently using + only ME_STATUS_IDLE which is not as per the standard.We need to assign + me_status correctly. +*/ + +GLOBAL void att_set_tim_advance_info (void) +{ + GET_INSTANCE_DATA; + T_TIM_ADV tim_adv; + tim_adv.me_status = ME_STATUS_IDLE; + tim_adv.tm_adv = rr_data->sc_data.new_ta; + cl_shrd_set_tim_adv(&tim_adv); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_func1_opt | ++--------------------------------------------------------------------+ + + PURPOSE : This function sets the system information read flag of the passed + si_type . It saves the neighbour cell list or Merges it to previously + saved list if available. +*/ +LOCAL void att_copy_sys_info_2bis_2ter_par(UBYTE index,T_SI_TYPE si_type, + T_LIST *new_2_bis_ter_list, BUF_neigh_cell_desc *neigh_cell_desc, + UBYTE indicate_changes) +{ + GET_INSTANCE_DATA; + T_LIST new_list; + T_CELL_DATA *cd; + BOOL modified = FALSE; + + USHORT cur_si_type_read; /*Current SI type*/ + USHORT oth_si_type_read; /*The other SI type in this function */ + USHORT oth_si_to_clean;/*The other SI to clean in this function*/ + UCHAR si_type_msg; /* 2BIS or 2TER type msg*/ + + TRACE_FUNCTION("att_copy_sys_info_2bis_2ter_par()"); + + switch (index) + { + case SC_INDEX: + case CR_INDEX: + if(si_type EQ SI_TYPE_2BIS) + { + cur_si_type_read = SYS_INFO_2BIS_READ; + oth_si_type_read = SYS_INFO_2TER_READ; + oth_si_to_clean = IND_SI_2TER; + si_type_msg = SYS_INFO_2bis_MSG; + + } + else + { + cur_si_type_read = SYS_INFO_2TER_READ; + oth_si_type_read = SYS_INFO_2BIS_READ; + oth_si_to_clean = IND_SI_2BIS; + si_type_msg = SYS_INFO_2ter_MSG; + } + if (index EQ SC_INDEX) + { + cd = &rr_data->sc_data.cd; + if ((cd->sys_info_read & cur_si_type_read) EQ cur_si_type_read) + { + srv_copy_list (&cd->ncell_list, new_2_bis_ter_list, sizeof (T_LIST)); + att_clean_buf ((USHORT)(IND_SI_2 | oth_si_to_clean)); + cd->sys_info_read &= ~(SYS_INFO_2_READ | oth_si_type_read); + att_check_2ter_read (index); + } + else + srv_merge_list (&cd->ncell_list, new_2_bis_ter_list); + modified = TRUE; +#ifdef GPRS + rr_data->gprs_data.ba_bcch_modified= FALSE; +#endif + + } + else + { + cd = &rr_data->cr_data.cd; + /* + * merge 2bis list with the old neighbour cell list + */ + srv_copy_list (&new_list, &cd->ncell_list, + sizeof (T_LIST)); + srv_merge_list (&new_list, new_2_bis_ter_list); + + if (srv_compare_list (&cd->ncell_list, &new_list) EQ FALSE) + { + /* + * both lists are different + */ + srv_copy_list (&cd->ncell_list, &new_list, sizeof (T_LIST)); + modified = TRUE; + } + } + /* CSI-LLD section:4.1.1.11 + * This function Updates the black list with the BA list received in si2bis/ter + */ + cs_remove_BA_MA_from_black_list(rr_data->cs_data.region,&cd->ncell_list); + + dat_store_neigh_cell_desc (si_type_msg, index, + neigh_cell_desc, &cd->ncell_list); + /* + * Indicate that the system information type 2bis message has been read. + */ + att_set_sys_info_read (cur_si_type_read, index); + + /* + * forward new neighbour cell list to layer 1 + * if changes shall be indicated + */ + if (modified AND indicate_changes) + { + att_code_mph_ncell_req (index); + } + + break; + } +} + + + +#if defined (REL99) && defined (TI_PS_FF_EMR) +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : attf_send_enh_para_to_alr | ++--------------------------------------------------------------------+ + + PURPOSE : This function formats and sends a primitive with enhanced measurement + parameters. +*/ +GLOBAL void attf_send_enh_para_to_alr(UBYTE rep_type, T_enh_para_struct *p_src) +{ + + PALLOC(p_enh, MPH_ENHPARA_UPDATE_REQ); + TRACE_FUNCTION ("attf_send_enh_para_to_alr"); + p_enh->rep_type = rep_type; + p_enh->enh_para = *p_src; + PSENDX(PL,p_enh); + return; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_print_mcc_mnc | ++--------------------------------------------------------------------+ + + PURPOSE : Outputs to trace mcc and mnc arrays + +*/ +LOCAL void att_check_for_si5ter_and_enhpara (UBYTE old_index) +{ + GET_INSTANCE_DATA; + T_rr_enh_para *p_temp = &rr_data->sc_data.emr_data_temp; + T_rr_enh_para *p_cur = &rr_data->sc_data.emr_data_current; + + /*we have complete BA(SACCH) list (with or without SI-5 ter ) : we will + discard any enhanced para that are present in previous state which are + aligned to BA(BCCH)*/ + if (rr_data->sc_data.enh_para_status EQ ENH_PARA_IDLE ) + { + /*The enhanced parameters available are from different state, reset them*/ + for_set_default_emr_data(p_temp); + memset (rr_data->sc_data.rep_count, NOT_PRESENT_8BIT, MAX_NEIGHBOURCELLS); + for_set_default_emr_data(p_cur); + for_send_enh_para(p_cur); + rr_data->sc_data.enh_para_status = ENH_PARA_INVALID_STATE; + return; + } + if(old_index EQ rr_data->sc_data.ba_index) + { + /*Updation of enhanced cell list for EMR : we can receive + SI-5ter and MI in any random order*/ + if ( (rr_data->sc_data.emr_data_temp.is_data_valid EQ TRUE) AND + rr_data->sc_data.emr_data_temp.ba2bsic_map_pending ) + for_att_update_ba2bsic_mapping(&rr_data->sc_data.emr_data_temp); + else if ( (rr_data->sc_data.emr_data_current.is_data_valid EQ TRUE) AND + rr_data->sc_data.emr_data_current.ba2bsic_map_pending ) + for_att_update_ba2bsic_mapping(&rr_data->sc_data.emr_data_current); + + /*When BA(SACCH) is ready, check whether there are enhanced parameters in + temp that needs attention*/ + if ( (rr_data->sc_data.enh_para_status EQ ENH_PARA_DEDICATED) AND + (p_temp->is_data_valid EQ TRUE ) ) + { + /* This means enhanced parameters were received before BA list - so update + the enhanced list with actual ARFCN and update current EMR data*/ + if ( for_update_enh_cell_list( rr_data->act_ncell_list) EQ TRUE) + { + *p_cur = *p_temp; + if (p_cur->ba2bsic_map_pending EQ 0) /*send parameters when there are no more mapping pending*/ + for_send_enh_para(p_cur); + } + /*Reset temporary, irrespective of whether updation is succesful or not*/ + for_set_default_emr_data(p_temp); + } + else if (p_cur->is_data_valid EQ TRUE AND p_cur->ba2bsic_map_pending EQ 0) + for_send_enh_para(p_cur); + } + else + { + for_set_default_emr_data(p_temp); + for_set_default_emr_data(p_cur); + for_send_enh_para(p_cur); + } + return; +} +#endif + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : RR_ATT | +| STATE : code ROUTINE : att_update_std_band_indicator | ++--------------------------------------------------------------------+ + + PURPOSE : This function updates the std value depending upon the band + indicator value received in the SI1 or SI6 message. band + indicator will be ignored when received in the DCS 1800 or + PCS 1900 frequency band. Depending upon the std value region + will be updated. + +*/ +#ifdef TI_PS_FF_QUAD_BAND_SUPPORT +GLOBAL void att_update_std_band_indicator (UBYTE band_indicator) +{ + GET_INSTANCE_DATA; + UBYTE band_index = cs_get_band_index (rr_data->nc_data[SC_INDEX].arfcn); + UBYTE freq_bands; + UBYTE new_region = NOT_PRESENT_8BIT; + UBYTE mscr = 0; /* variable to hold msc release version*/ + + TRACE_FUNCTION ("att_update_std_band_indicator"); + + get_msc_release_version(&mscr); + TRACE_EVENT_P1("mscr (MSC release) version : 0x%X", mscr); + if (mscr NEQ MSCR_99) + { + TRACE_EVENT ("band indicator received when MSC release is not R99"); + TRACE_ERROR ("band indicator received when MSC release is not R99"); + return; + } + + if ((band_index EQ B_DCS_1800) OR (band_index EQ B_PCS_1900)) + { + TRACE_EVENT_P2 ("band indicator %x received in band %x", band_indicator, band_index); + return; + } + + rr_csf_get_freq_bands (&freq_bands); + if (band_indicator NEQ NOT_PRESENT_8BIT) + { + if (band_indicator EQ BAND_IND_1800) + { + if ((freq_bands & BAND_DCS_1800) EQ BAND_DCS_1800) + { + if (std EQ STD_DUAL_US) + { + std = STD_850_1800; + new_region = BOTH_REGIONS; + } + else if (std EQ STD_850_900_1900) + { + std = STD_850_900_1800; + new_region = BOTH_REGIONS; + } + } + } + else + { + if ((freq_bands & BAND_PCS_1900) EQ BAND_PCS_1900) + { + if (std EQ STD_DUAL_EGSM) + { + std = STD_900_1900; + new_region = BOTH_REGIONS; + } + else if (std EQ STD_850_900_1800) + { + std = STD_850_900_1900; + new_region = BOTH_REGIONS; + } + } + } + TRACE_EVENT_P1 ("Updated std to %x", std); + } + + if (new_region NEQ NOT_PRESENT_8BIT) + rr_data->cs_data.region = new_region; +} +#endif + +#endif /* RR_ATTF_C */