FreeCalypso > hg > fc-tourmaline
view src/g23m-gsm/alr3/alr_pch.c @ 221:5bf097aeaad7
LLS: when turning off all LEDs on boot, skip LED-C
Having LLS turn off LED-A and LED-B on boot is normally unnecessary
(they should already be off in Iota), but it is harmless, hence this
logic is kept for robustness. However, having LLS read-modify-write
the BCICTL2 register (to turn off LED-C) creates a potential race
condition with FCHG writes to this register, especially in the case
when baseband switch-on is caused by VCHG and charging is expected
to start right away. Furthermore, control of the charging LED itself
(on those hw targets that have it) is the responsibility of the FCHG
SWE, hence LLS should leave it alone.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 26 Apr 2021 21:55:13 +0000 |
parents | 3a14ee9a9843 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GSM-PS | Modul : ALR_PCH +----------------------------------------------------------------------------- | 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 Modul defines the SDL process PCH_Control. +----------------------------------------------------------------------------- */ #ifndef ALR_PCH_C #define ALR_PCH_C #define ENTITY_PL /*==== INCLUDES ===================================================*/ #include <string.h> #include <stdlib.h> #include <ctype.h> #include "typedefs.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_alr.h" #include "mon_alr.h" #include "pei.h" #include "tok.h" #include "pcm.h" #ifdef GPRS #include "alr_gprs.h" #endif #include "alr.h" #include "alr_em.h" /*==== EXPORT =====================================================*/ typedef enum { IMSI_TYPE_1=1, IMSI_TYPE_2 }T_IMSI_TYPE; typedef enum { TMSI_TYPE_1=4, TMSI_TYPE_2=8 }T_TMSI_TYPE; /*==== PRIVAT =====================================================*/ LOCAL BOOL pch_frm_chan_imsi (UBYTE *frame, UBYTE channel_needed, T_IMSI_TYPE imsi_type, UBYTE index, UBYTE *frame_start); LOCAL BOOL pch_tmsi_type (T_TMSI_TYPE tmsi_type, UBYTE *frame, UBYTE channel_needed); /*==== VARIABLES ==================================================*/ UBYTE page_mode_before_hplmn_search = PGM_NORMAL; /*==== CONSTANTS ==================================================*/ #define IMSI_ODD_FLAG 8 #define IMSI_EVEN_FLAG 0 #define IDENT_TYPE_MON 0 #define IDENT_TYPE_IMSI 1 #define IDENT_TYPE_IMEI 2 #define IDENT_TYPE_IMEISV 3 #define IDENT_TYPE_TMSI 4 #define END_MARK 0xF0 /*==== FUNCTIONS ==================================================*/ #define TRACING #if defined (TRACING) #define ALR_TRACE_PCH(a) ALR_TRACE(a) #else #define ALR_TRACE_PCH(a) #endif #ifdef TRACING #define ALR_TRACE_PCH_CONFIG(b,a,c,t,p,m) \ TRACE_EVENT_P6 ("MFRMS: %d AG_RES: %d COMB: %d GRP: %d PGRP: %d PI: %d",b,a,c,t,p,m) #define ALR_TRACE_PCH_PGM(p,x) \ TRACE_EVENT_P2 ("new_pgm: %d cur_pgm: %d",p,x) #define ALR_TRACE_PCH_IMSI() \ { for (i=0; i<alr_data->pch_data.imsi[0]+1;i++) { \ TRACE_EVENT_P2 ("imsi[%d]=%x",i,alr_data->pch_data.imsi[i]);} } #else #define ALR_TRACE_PCH_CONFIG(b,a,c,t,p,m) #define ALR_TRACE_PCH_PGM(p,x) #define ALR_TRACE_PCH_IMSI() #endif /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_init | +--------------------------------------------------------------------+ PURPOSE : Initialize PCH Control Process. */ GLOBAL void pch_init (void) { GET_INSTANCE_DATA; alr_data->pch_data.saved_page_mode = PGM_REORG; alr_data->pch_data.reorg_bcch_reading = FALSE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_start | +--------------------------------------------------------------------+ PURPOSE : Process signal pch_start from SDL process Main_Control. */ static const UBYTE PAG_BLOCK_TABLE [2][8] = { /* not combined ccch */ 9,8,7,6,5,4,3,2, /* combined ccch */ 3,2,1,1,1,1,1,1 }; /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_configure | +--------------------------------------------------------------------+ PURPOSE : Configutes L1 for paging. */ GLOBAL void pch_configure (T_MPH_IDLE_REQ *idle, UBYTE page_mode) { GET_INSTANCE_DATA; UBYTE pag_blocks_per_mfr; if(idle NEQ NULL) { alr_data->pch_data.dlt = idle->dlt; alr_data->pch_data.act_dlt = idle->dlt; ALR_EM_SET_EM_ACT_DLT; pag_blocks_per_mfr = PAG_BLOCK_TABLE [idle->comb_ccch][idle->bs_ag_blocks_res]; /* * pl_idle.bs_pa_mfrms has a range from 2-9. * MPH_IDLE_REQ codes them from 0-7 */ alr_data->pch_data.pl_idle.bs_pa_mfrms = (UBYTE)(idle->bs_pa_mfrms + 2); alr_data->pch_data.pl_idle.bs_ag_blks_res = idle->bs_ag_blocks_res; alr_data->pch_data.pl_idle.bcch_combined = idle->comb_ccch; alr_data->pch_data.pl_idle.ccch_group = (UBYTE)(idle->tn / 2); alr_data->pch_data.pl_idle.page_group = idle->pg; alr_data->pch_data.pl_idle.page_block_index = (UBYTE)(idle->pg % pag_blocks_per_mfr); ALR_TRACE_PCH_CONFIG(idle->bs_pa_mfrms+2, idle->bs_ag_blocks_res, idle->comb_ccch, idle->tn/2, idle->pg, idle->pg % pag_blocks_per_mfr); } /* * During cell reselection reading of PCH is started hard coded with * page mode PGM_REORG because of the lack of parameters to calculate * the right paging group. Detection of SI3 during cell reselection * triggers the function pch_config_resel() to reconfigure PCH reading, * detection of a changed page mode during cell reselection is handled * by function pch_check_page_mode_cr() which needs to know whether SI3 * is read */ if (GET_STATE (STATE_MA) EQ MA_CELL_RESELECTION) alr_data->pch_data.si3_read = FALSE; /* Ensure that L1 does not get initialised with PAGING EXTENDED */ switch( page_mode ) { case SAVED_PGM: if( alr_data->pch_data.saved_page_mode EQ PGM_EXTENDED ) { alr_data->pch_data.saved_page_mode = PGM_REORG; } page_mode = alr_data->pch_data.saved_page_mode; /*lint -fallthrough*/ default: alr_data->pch_data.pl_idle.page_mode = page_mode; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_save_pgm | +--------------------------------------------------------------------+ PURPOSE : Configure Paging */ GLOBAL void pch_save_pgm(UBYTE mode) { GET_INSTANCE_DATA; if(mode) alr_data->pch_data.saved_page_mode = mode; else alr_data->pch_data.saved_page_mode = alr_data->pch_data.pl_idle.page_mode; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_start_ccch_req | +--------------------------------------------------------------------+ PURPOSE : Configure Paging */ GLOBAL void pch_start_ccch_req (void) { GET_INSTANCE_DATA; PALLOC(pl_idle, MPHC_START_CCCH_REQ); memset(pl_idle, 0, sizeof(T_MPHC_START_CCCH_REQ)); ALR_EM_PAGE_MODE_CHANGE; switch (alr_data->pch_data.pl_idle.page_mode) { case PGM_REORG: ALR_TRACE_PCH ("config REORG"); /* dummy values */ pl_idle->bs_pa_mfrms = 2; pl_idle->bs_ag_blks_res = 7; pl_idle->bcch_combined = 0; pl_idle->ccch_group = 0; pl_idle->page_group = 0; pl_idle->page_block_index = 0; pl_idle->page_mode = PGM_REORG; break; case PGM_REORG_CS: ALR_TRACE_PCH ("config REORG_CS"); memcpy (pl_idle, &alr_data->pch_data.pl_idle, sizeof (T_MPHC_START_CCCH_REQ)); /* * if the page_mode is PGM_REORG_CS then * we have to change this to PGM_REORG * before we send it to L1 */ pl_idle->page_mode = PGM_REORG; break; case PGM_EXTENDED: ALR_TRACE_PCH ("config EXT"); memcpy (pl_idle, &alr_data->pch_data.pl_idle, sizeof (T_MPHC_START_CCCH_REQ)); pl_idle->page_mode = PGM_EXTENDED; break; case PGM_REORG_NC_SYNC: /*this case is the same as the default - except for the TRACE*/ ALR_TRACE_PCH ("config PGM_REORG_NC_SYNC (NORMAL)"); memcpy (pl_idle, &alr_data->pch_data.pl_idle, sizeof (T_MPHC_START_CCCH_REQ)); pl_idle->page_mode = PGM_NORMAL; break; default: ALR_TRACE_PCH ("config NORMAL"); memcpy (pl_idle, &alr_data->pch_data.pl_idle, sizeof (T_MPHC_START_CCCH_REQ)); pl_idle->page_mode = PGM_NORMAL; break; } SET_STATE(STATE_PCH,PCH_ACTIVE); ma_pch_start_ccch_req(pl_idle); TRACE_EVENT_P1("reorg_bcch_reading = %d",alr_data->pch_data.reorg_bcch_reading); if(alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG OR alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_CS OR alr_data->pch_data.reorg_bcch_reading EQ TRUE) { /* * if we're going into reorg paging we also need to read the BCCH * to read possibly changed channel configuration * XXX but not at PGM_REORG_NC_SYNC (NORMAL) */ ma_scell_full_nbcch(); #if defined (REL99) && defined (TI_PS_FF_EMR) if (alr_data->nc_data.si2quater_status EQ SI2QUATER_CONFIGURE ) { if(alr_data->ma_data.sys_info_2quater[1] EQ D_SYS_INFO_2QUATER) { ma_send_stored_SI2qtr(&alr_data->ma_data.sys_info_2quater[0]); memset (alr_data->ma_data.sys_info_2quater, 0, 22); } alr_data->nc_data.si2quater_status = SI2QUATER_ACQ_FULL_BCCH; } #endif } else { /* * otherwise we stop the reading of the BCCH and start the periodic read. * XXX but not if we have a PBCCH */ #ifdef GPRS if(alr_data->gprs_data.pbcch EQ FALSE) #endif #if defined (REL99) && defined (TI_PS_FF_EMR) { TRACE_EVENT_P1("SI2qtr status: %d", alr_data->nc_data.si2quater_status); if ( (alr_data->nc_data.si2quater_status EQ SI2QUATER_ABSENT) OR (alr_data->nc_data.si2quater_status EQ SI2QUATER_ACQ_WRONG_BAIND) OR (alr_data->nc_data.si2quater_status EQ SI2QUATER_ACQ_COMP) ) sc_start_periodic(); else if ((alr_data->nc_data.si2quater_status EQ SI2QUATER_CONFIGURE ) OR (alr_data->nc_data.si2quater_status EQ SI2QUATER_ACQ_FULL_BCCH)) { if(alr_data->ma_data.sys_info_2quater[1] EQ D_SYS_INFO_2QUATER) { ma_send_stored_SI2qtr(&alr_data->ma_data.sys_info_2quater[0]); memset (alr_data->ma_data.sys_info_2quater, 0, 22); } if (alr_data->nc_data.si2quater_pos EQ SI2QUATER_ON_NBCCH) ma_scell_mon_si2quater_nbcch(); else ma_scell_mon_si2quater_ebcch(); alr_data->nc_data.si2quater_status = SI2QUATER_ACQ_PENDING; } } #else sc_start_periodic(); #endif } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_identity_req | +--------------------------------------------------------------------+ PURPOSE : Get new mobile identity information from RR. Build IMSI pattern and store TMSI. */ GLOBAL void pch_identity_req (T_MPH_IDENTITY_REQ *mph_identity_req) { GET_INSTANCE_DATA; UBYTE i; /* the IMSI in the identity request is coded as a 15byte long array and is stored for later usage in pch_data as the message representation of the IMSI according to GSM4.08 10.5.1.4 */ if (mph_identity_req->mid.len_imsi EQ 0) { /* * limited service, no paging */ memset (alr_data->pch_data.imsi, 0, IMSI_LEN); alr_data->pch_data.v_tmsi = FALSE; alr_data->pch_data.tmsi = 0L; } else { /* * The IMSI is available */ /* store length */ alr_data->pch_data.imsi[0] = (UBYTE)((mph_identity_req->mid.len_imsi + 2) / 2); if (mph_identity_req->mid.len_imsi & 1) { ALR_TRACE_PCH ("IMSI is odd"); /* * odd number of digits * first digit + odd flag + identity type IMSI */ alr_data->pch_data.imsi[1] = (UBYTE)((mph_identity_req->mid.imsi[0] << 4) + IMSI_ODD_FLAG + IDENT_TYPE_IMSI); } else { ALR_TRACE_PCH ("IMSI is even"); /* * even number of digits * first digit + even flag + identity type IMSI */ alr_data->pch_data.imsi[1] = (UBYTE)((mph_identity_req->mid.imsi[0] << 4) + IMSI_EVEN_FLAG + IDENT_TYPE_IMSI); } /* * fill in the rest of digits */ for (i=1;i<mph_identity_req->mid.len_imsi;i++) { if (i & 1) alr_data->pch_data.imsi[(i/2)+2] = (UBYTE)(END_MARK + mph_identity_req->mid.imsi[i]); else { alr_data->pch_data.imsi[(i/2)+1] &= ~END_MARK; /* remove end mark */ alr_data->pch_data.imsi[(i/2)+1] = (UBYTE)(alr_data->pch_data.imsi[(i/2)+1] + (mph_identity_req->mid.imsi[i] << 4)); } } alr_data->pch_data.imsi_mod_1000 = (SHORT) ( (mph_identity_req->mid.imsi[mph_identity_req->mid.len_imsi-1] + mph_identity_req->mid.imsi[mph_identity_req->mid.len_imsi-2] * 10 + mph_identity_req->mid.imsi[mph_identity_req->mid.len_imsi-3] * 100 ) % 1000); ALR_TRACE_PCH_IMSI(); /* * copy TMSI */ alr_data->pch_data.v_tmsi = mph_identity_req->mid.v_tmsi; alr_data->pch_data.tmsi = mph_identity_req->mid.tmsi; #ifdef GPRS gprs_alr_store_ptmsi(mph_identity_req->mid.v_ptmsi, mph_identity_req->mid.ptmsi); gprs_alr_store_ptmsi2(mph_identity_req->mid.v_ptmsi2, mph_identity_req->mid.ptmsi2); #endif } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_increment_dlt | +--------------------------------------------------------------------+ PURPOSE : Incrementation of downlink timeout counter after receiving a valid PCH block. */ GLOBAL void pch_increment_dlt (void) { GET_INSTANCE_DATA; if (alr_data->pch_data.act_dlt < alr_data->pch_data.dlt) { #if !defined NTRACE trc_mon_counter_idle (alr_data->pch_data.act_dlt, alr_data->pch_data.dlt); #endif /* (!defined NTRACE) */ alr_data->pch_data.act_dlt++; ALR_EM_SET_EM_ACT_DLT; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_decrement_dlt | +--------------------------------------------------------------------+ PURPOSE : Decrementation of downlink timeout counter after receiving an invalid PCH block. */ GLOBAL void pch_decrement_dlt (void) { GET_INSTANCE_DATA; if (alr_data->pch_data.act_dlt > 4) { #if !defined NTRACE trc_mon_counter_idle (alr_data->pch_data.act_dlt, alr_data->pch_data.dlt); #endif /* (!defined NTRACE) */ alr_data->pch_data.act_dlt -= 4; ALR_EM_SET_EM_ACT_DLT; } else { alr_data->pch_data.act_dlt = alr_data->pch_data.dlt; #if !defined NTRACE trc_mon_counter_idle (alr_data->pch_data.act_dlt, alr_data->pch_data.dlt); #endif ALR_EM_SET_EM_ACT_DLT; ALR_TRACE_PCH ("downlink fail"); ma_error_ind (CS_DOWN_LINK_FAIL, alr_data->serving_cell); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_check_page_mode | +--------------------------------------------------------------------+ PURPOSE : Check the page mode of an incoming unacknowledged message. */ static const UBYTE PAGE_MODE_CHANGE [3][4] = { /* old mode = paging normal */ NONE, SWAP_TO_EXTEND, SWAP_TO_REORG, NONE, /* old mode = extended paging */ SWAP_TO_NORMAL, NONE, SWAP_TO_REORG, NONE, /* old mode = paging reorganisation */ SWAP_TO_NORMAL, SWAP_TO_EXTEND, NONE, NONE }; GLOBAL void pch_check_page_mode (T_MPHC_DATA_IND *data_ind) { GET_INSTANCE_DATA; UBYTE page_mode; UBYTE cur_page_mode = alr_data->pch_data.pl_idle.page_mode; page_mode = (UBYTE)(data_ind->l2_frame.content [3] & 3); ALR_TRACE_PCH_PGM(page_mode, alr_data->pch_data.pl_idle.page_mode); /*if HPLMN search is going on and we should be in REORG, we are really in REORG_NC_SYNC (NORMAL). Otherwise we cannot synchronize to the NC's*/ if(alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_NC_SYNC) cur_page_mode = PGM_REORG; if(alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_CS) cur_page_mode = PGM_REORG; switch (PAGE_MODE_CHANGE [cur_page_mode][page_mode]) { case SWAP_TO_NORMAL: ALR_TRACE_PCH ("SWAP_TO_NORMAL"); alr_data->pch_data.pl_idle.page_mode = PGM_NORMAL; pch_start_ccch_req (); break; case SWAP_TO_EXTEND: ALR_TRACE_PCH ("SWAP_TO_EXT"); alr_data->pch_data.pl_idle.page_mode = PGM_EXTENDED; pch_start_ccch_req (); break; case SWAP_TO_REORG: ALR_TRACE_PCH ("SWAP_TO_REORG"); alr_data->pch_data.reorg_bcch_reading = TRUE; alr_data->pch_data.si_bitmap = 0; alr_data->pch_data.pl_idle.page_mode = PGM_REORG_CS; pch_start_ccch_req (); break; default: break; } } GLOBAL void pch_check_page_mode_cr (T_MPHC_DATA_IND *data_ind) { GET_INSTANCE_DATA; UBYTE page_mode; UBYTE cur_page_mode = alr_data->pch_data.saved_page_mode; UBYTE swap = TRUE; page_mode = (UBYTE)(data_ind->l2_frame.content [3] & 3); if(alr_data->pch_data.saved_page_mode EQ PGM_REORG_CS) cur_page_mode = PGM_REORG; switch (PAGE_MODE_CHANGE [cur_page_mode][page_mode]) { case SWAP_TO_NORMAL: ALR_TRACE_PCH ("CR:SWAP_TO_NORMAL"); alr_data->pch_data.saved_page_mode = PGM_NORMAL; break; case SWAP_TO_EXTEND: ALR_TRACE_PCH ("CR:SWAP_TO_EXT"); alr_data->pch_data.saved_page_mode = PGM_EXTENDED; break; case SWAP_TO_REORG: ALR_TRACE_PCH ("CR:SWAP_TO_REORG"); alr_data->pch_data.saved_page_mode = PGM_REORG_CS; break; default: swap = FALSE; break; } if (swap AND alr_data->pch_data.si3_read AND alr_data->pch_data.last_start_ccch_req.bs_pa_mfrms NEQ NOT_PRESENT_8BIT) { PALLOC(pl_idle, MPHC_START_CCCH_REQ); memcpy ( pl_idle, &(alr_data->pch_data.last_start_ccch_req), sizeof(T_MPHC_START_CCCH_REQ)); pl_idle->page_mode = alr_data->pch_data.saved_page_mode; ma_pch_start_ccch_req (pl_idle); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_check_pag_1 | +--------------------------------------------------------------------+ PURPOSE : The function checks a paging request type 1 message. */ GLOBAL void pch_check_pag_1 (T_MPHC_DATA_IND *data_ind) { GET_INSTANCE_DATA; UBYTE *frame = data_ind->l2_frame.content; UBYTE channel_needed; UBYTE *frame_start = data_ind->l2_frame.content; /*ALR_TRACE_PCH ("p1");*/ /* * Check only if IMSI available (len NEQ 0), * ti and pd = 0x06 and * l2 pseudolength is greater than 5 bytes */ if (alr_data->pch_data.imsi[0] AND frame[1] EQ 0x06 AND frame[0] > 0x15) { /* * store channel needed type */ channel_needed = frame[3]; /* * check type of identity for mobile identity 1 */ if(pch_frm_chan_imsi( frame, channel_needed, IMSI_TYPE_1, 5,frame_start)) return; /* * check type of identity for mobile identity 2 * set frame pointer to start of mobile identity 2 (id tag) * old frame pointer (frame) + * offset pseudo length etc (4) + * length mobile identity 1 (frame [4]) + * plus 1 byte for length field */ frame = frame + 4 + frame[4] + 1; if (frame[0] EQ 0x17) { /* * mobile identity 2 is available */ if(pch_frm_chan_imsi( frame, channel_needed, IMSI_TYPE_2, 2, frame_start)) return; } } //ALR_TRACE_PCH("end p1"); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_check_pag_2 | +--------------------------------------------------------------------+ PURPOSE : The function checks a paging request type 2 message. */ GLOBAL void pch_check_pag_2 (T_MPHC_DATA_IND *data_ind) { GET_INSTANCE_DATA; UBYTE *frame = data_ind->l2_frame.content; ULONG tmsi; UBYTE i; UBYTE channel_needed; /* * Check only if IMSI available (len NEQ 0) and * ti and pd = 0x06 and * l2 pseudolength is greater than 5 bytes */ if (alr_data->pch_data.imsi[0] AND frame[1] EQ 0x06 AND frame[0] > 0x15) { /* * store channel needed type */ channel_needed = frame[3]; /* * check mobile identity 1 only if TMSI is available */ if(pch_tmsi_type(TMSI_TYPE_1, frame, channel_needed)) return; #ifdef GPRS if(GET_STATE(STATE_MA) NEQ MA_CON_EST) { tmsi = 0L; for (i=0;i<4;i++) tmsi += frame[i+4] << (8*(3-i)); if(gprs_alr_check_ptmsi(tmsi)) return; } #endif /* * check mobile identity 2 only if TMSI is available */ if(pch_tmsi_type(TMSI_TYPE_2, frame, channel_needed)) return; #ifdef GPRS if(GET_STATE(STATE_MA) NEQ MA_CON_EST) { tmsi = 0L; for (i=0;i<4;i++) tmsi += frame[i+8] << (8*(3-i)); if(gprs_alr_check_ptmsi(tmsi)) return; } #endif if (frame[12] EQ 0x17) { /* * mobile identity 3 is available * calculation of channel needed for * mobile identity 3 from the rest octet. */ channel_needed = frame [ frame[13]+14 ]; if (channel_needed & 0x80) channel_needed = (UBYTE)((channel_needed >> 5) & 3); else channel_needed = 0; switch (frame [14] & 7) { case 1: /* * IMSI */ if (!memcmp (alr_data->pch_data.imsi, &frame[13], alr_data->pch_data.imsi[0]+1)) { /* * IMSI matches */ #ifdef GPRS if(! gprs_alr_check_packet_paging_2(frame,3)) #endif ma_pch_paging_ind (1, (UBYTE) channel_needed); #ifdef GPRS else if(GET_STATE(STATE_MA) NEQ MA_CON_EST) ma_pch_paging_ind (ID_IMSI, CN_PACKET); #endif return; } break; case 4: /* * TMSI */ if (alr_data->pch_data.v_tmsi) { tmsi = 0L; for (i=0;i<frame[13]-1;i++) tmsi += frame[i+15] << ((8*(frame[13]-2-i))); if (alr_data->pch_data.tmsi EQ tmsi) { /* * TMSI matches */ ma_pch_paging_ind (4, channel_needed); return; } #ifdef GPRS if(GET_STATE(STATE_MA) NEQ MA_CON_EST) { tmsi = 0L; for (i=0;i<frame[13]-1;i++) tmsi += frame[i+15] << ((8*(frame[13]-2-i))); if(gprs_alr_check_ptmsi(tmsi)) return; } #endif } break; } } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_check_pag_3 | +--------------------------------------------------------------------+ PURPOSE : The function checks a paging request type 3 message. */ GLOBAL void pch_check_pag_3 (T_MPHC_DATA_IND *data_ind) { GET_INSTANCE_DATA; UBYTE *frame = data_ind->l2_frame.content; ULONG tmsi; UBYTE i; UBYTE channel_needed; /* * Check only if IMSI available (len NEQ 0) and * ti and pd = 0x06 and * l2 pseudolength is greater than 5 bytes */ if (alr_data->pch_data.imsi[0] AND frame[1] EQ 0x06 AND frame[0] > 0x15) { /* * store channel needed type */ channel_needed = frame[3]; /* * check mobile identity 1 only if TMSI is available */ if(pch_tmsi_type(TMSI_TYPE_1, frame, channel_needed)) return; #ifdef GPRS if(GET_STATE(STATE_MA) NEQ MA_CON_EST) { tmsi = 0L; for (i=0;i<4;i++) tmsi += frame[i+4] << (8*(3-i)); if(gprs_alr_check_ptmsi(tmsi)) return; } #endif /* * check mobile identity 2 only if TMSI is available */ if(pch_tmsi_type(TMSI_TYPE_2, frame, channel_needed)) return; #ifdef GPRS if(GET_STATE(STATE_MA) NEQ MA_CON_EST) { tmsi = 0L; for (i=0;i<4;i++) tmsi += frame[i+8] << (8*(3-i)); if(gprs_alr_check_ptmsi(tmsi)) return; } #endif /* * calculation of channel needed for * mobile identity 3 and 4 from the rest octet. */ channel_needed = frame [ 20 ]; if (channel_needed & 0x80) channel_needed = (UBYTE)((channel_needed & 0x78) >> 3); else channel_needed = 0; /* * check mobile identity 3 only if TMSI is available */ if (alr_data->pch_data.v_tmsi) { tmsi = 0L; for (i=0;i<4;i++) tmsi += frame[i+12] << (8*(3-i)); if (alr_data->pch_data.tmsi EQ tmsi) { /* * TMSI matches */ ma_pch_paging_ind (4, (UBYTE)(channel_needed >> 2)); return; } #ifdef GPRS if(GET_STATE(STATE_MA) NEQ MA_CON_EST) { tmsi = 0L; for (i=0;i<4;i++) tmsi += frame[i+12] << (8*(3-i)); if(gprs_alr_check_ptmsi(tmsi)) return; } #endif } /* * check mobile identity 4 only if TMSI is available */ if (alr_data->pch_data.v_tmsi) { tmsi = 0L; for (i=0;i<4;i++) tmsi += frame[i+16] << (8*(3-i)); if (alr_data->pch_data.tmsi EQ tmsi) { /* * TMSI matches */ ma_pch_paging_ind (4, (UBYTE)(channel_needed & 3)); return; } } #ifdef GPRS if(GET_STATE(STATE_MA) NEQ MA_CON_EST) { tmsi = 0L; for (i=0;i<4;i++) tmsi += frame[i+16] << (8*(3-i)); if(gprs_alr_check_ptmsi(tmsi)) return; } #endif } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_stop | +--------------------------------------------------------------------+ PURPOSE : The function stops paging. */ GLOBAL void pch_stop(void) { GET_INSTANCE_DATA; if(GET_STATE(STATE_PCH) EQ PCH_ACTIVE) { SET_STATE(STATE_PCH,PCH_NULL); if(alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG OR alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_CS) { ALR_TRACE_PCH ("stop sc for pch"); ma_stop_scell_bcch_req(); } ma_pch_stop(); } } /*used for S13 - to stop BCCH reading*/ GLOBAL UBYTE pch_mode_reorg(void) { GET_INSTANCE_DATA; if(alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG OR alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_CS OR alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_NC_SYNC) return TRUE; else return FALSE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_no_of_paging_blocks | +--------------------------------------------------------------------+ PURPOSE : The function configures the paging reading during cell reselection when reveived a SI3 */ LOCAL SHORT pch_no_of_paging_blocks (UBYTE ccch_conf, UBYTE bs_ag_blks_res, UBYTE bs_pa_mfrms) { /* in according to GSM 4.08 section 10.5.2.11, table 10.5.33 */ if (ccch_conf EQ COMB_CCCH_COMB) { /* * combined CCCH, * * number of paging blocks = (3 - BS_AG_BLKS_RES) * BS_PA_MFRMS * * Maximum function only for security reasons, BCCH coding range is 0..7, * but allowed is only 0..2. */ return (( (1 > (UBYTE)(3 - bs_ag_blks_res) ? 1 : (UBYTE)(3 - bs_ag_blks_res)) ) * ((UBYTE)(2 + bs_pa_mfrms))); } else { /* * non-combined CCCH, * * number of paging blocks = (9 - BS_AG_BLKS_RES) * BS_PA_MFRMS */ return ((9 - bs_ag_blks_res) * (2 + bs_pa_mfrms)); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6103) MODULE : ALR_PCH | | STATE : code ROUTINE : pch_config_resel | +--------------------------------------------------------------------+ PURPOSE : The function configures the L1 PCH reading during cell reselection when reveived an SI3 */ GLOBAL void pch_config_resel (T_MPHC_DATA_IND *data_ind) { GET_INSTANCE_DATA; UBYTE *p_ctrl = &(data_ind->l2_frame.content[SI_CONTENTS_MSG_T+8]); UBYTE ccch_conf, bs_ag_blks_res, bs_pa_mfrms, pg, pag_blocks_per_mfr; SHORT n, b; PALLOC(pl_idle, MPHC_START_CCCH_REQ); memset(pl_idle, 0, sizeof(T_MPHC_START_CCCH_REQ)); bs_ag_blks_res = (UBYTE)(((*p_ctrl) & 0x38) >> 3); ccch_conf = (((*p_ctrl) & 0x07) EQ 0x01) ? COMB_CCCH_COMB : COMB_CCCH_NOT_COMB; p_ctrl++; bs_pa_mfrms = (UBYTE)(((*p_ctrl) & 0x07)); /* TRACE_EVENT_P5("pch_config_resel IE: %02x %02x bs_ag_blks_res=%u ccch_conf=%u bs_pa_mfrms=%u", data_ind->l2_frame.content[SI_CONTENTS_MSG_T+8], *p_ctrl, bs_ag_blks_res, ccch_conf, bs_pa_mfrms);*/ n = pch_no_of_paging_blocks (ccch_conf, bs_ag_blks_res, bs_pa_mfrms); b = ((ccch_conf / 2) + 1) * n; pg = (UBYTE) ((alr_data->pch_data.imsi_mod_1000 % b) % n); pag_blocks_per_mfr = PAG_BLOCK_TABLE [ccch_conf][bs_ag_blks_res]; pl_idle->bs_ag_blks_res = bs_ag_blks_res; pl_idle->bs_pa_mfrms = (UBYTE)(bs_pa_mfrms + 2); pl_idle->bcch_combined = ccch_conf; pl_idle->ccch_group = (UBYTE) ((alr_data->pch_data.imsi_mod_1000 % b) / n); pl_idle->page_group = pg; pl_idle->page_block_index = (UBYTE)(pg % pag_blocks_per_mfr); pl_idle->page_mode = (alr_data->pch_data.saved_page_mode EQ PGM_REORG_CS) ? PGM_REORG : alr_data->pch_data.saved_page_mode; /* TRACE_EVENT_P3("n=%u b=%u page_mode=%u", n, b, pl_idle->page_mode);*/ ma_pch_start_ccch_req(pl_idle); alr_data->pch_data.si3_read = TRUE; } /* +--------------------------------------------------------------------+ | PROJECT : MODULE : ALR_PCH | | STATE : code ROUTINE : pch_frm_chan_imsi | +--------------------------------------------------------------------+ PURPOSE : Function replacing the common switch-code in the function "pch_check_pag_1". This function checks for the IMSI types. */ LOCAL BOOL pch_frm_chan_imsi (UBYTE *frame, UBYTE channel_needed, T_IMSI_TYPE imsi_type, UBYTE index, UBYTE *frame_start) { GET_INSTANCE_DATA; UBYTE i; ULONG tmsi; ALR_TRACE_PCH ("pch_frm_chan_imsi"); switch (frame[index] & 7) { case 1: /* * IMSI */ if (!memcmp (alr_data->pch_data.imsi, &frame[index-1], alr_data->pch_data.imsi[0]+1)) { /*ALR_TRACE_PCH ("p1 IMSI match");*/ /* * IMSI matches */ if(imsi_type EQ IMSI_TYPE_1) { #ifdef GPRS if(! gprs_alr_check_packet_paging(frame_start,1)) #endif ma_pch_paging_ind (1, (UBYTE)((channel_needed & 0x30)>>4)); #ifdef GPRS else if(GET_STATE(STATE_MA) NEQ MA_CON_EST) ma_pch_paging_ind (ID_IMSI, CN_PACKET); #endif return TRUE; } else if(imsi_type EQ IMSI_TYPE_2) { #ifdef GPRS if(! gprs_alr_check_packet_paging(frame_start,2)) #endif ma_pch_paging_ind (1, (UBYTE)((channel_needed & 0xC0)>>6)); #ifdef GPRS else if(GET_STATE(STATE_MA) NEQ MA_CON_EST) ma_pch_paging_ind (ID_IMSI, CN_PACKET); #endif return TRUE; } } break; /* for case-1 */ case 4: /*ALR_TRACE_PCH ("p1 TMSI");*/ /* * TMSI */ if (alr_data->pch_data.v_tmsi) { tmsi = 0L; for (i=0; i<frame[index-1]-1; i++) tmsi += frame[i+index+1] << ((8*(frame[index-1]-2-i))); if (alr_data->pch_data.tmsi EQ tmsi) { /*ALR_TRACE_PCH ("p1 TMSI match");*/ /* * TMSI matches */ if(imsi_type EQ IMSI_TYPE_1) ma_pch_paging_ind (4, (UBYTE)((channel_needed & 0x30)>>4)); else if(imsi_type EQ IMSI_TYPE_2) ma_pch_paging_ind (4, (UBYTE)((channel_needed & 0xC0)>>6)); return TRUE; } } #ifdef GPRS if(GET_STATE(STATE_MA) NEQ MA_CON_EST) { tmsi = 0L; for (i=0; i<frame[index-1]-1; i++) tmsi += frame[i+index+1] << ((8*(frame[index-1]-2-i))); if(gprs_alr_check_ptmsi(tmsi)) return TRUE; } #endif break;/* for case-4 */ } /* end of switch-case */ return FALSE; } /* +--------------------------------------------------------------------+ | PROJECT : MODULE : ALR_PCH | | STATE : code ROUTINE : pch_tmsi_type | +--------------------------------------------------------------------+ PURPOSE : Function replacing the common code from the function "pch_check_pag_2" */ LOCAL BOOL pch_tmsi_type (T_TMSI_TYPE tmsi_type, UBYTE *frame, UBYTE channel_needed) { GET_INSTANCE_DATA; UBYTE i; ULONG tmsi; ALR_TRACE_PCH ("pch_tmsi_type"); if (alr_data->pch_data.v_tmsi) { tmsi = 0L; if (tmsi_type EQ TMSI_TYPE_1) for (i=0; i<4; i++) tmsi += frame[i+4] << (8*(3-i)); else if (tmsi_type EQ TMSI_TYPE_2) for (i=0; i<4; i++) tmsi += frame[i+8] << (8*(3-i)); if (alr_data->pch_data.tmsi EQ tmsi) { /* * TMSI matches */ if (tmsi_type EQ TMSI_TYPE_1) ma_pch_paging_ind (4, (UBYTE)((channel_needed & 0x30)>>4)); else if (tmsi_type EQ TMSI_TYPE_2) ma_pch_paging_ind (4, (UBYTE)((channel_needed & 0xC0)>>6)); return TRUE; } } return FALSE; } #endif