view gsm-fw/g23m-gsm/rr/rr_datp.c @ 876:c9f353b5d70c

rvinterf/asyncshell/rxctl.c: buglet in the implementation of dis/enable commands
author Space Falcon <falcon@ivan.Harhan.ORG>
date Sat, 30 May 2015 07:50:05 +0000
parents 9924ad35640f
children
line wrap: on
line source

/*
+-----------------------------------------------------------------------------
|  Project :
|  Modul   :
+-----------------------------------------------------------------------------
|  Copyright 2002 Texas Instruments Berlin, AG
|                 All rights reserved.
|
|                 This file is confidential and a trade secret of Texas
|                 Instruments Berlin, AG
|                 The receipt of or possession of this file does not convey
|                 any rights to reproduce or disclose its contents or to
|                 manufacture, use, or sell anything it may describe, in
|                 whole, or in part, without the specific written consent of
|                 Texas Instruments Berlin, AG.
+-----------------------------------------------------------------------------
|  Purpose :  This Modul defines the functions for the data transfer
|             capability of the module Radio Resource.
+-----------------------------------------------------------------------------
*/

#ifndef RR_DATP_C
#define RR_DATP_C

#include "config.h"
#include "fixedconf.h"
#include "condat-features.h"

#define ENTITY_RR

/*==== INCLUDES ===================================================*/

#include <string.h>
#include <stdlib.h>
#include <stddef.h>     /* offsetof */
#include <stdio.h>      /* sprintf */
#include "typedefs.h"
#include "pcm.h"
#include "pconst.cdg"
#include "mconst.cdg"
#include "message.h"
#include "ccdapi.h"
#include "vsi.h"
#include "custom.h"
#include "gsm.h"
#include "prim.h"
#include "cnf_rr.h"
#include "tok.h"
#include "rr.h"
#include "rr_em.h"

/*==== EXPORT =====================================================*/
#if defined (REL99) && defined (TI_PS_FF_EMR)
#define MAX_MSTRUCT_CCD_RR MAXIMUM(MAX_MSTRUCT_LEN_RR_SHORT, MAX_MSTRUCT_LEN_RR)
GLOBAL UBYTE _decodedMsg [MAX_MSTRUCT_CCD_RR];
#else
GLOBAL UBYTE _decodedMsg [MAX_MSTRUCT_LEN_RR];
#endif


/*==== PRIVAT =====================================================*/

/*==== VARIABLES ==================================================*/

/*==== FUNCTIONS ==================================================*/

/*
 * -------------------------------------------------------------------
 * PRIMITIVE Processing functions
 * -------------------------------------------------------------------
 */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_init_rr_data           |
+--------------------------------------------------------------------+

  PURPOSE : Initialize the RR data for the module data transfer.

*/

GLOBAL void dat_init_rr_data (void)
{
  GET_INSTANCE_DATA;
  TRACE_FUNCTION ("dat_init_rr_data()");

  SET_STATE (STATE_DAT, DAT_NULL);
}


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_dl_establish_cnf       |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive DL_ESTABLISH_CNF received from DL.

*/
GLOBAL void dat_dl_establish_cnf (T_DL_ESTABLISH_CNF *dl_establish_cnf_orig)
{
  GET_INSTANCE_DATA;
  /*
   * sys infos during l2 establishment are
   * lost, inform layer 1 to send them again
   */
  PPASS(dl_establish_cnf_orig, dl_establish_cnf, DL_ESTABLISH_CNF);

  TRACE_FUNCTION ("dat_dl_establish_cnf()");
  rr_data->net_lost = FALSE;
  TRACE_EVENT_P1("rr_data->net_lost = %u", rr_data->net_lost);
  
  switch (GET_STATE (STATE_DAT))
  {
    case DAT_CHAN_ASS_1:
    case DAT_CHAN_ASS_2:
    case DAT_IMM_ASS_1:
      break;

    default :
      if (dl_establish_cnf->sapi EQ SAPI_0)
      {
        PALLOC (mph_sync_req, MPH_SYNC_REQ);
        mph_sync_req->cs = CS_CLEAN_SYS_INFO;
        PSENDX (PL, mph_sync_req);
      }
      break;
  }

  switch (GET_STATE (STATE_DAT))
  {
    case DAT_CHAN_ASS_1:
      /*
       * successfull establishment of new layer 2 connection
       * after channel assignment
       */

      EM_DL_ESTABLISH_CNF;

      PFREE (dl_establish_cnf);

      if (rr_data->sc_data.ch_mode NEQ
          rr_data->cr_data.ch_mode)
      {
        /*
         * a changed channel mode has been detected.
         * update channel description and channel mode
         * for the serving cell and inform MM about the
         * new channel mode.
         */
        memcpy (&rr_data->sc_data.chan_desc,
                &rr_data->cr_data.chan_desc,
                sizeof (T_chan_desc));
        rr_data->sc_data.ch_mode = rr_data->cr_data.ch_mode;
        dat_code_channel_mode_to_mm ();
      }

      if (rr_data->cr_data.ciph_on NEQ
          rr_data->sc_data.ciph_on)
      {
        /*
         * the ciphering has changed. Inform MM about the new
         * ciphering.
         */
        dat_code_ciphering_to_mm (rr_data->cr_data.ciph_on);
      }

      /*
       * copy cr data to sc data and go back to normal dedicated mode.
       */
      rr_data->sc_data.ciph_on  = rr_data->cr_data.ciph_on;
      rr_data->sc_data.algo     = rr_data->cr_data.algo;
      rr_data->sc_data.ch_mode  = rr_data->cr_data.ch_mode;
      rr_data->sc_data.cd.v_cell_chan_desc =
               rr_data->cr_data.cd.v_cell_chan_desc;
      memcpy (&rr_data->sc_data.cd.cell_chan_desc,
              &rr_data->cr_data.cd.cell_chan_desc,
              sizeof (T_LIST));
      memcpy (&rr_data->sc_data.chan_desc,
              &rr_data->cr_data.chan_desc,
              sizeof (T_chan_desc));
      memcpy (&rr_data->sc_data.amr_conf,
              &rr_data->cr_data.amr_conf,
              sizeof (T_multirate_conf));

      rr_data->nc_data[CR_INDEX].arfcn = NOT_PRESENT_16BIT;
      att_remove_multiple_channels ();
      SET_STATE (STATE_SAPI_3, SMS_IDLE);
      srv_use_stored_prim ();
      dat_set_last_used_channel (&rr_data->sc_data.chan_desc);
      att_dat_dedicated ();
      dat_emo_stop ( TRUE );
      SET_STATE (STATE_DAT, DAT_DEDICATED);
      rr_data->mode_after_dedi = MODE_CELL_RESELECTION;
      break;

    case DAT_CHAN_ASS_2:
      /*
       * successfull reconnection on old channel after failed
       * channel assignment
       *
       * update some parameters to go back to normal dedicated mode.
       */
      PFREE (dl_establish_cnf);
      srv_use_stored_prim ();
      SET_STATE (STATE_SAPI_3, SMS_IDLE);
      att_dat_dedicated ();
      rr_data->nc_data[CR_INDEX].arfcn = NOT_PRESENT_16BIT;
      SET_STATE (STATE_DAT, DAT_DEDICATED);

      rr_data->mode_after_dedi = MODE_CELL_RESELECTION;

      EM_ASS_FAILURE_RECONNECT_SUCCESS;

      break;

    case DAT_DEDICATED:
      /*
       * An establish confirm in normal dedicated mode is only
       * expected for short messages (SAPI 3)
       */
      if (dl_establish_cnf->sapi EQ SAPI_3)
      {
        SET_STATE (STATE_SAPI_3, SMS_ESTABLISHED);
        srv_use_stored_prim ();
      }
      PFREE (dl_establish_cnf);
      break;

    case DAT_HANDOVER_4:
      TRACE_EVENT ("DL_ESTABLISH_CNF");

      EM_L2_CONNECTION_ESTABLISHED;

      PFREE (dl_establish_cnf);

      /*
       * successfull establishment of new layer 2 connection
       * after handover
       */
      if (rr_data->sc_data.ch_mode NEQ
          rr_data->cr_data.ch_mode)
      {
        /*
         * a changed channel mode has been detected.
         * update channel description and channel mode
         * for the serving cell and inform MM about the
         * new channel mode.
         */
        memcpy (&rr_data->sc_data.chan_desc,
                &rr_data->cr_data.chan_desc,
                sizeof (T_chan_desc));
        rr_data->sc_data.ch_mode = rr_data->cr_data.ch_mode;
        dat_code_channel_mode_to_mm ();
      }

      if (rr_data->cr_data.ciph_on NEQ rr_data->sc_data.ciph_on)
      {
        /*
         * the ciphering has changed. Inform MM about the new
         * ciphering.
         */
        dat_code_ciphering_to_mm (rr_data->cr_data.ciph_on);
      }

      /*
       * copy cr data to sc data and go back to normal dedicated mode.
       */
      rr_data->sc_data.ciph_on  = rr_data->cr_data.ciph_on;
      rr_data->sc_data.algo     = rr_data->cr_data.algo;
      rr_data->sc_data.ch_mode  = rr_data->cr_data.ch_mode;
      rr_data->sc_data.cd.v_cell_chan_desc =
               rr_data->cr_data.cd.v_cell_chan_desc;
      memcpy (&rr_data->sc_data.cd.cell_chan_desc,
              &rr_data->cr_data.cd.cell_chan_desc,
              sizeof (T_LIST));
      memcpy (&rr_data->sc_data.chan_desc,
              &rr_data->cr_data.chan_desc,
              sizeof (T_chan_desc));
      memcpy (&rr_data->sc_data.amr_conf,
              &rr_data->cr_data.amr_conf,
              sizeof (T_multirate_conf));

      rr_data->nc_data[SC_INDEX].bsic = rr_data->nc_data[CR_INDEX].bsic;
      rr_data->nc_data[SC_INDEX].arfcn = rr_data->nc_data[CR_INDEX].arfcn;
      rr_data->nc_data[CR_INDEX].arfcn = NOT_PRESENT_16BIT;
      /*
       * after a handover we cannot come back directly to the
       * cell instead we have to do a normal cell reselection
       */
      rr_data->mode_after_dedi = MODE_CELL_RESELECTION;
      att_remove_multiple_channels ();
      SET_STATE (STATE_SAPI_3, SMS_IDLE);
      srv_use_stored_prim ();
      dat_set_last_used_channel (&rr_data->sc_data.chan_desc);
      att_dat_dedicated ();
      dat_emo_stop ( TRUE );
      SET_STATE (STATE_DAT, DAT_DEDICATED);
      break;

    case DAT_HANDOVER_5:
      TRACE_EVENT ("DL_ESTABLISH_CNF");
      /*
       * successfull reconnection on old channel after failed
       * handover
       *
       * update some parameters to go back to normal dedicated mode.
       */
      PFREE (dl_establish_cnf);
      srv_use_stored_prim ();
      SET_STATE (STATE_SAPI_3, SMS_IDLE);
      att_dat_dedicated ();
      rr_data->nc_data[CR_INDEX].arfcn = NOT_PRESENT_16BIT;
      SET_STATE (STATE_DAT, DAT_DEDICATED);

      rr_data->mode_after_dedi = MODE_CELL_RESELECTION;

      EM_HO_FAILURE_RECONNECT_SUCCESS;
      break;

    case DAT_IMM_ASS_1:
      /*
       * successfull establishment of a dedicated connection.
       * Depending on the originator of the connection MM
       * is informed.
       */
      EM_L2_CONNECTION_ESTABLISHED;

#ifdef GPRS
      if(! dat_check_packet_access())
      {
#endif
        if (rr_data->ms_data.establish_cause EQ ESTCS_PAGING)
        {
          PREUSE (dl_establish_cnf, rr_establish_ind, RR_ESTABLISH_IND);
          PSENDX (MM, rr_establish_ind);
        }
        else
        {
          PREUSE (dl_establish_cnf, rr_establish_cnf, RR_ESTABLISH_CNF);
          PSENDX (MM, rr_establish_cnf);
        }
#ifdef GPRS
      }
      else
      { /* packet access */
        PFREE (dl_establish_cnf);
      }
#endif

      /*
       * initialize some variables for the dedicated mode.
       */
      rr_data->dyn_config.fho                       = 0;
      rr_data->dyn_config.fca                       = 0;
      rr_data->tch_loop_subch            = NOT_PRESENT_8BIT;
      rr_data->sc_data.ciph_received     = FALSE;
      rr_data->rel_cause                 = RRCS_INT_NOT_PRESENT;
      rr_data->sc_data.ciph_on           = CIPH_OFF;
      att_copy_old_lai_rac(SC_INDEX);
#if 0
      memcpy (&rr_data->old_lai,
              &rr_data->nc_data[SC_INDEX].lai,
              sizeof (rr_data->old_lai));
      rr_data->old_cell_id               = rr_data->nc_data[SC_INDEX].cell_id;
#endif
      SET_STATE (STATE_SAPI_3, SMS_IDLE);
      att_dat_dedicated ();
      SET_STATE (STATE_DAT, DAT_DEDICATED);

      /*
       * Early classmark Sending is performed if the mobile supports it
       * and the network requests it.
       */

      if (rr_data->ms_data.classmark2.es_ind AND
          rr_data->nc_data[SC_INDEX].c2_par.ecsc)
      {
        /*
         * building of the Early Classmark Sending message
         */
        /* Implements RR Clone findings #15 */
        dat_class_chng_data_req();
      }

#ifdef GPRS
      dat_gprs_suspend_req ();
#endif

      EM_EARLY_CLASSMARK_SENDING;
      break;

#ifdef GPRS
    case DAT_PDCH_ASS_4:
      dat_rrgrr_reconnect_dcch_cnf (RECONN_OK);
      SET_STATE (STATE_DAT, DAT_DEDICATED);
      PFREE (dl_establish_cnf);
      break;

    case DAT_CCO_4:
      if ( rr_data->gprs_data.cco_need_reconnect_cnf )
      {
        dat_rrgrr_reconnect_dcch_cnf (RECONN_OK);
      }
      else
      {
        /*
         * GRR has received d_change_order message,
         * but the BCCH reading in the new cell failed.
         * The connection is resumed on the old channel
         * in dedicated mode.
         */

        PALLOC (rrgrr_sync_ind, RRGRR_SYNC_IND);
        rrgrr_sync_ind->sync_res  = SYNC_FAILED;
        PSENDX (GRR, rrgrr_sync_ind);
      }
      SET_STATE (STATE_DAT, DAT_DEDICATED);
      PFREE (dl_establish_cnf);
      break;
#endif

    default:
      PFREE (dl_establish_cnf);
      break;
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_dl_establish_ind       |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive DL_ESTABLISH_IND received from DL.
            This is only expected for short messages on SAPI 3 during
            a connection.

*/

GLOBAL void dat_dl_establish_ind (T_DL_ESTABLISH_IND *dl_establish_ind)
{
  GET_INSTANCE_DATA;

  TRACE_FUNCTION ("dat_dl_establish_ind()");

  switch (GET_STATE (STATE_DAT))
  {
    case DAT_DEDICATED:
      /*
       * if it indicates a mobile terminated connection establishment
       * for SAPI 3 in the layer 2, change the state in RR for SMS.
       * Answers from upper layer for SMS can be forwarded then
       * immediately.
       */
      if (dl_establish_ind->sapi EQ SAPI_3)
      {
        /*
         * set state for SMS if it is on SAPI 3
         */
        SET_STATE (STATE_SAPI_3, SMS_ESTABLISHED);
        srv_use_stored_prim ();
      }
      break;

    default:
      break;
  }
  PFREE (dl_establish_ind);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_mph_random_access_cnf  |
+--------------------------------------------------------------------+

  PURPOSE : Layer 1 confirms with the primitive MPH_RANDOM_ACCESS_CNF
            the sending of a random burst during connection establishment.

*/

GLOBAL void dat_mph_random_access_cnf (T_MPH_RANDOM_ACCESS_CNF *mph_random_access_cnf)
{
  GET_INSTANCE_DATA;
  TRACE_FUNCTION ("dat_mph_random_access_cnf()");

  EM_CHANNEL_REQUEST_SENT;

  switch (GET_STATE (STATE_DAT))
  {
    case DAT_IMM_ASS:
      if (rr_data->ms_data.access_counter < rr_data->ms_data.max_attempt)
      {
        /*
         * if it the last or less then last random burst
         * copy the frame number of the random burst for later
         * comparision with the request reference of an immediate
         * assignment message.
         */
        memcpy (&rr_data->used_frame_no[rr_data->ms_data.access_counter],
                &mph_random_access_cnf->frame_no,
                sizeof (T_frame_no));

        /*
        TRACE_EVENT_P5 ("RA %u CNF: %d %d %d 0x%02x",
          rr_data->ms_data.access_counter,
          mph_random_access_cnf->frame_no.t1,
          mph_random_access_cnf->frame_no.t2,
          mph_random_access_cnf->frame_no.t3,
          rr_data->used_channel_ref[rr_data->ms_data.access_counter]);
        */

        /*
         * increment the number of already sent messages
         */
        rr_data->ms_data.access_counter++;

        if (rr_data->ms_data.access_counter EQ rr_data->ms_data.max_attempt)
        {
          /*
           * T3126 and T3146 (GPRS Packet Access on CCCH) are
           * the same so use them for both purposes
           *
           * if it is the last random burst, start T3126 if the timer is not
           * running yet (can be started after reception of an immediate
           * assignment reject message).
           * The timer controls reception of an immediate assignment message
           * as response to the random bursts.
           */
/* Implements Measure#32: Row 196,197 */
          (IS_TIMER_ACTIVE(T3126)) ? 
            TRACE_TIMER ( "T3126 re-start") : TRACE_TIMER ( "T3126 start");
          
          if (! IS_TIMER_ACTIVE(T3126))
          {
            TIMERSTART (T3126, T3126_VALUE);
          }

          /*
           * set a flag that all random bursts are send and confirmed.
           */
          rr_data->ms_data.all_conf_received = TRUE;
        }
      }
      break;

    default:
      break;
  }
  PFREE (mph_random_access_cnf);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_dl_release_cnf         |
+--------------------------------------------------------------------+

  PURPOSE : Layer 2 confirms with DL_RELEASE_CNF a disconnection on
            layer 2 which has been initiated by RR.

*/

GLOBAL void dat_dl_release_cnf (T_DL_RELEASE_CNF *dl_release_cnf)
{
  GET_INSTANCE_DATA;
  TRACE_FUNCTION ("dat_dl_release_cnf()");

  switch (GET_STATE (STATE_DAT))
  {
    case DAT_CHAN_REL:
      /*
       * after reception of a channel release message RR has
       * started disconnection to come from dedicated to idle
       * mode. Stop T3110, which controls the disconnection in
       * layer 2.
       */
      TIMERSTOP (T3110);
      /*
       * Send STOP_DEDICATED_REQUEST to L1 and wait for confirmation 
       */
      att_stop_dedicated();
      break;

#ifdef GPRS
    case DAT_PDCH_ASS_2:
      dat_rrgrr_resumed_tbf_cnf();
      rr_data->gprs_data.tbf_est = TBF_EST_NONE;  /* the initial state */
      break;
#endif

    case DAT_HANDOVER_4:
      TRACE_EVENT ("Event: DAT_HANDOVER_4");
      /*
       * the layer 2 resumption on the new channel during handover
       * has failed and RR switches back to the old channel.
       */
      dat_code_mph_old_chan_req ();
      SET_STATE (STATE_DAT, DAT_HANDOVER_5);
      break;

    case DAT_CHAN_ASS_1:
      /*
       * resumption of layer 2 has failed after channel assignment
       * go back to the old channel.
       */
      dat_code_mph_old_chan_req ();
      SET_STATE (STATE_DAT, DAT_CHAN_ASS_2);
      break;

    case DAT_DEDICATED:
    case DAT_CHAN_ASS:
    case DAT_CHAN_ASS_2:
    case DAT_HANDOVER_5:
      TRACE_EVENT ("Event: DAT_DEDICATED, DAT_CHAN_ASS, DAT_CHAN_ASS_2 or DAT_HANDOVER_5");

      if (dl_release_cnf->sapi EQ SAPI_3)
      {
        /*
         * the connection for SAPI 3 is disconnected by the
         * network.
         */
        SET_STATE (STATE_SAPI_3, SMS_IDLE);
        dat_rr_release_ind(RRCS_DATA_LINK_FAIL, SAPI_3);

        /*
         * clear any stored SAPI 3 message
         */
        srv_clear_stored_prim (RR_DATA_REQ);
      }
      else
      {
        /*
         * the reconnection to the old channel has failed
         * or a lower layer failure had happen.
         * Indicate the abort to MM and start cell reselection.
         */
        switch (GET_STATE (STATE_DAT))
        {
          case DAT_CHAN_ASS:
          case DAT_CHAN_ASS_2:
            TRACE_EVENT("Assignment failed: reconnect failed");
            EM_ASS_FAILURE_RECONNECT_FAILED;
            break;
          case DAT_HANDOVER_5:
            TRACE_EVENT("Handover failed: reconnect failed");
            EM_HO_FAILURE_RECONNECT_FAILED;
            break;
          default:
            break;
        }

        att_code_rr_abort_ind (RRCS_DATA_LINK_FAIL);

        rr_data->net_lost = TRUE;
        att_stop_dedicated();
      }
      break;

    case DAT_IMM_ASS_1:
      /*
       * Layer 2 establishment has failed for immediate assignment
       * Stop dedicated and go back to idle mode. MM will be informed about
       * release after receiving MPH_STOP_DEDICATED_CNF from L1.
       */
      if (rr_data->ms_data.establish_cause NEQ ESTCS_PAGING)
      {
        rr_data->rel_cause = RRCS_DL_EST_FAIL;
      }
      att_stop_dedicated();
      break;

    default:
      break;
  }
  PFREE (dl_release_cnf);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_dl_release_ind         |
+--------------------------------------------------------------------+

  PURPOSE : Layer 2 indicates disconnection due to layer 2 problems.

*/

GLOBAL void dat_dl_release_ind (T_DL_RELEASE_IND *dl_release_ind)
{
  GET_INSTANCE_DATA;
  TRACE_FUNCTION ("dat_dl_release_ind()");

  switch (GET_STATE (STATE_DAT))
  {
    case DAT_CHAN_ASS:
    case DAT_CHAN_ASS_2:
    case DAT_DEDICATED:
    case DAT_HANDOVER:
    case DAT_HANDOVER_5:
      TRACE_EVENT ("DL_RELEASE_IND");
      if (dl_release_ind->sapi EQ SAPI_3)
      {
        /*
         * indicate release for SAPI 3 (SMS)
         * to MM and reset RR state back to SMS_IDLE.
         */
        dat_rr_release_ind(RRCS_DATA_LINK_FAIL, SAPI_3);
        SET_STATE (STATE_SAPI_3, SMS_IDLE);
        /*
         * clear any stored SAPI 3 message
         */
        srv_clear_stored_prim (RR_DATA_REQ);
      }
      else
      {
        /*
         * Delay 4 frames to allow sending UA response
         * in RF for FTA testcase 25.2.3
         * else the idle mode is configured too early.
         * vsi_t_sleep (VSI_CALLER FOUR_FRAMES);
         *
         * msb: DL delays the release indication itself for completion of the
         *      UA response transmission.
         */
        EM_DL_RELEASE_IND;

        /*
         * Inform MM about the release and start cell reselection.
         */
        att_code_rr_abort_ind (RRCS_DATA_LINK_FAIL);

        rr_data->net_lost = TRUE;
        att_stop_dedicated();
      }
      break;

    case DAT_CHAN_ASS_1:
      /*
       * resumption of layer 2 has failed after channel assignment
       * go back to the old channel.
       */
      dat_code_mph_old_chan_req ();
      SET_STATE (STATE_DAT, DAT_CHAN_ASS_2);

      EM_ASS_FAILURE_RECONNECT_FAILED2
      break;

    case DAT_CHAN_REL:
      /*
       * after reception of a channel release message RR has
       * started disconnection to come from dedicated to idle
       * mode. Stop T3110, which controls the disconnection in
       * layer 2.
       */
      TIMERSTOP (T3110);

      /*
       * Send STOP_DEDICATED_REQUEST to L1 and wait for confirmation 
       */
      att_stop_dedicated();

      EM_L2_CONNECTION_LOST;
      break;

    case DAT_HANDOVER_4:
      TRACE_EVENT ("DL_RELEASE_IND");
      /*
       * resumption of layer 2 has failed handover
       * go back to the old channel.
       */
      dat_code_mph_old_chan_req ();
      SET_STATE (STATE_DAT, DAT_HANDOVER_5);

      EM_HO_FAILURE_RECONNECT_FAILED2;

      break;

    case DAT_IMM_ASS_1:

      /*
       * layer 2 establishment has failed during immediate assignment
       */
      if (dl_release_ind->cs EQ DL_INFO_FIELD_MISMATCH AND
          rr_data->sc_data.first_attempt)
      {
        /*
         * if the reason is a mismatch in the layer 3 messages in SABM
         * and the response UA, a second attempt of establishment is started.
         */
        rr_data->sc_data.first_attempt = FALSE;
        rr_data->repeat_est    = TRUE;
#ifdef GPRS
        if (rr_data->ms_data.establish_cause EQ ESTCS_GPRS_PAGING)
          rr_data->dcch_stop_cause = CONTENTION_RESOLUTION_FAIL;
#endif
      }
      else
      {
        switch (rr_data->ms_data.establish_cause)
        {
#ifdef GPRS
          case ESTCS_GPRS_PAGING:
            rr_data->dcch_stop_cause = DL_ESTABLISHMENT_FAIL;
            break;
          case ESTCS_PAGING:
            rr_data->rel_cause = RRCS_INT_NOT_PRESENT;
#else
          case ESTCS_PAGING:
#endif
            break;
          default:
            rr_data->rel_cause = RRCS_DL_EST_FAIL;
            break;
        }
      }

      /*
       * Stop dedicated and go back to idle mode.
       */
      att_stop_dedicated();
      break;

#ifdef GPRS
    case DAT_PDCH_ASS_4:
    case DAT_CCO_4:
      if ( GET_STATE (STATE_DAT) EQ DAT_PDCH_ASS_4 OR
           rr_data->gprs_data.cco_need_reconnect_cnf )
      {
        dat_rrgrr_reconnect_dcch_cnf (RECONN_LOW_FAIL);
      }
      att_build_idle_req (SC_INDEX, MODE_CELL_RESELECTION);
      SET_STATE (STATE_DAT, DAT_IDLE);
      break;
#endif

    default:
      break;
  }
  PFREE (dl_release_ind);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_mph_dedicated_cnf      |
+--------------------------------------------------------------------+

  PURPOSE : Layer 1 confirms the configuration of a dedicated channel.

*/

GLOBAL void dat_mph_dedicated_cnf (T_MPH_DEDICATED_CNF *mph_dedicated_cnf)
{
  GET_INSTANCE_DATA;
  TRACE_FUNCTION ("dat_mph_dedicated_cnf()");

  switch (GET_STATE (STATE_DAT))
  {
    case DAT_IMM_ASS_1:
      /*
       * A dedicated channel has been configured after
       * reception of the immediate assignment message.
       *
       * clear neighbourcell list and start layer 2 establishment
       */
      srv_clear_list (&rr_data->sc_data.cd.ncell_list);
      srv_clear_list (&rr_data->sc_data.five_ter_list);
      att_clean_buf (IND_ALL_DEDI_SI);
      rr_data->sc_data.cd.sys_info_read &= ~ALL_DEDI_SYS_INFOS;
      /*
       * from now on we have a channel assigned
       * even if the contention resolution is not
       * done yet. If the contention resolution fails
       * we use the same procedure for selecting a cell
       * as in dedicated mode
       */

      rr_data->mode_after_dedi = MODE_CELL_SELECTION; /* default mode */
      TIMERSTART (T_DEDICATED_MODE, THIRTY_SEC);
#ifdef GPRS
      if(! dat_gprs_start_sabm())
#endif
        dat_start_sabm ();
      break;

    case DAT_CHAN_ASS:

      if (rr_data->dyn_config.fca)
      {
        /*
         * special testfeature to force a failed layer 2 establishment
         * during  channel assignment. Reset flag and switch back to old
         * channel.
         */
        rr_data->dyn_config.fca = 0;
        dat_code_mph_old_chan_req ();
        SET_STATE (STATE_DAT, DAT_CHAN_ASS_2);
      }
      else
      {
        /*
         * Resume layer 2 connection on the new channel with
         * an assignment complete message.
         */
        MCAST (assign_com, U_ASSIGN_COMP);
        PALLOC_MSG ( dl_resume_req, DL_RESUME_REQ, U_ASSIGN_COMP);

        SET_STATE (STATE_DAT, DAT_CHAN_ASS_1);
        assign_com->msg_type  = U_ASSIGN_COMP;
        assign_com->rr_cause  = RRC_NORMAL_EVENT;

        /*
         * set channel and sapi for the new channel description
         */
        dat_code_prr_channel (&dl_resume_req->ch_type,
                              &dl_resume_req->sapi,
                              rr_data->cr_data.chan_desc.chan_type);

        /*
         * start layer 2 resumption.
         */
        for_dat_resume_req (dl_resume_req);
        EM_ASSIGNMENT_COMPLETE;
      }
      break;

#ifdef GPRS
    case DAT_PDCH_ASS:
      /*
       * The current channel has been stopped at the Physical Layer.
       */
      dat_rrgrr_suspend_dcch_cnf();
      SET_STATE (STATE_DAT, DAT_PDCH_ASS_1);
      SET_STATE (STATE_GPRS, GPRS_PIM_BCCH); /* force MPH_IDLE_REQ with RRGRR_STOP_MON_CCCH_REQ */
      rr_data->gprs_data.tbf_est = TBF_EST_PDCH;
      break;
#endif

    case DAT_HANDOVER:
    {
      /*
       * clearing of neighbourcells is already done
       * after reception of the handover command.
       *
       * following behaviour depends on the result of
       * handover execution in layer 1.
       */
      switch (mph_dedicated_cnf->dedi_res)
      {
        case DEDI_RES_OK:
          /*
           * handover is successfull.
           */
          if (rr_data->dyn_config.fca)
          {
            /*
             * special testfeature to simulate
             * failed handover, reset flag
             * and start reconnection.
             */
            rr_data->dyn_config.fca = 0;
            dat_code_mph_old_chan_req ();
            SET_STATE (STATE_DAT, DAT_HANDOVER_5);
          }
          else
          {
            /*
             * build a handover complete message.
             */
            MCAST (handov_comp, U_HANDOV_COMP);
            PALLOC_MSG (dl_resume, DL_RESUME_REQ, U_HANDOV_COMP);

            if (rr_data->ms_data.ho_type.rot EQ TIME_DIFF_YES)
            {
              /*
               * handover command has requested the observed time difference.
               */
              handov_comp->v_mob_time_diff = TRUE;
              handov_comp->mob_time_diff.diff   = rr_data->sc_data.observed_ta;
            }
            else
            {
              handov_comp->v_mob_time_diff = FALSE;
            }

            handov_comp->msg_type = U_HANDOV_COMP;
            handov_comp->rr_cause = RRC_NORMAL_EVENT;

            /*
             * set channel type and sapi for the new channel
             */
            dat_code_prr_channel (&dl_resume->ch_type,
                                  &dl_resume->sapi,
                                  rr_data->cr_data.chan_desc.chan_type);

            EM_HANDOVER_COMPLETE;

            /*
             * start layer 2 resumption.
             */
            for_dat_resume_req (dl_resume);
            SET_STATE (STATE_DAT, DAT_HANDOVER_4);
          }
          break;

        case DEDI_RES_TIMEOUT:
          /*
           * the timer T3124 during an asynchronous handover
           * has timed out, start reconnection.
           */
          dat_code_mph_old_chan_req ();
          SET_STATE (STATE_DAT, DAT_HANDOVER_5);
          break;

        case DEDI_RES_CELL_NOT_SYNC :
           /*
            * Timing Info for this cell is not present in ALR.
            * This could be due to :
            * a) Cell not present in BA list,
            * b) Synchronization to this cell failed or not attempted.
            */
        case DEDI_RES_TA_OUT_OF_RANGE:
        {
          /*
           * Layer 1 has detected that the timing advance is out of range.
           * In fact the new channel has not been configured and RR
           * can start reconnection to the old layer 2 connection immediately.
           * It sends a handover failure message with the expected cause.
           */
          MCAST (handov_fail, U_HANDOV_FAIL);
          PALLOC_MSG (dl_reconnect_req, DL_RECONNECT_REQ, U_HANDOV_FAIL);

          /*
           * set channel type and sapi for the old channel
           */
          dat_code_prr_channel (&dl_reconnect_req->ch_type,
                                &dl_reconnect_req->sapi,
                                rr_data->sc_data.chan_desc.chan_type);
          handov_fail->msg_type = U_HANDOV_FAIL;

          if( mph_dedicated_cnf->dedi_res EQ DEDI_RES_TA_OUT_OF_RANGE)
            handov_fail->rr_cause = RRC_TIME_ADVANCE;
          else if ( mph_dedicated_cnf->dedi_res EQ DEDI_RES_CELL_NOT_SYNC)
#if defined (REL99) && defined (FF_BHO)
            handov_fail->rr_cause = RRC_LOWER_LAYER_FAIL;
#else
            handov_fail->rr_cause = RRC_CHAN_UNACCEPT;
#endif
          RR_EM_SET_HANDOVER_FAIL_CAUSE(handov_fail->rr_cause);

          /*
           * start reconnection of the layer 2 link on the old channel.
           */
          for_dat_reconnect_req (dl_reconnect_req);
          SET_STATE (STATE_DAT, DAT_HANDOVER_5);

          break;
        }
      }
      break;
    }

    default:
      break;
  }
  PFREE (mph_dedicated_cnf);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_mph_dedicated_fail_cnf |
+--------------------------------------------------------------------+

  PURPOSE : Layer 1 confirms the re-configuration of the old channel
            after a failed handover or channel assignment with the
            primitive MPH_DEDICATED_FAIL_CNF.

*/

GLOBAL void dat_mph_dedicated_fail_cnf (T_MPH_DEDICATED_FAIL_CNF *mph_dedicated_fail_cnf)
{
  GET_INSTANCE_DATA;
  TRACE_FUNCTION ("dat_mph_dedicated_fail_cnf()");

  switch (GET_STATE (STATE_DAT))
  {
    case DAT_CHAN_ASS_2:
    {
      /*
       * reconnection is done in layer 2. An assignment failure
       * message is send to the network.
       */
    
      MCAST (assign_fail, U_ASSIGN_FAIL);
      PALLOC_MSG (dl_reconnect_req, DL_RECONNECT_REQ, U_ASSIGN_FAIL);

      assign_fail->msg_type = U_ASSIGN_FAIL;
      assign_fail->rr_cause = RRC_PROT_UNSPECIFIED;

      RR_EM_SET_ASSIGN_FAIL_CAUSE(assign_fail->rr_cause);

      /*
       * set channel type and SAPI for layer 2
       */
      dat_code_prr_channel (&dl_reconnect_req->ch_type,
                            &dl_reconnect_req->sapi,
                            rr_data->sc_data.chan_desc.chan_type);

      /*
       * start layer 2 reconnection
       */
      for_dat_reconnect_req (dl_reconnect_req);

      break;
    }

    case DAT_HANDOVER_5:
    {
      /*
       * reconnection is done in layer 2. A handover failure
       * message is send to the network.
       */
      MCAST (handov_fail, U_HANDOV_FAIL);
      PALLOC_MSG (dl_reconnect_req, DL_RECONNECT_REQ, U_HANDOV_FAIL);

      /*
       * clear neighbourcell list
       */
      srv_clear_list (&rr_data->sc_data.cd.ncell_list);
      srv_clear_list (&rr_data->sc_data.five_ter_list);
      att_clean_buf (IND_ALL_DEDI_SI);
      rr_data->sc_data.cd.sys_info_read &= ~ALL_DEDI_SYS_INFOS;
      handov_fail->msg_type = U_HANDOV_FAIL;
      handov_fail->rr_cause = RRC_UNSPECIFIED;

      RR_EM_SET_HANDOVER_FAIL_CAUSE(handov_fail->rr_cause);

      /*
       * set channel type and SAPI for layer 2
       */
      dat_code_prr_channel (&dl_reconnect_req->ch_type,
                            &dl_reconnect_req->sapi,
                            rr_data->sc_data.chan_desc.chan_type);

      /*
       * start layer 2 reconnection
       */
      for_dat_reconnect_req (dl_reconnect_req);
      break;
    }

#ifdef GPRS
    case DAT_PDCH_ASS_3:
    {
      MCAST (u_assign_fail, U_ASSIGN_FAIL);
      PALLOC_MSG (dl_reconnect_req, DL_RECONNECT_REQ, U_ASSIGN_FAIL);

      /*
       * set channel type and SAPI
       */
      dat_code_prr_channel (&dl_reconnect_req->ch_type,
                            &dl_reconnect_req->sapi,
                            rr_data->sc_data.chan_desc.chan_type);

      u_assign_fail->msg_type = U_ASSIGN_FAIL;
      u_assign_fail->rr_cause = rr_data->gprs_data.reconn_cause;

      for_dat_reconnect_req (dl_reconnect_req);
  
      SET_STATE (STATE_DAT, DAT_PDCH_ASS_4);
      break;
    }

    case DAT_CCO_3:
    {
      MCAST (u_handov_fail, U_HANDOV_FAIL);
      PALLOC_MSG (dl_reconnect_req, DL_RECONNECT_REQ, U_HANDOV_FAIL);

      /*
       * set channel type and SAPI
       */
      dat_code_prr_channel (&dl_reconnect_req->ch_type,
                            &dl_reconnect_req->sapi,
                            rr_data->sc_data.chan_desc.chan_type);

      u_handov_fail->msg_type = U_HANDOV_FAIL;
      u_handov_fail->rr_cause = rr_data->gprs_data.reconn_cause;

      for_dat_reconnect_req (dl_reconnect_req);
      SET_STATE (STATE_DAT, DAT_CCO_4);
      break;
    }
#endif

    default:
      break;
  }
  PFREE (mph_dedicated_fail_cnf);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_rr_abort_req           |
+--------------------------------------------------------------------+

  PURPOSE : MM aborts a connection due to several reasons (SIM remove,
            timeout, power off etc.).

*/

GLOBAL void dat_rr_abort_req (T_RR_ABORT_REQ *rr_abort_req)
{
  GET_INSTANCE_DATA;
  TRACE_FUNCTION ("dat_rr_abort_req()");

  switch (GET_STATE (STATE_DAT))
  {
    case DAT_CHAN_ASS:
    case DAT_CHAN_ASS_1:
    case DAT_CHAN_ASS_2:
    case DAT_DEDICATED:
    case DAT_HANDOVER:
    case DAT_HANDOVER_4:
    case DAT_HANDOVER_5:
      if (rr_abort_req->abcs EQ ABCS_SIM_REM)
      {
        /*
         * in case of SIM remove the registration data
         * especially the mobile identities are cleared
         */
        att_clear_registration_data ();
      }

      /*
       * the disconnection of the layer 2 link is started.
       */
      dat_disconnect_link (RRCS_MM_ABORTED);
      break;

    case DAT_CHAN_REL:
      /*
       * RR has already started the layer 2 link disconnection.
       * Wait for T3110 timeout or DL disconnection and process
       * normal cell reselection.
       */
      if (rr_abort_req->abcs EQ ABCS_SIM_REM)
      {
        /*
         * in case of SIM remove the registration data
         * especially the mobile identities are cleared
         */
        att_clear_registration_data ();
      }
      break;

    case DAT_IDLE:
      if (rr_abort_req->abcs EQ ABCS_SIM_REM)
      {
        /*
         * in case of SIM remove the registration data
         * especially the mobile identities are cleared
         * The idle mode is configured again to set a
         * faked BS_PA_MFRMS of 9 to slow down layer 1
         * and save power. A correct paging group is not
         * longer needed, because paging is not possible
         * in limited service.
         */
        att_clear_registration_data ();
        att_build_idle_req (SC_INDEX,
                            MODE_SYS_INFO_CHANGE);
#ifdef REL99
        att_config_cbch ();
#else
        att_build_cbch ();
#endif
      }
      break;

    case DAT_IMM_ASS:
    case DAT_IMM_ASS_1:
      if (rr_abort_req->abcs EQ ABCS_SIM_REM)
      {
        /*
         * in case of SIM remove the registration data
         * especially the mobile identities are cleared
         */
        att_clear_registration_data ();
      }

      /*
       * stop any timer related to connection establishment
       */
      TIMERSTOP (T3122);
      TIMERSTOP (T3126);

      /*
       * set the release establishment cause. This will be used in 
       * dat_release_connection() function
       */
      rr_data->rel_cause = RRCS_MM_ABORTED;

      if(GET_STATE (STATE_DAT) EQ DAT_IMM_ASS)
      {
        dat_rr_release_ind(rr_data->rel_cause, SAPI_0);
        att_leave_dat_imm_ass();
      }
      else
      {
        /*
         * go back to idle mode.
         * inform GRR, and don't wait for CR_RSP 
         */
        att_stop_dedicated();
      }
      break;

    default:
      if (rr_abort_req->abcs EQ ABCS_SIM_REM)
      {
        /*
         * in case of SIM remove the registration data
         * especially the mobile identities are cleared
         */
        att_clear_registration_data ();
      }
      /*
       * clear any store establish requests if available
       * due to a timeout abort of the upper layer.
       */
      if (srv_check_stored_prim (RR_ESTABLISH_REQ))
      {
        /*
         * release previous establish request
         */
        dat_rr_release_ind(RRCS_MM_ABORTED, SAPI_0);
        srv_clear_stored_prim (RR_ESTABLISH_REQ);
      }
      break;
  }

  PFREE (rr_abort_req);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_rr_data_req            |
+--------------------------------------------------------------------+

  PURPOSE : A layer 3 message of an upper layer shall be send.

*/

GLOBAL void dat_rr_data_req (T_RR_DATA_REQ *rr_data_req)
{
  GET_INSTANCE_DATA;
  UBYTE pd;

  TRACE_FUNCTION ("dat_rr_data_req()");

  /*
   * get the protocol discriminator of the message.
   */
  GET_PD (rr_data_req->sdu, pd);

  if (pd EQ PD_SMS)
  {
    TRACE_EVENT ("SMS Message");

    /*
     * A SMS must be send with SAPI 3. Therefore the
     * SAPI 3 connection must be established on layer 2.
     * The STATE_SAPI_3 variable in RR indicates whether
     * the connection is established or not. If not the
     * message is stored and the connection will be established.
     * A SAPI 3 connection is automatically released after
     * channel assignment, handover or SAPI 0 release.
     */
    switch (GET_STATE (STATE_SAPI_3))
    {
      case SMS_ESTABLISHED:
      {
        /*
         * SAPI 3 connection is available, then send the message
         * directly.
         */       
        PPASS (rr_data_req, dl_data_req, DL_DATA_REQ);

        /*
         * set channel type and SAPI for SMS message.
         */
        dat_code_prr_channel_sms (dl_data_req,
                                  rr_data->sc_data.chan_desc.chan_type);
        for_dat_l3_data_req (dl_data_req);  
        break;
      }

      case SMS_PENDING:
        /*
         * the establishment of SAPI 3 connection is still ongoing.
         * store the message until connection is ready.
         */
        if (!srv_store_prim ((T_PRIM *)D2P(rr_data_req)))
        {
          PFREE (rr_data_req);
        }
        break;

      case SMS_IDLE:
        /*
         * the establishment of SAPI 3 connection is not available
         * store the message until connection is ready.
         */
        if (!srv_store_prim ((T_PRIM *)D2P(rr_data_req)))
        {
          PFREE (rr_data_req);
        }
        else
        {
          /*
           * Maximum size of the initial message is one frame (= 23 Bytes).
           */
          PALLOC_SDU (dl_establish_req, DL_ESTABLISH_REQ, MAX_L2_FRAME_SIZE * BITS_PER_BYTE);
          dat_code_prr_channel_sms ((T_DL_DATA_REQ *)dl_establish_req,
                                    rr_data->sc_data.chan_desc.chan_type);

          SET_STATE (STATE_SAPI_3, SMS_PENDING);
          for_dat_est_req (dl_establish_req);
        }
        break;
    }
  }
  else
  {
    /*
     * it is a SAPI 0 message
     */
    PPASS (rr_data_req, dl_data_req, DL_DATA_REQ);

    /*
     * set channel type and SAPI according the channel type.
     */
    dat_code_prr_channel (&dl_data_req->ch_type,
                          &dl_data_req->sapi,
                          rr_data->sc_data.chan_desc.chan_type);

    /*
     * set N(S) for upper layer message and forward it to Layer 2.
     */
    dat_vsd_bit_set ((T_L3_SDU *)&dl_data_req->sdu, SET_ONLY);
    for_dat_l3_data_req (dl_data_req);   
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_rr_establish_req       |
+--------------------------------------------------------------------+

  PURPOSE : A mobile originated connection is started.

*/

GLOBAL void dat_rr_establish_req (T_RR_ESTABLISH_REQ *rr_establish_req)
{
  GET_INSTANCE_DATA;
  TRACE_FUNCTION ("dat_rr_establish_req()");

  switch (GET_STATE (STATE_DAT))
  {
    case DAT_NULL:
      /*
       * Data transfer process is in null state, that means
       * the MS has no service
       */
      if (!srv_store_prim ((T_PRIM *)D2P(rr_establish_req)))
      {
        /*
         * storing is not possible due to an overflow of the storage area
         * then reject the connection attempt.
         */
        dat_rr_release_ind(RRCS_QUEUE_FULL, SAPI_0);
        PFREE (rr_establish_req);
      }
      break;

    case DAT_IDLE:
      if (IS_TIMER_ACTIVE(T3122) AND (rr_establish_req->estcs NEQ ESTCS_EMRG_CAL))
      {
        /*
         * all non-emergency calls are rejected if T3122 is running.
         * The timer has been started after reception of an immediate
         * assignment reject message.
         */
        dat_rr_release_ind(RRCS_T3122_RUNNING, SAPI_0);
        PFREE (rr_establish_req);

        TRACE_EVENT ("imm ass delayed");
      }
      else
      {
        /*
         * If T3122 is not running the access to the network is checked.
         */
        if (dat_access_allowed (rr_establish_req->estcs))
        {
          if (rr_establish_req->estcs EQ ESTCS_SERV_REQ_BY_MM)
          {
            /*
             * if location updating is started, store fieldstrength
             * for an optimisation. RR indicates to MM fieldstrength jumps
             * over 6 dBm in the field, that means better chance to
             * perform a successfull location updating.
             */
            rr_data->lup_rxlev = rr_data->nc_data[SC_INDEX].rxlev;
          }

          /*
           * store the piggy-backed layer 3 message for later use.
           */
          memcpy (&rr_data->ms_data.l3msg, &rr_establish_req->sdu,
                  sizeof (T_L3_SDU));/*lint !e420 Apparent access beyond array for function*/

          /*
           * Initialize the N(S) for upper layer messages.
           */
          dat_vsd_bit_set (&rr_data->ms_data.l3msg, SET_AND_RESET);

          /*
           * Initialize some parameters and start immediate assignment.
           */
          rr_data->sc_data.first_attempt = TRUE;
          rr_data->repeat_est    = FALSE;
#ifdef GPRS
          dat_gprs_set_suspended();
#endif
          dat_start_immediate_assign (rr_establish_req->estcs);
          PFREE (rr_establish_req);
        }
        else
        {
          /*
           * Access is not allowed and the rejection is signalled to MM.
           */
          dat_rr_release_ind(RRCS_ACCESS_BARRED, SAPI_0);
          PFREE (rr_establish_req);

          TRACE_EVENT ("access barred");
        }
      }
      break;

    case DAT_IMM_ASS:
    case DAT_IMM_ASS_1:
    case DAT_DEDICATED:
      {
        /*
         * collision of MO and MT calls. MT has higher priority than
         * MO calls.
         */
        dat_rr_release_ind(RRCS_MO_MT_COLL, SAPI_0);
        PFREE (rr_establish_req);
        break;
      }

    default:
      PFREE (rr_establish_req);
      break;
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_mph_paging_ind         |
+--------------------------------------------------------------------+

  PURPOSE : Layer 1 has detected a paging for the mobile.
            RR starts the immediate assignment procedure.

*/

GLOBAL void dat_mph_paging_ind (T_MPH_PAGING_IND *mph_paging_ind)
{
  GET_INSTANCE_DATA;
#ifdef GPRS
  UBYTE ret;
#endif
  TRACE_FUNCTION ("dat_mph_paging_ind()");

  EM_PAGING_IND;

  /* check access control class before processing for paging */
  if (dat_access_allowed(ESTCS_PAGING) EQ FALSE)
  {
    PFREE (mph_paging_ind);
    TRACE_EVENT("Access ctrl class not allowed for responding to the page msg");
    return;
  }

  switch (GET_STATE (STATE_DAT))
  {
    case DAT_NULL:
      /*
       * MS is not in idle mode, searching for cell
       */
      if (! IS_TIMER_ACTIVE(T3122) AND GET_STATE (STATE_ATT) NEQ ATT_NULL)
      {
        /*
         * paging is only excepted if T3122 is not running and there isn't
         * performed a RR_DEACTIVATE_REQ just before
         */
        if (rr_data->pag_rec EQ FALSE)
        {
          /*
           * store paging if no paging is stored until now.
           */
          if (!srv_store_prim ((T_PRIM *)D2P(mph_paging_ind)))
          {
            /*
             * storage is full
             */
            PFREE (mph_paging_ind);
          }
          else
          {
            /*
             * marker that paging has been received.
             */
            rr_data->pag_rec = TRUE;
          }
          return;
        }
      }
      break;

    case DAT_IDLE:
      if (! IS_TIMER_ACTIVE(T3122))
      {
        if (rr_data->first_meas_received EQ FALSE)
        {
          /*
           *  we are actually still in cell reselection
           *  because we have not yet received a measurement
           *  report. But we have to be in idle mode to make
           *  measurements in the first place.
           */

          if (srv_check_stored_prim (MPH_PAGING_IND))
          {
            /*
             * if already a paging is stored, ignore subsequent pagings
             */
            PFREE (mph_paging_ind);
          }
          else
          {
            /*
             * store paging until measurement receives
             */
            rr_data->pag_rec = TRUE;
            if (!srv_store_prim ((T_PRIM *)D2P(mph_paging_ind)))
            {
              /*
               * storage buffer is full
               */
              rr_data->pag_rec = FALSE;
              PFREE (mph_paging_ind);
            }
          }
          return;
        }

#ifdef GPRS
        ret = dat_check_packet_paging_ind(mph_paging_ind);
        if(ret EQ FALSE)
        {
            /*
             * we are suspended and it is not a packet paging
             */
            dat_begin_start_immediate_assign (mph_paging_ind->identity_type,
                                              mph_paging_ind->channel_needed);
        }
        else if(ret EQ TRUE)
        {
          /*
           * we are not suspended and it is not a packet paging
           * and GPRS is activate
           */
          dat_ask_paging_ind(mph_paging_ind);
        }
        /* ret EQ 2-> packet paging for GPRS, do nothing */
#else  /* GPRS */
        dat_begin_start_immediate_assign (mph_paging_ind->identity_type,
                                          mph_paging_ind->channel_needed);
#endif  /* GPRS */
      }

      break;
#ifdef GPRS
    case DAT_IMM_ASS:
      /* only PS pagings are received in this state */
      dat_ask_paging_ind_pa_only(mph_paging_ind);
      break;
#endif
    default:
      break;
  }
  PFREE (mph_paging_ind);
}

#if defined FF_EOTD
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_rrlc_meas_req          |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive RRLC_MEAS_REQ received from LC.
            Start the LCS/EOTD postion measurement procedure.

*/

GLOBAL void dat_rrlc_meas_req (T_RRLC_MEAS_REQ *rrlc_meas_req)
{
  GET_INSTANCE_DATA;
  T_NC_DATA   *sc;
  int         i,n;

  TRACE_FUNCTION ("dat_rrlc_meas_req()");

  switch ( GET_STATE (STATE_DAT) )
  {
    case DAT_HANDOVER  :
    case DAT_HANDOVER_4:
    case DAT_HANDOVER_5:
      {
        PALLOC (rrlc_error_ind, RRLC_ERROR_IND);
        rrlc_error_ind->cause = LCS_HANDOVER;

        rr_data->eotd_req_id = NOT_PRESENT_16BIT;

        PSENDX (LC, rrlc_error_ind);

        PFREE(rrlc_meas_req);
        return;
      }
    default:
      break;
  }

  /*
   *  Check if the requested cell matches the serving cell.
   */

  sc = &rr_data->nc_data[SC_INDEX];

  if ( rrlc_meas_req->v_arfcn              AND
       rrlc_meas_req->  arfcn NEQ sc->arfcn AND
       rrlc_meas_req->v_bsic               AND
       rrlc_meas_req->  bsic  NEQ sc->bsic     )
  {
    PALLOC (rrlc_error_ind, RRLC_ERROR_IND);
    rrlc_error_ind->cause = LCS_WRONG_BTS;
    PSENDX (LC, rrlc_error_ind);

    PFREE(rrlc_meas_req);
    return;
  }

  /*
   *  The requested cell matches the serving cell or
   *  the requested cell was not specified.
   */

  {
    PALLOC ( mph_ncell_pos_req, MPH_NCELL_POS_REQ );

    rr_data->eotd_req_id = rrlc_meas_req->req_id;

    n = rrlc_meas_req->v_assist_data ? rrlc_meas_req->c_assist_data : 0;
    mph_ncell_pos_req->c_ncell_eotd = n;
    mph_ncell_pos_req->req_id       = rrlc_meas_req->req_id;
    for ( i = 0; i < n; ++i )
      mph_ncell_pos_req->ncell_eotd[i] = *(T_ncell_eotd*)&rrlc_meas_req->assist_data[i];

    PSENDX ( PL, mph_ncell_pos_req );
  }
  PFREE(rrlc_meas_req);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : dat_rrrrlp_data_req        |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive RRRRLP_DATA_REQ received from LC.
            Transmit a APDU according 3GPP TS 04.18, section 3.4.21.

*/

GLOBAL void dat_rrrrlp_data_req (T_RRRRLP_DATA_REQ *rrrrlp_data_req_orig)
{
  GET_INSTANCE_DATA;

  UBYTE  cr      =  rrrrlp_data_req_orig->cr;
  T_sdu *sdu     = &rrrrlp_data_req_orig->sdu;
  UBYTE *buf     = &sdu->buf[sdu->o_buf/BITS_PER_BYTE];
  USHORT len     = BYTELEN(sdu->l_buf);
  USHORT num_seg = len / APDU_FULL_L2_FRAME;      /* number of full segments */
  USHORT rem_seg = len % APDU_FULL_L2_FRAME;      /* size of last segment    */
  USHORT n_seg;                                   /* total number of segments*/
  USHORT i;
  UBYTE  flag;

  PPASS(rrrrlp_data_req_orig, rrrrlp_data_req, RRRRLP_DATA_REQ);

  TRACE_FUNCTION ("dat_rrrrlp_data_req()");

  /* sdu->o_buf must be a multiple of BITS_PER_BYTE */
  TRACE_ASSERT ( sdu->o_buf % BITS_PER_BYTE EQ 0 );

  /* compute the total number of segments (n_seg) */

  if ( len EQ 0 )
  {
    PFREE(rrrrlp_data_req);
    return;
  }

  n_seg = num_seg + ((rem_seg EQ 0) ? 0 : 1);

  /* in a loop with DL_DATA_REQ send all APDU segments */

  for ( i = 0; i < num_seg; ++i )
  {
    PALLOC_MSG ( dl_data_req, DL_DATA_REQ, B_APPLIC_INFO );

    dat_code_prr_channel (&dl_data_req->ch_type,
                          &dl_data_req->sapi,
                          rr_data->sc_data.chan_desc.chan_type );

    /* compute the APDU control flags */

    if ( n_seg EQ 1 )
    {
      flag = (UBYTE)(FIRST_SEG | LAST_SEG | (cr << 2));
    }
    else
    {
      if ( i EQ 0 )
      {
        flag = FIRST_SEG | NOT_LAST_SEG;
      }
      else
      {
        if ( i EQ num_seg-1 AND rem_seg EQ 0 )
          flag = NOT_FIRST_SEG | LAST_SEG | (cr << 2);
        else
          flag = NOT_FIRST_SEG | NOT_LAST_SEG;
      }
    }

    /* compile the APDU message and send it to DL */

    dl_data_req->sdu.buf[0] = PD_RR_TI_0;
    dl_data_req->sdu.buf[1] = B_APPLIC_INFO;
    dl_data_req->sdu.buf[2] = (flag << 4 ) | RRLP_LCS;
    dl_data_req->sdu.buf[3] = APDU_FULL_L2_FRAME;
    memcpy ( &dl_data_req->sdu.buf[4], buf, APDU_FULL_L2_FRAME );

    buf += APDU_FULL_L2_FRAME;
    dl_data_req->sdu.l_buf = (4 + APDU_FULL_L2_FRAME) * BITS_PER_BYTE;
    dl_data_req->sdu.o_buf = 0;

    PSENDX ( DL, dl_data_req );
  }

  /* send remaining APDU segment if its length > 0 */

  if ( rem_seg > 0 )
  {
    PALLOC_MSG ( dl_data_req, DL_DATA_REQ, B_APPLIC_INFO );

    dat_code_prr_channel (&dl_data_req->ch_type,
                          &dl_data_req->sapi,
                          rr_data->sc_data.chan_desc.chan_type );

    /* compute the APDU control flags */

    if ( n_seg EQ 1 )
      flag = FIRST_SEG | LAST_SEG | (cr << 2);
    else
      flag = NOT_FIRST_SEG | LAST_SEG | (cr << 2);

    /* compile the APDU message and send it to DL */

    dl_data_req->sdu.buf[0] = PD_RR_TI_0;
    dl_data_req->sdu.buf[1] = B_APPLIC_INFO;
    dl_data_req->sdu.buf[2] = (flag << 4 ) | RRLP_LCS;
    dl_data_req->sdu.buf[3] = (UBYTE)rem_seg;
    memcpy ( &dl_data_req->sdu.buf[4], buf, rem_seg );

    dl_data_req->sdu.l_buf = (4 + rem_seg) * BITS_PER_BYTE;
    dl_data_req->sdu.o_buf = 0;

    PSENDX ( DL, dl_data_req );
  }

  /* release RRRRLP_DATA_REQ */
  PFREE(rrrrlp_data_req);
#ifdef REL99
  /* Send RRLP procedure stop indication to MM*/
  {
    PALLOC (rr_rrlp_stop_ind, RR_RRLP_STOP_IND);
    PSENDX (MM, rr_rrlp_stop_ind);
  }
#endif
}
#endif /* FF_EOTD */

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : RR_DAT                     |
| STATE   : code                ROUTINE : att_mph_stop_dedicated_cnf        |
+--------------------------------------------------------------------+

  PURPOSE : Process the primitive MPH_STOP_DEDICATED_CNF received from L1
*/
GLOBAL void att_mph_stop_dedicated_cnf (T_MPH_STOP_DEDICATED_CNF * stop_cnf)
{
  GET_INSTANCE_DATA;
  PFREE(stop_cnf);
  TRACE_FUNCTION ("att_mph_stop_dedicated_cnf()");
  /*
   * Dedicated mode activity can be stopped in 3 cases
   *
   * - normal case :- Dedicated mode actvity has been stopped cleanly, without any errors.
   *                  Either a cell selection or a cell reselection (to the same cell) will take
   *                  place, depending on the timer T_DEDICATED_MODE.
   *
   * - failure :- Dedicated mode actvity has been stopped because of a radio link failure or a 
   *              data link failure. In this case cell re-selection must be started immediately.
   *
   * - CCO :- This is Applicable after RR has received a network cell change order
   */
  switch(GET_STATE (STATE_ATT))
  {
    case ATT_NULL:
    case ATT_CS1:
    case ATT_CS2:
      break;

    default:
#ifdef GPRS
      if( rr_data->mode_after_dedi EQ MODE_CELL_CHANGE_ORDER)
      {
        PALLOC (mph_bsic_req, MPH_BSIC_REQ);
        mph_bsic_req->arfcn = rr_data->gprs_data.arfcn;
        SET_STATE (STATE_ATT, ATT_IDLE);
        SET_STATE (STATE_CELL_SEL, CS_CCO);
        rr_data->mode_after_dedi = NOT_PRESENT_8BIT;
        PSENDX( PL, mph_bsic_req);
        return;
      } 
#endif
      if(! rr_data->net_lost )
      {
        /* Send Release indication to MM and go back to IDLE state */
        dat_release_connection();
      }
      else
      {
#ifdef GPRS
        att_start_cell_reselection_gprs (BACK_FROM_DEDICATED_RLF);
#else
        att_start_cell_reselection (BACK_FROM_DEDICATED_RLF);
#endif
      }
      break;
   } 
}
#endif