diff src/cs/services/cst/cst_pei.c @ 0:92470e5d0b9e

src: partial import from FC Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 15 May 2020 01:28:16 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/cst/cst_pei.c	Fri May 15 01:28:16 2020 +0000
@@ -0,0 +1,1013 @@
+/*
++--------------------------------------------------------------------+
+/*
++-------------------------------------------------------------------+
+| PROJECT: GSM-F&D (8411)               $Workfile:: cst_pei.c       $|
+| $Author:: Be $ CONDAT GmbH            $Revision:: 14              $|
+| CREATED: 01.02.99                     $Modtime:: 14.02.00 12:14   $|
+| STATE  : code                                                      |
++--------------------------------------------------------------------+
+
+   MODULE  : CST_PEI
+
+   PURPOSE : This Modul defines the process body interface for the
+             component CST of the mobile station.
+
+   EXPORT  : pei_create    - Create the Protocol Stack Entity
+             pei_init      - Initialize Protocol Stack Entity
+             pei_primitive - Process Primitive
+             pei_timeout   - Process Timeout
+             pei_exit      - Close resources and terminate
+             pei_run       - Process Primitive
+             pei_config    - Dynamic Configuration
+             pei_monitor   - Monitoring of physical Parameters
+*/
+
+#ifndef CST_PEI_C
+#define CST_PEI_C
+#endif
+
+#include "config/swconfig.cfg"
+#include "config/chipset.cfg"
+
+#ifndef DISABLE_SLEEP
+#define DISABLE_SLEEP 0
+#endif
+
+#define ENTITY_CST
+
+/*==== INCLUDES ===================================================*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "typedefs.h"
+#include "vsi.h"
+#include "custom.h"
+#include "gsm.h"
+#include "prim.h"
+#include "cst/cnf_cst.h"
+#include "cst/cus_cst.h"
+#include "cst/mon_cst.h"
+#include "tok.h"
+#include "p_cst.h"
+#include "cst/cst.h"
+#include "rx.h"
+#include "audio.h"
+
+/*==== CONSTANTS ==================================================*/
+
+// token processing
+#define ERROR     -1
+#define EOS        1
+#define COMMA      2
+#define EQUAL      3
+#define IDENT      4
+#define STRING     5
+#define LBRACK     6
+#define RBRACK     7
+
+/*==== EXPORT =====================================================*/
+extern void CST_stack_trace(void);
+int cst_gsm_parameters(TOK_DCB *dcb);
+extern void l1_cst_l1_parameters(char*); 
+extern void csf_adc_start (UBYTE tx_flag, UBYTE traffic_period, UBYTE idle_period);
+extern void spi_adc_on (void); 
+
+GLOBAL T_HANDLE t_adc_timer    = VSI_ERROR;
+GLOBAL T_HANDLE hCommPL        = VSI_ERROR;    /* PL Communication */
+GLOBAL T_HANDLE hCommL1        = VSI_ERROR;    /* L1 Communication */
+       T_HANDLE cst_handle;
+GLOBAL UBYTE extDisplay = 0;
+
+EXTERN UBYTE audio_is_free;
+/*==== PRIVATE ====================================================*/
+
+LOCAL const void pei_not_supported (void *data);
+
+#ifdef OPTION_RELATIVE
+LOCAL ULONG offset;
+#endif
+
+/*==== VARIABLES ==================================================*/
+
+LOCAL USHORT            t_flag = 0;
+LOCAL BOOL              exit_flag = FALSE;
+LOCAL BOOL              first_access = TRUE;
+LOCAL T_MONITOR         cst_mon;
+
+/*==== FUNCTIONS ==================================================*/
+LOCAL const T_FUNC cst_table[] =
+{
+  MAK_FUNC_0 ( csf_adc_process          , CST_ADC_IND             )
+};
+
+/*==== PROTOTYPES==================================================*/
+
+#if defined (_TMS470)
+
+static SHORT cst_tok_gettok (TOK_DCB *dcb, char ** token);
+static SHORT cst_tok_value (TOK_DCB *dcb, char * value []);
+static int   cst_tokenizer_has_more_data(const TOK_DCB *dcb);
+static SHORT cst_tok_issep (char c);
+static void  cst_tok_init (char * s, TOK_DCB *dcb, char *buf, int buf_len);
+static SHORT cst_get_values(TOK_DCB *dcb, char *value[]);
+static int   cst_getbyte(TOK_DCB *dcb);
+
+#endif
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : pei_primitive       |
++--------------------------------------------------------------------+
+
+  PURPOSE : This function processes protocol specific primitives.
+*/
+LOCAL SHORT pei_primitive (void * ptr)
+{
+  T_PRIM *prim = ptr;
+
+  if (prim NEQ NULL)
+  {
+    USHORT           opc = prim->custom.opc;
+    USHORT           n;
+    const T_FUNC    *table;
+
+    VSI_PPM_REC ((T_PRIM_HEADER*)prim, __FILE__, __LINE__);
+
+    switch (opc & OPC_MASK)
+    {
+      case    CST_DL: table =     cst_table; n = TAB_SIZE     (cst_table); break;
+      default : table = NULL; n = 0; break;
+    }
+
+    if (table != NULL )
+    {
+      if ((opc & PRM_MASK) < n)
+      {
+        table += opc & PRM_MASK;
+#ifdef PALLOC_TRANSITION
+        P_SDU(prim) = table->soff ? (T_sdu*) (((char*)&prim->data) + table->soff) : 0;
+        P_LEN(prim) = table->size + sizeof (T_PRIM_HEADER);
+#endif
+        JUMP (table->func) (P2D(prim));
+      }
+      else
+      {
+        pei_not_supported (P2D(prim));
+      }
+      return PEI_OK;
+    }
+
+#ifdef GSM_ONLY
+    PFREE (P2D(prim))
+    return PEI_ERROR;
+#else
+    if (opc & SYS_MASK)
+    {
+      vsi_c_primitive (VSI_CALLER prim);
+    }
+    else
+    {
+      PFREE (P2D(prim))
+      return PEI_ERROR;
+    }
+#endif
+  }
+  return PEI_OK;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : pei_not_supported   |
++--------------------------------------------------------------------+
+
+  PURPOSE : This function handles an unsupported primitive.
+*/
+LOCAL const void pei_not_supported (void *data)
+{
+  TRACE_FUNCTION ("pei_not_supported()");
+
+  PFREE (data);
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : pei_init            |
++--------------------------------------------------------------------+
+
+  PURPOSE : This function initializes the protocol stack entity
+
+*/
+
+LOCAL SHORT pei_init (T_HANDLE handle)
+{
+  cst_handle = handle;
+
+  TRACE_FUNCTION ("pei_init()");
+
+  exit_flag = FALSE;
+
+  if (hCommPL < VSI_OK)
+  {
+    if ((hCommPL = vsi_c_open (VSI_CALLER PL_NAME)) < VSI_OK)
+    {
+      return PEI_ERROR;
+  	}
+    }
+
+  if (hCommL1 < VSI_OK)
+  {
+    if ((hCommL1 = vsi_c_open (VSI_CALLER L1_NAME)) < VSI_OK)
+    {
+      return PEI_ERROR;
+    }
+  }
+
+  vsi_t_start (VSI_CALLER CST_ADC_TIMER, 230);  // equal to 50 TDMA frames
+
+#if defined (_TMS470)
+  // Set the sleep mode authorized for the layer1 synchronous.
+  // Possible modes are :
+  //          for CHIPSET = 0 : NO_SLEEP, SMALL_SLEEP, BIG_SLEEP.
+  //                            It is necessary to indicate in the prototype of power_down_config()
+  //                            function which clocks (amongst ARMIO_CLK, UWIRE_CLK, SIM_CLK and UART_CLK)
+  //                            to be stopped in case of BIG_SLEEP mode.
+  //                            With this default init, ARMIO_CLK, UWIRE_CLK, SIM_CLK and UART_CLK will be stopped
+  //                            in case of BIG_SLEEP mode, but it can be changed here.
+
+  //          other CHIPSETs  : NO_SLEEP, SMALL_SLEEP, BIG_SLEEP, DEEP_SLEEP, ALL_SLEEP.
+  //                            It is necessary to indicate in the prototype of power_down_config()
+  //                            function which clocks to be stopped in case of BIG_SLEEP mode,
+  //                            amongst ARMIO and UWIRE clocks.
+  //                            With this default init, UWIRE_CLK will always be stopped
+  //                            in case of BIG_SLEEP mode, but it can be changed here.
+
+  // The default configuration is ALL SLEEP. It can be changed in this init.
+
+  // WARNING !!     THE SLEEP MODE SHOULD NOT BE MODIFIED ONCE THE SYSTEM INIT IS FINISHED     !!
+
+  #if !defined (TI_VERSION)
+    #if (CHIPSET == 0)
+      power_down_config(NO_SLEEP, ARMIO_CLK | UWIRE_CLK | SIM_CLK | UART_CLK);
+    #elif (DISABLE_SLEEP == 1)
+      power_down_config(NO_SLEEP, UWIRE_CLK_CUT);
+    #elif ((CHIPSET == 2) || (CHIPSET == 3) ||  \
+           (CHIPSET == 5) || (CHIPSET == 6) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11))
+      power_down_config(ALL_SLEEP, UWIRE_CLK_CUT);
+    #elif ((CHIPSET == 4) || (CHIPSET == 9))
+      power_down_config(NO_SLEEP, UWIRE_CLK_CUT);
+    #endif
+  #endif
+#endif
+
+  return PEI_OK;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : pei_timeout         |
++--------------------------------------------------------------------+
+
+  PURPOSE : This function processes timeouts.
+*/
+
+LOCAL SHORT pei_timeout (USHORT index)
+{
+  rx_timeout    (index);
+  audio_timeout (index);
+
+  if (index EQ CST_ADC_TIMER)
+  {
+    // start the AD conversions in layer1 synchronous
+    // this function will send MMI_ADC_REQ primitive to L1A for test reason.
+    // The user has to implement it by himself in the MMI.
+    // The parameters are : tx_flag, traffic_period, idle_period.
+    // Please refer to the ADC specification for details.
+    
+	// WCS Patch : Schedule ADC on RX and TX
+    #if (OP_WCP == 1)
+	  csf_adc_start(1, 10, 1);    
+    #else
+      csf_adc_start(0, 10, 1);
+    #endif
+    
+    spi_adc_on();
+  }
+
+  return PEI_OK;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : pei_exit            |
++--------------------------------------------------------------------+
+
+  PURPOSE : This function closes all resources and terminates.
+*/
+
+LOCAL SHORT pei_exit (void)
+{
+  TRACE_FUNCTION ("pei_exit()");
+
+  /*
+   * clean up communication
+   */
+
+  vsi_c_close (VSI_CALLER hCommPL);
+  hCommPL = VSI_ERROR;
+
+  vsi_c_close (VSI_CALLER hCommL1);
+  hCommL1 = VSI_ERROR;
+
+  exit_flag = TRUE;
+
+  return PEI_OK;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : pei_config          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Dynamic Configuration
+
+*/
+
+#if !defined (NCONFIG)
+LOCAL KW_DATA kwtab[] = {
+                   CST_CONFIG,           ID_CONFIG,
+                   CST_MUTE,             ID_MUTE,
+                   CST_GSM_PARAMETERS,	 ID_GSM_PARAMETERS,
+                   CST_L1_PARAMETERS,    ID_L1_PARAMETERS,
+                   "",                   0
+       	          };
+
+GLOBAL KW_DATA partab[] = {
+                   "",                 0
+       	          };
+#endif
+
+
+GLOBAL SHORT pei_config (T_PEI_CONFIG inString)
+{
+#if !defined (NCONFIG)
+  char    * s = inString;
+  SHORT     valno;
+  USHORT    keyno;
+  char    * keyw;
+  char    * val [10];
+  TOK_DCB   tokenizer;
+  char      token_buf[80];
+  SHORT     token_type;
+  int       error;      /* terminate processing */
+
+  TRACE_FUNCTION ("pei_config()");
+
+  TRACE_FUNCTION (s);
+
+  cst_tok_init(s, &tokenizer, &token_buf[0], sizeof(token_buf));
+
+  /*
+   * Parse next keyword and number of variables
+   */
+  error = 0;
+  while (!error && cst_tokenizer_has_more_data(&tokenizer))
+  {
+    token_type = cst_tok_gettok(&tokenizer, &keyw);
+    if (token_type != IDENT)
+    {
+      error = 1;
+    }
+    else
+    {
+      switch ((keyno = tok_key((KW_DATA *)kwtab, keyw)))
+      {
+        case ID_CONFIG:
+          valno = cst_get_values(&tokenizer, val);
+          if (valno EQ 3)
+          {
+            extDisplay = 1;
+          }
+          break;
+        case ID_MUTE:
+          valno = cst_get_values(&tokenizer, val);  /* eat up rest of line */
+          /*
+           * FTA testcase 26.6.3.4 needs the the MS is in audio free
+           * environment. This config disables opening of the audio
+           * path.
+           */
+          audio_is_free = FALSE;
+          break;
+        case ID_GSM_PARAMETERS:
+          cst_gsm_parameters(&tokenizer);
+          break;
+        case ID_L1_PARAMETERS:
+          /* pass parameters to L1 function for further process */
+          l1_cst_l1_parameters(s); 
+          valno = cst_get_values(&tokenizer, val);  /* eat up rest of line */
+          break;
+        default:
+          TRACE_ERROR ("[PEI_CONFIG]: Illegal Keyword");
+          break;
+      }
+    }
+  }
+#endif
+  return PEI_OK;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)              MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : cst_pei_config      |
++--------------------------------------------------------------------+
+
+  PURPOSE : Dynamic Configuration
+
+*/
+
+GLOBAL SHORT cst_pei_config ( char * inString, char * dummy )
+{
+  pei_config ( inString );
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : pei_monitor         |
++--------------------------------------------------------------------+
+
+  PURPOSE : This function monitors physical parameters.
+*/
+LOCAL SHORT pei_monitor (void ** monitor)
+{
+  TRACE_FUNCTION ("pei_monitor()");
+
+  cst_mon.version = VERSION_CST;
+
+  *monitor = &cst_mon;
+
+  return PEI_OK;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : pei_create          |
++--------------------------------------------------------------------+
+
+  PURPOSE : This function creates the protocol stack entity.
+*/
+
+GLOBAL SHORT cst_pei_create (T_PEI_INFO **info)
+{
+  static const T_PEI_INFO pei_info =
+  {
+    "CST",
+    {
+      pei_init,
+      pei_exit,
+      pei_primitive,
+      pei_timeout,
+      NULL,             /* no signal function  */
+      NULL,             /* no run function     */
+      pei_config,
+      pei_monitor,
+    },
+    1536,     /* Stack Size      */
+    10,       /* Queue Entries   */
+    55,       /* Priority        */
+    MAX_CST_TIMER,        /* number of timer */
+    0x03      /* flags           */
+  };
+
+  TRACE_FUNCTION ("pei_create()");
+
+  /*
+   *  Close Resources if open
+   */
+
+  if (first_access)
+    first_access = FALSE;
+  else
+    pei_exit ();
+
+  /*
+   *  Export startup configuration data
+   */
+
+  *info = (T_PEI_INFO *)&pei_info;
+
+  return PEI_OK;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : cst_tok_init        |
++--------------------------------------------------------------------+
+
+   PURPOSE : Initialize token scanner.
+
+*/
+static void cst_tok_init (char * s, TOK_DCB *dcb, char *buf, int buf_len)
+{
+  int i;
+  dcb->nexttok = dcb->tokbuf = buf;
+  // can't use strcpy since it stops at 0s
+  for (i=0; i<buf_len-1; i++)
+  {
+    dcb->tokbuf[i] = s[i];
+  }
+  dcb->tokbuf[buf_len-1]  = '\0';
+  dcb->lastchar    = 0;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : cst_get_values      |
++--------------------------------------------------------------------+
+*/
+static SHORT cst_get_values(TOK_DCB *dcb, char *value[])
+{
+  char * val;  /* not identifier, so thrown away */
+  /*
+   * Check next token
+   */
+  switch (cst_tok_gettok (dcb, &val))
+  {
+    /*
+     * No value present
+     */
+    case COMMA:
+      return (0);
+    /*
+     * Value(s) follows
+     */
+    case EQUAL:
+      return (cst_tok_value (dcb, value));
+    /*
+     * No value present and EOS
+     */
+    case EOS:
+      dcb->nexttok = NULL;
+      return (0);
+    /*
+     * Syntax error
+     */
+    default:
+      dcb->nexttok = NULL;
+      return (TOK_EOCS);
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : cst_tok_value		 |
++--------------------------------------------------------------------+
+*/
+static SHORT cst_tok_value (TOK_DCB *dcb, char * value [])
+{
+  SHORT   count;
+  SHORT   tok;
+  SHORT   inbrack;
+  char  * val;
+  char  * val2;
+
+  inbrack = 0;
+  /*
+   * Get next token
+   */
+  tok = cst_tok_gettok (dcb, &val);
+
+  switch (tok)
+  {
+    case LBRACK:
+      inbrack++;
+      break;
+
+    case IDENT  :
+    case STRING :
+      tok = cst_tok_gettok (dcb, &val2);  /* val2 ignored since next tok */
+      if ((tok == COMMA) || (tok == EOS)) /* shouldn't be an IDENT       */
+      {
+        /* just single value, return */
+        value[0] = val;
+        return (1);
+      }
+      else
+      {
+        /* error */
+        dcb->nexttok = NULL;
+        return (0);
+      }
+
+    case EOS :
+    default  :
+      dcb->nexttok = NULL;
+      return (0);
+  }
+
+  /*
+   * Get first token of list
+   */
+
+  tok = cst_tok_gettok (dcb, &val);
+  count = 0;
+  while (1)
+  {
+    if ((tok == IDENT) || (tok == STRING))
+    {
+      value[count++] = val;
+    }
+    else
+    {
+      dcb->nexttok = NULL;
+      return (0);
+    }
+
+    tok = cst_tok_gettok (dcb, &val);
+    switch (tok)
+    {
+      case COMMA:
+        break;
+
+      case RBRACK :
+        if (inbrack)
+        {
+          if (((tok = cst_tok_gettok (dcb, &val)) == COMMA) ||
+               (tok == EOS))
+          {
+            return (count);
+          }
+        }
+        /*
+         * Fall through
+         */
+      default:
+        dcb->nexttok = NULL;
+        return (0);
+    }
+    tok = cst_tok_gettok (dcb, &val);
+  }
+  return (0);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : cst_tok_gettok		 |
++--------------------------------------------------------------------+
+
+   PURPOSE : Get list of values for token.
+             Return number of values found.
+
+             Formats:  Value
+                       (Value)
+                       (Value, Value,...)
+                       ()
+*/
+static SHORT cst_tok_gettok (TOK_DCB *dcb, char ** token)
+{
+  SHORT   tok;
+  /* if previous token was IDENT, a '\0' was placed afterwards
+   * for string processing and the overwritten character was
+   * placed in lastchar.  We now replace this character.
+   */
+  if (dcb->lastchar)
+  {
+    *(dcb->nexttok) = dcb->lastchar;
+    dcb->lastchar = 0;
+  }
+  /*
+   * Skip leading white space
+   */
+  while (isspace (*(dcb->nexttok)))
+  {
+    dcb->nexttok++;
+  }
+
+  * token = dcb->nexttok++;
+
+  switch (** token)
+  {
+    case '\0':                         /* End of string             */
+    case '\n':
+      tok = EOS;
+      break;
+
+    case ',':
+      ** token = '\0';
+      tok = COMMA;
+      break;
+
+    case '=':
+      ** token = '\0';
+      tok = EQUAL;
+      break;
+
+      case '(':
+      case '<':
+      case '[':
+        ** token = '\0';
+        tok = LBRACK;
+        break;
+
+      case ')':
+      case '>':
+      case ']':
+        ** token = '\0';
+        tok = RBRACK;
+        break;
+
+      case '"':
+        /*
+         * Get first char of string
+         */
+        * token = dcb->nexttok;
+        while ((*(dcb->nexttok) != '\0') && (*(dcb->nexttok) != '"'))
+        {
+          dcb->nexttok++;
+        }
+
+        if (*(dcb->nexttok) != '\0')
+        {
+          *(dcb->nexttok++) = '\0';
+        }
+
+        tok = STRING;
+        break;
+
+      default:
+        /*
+         * Read an identifier
+         */
+        while ( !cst_tok_issep (*(dcb->nexttok)) )
+        {
+          dcb->nexttok++;
+        }
+
+        dcb->lastchar = *(dcb->nexttok);
+        *(dcb->nexttok) = '\0';
+
+        if (*token == dcb->nexttok)
+        {
+          /* no characters in identifier. Error in code! */
+          tok = ERROR;
+        }
+        else
+        {
+          tok = IDENT;
+        }
+        break;
+  }
+  return (tok);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : cst_tok_issep       |
++--------------------------------------------------------------------+
+
+  PURPOSE : Return 1 if special character.
+*/
+static SHORT cst_tok_issep (char c)
+{
+  switch (c)
+  {
+    case '\0' :
+    case '\n' :
+    case ','  :
+    case '='  :
+    case '('  :
+    case '<'  :
+    case '['  :
+    case ')'  :
+    case '>'  :
+    case ']'  :
+    case '"'  : return (1);
+
+    default   : return (isspace (c));
+  }
+}
+
+/* if string in tokenizer state has unprocessed tokens return 1 */
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                MODULE  : CST_PEI                     |
+| STATE   : code               ROUTINE : cst_tokenizer_has_more_data |
++--------------------------------------------------------------------+
+
+  PURPOSE : Return 1 if string in tokenizer state has unprocessed tokens.
+*/
+static int cst_tokenizer_has_more_data(const TOK_DCB *dcb)
+{
+  return (dcb->nexttok != NULL);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : cst_getbyte		 |
++--------------------------------------------------------------------+
+*/
+
+static int cst_getbyte(TOK_DCB *dcb)
+{
+  if (dcb->nexttok)
+  {
+    return *(dcb->nexttok++);
+  }
+  else
+  {
+    return -1;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : XXX                        MODULE  : CST_PEI             |
+| STATE   : code                       ROUTINE : cst_gsm_parameters	 |
++--------------------------------------------------------------------+
+*/
+
+int cst_gsm_parameters(TOK_DCB *dcb)
+{
+  unsigned char id;
+  char str[80];
+  int i;
+
+  // STRIP FIRST TWO DELIMITERS
+  {
+    char *tok_string;
+
+    if (cst_tok_gettok(dcb, &tok_string) != EQUAL)
+    {
+       return (0);
+    }
+    if (cst_tok_gettok(dcb, &tok_string) != LBRACK)
+    {
+       return (0);
+    }
+  }
+
+  // GET CONTROL ID
+  if ((id = cst_getbyte(dcb)) == -1)
+  {
+    // vsi_o_trace("CST", 0x08, "gsm_parameters() parser error: out of bytes");
+    return (0);
+  }
+
+  // STACK TRACE
+  else if (id == '1')
+  {
+  CST_stack_trace();
+  } //end else if (id == '1')
+
+  // Crash Me
+  else if (id == '2')
+  {
+    // No instruction before setting the reset vector
+    void (*reset_vector)() = (void (*)()) 0x3000000;
+    (*reset_vector)();
+  } //end else if (id == '2')
+#if defined (ALR)
+  // Print Reg Copy
+  else if (id == '3')
+  {
+    extern int xdump_buffer;
+    int *xp = &xdump_buffer;
+    int magic_word;
+
+    // displays the 16 User mode 32bits registers saved on exception
+    // vsi_o_trace("CST", 0x08, "User mode registers [r0-r15] = ...");
+    for (i=0; i<4; i++)
+	{
+	   sprintf(str, "%08x  %08x  %08x  %08x", *(xp++), *(xp++),
+	                                       *(xp++), *(xp++));
+       // vsi_o_trace("CST", 0x08, str);
+	}
+
+    // displays the User mode CPSR saved on exception
+	sprintf(str, "User mode CPSR = %08x", *(xp++));
+    // vsi_o_trace("CST", 0x08, str);
+
+    // displays the magic word and the index of vector taken
+    magic_word = *(xp++);
+    sprintf(str, "Magic Word + Index of Vector = %08x", magic_word);
+    // vsi_o_trace("CST", 0x08, str);
+
+    // displays the cause of the exception
+	magic_word &= 0x000F;
+
+    switch (magic_word) {
+
+        case 1:
+            // vsi_o_trace("CST", 0x08, "Exception: Undefined Instruction");
+			break;
+
+        case 2:
+            // vsi_o_trace("CST", 0x08, "Exception: Unexpected Software Interrupt");
+			break;
+
+        case 3:
+            // vsi_o_trace("CST", 0x08, "Exception: Abort Prefetch");
+			break;
+
+        case 4:
+            // vsi_o_trace("CST", 0x08, "Exception: Abort Data");
+			break;
+
+        case 5:
+            // vsi_o_trace("CST", 0x08, "Exception: Reserved");
+			break;
+
+        default:
+		    break;
+	}
+
+    // displays the bottom 20 words of user mode stack saved on exception
+    // vsi_o_trace("CST", 0x08, "Bottom 20 words of User mode stack = ...");
+    for (i=0; i<5; i++)
+	{
+	   sprintf(str, "%08x  %08x  %08x  %08x", *(xp++), *(xp++),
+	                                       *(xp++), *(xp++));
+       // vsi_o_trace("CST", 0x08, str);
+	}
+  } //end else if (id == '3')
+
+  // Clear Reg Copy
+  else if (id == '4')
+  {
+    extern int xdump_buffer;
+	int *xp = &xdump_buffer;
+    // Clears the 38 32bits registers saved on exception
+    for (i=0; i<38; i++)
+	{
+       *(xp+i) = 0;
+	}
+    // vsi_o_trace("CST", 0x08, "Registers Copy cleared ...");
+  } //end else if (id == '4')
+#endif
+#if (OP_WCP == 1)
+#if (WCP_PROF == 1)
+  // Enable/disable MC profiler
+  else if (id == '5')
+  {
+    PR_EnableProfiler(0);
+  } 
+  else if (id == '6')
+  {
+    PR_EnableProfiler(1);
+    power_down_config(0, 0x5ff);  // disable sleep, which interferes with profiler
+  } 
+
+  // Enable/disable CPU Meter
+  else if (id == '7')
+  {
+    PR_EnableCpuMeter(0);
+  } 
+  else if (id == '8')
+  {
+    PR_EnableCpuMeter(1);
+    power_down_config(0, 0x5ff);  // disable sleep, which interferes with CPU meter
+  } 
+#endif
+#endif
+
+  // STRIP LAST DELIMITER
+  {
+    char *tok_string;
+
+    if (cst_tok_gettok(dcb, &tok_string) != RBRACK)
+    {
+       return (0);
+    }
+  }
+}  // end cst_gsm_parameters
+
+/*
+ * Reach here if unexpected event occurs (e.g. Undefined instruction, Abort,
+ * out of memory); choose whether to restart or stay in datadump mode to find
+ * out cause of problem
+ */
+void exception_handler(void)
+{
+   void (*jump_address)() = (void (*)()) ((unsigned)0x0);
+
+   (*jump_address)();
+}