FreeCalypso > hg > fc-tourmaline
diff src/g23m-gprs/llc/llc_pei.c @ 1:fa8dc04885d8
src/g23m-*: import from Magnetite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:25:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/g23m-gprs/llc/llc_pei.c Fri Oct 16 06:25:50 2020 +0000 @@ -0,0 +1,825 @@ +/* ++----------------------------------------------------------------------------- +| 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 implements the process body interface +| for the entity Logical Link Control (LLC) +| +| Exported functions: +| +| 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 ++----------------------------------------------------------------------------- +*/ + +#define LLC_PEI_C + +#define ENTITY_LLC + +/*==== INCLUDES =============================================================*/ + +#include <stddef.h> /* to get definition of offsetof(), for MAK_FUNC_S */ +#include <stdlib.h> /* to get atoi() */ +#include "typedefs.h" /* to get Condat data types */ +#include "vsi.h" /* to get a lot of macros */ +#include "macdef.h" +#include "gprs.h" +#include "gsm.h" /* to get a lot of macros */ +#include "cnf_llc.h" /* to get cnf-definitions */ +#include "mon_llc.h" /* to get mon-definitions */ +#include "prim.h" /* to get the definitions of used SAP and directions */ +#include "pei.h" /* to get PEI interface */ +#include "llc.h" /* to get the global entity definitions */ +#include "llc_f.h" /* to get the global entity definitions */ + +#include "llc_llmep.h" /* to get primitive interface to LLME */ +#include "llc_up.h" /* to get primitive interface to U */ +#include "llc_itxp.h" /* to get primitive interface to ITX */ +#include "llc_irxp.h" /* to get primitive interface to IRX */ +#include "llc_itxt.h" /* to get timer interface to IRX */ +#include "llc_uitxp.h" /* to get primitive interface to UITX */ +#include "llc_uirxp.h" /* to get primitive interface to UIRX */ +#include "llc_t200p.h" /* to get primitive interface to T200 */ +#include "llc_txp.h" /* to get primitive interface to TX */ +#include "llc_rxp.h" /* to get primitive interface to RX */ +#include "llc_llmef.h" /* to get init function of LLME */ +#include "llc_uf.h" /* to get init function of U */ +#include "llc_itxf.h" /* to get init function of ITX */ +#include "llc_irxf.h" /* to get init function of IRX */ +#include "llc_uitxf.h" /* to get init function of UITX */ +#include "llc_uirxf.h" /* to get init function of UIRX */ +#include "llc_t200f.h" /* to get init function of T200 */ +#include "llc_txf.h" /* to get init function of TX */ +#include "llc_rxf.h" /* to get init function of RX */ + + + +/*==== DEFINITIONS ==========================================================*/ + +/*==== TYPES ================================================================*/ + +/*==== GLOBAL VARS ==========================================================*/ + +/*==== LOCAL VARS ===========================================================*/ + +static BOOL first_access = TRUE; +static T_MONITOR llc_mon; + +/* + * Jumptables to primitive handler functions. One table per SAP. + * + * Use MAK_FUNC_0 for primitives which contains no SDU. + * Use MAK_FUNC_S for primitives which contains a SDU. + */ + +/* + * This Function is needed for primitives, that are not (yet?) supported. + * It frees the primitive for which it is specified in the jump table. + */ +LOCAL void primitive_not_supported (T_PRIM_HEADER *data); + + +static const T_FUNC ll_table[] = +{ + MAK_FUNC_S(u_ll_establish_req, LL_ESTABLISH_REQ), + MAK_FUNC_S(u_ll_establish_res, LL_ESTABLISH_RES), + MAK_FUNC_0(u_ll_release_req, LL_RELEASE_REQ), + MAK_FUNC_S(u_ll_xid_req, LL_XID_REQ), + MAK_FUNC_S(u_ll_xid_res, LL_XID_RES), + MAK_FUNC_0(irx_ll_getdata_req, LL_GETDATA_REQ), + MAK_FUNC_0(uirx_ll_getunitdata_req, LL_GETUNITDATA_REQ), +#ifdef LL_DESC + MAK_FUNC_S(itx_ll_data_req, LL_DATA_REQ), + MAK_FUNC_S(uitx_ll_unitdata_req, LL_UNITDATA_REQ), + MAK_FUNC_0(itx_ll_desc_req, LL_DESC_REQ), + MAK_FUNC_0(uitx_ll_unitdesc_req, LL_UNITDESC_REQ), +#else + MAK_FUNC_S(itx_ll_desc_req, LL_DATA_REQ), + MAK_FUNC_S(uitx_ll_unitdesc_req, LL_UNITDATA_REQ) +#endif +}; + +static const T_FUNC llgmm_table[] = +{ + MAK_FUNC_0(llme_llgmm_assign_req, LLGMM_ASSIGN_REQ), + MAK_FUNC_0(llme_llgmm_trigger_req, LLGMM_TRIGGER_REQ), + MAK_FUNC_0(llme_llgmm_suspend_req, LLGMM_SUSPEND_REQ), + MAK_FUNC_0(llme_llgmm_resume_req, LLGMM_RESUME_REQ) +}; + +static const T_FUNC grlc_table[] = +{ + MAK_FUNC_0(rx_grlc_data_ind, GRLC_DATA_IND), +#ifdef _SIMULATION_ + MAK_FUNC_S(rx_grlc_data_ind_test, GRLC_DATA_IND_TEST), +#else + MAK_FUNC_N(primitive_not_supported, GRLC_DATA_IND_TEST), +#endif + MAK_FUNC_0(rx_grlc_unitdata_ind, GRLC_UNITDATA_IND), +#ifdef _SIMULATION_ + MAK_FUNC_S(rx_grlc_unitdata_ind_test, GRLC_UNITDATA_IND_TEST), +#else + MAK_FUNC_N(primitive_not_supported, GRLC_UNITDATA_IND_TEST), +#endif + MAK_FUNC_N(tx_grlc_ready_ind, GRLC_READY_IND), + MAK_FUNC_N(tx_grlc_suspend_ready_ind, GRLC_SUSPEND_READY_IND) +}; + + +/*==== PRIVATE FUNCTIONS ====================================================*/ + +/* ++------------------------------------------------------------------------------ +| Function : primitive_not_supported ++------------------------------------------------------------------------------ +| Description : This function handles unsupported primitives. +| +| Parameters : - +| +| Return : - +| ++------------------------------------------------------------------------------ +*/ +LOCAL void primitive_not_supported (T_PRIM_HEADER *data) +{ + TRACE_FUNCTION ("primitive_not_supported"); + + PFREE (data); +} + + +/*==== PUBLIC FUNCTIONS =====================================================*/ + +/* ++------------------------------------------------------------------------------ +| Function : pei_primitive ++------------------------------------------------------------------------------ +| Description : This function is called by the frame when a primitive is +| received and needs to be processed. +| +| | | +| LLGMM LL UPLINK +| | | +| +------v-----------v-------+ +| | | +| | LLC | +| | | +| +-------------^------------+ +| | +| GRLC DOWNLINK +| | +| +| +| Parameters : prim - Pointer to the received primitive +| +| Return : PEI_OK - function succeeded +| PEI_ERROR - function failed +| ++------------------------------------------------------------------------------ +*/ +LOCAL SHORT pei_primitive (void * primptr) +{ + TRACE_FUNCTION ("pei_primitive"); + + if (primptr != NULL) + { + T_PRIM *prim = (T_PRIM *)primptr; + ULONG opc = prim->custom.opc; + USHORT n; + const T_FUNC *table; + + /* + * This must be called to enable Partition Pool (memory) supervision. + */ + VSI_PPM_REC (&prim->custom, __FILE__, __LINE__); + + switch (SAP_NR(opc)) + { + case SAP_NR(LLGMM_UL): + table = llgmm_table; + n = TAB_SIZE (llgmm_table); + break; + case SAP_NR(LL_UL): +#ifdef TRACE_EVE + { + /* + * following line requires sapi is always the first struct member + * in all LL primitive headers and always using the same size. + */ + T_LL_GETUNITDATA_REQ* pData = (T_LL_GETUNITDATA_REQ*)(P2D(prim)); + + switch (pData->sapi) + { + case LL_SAPI_1: TRACE_PRIM_FROM("GMM"); break; +#ifdef LL_2to1 + case LL_SAPI_7: TRACE_PRIM_FROM("MM"); break; +#else + case LL_SAPI_7: TRACE_PRIM_FROM("GSMS"); break; +#endif + default: break; + } + } +#endif + table = ll_table; + n = TAB_SIZE (ll_table); + break; + case SAP_NR(GRLC_DL): + table = grlc_table; + n = TAB_SIZE (grlc_table); + break; + default: + table = NULL; + n = 0; + break; + } + + PTRACE_IN (opc); + + if (table != NULL) + { + if ((PRIM_NR(opc)) < n) + { + table += PRIM_NR(opc); +#ifdef PALLOC_TRANSITION + P_SDU(prim) = table->soff ? (T_sdu*) (((char*)&prim->data) + table->soff) : 0; +#ifndef NO_COPY_ROUTING + P_LEN(prim) = table->size + sizeof (T_PRIM_HEADER); +#endif /* NO_COPY_ROUTING */ +#endif /* PALLOC_TRANSITION */ + JUMP (table->func) (P2D(prim)); + } + else + { + primitive_not_supported (P2D(prim)); + } + return PEI_OK; + } + + /* + * primitive is not a GSM primitive - forward it to the environment + */ + if (opc & SYS_MASK) + vsi_c_primitive (VSI_CALLER prim); + else + { + PFREE (P2D(prim)); + return PEI_ERROR; + } + } + return PEI_OK; +} + + +/* ++------------------------------------------------------------------------------ +| Function : pei_init ++------------------------------------------------------------------------------ +| Description : This function is called by the frame. It is used to initialise +| the entitiy. +| +| Parameters : handle - task handle +| +| Return : PEI_OK - entity initialised +| PEI_ERROR - entity not (yet) initialised +| ++------------------------------------------------------------------------------ +*/ +LOCAL SHORT pei_init (T_HANDLE handle) +{ + TRACE_FUNCTION ("pei_init"); + + /* + * Initialize task handle + */ + LLC_handle = handle; + + /* + * Open communication channels + */ + if (hCommGMM < VSI_OK) + { +#ifdef LL_2to1 + if ((hCommGMM = vsi_c_open (VSI_CALLER MM_NAME)) < VSI_OK) +#else + if ((hCommGMM = vsi_c_open (VSI_CALLER GMM_NAME)) < VSI_OK) +#endif + return PEI_ERROR; + } + if (hCommSNDCP < VSI_OK) + { + if ((hCommSNDCP = vsi_c_open (VSI_CALLER SNDCP_NAME)) < VSI_OK) + return PEI_ERROR; + } +#ifdef LL_2to1 + if (hCommMM < VSI_OK) + { + if ((hCommMM = vsi_c_open (VSI_CALLER MM_NAME)) < VSI_OK) + return PEI_ERROR; + } +#else + if (hCommGSMS < VSI_OK) + { + if ((hCommGSMS = vsi_c_open (VSI_CALLER GSMS_NAME)) < VSI_OK) + return PEI_ERROR; + } +#endif + if (hCommGRLC < VSI_OK) + { + if ((hCommGRLC = vsi_c_open (VSI_CALLER GRLC_NAME)) < VSI_OK) + return PEI_ERROR; + } + + + /* + * Initialize global pointer llc_data. This is required to access all + * entity data. + */ + llc_data = &llc_data_base; + + + /* + * Initialize entity data (call init function of every service) + */ + llme_init(); + u_init(); + itx_init(); + irx_init(); + uitx_init(); + uirx_init(); + t200_init(); + llc_tx_init(); + rx_init(); +#ifndef TI_PS_OP_CIPH_DRIVER + llc_fbs_init(); +#endif + return (PEI_OK); +} + +/* ++------------------------------------------------------------------------------ +| Function : pei_timeout ++------------------------------------------------------------------------------ +| Description : This function is called by the frame when a timer has expired. +| +| Parameters : index - timer index +| +| Return : PEI_OK - timeout processed +| PEI_ERROR - timeout not processed +| ++------------------------------------------------------------------------------ +*/ +LOCAL SHORT pei_timeout (USHORT index) +{ + TRACE_FUNCTION ("pei_timeout"); + + /* + * Process timeout + */ + switch (index) + { + case TIMER_T200_1: + /* + * T200 for SAPI 1 expired. + */ + t200_timer_t200 (LL_SAPI_1); + break; + case TIMER_T200_3: + /* + * T200 for SAPI 3 expired. + */ + t200_timer_t200 (LL_SAPI_3); + break; + case TIMER_T200_5: + /* + * T200 for SAPI 5 expired. + */ + t200_timer_t200 (LL_SAPI_5); + break; + case TIMER_T200_7: + /* + * T200 for SAPI 7 expired. + */ + t200_timer_t200 (LL_SAPI_7); + break; + case TIMER_T200_9: + /* + * T200 for SAPI 9 expired. + */ + t200_timer_t200 (LL_SAPI_9); + break; + case TIMER_T200_11: + /* + * T200 for SAPI 11 expired. + */ + t200_timer_t200 (LL_SAPI_11); + break; + case TIMER_T201_3: + /* + * T201 for SAPI 3 expired. + */ + itx_timer_t201 (LL_SAPI_3); + break; + case TIMER_T201_5: + /* + * T201 for SAPI 5 expired. + */ + itx_timer_t201 (LL_SAPI_5); + break; + case TIMER_T201_9: + /* + * T201 for SAPI 9 expired. + */ + itx_timer_t201 (LL_SAPI_9); + break; + case TIMER_T201_11: + /* + * T201 for SAPI 11 expired. + */ + itx_timer_t201 (LL_SAPI_11); + break; + default: + TRACE_ERROR("Unknown Timeout"); + break; + } + + return PEI_OK; +} + +/* ++------------------------------------------------------------------------------ +| Function : pei_signal ++------------------------------------------------------------------------------ +| Description : This function is called by the frame when a signal has been +| received. +| +| Parameters : opc - signal operation code +| *data - pointer to primitive +| +| Return : PEI_OK - signal processed +| PEI_ERROR - signal not processed +| ++------------------------------------------------------------------------------ +*/ +LOCAL SHORT pei_signal (ULONG opc, void *data) +{ + TRACE_FUNCTION ("pei_signal"); + + /* + * Process signal + */ + TRACE_ERROR("Unknown Signal OPC"); + + return PEI_OK; +} + +/* ++------------------------------------------------------------------------------ +| Function : pei_exit ++------------------------------------------------------------------------------ +| Description : This function is called by the frame when the entity is +| terminated. All open resources are freed. +| +| Parameters : - +| +| Return : PEI_OK - exit sucessful +| PEI_ERROR - exit not sueccessful +| ++------------------------------------------------------------------------------ +*/ +LOCAL SHORT pei_exit (void) +{ + TRACE_FUNCTION ("pei_exit"); + + /* + * Close communication channels + */ + vsi_c_close (VSI_CALLER hCommGMM); + hCommGMM = VSI_ERROR; + + vsi_c_close (VSI_CALLER hCommSNDCP); + hCommSNDCP = VSI_ERROR; + +#ifdef LL_2to1 + vsi_c_close (VSI_CALLER hCommMM); + hCommMM = VSI_ERROR; +#else + vsi_c_close (VSI_CALLER hCommGSMS); + hCommGSMS = VSI_ERROR; +#endif + + vsi_c_close (VSI_CALLER hCommGRLC); + hCommGRLC = VSI_ERROR; + + return PEI_OK; +} + +/* ++------------------------------------------------------------------------------ +| Function : pei_run ++------------------------------------------------------------------------------ +| Description : This function is called by the frame when entering the main +| loop. This fucntion is only required in the active variant. +| +| This function is not used. +| +| Parameters : handle - Communication handle +| +| Return : PEI_OK - sucessful +| PEI_ERROR - not successful +| ++------------------------------------------------------------------------------ +*/ +LOCAL SHORT pei_run (T_HANDLE TaskHandle, T_HANDLE ComHandle ) +{ +/* + * Does not compile! + * + T_QMSG Message; + + TRACE_FUNCTION ("pei_run"); + + if (pei_init (TaskHandle) != PEI_OK) + return PEI_ERROR; + + while (!exit_flag) + { + vsi_c_await (VSI_CALLER ComHandle, &Message); + switch (Message.MsgType) + { + case MSG_PRIMITIVE: + pei_primitive (Message.Msg.Primitive.Prim ); + break; + case MSG_SIGNAL: + pei_signal ( (USHORT)Message.Msg.Signal.SigOPC, + Message.Msg.Signal.SigBuffer ); + break; + case MSG_TIMEOUT: + pei_timeout ( (USHORT)Message.Msg.Timer.Index ); + break; + default: + TRACE_ERROR("Unknown Message Type"); + break; + } + } + + * + * + */ + + return PEI_OK; +} + +/* ++------------------------------------------------------------------------------ +| Function : pei_config ++------------------------------------------------------------------------------ +| Description : This function is called by the frame when a primitive is +| received indicating dynamic configuration. +| +| This function is not used in this entity. +| +| Parameters : handle - Communication handle +| +| Return : PEI_OK - sucessful +| PEI_ERROR - not successful +| ++------------------------------------------------------------------------------ +*/ +LOCAL SHORT pei_config (char *inString) +{ + TRACE_FUNCTION ("pei_config"); + TRACE_FUNCTION (inString); + +#ifdef _SIMULATION_ +#ifndef NCONFIG + /* + * Parse for config keywords: + * SAPI XX KU YYYY + * SAPI XX KD YYYY + * SAPI XX MU YYYY + * SAPI XX MD YYYY + * SAPI XX N200 YYYY + * SAPI XX T200 YYYY + * SAPI XX N201_U YYYY + * SAPI XX N201_I YYYY + * The configured values are currently stored in the requested_xid struct, which is + * refilled completely after change into LLC assigned state and after LLC XID reset. + */ + if (inString[0] == 'S' AND inString[1] == 'A' AND inString[2] == 'P' AND + inString[3] == 'I' AND inString[4] == ' ') + { + UBYTE sapi = 0; + UBYTE i = 5; + + /* get first sapi number */ + if (inString[i] >= '0' AND inString[i] <= '9') + { + sapi = (inString[i] - '0'); + i++; + } + + /* get second sapi number, if available */ + if (inString[i] >= '0' AND inString[i] <= '9') + { + sapi = (sapi * 10) + (inString[i] - '0'); + i++; + } + + /* skip next whitespace */ + i++; + + /* get XID value to change */ + if (inString[i] == 'K' AND inString[i+2] == ' ') + { + if (inString[i+1] == 'U') /* KU */ + { + llc_data->ffs_xid.ku[IMAP(sapi)].valid = TRUE; + llc_data->ffs_xid.ku[IMAP(sapi)].value = (UBYTE)atoi(&inString[i+3]); + } + else /* KD */ + { + llc_data->ffs_xid.kd[IMAP(sapi)].valid = TRUE; + llc_data->ffs_xid.kd[IMAP(sapi)].value = (UBYTE)atoi(&inString[i+3]); + } + } + else if (inString[i] == 'M' AND inString[i+2] == ' ') + { + if (inString[i+1] == 'U') /* MU */ + { + llc_data->ffs_xid.mu[IMAP(sapi)].valid = TRUE; + llc_data->ffs_xid.mu[IMAP(sapi)].value = (UBYTE)atoi(&inString[i+3]); + } + else /* MD */ + { + llc_data->ffs_xid.md[IMAP(sapi)].valid = TRUE; + llc_data->ffs_xid.md[IMAP(sapi)].value = (UBYTE)atoi(&inString[i+3]); + } + } + else if (inString[i+0] == 'N' AND inString[i+1] == '2' AND inString[i+2] == '0' AND + inString[i+3] == '1' AND inString[i+4] == '_' AND inString[i+6] == ' ' ) + { + if (inString[i+5] == 'I') /* N201_I */ + { + llc_data->ffs_xid.n201_i[IMAP(sapi)].valid = TRUE; + llc_data->ffs_xid.n201_i[IMAP(sapi)].value = (USHORT)atoi(&inString[i+7]); + } + else if (inString[i+5] == 'U') /* N201_U */ + { + llc_data->ffs_xid.n201_u[UIMAP(sapi)].valid = TRUE; + llc_data->ffs_xid.n201_u[UIMAP(sapi)].value = (USHORT)atoi(&inString[i+7]); + } + } + else if (inString[i+1] == '2' AND inString[i+2] == '0' AND inString[i+3] == '0' AND + inString[i+4] == ' ') + { + if (inString[i+0] == 'N') /* N200 */ + { + llc_data->ffs_xid.n200[UIMAP(sapi)].valid = TRUE; + llc_data->ffs_xid.n200[UIMAP(sapi)].value = (UBYTE)atoi(&inString[i+5]); + } + else if (inString[i+0] == 'T') /* T200 */ + { + llc_data->ffs_xid.t200[UIMAP(sapi)].valid = TRUE; + llc_data->ffs_xid.t200[UIMAP(sapi)].value = (USHORT)atoi(&inString[i+5]); + } + } + } + +#endif + +#else /*_SIMULATION_*/ +/* CCI_INFO */ + if(inString[0] == 'C' AND + inString[1] == 'C' AND + inString[2] == 'I' AND + inString[3] == '_' AND + inString[4] == 'I' AND + inString[5] == 'N' AND + inString[6] == 'F' AND + inString[7] == 'O') { + TRACE_EVENT("CCI Info Trace Enabled"); + llc_fbs_enable_cci_info_trace(); + } else if (inString[0] == 'D' && + inString[1] == 'E' && + inString[2] == 'L' && + inString[3] == 'A' && + inString[4] == 'Y') { + + USHORT millis = (USHORT)atoi(&inString[5]); + llc_data->millis = millis; + TRACE_1_OUT_PARA("Delay timer :%d milliseconds", llc_data->millis); + } else { + TRACE_EVENT("PEI ERROR: invalid config primitive"); + } +#endif/*_SIMULATION_*/ + + return PEI_OK; +} + +/* ++------------------------------------------------------------------------------ +| Function : pei_config ++------------------------------------------------------------------------------ +| Description : This function is called by the frame in case sudden entity +| specific data is requested (e.g. entity Version). +| +| Parameters : out_monitor - return the address of the data to be +| monitoredCommunication handle +| +| Return : PEI_OK - sucessful (address in out_monitor is valid) +| PEI_ERROR - not successful +| ++------------------------------------------------------------------------------ +*/ +LOCAL SHORT pei_monitor (void ** out_monitor) +{ + TRACE_FUNCTION ("pei_monitor"); + + /* + * Version = "0.S" (S = Step). + */ + llc_mon.version = "LLC 1.0"; + *out_monitor = &llc_mon; + + return PEI_OK; +} + +/* ++------------------------------------------------------------------------------ +| Function : pei_create ++------------------------------------------------------------------------------ +| Description : This function is called by the frame when the process is +| created. +| +| Parameters : out_name - Pointer to the buffer in which to locate +| the name of this entity +| +| Return : PEI_OK - entity created successfuly +| PEI_ERROR - entity could not be created +| ++------------------------------------------------------------------------------ +*/ +GLOBAL SHORT pei_create (T_PEI_INFO **info) +{ +static T_PEI_INFO pei_info = + { + "LLC", /* name */ + { /* pei-table */ + pei_init, + pei_exit, + pei_primitive, + pei_timeout, + pei_signal, + pei_run, + pei_config, + pei_monitor + }, + 2560, /* stack size */ + 32, /* queue entries */ + 200, /* priority (1->low, 255->high) */ + TIMER_NUM, /* number of timers */ +#ifdef _TARGET_ + PASSIVE_BODY|COPY_BY_REF|TRC_NO_SUSPEND|PRIM_NO_SUSPEND +#else + PASSIVE_BODY|COPY_BY_REF +#endif + }; + + + TRACE_FUNCTION ("pei_create"); + + /* + * Close Resources if open + */ + if (first_access) + first_access = FALSE; + else + pei_exit(); + + /* + * Export startup configuration data + */ + *info = &pei_info; + + return PEI_OK; +} + +/*==== END OF FILE ==========================================================*/