view src/g23m-gsm/alr2/alr_em.c @ 223:740a8e8fc9d7

startup sync logic rework for the new PWON button boot scheme Previously we added logic to the MMI task to hold off PEI init until R2D is running, and then extended that condition to wait for FCHG init too. However, the dependencies of MMI upon R2D and FCHG don't start until mmiInit(), and that call is driven by Switch_ON() code, hence the wait for R2D and FCHG init can be made in that code path instead of the MMI task. Furthermore, with our new way of signaling PWON button boot to MMI, we need a new wait to ensure that the MMI task is up - previously this assurance was provided by the wait for Kp pointers to be set. Solution: revert our previous PEI init hold-off additions to MMI, add a new flag indicating MMI task init done, and put the combined wait for all needed conditions into our new PWON button boot code in power.c.
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 27 Apr 2021 06:24:52 +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 */