view src/cs/services/cst/cst_pei.c @ 274:fa22012c4a39

CST: remove AT%Nxxxx old AEC control This crude method of enabling and configuring AEC is not compatible with L1_NEW_AEC, and even for the old AEC it did not support every possible combination. It is time for this hack to go. The new and proper way of enabling and configuring AEC is via RiViera Audio Service audio mode facility, either audio mode files or full access write, most directly accessible via fc-tmsh auw 12 for free experimentation.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 29 Jul 2021 18:57:36 +0000
parents 4e78acac3d88
children
line wrap: on
line source

/*
+--------------------------------------------------------------------+
/*
+-------------------------------------------------------------------+
| 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)();
}