/*+-----------------------------------------------------------------------------| 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 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; 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 ( (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;/* Implements Measure#32: Row 56 */ TRACE_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)#elsestatic 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)#elsestatic 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 */