diff gsm-fw/g23m-gsm/rr/rr_datp.c @ 673:2f7df7a314f8

gsm-fw/g23m-gsm subtree: initial import from LoCosto source
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 28 Sep 2014 23:20:04 +0000
parents
children 9924ad35640f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gsm-fw/g23m-gsm/rr/rr_datp.c	Sun Sep 28 23:20:04 2014 +0000
@@ -0,0 +1,1992 @@
+/*
++-----------------------------------------------------------------------------
+|  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 Modul defines the functions for the data transfer
+|             capability of the module Radio Resource.
++-----------------------------------------------------------------------------
+*/
+
+#ifndef RR_DATP_C
+#define RR_DATP_C
+
+#define ENTITY_RR
+
+/*==== INCLUDES ===================================================*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>     /* offsetof */
+#include <stdio.h>      /* sprintf */
+#include "typedefs.h"
+#include "pcm.h"
+#include "pconst.cdg"
+#include "mconst.cdg"
+#include "message.h"
+#include "ccdapi.h"
+#include "vsi.h"
+#include "custom.h"
+#include "gsm.h"
+#include "prim.h"
+#include "cnf_rr.h"
+#include "tok.h"
+#include "rr.h"
+#include "rr_em.h"
+
+/*==== EXPORT =====================================================*/
+#if defined (REL99) && defined (TI_PS_FF_EMR)
+#define MAX_MSTRUCT_CCD_RR MAXIMUM(MAX_MSTRUCT_LEN_RR_SHORT, MAX_MSTRUCT_LEN_RR)
+GLOBAL UBYTE _decodedMsg [MAX_MSTRUCT_CCD_RR];
+#else
+GLOBAL UBYTE _decodedMsg [MAX_MSTRUCT_LEN_RR];
+#endif
+
+
+/*==== PRIVAT =====================================================*/
+
+/*==== VARIABLES ==================================================*/
+
+/*==== FUNCTIONS ==================================================*/
+
+/*
+ * -------------------------------------------------------------------
+ * PRIMITIVE Processing functions
+ * -------------------------------------------------------------------
+ */
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_init_rr_data           |
++--------------------------------------------------------------------+
+
+  PURPOSE : Initialize the RR data for the module data transfer.
+
+*/
+
+GLOBAL void dat_init_rr_data (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_init_rr_data()");
+
+  SET_STATE (STATE_DAT, DAT_NULL);
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_dl_establish_cnf       |
++--------------------------------------------------------------------+
+
+  PURPOSE : Process the primitive DL_ESTABLISH_CNF received from DL.
+
+*/
+GLOBAL void dat_dl_establish_cnf (T_DL_ESTABLISH_CNF *dl_establish_cnf_orig)
+{
+  GET_INSTANCE_DATA;
+  /*
+   * sys infos during l2 establishment are
+   * lost, inform layer 1 to send them again
+   */
+  PPASS(dl_establish_cnf_orig, dl_establish_cnf, DL_ESTABLISH_CNF);
+
+  TRACE_FUNCTION ("dat_dl_establish_cnf()");
+  rr_data->net_lost = FALSE;
+  TRACE_EVENT_P1("rr_data->net_lost = %u", rr_data->net_lost);
+  
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_CHAN_ASS_1:
+    case DAT_CHAN_ASS_2:
+    case DAT_IMM_ASS_1:
+    	    
+      break;
+    default :
+      if (dl_establish_cnf->sapi EQ SAPI_0)
+      {
+        PALLOC (mph_sync_req, MPH_SYNC_REQ);
+        mph_sync_req->cs = CS_CLEAN_SYS_INFO;
+        PSENDX (PL, mph_sync_req);
+      }
+      break;
+  }
+
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_CHAN_ASS_1:
+      /*
+       * successfull establishment of new layer 2 connection
+       * after channel assignment
+       */
+
+      EM_DL_ESTABLISH_CNF;
+
+      PFREE (dl_establish_cnf);
+
+      if (rr_data->sc_data.ch_mode NEQ
+          rr_data->cr_data.ch_mode)
+      {
+        /*
+         * a changed channel mode has been detected.
+         * update channel description and channel mode
+         * for the serving cell and inform MM about the
+         * new channel mode.
+         */
+        memcpy (&rr_data->sc_data.chan_desc,
+                &rr_data->cr_data.chan_desc,
+                sizeof (T_chan_desc));
+        rr_data->sc_data.ch_mode = rr_data->cr_data.ch_mode;
+        dat_code_channel_mode_to_mm ();
+      }
+
+      if (rr_data->cr_data.ciph_on NEQ
+          rr_data->sc_data.ciph_on)
+      {
+        /*
+         * the ciphering has changed. Inform MM about the new
+         * ciphering.
+         */
+        dat_code_ciphering_to_mm (rr_data->cr_data.ciph_on);
+      }
+
+      /*
+       * copy cr data to sc data and go back to normal dedicated mode.
+       */
+      rr_data->sc_data.ciph_on  = rr_data->cr_data.ciph_on;
+      rr_data->sc_data.algo     = rr_data->cr_data.algo;
+      rr_data->sc_data.ch_mode  = rr_data->cr_data.ch_mode;
+      rr_data->sc_data.cd.v_cell_chan_desc =
+               rr_data->cr_data.cd.v_cell_chan_desc;
+      memcpy (&rr_data->sc_data.cd.cell_chan_desc,
+              &rr_data->cr_data.cd.cell_chan_desc,
+              sizeof (T_LIST));
+      memcpy (&rr_data->sc_data.chan_desc,
+              &rr_data->cr_data.chan_desc,
+              sizeof (T_chan_desc));
+      memcpy (&rr_data->sc_data.amr_conf,
+              &rr_data->cr_data.amr_conf,
+              sizeof (T_multirate_conf));
+
+      rr_data->nc_data[CR_INDEX].arfcn = NOT_PRESENT_16BIT;
+      att_remove_multiple_channels ();
+      SET_STATE (STATE_SAPI_3, SMS_IDLE);
+      srv_use_stored_prim ();
+      dat_set_last_used_channel (&rr_data->sc_data.chan_desc);
+      att_dat_dedicated ();
+      dat_emo_stop ( TRUE );
+      SET_STATE (STATE_DAT, DAT_DEDICATED);
+      rr_data->mode_after_dedi = MODE_CELL_RESELECTION;
+      break;
+
+    case DAT_CHAN_ASS_2:
+      /*
+       * successfull reconnection on old channel after failed
+       * channel assignment
+       *
+       * update some parameters to go back to normal dedicated mode.
+       */
+      PFREE (dl_establish_cnf);
+      srv_use_stored_prim ();
+      SET_STATE (STATE_SAPI_3, SMS_IDLE);
+      att_dat_dedicated ();
+      rr_data->nc_data[CR_INDEX].arfcn = NOT_PRESENT_16BIT;
+      SET_STATE (STATE_DAT, DAT_DEDICATED);
+
+      rr_data->mode_after_dedi = MODE_CELL_RESELECTION;
+
+      EM_ASS_FAILURE_RECONNECT_SUCCESS;
+
+      break;
+
+    case DAT_DEDICATED:
+      /*
+       * An establish confirm in normal dedicated mode is only
+       * expected for short messages (SAPI 3)
+       */
+      if (dl_establish_cnf->sapi EQ SAPI_3)
+      {
+        SET_STATE (STATE_SAPI_3, SMS_ESTABLISHED);
+        srv_use_stored_prim ();
+      }
+      PFREE (dl_establish_cnf);
+      break;
+
+    case DAT_HANDOVER_4:
+      TRACE_EVENT ("DL_ESTABLISH_CNF");
+
+      EM_L2_CONNECTION_ESTABLISHED;
+
+      PFREE (dl_establish_cnf);
+
+      /*
+       * successfull establishment of new layer 2 connection
+       * after handover
+       */
+      if (rr_data->sc_data.ch_mode NEQ
+          rr_data->cr_data.ch_mode)
+      {
+        /*
+         * a changed channel mode has been detected.
+         * update channel description and channel mode
+         * for the serving cell and inform MM about the
+         * new channel mode.
+         */
+        memcpy (&rr_data->sc_data.chan_desc,
+                &rr_data->cr_data.chan_desc,
+                sizeof (T_chan_desc));
+        rr_data->sc_data.ch_mode = rr_data->cr_data.ch_mode;
+        dat_code_channel_mode_to_mm ();
+      }
+
+      if (rr_data->cr_data.ciph_on NEQ rr_data->sc_data.ciph_on)
+      {
+        /*
+         * the ciphering has changed. Inform MM about the new
+         * ciphering.
+         */
+        dat_code_ciphering_to_mm (rr_data->cr_data.ciph_on);
+      }
+
+      /*
+       * copy cr data to sc data and go back to normal dedicated mode.
+       */
+      rr_data->sc_data.ciph_on  = rr_data->cr_data.ciph_on;
+      rr_data->sc_data.algo     = rr_data->cr_data.algo;
+      rr_data->sc_data.ch_mode  = rr_data->cr_data.ch_mode;
+      rr_data->sc_data.cd.v_cell_chan_desc =
+               rr_data->cr_data.cd.v_cell_chan_desc;
+      memcpy (&rr_data->sc_data.cd.cell_chan_desc,
+              &rr_data->cr_data.cd.cell_chan_desc,
+              sizeof (T_LIST));
+      memcpy (&rr_data->sc_data.chan_desc,
+              &rr_data->cr_data.chan_desc,
+              sizeof (T_chan_desc));
+      memcpy (&rr_data->sc_data.amr_conf,
+              &rr_data->cr_data.amr_conf,
+              sizeof (T_multirate_conf));
+
+      rr_data->nc_data[SC_INDEX].bsic = rr_data->nc_data[CR_INDEX].bsic;
+      rr_data->nc_data[SC_INDEX].arfcn = rr_data->nc_data[CR_INDEX].arfcn;
+      rr_data->nc_data[CR_INDEX].arfcn = NOT_PRESENT_16BIT;
+      /*
+       * after a handover we cannot come back directly to the
+       * cell instead we have to do a normal cell reselection
+       */
+      rr_data->mode_after_dedi = MODE_CELL_RESELECTION;
+      att_remove_multiple_channels ();
+      SET_STATE (STATE_SAPI_3, SMS_IDLE);
+      srv_use_stored_prim ();
+      dat_set_last_used_channel (&rr_data->sc_data.chan_desc);
+      att_dat_dedicated ();
+      dat_emo_stop ( TRUE );
+      SET_STATE (STATE_DAT, DAT_DEDICATED);
+      break;
+
+    case DAT_HANDOVER_5:
+      TRACE_EVENT ("DL_ESTABLISH_CNF");
+      /*
+       * successfull reconnection on old channel after failed
+       * handover
+       *
+       * update some parameters to go back to normal dedicated mode.
+       */
+      PFREE (dl_establish_cnf);
+      srv_use_stored_prim ();
+      SET_STATE (STATE_SAPI_3, SMS_IDLE);
+      att_dat_dedicated ();
+      rr_data->nc_data[CR_INDEX].arfcn = NOT_PRESENT_16BIT;
+      SET_STATE (STATE_DAT, DAT_DEDICATED);
+
+      rr_data->mode_after_dedi = MODE_CELL_RESELECTION;
+
+      EM_HO_FAILURE_RECONNECT_SUCCESS;
+      break;
+
+    case DAT_IMM_ASS_1:
+      /*
+       * successfull establishment of a dedicated connection.
+       * Depending on the originator of the connection MM
+       * is informed.
+       */
+      EM_L2_CONNECTION_ESTABLISHED;
+
+#ifdef GPRS
+      if(! dat_check_packet_access())
+      {
+#endif
+        if (rr_data->ms_data.establish_cause EQ ESTCS_PAGING)
+        {
+          PREUSE (dl_establish_cnf, rr_establish_ind, RR_ESTABLISH_IND);
+          PSENDX (MM, rr_establish_ind);
+        }
+        else
+        {
+          PREUSE (dl_establish_cnf, rr_establish_cnf, RR_ESTABLISH_CNF);
+          PSENDX (MM, rr_establish_cnf);
+        }
+#ifdef GPRS
+      }
+      else
+      { /* packet access */
+        PFREE (dl_establish_cnf);
+      }
+#endif
+
+
+      /*
+       * initialize some variables for the dedicated mode.
+       */
+      rr_data->dyn_config.fho                       = 0;
+      rr_data->dyn_config.fca                       = 0;
+      rr_data->tch_loop_subch            = NOT_PRESENT_8BIT;
+      rr_data->sc_data.ciph_received     = FALSE;
+      rr_data->rel_cause                 = RRCS_INT_NOT_PRESENT;
+      rr_data->sc_data.ciph_on           = CIPH_OFF;
+      att_copy_old_lai_rac(SC_INDEX);
+#if 0
+      memcpy (&rr_data->old_lai,
+              &rr_data->nc_data[SC_INDEX].lai,
+              sizeof (rr_data->old_lai));
+      rr_data->old_cell_id               = rr_data->nc_data[SC_INDEX].cell_id;
+#endif
+      SET_STATE (STATE_SAPI_3, SMS_IDLE);
+      att_dat_dedicated ();
+      SET_STATE (STATE_DAT, DAT_DEDICATED);
+
+      /*
+       * Early classmark Sending is performed if the mobile supports it
+       * and the network requests it.
+       */
+
+      if (rr_data->ms_data.classmark2.es_ind AND
+          rr_data->nc_data[SC_INDEX].c2_par.ecsc)
+      {
+        /*
+         * building of the Early Classmark Sending message
+         */
+      
+/* Implements RR Clone findings #15 */
+          dat_class_chng_data_req();
+      }
+
+   
+#ifdef GPRS
+      dat_gprs_suspend_req ();
+#endif
+
+      EM_EARLY_CLASSMARK_SENDING;
+      break;
+
+#ifdef GPRS
+    case DAT_PDCH_ASS_4:
+      dat_rrgrr_reconnect_dcch_cnf (RECONN_OK);
+      SET_STATE (STATE_DAT, DAT_DEDICATED);
+      PFREE (dl_establish_cnf);
+      break;
+
+    case DAT_CCO_4:
+      if ( rr_data->gprs_data.cco_need_reconnect_cnf )
+      {
+        dat_rrgrr_reconnect_dcch_cnf (RECONN_OK);
+      }
+      else
+      {
+        /*
+         * GRR has received d_change_order message,
+         * but the BCCH reading in the new cell failed.
+         * The connection is resumed on the old channel
+         * in dedicated mode.
+         */
+
+        PALLOC (rrgrr_sync_ind, RRGRR_SYNC_IND);
+        rrgrr_sync_ind->sync_res  = SYNC_FAILED;
+        PSENDX (GRR, rrgrr_sync_ind);
+      }
+      SET_STATE (STATE_DAT, DAT_DEDICATED);
+      PFREE (dl_establish_cnf);
+      break;
+#endif
+
+    default:
+      PFREE (dl_establish_cnf);
+      break;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_dl_establish_ind       |
++--------------------------------------------------------------------+
+
+  PURPOSE : Process the primitive DL_ESTABLISH_IND received from DL.
+            This is only expected for short messages on SAPI 3 during
+            a connection.
+
+*/
+
+GLOBAL void dat_dl_establish_ind (T_DL_ESTABLISH_IND *dl_establish_ind)
+{
+  GET_INSTANCE_DATA;
+
+  TRACE_FUNCTION ("dat_dl_establish_ind()");
+
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_DEDICATED:
+      /*
+       * if it indicates a mobile terminated connection establishment
+       * for SAPI 3 in the layer 2, change the state in RR for SMS.
+       * Answers from upper layer for SMS can be forwarded then
+       * immediately.
+       */
+      if (dl_establish_ind->sapi EQ SAPI_3)
+      {
+        /*
+         * set state for SMS if it is on SAPI 3
+         */
+        SET_STATE (STATE_SAPI_3, SMS_ESTABLISHED);
+        srv_use_stored_prim ();
+      }
+      break;
+
+    default:
+      break;
+  }
+  PFREE (dl_establish_ind);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_mph_random_access_cnf  |
++--------------------------------------------------------------------+
+
+  PURPOSE : Layer 1 confirms with the primitive MPH_RANDOM_ACCESS_CNF
+            the sending of a random burst during connection establishment.
+
+*/
+
+GLOBAL void dat_mph_random_access_cnf (T_MPH_RANDOM_ACCESS_CNF *mph_random_access_cnf)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_mph_random_access_cnf()");
+
+  EM_CHANNEL_REQUEST_SENT;
+
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_IMM_ASS:
+      if (rr_data->ms_data.access_counter < rr_data->ms_data.max_attempt)
+      {
+        /*
+         * if it the last or less then last random burst
+         * copy the frame number of the random burst for later
+         * comparision with the request reference of an immediate
+         * assignment message.
+         */
+        memcpy (&rr_data->used_frame_no[rr_data->ms_data.access_counter],
+                &mph_random_access_cnf->frame_no,
+                sizeof (T_frame_no));
+
+        /*
+        TRACE_EVENT_P5 ("RA %u CNF: %d %d %d 0x%02x",
+          rr_data->ms_data.access_counter,
+          mph_random_access_cnf->frame_no.t1,
+          mph_random_access_cnf->frame_no.t2,
+          mph_random_access_cnf->frame_no.t3,
+          rr_data->used_channel_ref[rr_data->ms_data.access_counter]);
+        */
+
+        /*
+         * increment the number of already sent messages
+         */
+        rr_data->ms_data.access_counter++;
+
+        if (rr_data->ms_data.access_counter EQ rr_data->ms_data.max_attempt)
+        {
+          /*
+           * T3126 and T3146 (GPRS Packet Access on CCCH) are
+           * the same so use them for both purposes
+           *
+           * if it is the last random burst, start T3126 if the timer is not
+           * running yet (can be started after reception of an immediate
+           * assignment reject message).
+           * The timer controls reception of an immediate assignment message
+           * as response to the random bursts.
+           */
+/* Implements Measure#32: Row 196,197 */
+          (IS_TIMER_ACTIVE(T3126)) ? 
+            TRACE_TIMER ( "T3126 re-start") : TRACE_TIMER ( "T3126 start");
+          
+          if (! IS_TIMER_ACTIVE(T3126))
+          {
+            TIMERSTART (T3126, T3126_VALUE);
+          }
+
+          /*
+           * set a flag that all random bursts are send and confirmed.
+           */
+          rr_data->ms_data.all_conf_received = TRUE;
+        }
+      }
+
+
+      break;
+
+    default:
+      break;
+  }
+  PFREE (mph_random_access_cnf);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_dl_release_cnf         |
++--------------------------------------------------------------------+
+
+  PURPOSE : Layer 2 confirms with DL_RELEASE_CNF a disconnection on
+            layer 2 which has been initiated by RR.
+
+*/
+
+GLOBAL void dat_dl_release_cnf (T_DL_RELEASE_CNF *dl_release_cnf)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_dl_release_cnf()");
+
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_CHAN_REL:
+      /*
+       * after reception of a channel release message RR has
+       * started disconnection to come from dedicated to idle
+       * mode. Stop T3110, which controls the disconnection in
+       * layer 2.
+       */
+      TIMERSTOP (T3110);
+      /*
+       * Send STOP_DEDICATED_REQUEST to L1 and wait for confirmation 
+       */
+      att_stop_dedicated();
+      break;
+
+#ifdef GPRS
+    case DAT_PDCH_ASS_2:
+      dat_rrgrr_resumed_tbf_cnf();
+      rr_data->gprs_data.tbf_est = TBF_EST_NONE;  /* the initial state */
+      break;
+#endif
+
+    case DAT_HANDOVER_4:
+      TRACE_EVENT ("Event: DAT_HANDOVER_4");
+      /*
+       * the layer 2 resumption on the new channel during handover
+       * has failed and RR switches back to the old channel.
+       */
+      dat_code_mph_old_chan_req ();
+      SET_STATE (STATE_DAT, DAT_HANDOVER_5);
+      break;
+
+    case DAT_CHAN_ASS_1:
+      /*
+       * resumption of layer 2 has failed after channel assignment
+       * go back to the old channel.
+       */
+      dat_code_mph_old_chan_req ();
+      SET_STATE (STATE_DAT, DAT_CHAN_ASS_2);
+      break;
+
+    case DAT_DEDICATED:
+    case DAT_CHAN_ASS:
+    case DAT_CHAN_ASS_2:
+    case DAT_HANDOVER_5:
+      TRACE_EVENT ("Event: DAT_DEDICATED, DAT_CHAN_ASS, DAT_CHAN_ASS_2 or DAT_HANDOVER_5");
+
+      if (dl_release_cnf->sapi EQ SAPI_3)
+      {
+        /*
+         * the connection for SAPI 3 is disconnected by the
+         * network.
+         */
+        SET_STATE (STATE_SAPI_3, SMS_IDLE);
+        dat_rr_release_ind(RRCS_DATA_LINK_FAIL, SAPI_3);
+
+        /*
+         * clear any stored SAPI 3 message
+         */
+        srv_clear_stored_prim (RR_DATA_REQ);
+      }
+      else
+      {
+        /*
+         * the reconnection to the old channel has failed
+         * or a lower layer failure had happen.
+         * Indicate the abort to MM and start cell reselection.
+         */
+        switch (GET_STATE (STATE_DAT))
+        {
+          case DAT_CHAN_ASS:
+          case DAT_CHAN_ASS_2:
+            TRACE_EVENT("Assignment failed: reconnect failed");
+            EM_ASS_FAILURE_RECONNECT_FAILED;
+            break;
+          case DAT_HANDOVER_5:
+            TRACE_EVENT("Handover failed: reconnect failed");
+            EM_HO_FAILURE_RECONNECT_FAILED;
+            break;
+          default:
+            break;
+        }
+
+        att_code_rr_abort_ind (RRCS_DATA_LINK_FAIL);
+
+        rr_data->net_lost = TRUE;
+        att_stop_dedicated();
+      }
+      break;
+
+    case DAT_IMM_ASS_1:
+      /*
+       * Layer 2 establishment has failed for immediate assignment
+       * Stop dedicated and go back to idle mode. MM will be informed about
+       * release after receiving MPH_STOP_DEDICATED_CNF from L1.
+       */
+      if (rr_data->ms_data.establish_cause NEQ ESTCS_PAGING)
+      {
+        rr_data->rel_cause = RRCS_DL_EST_FAIL;
+      }
+      att_stop_dedicated();
+      break;
+
+    default:
+      break;
+  }
+  PFREE (dl_release_cnf);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_dl_release_ind         |
++--------------------------------------------------------------------+
+
+  PURPOSE : Layer 2 indicates disconnection due to layer 2 problems.
+
+*/
+
+GLOBAL void dat_dl_release_ind (T_DL_RELEASE_IND *dl_release_ind)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_dl_release_ind()");
+
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_CHAN_ASS:
+    case DAT_CHAN_ASS_2:
+    case DAT_DEDICATED:
+    case DAT_HANDOVER:
+    case DAT_HANDOVER_5:
+      TRACE_EVENT ("DL_RELEASE_IND");
+      if (dl_release_ind->sapi EQ SAPI_3)
+      {
+        /*
+         * indicate release for SAPI 3 (SMS)
+         * to MM and reset RR state back to SMS_IDLE.
+         */
+        dat_rr_release_ind(RRCS_DATA_LINK_FAIL, SAPI_3);
+        SET_STATE (STATE_SAPI_3, SMS_IDLE);
+        /*
+         * clear any stored SAPI 3 message
+         */
+        srv_clear_stored_prim (RR_DATA_REQ);
+      }
+      else
+      {
+        /*
+         * Delay 4 frames to allow sending UA response
+         * in RF for FTA testcase 25.2.3
+         * else the idle mode is configured too early.
+         * vsi_t_sleep (VSI_CALLER FOUR_FRAMES);
+         *
+         * msb: DL delays the release indication itself for completion of the
+         *      UA response transmission.
+         */
+        EM_DL_RELEASE_IND;
+
+        /*
+         * Inform MM about the release and start cell reselection.
+         */
+        att_code_rr_abort_ind (RRCS_DATA_LINK_FAIL);
+
+        rr_data->net_lost = TRUE;
+        att_stop_dedicated();
+      }
+      break;
+
+    case DAT_CHAN_ASS_1:
+      /*
+       * resumption of layer 2 has failed after channel assignment
+       * go back to the old channel.
+       */
+      dat_code_mph_old_chan_req ();
+      SET_STATE (STATE_DAT, DAT_CHAN_ASS_2);
+
+      EM_ASS_FAILURE_RECONNECT_FAILED2
+      break;
+
+    case DAT_CHAN_REL:
+      /*
+       * after reception of a channel release message RR has
+       * started disconnection to come from dedicated to idle
+       * mode. Stop T3110, which controls the disconnection in
+       * layer 2.
+       */
+      TIMERSTOP (T3110);
+
+      /*
+       * Send STOP_DEDICATED_REQUEST to L1 and wait for confirmation 
+       */
+      att_stop_dedicated();
+
+      EM_L2_CONNECTION_LOST;
+      break;
+
+    case DAT_HANDOVER_4:
+      TRACE_EVENT ("DL_RELEASE_IND");
+      /*
+       * resumption of layer 2 has failed handover
+       * go back to the old channel.
+       */
+      dat_code_mph_old_chan_req ();
+      SET_STATE (STATE_DAT, DAT_HANDOVER_5);
+
+      EM_HO_FAILURE_RECONNECT_FAILED2;
+
+
+      break;
+
+    case DAT_IMM_ASS_1:
+      
+      /*
+       * layer 2 establishment has failed during immediate assignment
+       */
+      if (dl_release_ind->cs EQ DL_INFO_FIELD_MISMATCH AND
+          rr_data->sc_data.first_attempt)
+      {
+        /*
+         * if the reason is a mismatch in the layer 3 messages in SABM
+         * and the response UA, a second attempt of establishment is started.
+         */
+        rr_data->sc_data.first_attempt = FALSE;
+        rr_data->repeat_est    = TRUE;
+#ifdef GPRS
+        if (rr_data->ms_data.establish_cause EQ ESTCS_GPRS_PAGING)
+          rr_data->dcch_stop_cause = CONTENTION_RESOLUTION_FAIL;
+#endif
+      }
+      else
+      {
+        switch (rr_data->ms_data.establish_cause)
+        {
+#ifdef GPRS
+          case ESTCS_GPRS_PAGING:
+            rr_data->dcch_stop_cause = DL_ESTABLISHMENT_FAIL;
+            break;
+          case ESTCS_PAGING:
+            rr_data->rel_cause = RRCS_INT_NOT_PRESENT;
+#else
+          case ESTCS_PAGING:
+#endif
+            break;
+          default:
+            rr_data->rel_cause = RRCS_DL_EST_FAIL;
+            break;
+        }
+      }
+
+      /*
+       * Stop dedicated and go back to idle mode.
+       */
+      att_stop_dedicated();
+      break;
+
+#ifdef GPRS
+    case DAT_PDCH_ASS_4:
+    case DAT_CCO_4:
+      if ( GET_STATE (STATE_DAT) EQ DAT_PDCH_ASS_4 OR
+           rr_data->gprs_data.cco_need_reconnect_cnf )
+      {
+        dat_rrgrr_reconnect_dcch_cnf (RECONN_LOW_FAIL);
+      }
+      att_build_idle_req (SC_INDEX, MODE_CELL_RESELECTION);
+      SET_STATE (STATE_DAT, DAT_IDLE);
+      break;
+#endif
+
+    default:
+      break;
+  }
+  PFREE (dl_release_ind);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_mph_dedicated_cnf      |
++--------------------------------------------------------------------+
+
+  PURPOSE : Layer 1 confirms the configuration of a dedicated channel.
+
+*/
+
+GLOBAL void dat_mph_dedicated_cnf (T_MPH_DEDICATED_CNF *mph_dedicated_cnf)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_mph_dedicated_cnf()");
+
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_IMM_ASS_1:
+      /*
+       * A dedicated channel has been configured after
+       * reception of the immediate assignment message.
+       *
+       * clear neighbourcell list and start layer 2 establishment
+       */
+      srv_clear_list (&rr_data->sc_data.cd.ncell_list);
+      srv_clear_list (&rr_data->sc_data.five_ter_list);
+      att_clean_buf (IND_ALL_DEDI_SI);
+      rr_data->sc_data.cd.sys_info_read &= ~ALL_DEDI_SYS_INFOS;
+      /*
+       * from now on we have a channel assigned
+       * even if the contention resolution is not
+       * done yet. If the contention resolution fails
+       * we use the same procedure for selecting a cell
+       * as in dedicated mode
+       */
+
+      rr_data->mode_after_dedi = MODE_CELL_SELECTION; /* default mode */
+      TIMERSTART (T_DEDICATED_MODE, THIRTY_SEC);
+#ifdef GPRS
+      if(! dat_gprs_start_sabm())
+#endif
+        dat_start_sabm ();
+      break;
+
+    case DAT_CHAN_ASS:
+
+      if (rr_data->dyn_config.fca)
+      {
+        /*
+         * special testfeature to force a failed layer 2 establishment
+         * during  channel assignment. Reset flag and switch back to old
+         * channel.
+         */
+        rr_data->dyn_config.fca = 0;
+        dat_code_mph_old_chan_req ();
+        SET_STATE (STATE_DAT, DAT_CHAN_ASS_2);
+      }
+      else
+      {
+        /*
+         * Resume layer 2 connection on the new channel with
+         * an assignment complete message.
+         */
+        MCAST (assign_com, U_ASSIGN_COMP);
+        PALLOC_MSG ( dl_resume_req, DL_RESUME_REQ, U_ASSIGN_COMP);
+
+        SET_STATE (STATE_DAT, DAT_CHAN_ASS_1);
+        assign_com->msg_type  = U_ASSIGN_COMP;
+        assign_com->rr_cause  = RRC_NORMAL_EVENT;
+
+        /*
+         * set channel and sapi for the new channel description
+         */
+        dat_code_prr_channel (&dl_resume_req->ch_type,
+                              &dl_resume_req->sapi,
+                              rr_data->cr_data.chan_desc.chan_type);
+
+        /*
+         * start layer 2 resumption.
+         */
+        for_dat_resume_req (dl_resume_req);
+        EM_ASSIGNMENT_COMPLETE;
+      }
+      break;
+
+#ifdef GPRS
+    case DAT_PDCH_ASS:
+      /*
+       * The current channel has been stopped at the Physical Layer.
+       */
+      dat_rrgrr_suspend_dcch_cnf();
+      SET_STATE (STATE_DAT, DAT_PDCH_ASS_1);
+      SET_STATE (STATE_GPRS, GPRS_PIM_BCCH); /* force MPH_IDLE_REQ with RRGRR_STOP_MON_CCCH_REQ */
+      rr_data->gprs_data.tbf_est = TBF_EST_PDCH;
+      break;
+#endif
+
+    case DAT_HANDOVER:
+    {
+      /*
+       * clearing of neighbourcells is already done
+       * after reception of the handover command.
+       *
+       * following behaviour depends on the result of
+       * handover execution in layer 1.
+       */
+      switch (mph_dedicated_cnf->dedi_res)
+      {
+        case DEDI_RES_OK:
+          /*
+           * handover is successfull.
+           */
+          if (rr_data->dyn_config.fca)
+          {
+            /*
+             * special testfeature to simulate
+             * failed handover, reset flag
+             * and start reconnection.
+             */
+            rr_data->dyn_config.fca = 0;
+            dat_code_mph_old_chan_req ();
+            SET_STATE (STATE_DAT, DAT_HANDOVER_5);
+          }
+          else
+          {
+            /*
+             * build a handover complete message.
+             */
+            MCAST (handov_comp, U_HANDOV_COMP);
+            PALLOC_MSG (dl_resume, DL_RESUME_REQ, U_HANDOV_COMP);
+
+            if (rr_data->ms_data.ho_type.rot EQ TIME_DIFF_YES)
+            {
+              /*
+               * handover command has requested the observed time difference.
+               */
+              handov_comp->v_mob_time_diff = TRUE;
+              handov_comp->mob_time_diff.diff   = rr_data->sc_data.observed_ta;
+            }
+            else
+            {
+              handov_comp->v_mob_time_diff = FALSE;
+            }
+
+            handov_comp->msg_type = U_HANDOV_COMP;
+            handov_comp->rr_cause = RRC_NORMAL_EVENT;
+
+            /*
+             * set channel type and sapi for the new channel
+             */
+            dat_code_prr_channel (&dl_resume->ch_type,
+                                  &dl_resume->sapi,
+                                  rr_data->cr_data.chan_desc.chan_type);
+
+            EM_HANDOVER_COMPLETE;
+
+            /*
+             * start layer 2 resumption.
+             */
+            for_dat_resume_req (dl_resume);
+            SET_STATE (STATE_DAT, DAT_HANDOVER_4);
+          }
+          break;
+
+        case DEDI_RES_TIMEOUT:
+          /*
+           * the timer T3124 during an asynchronous handover
+           * has timed out, start reconnection.
+           */
+          dat_code_mph_old_chan_req ();
+          SET_STATE (STATE_DAT, DAT_HANDOVER_5);
+          break;
+
+        case DEDI_RES_CELL_NOT_SYNC :
+           /*
+            * Timing Info for this cell is not present in ALR.
+            * This could be due to :
+            * a) Cell not present in BA list,
+            * b) Synchronization to this cell failed or not attempted.
+            */
+        case DEDI_RES_TA_OUT_OF_RANGE:
+        {
+          /*
+           * Layer 1 has detected that the timing advance is out of range.
+           * In fact the new channel has not been configured and RR
+           * can start reconnection to the old layer 2 connection immediately.
+           * It sends a handover failure message with the expected cause.
+           */
+          MCAST (handov_fail, U_HANDOV_FAIL);
+          PALLOC_MSG (dl_reconnect_req, DL_RECONNECT_REQ, U_HANDOV_FAIL);
+
+          /*
+           * set channel type and sapi for the old channel
+           */
+          dat_code_prr_channel (&dl_reconnect_req->ch_type,
+                                &dl_reconnect_req->sapi,
+                                rr_data->sc_data.chan_desc.chan_type);
+          handov_fail->msg_type = U_HANDOV_FAIL;
+
+          if( mph_dedicated_cnf->dedi_res EQ DEDI_RES_TA_OUT_OF_RANGE)
+            handov_fail->rr_cause = RRC_TIME_ADVANCE;
+          else if ( mph_dedicated_cnf->dedi_res EQ DEDI_RES_CELL_NOT_SYNC)
+#if defined (REL99) && defined (FF_BHO)
+            handov_fail->rr_cause = RRC_LOWER_LAYER_FAIL;
+#else
+            handov_fail->rr_cause = RRC_CHAN_UNACCEPT;
+#endif
+          RR_EM_SET_HANDOVER_FAIL_CAUSE(handov_fail->rr_cause);
+
+          /*
+           * start reconnection of the layer 2 link on the old channel.
+           */
+          for_dat_reconnect_req (dl_reconnect_req);
+          SET_STATE (STATE_DAT, DAT_HANDOVER_5);
+
+          break;
+        }
+      }
+      break;
+    }
+
+    default:
+      break;
+  }
+  PFREE (mph_dedicated_cnf);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_mph_dedicated_fail_cnf |
++--------------------------------------------------------------------+
+
+  PURPOSE : Layer 1 confirms the re-configuration of the old channel
+            after a failed handover or channel assignment with the
+            primitive MPH_DEDICATED_FAIL_CNF.
+
+*/
+
+GLOBAL void dat_mph_dedicated_fail_cnf (T_MPH_DEDICATED_FAIL_CNF *mph_dedicated_fail_cnf)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_mph_dedicated_fail_cnf()");
+
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_CHAN_ASS_2:
+    {
+      /*
+       * reconnection is done in layer 2. An assignment failure
+       * message is send to the network.
+       */
+    
+      MCAST (assign_fail, U_ASSIGN_FAIL);
+      PALLOC_MSG (dl_reconnect_req, DL_RECONNECT_REQ, U_ASSIGN_FAIL);
+
+      assign_fail->msg_type = U_ASSIGN_FAIL;
+      assign_fail->rr_cause = RRC_PROT_UNSPECIFIED;
+
+      RR_EM_SET_ASSIGN_FAIL_CAUSE(assign_fail->rr_cause);
+
+      /*
+       * set channel type and SAPI for layer 2
+       */
+      dat_code_prr_channel (&dl_reconnect_req->ch_type,
+                            &dl_reconnect_req->sapi,
+                            rr_data->sc_data.chan_desc.chan_type);
+
+      /*
+       * start layer 2 reconnection
+       */
+      for_dat_reconnect_req (dl_reconnect_req);
+
+      break;
+    }
+
+    case DAT_HANDOVER_5:
+    {
+      /*
+       * reconnection is done in layer 2. A handover failure
+       * message is send to the network.
+       */
+      MCAST (handov_fail, U_HANDOV_FAIL);
+      PALLOC_MSG (dl_reconnect_req, DL_RECONNECT_REQ, U_HANDOV_FAIL);
+
+      /*
+       * clear neighbourcell list
+       */
+      srv_clear_list (&rr_data->sc_data.cd.ncell_list);
+      srv_clear_list (&rr_data->sc_data.five_ter_list);
+      att_clean_buf (IND_ALL_DEDI_SI);
+      rr_data->sc_data.cd.sys_info_read &= ~ALL_DEDI_SYS_INFOS;
+      handov_fail->msg_type = U_HANDOV_FAIL;
+      handov_fail->rr_cause = RRC_UNSPECIFIED;
+
+      RR_EM_SET_HANDOVER_FAIL_CAUSE(handov_fail->rr_cause);
+
+      /*
+       * set channel type and SAPI for layer 2
+       */
+      dat_code_prr_channel (&dl_reconnect_req->ch_type,
+                            &dl_reconnect_req->sapi,
+                            rr_data->sc_data.chan_desc.chan_type);
+
+      /*
+       * start layer 2 reconnection
+       */
+      for_dat_reconnect_req (dl_reconnect_req);
+      break;
+    }
+
+#ifdef GPRS
+    case DAT_PDCH_ASS_3:
+    {
+      MCAST (u_assign_fail, U_ASSIGN_FAIL);
+      PALLOC_MSG (dl_reconnect_req, DL_RECONNECT_REQ, U_ASSIGN_FAIL);
+
+      /*
+       * set channel type and SAPI
+       */
+      dat_code_prr_channel (&dl_reconnect_req->ch_type,
+                            &dl_reconnect_req->sapi,
+                            rr_data->sc_data.chan_desc.chan_type);
+
+      u_assign_fail->msg_type = U_ASSIGN_FAIL;
+      u_assign_fail->rr_cause = rr_data->gprs_data.reconn_cause;
+
+      for_dat_reconnect_req (dl_reconnect_req);
+  
+      SET_STATE (STATE_DAT, DAT_PDCH_ASS_4);
+      break;
+    }
+
+    case DAT_CCO_3:
+    {
+      MCAST (u_handov_fail, U_HANDOV_FAIL);
+      PALLOC_MSG (dl_reconnect_req, DL_RECONNECT_REQ, U_HANDOV_FAIL);
+
+      /*
+       * set channel type and SAPI
+       */
+      dat_code_prr_channel (&dl_reconnect_req->ch_type,
+                            &dl_reconnect_req->sapi,
+                            rr_data->sc_data.chan_desc.chan_type);
+
+      u_handov_fail->msg_type = U_HANDOV_FAIL;
+      u_handov_fail->rr_cause = rr_data->gprs_data.reconn_cause;
+
+      for_dat_reconnect_req (dl_reconnect_req);
+      SET_STATE (STATE_DAT, DAT_CCO_4);
+      break;
+    }
+#endif
+
+    default:
+      break;
+  }
+  PFREE (mph_dedicated_fail_cnf);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_rr_abort_req           |
++--------------------------------------------------------------------+
+
+  PURPOSE : MM aborts a connection due to several reasons (SIM remove,
+            timeout, power off etc.).
+
+*/
+
+GLOBAL void dat_rr_abort_req (T_RR_ABORT_REQ *rr_abort_req)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_rr_abort_req()");
+
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_CHAN_ASS:
+    case DAT_CHAN_ASS_1:
+    case DAT_CHAN_ASS_2:
+    case DAT_DEDICATED:
+    case DAT_HANDOVER:
+    case DAT_HANDOVER_4:
+    case DAT_HANDOVER_5:
+      if (rr_abort_req->abcs EQ ABCS_SIM_REM)
+      {
+        /*
+         * in case of SIM remove the registration data
+         * especially the mobile identities are cleared
+         */
+        att_clear_registration_data ();
+      }
+
+      /*
+       * the disconnection of the layer 2 link is started.
+       */
+      dat_disconnect_link (RRCS_MM_ABORTED);
+      break;
+
+    case DAT_CHAN_REL:
+      /*
+       * RR has already started the layer 2 link disconnection.
+       * Wait for T3110 timeout or DL disconnection and process
+       * normal cell reselection.
+       */
+      if (rr_abort_req->abcs EQ ABCS_SIM_REM)
+      {
+        /*
+         * in case of SIM remove the registration data
+         * especially the mobile identities are cleared
+         */
+        att_clear_registration_data ();
+      }
+      break;
+
+    case DAT_IDLE:
+      if (rr_abort_req->abcs EQ ABCS_SIM_REM)
+      {
+        /*
+         * in case of SIM remove the registration data
+         * especially the mobile identities are cleared
+         * The idle mode is configured again to set a
+         * faked BS_PA_MFRMS of 9 to slow down layer 1
+         * and save power. A correct paging group is not
+         * longer needed, because paging is not possible
+         * in limited service.
+         */
+        att_clear_registration_data ();
+        att_build_idle_req (SC_INDEX,
+                            MODE_SYS_INFO_CHANGE);
+#ifdef REL99
+        att_config_cbch ();
+#else
+        att_build_cbch ();
+#endif
+      }
+      break;
+
+    case DAT_IMM_ASS:
+    case DAT_IMM_ASS_1:
+      if (rr_abort_req->abcs EQ ABCS_SIM_REM)
+      {
+        /*
+         * in case of SIM remove the registration data
+         * especially the mobile identities are cleared
+         */
+        att_clear_registration_data ();
+      }
+
+      /*
+       * stop any timer related to connection establishment
+       */
+      TIMERSTOP (T3122);
+      TIMERSTOP (T3126);
+
+      /*
+       * set the release establishment cause. This will be used in 
+       * dat_release_connection() function
+       */
+      rr_data->rel_cause = RRCS_MM_ABORTED;
+
+      if(GET_STATE (STATE_DAT) EQ DAT_IMM_ASS)
+      {
+        dat_rr_release_ind(rr_data->rel_cause, SAPI_0);
+        att_leave_dat_imm_ass();
+      }
+      else
+      {
+        /*
+         * go back to idle mode.
+         * inform GRR, and don't wait for CR_RSP 
+         */
+        att_stop_dedicated();
+      }
+      break;
+
+    default:
+      if (rr_abort_req->abcs EQ ABCS_SIM_REM)
+      {
+        /*
+         * in case of SIM remove the registration data
+         * especially the mobile identities are cleared
+         */
+        att_clear_registration_data ();
+      }
+      /*
+       * clear any store establish requests if available
+       * due to a timeout abort of the upper layer.
+       */
+      if (srv_check_stored_prim (RR_ESTABLISH_REQ))
+      {
+        /*
+         * release previous establish request
+         */
+        dat_rr_release_ind(RRCS_MM_ABORTED, SAPI_0);
+        srv_clear_stored_prim (RR_ESTABLISH_REQ);
+      }
+      break;
+  }
+
+  PFREE (rr_abort_req);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_rr_data_req            |
++--------------------------------------------------------------------+
+
+  PURPOSE : A layer 3 message of an upper layer shall be send.
+
+*/
+
+GLOBAL void dat_rr_data_req (T_RR_DATA_REQ *rr_data_req)
+{
+  GET_INSTANCE_DATA;
+  UBYTE pd;
+
+  TRACE_FUNCTION ("dat_rr_data_req()");
+
+  /*
+   * get the protocol discriminator of the message.
+   */
+  GET_PD (rr_data_req->sdu, pd);
+
+  if (pd EQ PD_SMS)
+  {
+    TRACE_EVENT ("SMS Message");
+
+    /*
+     * A SMS must be send with SAPI 3. Therefore the
+     * SAPI 3 connection must be established on layer 2.
+     * The STATE_SAPI_3 variable in RR indicates whether
+     * the connection is established or not. If not the
+     * message is stored and the connection will be established.
+     * A SAPI 3 connection is automatically released after
+     * channel assignment, handover or SAPI 0 release.
+     */
+    switch (GET_STATE (STATE_SAPI_3))
+    {
+      case SMS_ESTABLISHED:
+      {
+        /*
+         * SAPI 3 connection is available, then send the message
+         * directly.
+         */       
+        PPASS (rr_data_req, dl_data_req, DL_DATA_REQ);
+
+        /*
+         * set channel type and SAPI for SMS message.
+         */
+        dat_code_prr_channel_sms (dl_data_req,
+                                  rr_data->sc_data.chan_desc.chan_type);
+        for_dat_l3_data_req (dl_data_req);  
+        break;
+      }
+
+      case SMS_PENDING:
+        /*
+         * the establishment of SAPI 3 connection is still ongoing.
+         * store the message until connection is ready.
+         */
+        if (!srv_store_prim ((T_PRIM *)D2P(rr_data_req)))
+        {
+          PFREE (rr_data_req);
+        }
+        break;
+
+      case SMS_IDLE:
+        /*
+         * the establishment of SAPI 3 connection is not available
+         * store the message until connection is ready.
+         */
+        if (!srv_store_prim ((T_PRIM *)D2P(rr_data_req)))
+        {
+          PFREE (rr_data_req);
+        }
+        else
+        {
+          /*
+           * Maximum size of the initial message is one frame (= 23 Bytes).
+           */
+          PALLOC_SDU (dl_establish_req, DL_ESTABLISH_REQ, MAX_L2_FRAME_SIZE * BITS_PER_BYTE);
+          dat_code_prr_channel_sms ((T_DL_DATA_REQ *)dl_establish_req,
+                                    rr_data->sc_data.chan_desc.chan_type);
+
+          SET_STATE (STATE_SAPI_3, SMS_PENDING);
+          for_dat_est_req (dl_establish_req);
+        }
+        break;
+    }
+  }
+  else
+  {
+    /*
+     * it is a SAPI 0 message
+     */
+    PPASS (rr_data_req, dl_data_req, DL_DATA_REQ);
+
+    /*
+     * set channel type and SAPI according the channel type.
+     */
+    dat_code_prr_channel (&dl_data_req->ch_type,
+                          &dl_data_req->sapi,
+                          rr_data->sc_data.chan_desc.chan_type);
+
+    /*
+     * set N(S) for upper layer message and forward it to Layer 2.
+     */
+    dat_vsd_bit_set ((T_L3_SDU *)&dl_data_req->sdu, SET_ONLY);
+    for_dat_l3_data_req (dl_data_req);   
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_rr_establish_req       |
++--------------------------------------------------------------------+
+
+  PURPOSE : A mobile originated connection is started.
+
+*/
+
+GLOBAL void dat_rr_establish_req (T_RR_ESTABLISH_REQ *rr_establish_req)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_rr_establish_req()");
+
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_NULL:
+      /*
+       * Data transfer process is in null state, that means
+       * the MS has no service
+       */
+      if (!srv_store_prim ((T_PRIM *)D2P(rr_establish_req)))
+      {
+        /*
+         * storing is not possible due to an overflow of the storage area
+         * then reject the connection attempt.
+         */
+        dat_rr_release_ind(RRCS_QUEUE_FULL, SAPI_0);
+        PFREE (rr_establish_req);
+      }
+      break;
+
+    case DAT_IDLE:
+      if (IS_TIMER_ACTIVE(T3122) AND (rr_establish_req->estcs NEQ ESTCS_EMRG_CAL))
+      {
+        /*
+         * all non-emergency calls are rejected if T3122 is running.
+         * The timer has been started after reception of an immediate
+         * assignment reject message.
+         */
+        dat_rr_release_ind(RRCS_T3122_RUNNING, SAPI_0);
+        PFREE (rr_establish_req);
+
+        TRACE_EVENT ("imm ass delayed");
+      }
+      else
+      {
+        /*
+         * If T3122 is not running the access to the network is checked.
+         */
+        if (dat_access_allowed (rr_establish_req->estcs))
+        {
+          if (rr_establish_req->estcs EQ ESTCS_SERV_REQ_BY_MM)
+          {
+            /*
+             * if location updating is started, store fieldstrength
+             * for an optimisation. RR indicates to MM fieldstrength jumps
+             * over 6 dBm in the field, that means better chance to
+             * perform a successfull location updating.
+             */
+            rr_data->lup_rxlev = rr_data->nc_data[SC_INDEX].rxlev;
+          }
+
+          /*
+           * store the piggy-backed layer 3 message for later use.
+           */
+          memcpy (&rr_data->ms_data.l3msg, &rr_establish_req->sdu,
+                  sizeof (T_L3_SDU));/*lint !e420 Apparent access beyond array for function*/
+
+          /*
+           * Initialize the N(S) for upper layer messages.
+           */
+          dat_vsd_bit_set (&rr_data->ms_data.l3msg, SET_AND_RESET);
+
+          /*
+           * Initialize some parameters and start immediate assignment.
+           */
+          rr_data->sc_data.first_attempt = TRUE;
+          rr_data->repeat_est    = FALSE;
+#ifdef GPRS
+          dat_gprs_set_suspended();
+#endif
+          dat_start_immediate_assign (rr_establish_req->estcs);
+          PFREE (rr_establish_req);
+        }
+        else
+        {
+          /*
+           * Access is not allowed and the rejection is signalled to MM.
+           */
+          dat_rr_release_ind(RRCS_ACCESS_BARRED, SAPI_0);
+          PFREE (rr_establish_req);
+
+          TRACE_EVENT ("access barred");
+        }
+      }
+      break;
+
+    case DAT_IMM_ASS:
+    case DAT_IMM_ASS_1:
+    case DAT_DEDICATED:
+      {
+        /*
+         * collision of MO and MT calls. MT has higher priority than
+         * MO calls.
+         */
+        dat_rr_release_ind(RRCS_MO_MT_COLL, SAPI_0);
+        PFREE (rr_establish_req);
+        break;
+      }
+
+    default:
+      PFREE (rr_establish_req);
+      break;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_mph_paging_ind         |
++--------------------------------------------------------------------+
+
+  PURPOSE : Layer 1 has detected a paging for the mobile.
+            RR starts the immediate assignment procedure.
+
+*/
+
+GLOBAL void dat_mph_paging_ind (T_MPH_PAGING_IND *mph_paging_ind)
+{
+  GET_INSTANCE_DATA;
+#ifdef GPRS
+  UBYTE ret;
+#endif
+  TRACE_FUNCTION ("dat_mph_paging_ind()");
+
+  EM_PAGING_IND;
+
+  /* check access control class before processing for paging */
+  if (dat_access_allowed(ESTCS_PAGING) EQ FALSE)
+  {
+    PFREE (mph_paging_ind);
+    TRACE_EVENT("Access ctrl class not allowed for responding to the page msg");
+    return;
+  }
+
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_NULL:
+      /*
+       * MS is not in idle mode, searching for cell
+       */
+      if (! IS_TIMER_ACTIVE(T3122) AND GET_STATE (STATE_ATT) NEQ ATT_NULL)
+      {
+        /*
+         * paging is only excepted if T3122 is not running and there isn't
+         * performed a RR_DEACTIVATE_REQ just before
+         */
+        if (rr_data->pag_rec EQ FALSE)
+        {
+          /*
+           * store paging if no paging is stored until now.
+           */
+          if (!srv_store_prim ((T_PRIM *)D2P(mph_paging_ind)))
+          {
+            /*
+             * storage is full
+             */
+            PFREE (mph_paging_ind);
+          }
+          else
+          {
+            /*
+             * marker that paging has been received.
+             */
+            rr_data->pag_rec = TRUE;
+          }
+          return;
+        }
+      }
+      break;
+
+    case DAT_IDLE:
+      if (! IS_TIMER_ACTIVE(T3122))
+      {
+        if (rr_data->first_meas_received EQ FALSE)
+        {
+          /*
+           *  we are actually still in cell reselection
+           *  because we have not yet received a measurement
+           *  report. But we have to be in idle mode to make
+           *  measurements in the first place.
+           */
+
+          if (srv_check_stored_prim (MPH_PAGING_IND))
+          {
+            /*
+             * if already a paging is stored, ignore subsequent pagings
+             */
+            PFREE (mph_paging_ind);
+          }
+          else
+          {
+            /*
+             * store paging until measurement receives
+             */
+            rr_data->pag_rec = TRUE;
+            if (!srv_store_prim ((T_PRIM *)D2P(mph_paging_ind)))
+            {
+              /*
+               * storage buffer is full
+               */
+              rr_data->pag_rec = FALSE;
+              PFREE (mph_paging_ind);
+            }
+          }
+          return;
+        }
+
+#ifdef GPRS
+        ret = dat_check_packet_paging_ind(mph_paging_ind);
+        if(ret EQ FALSE)
+        {
+            /*
+             * we are suspended and it is not a packet paging
+             */
+            dat_begin_start_immediate_assign (mph_paging_ind->identity_type,
+                                              mph_paging_ind->channel_needed);
+        }
+        else if(ret EQ TRUE)
+        {
+          /*
+           * we are not suspended and it is not a packet paging
+           * and GPRS is activate
+           */
+          dat_ask_paging_ind(mph_paging_ind);
+        }
+        /* ret EQ 2-> packet paging for GPRS, do nothing */
+#else  /* GPRS */
+        dat_begin_start_immediate_assign (mph_paging_ind->identity_type,
+                                          mph_paging_ind->channel_needed);
+#endif  /* GPRS */
+      }
+
+      break;
+#ifdef GPRS
+    case DAT_IMM_ASS:
+      /* only PS pagings are received in this state */
+      dat_ask_paging_ind_pa_only(mph_paging_ind);
+      break;
+#endif
+    default:
+      break;
+  }
+  PFREE (mph_paging_ind);
+}
+
+#if defined FF_EOTD
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_rrlc_meas_req          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Process the primitive RRLC_MEAS_REQ received from LC.
+            Start the LCS/EOTD postion measurement procedure.
+
+*/
+
+GLOBAL void dat_rrlc_meas_req (T_RRLC_MEAS_REQ *rrlc_meas_req)
+{
+  GET_INSTANCE_DATA;
+  T_NC_DATA   *sc;
+  int         i,n;
+
+  TRACE_FUNCTION ("dat_rrlc_meas_req()");
+
+  switch ( GET_STATE (STATE_DAT) )
+  {
+    case DAT_HANDOVER  :
+    case DAT_HANDOVER_4:
+    case DAT_HANDOVER_5:
+      {
+        PALLOC (rrlc_error_ind, RRLC_ERROR_IND);
+        rrlc_error_ind->cause = LCS_HANDOVER;
+
+        rr_data->eotd_req_id = NOT_PRESENT_16BIT;
+
+        PSENDX (LC, rrlc_error_ind);
+
+        PFREE(rrlc_meas_req);
+        return;
+      }
+    default:
+      break;
+  }
+
+  /*
+   *  Check if the requested cell matches the serving cell.
+   */
+
+  sc = &rr_data->nc_data[SC_INDEX];
+
+  if ( rrlc_meas_req->v_arfcn              AND
+       rrlc_meas_req->  arfcn NEQ sc->arfcn AND
+       rrlc_meas_req->v_bsic               AND
+       rrlc_meas_req->  bsic  NEQ sc->bsic     )
+  {
+    PALLOC (rrlc_error_ind, RRLC_ERROR_IND);
+    rrlc_error_ind->cause = LCS_WRONG_BTS;
+    PSENDX (LC, rrlc_error_ind);
+
+    PFREE(rrlc_meas_req);
+    return;
+  }
+
+  /*
+   *  The requested cell matches the serving cell or
+   *  the requested cell was not specified.
+   */
+
+  {
+    PALLOC ( mph_ncell_pos_req, MPH_NCELL_POS_REQ );
+
+    rr_data->eotd_req_id = rrlc_meas_req->req_id;
+
+    n = rrlc_meas_req->v_assist_data ? rrlc_meas_req->c_assist_data : 0;
+    mph_ncell_pos_req->c_ncell_eotd = n;
+    mph_ncell_pos_req->req_id       = rrlc_meas_req->req_id;
+    for ( i = 0; i < n; ++i )
+      mph_ncell_pos_req->ncell_eotd[i] = *(T_ncell_eotd*)&rrlc_meas_req->assist_data[i];
+
+    PSENDX ( PL, mph_ncell_pos_req );
+  }
+  PFREE(rrlc_meas_req);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_rrrrlp_data_req        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Process the primitive RRRRLP_DATA_REQ received from LC.
+            Transmit a APDU according 3GPP TS 04.18, section 3.4.21.
+
+*/
+
+GLOBAL void dat_rrrrlp_data_req (T_RRRRLP_DATA_REQ *rrrrlp_data_req_orig)
+{
+  GET_INSTANCE_DATA;
+
+  UBYTE  cr      =  rrrrlp_data_req_orig->cr;
+  T_sdu *sdu     = &rrrrlp_data_req_orig->sdu;
+  UBYTE *buf     = &sdu->buf[sdu->o_buf/BITS_PER_BYTE];
+  USHORT len     = BYTELEN(sdu->l_buf);
+  USHORT num_seg = len / APDU_FULL_L2_FRAME;      /* number of full segments */
+  USHORT rem_seg = len % APDU_FULL_L2_FRAME;      /* size of last segment    */
+  USHORT n_seg;                                   /* total number of segments*/
+  USHORT i;
+  UBYTE  flag;
+
+  PPASS(rrrrlp_data_req_orig, rrrrlp_data_req, RRRRLP_DATA_REQ);
+
+  TRACE_FUNCTION ("dat_rrrrlp_data_req()");
+
+  /* sdu->o_buf must be a multiple of BITS_PER_BYTE */
+  TRACE_ASSERT ( sdu->o_buf % BITS_PER_BYTE EQ 0 );
+
+  /* compute the total number of segments (n_seg) */
+
+  if ( len EQ 0 )
+  {
+    PFREE(rrrrlp_data_req);
+    return;
+  }
+
+  n_seg = num_seg + ((rem_seg EQ 0) ? 0 : 1);
+
+  /* in a loop with DL_DATA_REQ send all APDU segments */
+
+  for ( i = 0; i < num_seg; ++i )
+  {
+    PALLOC_MSG ( dl_data_req, DL_DATA_REQ, B_APPLIC_INFO );
+
+    dat_code_prr_channel (&dl_data_req->ch_type,
+                          &dl_data_req->sapi,
+                          rr_data->sc_data.chan_desc.chan_type );
+
+    /* compute the APDU control flags */
+
+    if ( n_seg EQ 1 )
+    {
+      flag = (UBYTE)(FIRST_SEG | LAST_SEG | (cr << 2));
+    }
+    else
+    {
+      if ( i EQ 0 )
+      {
+        flag = FIRST_SEG | NOT_LAST_SEG;
+      }
+      else
+      {
+        if ( i EQ num_seg-1 AND rem_seg EQ 0 )
+          flag = NOT_FIRST_SEG | LAST_SEG | (cr << 2);
+        else
+          flag = NOT_FIRST_SEG | NOT_LAST_SEG;
+      }
+    }
+
+    /* compile the APDU message and send it to DL */
+
+    dl_data_req->sdu.buf[0] = PD_RR_TI_0;
+    dl_data_req->sdu.buf[1] = B_APPLIC_INFO;
+    dl_data_req->sdu.buf[2] = (flag << 4 ) | RRLP_LCS;
+    dl_data_req->sdu.buf[3] = APDU_FULL_L2_FRAME;
+    memcpy ( &dl_data_req->sdu.buf[4], buf, APDU_FULL_L2_FRAME );
+
+    buf += APDU_FULL_L2_FRAME;
+    dl_data_req->sdu.l_buf = (4 + APDU_FULL_L2_FRAME) * BITS_PER_BYTE;
+    dl_data_req->sdu.o_buf = 0;
+
+    PSENDX ( DL, dl_data_req );
+  }
+
+  /* send remaining APDU segment if its length > 0 */
+
+  if ( rem_seg > 0 )
+  {
+    PALLOC_MSG ( dl_data_req, DL_DATA_REQ, B_APPLIC_INFO );
+
+    dat_code_prr_channel (&dl_data_req->ch_type,
+                          &dl_data_req->sapi,
+                          rr_data->sc_data.chan_desc.chan_type );
+
+    /* compute the APDU control flags */
+
+    if ( n_seg EQ 1 )
+      flag = FIRST_SEG | LAST_SEG | (cr << 2);
+    else
+      flag = NOT_FIRST_SEG | LAST_SEG | (cr << 2);
+
+    /* compile the APDU message and send it to DL */
+
+    dl_data_req->sdu.buf[0] = PD_RR_TI_0;
+    dl_data_req->sdu.buf[1] = B_APPLIC_INFO;
+    dl_data_req->sdu.buf[2] = (flag << 4 ) | RRLP_LCS;
+    dl_data_req->sdu.buf[3] = (UBYTE)rem_seg;
+    memcpy ( &dl_data_req->sdu.buf[4], buf, rem_seg );
+
+    dl_data_req->sdu.l_buf = (4 + rem_seg) * BITS_PER_BYTE;
+    dl_data_req->sdu.o_buf = 0;
+
+    PSENDX ( DL, dl_data_req );
+  }
+
+  /* release RRRRLP_DATA_REQ */
+  PFREE(rrrrlp_data_req);
+#ifdef REL99
+  /* Send RRLP procedure stop indication to MM*/
+  {
+    PALLOC (rr_rrlp_stop_ind, RR_RRLP_STOP_IND);
+    PSENDX (MM, rr_rrlp_stop_ind);
+  }
+#endif
+}
+#endif /* FF_EOTD */
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : att_mph_stop_dedicated_cnf        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Process the primitive MPH_STOP_DEDICATED_CNF received from L1
+*/
+GLOBAL void att_mph_stop_dedicated_cnf (T_MPH_STOP_DEDICATED_CNF * stop_cnf)
+{
+  GET_INSTANCE_DATA;
+  PFREE(stop_cnf);
+  TRACE_FUNCTION ("att_mph_stop_dedicated_cnf()");
+  /*
+   * Dedicated mode activity can be stopped in 3 cases
+   *
+   * - normal case :- Dedicated mode actvity has been stopped cleanly, without any errors.
+   *                  Either a cell selection or a cell reselection (to the same cell) will take
+   *                  place, depending on the timer T_DEDICATED_MODE.
+   *
+   * - failure :- Dedicated mode actvity has been stopped because of a radio link failure or a 
+   *              data link failure. In this case cell re-selection must be started immediately.
+   *
+   * - CCO :- This is Applicable after RR has received a network cell change order
+   */
+  switch(GET_STATE (STATE_ATT))
+  {
+    case ATT_NULL:
+    case ATT_CS1:
+    case ATT_CS2:
+      break;
+
+    default:
+#ifdef GPRS
+      if( rr_data->mode_after_dedi EQ MODE_CELL_CHANGE_ORDER)
+      {
+        PALLOC (mph_bsic_req, MPH_BSIC_REQ);
+        mph_bsic_req->arfcn = rr_data->gprs_data.arfcn;
+        SET_STATE (STATE_ATT, ATT_IDLE);
+        SET_STATE (STATE_CELL_SEL, CS_CCO);
+        rr_data->mode_after_dedi = NOT_PRESENT_8BIT;
+        PSENDX( PL, mph_bsic_req);
+        return;
+      } 
+#endif
+      if(! rr_data->net_lost )
+      {
+        /* Send Release indication to MM and go back to IDLE state */
+        dat_release_connection();
+      }
+      else
+      {
+#ifdef GPRS
+        att_start_cell_reselection_gprs (BACK_FROM_DEDICATED_RLF);
+#else
+        att_start_cell_reselection (BACK_FROM_DEDICATED_RLF);
+#endif
+      }
+      break;
+   } 
+}
+#endif