FreeCalypso > hg > fc-tourmaline
view src/cs/services/cst/cst_pei.c @ 304:58c7961bd0b0 default tip
TCH tap: extend DL sniffing feature to support CSD modes
Our debug feature for TCH DL sniffing reads the content of the DSP's
a_dd_0 buffer (or a_dd_1 for TCH/H subchannel 1) at appropriate times
and forwards captured bits to the host. This feature was originally
implemented for TCH/FS, TCH/EFS and TCH/HS - now extend it to cover
TCH/F data modes too.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 25 Nov 2024 23:33:27 +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)(); }