diff src/g23m-gsm/rr/rr_datf.c @ 104:27a4235405c6

src/g23m-gsm: import from LoCosto source
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 04 Oct 2016 18:24:05 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/g23m-gsm/rr/rr_datf.c	Tue Oct 04 18:24:05 2016 +0000
@@ -0,0 +1,3533 @@
+/*
++-----------------------------------------------------------------------------
+|  Project :
+|  Modul   :
++-----------------------------------------------------------------------------
+|  Copyright 2002 Texas Instruments Berlin, AG
+|                 All rights reserved.
+|
+|                 This file is confidential and a trade secret of Texas
+|                 Instruments Berlin, AG
+|                 The receipt of or possession of this file does not convey
+|                 any rights to reproduce or disclose its contents or to
+|                 manufacture, use, or sell anything it may describe, in
+|                 whole, or in part, without the specific written consent of
+|                 Texas Instruments Berlin, AG.
++-----------------------------------------------------------------------------
+|  Purpose :  This module defines the functions for the data transfer
+|             capability of the module Radio Resource.
++-----------------------------------------------------------------------------
+*/
+
+#ifndef RR_DATF_C
+#define RR_DATF_C
+
+#define ENTITY_RR
+
+/*==== INCLUDES ===================================================*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>     /* offsetof */
+#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 =====================================================*/
+
+/*==== PRIVATE ====================================================*/
+static void  dat_fill_mobile_identity    (USHORT              fill_type,
+                                          T_mob_ident         *moid);
+static BOOL  dat_eplmn_equal_req         (const UBYTE *mcc,
+                                          const UBYTE *mnc);
+static void  dat_get_background_and_bits (UBYTE               *background,
+                                          UBYTE               *bits);
+static UBYTE dat_get_burst               (UBYTE               background,
+                                          UBYTE               bits);
+static UBYTE dat_get_delta               (UBYTE               i);
+static UBYTE dat_get_ncell_pos           (USHORT              channel);
+static BOOL  dat_hplmn_country           (const UBYTE         *mcc);
+static SHORT dat_imsi_mod_1000           (void);
+static SHORT dat_no_of_paging_blocks     (UBYTE               index);
+static BOOL  dat_owner_of_auth_0_to_9    (void);
+static BOOL  dat_owner_of_auth_11_to_15  (void);
+static void  dat_send_random_bursts      (void);
+
+typedef struct  CODE_TABLE
+{
+  USHORT  cause;
+  UBYTE   last_channel;
+  UBYTE   neci_flag;
+  UBYTE   channel_needed;
+  UBYTE   ms_capability;
+  UBYTE   tch_f_needed;
+  UBYTE   background;
+  UBYTE   bits;
+} CODE_TABLE ;
+
+typedef struct CONVER_TXINTEGER
+{
+  USHORT  t;
+  USHORT  s_non_combined;
+  USHORT  s_combined;
+} CONVERT_TXINTEGER;
+
+/*==== VARIABLES ==================================================*/
+
+/*==== FUNCTIONS ==================================================*/
+
+
+/*
+ * -------------------------------------------------------------------
+ * Procedures
+ * -------------------------------------------------------------------
+ */
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_access_allowed         |
++--------------------------------------------------------------------+
+
+  PURPOSE : The function decides whether the access to the network is 
+            allowed or not. 
+            (GSM 4.18, chapter 3.3.1.1.1 Permission to access the network).
+
+*/
+
+GLOBAL BOOL dat_access_allowed (USHORT    establish_cause)
+{
+  GET_INSTANCE_DATA;
+  BOOL  result      = TRUE;
+
+  TRACE_FUNCTION ("dat_access_allowed()");
+
+#if defined (_SIMULATION_)
+  TRACE_EVENT_P1 ("ACC CLASS BCCH = %4x", rr_data->nc_data[SC_INDEX].rach.ac);
+  TRACE_EVENT_P1 ("ACC CLASS SIM  = %4x", rr_data->ms_data.access_classes);
+#endif
+
+  if (establish_cause EQ ESTCS_EMERGENCY_CALL)
+  {
+    /*
+     * if it is an emergency call the corresponding flag
+     * in the random access control parameters must be set
+     */
+    if (rr_data->nc_data[SC_INDEX].rach.ac & 0x0400)
+      result = FALSE;
+
+    /*
+     * or the MS must be member of one of the special classes
+     * defined on the SIM card.
+     */
+    if (result EQ FALSE)
+    {
+      result = dat_owner_of_auth_11_to_15 ();
+    }
+  }
+  else
+  {
+    /*
+     * for non-ememrgency calls
+     */
+
+    /*
+     * Normally, the whole check here should not be necessary as MM
+     * should know about limited service condition and not try to
+     * update in automatic mode or to establish a non-emergency CM service.
+     * So the check here is superflous, but if it catches, MM has a problem
+     * as it will think the cell is temporary barred and will wait for the
+     * barr state to change, not indicating limited service to the MMI under
+     * certain circumstances. It seems so that here something was fixed at
+     * the wrong place.
+     * The old condition was: if (dat_forbidden_lai_check (SC_INDEX))
+     */
+    if(
+         (establish_cause EQ ESTCS_LOCATION_UPDATING)
+           AND
+         ((rr_data->ms_data.operation_mode & 0x40) EQ 0x40)
+      )
+    {
+      /*
+        * Do not barr access for MM procedure establishment if we are in manual
+        * mode. This was previously bypassed within dat_forbidden_lai_check()
+        * function but was leading to incorrect cell reselection whilst RR
+        * was in manual.
+        * If MM wants to perform a LU at this place it means that user manually
+        * selected this network and is then allowed to attempt registration. If
+        * we reseleted on a LAC forbidden for provision of regional service, MM
+        * is switched to limited service so no normal LU will be triggered.
+        */
+      if (dat_owner_of_auth_0_to_9 ())
+        result = TRUE;
+      else
+        result = dat_owner_of_auth_11_to_15 ();
+    }
+    else if ( rr_data->ms_data.rr_service EQ LIMITED_SERVICE)
+    {
+      /*
+        * RR is in limited service.
+        * Only emergency calls are allowed in this state
+        */
+       result = FALSE;
+    }
+    else if (
+                 dat_forb_lai_check (SC_INDEX)
+                   AND
+                 dat_roam_forb_lai_check (SC_INDEX)
+               )
+    {
+      /*
+       * if RR is not inside of a forbidden location area,
+       * the MS must be member of one of the normal or one
+       * of the special classes stored on the SIM card.
+       */
+      if (dat_owner_of_auth_0_to_9 ())
+        result = TRUE;
+      else
+        result = dat_owner_of_auth_11_to_15 ();
+
+    }
+    else
+    {
+      /*
+       * if RR is inside of a forbidden location area
+       * no normal calls are allowed
+       */
+      TRACE_ERROR ("Unexpected, MM doesn't know its service state.");
+      result = FALSE;
+    }
+  }
+
+  return (result);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_calc_downlink_timeout  |
++--------------------------------------------------------------------+
+
+  PURPOSE : The downlink signalling failure criterion is based on the
+            downlink signalling failure counter DSC. When the MS
+            camps on a cell, DSC shall be initialized to a value equal
+            to the nearest integer to 90/N where N is the BS_PA_MFRMS
+            parameter for that cell (GSM 5.08, chapter 6.5 Downlink
+            Signalling Failure).
+
+*/
+
+GLOBAL UBYTE dat_calc_downlink_timeout (UBYTE     index)
+{
+  GET_INSTANCE_DATA;
+  UBYTE divisor;
+  UBYTE dl=0;
+
+  TRACE_FUNCTION ("dat_calc_downlink_timeout()");
+
+  /*
+   * The stored value for BS_PA_MFRMS is in air-interface coding.
+   * To get the real value a value of 2 must be added
+   */
+  divisor = rr_data->nc_data[index].control_descr.bs_pa_mfrms + 2;
+
+  /*
+   * calculate the initial value for the downlink signalling counter.
+   */
+  TRACE_ASSERT(divisor NEQ 0);
+  if(divisor NEQ 0)
+  {
+    dl = 90 / divisor;
+  }
+
+  /*
+   * correct rounding failures
+   *
+   * BS_PA_MFRMS =   2   -> 90/2   = 45
+   *                 3   -> 90/3   = 30
+   *                 4   -> 90/4   = 22.5   -> 23
+   *                 5   -> 90/5   = 18
+   *                 6   -> 90/6   = 15
+   *                 7   -> 90/7   = 12.85  -> 13
+   *                 8   -> 90/8   = 11.25
+   *                 9   -> 90/9   = 10
+   */
+  if (divisor EQ 4 OR divisor EQ 7)
+  {
+    dl++;
+  }
+  return (dl);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_calc_paging_group      |
++--------------------------------------------------------------------+
+
+  PURPOSE : Calculation of paging group is described in GSM 5.02,
+            chapter 6.5.2.
+
+            PAGING_GROUP (0 .. N-1) = ((IMSI mod 1000) mod (BS_CC_CHANS x N)) mod N
+
+            where
+
+            N = number of paging blocks "available" on one CCCH =
+                (number of paging blocks "available" in a 51-multiframe
+                 on one CCCH) x BS_PA_MFRMS.
+
+            IMSI = International Mobile Subscriber Identity, as defined in GSM 03.03.
+
+            mod = Modulo.
+
+*/
+
+GLOBAL UBYTE dat_calc_paging_group (UBYTE     index)
+{
+  GET_INSTANCE_DATA;
+  /*
+   * calculation of the number of paging blocks
+   */
+  SHORT n = dat_no_of_paging_blocks (index);
+
+  /*
+   * calculation of IMSI modulo 1000
+   */
+  SHORT a = dat_imsi_mod_1000 ();
+
+  /*
+   * calculation of BS_CC_CHANS * N (GSM 5.02 section 3.3.2.3)
+   */
+  SHORT b = ((rr_data->nc_data[index].control_descr.ccch_conf / 2) + 1) * n;
+
+  TRACE_FUNCTION ("dat_calc_paging_group()");
+
+  /*
+   * calculation of the paging group
+   */
+  return ((UBYTE) ((a % b) % n));
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_calc_tn                |
++--------------------------------------------------------------------+
+
+  PURPOSE : Determination of the timeslot of the paging block for the
+            MS in idle mode is described in GSM 5.02, chapter 6.5.2
+
+            The formula for calculation of the CCCH group must be used.
+            The dependency between timeslot and CCCH group is
+
+            tn = 2 * CCCH_GROUP
+
+            CCCH_GROUP (0 .. BS_CC_CHANS-1) = ((IMSI mod 1000) mod (BS_CC_CHANS x N)) div N
+
+            where
+
+            N = number of paging blocks "available" on one CCCH =
+                (number of paging blocks "available" in a 51-multiframe
+                on one CCCH) x BS_PA_MFRMS.
+
+            IMSI = International Mobile Subscriber Identity, as defined in GSM 03.03.
+
+            mod = Modulo.
+
+            div = Integer division.
+
+*/
+
+GLOBAL UBYTE dat_calc_tn (UBYTE      index)
+{
+  GET_INSTANCE_DATA;
+  /*
+   * calculate the number of paging blocks
+   */
+  SHORT n = dat_no_of_paging_blocks (index);
+
+  /*
+   * calculate IMSI modulo 1000
+   */
+  SHORT a = dat_imsi_mod_1000 ();
+
+  /*
+   * calculate BS_CC_CHANS * N (GSM 5.02 section 3.3.2.3)
+   */
+  SHORT b = ((rr_data->nc_data[index].control_descr.ccch_conf / 2) + 1) * n;
+
+  TRACE_FUNCTION ("dat_calc_tn()");
+
+  /*
+   * calculate the timeslot
+   */
+  return ((UBYTE) ((a % b) / n) * 2);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_check_error_flag       |
++--------------------------------------------------------------------+
+
+  PURPOSE : In the formatter module several tests are performed to
+            check the syntax and the semantic of the incoming messages.
+            The results of this checks are stored in the error variables.
+            This function sends a RR STATUS message back to the network
+            if a mandatory or conditional error has been detected for
+            a message received in acknowledged mode. It indicates to the
+            calling function whether the message shall be ignored or not.
+
+*/
+
+GLOBAL BOOL dat_check_error_flag (BOOL      send_rr_status)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_check_error_flag()");
+
+  /*
+   * if an error unequal to optional info error has occured
+   */
+  if (rr_data->ms_data.error.cs NEQ 0 AND
+      rr_data->ms_data.error.cs NEQ OPTIONAL_INFO_ERROR)
+  {
+
+  
+    if (send_rr_status)
+    {
+      /*
+       * if the message has been received in acknowledged mode,
+       * answer to the network with a RR STATUS message.
+       */
+/* Implements RR Clone findings #23 */
+      dat_send_rr_status_msg(rr_data->ms_data.error.cs);
+
+ 
+    }
+   
+  }
+
+  switch (rr_data->ms_data.error.cs)
+  {
+    /* case RRC_INVALID_MAN_INFO: this value is currently never set */
+    case RRC_INCORRECT_MSG:
+    case RRC_COND_IE_ERROR:
+      /*
+       * Major failure in the message, ignore it
+       */
+      return FALSE;
+
+    default:
+      /*
+       * minor or no failure, process the message
+       */
+      return TRUE;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_code_channel_mode_to_mm|
++--------------------------------------------------------------------+
+
+  PURPOSE : A changed channel mode is signalled to MM.
+
+*/
+
+GLOBAL void dat_code_channel_mode_to_mm  (void)
+{
+  GET_INSTANCE_DATA;
+  PALLOC (sync_ind, RR_SYNC_IND);
+
+  TRACE_FUNCTION ("dat_code_channel_mode_to_mm()");
+
+  /*
+   * set the channel type
+   */
+  switch (rr_data->sc_data.chan_desc.chan_type)
+  {
+    case CH_TCH_F:
+      TRACE_EVENT ("TCH/F configured");
+      sync_ind->chm.ch_type  = CH_TCH_F;
+      break;
+    case CH_TCH_H_1:
+    case CH_TCH_H_2:
+      TRACE_EVENT ("TCH/H configured");
+      sync_ind->chm.ch_type  = CH_TCH_H;
+      break;
+    default:
+      TRACE_EVENT ("SDCCH configured");
+      sync_ind->chm.ch_type = CH_SDCCH;
+      break;
+  }
+
+  /*
+   * set the rest of the parameters
+   */
+  sync_ind->ciph             = NOT_PRESENT_8BIT;
+  sync_ind->chm.ch_mode      = rr_data->sc_data.ch_mode;
+  memset(&sync_ind->mm_info, 0, sizeof(T_mm_info));
+  sync_ind->mm_info.valid    = FALSE;
+  memset(&sync_ind->bcch_info, 0, sizeof(T_bcch_info));
+  sync_ind->bcch_info.v_bcch = FALSE;
+  sync_ind->synccs           = NOT_PRESENT_16BIT;
+
+  PSENDX(MM, sync_ind);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_code_ciphering_to_mm   |
++--------------------------------------------------------------------+
+
+  PURPOSE : A changed ciphering mode is signalled to MM.
+
+*/
+
+GLOBAL void dat_code_ciphering_to_mm (UBYTE ciph_on)
+{
+  PALLOC (sync_ind, RR_SYNC_IND);
+
+  TRACE_FUNCTION ("dat_code_ciphering_to_mm()");
+
+  /*
+   * set the new cipher mode
+   */
+  sync_ind->ciph             = ciph_on;
+
+  /*
+   * clear the rest of the parameters
+   */
+  sync_ind->chm.ch_mode      = NOT_PRESENT_8BIT;
+  memset(&sync_ind->mm_info, 0, sizeof(T_mm_info));
+  sync_ind->mm_info.valid    = FALSE;
+  memset(&sync_ind->bcch_info, 0, sizeof(T_bcch_info));
+  sync_ind->bcch_info.v_bcch = FALSE;
+  sync_ind->synccs           = NOT_PRESENT_16BIT;
+
+  PSENDX(MM, sync_ind);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)    MODULE  : RR_DAT                        |
+| STATE   : code             ROUTINE : dat_code_reestablishment_fail |
++--------------------------------------------------------------------+
+
+  PURPOSE : Indicate a failed call reestablishment to MM. If a radio
+            link failure has occured, RR performs a cell reselection
+            to come back to idle mode and then the reestablishment may
+            starts. If no suitable cell is available, it may takes
+            a long time until no service is signalled. This function is
+            used to finish the reestablish earlier, if no candidate
+            is available during coming back from dedicated.
+
+*/
+
+GLOBAL void dat_code_reestablishment_fail (void)
+{
+  GET_INSTANCE_DATA;
+  T_NC_DATA *rrd = &rr_data->nc_data[SC_INDEX];
+
+  PALLOC (sync_ind, RR_SYNC_IND);
+
+  TRACE_FUNCTION ("dat_code_reestablishment_fail()");
+
+  sync_ind->mm_info.valid    = TRUE;
+  sync_ind->mm_info.att      = rrd->control_descr.att;
+  /*
+   * No reestablishment
+   */
+  sync_ind->mm_info.re       = 1;
+  sync_ind->mm_info.ncc      = (rrd->bsic >> 3) & 7;
+  sync_ind->mm_info.bcc      = rrd->bsic & 7;
+  sync_ind->mm_info.t3212    = rrd->control_descr.t3212;
+  /*sync_ind->mm_info.la       = !dat_forb_lai_check (SC_INDEX);*/
+  sync_ind->mm_info.la       = (!(dat_forb_lai_check (SC_INDEX) AND
+                                  dat_roam_forb_lai_check (SC_INDEX)));
+
+  sync_ind->ciph             = NOT_PRESENT_8BIT;;
+  sync_ind->chm.ch_mode      = NOT_PRESENT_8BIT;
+  sync_ind->bcch_info.v_bcch = FALSE;
+  sync_ind->synccs           = NOT_PRESENT_16BIT;
+
+  PSENDX (MM, sync_ind);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_code_measure_report    |
++--------------------------------------------------------------------+
+
+  PURPOSE : RR builds a RR MEASUREMENT REPORT message for the uplink
+            sacch, whenever it receives a measurement report from the
+            layer 1.
+
+*/
+
+GLOBAL void dat_code_measure_report (T_MPH_MEASUREMENT_IND *report)
+{
+  GET_INSTANCE_DATA;
+  USHORT                i;
+
+  MCAST (meas, U_MEAS_REP);
+  PALLOC_MSG (dl_unitdata_req, DL_UNITDATA_REQ, U_MEAS_REP);/* T_DL_UNITDATA_REQ */
+
+  TRACE_FUNCTION ("dat_code_measure_report()");
+  memset (&dl_unitdata_req->sdu.buf[0], 0, dl_unitdata_req->sdu.o_buf / BITS_PER_BYTE);
+
+  /*
+   * initialize C-structure for the Uplink message
+   */
+  memset (meas, 0, sizeof (T_U_MEAS_REP));
+
+  /*
+   * set message type
+   */
+  meas->msg_type                = U_MEAS_REP;
+
+
+  if (report->valid)
+  {
+    /*
+     * measurement report from layer 1 is valid,
+     * then copy data to C-structure for message
+     */
+    meas->meas_result.ba_used     = rr_data->sc_data.ba_index;
+    meas->meas_result.dtx_used    = report->dtx;
+    meas->meas_result.meas_valid  = 0;
+
+    if (rr_data->dyn_config.fho)
+    {
+      /*
+       * forced handover, special test feature to simulate
+       * a bad serving cell
+       */
+      meas->meas_result.rxlev_full = 0;
+      meas->meas_result.rxlev_sub  = 0;
+    }
+    else
+    {
+      /*
+       * take values from layer 1
+       */
+      meas->meas_result.rxlev_full  = report->rx_lev_full;
+      meas->meas_result.rxlev_sub   = report->rx_lev_sub;
+    }
+
+    meas->meas_result.rxqual_full = report->rx_qual_full;
+    meas->meas_result.rxqual_sub  = report->rx_qual_sub;
+
+    /*
+     * copy neighbourcell values
+     */
+    meas->meas_result.num_ncell   = report->ncells.no_of_ncells;
+
+#if defined (REL99) && defined (TI_PS_FF_EMR)
+    if ( (rr_data->sc_data.ba_list_idle EQ TRUE) OR
+         (rr_data->sc_data.ba_list_ded  EQ TRUE) )   
+#else
+    /*
+     * report ncells only if BA complete or
+     * itīs a expansion (5ter) and the 5/5bis are sent before
+     */
+    if ( (rr_data->sc_data.cd.sys_info_read &  (SYS_INFO_5_READ | SYS_INFO_5BIS_READ))
+                                            EQ (SYS_INFO_5_READ | SYS_INFO_5BIS_READ) )
+#endif
+    {
+      /*
+       * fill ncells to the measurement report
+       */
+      for (i=0;i<meas->meas_result.num_ncell;i++)
+      {
+        meas->meas_result.ncell[i].bsic = report->ncells.bsic[i];
+
+        /*
+         * set position in neighbourcell list instead of channel number
+         */
+        meas->meas_result.ncell[i].bcch_ncell = dat_get_ncell_pos (report->ncells.arfcn[i]);
+        meas->meas_result.ncell[i].rx_lev_ncell = report->ncells.rx_lev[i];
+
+        TRACE_EVENT_P4 ("MR:%u[%4u] p=%u rxl=%u",
+          i, report->ncells.arfcn[i],
+          meas->meas_result.ncell[i].bcch_ncell,
+          meas->meas_result.ncell[i].rx_lev_ncell); /* +++ */
+
+      }
+    }
+    else
+    {
+      /*
+       * Table 10.5.47/GSM 04.08: Measurement Results information element
+       * Range: 0 to 7 (See GSM 05.08)
+       * NO-NCELL-M, Number of neighbouring cell measurements (octets 4 and 5)
+       *
+       * No neighbour cell measurement result := 0
+       * Neighbour cell information not available for serving cell := 7
+       */
+      meas->meas_result.num_ncell = 7;
+    }
+
+  }
+  else
+  {
+    /*
+     * measurement report from layer 1 is invalid
+     */
+    TRACE_EVENT ("invalid Meas");
+    meas->meas_result.meas_valid = 1;
+  }
+
+  /*
+   * code message and send to layer 2.
+   */
+  for_dat_unitdata_req (dl_unitdata_req);
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_code_ext_meas_report   |
++--------------------------------------------------------------------+
+
+  PURPOSE : RR builds a RR EXTENDED MEASUREMENT REPORT message for the
+            uplink sacch.
+*/
+
+GLOBAL void dat_code_ext_meas_report (T_MPH_EMO_MEAS_IND  *mph_emo_meas_ind)
+{
+  GET_INSTANCE_DATA;
+  USHORT          *emo_arfcn = rr_data->  emo_arfcn;
+  UBYTE          c_emo_arfcn = rr_data->c_emo_arfcn;
+  T_ext_meas_res  *ext_meas_res;
+  UBYTE           *rx_lev_ncell;
+  T_meas_results  *meas_results;
+  UBYTE           i,k;
+
+  MCAST (u_ext_meas_report, U_EXT_MEAS_REPORT);
+  PALLOC_MSG (dl_unitdata_req, DL_UNITDATA_REQ, U_EXT_MEAS_REPORT);
+
+  TRACE_FUNCTION ("dat_code_ext_meas_report()");
+
+  /*
+   * initialize C-structure for the Uplink message
+   */
+  memset (u_ext_meas_report, 0, sizeof (T_U_EXT_MEAS_REPORT));
+
+  ext_meas_res = &u_ext_meas_report->ext_meas_res;
+
+  /*
+   * set message type
+   */
+  u_ext_meas_report->msg_type = U_EXT_MEAS_REPORT;
+
+  ext_meas_res->sc_used  = rr_data->emo_seq;
+  ext_meas_res->dtx_used = mph_emo_meas_ind->dtx;
+
+  rx_lev_ncell = &ext_meas_res->rx_lev_ncell[0];
+  meas_results = &mph_emo_meas_ind->meas_results[0];
+
+  TRACE_ASSERT( c_emo_arfcn <=  MAX_EMO_CHANNELS);
+  TRACE_ASSERT( mph_emo_meas_ind->c_meas_results <= (MAX_EMO_CHANNELS +1));
+
+  for ( k = 0; k < c_emo_arfcn; k++ )
+  {
+    for ( i = 0; i < mph_emo_meas_ind->c_meas_results; i++ )
+    {
+      if ( emo_arfcn[k] EQ meas_results[i].arfcn )
+      {
+        rx_lev_ncell[k] = meas_results[i].rx_lev;
+      }
+    }
+  }
+
+  /*
+   * code message and send to layer 2.
+   */
+  for_dat_unitdata_req (dl_unitdata_req);
+
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_code_mph_chan_mode_req |
++--------------------------------------------------------------------+
+
+  PURPOSE : configure a new channel mode to layer 1.
+
+*/
+
+GLOBAL void dat_code_mph_chan_mode_req (T_D_CHAN_MOD *chan_mod)
+{
+  GET_INSTANCE_DATA;
+  PALLOC (channel_mode_req, MPH_CHANNEL_MODE_REQ);
+
+  TRACE_FUNCTION ("dat_code_mph_chan_mode_req()");
+
+  memset(channel_mode_req, 0, sizeof(T_MPH_CHANNEL_MODE_REQ));
+
+  /*
+   *  configure layer 1 with multi-rate configuration if present
+  */
+  if ( rr_data->sc_data.ch_mode EQ CM_AMR )
+  {
+    int i;
+    channel_mode_req->amr_conf.nscb    = rr_data->sc_data.amr_conf.nscb;
+    channel_mode_req->amr_conf.icmi    = rr_data->sc_data.amr_conf.icmi;
+    channel_mode_req->amr_conf.st_mode = rr_data->sc_data.amr_conf.st_mode;
+    channel_mode_req->amr_conf.acs     = rr_data->sc_data.amr_conf.set_amr;
+
+    channel_mode_req->amr_conf.v_cod_prop = rr_data->sc_data.amr_conf.v_cod_prop;
+    if(channel_mode_req->amr_conf.v_cod_prop)
+    {
+      channel_mode_req->amr_conf.c_cod_prop = rr_data->sc_data.amr_conf.c_cod_prop;
+      for (i=0; i< channel_mode_req->amr_conf.c_cod_prop; i++)
+        memcpy(&channel_mode_req->amr_conf.cod_prop[i],
+               &rr_data->sc_data.amr_conf.cod_prop[i], sizeof(T_cod_prop));
+    }
+  }
+
+  /*
+   * set new channel mode
+   */
+  channel_mode_req->ch   = chan_mod->chan_desc.chan_type;
+  channel_mode_req->mode = chan_mod->chan_mode;
+  PSENDX (PL, channel_mode_req);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_code_mph_ciphering_req |
++--------------------------------------------------------------------+
+
+  PURPOSE : configure new cipher parameter to layer 1.
+
+*/
+
+GLOBAL void dat_code_mph_ciphering_req (UBYTE       ciph_on,
+                                        UBYTE       algo,
+                                        UBYTE     * kc)
+{
+  PALLOC (mph_ciphering_req, MPH_CIPHERING_REQ);
+
+  TRACE_FUNCTION ("dat_code_mph_ciphering_req()");
+
+  if (ciph_on)
+  {
+    /*
+     * ciphering is on, then set cipher algorithm
+     * and Kc value.
+     */
+    mph_ciphering_req->ciph.stat    = CIPH_ON;
+    mph_ciphering_req->ciph.algo    = algo;
+    memcpy (mph_ciphering_req->ciph.kc, kc, KC_STRING_SIZE);
+  }
+  else
+  {
+    /*
+     * ciphering is off, then set default values
+     */
+    mph_ciphering_req->ciph.stat    = CIPH_OFF;
+    mph_ciphering_req->ciph.algo    = 0;
+    memset (mph_ciphering_req->ciph.kc, 0, KC_STRING_SIZE);
+  }
+
+  PSENDX (PL, mph_ciphering_req);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_code_sys_info_change   |
++--------------------------------------------------------------------+
+
+  PURPOSE : A change in parameters of system information type 6
+            has been detected. The parameters are configured
+            in layer 1.
+
+*/
+
+GLOBAL void dat_code_sys_info_change  (UBYTE     dtx,
+                                       UBYTE     pwrc,
+                                       UBYTE     rlt)
+{
+  PALLOC (dedicated_req, MPH_DEDICATED_REQ);
+
+  TRACE_FUNCTION ("dat_code_sys_info_change()");
+
+  memset (dedicated_req, 0, sizeof (T_MPH_DEDICATED_REQ));
+
+  /*
+   * set new dtx, rlt, pwrc and ncc_permitted values
+   */
+  dedicated_req->tr_para.dtx   = dtx;
+  dedicated_req->tr_para.rlt   = rlt;
+  dedicated_req->tr_para.pwrc  = pwrc;
+  dedicated_req->mod           = MODE_SYS_INFO_CHANGE;
+
+  PSENDX (PL, dedicated_req);
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)      MODULE  : RR_DAT                      |
+| STATE   : code               ROUTINE : dat_code_mph_imm_assign_req |
++--------------------------------------------------------------------+
+
+  PURPOSE : configure layer 1 after reception of an immediate assignment
+            or immediate assignment extended message.
+
+*/
+
+GLOBAL void dat_code_mph_imm_assign_req (T_start      *start,
+                                         UBYTE         power,
+                                         UBYTE         maio,
+                                         T_LIST       *freq_after_sti,
+                                         T_LIST       *freq_bef_sti)
+{
+  GET_INSTANCE_DATA;
+
+  PALLOC (dedicated_req, MPH_DEDICATED_REQ);
+
+  TRACE_FUNCTION ("dat_code_mph_imm_assign_req()");
+
+  memset (dedicated_req, 0, sizeof (T_MPH_DEDICATED_REQ));
+
+  dedicated_req->mod = MODE_IMM_ASSIGN;
+
+  /*
+   * set starting time if available
+   */
+  memcpy (&dedicated_req->start, start,
+          sizeof (T_start));
+
+  /*
+   * set channel type
+   */
+  dedicated_req->ch_type.ch    = rr_data->sc_data.chan_desc.chan_type;
+  dedicated_req->ch_type.tn    = rr_data->sc_data.chan_desc.tn;
+  dedicated_req->ch_type.tsc   = rr_data->sc_data.chan_desc.tsc;
+  dedicated_req->ch_type.h     = rr_data->sc_data.chan_desc.hop;
+
+  if (rr_data->sc_data.chan_desc.hop EQ H_NO)
+  {
+    /*
+     * set channel number if no hopping is configured
+     */
+    dedicated_req->ch_type.arfcn = rr_data->sc_data.chan_desc.arfcn;
+  }
+  else
+  {
+    /*
+     * set maio, hsn and hopping list, if hopping is configured
+     */
+    dedicated_req->ch_type.maio  = rr_data->sc_data.chan_desc.maio;
+    dedicated_req->ch_type.hsn   = rr_data->sc_data.chan_desc.hsn;
+
+    /* CSI-LLD section:4.1.1.11
+     * This function Updates the black list with the MA list received
+     * in immediate_assignment req
+     */
+    cs_remove_BA_MA_from_black_list(rr_data->cs_data.region,freq_after_sti);
+
+    srv_create_list (freq_after_sti, dedicated_req->ch_type.ma,
+                     MAX_MA_CHANNELS, TRUE, 0);
+  }
+
+  /*
+   * set channel type 2 (only maio and mobile allocation)
+   */
+  dedicated_req->ch_type2.maio  = maio;
+
+  /* CSI-LLD section:4.1.1.11
+   * This function Updates the black list with the MA list received
+   * in immediate_assignment req
+   */
+  cs_remove_BA_MA_from_black_list(rr_data->cs_data.region,freq_bef_sti);
+
+  srv_create_list (freq_bef_sti, dedicated_req->ch_type2.ma, MAX_MA_CHANNELS,
+                   TRUE, 0);
+
+  dedicated_req->arfcn         = rr_data->nc_data[SC_INDEX].arfcn;
+
+  /*
+   * set power, dtx, rlt, pwrc, timing advance and channel mode
+   */
+  dedicated_req->tr_para.power = power;
+  dedicated_req->tr_para.dtx   = rr_data->sc_data.cd.dtx;
+  dedicated_req->tr_para.rlt   = rr_data->sc_data.cd.cell_options.rlt;
+  dedicated_req->tr_para.pwrc  = rr_data->sc_data.cd.cell_options.pow_ctrl;
+  dedicated_req->tr_para.tav   = rr_data->sc_data.new_ta;
+  dedicated_req->tr_para.mode  = rr_data->sc_data.ch_mode;
+
+  RR_EM_GET_HOPPING_CHANNEL(dedicated_req->ch_type.ma,dedicated_req->ch_type2.ma,
+	                            dedicated_req->start.v_start,maio);
+
+  PSENDX (PL, dedicated_req);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_code_mph_freq_redef_req|
++--------------------------------------------------------------------+
+
+  PURPOSE : configure a new hopping list after reception of a frequency
+            redefinition message.
+
+*/
+
+GLOBAL void dat_code_mph_freq_redef_req (T_start   *start,
+                                         T_LIST    *hop_list)
+{
+  GET_INSTANCE_DATA;
+
+  T_chan_desc * chan_desc = &rr_data->sc_data.chan_desc;
+
+  PALLOC (freq_redef_req, MPH_FREQ_REDEF_REQ);
+
+  TRACE_FUNCTION ("dat_code_mph_freq_redef_req()");
+
+  /*
+   * copy start time
+   */
+  memcpy (&freq_redef_req->start, start, sizeof (T_start));
+
+  /*
+   * set new hopping list
+   */
+  srv_create_list (hop_list, freq_redef_req->ch_type.ma, MAX_MA_CHANNELS, TRUE,0);
+
+  /* CSI-LLD section:4.1.1.11
+   * This function Updates the black list with the MA list received
+   * in Frequency redifinition message
+   */
+  cs_remove_BA_MA_from_black_list(rr_data->cs_data.region,hop_list);
+
+  /*
+   * set channel type, timeslot, training sequence code,
+   * hopping indication, maio and hsn.
+   */
+  freq_redef_req->ch_type.ch   = chan_desc->chan_type;
+  freq_redef_req->ch_type.tn   = chan_desc->tn;
+  freq_redef_req->ch_type.tsc  = chan_desc->tsc;
+  freq_redef_req->ch_type.h    = chan_desc->hop;
+  freq_redef_req->ch_type.maio = chan_desc->maio;
+  freq_redef_req->ch_type.hsn  = chan_desc->hsn;
+
+  rr_data->mode_after_dedi = MODE_CELL_RESELECTION;
+
+  EM_FREQ_REDEF;
+
+  RR_EM_GET_HOPPING_CHANNEL (freq_redef_req->ch_type.ma, freq_redef_req->ch_type.ma, FALSE,0);
+
+  PSENDX (PL, freq_redef_req);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_code_mph_old_chan_req  |
++--------------------------------------------------------------------+
+
+  PURPOSE : During channel assignment or handover the layer 2 link is
+            suspended and a new channel is configured. Then the layer 2
+            connection is resumed on the new channel. If this fails,
+            RR switches back to the old channel. The trigger for this
+            is this function.
+
+*/
+
+GLOBAL void dat_code_mph_old_chan_req (void)
+{
+  PALLOC ( mph_dedicated_fail_req, MPH_DEDICATED_FAIL_REQ);
+
+  TRACE_FUNCTION ("dat_code_mph_old_chan_req()");
+
+  PSENDX (PL, mph_dedicated_fail_req);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_code_prr_channel       |
++--------------------------------------------------------------------+
+
+  PURPOSE : Set the channel type and the service access point
+            identification according to the configured channel type.
+
+*/
+
+GLOBAL void dat_code_prr_channel (UBYTE     *ch_type,
+                                  UBYTE     *sapi,
+                                  UBYTE      chan_type)
+{
+  TRACE_FUNCTION ("dat_code_prr_channel()");
+
+  /*
+   * SAPI is always 0
+   */
+  *sapi    = SAPI_0;
+
+  /*
+   * convert air-interface coding of channel type
+   * to internal values.
+   */
+  switch (chan_type)
+  {
+    case CH_TCH_F:
+      *ch_type = L2_CHANNEL_FACCH_F;
+      break;
+    case CH_TCH_H_1:
+    case CH_TCH_H_2:
+      *ch_type = L2_CHANNEL_FACCH_H;
+      break;
+    default:
+      *ch_type = L2_CHANNEL_SDCCH;
+      break;
+  }
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_code_prr_channel_sms   |
++--------------------------------------------------------------------+
+
+  PURPOSE : Set the channel type and the service access point
+            identification according to the configured channel type
+            for short messages.
+
+*/
+
+GLOBAL void dat_code_prr_channel_sms (T_DL_DATA_REQ *dl_data_req,
+                                      UBYTE         chan_type)
+{
+  TRACE_FUNCTION ("dat_code_prr_channel_sms()");
+
+  /*
+   * sapi is always 3
+   */
+  dl_data_req->sapi    = SAPI_3;
+
+  /*
+   * channel type is SACCH if the main channel (sapi = 0)
+   * is FACCH, else it is SDCCH.
+   */
+  dl_data_req->ch_type = (chan_type < CH_SDCCH_4_0)\
+                         ? L2_CHANNEL_SACCH : L2_CHANNEL_SDCCH;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_code_prr_bcch_info     |
++--------------------------------------------------------------------+
+
+  PURPOSE : create a list of channels from the ba_range information
+            element of a channel release message.
+
+*/
+
+GLOBAL void dat_code_prr_bcch_info (UBYTE        v_ba_range,
+                                    T_ba_range * ba_range)
+{
+  T_LIST   list;
+  USHORT   i;
+  USHORT   j;
+  USHORT   x1;
+  USHORT   x2;
+
+  TRACE_FUNCTION ("dat_code_prr_bcch_info()");
+
+  /*
+   * initialization : the list is empty.
+   */
+  srv_clear_list (&list);
+
+  if (v_ba_range)
+  {
+    /*
+     * only if the information element is inside the
+     * channel release message.
+     * Then for all ranges inside the information element.
+     */
+    for (i=0;i<ba_range->c_freq_range;i++)
+    {
+      x1 = ba_range->freq_range[i].freq_lower;
+      x2 = ba_range->freq_range[i].freq_higher;
+      /*
+       *   set interval borders
+       */
+      if (x1 > HIGH_CHANNEL_900)
+        x1 = HIGH_CHANNEL_900;
+      if (x2 > HIGH_CHANNEL_900)
+        x2 = HIGH_CHANNEL_900;
+
+      if (x1 EQ x2)
+      {
+        /*
+         * add x1 to channel list if both boarders have the same value
+         */
+        srv_set_channel (&list, x1);
+      }
+
+      if (x1 < x2)
+      {
+        /*
+         * add x1..x2 to channel list if the boarders define a range
+         */
+        for (j=x1;j<=x2;j++)
+          srv_set_channel (&list, j);
+      }
+
+      if (x1 > x2)
+      {
+        /*
+         * add LOW_CHANNEL_900..x2 and x1..HIGH_CHANNEL_900 to channel list
+         */
+        for (j=LOW_CHANNEL_900;j<=HIGH_CHANNEL_900;j++)
+          if (j <= x2 OR j>=x1)
+            srv_set_channel (&list, j);
+      }
+    }
+
+    /*
+     * send the resulting list to the SIM card or store it inside the PCM
+     */
+  }
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_send_bcchinfo_mm       |
++--------------------------------------------------------------------+
+
+  PURPOSE : Send neigbour cell description to MM
+
+*/
+
+GLOBAL void dat_send_bcchinfo_mm (UBYTE *p)
+{
+  PALLOC (sync_ind, RR_SYNC_IND);
+  sync_ind->ciph             = NOT_PRESENT_8BIT;
+  sync_ind->chm.ch_mode      = NOT_PRESENT_8BIT;
+  sync_ind->mm_info.valid    = FALSE;
+  sync_ind->bcch_info.v_bcch = TRUE;
+  sync_ind->synccs           = NOT_PRESENT_16BIT;
+  if (p)
+  {
+    memcpy (sync_ind->bcch_info.bcch, p, BA_BITMAP_SIZE);
+    TRACE_EVENT_P4 ("BCCHINFO: send 16 byte to MM/SIM (%x,%x,%x,%x,...)", p[0], p[1], p[2], p[3]);
+  }
+  else
+  {
+    memset (sync_ind->bcch_info.bcch, 0, BA_BITMAP_SIZE);
+    TRACE_EVENT ("BCCHINFO: clear SIM");
+  }
+  PSENDX (MM, sync_ind);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_convert_white_list     |
++--------------------------------------------------------------------+
+
+  PURPOSE : Updates White List after cell selection and cell reselection
+            in Full service
+            CSI-LLD section:4.1.2.2.2
+*/
+
+GLOBAL void dat_convert_white_list(void)
+{
+  GET_INSTANCE_DATA;
+  U8 *p = NULL;
+  U8 i;
+  T_LIST tmp_list;
+  BUF_neigh_cell_desc cd;
+
+  TRACE_FUNCTION("dat_convert_white_list()");
+
+  if(rr_data->ms_data.rr_service EQ FULL_SERVICE)
+  {
+    TRACE_EVENT("CR white list -> CS white list");
+
+    /* Clear the old White List info */
+    memset(&rr_data->cs_data.white_list, 0x00, sizeof(T_CS_WHITE_LIST));
+
+    /* copy the serving cell ARFCN */
+    rr_data->cs_data.white_list.last_sc_arfcn = rr_data->nc_data[SC_INDEX].arfcn;
+
+    /* copy the serving cell region */
+    rr_data->cs_data.white_list.region = rr_data->cs_data.region;
+
+    /* Copy the serving cell location area identity */
+    memcpy(&rr_data->cs_data.white_list.last_sc_lac,&rr_data->nc_data[SC_INDEX].lai,
+            sizeof(T_loc_area_ident));
+
+    /* Convert CR white list into T_LIST format and store the same */
+    for(i=0;i<=32;i+=BA_BITMAP_SIZE)
+    {
+      switch(i)
+      {
+        case 0:
+         p = rr_data->cr_data.cr_white_list.si2;
+         break;
+        case 16:
+         p = rr_data->cr_data.cr_white_list.si2bis;
+         break;
+        case 32:
+         p = rr_data->cr_data.cr_white_list.si2ter;
+         break;
+        default:
+          continue;
+      }
+
+      if(p NEQ NULL)
+      {
+        memcpy(cd.b_neigh_cell_desc,p,BA_BITMAP_SIZE);
+        cd.o_neigh_cell_desc = 0;
+        cd.l_neigh_cell_desc = NCELL_DESC_BIT_LEN;
+
+        for_create_channel_list((T_f_range *)&cd,&tmp_list);
+        srv_merge_list(&rr_data->cs_data.white_list.list,&tmp_list);
+      }
+    }
+
+    /* Use last serving cell information also */
+    if(rr_data->cs_data.white_list.last_sc_arfcn NEQ NOT_PRESENT_16BIT)
+    {
+      srv_set_channel(&rr_data->cs_data.white_list.list,
+                      rr_data->cs_data.white_list.last_sc_arfcn&ARFCN_MASK);
+     }
+
+    TRACE_EVENT_P9 ( "White List:[%d]Reg,[%d]Arfcn MCC/MNC r=%x%x%x/%x%x%x/%d",
+      rr_data->cs_data.white_list.region,
+      rr_data->cs_data.white_list.last_sc_arfcn,
+      rr_data->cs_data.white_list.last_sc_lac.mcc[0],
+      rr_data->cs_data.white_list.last_sc_lac.mcc[1],
+      rr_data->cs_data.white_list.last_sc_lac.mcc[2],
+      rr_data->cs_data.white_list.last_sc_lac.mnc[0],
+      rr_data->cs_data.white_list.last_sc_lac.mnc[1],
+      rr_data->cs_data.white_list.last_sc_lac.mnc[2],
+      rr_data->cs_data.white_list.last_sc_lac.lac);
+
+  } /* Full service */
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_store_neigh_cell_desc  |
++--------------------------------------------------------------------+
+
+  PURPOSE : Store neigbour cell description in case of full service
+
+*/
+
+GLOBAL void dat_store_neigh_cell_desc (UBYTE si, UBYTE index,
+                                       BUF_neigh_cell_desc *cd,
+                                       T_LIST *new_neigh_list)
+{
+  GET_INSTANCE_DATA;
+  U8 *p = NULL;
+  U16 o;
+  U8 att_state = GET_STATE (STATE_ATT);
+
+#if defined(_SIMULATION_)
+  {
+    BOOL  plmn_ok;
+
+    plmn_ok = dat_plmn_equal_req (rr_data->nc_data[index].lai.mcc,
+                                  rr_data->nc_data[index].lai.mnc,
+                                  rr_data->ms_data.plmn.mcc,
+                                  rr_data->ms_data.plmn.mnc);
+    TRACE_EVENT_P8 ("dat_store_neigh_cell_desc(): srv:%s op:%s tried:%u, st:%s, NC%u plmn:%u CR:%d SC:%d",
+      _rr_str_SERVICE[rr_data->ms_data.rr_service],
+      _rr_str_FUNC[rr_data->ms_data.req_mm_service],
+      (rr_data->cs_data.scan_mode EQ CS_SECOND_SCAN),
+      STATE_ATT_NAME[att_state], index, plmn_ok,
+      ((int)rr_data->nc_data[CR_INDEX].arfcn),
+      ((int)rr_data->nc_data[SC_INDEX].arfcn));
+  }
+#endif  /* 0|1 */
+
+  if (rr_data->ms_data.req_mm_service EQ FUNC_PLMN_SRCH)
+  {
+    /*
+     * In states ATT_CS2 and ATT_CS3, store BA lists from SI2, 2Bis and 2Ter
+     * inside rr_data->cr_data
+     */
+    if ((att_state EQ ATT_CS2 OR att_state EQ ATT_CS3) AND (index EQ CR_INDEX))
+    {
+      switch (si)
+      {
+        case SYS_INFO_2_MSG:
+          p = rr_data->cr_data.cr_white_list.si2;
+          break;
+        case SYS_INFO_2bis_MSG:
+          p = rr_data->cr_data.cr_white_list.si2bis;
+          break;
+        case SYS_INFO_2ter_MSG:
+          p = rr_data->cr_data.cr_white_list.si2ter;
+          break;
+        default:
+          return;
+      }
+
+      TRACE_EVENT_P3 ("BCCHINFO: store cd of [%d]i%u: si=%02x ",
+                       rr_data->nc_data[index].arfcn, index, si);
+
+      /* compare; store and indicate only if changed */
+      o = cd->o_neigh_cell_desc>>3;
+      if (p NEQ NULL)
+      {
+        if (memcmp (p, &cd->b_neigh_cell_desc[o], BA_BITMAP_SIZE))
+        {
+          memcpy (p, &cd->b_neigh_cell_desc[o], BA_BITMAP_SIZE);
+        }
+      }
+    } /* CR_INDEX */
+
+    else if((att_state EQ ATT_IDLE) AND (index EQ SC_INDEX) AND
+            (rr_data->ms_data.rr_service EQ FULL_SERVICE))
+    {
+      /* In state ATT_IDLE, store BA list directly inside the white list
+       * (only if we are in Full Service)
+       */
+      srv_copy_list (&rr_data->cs_data.white_list.list, new_neigh_list,
+                     sizeof (T_LIST));
+
+      /* Add current serving cell to White List */
+      srv_set_channel(&rr_data->cs_data.white_list.list,
+                      rr_data->nc_data[SC_INDEX].arfcn&ARFCN_MASK);
+
+      if(si EQ SYS_INFO_2_MSG)
+      {
+        /* In case it is the description of system information 2 (and only then)
+         * it should be stored in the SIM card.
+         */
+        o = cd->o_neigh_cell_desc>>3;
+        dat_send_bcchinfo_mm (&cd->b_neigh_cell_desc[o]);
+      }
+    }
+
+    /* additional storing of current serving cell and cell-re-selection cell */
+    rr_data->cs_data.arfcn_sc = rr_data->nc_data[SC_INDEX].arfcn;
+    rr_data->cs_data.arfcn_cr = rr_data->nc_data[CR_INDEX].arfcn;
+  }
+}
+
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_compare_request_ref    |
++--------------------------------------------------------------------+
+
+  PURPOSE : Reference is GSM 4.08, chapter 3.3.1.1.3.1 On receipt of a
+            CHANNEL REQUEST message
+
+            On receipt of an IMMEDIATE ASSIGNMENT or IMMEDIATE ASSIGNMENT
+            EXTENDED message corresponding to one of its 3 last CHANNEL
+            REQUEST messages, the message shall be identified as the
+            channel description for the MS.
+
+*/
+
+GLOBAL BOOL dat_compare_request_ref (T_req_ref *req_ref, UBYTE * index)
+{
+  GET_INSTANCE_DATA;
+  UBYTE        from;
+  UBYTE        i;
+
+  TRACE_FUNCTION ("dat_compare_request_ref()");
+
+  /*
+   * RR stores the request references for all outgoing
+   * channel requests. The variable from indicates the
+   * beginning of the maximum 3 last channel requests.
+   */
+
+  from = (rr_data->ms_data.access_counter > 2) ?
+          rr_data->ms_data.access_counter - 3 : 0;
+
+  TRACE_EVENT_P4 ("compare: %d %d %d 0x%02x",
+    req_ref->t1, req_ref->t2, req_ref->t3, req_ref->ra);
+
+  TRACE_ASSERT(  rr_data->ms_data.access_counter <=  MAX_RACH_REQ);
+
+  for (i = from; i < rr_data->ms_data.access_counter; i++)
+  {
+    /*
+     * RR checks the sending time T1/T2/T3 of the channel
+     * request message and the content of the message.
+     * If all matches the immediate assignment (extended)
+     * message is identified for the MS.
+     */
+     TRACE_EVENT_P5 ("with[%u]: %d %d %d 0x%02x", i,
+      rr_data->used_frame_no[i].t1, rr_data->used_frame_no[i].t2,
+      rr_data->used_frame_no[i].t3, rr_data->used_channel_ref[i]);
+
+     if (rr_data->used_frame_no[i].t1 EQ req_ref->t1 AND
+         rr_data->used_frame_no[i].t2 EQ req_ref->t2 AND
+         rr_data->used_frame_no[i].t3 EQ req_ref->t3 AND
+         rr_data->used_channel_ref[i] EQ req_ref->ra)
+     {
+       *index = i;
+       return TRUE;
+     }
+  }
+
+  /*
+   * The message is not for the MS
+   */
+  return FALSE;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_disconnect_link        |
++--------------------------------------------------------------------+
+
+  PURPOSE : After reception of a channel release message this function
+            starts the disconnection of the link in layer 2.
+
+*/
+
+GLOBAL void dat_disconnect_link (USHORT cause)
+{
+  GET_INSTANCE_DATA;
+  UBYTE  ch_type;
+
+  PALLOC (dl_release_req, DL_RELEASE_REQ);
+
+  TRACE_FUNCTION ("dat_disconnect_link()");
+
+  rr_data->rel_cause      = cause;
+
+  /*
+   * set channel type and sapi according the configured channel
+   * configuration
+   */
+  dat_code_prr_channel (&dl_release_req->ch_type,
+                        &dl_release_req->sapi,
+                        rr_data->sc_data.chan_desc.chan_type);
+
+  ch_type = dl_release_req->ch_type;
+  dl_release_req->mode = DL_NORMAL_RELEASE;
+  PSENDX (DL, dl_release_req);
+
+  /*
+   * control layer 2 release. The timer shall be set in a way
+   * that layer 2 has enough time for at least two DISC frames.
+   * So the value of the timer depends on the channel type
+   * (SDCCH or FACCH).
+   */
+  if (ch_type EQ L2_CHANNEL_SDCCH)
+  {
+    TIMERSTART (T3110, T3110_SDCCH_VALUE);
+  }
+  else
+  {
+    TIMERSTART (T3110, T3110_VALUE);
+  }
+
+  SET_STATE (STATE_DAT, DAT_CHAN_REL);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_fill_mobile_identity   |
++--------------------------------------------------------------------+
+
+  PURPOSE : In several update message the mobile identity must be set.
+            For mobile terminated message the mobile identity of
+            the paging message must be used.
+            For mobile originated connections the mobile identity type
+            depends on the availability of the mobile identities in
+            this order:  TMSI, IMSI, no identity
+
+*/
+
+static void dat_fill_mobile_identity (USHORT      fill_type,
+                                     T_mob_ident *moid)
+{
+  GET_INSTANCE_DATA;
+  UBYTE mobile_type;
+
+  TRACE_FUNCTION ("dat_fill_mobile_identity()");
+
+  memset (moid, 0, sizeof (T_mob_ident));
+
+  /*
+   * for MTC set the type according the paging identity type.
+   */
+  if (fill_type EQ ESTCS_PAGING)
+    mobile_type = rr_data->page_identity_type;
+  else
+  {
+    /*
+     * for MOC set the type according the availability
+     */
+    if (rr_data->ms_data.tmsi_available)
+      mobile_type = TYPE_TMSI;
+    else
+      mobile_type = (rr_data->ms_data.imsi_available)
+                    ? TYPE_IMSI : TYPE_NO_ID;
+  }
+
+  /*
+   * fill the identity according the calculated type
+   */
+  switch (mobile_type)
+  {
+    case TYPE_TMSI:
+      TRACE_EVENT ("FILL TMSI");
+      moid->ident_type      = TYPE_TMSI;
+      moid->tmsi_1.l_tmsi_1   = 32;
+      moid->tmsi_1.o_tmsi_1   = 0;
+      moid->odd_even        = 0;
+      moid->v_tmsi_1        = TRUE;
+      ccd_codeByte (moid->tmsi_1.b_tmsi_1, 0, 8, (UBYTE)(rr_data->ms_data.tmsi_binary >> 24));
+      ccd_codeByte (moid->tmsi_1.b_tmsi_1, 8, 8, (UBYTE)(rr_data->ms_data.tmsi_binary >> 16));
+      ccd_codeByte (moid->tmsi_1.b_tmsi_1, 16, 8, (UBYTE)(rr_data->ms_data.tmsi_binary >> 8));
+      ccd_codeByte (moid->tmsi_1.b_tmsi_1, 24, 8, (UBYTE)rr_data->ms_data.tmsi_binary);
+      break;
+
+    case TYPE_IMSI:
+      TRACE_EVENT ("FILL IMSI");
+      memcpy (moid, &rr_data->ms_data.imsi, sizeof (T_mob_ident));
+      break;
+
+    default:
+      TRACE_EVENT ("FILL NOTHING");
+      memset (moid, 0, sizeof (T_mob_ident));
+      break;
+  }
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_check_forb_list        |
++--------------------------------------------------------------------+
+
+  PURPOSE : In automatic mode a cell shall be only selected if it is
+            not member of a forbidden location area list.
+            This function checks the membership in a forbidden LAI
+            independant of the selected mode (manual or automatic).
+
+*/
+
+LOCAL BOOL dat_check_forb_list (int list_type, UBYTE index)
+{
+  GET_INSTANCE_DATA;
+  int i;
+  T_loc_area_ident *forb_list;
+
+  TRACE_FUNCTION ("dat_check_forb_list()");
+
+  if (list_type EQ FORBIDDEN_LIST_NORMAL)
+    forb_list = &rr_data->ms_data.forb_lac_list[0];
+  else
+    forb_list = &rr_data->ms_data.roam_forb_lac_list[0];
+
+  TRACE_ASSERT(index < NCELL_SIZE);
+  
+  /*
+   *
+   * check only in automatic mode
+   *
+   * if ((rr_data->ms_data.operation_mode & 0x40) EQ 0) M_MAN
+   */
+  {
+    /*
+     * check all entries of this list
+     */
+    for (i = 0; i < MAX_LAI; i++)
+    {
+      if ((rr_data->nc_data[index].lai.lac EQ forb_list[i].lac) AND
+          dat_plmn_equal_req (rr_data->nc_data[index].lai.mcc,
+                              rr_data->nc_data[index].lai.mnc,
+                              forb_list[i].mcc,
+                              forb_list[i].mnc))/*lint !e661 !e662 (possible access/creation of out-of-bounds pointer)*/
+      {
+        /*
+         * the check is failed if the location area code is stored.
+         */
+        return FALSE;
+      }
+    }
+  }
+  /*
+   * the check has passed.
+   */
+  return TRUE;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_forb_lai_check         |
++--------------------------------------------------------------------+
+
+  PURPOSE : In automatic mode a cell shall be only selected if it is
+            not member of a forbidden location area list.
+
+*/
+
+GLOBAL BOOL dat_forb_lai_check (UBYTE index)
+{
+  TRACE_FUNCTION ("dat_forb_lai_check()");
+
+  return dat_check_forb_list (FORBIDDEN_LIST_NORMAL, index);
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_roam_forb_lai_check    |
++--------------------------------------------------------------------+
+
+  PURPOSE : In automatic mode a cell shall be only selected if it is
+            not member of a forbidden location area list.
+
+*/
+
+GLOBAL BOOL dat_roam_forb_lai_check (UBYTE index)
+{
+  TRACE_FUNCTION ("dat_roam_forb_lai_check()");
+
+  return dat_check_forb_list (FORBIDDEN_LIST_ROAMING, index);
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_get_background_and_bits|
++--------------------------------------------------------------------+
+
+  PURPOSE : The content of a channel request consists of two parts:
+            The establishment cause and a random value. The function
+            calculates the establishment cause (here defined as background)
+            and the number of bits for the random value.
+
+            The establishment cause inside the channel request message
+            depends on several parameters:
+
+            the internal used establishment cause,
+            the last used channel
+            the NECI-Flag in the system information message
+            the needed channel indicated in a paging message
+            the mobile station capabilities and
+            whether a TCH fullrate is needed
+
+            The abbreviation IG means Ignore. In this case the parameter
+            is not relevant for the calculation.
+
+*/
+#ifdef GPRS
+#define TABLE_SIZE 30
+#else
+#define TABLE_SIZE 21
+#endif
+
+static const CODE_TABLE coding_table [TABLE_SIZE] =
+/*
+ *  establish cause         last NECI  channel   MS    TCH/F   Back-  Bits
+ *                       channel        needed  cap.  needed  ground
+ */
+{ ESTCS_EMERGENCY_CALL,       IG,  IG,      IG,   IG,     IG,  0xA0,    5,
+  ESTCS_REESTABLISHMENT,  TCHFCH,  IG,      IG,   IG,     IG,  0xC0,    5,
+  ESTCS_REESTABLISHMENT,  TCHHCH,   0,      IG,   IG,     IG,  0xC0,    5,
+  ESTCS_REESTABLISHMENT,  TCHHCH,   1,      IG,   IG,     IG,  0x68,    2,
+#ifdef GPRS
+  ESTCS_GPRS_PAGING,          IG,  IG,   ANYCH,   IG,     IG,  0x80,    5,
+  ESTCS_GPRS_PAGING,          IG,  IG,  TCHFCH, FULL,     IG,  0x80,    5,
+  ESTCS_GPRS_PAGING,          IG,  IG, TCHHFCH, FULL,     IG,  0x80,    5,
+  ESTCS_GPRS_PAGING,          IG,  IG,  TCHFCH, DUAL,     IG,  0x20,    4,
+  ESTCS_GPRS_PAGING,          IG,  IG, TCHHFCH, DUAL,     IG,  0x30,    4,
+  ESTCS_GPRS_PAGING,          IG,  IG, SDCCHCH,   IG,     IG,  0x10,    4,
+  ESTCS_GPRS_PAGING,          IG,  IG,      IG, SIGN,     IG,  0x10,    4,
+#endif
+  ESTCS_PAGING,               IG,  IG,   ANYCH,   IG,     IG,  0x80,    5,
+  ESTCS_PAGING,               IG,  IG,  TCHFCH, FULL,     IG,  0x80,    5,
+  ESTCS_PAGING,               IG,  IG, TCHHFCH, FULL,     IG,  0x80,    5,
+  ESTCS_PAGING,               IG,  IG,  TCHFCH, DUAL,     IG,  0x20,    4,
+  ESTCS_PAGING,               IG,  IG, TCHHFCH, DUAL,     IG,  0x30,    4,
+  ESTCS_PAGING,               IG,  IG, SDCCHCH,   IG,     IG,  0x10,    4,
+  ESTCS_PAGING,               IG,  IG,      IG, SIGN,     IG,  0x10,    4,
+  ESTCS_MOC_SPEECH,           IG,   0,      IG,   IG,     IG,  0xE0,    5,
+  ESTCS_MOC_SPEECH,           IG,   1,      IG, DUAL,  FALSE,  0x40,    4,
+  ESTCS_MOC_SPEECH,           IG,  IG,      IG,   IG,     IG,  0xE0,    5,
+  ESTCS_MOC_DATA,             IG,   0,      IG,   IG,     IG,  0xE0,    5,
+  ESTCS_MOC_DATA_HR_SUFF,     IG,   1,      IG, DUAL,  FALSE,  0x50,    4,
+  ESTCS_MOC_DATA,             IG,  IG,      IG,   IG,     IG,  0xE0,    5,
+  ESTCS_LOCATION_UPDATING,    IG,   0,      IG,   IG,     IG,  0x00,    5,  /* new */
+  ESTCS_LOCATION_UPDATING,    IG,   1,      IG,   IG,     IG,  0x00,    4,
+  ESTCS_MOC_SS_SMS,           IG,   0,      IG,   IG,     IG,  0xE0,    5,
+#ifndef GPRS
+  ESTCS_MOC_SS_SMS,           IG,   1,      IG,   IG,     IG,  0x10,    4
+#else
+  ESTCS_MOC_SS_SMS,           IG,   1,      IG,   IG,     IG,  0x10,    4,
+  ESTCS_GPRS_1P,              IG,  IG,      IG,   IG,     IG,  0x78,    3,
+  ESTCS_GPRS_SB,              IG,  IG,      IG,   IG,     IG,  0x70,    3
+#endif
+};
+
+static void dat_get_background_and_bits (UBYTE     *background,
+                                        UBYTE     *bits)
+{
+  GET_INSTANCE_DATA;
+
+  UBYTE  i;
+  USHORT ms_capability;
+
+  TRACE_FUNCTION ("dat_get_background_and_bits()");
+
+  /*
+   * initialise the output parameter
+   */
+  *background   = 0;
+  *bits         = 5;
+  ms_capability = SIGN;
+
+  /*
+   * check the support of vocoder
+   */
+  if (FldGet(rr_data->mscap.chnMode, VocSup))
+  {
+    ms_capability = (FldGet (rr_data->mscap.chnMode, hrSup)) ? DUAL : FULL;
+  }
+
+  /*
+   * go through the table until all criterions are passed (or can be ignored).
+   */
+  for (i = 0; i < TABLE_SIZE; i++)
+  {
+    /*
+     * check internal establishment cause
+     */
+     if (rr_data->ms_data.establish_cause NEQ coding_table[i].cause)
+       continue;
+
+     /*
+      * check last used channel if applicable
+      */
+     if (coding_table[i].last_channel NEQ IG)
+     {
+       if (rr_data->ms_data.last_used_channel NEQ
+           coding_table[i].last_channel)
+         continue;
+     }
+
+     /*
+      * check new establishment cause indication flag if applicable
+      */
+     if (coding_table[i].neci_flag NEQ IG)
+     {
+       if (rr_data->nc_data[SC_INDEX].select_para.neci NEQ
+           coding_table[i].neci_flag)
+         continue;
+     }
+
+     /*
+      * check the channel needed indication of the paging messages
+      * if applicable
+      */
+     if (coding_table[i].channel_needed NEQ IG)
+     {
+       if (rr_data->ms_data.channel_needed NEQ
+           coding_table[i].channel_needed)
+         continue;
+     }
+
+     /*
+      * check the MS capability if applicable
+      */
+     if (coding_table[i].ms_capability NEQ IG)
+     {
+       if (ms_capability NEQ coding_table[i].ms_capability)
+         continue;
+     }
+
+     /*
+      * check the TCH Fullrate needed flag is applicable.
+      */
+     if (coding_table[i].tch_f_needed NEQ IG)
+     {
+       if ((rr_data->ms_data.establish_cause NEQ ESTCS_MOC_SPEECH) AND
+           (rr_data->ms_data.establish_cause NEQ ESTCS_MOC_DATA_HR_SUFF))
+         continue;
+     }
+
+     /*
+      * add this point all criterions are passed, so use the table contents.
+      */
+     *background = coding_table[i].background;
+     *bits       = coding_table[i].bits;
+     return;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_get_burst              |
++--------------------------------------------------------------------+
+
+  PURPOSE : This functions adds a random value to the channel request
+            content. The random value is calculated from a well distributed
+            table.
+
+*/
+static const UBYTE random_values[32] = {  9, 27, 17,  6, 10, 15,  2, 23,
+                                         29, 14,  4, 26, 18,  0, 31, 13,
+                                         21,  1, 30, 22,  5, 24, 20,  8,
+                                          7, 28, 16, 11, 25, 12,  3, 19
+                                        };
+static const UBYTE mask[]            = { 3, 7, 15, 31 };
+
+static UBYTE dat_get_burst (UBYTE     background,
+                            UBYTE     bits)
+{
+  GET_INSTANCE_DATA;
+  UBYTE random_value;
+
+  TRACE_FUNCTION ("dat_get_burst()");
+
+  rr_data->ms_data.index++;
+  rr_data->ms_data.index %= 32;
+  random_value = random_values[rr_data->ms_data.index];
+
+#ifdef GPRS
+  if(
+      (rr_data->ms_data.establish_cause EQ ESTCS_GPRS_1P)
+        AND
+      ((random_value & mask[bits - 2]) EQ 7)
+    )
+  {
+
+    return (background + 6);
+  }
+#endif
+
+  return (background + (random_value & mask[bits - 2]));
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_get_delta              |
++--------------------------------------------------------------------+
+
+  PURPOSE : Reference GSM 4.08, chapter 3.3.1.1.2 Initiation of the
+            immediate assignment procedure
+
+            The RR entity of the mobile station initiates the immediate
+            assignment procedure by scheduling the sending on the
+            RACH and leaving idle mode.
+
+            It then sends maximally M + 1 CHANNEL REQUEST messages on
+            the RACH in a way such that:
+
+            - the number of slots belonging to the mobile station's RACH
+            between initiation of the immediate assignment procedure and
+            the first CHANNEL REQUEST message (excluding the slot containing
+            the message itself) is a random value drawn randomly for each
+            new initial assignment initiation with uniform probability
+            distribution in the set {0, 1, ..., max (T,8) - 1};
+
+            - the number of slots belonging to the mobile station's RACH
+            between two successive CHANNEL REQUEST messages (excluding
+            the slots containing the messages themselves) is a random value
+            drawn randomly for each new transmission with uniform probability
+            distribution in the set {S, S + 1, ..., S + T - 1};
+
+            Here, T is the value of the parameter "Tx-integer" broadcast on the BCCH;
+
+            M is the value of the parameter "max retrans" broadcast on the BCCH;
+
+            S is a parameter depending on the CCCH configuration and on the value
+            of Tx-integer as defined in table 3.1/GSM 04.08.
+
+            Table 3.1/GSM 04.08: Values of parameter S
+
+            +-----------------------------------------------------+
+            + TX-integer + non combined CCCH + combined CCH/SDCCH +
+            +------------+-------------------+--------------------+
+            + 3,8,14,50  +         55        +          41        +
+            + 4,9,16     +         76        +          52        +
+            + 5,10,20    +        109        +          58        +
+            + 6,11,25    +        163        +          86        +
+            + 7,12,32    +        217        +         115        +
+            +-----------------------------------------------------+
+
+*/
+static const CONVERT_TXINTEGER  convert_table[MAX_TX_INTEGER] =
+  /*
+   *      T   S non combined   S combined Tx-integer
+   */
+    {
+          3,  55,              41,        /*  0 */
+          4,  76,              52,        /*  1 */
+          5, 109,              58,        /*  2 */
+          6, 163,              86,        /*  3 */
+          7, 217,             115,        /*  4 */
+          8,  55,              41,        /*  5 */
+          9,  76,              52,        /*  6 */
+         10, 109,              58,        /*  7 */
+         11, 163,              86,        /*  8 */
+         12, 217,             115,        /*  9 */
+         14,  55,              41,        /* 10 */
+         16,  76,              52,        /* 11 */
+         20, 109,              58,        /* 12 */
+         25, 163,              86,        /* 13 */
+         32, 217,             115,        /* 14 */
+         50,  55,              41         /* 15 */
+    };
+
+
+static UBYTE dat_get_delta (UBYTE i)
+{
+  GET_INSTANCE_DATA;
+
+  USHORT index = rr_data->nc_data[SC_INDEX].rach.tx_integer;
+  USHORT n;
+  USHORT result=0;
+
+  TRACE_FUNCTION ("dat_get_delta()");
+
+  /*
+   * calculate righ boarder of the interval.
+   */
+  TRACE_ASSERT( index < MAX_TX_INTEGER );
+  if( index < MAX_TX_INTEGER)
+  {
+    n = (i EQ 0) ? att_max (convert_table[index].t, 8) - 1
+               : convert_table[index].t - 1;
+
+  /*
+   * calculate random value
+   */
+  result = dat_random ((USHORT)(n+1));
+
+  /*
+   * If it is not the first value, add left boarder S
+   */
+  if (i NEQ 0)
+    {
+      /*
+       * in according to GSM 4.08, section 10.5.2.11 (Control Channel Description)
+       * and section 3.3.1.1.2 (Initiation of the immediate assignment procedure)
+       */
+      result +=
+        (rr_data->nc_data[SC_INDEX].control_descr.ccch_conf EQ COMB_CCCH_COMB)
+          ? convert_table[index].s_combined
+          : convert_table[index].s_non_combined;
+    }
+  }
+  return (UBYTE)result;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_get_ncell_pos          |
++--------------------------------------------------------------------+
+
+  PURPOSE : for uplink SACCH RR MEASUREMENT REPORT message the
+            position of a cell inside the neighbourcell list must
+            be calculated. This is done by this function.
+
+*/
+
+static UBYTE dat_get_ncell_pos (USHORT channel)
+{
+  GET_INSTANCE_DATA;
+  UBYTE i;
+
+  TRACE_FUNCTION ("dat_get_ncell_pos()");
+
+  /*
+   * the loop counter i is the position inside the actual
+   * neighbourcell list.
+   */
+  for (i=0; i<MAX_NEIGHBOURCELLS;i++)
+  {
+    if (channel EQ rr_data->act_ncell_list[i])
+    {
+      /*
+       * channel is found, then return the position.
+       */
+      return i;
+    }
+  }
+  return 0;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_eplmn_equal_req        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Compare found PLMN with all PLMNs in EPLMN list 
+
+
+*/
+
+static BOOL dat_eplmn_equal_req(const UBYTE *mcc, const UBYTE *mnc)
+{
+  GET_INSTANCE_DATA;
+  UBYTE i;
+
+  TRACE_FUNCTION("dat_eplmn_equal_req");
+
+  
+  if(rr_data->ms_data.v_eq_plmn)
+  {
+    for(i = 0; i < RR_EPLMNLIST_SIZE; i++)
+    {
+      if(!memcmp(rr_data->ms_data.eq_plmn_list[i].mcc, mcc, SIZE_MCC) &&
+         !memcmp(rr_data->ms_data.eq_plmn_list[i].mnc, mnc, SIZE_MNC))
+        return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_plmn_equal_req         |
++--------------------------------------------------------------------+
+
+  PURPOSE : The function checks whether the given mobile country code
+            and the given mobile network code describes the requested
+            PLMN, eg. the HPLMN distilled from the IMSI.
+            This is not exactly the algorithm as shown for HPLMN
+            matching as shown in 03.22 Normative Annex A, this version
+            here is more universal.
+
+*/
+
+GLOBAL BOOL dat_plmn_equal_req (const UBYTE *bcch_mcc, const UBYTE *bcch_mnc,
+                                const UBYTE *mm_mcc,  const UBYTE *mm_mnc)
+{
+  GET_INSTANCE_DATA;
+  if(((rr_data->ms_data.operation_mode >> SHIFT_FOR_SEARCH_OFFSET) & 1) EQ M_AUTO &&
+     rr_data->ms_data.req_mm_service NEQ FUNC_LIM_SERV_ST_SRCH)    
+  {
+    /* Check for equivalent EPLMNs */
+    if(dat_eplmn_equal_req(bcch_mcc, bcch_mnc))
+      return TRUE;
+  }
+
+  /* Check MCC */
+  if (memcmp (mm_mcc, bcch_mcc, SIZE_MCC) NEQ 0)
+    return FALSE;
+
+  /* Check first 2 MNC digits */
+  if (memcmp (mm_mnc, bcch_mnc, 2) NEQ 0)
+    return FALSE;
+
+  /* Check for full match */
+  if (mm_mnc[2] EQ bcch_mnc[2])
+    return TRUE;
+
+  /* The 3rd digit of the MNC differs */
+  if ((bcch_mcc[0] EQ 3) AND
+      (bcch_mcc[1] EQ 1) AND
+      INRANGE(0,bcch_mcc[2],6))
+  {
+    /*
+     * The MCC is in the range 310..316, this means North America.
+     * The zero suffix rule applies.
+     */
+    return (((mm_mnc[2] EQ 0xf) AND (bcch_mnc[2] EQ 0x0)) OR
+            ((mm_mnc[2] EQ 0x0) AND (bcch_mnc[2] EQ 0xf)));
+  }
+  return (bcch_mnc[2] EQ 0xf);
+}
+
+GLOBAL BOOL dat_hplmn (const UBYTE *mcc, const UBYTE *mnc)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_hplmn()");
+
+  /*
+   * only if a SIM is inserted and an IMSI is available
+   */
+  if (!rr_data->ms_data.imsi_available)
+    return FALSE;
+
+  if ((rr_data->ms_data.ahplmn.v_plmn EQ V_PLMN_PRES) AND
+      (rr_data->ms_data.req_mm_service EQ FUNC_PLMN_SRCH))
+  {
+    /*
+     * If AHPLMN is available
+     * do not compare the mcc, mnc from IMSI for the HPLMN
+     * use the AHPLMN
+     */
+    return dat_plmn_equal_req (mcc, mnc,
+                               rr_data->ms_data.ahplmn.mcc,
+                               rr_data->ms_data.ahplmn.mnc);
+  }
+
+  return dat_plmn_equal_req (mcc, mnc,
+                             &rr_data->ms_data.imsi.ident_dig[0],
+                             &rr_data->ms_data.imsi.ident_dig[3]);       
+   
+ }
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_hplmn_country          |
++--------------------------------------------------------------------+
+
+  PURPOSE : The function checks whether the given mobile country
+            code is equal to the first three digits of the IMSI.
+            The first three digits of the IMSI are equal to the
+            mobile country code of the HPLMN.
+
+*/
+
+static BOOL dat_hplmn_country (const UBYTE *mcc)
+{
+  GET_INSTANCE_DATA;
+  SHORT i;
+  UBYTE mcc_digit;
+
+  TRACE_FUNCTION ("dat_hplmn_country()");
+
+  /*
+   * Only if an IMSI is available
+   */
+  if (rr_data->ms_data.imsi_available)
+  {
+/*    EM_HPLMN_SEARCH_STARTED; - Not supported*/
+    for (i = 0; i < SIZE_MCC; i++)
+    {
+      
+      if((rr_data->ms_data.ahplmn.v_plmn EQ V_PLMN_PRES) AND
+         (rr_data->ms_data.req_mm_service EQ FUNC_PLMN_SRCH))
+      {
+        /*
+         * If AHPLMN is available
+         * do not compare the mcc from IMSI for the HPLMN
+         * use the MM req HPLMN
+         */
+        mcc_digit = rr_data->ms_data.ahplmn.mcc[i];
+      }      
+      else
+      {
+        mcc_digit = rr_data->ms_data.imsi.ident_dig[i];
+      }
+
+      /*
+       * if one of the three first digits of the IMSI is unequal to
+       * the mobile country code, it is not the HPLMN country.
+       */
+      if (mcc[i] NEQ mcc_digit)
+      {
+        return FALSE;
+      }
+    }
+    
+    EM_HPLMN_SEARCH_PASSED;
+    
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_imsi_mod_1000          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Calculate IMSI modulo 1000. That means take the last three
+            digits of the IMSI. The length of the IMSI (and so the number
+            of digits overall) is variable.
+
+            This value is needed for calculation of the paging group.
+
+*/
+
+static SHORT dat_imsi_mod_1000 (void)
+{
+  GET_INSTANCE_DATA;
+  SHORT i      = 0;
+  SHORT ret    = 0;
+  int   n;
+
+  TRACE_FUNCTION ("dat_imsi_mod_1000()");
+
+  while (rr_data->ms_data.imsi.ident_dig[i] < 0x0A)
+    i++;
+
+  if (i)
+  {
+    for (n = MAXIMUM (i-3, 0); n <= MAXIMUM (i-1, 0); n++)
+    {
+      ret = ret * 10 + rr_data->ms_data.imsi.ident_dig[n];
+    }
+  }
+  return ret;
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_no_of_paging_blocks    |
++--------------------------------------------------------------------+
+
+  PURPOSE : The function calculates the number of paging blocks.
+
+            For 51-Multiframe the following condition exists:
+
+            A non-combined CCCH configuration has 9 CCCH Blocks.
+            A combined CCCH configuration has 3 CCCH Blocks.
+
+            From this n CCCH Blocks BS_AG_BLKS_RES blocks are reserved
+            for AGCH (access grant channels for immediate assignment).
+            The rest is reserved for PCH (Paging Channel).
+
+            This number must be multiplied by the BS_PA_MFRMS parameter
+            (internally stored is the air-interface coding, add 2 for
+            the real value).
+
+            The BS_PA_MFRMS parameter defines the number of 51-Multiframes
+            until the paging blocks are repeated.
+
+*/
+
+static SHORT dat_no_of_paging_blocks (UBYTE     index)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_no_of_paging_blocks()");
+
+  /* in according to GSM 4.08 section 10.5.2.11, table 10.5.33 */
+  if (rr_data->nc_data[index].control_descr.ccch_conf EQ COMB_CCCH_COMB)
+  {
+    /*
+     * combined CCCH,
+     *
+     * number of paging blocks = (3 - BS_AG_BLKS_RES) * BS_PA_MFRMS
+     *
+     * Maximum function only for security reasons, BCCH coding range is 0..7,
+     * but allowed is only 0..2.
+     */
+    return ((att_max (1, (UBYTE)(3 - rr_data->nc_data[index].control_descr.
+                                                bs_ag_blks_res))) *
+            ((UBYTE)(2 + rr_data->nc_data[index].control_descr.bs_pa_mfrms)));
+  }
+  else
+  {
+    /*
+     * non-combined CCCH,
+     *
+     * number of paging blocks = (9 - BS_AG_BLKS_RES) * BS_PA_MFRMS
+     */
+    return ((9 - rr_data->nc_data[index].control_descr.bs_ag_blks_res) *
+            (2 + rr_data->nc_data[index].control_descr.bs_pa_mfrms));
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_owner_of_auth_0_to_9   |
++--------------------------------------------------------------------+
+
+  PURPOSE : It is checked whether the MS is owner of at least one
+            of the normal classes 0 to 9. The coding on the SIM card
+            is in opposite to the coding on the BCCH.
+
+*/
+
+static BOOL dat_owner_of_auth_0_to_9 (void)
+{
+  GET_INSTANCE_DATA;
+  BOOL  result            = FALSE;
+
+  /*
+   * get bits 0 to 9 from SIM card and BCCH
+   */
+  USHORT ms_classes = rr_data->ms_data.access_classes & 0x3FF;
+  USHORT plmn_classes = rr_data->nc_data[SC_INDEX].rach.ac & 0x3FF;
+
+  TRACE_FUNCTION ("dat_owner_of_auth_0_to_9()");
+
+  /*
+   * check only if IMSI is available
+   * else no valid classes of the SIM card available
+   */
+  if (rr_data->ms_data.imsi_available)
+  {
+    /*
+     * check classes
+     */
+    if ((ms_classes & (~plmn_classes)) NEQ 0)
+      result = TRUE;
+  }
+  return result;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_owner_of_auth_11_to_15 |
++--------------------------------------------------------------------+
+
+PURPOSE : It is checked whether the MS is owner of at least one
+          of the normal classes 11 to 15. The coding on the SIM card
+          is in opposite to the coding on the BCCH.
+
+*/
+
+static BOOL dat_owner_of_auth_11_to_15 (void)
+{
+  GET_INSTANCE_DATA;
+  BOOL  result            = FALSE;
+
+  /*
+   * get bits 11 to 15 from the SIM card and the BCCH.
+   */
+  USHORT ms_classes   = rr_data->ms_data.access_classes & 0xF800;
+  USHORT plmn_classes = rr_data->nc_data[SC_INDEX].rach.ac & 0xF800;
+
+  TRACE_FUNCTION ("dat_owner_of_auth_11_to_15()");
+
+  /*
+   * check only if IMSI is available
+   * else no valid classes of the SIM card available
+   */
+  if (rr_data->ms_data.imsi_available)
+  {
+    if (! dat_hplmn (rr_data->nc_data[SC_INDEX].lai.mcc, 
+                     rr_data->nc_data[SC_INDEX].lai.mnc))
+    {
+     /*
+      * ignore bit 11 and 15 if not in the HPLMN
+      */
+        ms_classes   = ms_classes & 0x7000;
+        plmn_classes = plmn_classes & 0x7000;
+    }
+
+    if (! dat_hplmn_country (rr_data->nc_data[SC_INDEX].lai.mcc))
+    {
+     /*
+      * ignore bit 12 to 14 if not in the HPLMN country
+      */
+        ms_classes   = ms_classes & 0x8F00;
+        plmn_classes = plmn_classes & 0x8F00;
+    }
+
+     /*
+      * check classes
+      */
+    if ((ms_classes & (~plmn_classes)) NEQ 0)
+      result = TRUE;
+  }
+
+  return result;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_random                 |
++--------------------------------------------------------------------+
+
+  PURPOSE : The function calculates a random value in the range 0..n-1.
+            The algorithm uses the system time as a base for the random
+            value calculation.
+
+*/
+
+GLOBAL USHORT dat_random (USHORT n)
+{
+  GET_INSTANCE_DATA;
+  T_TIME time_val;
+
+   static USHORT random_value = 0;
+
+  TRACE_FUNCTION ("dat_random()");
+
+  /*
+   * for module testing the random component can be switched off
+   */
+  if (rr_data->dyn_config.no_sys_time)
+    time_val = 0;
+  else
+    vsi_t_time (VSI_CALLER &time_val);
+
+  /*
+   * increment the base of the calculation by the system time.
+   */
+  random_value += (USHORT) time_val;
+
+  /*
+   * calculate the value in the range 0...n.1
+   */
+  return (random_value % n);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_release_connection     |
++--------------------------------------------------------------------+
+
+  PURPOSE : The function is called after receiving MPH_STOP_DEDICATED_CNF
+            from L1 following disconnection of L2 connection.
+
+*/
+
+GLOBAL void dat_release_connection (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_release_connection()");
+
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_IMM_ASS:
+      /* 
+       * Layer 2 disconnection is initiated by MM through RR_ABORT_REQ 
+       */
+      if(rr_data->rel_cause EQ RRCS_MM_ABORTED)
+      {
+        dat_rr_release_ind(RRCS_MM_ABORTED, SAPI_0);
+      }
+      break;
+
+    case DAT_IMM_ASS_1:
+      /* 
+       * Layer 2 disconnection is initiated by MM through RR_ABORT_REQ 
+       */
+      if(rr_data->rel_cause EQ RRCS_MM_ABORTED)
+      {
+        dat_rr_release_ind(RRCS_MM_ABORTED, SAPI_0);
+        break;
+      }
+      /* 
+       *DL establishment failure during immediate assignment
+       */
+      switch (rr_data->ms_data.establish_cause)
+      {
+#ifdef GPRS
+        case ESTCS_GPRS_PAGING:
+          dat_stop_dcch_ind ((UBYTE)rr_data->dcch_stop_cause);
+          break;
+        case ESTCS_PAGING:
+          if(!rr_data->repeat_est)
+            dat_rr_release_ind(rr_data->rel_cause, SAPI_0);
+#else
+        case ESTCS_PAGING:
+#endif
+          break;
+        default:
+          dat_rr_release_ind(rr_data->rel_cause, SAPI_0);
+          break;
+      }
+      break;
+
+    default:
+      dat_rr_release_ind (rr_data->rel_cause, SAPI_0);
+      break;
+  }
+
+  /*
+   * clear state of data transfer process and start
+   * cell reselection to come back to idle mode.
+   * Inform GRR, and wait for CR_RSP 
+   */
+  att_leave_dedicated();
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_send_random_bursts     |
++--------------------------------------------------------------------+
+
+  PURPOSE : The function configures layer 1 to send 2 to 8 random
+            bursts during connection establishment
+
+*/
+
+/*
+ * conversion of the air-interface coding (0..3) for the
+ * number of random bursts to be send
+ */
+static const UBYTE max_attempt[MAX_RACH_RETRANS_VAL] = { 2, 3, 5, MAX_RACH_REQ};
+
+static void dat_send_random_bursts (void)
+{
+  GET_INSTANCE_DATA;
+  UBYTE i;
+  UBYTE background;
+  UBYTE bits;
+
+  PALLOC (mph_random_access_req, MPH_RANDOM_ACCESS_REQ);
+
+  TRACE_FUNCTION ("dat_send_random_bursts()");
+
+  /*
+   * calculate the background and the number of bits for the
+   * random part depending on the establishment cause.
+   */
+  dat_get_background_and_bits (&background, &bits);
+  TRACE_EVENT("reset rej_rec");
+  rr_data->imm_ass_rej_rec = FALSE;
+  /*
+   * initialize the primitive and parameter for calculation
+   */
+  rr_data->ms_data.access_counter  = 0;
+  TRACE_ASSERT( rr_data->nc_data[SC_INDEX].rach.max_retrans < 
+                                     MAX_RACH_RETRANS_VAL );
+  rr_data->ms_data.max_attempt     = max_attempt[rr_data->nc_data
+                                     [SC_INDEX].rach.max_retrans];
+  memset (&mph_random_access_req->send_mode, 0, sizeof (T_send_mode));
+  mph_random_access_req->send_mode.no = rr_data->ms_data.max_attempt;
+
+  /*
+   * for all random bursts
+   */
+  TRACE_ASSERT( rr_data->ms_data.max_attempt <= MAX_RACH_REQ );
+  for (i = 0; i < rr_data->ms_data.max_attempt; i++)
+  {
+    /*
+     * calculate time until the random burst must be send
+     */
+    mph_random_access_req->send_mode.delta[i] = dat_get_delta (i);
+
+    /*
+     * calculate the random burst content and store it for
+     * later comparision with the incoming immediate assignment
+     * messages.
+     */
+    mph_random_access_req->send_mode.rach[i] = rr_data->used_channel_ref[i] =
+        dat_get_burst (background, bits);
+    /*
+    TRACE_EVENT_P3 ("RA %u: ref=0x%02x delta=%u",
+      i, rr_data->used_channel_ref[i],
+      mph_random_access_req->send_mode.delta[i]);
+    */
+  }
+
+  /*
+   * configure layer 1.
+   */
+  PSENDX (PL, mph_random_access_req);
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_set_last_used_channel  |
++--------------------------------------------------------------------+
+
+  PURPOSE : The last used channel during connection must be stored
+            for the case of call re-establishment.
+
+*/
+
+GLOBAL void dat_set_last_used_channel (T_chan_desc *chan_desc)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_set_last_used_channel()");
+
+  /*
+   * depending on the air-interface coding for the channel type
+   */
+  switch (chan_desc->chan_type)
+  {
+    case CH_TCH_F:
+      /*
+       * Traffic channel full rate
+       */
+      rr_data->ms_data.last_used_channel = TCHFCH;
+      break;
+
+    case CH_TCH_H_1:
+    case CH_TCH_H_2:
+      /*
+       * Traffic channel half rate
+       */
+      rr_data->ms_data.last_used_channel = TCHHCH;
+      break;
+
+    default:
+      /*
+       * SDCCH
+       */
+      rr_data->ms_data.last_used_channel = SDCCHCH;
+      break;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_start_immediate_assign |
++--------------------------------------------------------------------+
+
+  PURPOSE : start of the immediate assignment procedure after getting
+            a RR_ESTABLISH_REQ from MM for a mobile originated connection
+            or a MPH_PAGING_IND from layer 1 for a mobile terminated
+            connection.
+
+*/
+
+GLOBAL void dat_start_immediate_assign (USHORT    cause)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_start_immediate_assign()");
+
+  /*
+   * synchronize attachment process to connection establishment state
+   */
+  att_dat_con_est ();
+
+  /*
+   * initialize parameters for random access procedure
+   */
+  rr_data->ms_data.index             = dat_random (32);
+  rr_data->ms_data.establish_cause   = cause;
+  rr_data->ms_data.access_counter    = 0;
+  rr_data->ms_data.all_conf_received = FALSE;
+
+  /*
+   * if connection is too short to get one measurement report from layer 1,
+   * initialize the structure with the previous idle value
+   */
+  rr_data->ms_data.measurement_report.rx_lev_full = rr_data->nc_data[SC_INDEX].rxlev;
+
+  TRACE_EVENT_P1 ("imm ass SC=[%u]",rr_data->nc_data[SC_INDEX].arfcn);
+
+  /*
+   * send random bursts and wait for immediate assignment
+   */
+  dat_send_random_bursts ();
+  SET_STATE (STATE_DAT, DAT_IMM_ASS);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_start_sabm             |
++--------------------------------------------------------------------+
+
+  PURPOSE : After successful immediate assignment procedure the layer 1
+            is configured on a dedicated control channel (SDCCH or FACCH).
+            Now the layer 2 connection must be established. This is done
+            by this function.
+
+            Layer 2 sends a Paging response in case of mobile terminated
+            connection piggy-backed on the SABM.
+
+            In case of mobile terminated connection the piggy-backed layer 3
+            message is coming from MM.
+
+*/
+
+GLOBAL void dat_start_sabm (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_start_sabm()");
+
+  if (rr_data->ms_data.establish_cause EQ ESTCS_PAGING
+#ifdef GPRS
+      OR rr_data->ms_data.establish_cause EQ ESTCS_GPRS_PAGING
+#endif
+     )
+  {
+    MCAST (pag_res, U_PAG_RES);
+    PALLOC_MSG (establish_req, DL_ESTABLISH_REQ, U_PAG_RES);
+
+    dat_code_prr_channel (&establish_req->ch_type,
+                          &establish_req->sapi,
+                          rr_data->sc_data.chan_desc.chan_type);
+    /*
+     * if it is a mobile terminated connection,
+     * fill the C-Structure for a PAGING RESPONSE message.
+     */
+    pag_res->msg_type               = U_PAG_RES;
+    pag_res->ciph_key_num.key_seq   = rr_data->ms_data.cksn;
+    pag_res->mob_class_2            = rr_data->ms_data.classmark2;
+    pag_res->mob_class_2.rf_pow_cap = att_get_power ();
+
+    /*
+     * fill mobile identity and send it to layer 2
+     */
+    dat_fill_mobile_identity (ESTCS_PAGING, &pag_res->mob_ident);
+    for_dat_est_req_content  (establish_req);
+  }
+  else
+  {
+    /*
+     * mobile originated connection. set sdu with message from MM
+     * and send it to layer 2.
+     */
+    PALLOC_SDU (establish_req, DL_ESTABLISH_REQ, ((MAX_L2_FRAME_SIZE * BITS_PER_BYTE) - ENCODE_OFFSET));
+
+    dat_code_prr_channel (&establish_req->ch_type,
+                          &establish_req->sapi,
+                          rr_data->sc_data.chan_desc.chan_type);
+
+    /*lint -e419 (Warning -- Apparent data overrun for function memcpy exceeds argument 1)*/
+    establish_req->sdu.o_buf = rr_data->ms_data.l3msg.offset;
+    establish_req->sdu.l_buf = rr_data->ms_data.l3msg.length; 
+    memcpy (establish_req->sdu.buf, rr_data->ms_data.l3msg.buffer, MAX_L2_FRAME_SIZE);
+    /*lint +e419 (Warning -- Apparent data overrun for function memcpy exceeds argument 1)*/
+    for_dat_est_req_not_coding (establish_req);
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_test_sim_available     |
++--------------------------------------------------------------------+
+
+  PURPOSE : The function checks whether a test SIM is available or not.
+
+*/
+
+GLOBAL BOOL dat_test_sim_available (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_test_sim_available()");
+
+#if defined (_SIMULATION_)
+  /*
+   * some traces for debugging.
+   */
+  if (rr_data->ms_data.operation_mode & 0x80)
+  {
+      TRACE_FUNCTION ("Test SIM available");
+  }
+  else
+  {
+      TRACE_FUNCTION ("No Test SIM available");
+  }
+#endif
+
+  return ((rr_data->ms_data.operation_mode >> SHIFT_FOR_SIM_TYPE) & 1);
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_check_sim_available    |
++--------------------------------------------------------------------+
+
+  PURPOSE : The function checks whether the SIM is available or not.
+
+*/
+
+GLOBAL BOOL dat_check_sim_available (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_check_sim_available()");
+
+  return ((rr_data->ms_data.operation_mode >> SHIFT_FOR_SIM_INSERTED) & 1);
+}
+
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
+| STATE   : code                ROUTINE : dat_vsd_bit_set            |
++--------------------------------------------------------------------+
+
+  PURPOSE : To set the send state variable V(S) and the
+            corresponding bit for SAPI 0 messages on FACCH or SDCCH.
+            The following possibilities are available:
+
+            SET_ONLY:      V(S) in incremented and the message bit is set
+            RESET_ONLY:    V(S) is initialized and the message bit is not set
+            SET_AND_RESET: V(S) is initialized and the message bit is set.
+
+*/
+
+GLOBAL void dat_vsd_bit_set (T_L3_SDU  *m_buf,
+                            UBYTE     action)
+{
+  static UBYTE         vsd = 0;   /* Send state variable V(S)                    */
+         UBYTE          pd;       /* protocol discriminator of the message       */
+         UBYTE        * msp;      /* pointer to message type for setting the bit */
+#ifdef REL99
+         UBYTE         mscr = 0;     /* variable to hold msc release version*/
+#endif
+  TRACE_FUNCTION ("dat_vsd_bit_set()");
+
+  /*
+   * VSD shall be initialized
+   */
+  if (action NEQ SET_ONLY)
+    vsd = 0;
+
+  /*
+   * message bit shall be set
+   */
+  if (action NEQ RESET_ONLY)
+  {
+    /*
+     * calculate message type pointer and protocol discriminator
+     */
+    TRACE_ASSERT( (m_buf->offset >> 3) < L3_SDU_BUF_SIZE );
+    msp = &m_buf->buffer[m_buf->offset >> 3];
+    pd  = *msp++ & 0x0F;
+#ifdef REL99
+    /*
+     * Get MSCR of the serving MSC
+     */
+    get_msc_release_version(&mscr);
+    TRACE_EVENT_P1("mscr (MSC release) version : 0x%X", mscr);
+#endif
+    switch (pd)
+    {
+      case PD_SMS:
+        /*
+         * SMS on SDCCH is a SAPI 3 message and shall not be set.
+         */
+        break;
+      case PD_CC:
+      case PD_SS:
+      case PD_MM:
+#ifdef REL99
+        if (mscr EQ MSCR_99)
+        {           
+          /* for MSC release R99 or above modulo 4 will be done.
+           * SAPI 0 message: set bit 7th and 8th of MSG Type IE 
+           * and increment V(S) modulo 4.
+           */
+          *msp |= (vsd++ << 6);
+          vsd   = vsd & 0x03;
+        }
+        else
+#endif
+        {
+        /* for MSC release R98 or old modulo 2 will be done.
+         * SAPI 0 message: set bit if vsd is 1, else no effect
+         * and increment V(S) modulo 2.
+         */
+        *msp |= (vsd++ << 6);
+        vsd &= 1;
+    }
+  }
+}
+}
+
+/*
++---------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)  MODULE  : RR_DAT                           |
+| STATE   : code           ROUTINE : dat_begin_start_immediate_assign |
++---------------------------------------------------------------------+
+
+  PURPOSE : initiate immediate assignment procedure by sending
+            channel request
+
+*/
+GLOBAL void dat_begin_start_immediate_assign (UBYTE id_type, UBYTE chan_need)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_begin_start_immediate_assign()");
+
+  rr_data->page_identity_type = id_type;
+  rr_data->ms_data.channel_needed     = chan_need;
+  dat_vsd_bit_set (&rr_data->ms_data.l3msg, RESET_ONLY);
+  rr_data->sc_data.first_attempt = TRUE;
+  rr_data->repeat_est    = FALSE;
+  dat_start_immediate_assign (ESTCS_PAGING);
+}
+
+/*
++---------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)  MODULE  : RR_DAT                           |
+| STATE   : code           ROUTINE : dat_rr_release_ind               |
++---------------------------------------------------------------------+
+
+  PURPOSE : send RR_RELEASE_IND to MM
+
+*/
+GLOBAL void dat_rr_release_ind (USHORT relcs, UBYTE sapi)
+{
+    PALLOC (rr_release_ind, RR_RELEASE_IND);
+
+    rr_release_ind->cause = relcs;
+    rr_release_ind->sapi  = sapi;
+#ifdef GPRS
+    dat_set_gprs_resump(rr_release_ind);
+#endif
+
+    PSENDX (MM, rr_release_ind);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : dat_send_release_ind       |
++--------------------------------------------------------------------+
+
+  PURPOSE : Send RR_REELASE_IND to MM during the Access Procedure
+
+*/
+
+GLOBAL void dat_send_release_ind (USHORT cause)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("dat_send_release_ind()");
+
+  switch (rr_data->ms_data.establish_cause)
+  {
+#ifdef GPRS
+    case ESTCS_GPRS_1P:
+    case ESTCS_GPRS_SB:
+    case ESTCS_GPRS_PAGING:
+      SET_STATE(STATE_GPRS, GPRS_PIM_BCCH);
+      break;
+    case ESTCS_PAGING:
+      dat_rr_release_ind(RRCS_INT_NOT_PRESENT, SAPI_0);
+      /*
+       *   After sending a release_ind RR shall consider that GRR leaves SUSPENDED state
+       */
+      if(GPRS_SUSPENDED_BCCH EQ GET_STATE(STATE_GPRS))
+      {
+        SET_STATE(STATE_GPRS,GPRS_PIM_BCCH);
+      }
+      else if(GPRS_SUSPENDED_PBCCH EQ GET_STATE(STATE_GPRS))
+      {
+        SET_STATE(STATE_GPRS,GPRS_PIM_PBCCH);
+      }
+#else
+    case ESTCS_PAGING:
+#endif
+      break;
+
+    default:
+#ifdef GPRS
+      /*
+       *   After sending a release_ind RR shall consider that GRR leaves SUSPENDED state
+       */
+      if(GPRS_SUSPENDED_BCCH EQ GET_STATE(STATE_GPRS))
+      {
+        SET_STATE(STATE_GPRS,GPRS_PIM_BCCH);
+      }
+      else if(GPRS_SUSPENDED_PBCCH EQ GET_STATE(STATE_GPRS))
+      {
+        SET_STATE(STATE_GPRS,GPRS_PIM_PBCCH);
+      }
+#endif
+      if ( cause EQ RRCS_RND_ACC_FAIL )
+      {
+        if (! IS_TIMER_ACTIVE (T3122))
+        {
+          dat_rr_release_ind(RRCS_RND_ACC_FAIL, SAPI_0);
+        }
+        else
+        {
+          dat_rr_release_ind(RRCS_RND_ACC_DELAY, SAPI_0);
+        }
+      }
+      else
+      {
+        dat_rr_release_ind(cause, SAPI_0);
+      } 
+      break;
+  }
+}
+
+/*
++---------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)  MODULE  : RR_DAT                           |
+| STATE   : code           ROUTINE : dat_send_assign_fail_msg         |
++---------------------------------------------------------------------+
+
+  PURPOSE : send ASSIGNMENT FAILURE to network.
+
+*/
+void dat_send_assign_fail_msg(UBYTE cause)
+{
+  GET_INSTANCE_DATA;
+  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 = cause;
+  dat_code_prr_channel (&dl_reconnect_req->ch_type,
+                        &dl_reconnect_req->sapi,
+                        rr_data->sc_data.chan_desc.chan_type);
+
+  /*
+   * start reconnection in layer 2.
+   */
+  for_dat_reconnect_req (dl_reconnect_req);
+}
+
+/*
++---------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)  MODULE  : RR_DAT                           |
+| STATE   : code           ROUTINE : dat_send_rr_status_msg           |
++---------------------------------------------------------------------+
+
+  PURPOSE : send RR STATUS to network
+
+*/
+void dat_send_rr_status_msg(UBYTE cause)
+{
+  GET_INSTANCE_DATA;
+
+  MCAST (rr_status, B_RR_STATUS);
+  PALLOC_MSG (dl_data_req, DL_DATA_REQ, B_RR_STATUS);
+
+  /*
+   * set channel type and SAPI
+   */
+  dat_code_prr_channel (&dl_data_req->ch_type,
+                        &dl_data_req->sapi,
+                        rr_data->sc_data.chan_desc.chan_type);
+
+  rr_status->msg_type = B_RR_STATUS;
+  rr_status->rr_cause = cause;
+
+  EM_RR_STATUS_SEND;
+
+  for_dat_data_req (dl_data_req);
+}
+
+/*
++---------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)  MODULE  : RR_DAT                           |
+| STATE   : code           ROUTINE : dat_send_handov_fail_msg         |
++---------------------------------------------------------------------+
+
+  PURPOSE : send HANDOVER FAILURE to network
+
+*/
+void dat_send_handov_fail_msg(UBYTE cause)
+{
+  GET_INSTANCE_DATA;
+  MCAST (handov_fail, U_HANDOV_FAIL);
+  PALLOC_MSG (dl_reconnect_req, DL_RECONNECT_REQ, U_HANDOV_FAIL);
+
+  /*
+   * set channel type and sapi for the reconnection.
+   */
+  dat_code_prr_channel (&dl_reconnect_req->ch_type,
+                        &dl_reconnect_req->sapi,
+                        rr_data->sc_data.chan_desc.chan_type);
+
+  handov_fail->rr_cause = cause;
+  handov_fail->msg_type = U_HANDOV_FAIL;
+
+  /*
+   * reconnect layer 2 link.
+   */
+  for_dat_reconnect_req (dl_reconnect_req);
+}
+
+#if defined (REL99) && defined (TI_PS_FF_EMR)
+/*
++---------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)  MODULE  : RR_DAT                           |
+| STATE   : code           ROUTINE : dat_update_emr_data         |
++---------------------------------------------------------------------+
+
+  PURPOSE : Updates the enhanced measurement parameters, other than
+  BSIC and reporting priority.
+
+*/
+GLOBAL void dat_update_emr_rep_para(T_emp *p_em, T_enh_para_struct *p_enh)
+{  
+  p_enh->scale_order = p_em->scale_ord;
+  if (p_em->v_serv_band_rep EQ TRUE)
+    p_enh->servingband_rep = p_em->serv_band_rep;
+  if (p_em->v_mr EQ TRUE )
+    p_enh->multiband_rep = p_em->mr;
+    
+  /* Update reporting thresholds and reporting offsets*/
+  if (p_em->v_report_900 EQ TRUE)
+  {
+    p_enh->enh_rep_data[0].rep_offset = p_em->report_900.rep_offset_900;
+    p_enh->enh_rep_data[0].rep_offset = p_em->report_900.th_rep_900;
+  }
+  if (p_em->v_report_1800 EQ TRUE)
+  {
+    p_enh->enh_rep_data[1].rep_offset = p_em->report_1800.rep_offset_1800;
+    p_enh->enh_rep_data[1].rep_offset = p_em->report_1800.th_rep_1800;
+  }
+  if (p_em->v_report_400 EQ TRUE)
+  {
+    p_enh->enh_rep_data[2].rep_offset = p_em->report_400.rep_offset_400;
+    p_enh->enh_rep_data[2].rep_offset = p_em->report_400.th_rep_400;
+  }
+  if (p_em->v_report_1900 EQ TRUE)
+  {
+    p_enh->enh_rep_data[3].rep_offset = p_em->report_1900.rep_offset_1900;
+    p_enh->enh_rep_data[3].rep_offset = p_em->report_1900.th_rep_1900;
+  }
+  if (p_em->v_report_850 EQ TRUE)
+  {
+    p_enh->enh_rep_data[4].rep_offset = p_em->report_850.rep_offset_850;
+    p_enh->enh_rep_data[4].rep_offset = p_em->report_850.th_rep_850;
+  }
+  return;
+}
+
+/*
++---------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)  MODULE  : RR_DAT                           |
+| STATE   : code           ROUTINE : dat_code_enh_measure_report         |
++---------------------------------------------------------------------+
+
+  PURPOSE : Forms enhanced measurement report and sends it to DL as a
+  message with short PD.
+*/
+GLOBAL void dat_code_enh_measure_report(T_MPH_MEASUREMENT_IND *report)
+{
+  GET_INSTANCE_DATA;
+  UBYTE     size_avail = MSG_SIZE_EMR - MAND_SIZE_EMR;
+  MCAST (meas_emr, U_EMR);
+  PALLOC_MSG (dl_data, DL_SHORT_UNITDATA_REQ, U_EMR);
+  
+  TRACE_FUNCTION ("dat_code_enh_measure_report()");
+  memset (&dl_data->sdu.buf[0], 0, dl_data->sdu.o_buf / BITS_PER_BYTE); 
+  /* initialize C-structure for the Uplink message */
+  memset (meas_emr, 0, sizeof (T_U_EMR));
+  meas_emr->msg_type = U_EMR;
+  meas_emr->sl2h     = SL2H_0;
+
+  if (report->valid EQ TRUE)
+  {
+    T_enh_para_struct *src = &rr_data->sc_data.emr_data_current.enh_para;       
+    
+    /* Fill the non-measurement paramaters */    
+    meas_emr->ba_ind = rr_data->sc_data.ba_index;
+    meas_emr->scale = report->scale_used;
+    /* Now fill serving cell data */
+    if (report->rxlev_val NEQ 0)
+    {
+      meas_emr->v_scdata = TRUE;
+      meas_emr->scdata.rxlev = report->rxlev_val;
+      meas_emr->scdata.rxqual_full = report->rx_qual_full;
+      meas_emr->scdata.mean_bep = report->mean_bep;
+      meas_emr->scdata.cv_bep = report->cv_bep;
+      meas_emr->scdata.nr_rcvd_bl = report->nbr_rcvd_blks;
+      meas_emr->scdata.dtx_used = report->dtx;
+      size_avail -= SC_INFO_SIZE_EMR; 
+    }  
+    
+    /* Fill neighbour cell measurements */
+    if (report->ncells.no_of_ncells > 0)
+    {
+      UBYTE         i;
+      UBYTE         j;
+      UBYTE         highest_index = 0;
+      UBYTE         index_0 = 1;/*To decrement size by 1 when index is 0*/
+      ULONG         bit_map=0;
+      
+      
+      meas_emr->em_rep.c_rep_q_arr  = meas_emr->c_i_bsic_i = 0;
+      for (i =0; i < report->ncells.no_of_ncells; i++ )
+      {
+        j = report->nc_index[i];
+        /*Decide whether it is a valid BSIC cell or not*/
+        if ( j NEQ NOT_PRESENT_8BIT )
+        {
+          /*This is an valid BSIC cell*/
+          /*Check the priority of the cell*/
+          if ( (src->rep_rate EQ REDUCED_REP_RATE) AND 
+           (src->enh_cell_list[j].rep_priority EQ REP_PRIOR_NORM ))
+          {
+            /*Proceed further only if the cell has not been included-
+              in any report till now or if it's the time to include this
+              cell in the report*/
+            if ( (rr_data->sc_data.rep_count[j] NEQ rr_data->sc_data.emr_count ) AND
+                 (rr_data->sc_data.rep_count[j] NEQ NOT_PRESENT_8BIT ) )
+            {
+              bit_map |= (1<<i);
+              continue; /* Include this cell at the end only if size is available*/
+            }                 
+          }
+          meas_emr->em_rep.rep_q_arr[j].rep_q   = report->ncells.rx_lev[i];
+          
+          if ( j > highest_index ) 
+          {
+          /*When the place where the RXLEV has to be filled requires
+          additional bits in bit map, then we have to account for
+            these single bits and additional 6 bits for RXLEV*/
+            if (size_avail >= (j - highest_index)+6 + index_0 )
+            {
+            /*This means we require atleast j-highest_index+6 bits in bit map to 
+              include this rxlev*/
+              /* 6 bits for RXLEV itself*/                
+              size_avail = size_avail- (j-highest_index+6+index_0) ;
+              highest_index = j;
+              meas_emr->em_rep.c_rep_q_arr =  j+1; /*counter is index+1*/
+              index_0 = 0;  
+              meas_emr->em_rep.rep_q_arr[j].v_rep_q = TRUE;  
+              rr_data->sc_data.rep_count[j] = rr_data->sc_data.emr_count;
+            }             
+          }
+          else if (size_avail >= 6 + index_0)
+          {              
+            size_avail -= (6+index_0); /* size for bit map is already accounted for*/              
+            meas_emr->em_rep.c_rep_q_arr = highest_index +1;
+            index_0 = 0;   
+            meas_emr->em_rep.rep_q_arr[j].v_rep_q = TRUE;  
+            rr_data->sc_data.rep_count[j] = rr_data->sc_data.emr_count;
+          }
+        } /* if j NEQ NOT_PRESENT_8BIT  */
+        else
+        {
+          /*This is a Invalid BSIC cell*/
+          /*fill in invalid BSIC list since cell is not present in the neighbour cell
+          list. Here the index that needs to be filled is index of the ARFCN in BA(list)*/
+          if ( size_avail > NC_INVBSIC_EMR )
+          {            
+            meas_emr->i_bsic_i[meas_emr->c_i_bsic_i].ba_start_bsic = 
+              dat_get_ncell_pos (report->ncells.arfcn[i]);
+            meas_emr->i_bsic_i[meas_emr->c_i_bsic_i].bsic     = report->ncells.bsic[i] ;
+            meas_emr->i_bsic_i[meas_emr->c_i_bsic_i++].rxlev  = report->ncells.rx_lev[i];
+            size_avail -= NC_INVBSIC_EMR;            
+          }   
+        }
+        if (size_avail < 6) /*no more cells can be included*/
+          break;
+      } /* for 'i'*/    
+
+      /*All the low priority cells have to be filled in valid BSIC bmp reporting,
+       if still there's size available*/
+      i = 0;
+      while ( (bit_map NEQ 0) AND (size_avail >= 6) )
+      {
+        if ( ((bit_map >> i ) & (NOT_PRESENT_32BIT)) EQ TRUE )
+        {
+          j = report->nc_index[i];
+          meas_emr->em_rep.rep_q_arr[j].rep_q   = report->ncells.rx_lev[i];          
+          if ( j > highest_index ) 
+          {
+            /*When the place where the RXLEV has to be filled requires
+            additional bits in bit map, then we have to account for
+            these single bits and additional 6 bits for RXLEV*/
+            if (size_avail >= (j - highest_index)+6 + index_0 )
+            {
+            /*This means we require atleast j-highest_index+6 bits in bit map to 
+              include this rxlev*/
+              /* 6 bits for RXLEV itself*/                
+              size_avail = size_avail- (j-highest_index+6+index_0) ;
+              highest_index = j;
+              meas_emr->em_rep.c_rep_q_arr =  j+1; /*counter is index+1*/
+              index_0 = 0;  
+              meas_emr->em_rep.rep_q_arr[j].v_rep_q = TRUE;  
+              rr_data->sc_data.rep_count[j] = rr_data->sc_data.emr_count;
+            }             
+          }
+          else if (size_avail >= 6 + index_0)
+          {              
+            size_avail -= (6+index_0); /* size for bit map is already accounted for*/              
+            meas_emr->em_rep.c_rep_q_arr = highest_index +1;
+            index_0 = 0;   
+            meas_emr->em_rep.rep_q_arr[j].v_rep_q = TRUE;  
+            rr_data->sc_data.rep_count[j] = rr_data->sc_data.emr_count;
+          }
+          else
+            break;
+          bit_map = bit_map &  ( ~ ((ULONG)( 1 << i))); /*reset the corresponding bit in bit map*/
+        }
+      }/*while bit_map*/
+      if (meas_emr->em_rep.c_rep_q_arr > 0)
+        meas_emr->v_em_rep = TRUE;
+      if (meas_emr->c_i_bsic_i > 0)
+      {
+        meas_emr->v_i_bsic_i = TRUE;      
+        meas_emr->bsic_seen = report->bsic_seen;
+      }        
+    } /* if 'report->ncells.no_of_ncells'*/     
+    
+#if defined (REL99) && defined (TI_PS_FF_EMR)
+    /*Fill the report with '0's till the end of message or upto 96 cells  */    
+    while ( (size_avail > 0) AND (meas_emr->em_rep.c_rep_q_arr < 96 ) )
+    {
+      /* There are cells in GSM NC list for which bit map has to be set to '0' 
+         earlier memset takes care of this. we just need to set the counter appropriately*/
+      meas_emr->em_rep.c_rep_q_arr++;
+      size_avail--;
+    }
+#else
+    if ( meas_emr->em_rep.c_rep_q_arr < src->num_valid_cells )
+    {
+      /* There are cells in GSM NC list for which bit map has to be set to '0' 
+         earlier memset takes care of this. we just need to set the counter appropriately*/
+      meas_emr->em_rep.c_rep_q_arr = src->num_valid_cells;      
+    }
+    dl_data->ccd_assist = meas_emr->em_rep.nnc = meas_emr->em_rep.c_rep_q_arr; 
+#endif
+    rr_data->sc_data.emr_count = (rr_data->sc_data.emr_count +1) & 0x03; /*MOD4 addition*/    
+  }
+  else
+  {   
+    /*
+     * measurement report from layer 1 is invalid
+     */
+    TRACE_EVENT ("invalid meas_emr");  
+    /*A dummy msg with all options as FALSE will go in this case, to network.
+     may be useful to maintain periodicity*/
+  }
+  /* Send the message to DL */
+  
+  for_dat_spd_unitdata_req(dl_data);
+}
+#endif
+
+#if defined (TI_PS_FF_RTD) AND defined (REL99)
+/*
++---------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)  MODULE  : RR_DAT                           |
+| STATE   : code           ROUTINE : dat_update_rtd_data         |
++---------------------------------------------------------------------+
+
+  PURPOSE : Updates the real time difference parameters received on MEAS_INFO message.
+*/
+GLOBAL void dat_update_rtd_data(T_D_MEAS_INF *p_mi,T_rr_enh_para *p_temp)
+{
+T_rtdd *rtdd_struct= &p_mi->rtdd;
+dat_update_common_rtd_struct(rtdd_struct,p_temp);
+
+} /* end dat_update_rtd_data()*/
+
+
+/*
++---------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)  MODULE  : RR_DAT                           |
+| STATE   : code           ROUTINE : dat_update_common_rtd_struct     |
++---------------------------------------------------------------------+
+
+  PURPOSE : Common function called from for_store_rtd_data() to store 
+  rtd parameters received on si2 quater message and update the same on receiving 
+  meas_info message via function dat_update_rtd_data().
+*/
+
+GLOBAL void dat_update_common_rtd_struct(T_rtdd *rtdd,T_rr_enh_para *p_temp)
+{
+UBYTE     i,j,rtd_index,max_rtd_values;
+  
+  if(rtdd->v_rtdd6 EQ TRUE)
+  {
+    if(rtdd->rtdd6.v_ba_start_rtd EQ TRUE)
+      rtd_index = rtdd->rtdd6.ba_start_rtd;
+    else
+      rtd_index = RTD_DEFAULT_INDEX;
+    
+    if( rtd_index < MAX_NR_OF_NCELL)
+    {
+      p_temp->enh_para.enh_cell_list[rtd_index].v_rtd =  TRUE;
+      max_rtd_values = rtdd->rtdd6.rtds6.c_rtd6 > MAX_NUM_OF_RTD_VALUES ?
+                      MAX_NUM_OF_RTD_VALUES : rtdd->rtdd6.rtds6.c_rtd6;
+      for(i = 0;i < max_rtd_values;i++)
+        p_temp->enh_para.enh_cell_list[rtd_index].rtd[i] = rtdd->rtdd6.rtds6.rtd6[i];
+      p_temp->enh_para.enh_cell_list[rtd_index].c_rtd= max_rtd_values;
+    } /*if*/
+    
+    for(j = 0;j < rtdd->rtdd6.c_rtds6_add;j++)
+    {
+      rtd_index++;
+      if( rtd_index < MAX_NR_OF_NCELL)
+      {
+        p_temp->enh_para.enh_cell_list[rtd_index].v_rtd = TRUE;
+        max_rtd_values = rtdd->rtdd6.rtds6_add[j].c_rtd6 > MAX_NUM_OF_RTD_VALUES ?
+                           MAX_NUM_OF_RTD_VALUES : rtdd->rtdd6.rtds6_add[j].c_rtd6;
+        for(i = 0;i < max_rtd_values;i++)
+          p_temp->enh_para.enh_cell_list[rtd_index].rtd[i] = rtdd->rtdd6.rtds6_add[j].rtd6[i];
+        p_temp->enh_para.enh_cell_list[rtd_index].c_rtd= max_rtd_values;
+      } /*if*/
+    } /*for*/
+  } /*if*/
+  if(rtdd->v_rtdd12 EQ TRUE)
+  {
+    if(rtdd->rtdd12.v_ba_start_rtd EQ TRUE)
+      rtd_index = rtdd->rtdd12.ba_start_rtd;
+    else
+      rtd_index = RTD_DEFAULT_INDEX;
+    
+    if( rtd_index < MAX_NR_OF_NCELL)
+    {
+      p_temp->enh_para.enh_cell_list[rtd_index].v_rtd = TRUE;
+      max_rtd_values = rtdd->rtdd12.rtds12.c_rtd12 > MAX_NUM_OF_RTD_VALUES ?
+                        MAX_NUM_OF_RTD_VALUES: rtdd->rtdd12.rtds12.c_rtd12;
+      for(i = 0;i < max_rtd_values;i++)
+      {
+        p_temp->enh_para.enh_cell_list[rtd_index].rtd[i] =RTD_12BIT;
+        p_temp->enh_para.enh_cell_list[rtd_index].rtd[i] |= rtdd->rtdd12.rtds12.rtd12[i];
+      } /*for*/
+      p_temp->enh_para.enh_cell_list[rtd_index].c_rtd= max_rtd_values;
+    } /*if*/
+    for(j = 0;j < rtdd->rtdd12.c_rtds12_add;j++)
+    {
+      rtd_index++;
+      if(rtd_index < MAX_NR_OF_NCELL)
+      {
+        p_temp->enh_para.enh_cell_list[rtd_index].v_rtd = TRUE;
+        max_rtd_values = rtdd->rtdd12.rtds12_add[j].c_rtd12 > MAX_NUM_OF_RTD_VALUES ?
+                          MAX_NUM_OF_RTD_VALUES : rtdd->rtdd12.rtds12_add[j].c_rtd12;
+        for(i = 0;i < max_rtd_values;i++)
+        {
+          p_temp->enh_para.enh_cell_list[rtd_index].rtd[i] = RTD_12BIT;
+          p_temp->enh_para.enh_cell_list[rtd_index].rtd[i] |= rtdd->rtdd12.rtds12_add[j].rtd12[i];
+        } /*for*/
+        p_temp->enh_para.enh_cell_list[rtd_index].c_rtd= max_rtd_values;
+      } /*if*/
+    } /*for*/
+  } /*if*/
+} /* end of dat_update_common_rtd_struct() */
+
+
+#endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */
+
+#endif