FreeCalypso > hg > freecalypso-sw
diff gsm-fw/g23m-gsm/alr/alr_em.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 | a2a65fdc1a99 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/g23m-gsm/alr/alr_em.c Sun Sep 28 23:20:04 2014 +0000 @@ -0,0 +1,652 @@ +/* ++----------------------------------------------------------------------------- +| 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) +#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 */