FreeCalypso > hg > fc-tourmaline
view src/g23m-gsm/alr2/alr_em.c @ 222:c336ed5691a5
FCHG: clear BCICTL2 on boot for extra safety
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 26 Apr 2021 22:04:10 +0000 |
parents | 3a14ee9a9843 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : | Modul : +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : This Module defines the engineering mode (EM) device driver for the | G23 protocol stack. This driver is used to control all engineering | mode related functions. +----------------------------------------------------------------------------- */ #ifndef ALR_EM_C #define ALR_EM_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 #ifdef GPRS #ifdef _TARGET_ #include "inth/iq.h" #endif /* * obsolete (msb / 2002-04-25) #include "armio/armio.h" */ #endif #include "alr.h" #include "alr_em.h" /*==== IMPORT =====================================================*/ /*==== EXPORT =====================================================*/ /*==== PRIVAT =====================================================*/ /*==== VARIABLES ==================================================*/ #if defined (FF_EM_MODE) AND defined (ALR) /* Event tracing flags for EM */ GLOBAL BOOL alr_v[EM_MAX_ALR_EVENTS]; LOCAL UBYTE em_alr_trace_occured = 0; /* These variables are used between entities. Even this is not a clean solution it is a straigth forward way to reduce the overhead to a minimum. A clean solution would be based on an only usage of primitives which would stress the os with no aditional advantage!! */ GLOBAL volatile UBYTE em_l1_sem_buffer [EM_L1_SEM_SIZE]; /*lint -esym(765,em_l1_sem_buffer) | external could be made static | used externally */ GLOBAL volatile UBYTE em_l1_sem_index = 0; /*lint -esym(765,em_l1_sem_index) | external could be made static | used externally */ static T_HANDLE sem_EM_L1; #define ENTER_CRITICAL_SECTION(sem) if (alr_em_enter_critical_section(sem))return FALSE; #define LEAVE_CRITICAL_SECTION(sem) if (alr_em_leave_critical_section(sem))return FALSE; #endif /* FF_EM_MODE */ /*==== FUNCTIONS ==================================================*/ #if defined (FF_EM_MODE) AND defined (ALR) LOCAL UBYTE em_l1_sem (UBYTE length, UBYTE * data); LOCAL int em_l1_sem_clear (void); LOCAL void alr_em_first_event_check (void); /*Check for ACI - Notification*/ static void alr_em_semaphore_err (void); #if !defined(SYST_TRACE) #define SYST_TRACE(a) vsi_o_ttrace(0, TC_SYSTEM, a); #endif /* !SYST_TRACE */ static int alr_em_enter_critical_section (T_HANDLE sem); static int alr_em_leave_critical_section (T_HANDLE sem); /* +------------------------------------------------------------------------------ | Function : em_init_l1_event_trace +------------------------------------------------------------------------------ | Description : Initialize the event tracing flags | | Parameters : | | Return : | +------------------------------------------------------------------------------ */ GLOBAL void em_init_l1_event_trace(void) { UBYTE i; TRACE_FUNCTION("em_init_l1_event_trace ()"); for(i=0; i<EM_MAX_ALR_EVENTS; i++) alr_v[i] = 0; } /* +------------------------------------------------------------------------------ | Function : l1_em_l1_event_req +------------------------------------------------------------------------------ | Description : Set the event tracing flags according the bitmask | | Parameters : Primitive - Bitmask | | Return : | +------------------------------------------------------------------------------ */ GLOBAL const void l1_em_l1_event_req (T_EM_L1_EVENT_REQ *em_l1_event_req) { UBYTE i; TRACE_FUNCTION("l1_em_l1_event_req ()"); /* * The event tracing flags are set according the bitmask. alr_v[i] are * the flags belonging to the event number described in 8443.601 */ for(i=1; i<33; i++) { alr_v[i] = ((em_l1_event_req->bitmask_l1_l & (0x01<<(i-1))) > 0) ? TRUE : FALSE; } for(i=33; i<(EM_MAX_ALR_EVENTS); i++) { alr_v[i] = ((em_l1_event_req->bitmask_l1_h & (0x01<<(i-1))) > 0) ? TRUE : FALSE; } /* * A new event trace is generated therefor the flag is set to zero. */ em_alr_trace_occured = 0; PFREE(em_l1_event_req); } /* +------------------------------------------------------------------------------ | Function : em_write_buffer_2 +------------------------------------------------------------------------------ | Description : Perform buffer check and store corresponding data in it. | | Parameters : Event number | | Return : TRUE/FALSE | +------------------------------------------------------------------------------ */ GLOBAL UBYTE em_write_buffer_2 (UBYTE event_no) { UBYTE em_l1_event_buffer[2]; UBYTE em_l1_buffer_write = 0; UBYTE length = 2; TRACE_FUNCTION("alr_em_write_buffer_2 ()"); /* ACI is informed about the first event trace, used for later data processing. */ alr_em_first_event_check(); memset(em_l1_event_buffer, 0, 2); em_l1_event_buffer[em_l1_buffer_write++] = event_no; /* Event number */ em_l1_event_buffer[em_l1_buffer_write++] = length-2; /* Value length - 0 equals no data */ return (em_l1_sem (length, em_l1_event_buffer)); /* Data is stored inside buffer, reset flag */ } /* +------------------------------------------------------------------------------ | Function : em_write_buffer_3 +------------------------------------------------------------------------------ | Description : Perform buffer check and store corresponding data in it. | | Parameters : Event number, data value | | Return : TRUE/FALSE | +------------------------------------------------------------------------------ */ GLOBAL UBYTE em_write_buffer_3 (UBYTE event_no, UBYTE value) { UBYTE em_l1_event_buffer[3]; UBYTE em_l1_buffer_write = 0; UBYTE length = 3; TRACE_FUNCTION("alr_em_write_buffer_3 ()"); /* ACI is informed about the first event trace, used for later data processing. */ alr_em_first_event_check(); memset(em_l1_event_buffer, 0, 3); em_l1_event_buffer[em_l1_buffer_write++] = event_no; /* Event number */ em_l1_event_buffer[em_l1_buffer_write++] = length-2; /* Value length - 0 equals no value */ em_l1_event_buffer[em_l1_buffer_write++] = value; /* Data to be stored */ return (em_l1_sem (length, em_l1_event_buffer)); /* Data is stored inside buffer, reset flag */ } /* +------------------------------------------------------------------------------ | Function : em_write_buffer_3a +------------------------------------------------------------------------------ | Description : Perform buffer check and store corresponding data in it. | | Parameters : Event number, data value (USHORT) | | Return : TRUE/FALSE | +------------------------------------------------------------------------------ */ GLOBAL UBYTE em_write_buffer_3a (UBYTE event_no, USHORT value) { UBYTE em_l1_event_buffer[4]; UBYTE em_l1_buffer_write = 0; UBYTE length = 4; TRACE_FUNCTION("alr_em_write_buffer_4 ()"); /* ACI is informed about the first event trace, used for later data processing. */ alr_em_first_event_check(); memset(em_l1_event_buffer, 0, 4); em_l1_event_buffer[em_l1_buffer_write++] = event_no; /* Event number */ em_l1_event_buffer[em_l1_buffer_write++] = length-2; /* Value length - 0 equals no value */ em_l1_event_buffer[em_l1_buffer_write++] = (UBYTE)(value >> 8); /* Data to be stored - MSB first */ em_l1_event_buffer[em_l1_buffer_write++] = (UBYTE)(value); /* LSB second */ return (em_l1_sem (length, em_l1_event_buffer)); /* Data is stored inside buffer, reset flag */ } /* +------------------------------------------------------------------------------ | Function : em_write_buffer_4 +------------------------------------------------------------------------------ | Description : Perform buffer check and store corresponding data in it. | | Parameters : Event number, data value1 & value2 | | Return : TRUE/FALSE | +------------------------------------------------------------------------------ */ GLOBAL UBYTE em_write_buffer_4 (UBYTE event_no, UBYTE value1, UBYTE value2) { UBYTE em_l1_event_buffer[4]; UBYTE em_l1_buffer_write = 0; UBYTE length = 4; TRACE_FUNCTION("alr_em_write_buffer_4 ()"); /* ACI is informed about the first event trace, used for later data processing. */ alr_em_first_event_check(); memset(em_l1_event_buffer, 0, 4); em_l1_event_buffer[em_l1_buffer_write++] = event_no; /* Event number */ em_l1_event_buffer[em_l1_buffer_write++] = length-2; /* Value length - 0 equals no value */ em_l1_event_buffer[em_l1_buffer_write++] = value1; /* Data to be stored */ em_l1_event_buffer[em_l1_buffer_write++] = value2; /* Data to be stored */ return (em_l1_sem (length, em_l1_event_buffer)); /* Data is stored inside buffer, reset flag */ } /* +------------------------------------------------------------------------------ | Function : em_l1_sem_init +------------------------------------------------------------------------------ | Description : Initialize the semaphor for alr event traces. | | Parameters : void | | Return : void | +------------------------------------------------------------------------------ */ GLOBAL void em_l1_sem_init (void) { sem_EM_L1 = vsi_s_open (VSI_CALLER "EM_L1_SEM",1); if (sem_EM_L1 NEQ VSI_ERROR) em_l1_sem_clear (); else SYST_TRACE ("D1:canīt open semaphore \"EM_D1_SEM\""); } /* +------------------------------------------------------------------------------ | Function : em_l1_sem_exit +------------------------------------------------------------------------------ | Description : Close the semaphor for alr event traces. | | Parameters : void | | Return : void | +------------------------------------------------------------------------------ */ GLOBAL void em_l1_sem_exit (void) { if (sem_EM_L1 NEQ VSI_ERROR) vsi_s_close (VSI_CALLER sem_EM_L1); } /* +------------------------------------------------------------------------------ | Function : em_l1_sem_clear +------------------------------------------------------------------------------ | Description : Reset the index of the semaphor. | | Parameters : void | | Return : UBYTE | +------------------------------------------------------------------------------ */ LOCAL int em_l1_sem_clear (void) { ENTER_CRITICAL_SECTION (sem_EM_L1); em_l1_sem_index = 0; LEAVE_CRITICAL_SECTION (sem_EM_L1); SYST_TRACE ("L1:em_l1_sem_index cleared"); return TRUE; } /* +------------------------------------------------------------------------------ | Function : em_l1_sem_reset +------------------------------------------------------------------------------ | Description : Clears the content of the semaphor, must called after em_l1_sem_read. | | Parameters : void | | Return : UBYTE | +------------------------------------------------------------------------------ */ GLOBAL int em_l1_sem_reset (void) /*lint -esym(765,em_l1_sem_reset) | external could be made static | used externally */ { /* ENTER_CRITICAL_SECTION (sem_EM_L1); */ em_l1_sem_index = 0; LEAVE_CRITICAL_SECTION (sem_EM_L1); SYST_TRACE ("L1:em_l1_sem_index reseted"); return TRUE; } /* +------------------------------------------------------------------------------ | Function : em_l1_sem_read +------------------------------------------------------------------------------ | Description : Reads the content of the semaphor. | | Parameters : void | | Return : UBYTE | +------------------------------------------------------------------------------ */ GLOBAL int em_l1_sem_read (void) /*lint -esym(765,em_l1_sem_read) | external could be made static | used externally */ { USHORT semCount; TRACE_FUNCTION ("em_l1_sem_read()"); if (vsi_s_status (VSI_CALLER sem_EM_L1, &semCount) NEQ VSI_OK) { alr_em_semaphore_err(); return TRUE; } if (semCount EQ 0) { vsi_o_ttrace(VSI_CALLER TC_EVENT, "semCount = %d", semCount); SYST_TRACE ("semCount EQ 0"); return TRUE; } ENTER_CRITICAL_SECTION (sem_EM_L1); /* * The l1/alr semaphor will be read by the engineering mode via aci, * therefore the functions em_l1_sem_read and em_l1_sem_reset are defined * as global. To ensure that during reading only aci has access to the * semaphor the macro LEAVE_CRITICAL_SECTION is called after the read process * toke place - in the em_l1_sem_resest function. */ return TRUE; } /* Return value TRUE/FALSE - TRUE keeps the event flag valid, FALSE indicates a successful flag handle */ /* +------------------------------------------------------------------------------ | Function : em_l1_sem +------------------------------------------------------------------------------ | Description : Writes the data inside the semaphor. | | Parameters : void | | Return : UBYTE | +------------------------------------------------------------------------------ */ LOCAL UBYTE em_l1_sem (UBYTE length, UBYTE *data) { USHORT semCount; USHORT write_index; UBYTE i; TRACE_FUNCTION ("em_l1_sem()"); if (vsi_s_status (VSI_CALLER sem_EM_L1, &semCount) NEQ VSI_OK) { alr_em_semaphore_err(); return TRUE; } if (semCount EQ 0) { vsi_o_ttrace(VSI_CALLER TC_EVENT, "semCount = %d", semCount); SYST_TRACE ("semCount EQ 0"); return TRUE; } /* * buffer overflow protection */ if ( ((write_index = em_l1_sem_index) + length) > EM_L1_SEM_SIZE ) { TRACE_FUNCTION ("alr buffer full"); return FALSE; } ENTER_CRITICAL_SECTION(sem_EM_L1); for (i=0; i<length; i++) em_l1_sem_buffer[em_l1_sem_index++] = *(data++); LEAVE_CRITICAL_SECTION (sem_EM_L1); return FALSE; /* indicates that flag was handled */ } /* endfunc em_l1_sem */ /* +------------------------------------------------------------------------------ | Function : alr_em_semaphore_err +------------------------------------------------------------------------------ | Description : Semaphor error | | | Parameters : void | | Return : void | +------------------------------------------------------------------------------ */ static void alr_em_semaphore_err (void) { static UCHAR out = 0; if (!out) { out = 1; vsi_o_ttrace(VSI_CALLER TC_EVENT, "semaphore error"); } } /* +------------------------------------------------------------------------------ | Function : alr_em_enter_critical_section +------------------------------------------------------------------------------ | Description : Check on critical section entrance | | | Parameters : Handle | | Return : -1 semaphore error | 0 Ok. | +------------------------------------------------------------------------------ */ #if defined (NEW_FRAME) static int alr_em_enter_critical_section (T_HANDLE sem) #else static int alr_em_enter_critical_section (T_VSI_SHANDLE sem) #endif /* NEW_FRAME */ { if (vsi_s_get (VSI_CALLER sem) NEQ VSI_OK) { alr_em_semaphore_err(); return -1; } else { return 0; } }/* endfunc rr_enter_critical_section */ /* +------------------------------------------------------------------------------ | Function : alr_em_leave_critical_section +------------------------------------------------------------------------------ | Description : Check on critical section exit | | | Parameters : Handle | | Return : -1 semaphore error | 0 Ok. | +------------------------------------------------------------------------------ */ #if defined (NEW_FRAME) static int alr_em_leave_critical_section (T_HANDLE sem) #else static int alr_em_leave_critical_section (T_VSI_SHANDLE sem) #endif /* NEW_FRAME */ { if (vsi_s_release (VSI_CALLER sem) NEQ VSI_OK) { alr_em_semaphore_err(); return -1; } else { return 0; } }/* endfunc rr_leave_critical_section */ /* +------------------------------------------------------------------------------ | Function : alr_em_error_cause +------------------------------------------------------------------------------ | Description : Check the error cause and store it in the event buffer | | Parameters : Cause | | Return : None | +------------------------------------------------------------------------------ */ GLOBAL void alr_em_error_cause (UBYTE cause, USHORT arfcn) { switch(cause) { case CS_BCCH_READ_ERROR: { /* Power measurement request */ ALR_EM_BCCH_READ_ERROR; break; } case CS_DOWN_LINK_FAIL: { /* Downlink signalling failure */ ALR_EM_DOWNLINK_FAILURE; break; } case CS_NO_BCCH_AVAIL: { /* neighbourcell BCCH not available */ ALR_EM_NEIGHBOURCELL_BCCH(EM_NOT_AVAIL); break; } }/*switch*/ }/* alr_em_error_cause */ /* +------------------------------------------------------------------------------ | Function : alr_em_first_event_check() +------------------------------------------------------------------------------ | Description : Checks if first EM-Event ocured | | Parameters : None | | Return : None | +------------------------------------------------------------------------------ */ /* ACI is informed about the first event trace, used for later data processing. */ LOCAL void alr_em_first_event_check (void) { TRACE_FUNCTION("alr_em_first_event_check()"); if(em_alr_trace_occured EQ 0) { PALLOC(em_notification, EM_DATA_IND); em_notification->entity = EM_L1; PSENDX(MMI, em_notification); em_alr_trace_occured++; } }/* alr_em_first_event_check */ #endif /* FF_EM_MODE */ #endif /* ALR_EM_C */