diff src/g23m-gprs/gmm/gmm_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/gmm/gmm_pei.c	Fri Oct 16 06:25:50 2020 +0000
@@ -0,0 +1,1588 @@
+/* 
++----------------------------------------------------------------------------- 
+|  Project :  GPRS (8441)
+|  Modul   :  gmm_pei.c
++----------------------------------------------------------------------------- 
+|  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 GPRS Mobility Management (GMM)
+|             
+|             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 GMM_PEI_C
+
+#define ENTITY_GMM
+
+/*==== INCLUDES =============================================================*/
+
+#include <stddef.h>     /* to get definition of offsetof(), for MAK_FUNC_S */
+#include <stdlib.h>     /* to get atoi for tokenizer in pei_init */
+#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_gmm.h"    /* to get cnf-definitions */
+#include "mon_gmm.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 "gmm.h"        /* to get the global entity definitions */
+#include "gmm_f.h"      /* to get the debug print function */
+
+#include "gmm_kernp.h"  /* to get primitive interface to KERN */
+#include "gmm_txp.h"    /* to get primitive interface to TX */
+#include "gmm_rxp.h"    /* to get primitive interface to RX */
+#include "gmm_rdyp.h"   /* to get primitive interface to RDY */
+#include "gmm_syncp.h"  /* to get primitive interface to SYNC */
+
+#include "gmm_kernf.h"  /* to get functions from KERN */
+#include "gmm_txf.h"    /* to get functions from TX */
+#include "gmm_rxf.h"    /* to get functions from RX */
+#include "gmm_rdyf.h"   /* to get functions from RDY */
+#include "gmm_syncf.h"  /* to get functions from SYNC */
+
+
+#include "ccdapi.h"     /* to get ccd stuff */
+#include "tok.h"        /* to get tokenizer */
+#include  <string.h>    /* to get memcpy */
+
+#include "gmm_em.h"     /*to get definitions of the Engineering Mode*/
+/*==== DEFINITIONS ==========================================================*/
+
+/*==== TYPES ================================================================*/
+
+/*==== GLOBAL VARS ==========================================================*/
+
+/*==== LOCAL VARS ===========================================================*/
+
+static  BOOL          first_access  = TRUE;
+static  T_MONITOR     gmm_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.
+ */
+
+/*******************************************************
+ * SAVE prim
+ *******************************************************/
+
+#define PEI_SIGNAL_NOT_SAVED      FALSE
+#define PEI_SIGNAL_SAVED          TRUE
+#define PEI_END_SAVETAB           0xFF
+
+#define GMM_MAX_SIGNALS_SAVED      5     /* value adjusted to GMM requirements */
+
+typedef struct SAVE_QUEUE
+{
+  void*              prim;
+  T_VOID_FUNC        func;
+  struct SAVE_QUEUE* next;
+} T_SAVE_QUEUE;
+
+void gmm_pei_delete_queue( T_SAVE_QUEUE** queue );
+
+typedef struct
+{
+  USHORT  state;
+  USHORT  signal[GMM_MAX_SIGNALS_SAVED];
+} T_SAVE_TAB;
+
+/*==== LOCAL PROTOTYPES =====================================================*/
+LOCAL void gmm_pei_handle_prim( T_VOID_FUNC func, void* prim );
+LOCAL BOOL gmm_pei_handle_save( void* prim, T_SAVE_QUEUE** queue,
+                                     const T_SAVE_TAB* table, T_VOID_FUNC func);
+LOCAL void gmm_pei_handle_queue( T_SAVE_QUEUE** queue,
+                                      const T_SAVE_TAB* table);
+
+/*==== VAR LOCAL ============================================================*/
+
+LOCAL T_SAVE_QUEUE*     save_queue;     /* SAVE queue hangers */
+
+LOCAL const T_SAVE_TAB save_tab[] = {
+
+  { KERN_GMM_REG_INITIATED,      
+                            {MMGMM_LUP_NEEDED_IND,
+                             GMMREG_NET_REQ, 
+                             GMMREG_PLMN_RES,
+                             0, 0 }
+  },
+
+  { KERN_GMM_RAU_INITIATED,      
+                            {MMGMM_LUP_NEEDED_IND,
+                             GMMREG_DETACH_REQ,
+                             GMMREG_NET_REQ, 
+                             GMMREG_PLMN_RES,
+                             0 }
+  },
+
+  {KERN_GMM_RAU_WAIT_FOR_NPDU_LIST ,
+                           {GMMRR_CELL_IND, 
+                            0, 0, 0, 0 }
+  },
+  { KERN_GMM_DEREG_SUSPENDING,
+                            {GMMREG_NET_REQ, 
+                             GMMREG_PLMN_RES,
+                             GMMRR_CS_PAGE_IND,
+                             MMGMM_CM_ESTABLISH_IND,
+                             MMGMM_CM_EMERGENCY_IND     }
+  },
+  { KERN_GMM_REG_SUSPENDING,
+                            {GMMREG_NET_REQ, 
+                             GMMREG_PLMN_RES,
+                             GMMRR_CS_PAGE_IND,
+                             MMGMM_CM_ESTABLISH_IND,
+                             MMGMM_CM_EMERGENCY_IND     }
+  },
+  { KERN_GMM_REG_RESUMING,
+                            {GMMREG_DETACH_REQ, 
+                             GMMRR_CS_PAGE_IND,
+                             MMGMM_CM_ESTABLISH_IND,
+                             MMGMM_CM_EMERGENCY_IND,
+                             GMMREG_ATTACH_REQ }
+  },
+  { KERN_GMM_DEREG_RESUMING,
+                            {GMMREG_DETACH_REQ, 
+                             GMMRR_CS_PAGE_IND,
+                             MMGMM_CM_ESTABLISH_IND,
+                             MMGMM_CM_EMERGENCY_IND,
+                             GMMREG_ATTACH_REQ}
+  },
+  { PEI_END_SAVETAB,
+                           { 0, 0, 0, 0, 0 }
+  }
+};
+/*******************************************************
+ * End SAVE prim
+ *******************************************************/
+
+
+/*
+ * Function is needed for grr_table[]. This declaration can be removed
+ * as soon as this function is no more called (i.e. all primitives are
+ * handled).
+ */
+LOCAL void primitive_not_supported (void *data);
+
+static const T_FUNC gmmreg_table[] =
+{
+  MAK_FUNC_0(kern_gmmreg_attach_req,        GMMREG_ATTACH_REQ),
+  MAK_FUNC_0(kern_gmmreg_detach_req,        GMMREG_DETACH_REQ),
+  MAK_FUNC_0(kern_gmmreg_net_req,           GMMREG_NET_REQ),
+  MAK_FUNC_0(kern_gmmreg_plmn_res,          GMMREG_PLMN_RES),
+  MAK_FUNC_0(kern_gmmreg_plmn_mode_req,     GMMREG_PLMN_MODE_REQ),
+  MAK_FUNC_0(kern_gmmreg_config_req,        GMMREG_CONFIG_REQ),
+};
+
+#ifdef FF_EM_MODE
+static const T_FUNC em_ul_table[] =
+{
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x00 */
+  /*EM_SC_GPRS_INFO_REQ cannot be sent directly from ACI to GRR, because no SAP is defined.
+  So it have to be passed via GMM.*/
+  MAK_FUNC_0(em_gmm_sc_gprs_info_req,       EM_SC_GPRS_INFO_REQ     ), /* 0x01 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x02 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x03 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x04 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x05 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x06 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x07 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x08 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x09 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x0A */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x0B */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x0C */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x0D */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x0E */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x0F */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x10 */
+  MAK_FUNC_0(em_gmm_pco_trace_req   ,       EM_PCO_TRACE_REQ   ), /* 0x11*/ /*PCO output*/
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x12 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x13 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x14 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x15 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x16 */
+  MAK_FUNC_0(em_gmm_info_req,                EM_GMM_INFO_REQ   ), /* 0x17 */
+  /*EM_GRLC_INFO_REQ cannot be sent directly from ACI to GRLC, so it is passed via GMM*/
+  MAK_FUNC_0(em_gmm_grlc_info_req,          EM_GRLC_INFO_REQ        ),  /* 0x18 */
+  MAK_FUNC_N(primitive_not_supported,       0                       ), /* 0x19 */
+  MAK_FUNC_0(em_gmm_grr_event_req,          EM_GRR_EVENT_REQ        ), /* 0x1A */
+  MAK_FUNC_0(em_gmm_event_req,              EM_GMM_EVENT_REQ        ), /* 0x1B */
+  MAK_FUNC_0(em_gmm_grlc_event_req,         EM_GRLC_EVENT_REQ       ), /* 0x1C */
+  MAK_FUNC_0(em_gmm_throughput_info_req,    EM_THROUGHPUT_INFO_REQ  ) /* 0x1D */
+};
+
+static const T_FUNC em_dl_table[] =
+{
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x00 */
+/*EM_SC_GPRS_INFO_CNF cannot be sent directly from GRR to ACI, so it is passed via GMM*/
+  MAK_FUNC_0(em_gmm_sc_gprs_info_cnf,       EM_SC_GPRS_INFO_CNF      ), /* 0x01 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x02 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x03 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x04 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x05 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x06 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x07 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x08 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x09 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x0A */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x0B */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x0C */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x0D */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x0E */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x0F */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x10 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x11 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x12 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x13 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x14 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x15 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x16 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* 0x17 */
+/*EM_GRLC_INFO_CNF cannot be sent directly from ACI to GRLC, so it is passed via GMM*/
+  MAK_FUNC_0(em_gmm_grlc_info_cnf,          EM_GRLC_INFO_CNF         ), /* 0x18 */
+  MAK_FUNC_N(primitive_not_supported,       0                        ), /* 0x19 */
+  MAK_FUNC_N(primitive_not_supported,       0                        ), /* 0x1A */
+  MAK_FUNC_N(primitive_not_supported,       0                        ), /* 0x1B */
+  MAK_FUNC_N(primitive_not_supported,       0                        ), /* 0x1C */
+  MAK_FUNC_0(em_gmm_throughput_info_cnf,    EM_THROUGHPUT_INFO_CNF   ) /* 0x1D */
+};
+#endif /* FF_EM_MODE */  
+
+
+static const T_FUNC gmmrr_table[] =
+{
+  MAK_FUNC_0(sync_gmmrr_cell_ind,           GMMRR_CELL_IND),
+  MAK_FUNC_N(primitive_not_supported,       0                  ),
+  MAK_FUNC_0(kern_gmmrr_page_ind,           GMMRR_PAGE_IND),
+  MAK_FUNC_0(kern_gmmrr_cs_page_ind,        GMMRR_CS_PAGE_IND),
+  MAK_FUNC_0(kern_gmmrr_suspend_cnf,        GMMRR_SUSPEND_CNF),
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* TCS 2.1 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ),/* TCS 2.1 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* TCS 2.1 */
+  MAK_FUNC_0(kern_gmmrr_cr_ind,             GMMRR_CR_IND),
+};
+
+
+static const T_FUNC cgrlc_table[] = /* TCS 2.1 */
+{ /* TCS 2.1 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* TCS 2.1 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* TCS 2.1 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* TCS 2.1 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* TCS 2.1 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* TCS 2.1 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* TCS 2.1 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* TCS 2.1 */
+  MAK_FUNC_N(primitive_not_supported,       0                  ), /* TCS 2.1 */
+  MAK_FUNC_0(kern_cgrlc_status_ind,         CGRLC_STATUS_IND ), /* TCS 2.1 */
+  MAK_FUNC_0(kern_cgrlc_test_mode_cnf,      CGRLC_TEST_MODE_CNF ), /* TCS 2.1 */
+  MAK_FUNC_0(rdy_cgrlc_trigger_ind,         CGRLC_TRIGGER_IND ), /* TCS 2.1 */
+  MAK_FUNC_0(rdy_cgrlc_standby_state_ind,   CGRLC_STANDBY_STATE_IND ), /* TCS 2.1 */
+  MAK_FUNC_0(rdy_cgrlc_ready_state_ind,     CGRLC_READY_STATE_IND ), /* TCS 2.1 */
+}; /* TCS 2.1 */
+
+
+#ifndef GMM_TCS4
+static const T_FUNC gmmsm_table[] =
+{
+  MAK_FUNC_0(kern_gmmsm_establish_req,      GMMSM_ESTABLISH_REQ),
+  MAK_FUNC_S(tx_gmmsm_unitdata_req,         GMMSM_UNITDATA_REQ),
+  MAK_FUNC_0(kern_gmmsm_sequence_res,       GMMSM_SEQUENCE_RES),
+};
+#else   
+static const T_FUNC mmpm_table[] =
+{
+#ifdef REL99
+  MAK_FUNC_0(kern_gmmsm_pdp_status_req,    MMPM_PDP_CONTEXT_STATUS_REQ),
+#else
+  MAK_FUNC_0(primitive_not_supported,      MMPM_PDP_CONTEXT_STATUS_REQ),
+#endif
+  MAK_FUNC_N(primitive_not_supported,      0),
+  MAK_FUNC_N(primitive_not_supported,      0),
+  MAK_FUNC_0(kern_gmmsm_sequence_res,      MMPM_SEQUENCE_RES),
+  MAK_FUNC_S(tx_gmmsm_unitdata_req,        MMPM_UNITDATA_REQ),
+};
+
+#endif /* #ifndef GMM_TCS4 */
+
+static const T_FUNC gmmsms_table[] =
+{
+  MAK_FUNC_0(kern_gmmsms_reg_state_req,     GMMSMS_REG_STATE_REQ)
+};
+
+LOCAL const T_FUNC sim_table[] = {
+  MAK_FUNC_0 (primitive_not_supported      , SIM_READ_CNF           ), /* 0x00 */
+  MAK_FUNC_0 (primitive_not_supported      , SIM_UPDATE_CNF         ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_READ_RECORD_CNF    ),
+  MAK_FUNC_N (primitive_not_supported      , 0                      ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_UPDATE_RECORD_CNF  ),
+  MAK_FUNC_N (primitive_not_supported      , 0                      ),
+  MAK_FUNC_N (primitive_not_supported      , 0                      ),
+  MAK_FUNC_N (primitive_not_supported      , 0                      ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_INCREMENT_CNF      ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_VERIFY_PIN_CNF     ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_CHANGE_PIN_CNF     ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_DISABLE_PIN_CNF    ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_ENABLE_PIN_CNF     ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_UNBLOCK_CNF        ),
+  MAK_FUNC_0 (kern_sim_authentication_cnf       , SIM_AUTHENTICATION_CNF ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_MMI_INSERT_IND     ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_MM_INSERT_IND   ),  
+  MAK_FUNC_0 (kern_sim_remove_ind    , SIM_REMOVE_IND         ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_SYNC_CNF           ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_ACTIVATE_CNF       ),
+  MAK_FUNC_0 (primitive_not_supported      , SIM_SMS_INSERT_IND     ), /* 0x14 */
+  MAK_FUNC_0 (primitive_not_supported      , SIM_TOOLKIT_IND        ), /* 0x15 */
+  MAK_FUNC_0 (primitive_not_supported      , SIM_TOOLKIT_CNF        ), /* 0x16 */
+  MAK_FUNC_0 (primitive_not_supported      , SIM_ACTIVATE_IND       ), /* 0x17 */
+  MAK_FUNC_0 (primitive_not_supported      , SIM_MM_INFO_IND        ), /* 0x18 GMM GlumPs*/
+  MAK_FUNC_0 (primitive_not_supported      , SIM_ACCESS_CNF         ), /* 0x19 */
+  MAK_FUNC_0 (primitive_not_supported   , SIM_FILE_UPDATE_IND    ),  /* 0x1a */
+  MAK_FUNC_0 (kern_sim_gmm_insert_ind  , SIM_GMM_INSERT_IND   ),  /* 0x1b */
+};
+
+static const T_FUNC ll_table[] =
+{
+  MAK_FUNC_0(primitive_not_supported,       LL_RESET_IND),
+  MAK_FUNC_S(primitive_not_supported,       LL_ESTABLISH_CNF),
+  MAK_FUNC_S(primitive_not_supported,       LL_ESTABLISH_IND),
+  MAK_FUNC_0(primitive_not_supported,       LL_RELEASE_CNF),
+  MAK_FUNC_0(primitive_not_supported,       LL_RELEASE_IND),
+  MAK_FUNC_S(primitive_not_supported,       LL_XID_CNF),
+  MAK_FUNC_S(primitive_not_supported,       LL_XID_IND),
+  MAK_FUNC_0(primitive_not_supported,       LL_READY_IND),
+  MAK_FUNC_0(primitive_not_supported,       LL_UNITREADY_IND),
+  MAK_FUNC_0(primitive_not_supported,       LL_DATA_CNF),
+  MAK_FUNC_S(primitive_not_supported,       LL_DATA_IND),
+  MAK_FUNC_S(rx_ll_unitdata_ind,            LL_UNITDATA_IND)
+};
+
+static const T_FUNC llgmm_table[] =
+{
+  MAK_FUNC_0(kern_llgmm_status_ind,         LLGMM_STATUS_IND),
+  MAK_FUNC_0(kern_llgmm_tlli_ind,         LLGMM_TLLI_IND)
+};
+
+static const T_FUNC mmgmm_table[] =
+{
+  MAK_FUNC_0(sync_mmgmm_reg_cnf,            MMGMM_REG_CNF),
+  MAK_FUNC_0(sync_mmgmm_reg_rej,            MMGMM_REG_REJ),
+  MAK_FUNC_0(sync_mmgmm_nreg_ind,           MMGMM_NREG_IND),
+  MAK_FUNC_0(kern_mmgmm_nreg_cnf,           MMGMM_NREG_CNF),
+  MAK_FUNC_0(kern_mmgmm_plmn_ind,           MMGMM_PLMN_IND),
+  MAK_FUNC_0(kern_mmgmm_auth_rej_ind,       MMGMM_AUTH_REJ_IND),
+  MAK_FUNC_0(kern_mmgmm_cm_establish_ind,   MMGMM_CM_ESTABLISH_IND),
+  MAK_FUNC_0(kern_mmgmm_cm_release_ind,     MMGMM_CM_RELEASE_IND),
+  MAK_FUNC_0(sync_mmgmm_activate_ind,       MMGMM_ACTIVATE_IND),
+  MAK_FUNC_0(kern_mmgmm_t3212_val_ind,      MMGMM_T3212_VAL_IND),
+  MAK_FUNC_0(kern_mmgmm_info_ind,           MMGMM_INFO_IND),
+  MAK_FUNC_0(kern_mmgmm_cm_emergency_ind,   MMGMM_CM_EMERGENCY_IND),
+  MAK_FUNC_0(kern_mmgmm_lup_accept_ind,     MMGMM_LUP_ACCEPT_IND),
+  MAK_FUNC_0(kern_mmgmm_lup_needed_ind,     MMGMM_LUP_NEEDED_IND),
+  MAK_FUNC_0(kern_mmgmm_ciphering_ind,      MMGMM_CIPHERING_IND),
+  MAK_FUNC_0(kern_mmgmm_tmsi_ind,           MMGMM_TMSI_IND),
+  MAK_FUNC_0(kern_mmgmm_ahplmn_ind,         MMGMM_AHPLMN_IND)
+};
+
+
+/*==== PRIVATE FUNCTIONS ====================================================*/
+
+/*
++------------------------------------------------------------------------------
+|  Function    : primitive_not_supported
++------------------------------------------------------------------------------
+|  Description  :  This function handles unsupported primitives.
+|
+|  Parameters  :  -
+|
+|  Return      :  -
+|
++------------------------------------------------------------------------------
+*/
+LOCAL void primitive_not_supported (void *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.
+|
+|                             |
+|                          GMMREG
+|                       |     |     |     |
+|                     GMMSM   |   GMMSM GMMAA             UPLINK
+|                       |     |     |     |
+|                   +---v-----v-----v-----v----+
+|                   |                          |
+|         MMGMM ---->           GMM            |
+|                   |                          |
+|                   +---^--------^--------^----+
+|                       |        |        |
+|                       |        |      LLGMM            DOWNLINK
+|                       |      GMMRR      |
+|                       |        |
+|                     SIM
+|                       |
+|
+|
+|  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");
+#ifdef TRACE_FUNC
+#ifdef IDENTATION
+  gmm_data->deep=0;
+#endif
+#endif
+
+  if (primptr NEQ NULL)
+  {
+    T_PRIM *prim  = (T_PRIM *)primptr;
+    ULONG           opc = prim->custom.opc;
+    USHORT           n;
+    const T_FUNC    *table;
+
+    /*
+     * This must be called for Partition Pool supervision. Will be replaced
+     * by another macro some time.
+     */
+    VSI_PPM_REC (&prim->custom, __FILE__, __LINE__);
+
+    GMM_TRACE_GMM_DATA(GMM_DEBUG_PRINT_MASK_STATE);
+    PTRACE_IN (opc);
+
+    switch (SAP_NR(opc))
+    {
+      case GMMREG_UL:
+        table = gmmreg_table;
+        n = TAB_SIZE (gmmreg_table);
+        break;
+      case GMMRR_DL:
+        table = gmmrr_table;
+        n = TAB_SIZE (gmmrr_table);
+        break;      
+      case SAP_NR(CGRLC_DL):  /* TCS 2.1 */
+        table = cgrlc_table;  /* TCS 2.1 */
+        n = TAB_SIZE (cgrlc_table); /* TCS 2.1 */
+        break; /* TCS 2.1 */
+#ifndef GMM_TCS4
+      case GMMSM_UL:
+        table = gmmsm_table;
+        n = TAB_SIZE (gmmsm_table);
+        break;
+#else
+      case SAP_NR(MMPM_UL):
+        table = mmpm_table;
+        n = TAB_SIZE (mmpm_table);
+        break;
+#endif
+      case GMMSMS_UL:
+        table = gmmsms_table;
+        n = TAB_SIZE (gmmsms_table);
+        break;
+      case SAP_NR(SIM_UL):/*lint !e778 (Info -- Constant expression evaluates to 0 in operation '&') */
+        table = sim_table;
+        n = TAB_SIZE (sim_table);
+        break;
+      case LL_DL:
+        table = ll_table;
+        n = TAB_SIZE (ll_table);
+        break;
+      case LLGMM_DL:
+        table = llgmm_table;
+        n = TAB_SIZE (llgmm_table);
+        break;
+      case MMGMM_DL:
+        table = mmgmm_table;
+        n = TAB_SIZE (mmgmm_table);
+        break;
+#ifdef FF_EM_MODE
+      case EM_Ul:
+        table = em_ul_table;
+        n = TAB_SIZE (em_ul_table);
+        break;
+      case EM_Dl:
+        table = em_dl_table;
+        n = TAB_SIZE (em_dl_table);
+        break;
+#endif /* FF_EM_MODE */
+      default:
+        TRACE_ERROR("pei_primitive. Unknown SAP");
+        table = NULL;
+        n = 0;
+        break;
+    }
+
+    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 */
+
+        /*******************************************************
+         * SAVE prim
+         *******************************************************/
+
+        if( gmm_pei_handle_save( prim, &save_queue, save_tab, table->func )
+          ==  PEI_SIGNAL_NOT_SAVED )
+        {
+          UBYTE old_kern_state = gmm_data->kern.state;
+          /*******************************************************
+           * SAVE prim
+           *******************************************************/
+
+          JUMP (table->func) (P2D(prim));
+          
+          /*******************************************************
+           * SAVE prim
+           *******************************************************/
+          if( gmm_data->kern.state != old_kern_state )
+          {
+            gmm_pei_handle_queue(&save_queue, save_tab);
+          }
+        } 
+        else
+        {
+          TRACE_2_INFO ("S:%2d SAVE of Primitive 0x%x", gmm_data->kern.state, opc );
+        }
+
+
+
+        /*******************************************************
+         * End SAVE 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
+   */
+  GMM_handle = handle;
+
+  /*
+   * Open communication channels
+   */
+  if (hCommSMS < VSI_OK)
+  {
+    if ((hCommSMS = vsi_c_open (VSI_CALLER SMS_NAME)) < VSI_OK)
+      return PEI_ERROR;
+  }
+  if (hCommSM < VSI_OK)
+  {
+    if ((hCommSM = vsi_c_open (VSI_CALLER SM_NAME)) < VSI_OK)
+      return PEI_ERROR;
+  }
+  if (hCommGRLC < VSI_OK) /* TCS 2.1 */
+  { /* TCS 2.1 */
+    if ((hCommGRLC = vsi_c_open (VSI_CALLER GRLC_NAME)) < VSI_OK) /* TCS 2.1 */
+      return PEI_ERROR; /* TCS 2.1 */
+  } /* TCS 2.1 */
+
+  if (hCommGRR < VSI_OK)
+  {
+    if ((hCommGRR = vsi_c_open (VSI_CALLER GRR_NAME)) < VSI_OK)
+      return PEI_ERROR;
+  }
+  if (hCommLLC < VSI_OK)
+  {
+    if ((hCommLLC = vsi_c_open (VSI_CALLER LLC_NAME)) < VSI_OK)
+      return PEI_ERROR;
+  }
+  if (hCommSIM < VSI_OK)
+  {
+    if ((hCommSIM = vsi_c_open (VSI_CALLER SIM_NAME)) < VSI_OK)
+      return PEI_ERROR;
+  }
+  if (hCommMM < VSI_OK)
+  {
+    if ((hCommMM = vsi_c_open (VSI_CALLER MM_NAME)) < VSI_OK)
+      return PEI_ERROR;
+  }
+  if (hCommMMI < VSI_OK)
+  {
+    if ((hCommMMI = vsi_c_open (VSI_CALLER ACI_NAME)) < VSI_OK) /* TCS 2.1 */
+      return PEI_ERROR;
+  }
+  if (hCommGMM < VSI_OK)
+  {
+    if ((hCommGMM = vsi_c_open (VSI_CALLER GMM_NAME)) < VSI_OK)
+      return PEI_ERROR;
+  }
+#ifdef GMM_TCS4
+  if (hCommUPM < VSI_OK)
+  {
+    if ((hCommUPM = vsi_c_open (VSI_CALLER UPM_NAME)) < VSI_OK)
+      return PEI_ERROR;
+  }
+#endif
+
+
+  /*
+   * Initialize global pointer llc_data. This is required to access all
+   * entity data.
+   */
+  gmm_data = &gmm_data_base;
+
+  /*
+   * Initialite ccd
+   */
+  ccd_init ();
+
+#ifdef FF_EM_MODE
+  em_init_gmm_event_trace();
+#endif /* FF_EM_MODE */
+
+
+  /*
+   * Initialize entity data (call init function of every service)
+   */
+
+  kern_init();
+  rxgmm_init();
+  txgmm_init();
+  rdy_init();
+  sync_gmm_init();
+
+  GMM_TRACE_GMM_DATA(GMM_DEBUG_PRINT_MASK_FULL);
+
+  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)
+{
+  UBYTE      old_kern_state;
+  TRACE_FUNCTION ("pei_timeout");
+
+  old_kern_state = gmm_data->kern.state;
+  /*
+   * Process timeout
+   */
+  switch (index)
+  {
+    case kern_T3302:
+      /*
+       * T3302 expired.
+       */
+      kern_t3302 ();
+      break;
+    case kern_T3310:
+      /*
+       * T3310 expired.
+       */
+      kern_t3310 ();
+      break;
+    case kern_T3311:
+      /*
+       * T3311 expired.
+       */
+      kern_t3311 ();
+      break;
+    case kern_T3321:
+      /*
+       * T3321 expired.
+       */
+      kern_t3321 ();
+      break;
+    case rdy_T3312:
+      /*
+       * T3312 expired.
+       */
+      kern_t3312 ();
+      break;
+    case kern_TPOWER_OFF:
+      kern_tpower_off();
+      break;
+    case kern_TLOCAL_DETACH:
+      kern_tlocal_detach();
+      break;
+    case sync_TSYNC:
+      sync_tsync();
+      break;
+    default:
+      TRACE_ERROR("Unknown Timeout");
+      return PEI_ERROR;
+  }
+
+  if( gmm_data->kern.state != old_kern_state )
+  {
+    gmm_pei_handle_queue(  &save_queue, save_tab);
+  }
+  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
+   */
+  switch (opc)
+  {
+    default:
+      TRACE_ERROR("Unknown Signal OPC");
+      break;
+  }/*lint !e764 (Info -- switch statement does not have a case) */
+
+  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 hCommSMS);
+  hCommSMS = VSI_ERROR;
+
+  vsi_c_close (VSI_CALLER hCommSM);
+  hCommSM = VSI_ERROR;
+
+  vsi_c_close (VSI_CALLER hCommGRLC); /* TCS 2.1 */
+  hCommGRLC = VSI_ERROR; /* TCS 2.1 */
+
+  vsi_c_close (VSI_CALLER hCommGRR);
+  hCommGRR = VSI_ERROR;
+
+  vsi_c_close (VSI_CALLER hCommLLC);
+  hCommLLC = VSI_ERROR;
+
+  vsi_c_close (VSI_CALLER hCommSIM);
+  hCommSIM = VSI_ERROR;
+
+  vsi_c_close (VSI_CALLER hCommMM);
+  hCommMM = VSI_ERROR;
+
+  vsi_c_close (VSI_CALLER hCommMMI);
+  hCommMMI = VSI_ERROR;
+
+  vsi_c_close (VSI_CALLER hCommGMM);
+  hCommGMM = VSI_ERROR;
+
+  /*
+   * delete queues
+   */
+  gmm_pei_delete_queue(&save_queue);
+  
+  /*
+   * close ccd
+   */
+  ccd_exit ();
+
+  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 )
+{
+  return PEI_OK;
+}
+
+
+/*
++------------------------------------------------------------------------------
+|  Function    : gmm_tok_key
++------------------------------------------------------------------------------
+|  Description  : This function is used by pei_config in windows test
+|                 environment for string tokenizing for CHECK STATE command, e.g.
+|                 COMMAND("GMM CONFIG CHECK_STATE=<REG_NORMAL_SERVICE>");
+|
+|
+|  Parameters  :  
+|
+|  Return      :  
+|               
+|
++------------------------------------------------------------------------------
+*/
+#ifndef _TARGET_
+typedef struct KW_STATE_DATA
+{
+   char   keyword[60];
+   SHORT  code;
+} KW_STATE_DATA;
+
+LOCAL SHORT gmm_tok_key (KW_STATE_DATA * keytab, char * keyword)
+{
+  /*
+   * Empty string terminates
+   */
+  while (keytab->keyword[0])
+  {
+    if (strcmp (keytab->keyword, keyword ) == 0)
+      return (keytab->code);
+    keytab++;
+  }
+
+  return (TOK_NOT_FOUND);
+}
+#endif
+
+/*
++------------------------------------------------------------------------------
+|  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);
+
+#ifndef NCONFIG
+   /*
+   * Parse next keyword and number of variables
+   */
+    if(!strcmp(inString,"PERIODIC_LAU"))
+    {
+      PALLOC (mmgmm_lup_needed_ind, MMGMM_LUP_NEEDED_IND);
+      mmgmm_lup_needed_ind->reason = MMGMM_T3212; /* TCS 2.1 */
+      TRACE_EVENT(  "Info: Periodic LAU requested by MM");
+      PSEND (hCommGMM, mmgmm_lup_needed_ind);
+    }
+    else if(!strcmp(inString,"PERIODIC_RAU"))
+    {
+      kern_t3312();
+    }
+    else if(!strcmp(inString,"REATTACH"))
+    {
+      PALLOC (gmmrr_page_ind,  GMMRR_PAGE_IND);
+        gmmrr_page_ind->page_id=GMMRR_IMSI;
+      PSEND (hCommGMM, gmmrr_page_ind);
+    }
+    else if(!strcmp(inString,"CELL"))
+    {
+      PALLOC (gmmrr_cell_ind,  GMMRR_CELL_IND);
+      gmmrr_cell_ind->cell_info.service_state=GMMRR_SERVICE_FULL;
+      gmmrr_cell_ind->cell_info.cell_env.rai.lac=0x2506;
+      gmmrr_cell_ind->cell_info.cell_env.rai.rac=0x71;
+      gmmrr_cell_ind->cell_info.net_mode=gmm_data->config.nmo;
+      PSEND (hCommGMM, gmmrr_cell_ind);
+    }
+    else if(!strcmp(inString,"NMO_I"))
+    {
+      gmm_data->config.nmo = GMMRR_NET_MODE_I;
+    }
+    else if(!strcmp(inString,"NMO_II"))
+    {
+      gmm_data->config.nmo = GMMRR_NET_MODE_II;
+    }
+    else if(!strcmp(inString,"NMO_III"))
+    {
+      gmm_data->config.nmo = GMMRR_NET_MODE_III;
+    }
+    else if(!strcmp(inString,"GMM_INFO"))
+    {
+      PALLOC (gmmreg_info_ind,  GMMREG_INFO_IND);
+      PSEND (hCommMMI, gmmreg_info_ind);
+    }
+
+    else if(!strcmp(inString,"RESET_SIM"))
+    {
+      gmm_data->sim_gprs_invalid = TRUE;
+      kern_sim_del_locigprs ();
+      kern_sim_gmm_update();
+      kern_mm_auth_rej();
+      {
+        PALLOC (sim_update_req, SIM_UPDATE_REQ);
+
+        sim_update_req->source         = SRC_GMM;
+        /* req_id is not filled since response is not handled */
+
+        sim_update_req->v_path_info    = FALSE;
+
+        sim_update_req->datafield      = SIM_FPLMN;
+        sim_update_req->length         = 12;
+        memset (sim_update_req->trans_data,0xff,12);
+        sim_update_req->offset         = 0;
+
+        PSEND (hCommSIM, sim_update_req);
+      }
+      {
+        PALLOC (sim_update_req, SIM_UPDATE_REQ);
+
+        sim_update_req->source         = SRC_GMM;
+
+        /* req_id is not filled since response is not handled */        
+        sim_update_req->v_path_info    = FALSE;
+
+        sim_update_req->datafield      = SIM_LOCI;
+        sim_update_req->length         = 11;
+        memset (sim_update_req->trans_data,0xff,8);
+        sim_update_req->trans_data[8]=0xfe;
+        sim_update_req->trans_data[9]=0x0;
+        sim_update_req->trans_data[10]=GU2_NOT_UPDATED;
+        sim_update_req->offset         = 0;
+
+        PSEND (hCommSIM, sim_update_req);
+      }
+    }
+    else if(!strcmp(inString,"ANITE"))
+    {
+      gmm_data->anite = TRUE;
+    }
+    else if(!strcmp(inString,"CIPHER_OFF"))
+    {
+      gmm_data->config.cipher_on =   0x00;
+      TRACE_EVENT ("ciphering switched OFF");
+    }
+    else if(!strcmp(inString,"CIPHER_ON"))
+    {
+      gmm_data->config.cipher_on |= 0x01;
+    }
+    else if(!strcmp(inString,"PREUSE_OFF"))
+    {
+      gmm_data->config.preuse_off =    TRUE;
+    }
+
+#ifdef REL99
+    else if(!strcmp(inString,"CL_SGSN_REL_98_OR_OLDER")) /* TCS 4.0 */
+    { /* TCS 4.0 */
+      /*gmm_data->config.sgsnr_flag =    R_98NW; */
+      cl_nwrl_set_sgsn_release(PS_SGSN_98_OLDER); /*CL function*/ /* TCS 4.0 */
+    } /* TCS 4.0 */
+    else if(!strcmp(inString,"CL_SGSN_REL_99_ONWARDS")) /* TCS 4.0 */
+    { /* TCS 4.0 */
+      /* gmm_data->config.sgsnr_flag =    R_99NW; */
+      cl_nwrl_set_sgsn_release(PS_SGSN_99_ONWARDS); /*CL function*/ /* TCS 4.0 */
+    } /* TCS 4.0 */
+    else if (!strcmp(inString,"CELL_NOTIFY_ON")) /* TCS 4.0 */
+    { /* TCS 4.0 */
+      gmm_data->config.cell_notification = FIRST_CELL_NOTIFY; /* TCS 4.0 */
+    } /* TCS 4.0 */
+    else if (!strcmp(inString, "CELL_NOTIFY_OFF")) /* TCS 4.0 */
+    { /* TCS 4.0 */
+      gmm_data->config.cell_notification = NO_CELL_NOTIFY; /* TCS 4.0 */
+    } /* TCS 4.0 */
+#endif
+
+#ifdef _SIMULATION_    
+    else if(!strcmp(inString, "NEXT_TIMEOUT"))
+    {
+      T_TIME old_value = 0;
+      T_TIME new_value = 0;
+      USHORT timer;
+      USHORT timeout = TIMER_MAX;
+    
+      /* Find next timer to timeout */    
+      
+      for(timer = 0; timer < TIMER_MAX; timer++)
+      {
+        if ( VSI_OK == vsi_t_status ( GMM_handle ,timer, &new_value ))
+        {
+          if (new_value >0 )
+          {
+            if((old_value==0)||
+               (new_value < old_value))
+            {
+              old_value = new_value;
+              timeout = timer;        
+            }
+          }
+        }
+      }
+
+      
+      /* Force timeout */
+      if(TIMER_MAX != timeout )
+      {
+        TRACE_1_INFO("gmm_pei_config - forcing timeout:%d", timeout);
+        
+        vsi_t_stop ( GMM_handle, timeout);       
+
+        for(timer = 0; timer < TIMER_MAX ; timer++)
+        {
+          if ( VSI_OK == vsi_t_status ( GMM_handle ,timer, &new_value ))
+          {
+            if (timer!=timeout )
+            {
+              if (new_value>0 && new_value-old_value >0 )
+              {
+                vsi_t_start ( GMM_handle , timer, new_value-old_value ); 
+              }
+            }
+          }
+        }
+
+        pei_timeout(timeout);
+      }
+    }
+#endif
+
+#define GMM_CONFIG_DRX               1
+#define GMM_CONFIG_GEA            2
+
+#ifndef _TARGET_
+#define GMM_CONFIG_CHECK_STATE       3
+#endif
+
+#define GMM_DRX               "DRX"
+#define GMM_GEA               "GEA"
+
+#ifndef _TARGET_
+#define GMM_CHECK_STATE       "CHECK_STATE"
+
+#define GMM_NULL_NO_IMSI                      "NULL_NO_IMSI"
+#define GMM_NULL_IMSI                         "NULL_IMSI"
+#define GMM_DEREG_INITIATED                   "DEREG_INITIATED"  
+#define GMM_DEREG_ATTEMPTING_TO_ATTACH        "DEREG_ATTEMPTING_TO_ATTACH"
+#define GMM_DEREG_NO_CELL_AVAILABLE           "DEREG_NO_CELL_AVAILABLE"
+#define GMM_DEREG_LIMITED_SERVICE             "DEREG_LIMITED_SERVICE"
+#define GMM_DEREG_NO_IMSI                     "DEREG_NO_IMSI"
+#define GMM_DEREG_PLMN_SEARCH                 "DEREG_PLMN_SEARCH"
+#define GMM_DEREG_SUSPENDED                   "DEREG_SUSPENDED"
+
+#define GMM_REG_INITIATED                     "REG_INITIATED"
+
+#define GMM_REG_NO_CELL_AVAILABLE             "REG_NO_CELL_AVAILABLE"
+#define GMM_REG_LIMITED_SERVICE               "REG_LIMITED_SERVICE"
+#define GMM_REG_ATTEMPTING_TO_UPDATE_MM       "REG_ATTEMPTING_TO_UPDATE_MM  "
+#define GMM_REG_ATTEMPTING_TO_UPDATE          "REG_ATTEMPTING_TO_UPDATE"
+#define GMM_REG_RESUMING                      "REG_RESUMING"
+#define GMM_REG_SUSPENDED                     "REG_SUSPENDED"
+#define GMM_REG_NORMAL_SERVICE                "REG_NORMAL_SERVICE"
+
+#define GMM_RAU_INITIATED                     "RAU_INITIATED"
+
+#define GMM_RAU_WAIT_FOR_NPDU_LIST            "RAU_WAIT_FOR_NPDU_LIST"
+
+#define GMM_REG_IMSI_DETACH_INITIATED         "REG_IMSI_DETACH_INITIATED"
+
+#define GMM_DEREG_SUSPENDING                  "DEREG_SUSPENDING"
+#define GMM_DEREG_RESUMING                    "DEREG_RESUMING"
+
+#define GMM_REG_SUSPENDING                    "REG_SUSPENDING"
+#define GMM_NULL_NO_IMSI_LIMITED_SERVICE_REQ     "NULL_NO_IMSI_LIMITED_SERVICE_REQ"
+#define GMM_NULL_IMSI_LIMITED_SERVICE_REQ     "NULL_IMSI_LIMITED_SERVICE_REQ"
+#define GMM_REG_TEST_MODE                     "REG_TEST_MODE"
+#define GMM_NULL_PLMN_SEARCH                  "NULL_PLMN_SEARCH"
+#define GMM_REG_TEST_MODE_NO_IMSI             "REG_TEST_MODE_NO_IMSI "
+
+#endif
+    
+    {   
+      LOCAL KW_DATA kwtab[] = 
+      {
+        GMM_DRX, GMM_CONFIG_DRX,
+        GMM_GEA, GMM_CONFIG_GEA,
+#ifndef _TARGET_
+        GMM_CHECK_STATE, GMM_CONFIG_CHECK_STATE,
+#endif
+        "", 0  
+      };
+#ifndef _TARGET_
+      LOCAL KW_STATE_DATA kw_state_tab[] = 
+      {
+         GMM_NULL_NO_IMSI                      ,KERN_GMM_NULL_NO_IMSI,
+         GMM_NULL_IMSI                         ,KERN_GMM_NULL_IMSI,
+         GMM_DEREG_INITIATED                   ,KERN_GMM_DEREG_INITIATED,  
+         GMM_DEREG_ATTEMPTING_TO_ATTACH        ,KERN_GMM_DEREG_ATTEMPTING_TO_ATTACH,
+         GMM_DEREG_NO_CELL_AVAILABLE           ,KERN_GMM_DEREG_NO_CELL_AVAILABLE,
+         GMM_DEREG_LIMITED_SERVICE             ,KERN_GMM_DEREG_LIMITED_SERVICE,
+         GMM_DEREG_NO_IMSI                     ,KERN_GMM_DEREG_NO_IMSI,
+         GMM_DEREG_PLMN_SEARCH                 ,KERN_GMM_DEREG_PLMN_SEARCH,
+         GMM_DEREG_SUSPENDED                   ,KERN_GMM_DEREG_SUSPENDED,
+
+         GMM_REG_INITIATED                     ,KERN_GMM_REG_INITIATED,
+
+         GMM_REG_NO_CELL_AVAILABLE             ,KERN_GMM_REG_NO_CELL_AVAILABLE,
+         GMM_REG_LIMITED_SERVICE               ,KERN_GMM_REG_LIMITED_SERVICE,
+         GMM_REG_ATTEMPTING_TO_UPDATE_MM       ,KERN_GMM_REG_ATTEMPTING_TO_UPDATE_MM  ,
+         GMM_REG_ATTEMPTING_TO_UPDATE          ,KERN_GMM_REG_ATTEMPTING_TO_UPDATE,
+         GMM_REG_RESUMING                      ,KERN_GMM_REG_RESUMING,
+         GMM_REG_SUSPENDED                     ,KERN_GMM_REG_SUSPENDED,
+         GMM_REG_NORMAL_SERVICE                ,KERN_GMM_REG_NORMAL_SERVICE,
+
+         GMM_RAU_INITIATED                     ,KERN_GMM_RAU_INITIATED,
+
+         GMM_RAU_WAIT_FOR_NPDU_LIST            ,KERN_GMM_RAU_WAIT_FOR_NPDU_LIST,
+
+         GMM_REG_IMSI_DETACH_INITIATED         ,KERN_GMM_REG_IMSI_DETACH_INITIATED,
+
+         GMM_DEREG_SUSPENDING                  ,KERN_GMM_DEREG_SUSPENDING,
+         GMM_DEREG_RESUMING                    ,KERN_GMM_DEREG_RESUMING,
+         GMM_REG_SUSPENDING                    ,KERN_GMM_REG_SUSPENDING,
+         
+         GMM_NULL_NO_IMSI_LIMITED_SERVICE_REQ     ,KERN_GMM_NULL_NO_IMSI_LIMITED_SERVICE_REQ,
+         GMM_NULL_IMSI_LIMITED_SERVICE_REQ     ,KERN_GMM_NULL_IMSI_LIMITED_SERVICE_REQ,
+         GMM_REG_TEST_MODE                     ,KERN_GMM_REG_TEST_MODE,
+         GMM_NULL_PLMN_SEARCH                  ,KERN_GMM_NULL_PLMN_SEARCH,
+         GMM_REG_TEST_MODE_NO_IMSI             ,KERN_GMM_REG_TEST_MODE_NO_IMSI ,
+        "", 0  
+      };
+
+#endif
+      SHORT valno;
+      char *keyw;
+      char *val[10];
+      
+      tok_init (inString);
+
+      while((valno = tok_next(&keyw,val)) NEQ TOK_EOCS)
+      {
+        switch ((tok_key((KW_DATA *)kwtab, keyw)))
+        {
+          case GMM_CONFIG_DRX:
+            if (3==valno)
+            {
+              TRACE_EVENT ("use of DRX <split_pg_cycle_code,split_on_ccch,non_drx_timer>");
+              gmm_data->drx_parameter.split_pg_cycle_code = atoi (val[0]);
+              gmm_data->drx_parameter.split_on_ccch       = atoi (val[1]);
+              gmm_data->drx_parameter.non_drx_timer       = atoi (val[2]);
+            }
+            else
+            {
+              TRACE_ERROR("[PEI_CONFIG]: use CONFIG DRX <1,2,3>");
+            }
+            break;
+          case GMM_CONFIG_GEA:
+            if (1==valno)
+            {
+              TRACE_EVENT ("GEA=<bit_field of wanted GEA in dec>");
+              
+              gmm_data->config.cipher_on |= atoi (val[0]);
+              TRACE_1_INFO("GEA2=%d", (gmm_data->config.cipher_on & 0x02)>0);
+              TRACE_1_INFO("GEA3=%d", (gmm_data->config.cipher_on & 0x04)>0);
+              TRACE_1_INFO("GEA4=%d", (gmm_data->config.cipher_on & 0x08)>0);
+              TRACE_1_INFO("GEA5=%d", (gmm_data->config.cipher_on & 0x10)>0);
+              TRACE_1_INFO("GEA6=%d", (gmm_data->config.cipher_on & 0x20)>0);
+              TRACE_1_INFO("GEA7=%d", (gmm_data->config.cipher_on & 0x40)>0);
+            }
+            else
+            {
+              TRACE_ERROR("[PEI_CONFIG]: use CONFIG GEA=<0-255>//255 means all GEA wanted");
+            }
+            break;
+#ifndef _TARGET_
+          case GMM_CONFIG_CHECK_STATE:
+            if(1==valno)
+            {
+              if (gmm_tok_key ((KW_STATE_DATA *)kw_state_tab, val[0])!=GET_STATE(KERN))
+              {
+                PALLOC ( cgrlc_status_ind, CGRLC_STATUS_IND ); /* TCS 2.1 */
+                PSEND ( hCommGMM, cgrlc_status_ind ); /* TCS 2.1 */
+                TRACE_1_OUT_PARA(   "neq %s", val[0]);
+                TRACE_ERROR("state wrong");
+              }
+              else
+              {
+                TRACE_1_INFO("state %s ok",val[0]);
+              }
+            }
+            else
+            {
+              TRACE_ERROR("[PEI_CONFIG]: USE CONFIG CHECK_STATE <state>");
+            }
+            break;
+#endif            
+          default:
+            break;
+        }
+      }
+    }
+#endif
+    return PEI_OK;
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function    : pei_monitor
++------------------------------------------------------------------------------
+|  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).
+   */
+  gmm_mon.version = "GMM 0.1";
+  *out_monitor = &gmm_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 =
+              {
+               "GMM",         /* name */
+               {              /* pei-table */
+                 pei_init,
+                 pei_exit,
+                 pei_primitive,
+                 pei_timeout,
+                 pei_signal,
+                 pei_run,
+                 pei_config,
+                 pei_monitor
+               },
+               2048,          /* stack size */
+               25,            /* queue entries */
+               190,           /* priority (1->low, 255->high) */
+               TIMER_MAX,     /* number of timers */
+               0x03|PRIM_NO_SUSPEND /* flags: bit 0   active(0) body/passive(1) */
+              };              /*        bit 1   com by copy(0)/reference(1) */
+
+
+  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);
+}
+
+/*
++------------------------------------------------------------------------------
+| Function    : gmm_pei_handle_queue
++------------------------------------------------------------------------------
+| Description : This function searches for the first stored primitive, which
+|               must not be saved further in current state.
+|
+| Parameters  : state     - current state of the instance
+|               queue     - PtrPtr to the hanger of the instance save queue
+|               table     - Ptr to the state/signals-to-save table
+|               inst_data - Ptr to instance data
++------------------------------------------------------------------------------
+*/
+LOCAL void gmm_pei_handle_queue( T_SAVE_QUEUE** queue,
+                                      const T_SAVE_TAB* table)
+{
+  /* search for a T_SAVE_TAB entry which fits to current state */
+  if( *queue )
+    while( table->state != PEI_END_SAVETAB && table->state != gmm_data->kern.state )
+      table++;
+
+  while( *queue )
+  {
+    T_SAVE_QUEUE* current = *queue;
+    ULONG  opc            = ((T_PRIM_HEADER*)current->prim)->opc;
+    USHORT n              = 0;
+
+    if( table->state != PEI_END_SAVETAB )
+    {
+      /* search for this signals in savelist of this state */
+      while( n < GMM_MAX_SIGNALS_SAVED && table->signal[n] &&
+             table->signal[n] != opc                       )
+        n++;
+    }
+
+    if( table->signal[n] != opc )
+    {
+      TRACE_1_INFO ("Pimitive 0x%x send from SAVE queue",
+                    ((T_PRIM_HEADER*)current->prim)->opc );
+      /* this signal must not further be stored -> handle it now */
+      /* first remove it from save queue, because of recursion!! */
+      *queue = current->next;
+      gmm_pei_handle_prim(current->func, current->prim );
+      /* and free memory after last use */
+      MFREE( current );
+
+      /* recursion! handle at maximum one prim at once -> job done */
+      return;
+    }
+
+    /* goto next queued signal */
+    queue = &((*queue)->next);
+  }
+}
+/*
++------------------------------------------------------------------------------
+| Function    : gmm_pei_delete_queue
++------------------------------------------------------------------------------
+| Description : This function removes all stored primitives from the queue and
+|               frees the memory.
+|
+| Parameters  : queue    - PtrPtr to the hanger of the instance save queue
++------------------------------------------------------------------------------
+*/
+GLOBAL void gmm_pei_delete_queue( T_SAVE_QUEUE** queue )
+{
+  while( *queue )
+  {
+    T_SAVE_QUEUE* current = *queue;
+
+
+    TRACE_1_INFO( "Pimitive 0x%x deleted from SAVE queue",
+                                         ((T_PRIM_HEADER*)current->prim)->opc );
+
+    *queue = current->next;
+    PFREE( P2D(current->prim) );
+    MFREE( current );
+  }
+}
+/*
++------------------------------------------------------------------------------
+| Function    : gmm_pei_handle_prim
++------------------------------------------------------------------------------
+| Description : This function calls the handle function of the signal
+|
+| Parameters  : func       - Function, which should handle the signal
+|               inst_data  - Ptr to instance data
+|               *prim      - Ptr to primitive
++------------------------------------------------------------------------------
+*/
+LOCAL void gmm_pei_handle_prim( T_VOID_FUNC func, void* prim )
+{
+  JUMP(func)( P2D(prim));
+
+  gmm_pei_handle_queue(   &save_queue, save_tab);
+}
+/*
++------------------------------------------------------------------------------
+| Function    : gmm_pei_handle_save
++------------------------------------------------------------------------------
+| Description : This function saves the prim pointer to the save queue, if
+|               this is necessary in current state.
+|
+| Parameters  : *prim    - Ptr to primitive
+|               state    - Current state of the instance
+|               queue    - PtrPtr to the hanger of the instance save queue
+|               table    - Ptr to the state/signals-to-save table
+|               func     - Function, which should handle the signal
+|
+| Returns     : PEI_SIGNAL_SAVED      - if signal is stored to save queue
+|               PEI_SIGNAL_NOT_SAVED  - else
++------------------------------------------------------------------------------
+*/
+LOCAL BOOL gmm_pei_handle_save( void* prim, T_SAVE_QUEUE** queue,
+                                     const T_SAVE_TAB* table, T_VOID_FUNC func  )
+{
+  ULONG opc = ((T_PRIM_HEADER*)prim)->opc;
+
+  while( table->state != PEI_END_SAVETAB )
+  {
+    if( table->state == gmm_data->kern.state )
+    {
+      UBYTE n = 0;
+
+      /* check for signals to save */
+      while( n < GMM_MAX_SIGNALS_SAVED && table->signal[n] )
+      {
+        if( table->signal[n] == opc )
+        {
+          /* store signal to end of save queue */
+          while( *queue )
+            queue = &((*queue)->next);
+
+          MALLOC( *queue, sizeof(T_SAVE_QUEUE) );
+
+          if( *queue )
+          {
+            (*queue)->prim = prim;
+            (*queue)->func = func;
+            (*queue)->next = NULL;
+          }
+          else
+          {
+            TRACE_ERROR( "Out of memory in mm_pei_handle_save()" );
+            return PEI_SIGNAL_NOT_SAVED;
+          }
+
+          return PEI_SIGNAL_SAVED;
+        }
+
+        /* goto next signal */
+        n++;
+      }
+
+      break;
+    }
+
+    /* gote next entry */
+    table++;
+  }
+
+  return PEI_SIGNAL_NOT_SAVED;
+}
+
+/*==== END OF FILE ==========================================================*/