view src/g23m-gsm/dl/dl_drr.c @ 638:cab2f315827e

FFS dev.c: added Spansion PL032J to the "generic" table With the discovery of first GTM900 and then Tango, it now appears that Openmoko was not the only manuf after all who kept TI's TCS211 firmware largely intact (as opposed to changing it beyond all recognition like Compal, Chi-Mei and BenQ did), thus we are now getting new "alien" targets on which we reuse the original manuf's FFS with IMEI and RF calibration tables as if it were native. On these targets we use the original device table for FFS, even though we previously thought that it would never apply to any target other than dsample, leonardo and gtamodem. We have previously added Samsung K5L33xxCAM (a new kind of multi-ID device) to the generic table to support its use in Huawei GTM900-B modules; now we got news that some slightly older GTM900-B specimen used S71PL032J instead, so we are now adding PL032J as well.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 30 Jan 2020 17:45:48 +0000
parents 27a4235405c6
children
line wrap: on
line source

/*
+-----------------------------------------------------------------------------
|  Project :  GSM-PS
|  Modul   :  DL_DRR
+-----------------------------------------------------------------------------
|  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 distributing
|             all primitives of the upper layers.
+-----------------------------------------------------------------------------
*/

#ifndef DL_DRR_C
#define DL_DRR_C

#define ENTITY_DL

/*==== INCLUDES ===================================================*/
#include "typedefs.h"
#include <string.h>
#include "vsi.h"
#include "pconst.cdg"
#include "custom.h"
#include "gsm.h"
#include "mon_dl.h"
#include "prim.h"
#include "pei.h"
#include "tok.h"
#include "ccdapi.h"
#include "dl.h"
#include "dl_em.h"
#include "dl_trc.h"

/*==== EXPORT =====================================================*/

/*==== PRIVAT =====================================================*/
/*==== VARIABLES ==================================================*/
/*==== FUNCTIONS ==================================================*/
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : DL_DRR                     |
| STATE   : code                ROUTINE : drr_dl_establish_req       |
+--------------------------------------------------------------------+

  PURPOSE : Reception of a DL_ESTABLISH_REQ primitive.

*/

GLOBAL void drr_dl_establish_req (T_DL_ESTABLISH_REQ * est_req)
{
  BOOL fRelease;
  BOOL fInfoAvailable;
  GET_INSTANCE_DATA; 

  TRACE_FUNCTION ("drr_dl_establish_req()");

  if (est_req)
  {
    fRelease  = FALSE;
    fInfoAvailable  = (est_req->sdu.l_buf NEQ 0);

    TRACE_EVENT_WIN_P3 ("DL_ESTABLISH_REQ ch=%u SAPI=%u fInfoAvailable=%d",
      est_req->ch_type, est_req->sapi, fInfoAvailable);

    switch (est_req->ch_type)
    {
    case L2_CHANNEL_FACCH_F:
    case L2_CHANNEL_FACCH_H:
      if ((est_req->sapi EQ 0)/* AND (fInfoAvailable)*/)
      {
        dcch0_establish_req (est_req);
      }
      else
        fRelease = TRUE;
      break;
    case L2_CHANNEL_SACCH:
      if ((dl_data->RR_dedicated) AND (est_req->sapi EQ 3) AND (!fInfoAvailable))
      {
        dcch3_establish_req (est_req);
      }
      else
        fRelease = TRUE;
      break;
    case L2_CHANNEL_SDCCH:
      if ((est_req->sapi EQ 0)/* AND (fInfoAvailable)*/)
      {
        dcch0_establish_req (est_req);
      }
      else if ((est_req->sapi EQ 3) AND (!fInfoAvailable))
      {
        dcch3_establish_req (est_req);
      }
      else
        fRelease = TRUE;
      break;
    default:
      fRelease = TRUE;
      break;
    }/* endswitch */

    if (fRelease)
    {
      PREUSE (est_req, rel_ind, DL_RELEASE_IND);
#ifndef DL_2TO1
      rel_ind->cs = NOT_PRESENT_8BIT;
#else
      rel_ind->ps_cause.ctrl_value = CAUSE_is_from_dl;
      rel_ind->ps_cause.value.dl_cause = NOT_PRESENT_8BIT;
#endif /*DL_2TO1*/
      PSENDX (RR, rel_ind);
    }
  }
}

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

  PURPOSE : Send of a DL_ESTABLISH_IND primitive.

*/

GLOBAL void drr_dl_establish_ind (UBYTE ch_type,
                             UBYTE sapi, UBYTE indication)
{
  GET_INSTANCE_DATA;
#if defined(INVOKE_SIGNAL)
  if (dl_data->interrupt_context)
  {
    sig_invoke_drr_dl_establish_ind (ch_type, sapi, indication);
    return;
  }
  else
#endif  /* INVOKE_SIGNAL */
  {
    PALLOC (est_ind, DL_ESTABLISH_IND);

    TRACE_FUNCTION ("drr_dl_establish_ind()");

    est_ind->ch_type   = ch_type;
    est_ind->sapi      = sapi;
    est_ind->indication = indication;
    PSENDX (RR, est_ind);
  }
}

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

  PURPOSE : Reception of a DL_RESUME_REQ primitive.

*/

GLOBAL void drr_dl_resume_req (T_DL_RESUME_REQ * resume_req)
{
  TRACE_FUNCTION ("drr_dl_resume_req()");

  if (resume_req)
  {
    switch (resume_req->ch_type)
    {
    case L2_CHANNEL_FACCH_F:
    case L2_CHANNEL_FACCH_H:
    case L2_CHANNEL_SDCCH:
      dcch0_resume_req (resume_req);
      break;
    default:
      COM_FREE_POINTER (resume_req);
      break;
    }
  }
}

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

  PURPOSE : Reception of a DL_RECONNECT_REQ primitive.

*/

GLOBAL void drr_dl_reconnect_req (T_DL_RECONNECT_REQ * reconnect_req)
{
  TRACE_FUNCTION ("drr_dl_reconnect_req()");

  if (reconnect_req)
  {
    switch (reconnect_req->ch_type)
    {
    case L2_CHANNEL_FACCH_F:
    case L2_CHANNEL_FACCH_H:
    case L2_CHANNEL_SDCCH:
      dcch0_reconnect_req (reconnect_req);
      break;
    default:
      COM_FREE_POINTER (reconnect_req);
      break;
    }
  }
}

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

  PURPOSE : Reception of a DL_RELEASE_REQ primitive.

*/

GLOBAL void drr_dl_release_req (T_DL_RELEASE_REQ * release_req)
{
  TRACE_FUNCTION ("drr_dl_release_req()");


  if (release_req)
  {
    BOOL  bFree = TRUE;

#if !defined(LATE_LEAVING_DEDICATED)
    com_leave_dedicated (release_req->ch_type);
#endif  /* LATE_LEAVING_DEDICATED */

    switch (release_req->ch_type)
    {
    case L2_CHANNEL_FACCH_F:
    case L2_CHANNEL_FACCH_H:
    case L2_CHANNEL_SDCCH:
    case L2_CHANNEL_SACCH:

       DL_OFFLINE_TRACE (TRACE_DL_EVENT,
         release_req->sapi EQ PS_SAPI_0 ? C_DCCH0 : C_DCCH3,
         release_req->ch_type, "Release Req");

      if (release_req->sapi EQ PS_SAPI_0)
      {
        bFree = dcch0_release_req (release_req);
      }
      else if (release_req->sapi EQ PS_SAPI_3)
      {
        bFree = dcch3_release_req (release_req);
      }
      break;
    default:
      DL_OFFLINE_TRACE (TRACE_DL_EVENT, TRACE_CH_UNKNOWN, release_req->ch_type, "Release Req");
      break;
    }

    if (bFree)
    {
      COM_FREE_POINTER (release_req);
    }
  }
}
#ifndef DL_2TO1
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : DL_DRR                     |
| STATE   : code                ROUTINE : drr_mdl_release_req        |
+--------------------------------------------------------------------+

  PURPOSE : Reception of a MDL_RELEASE_REQ primitive.

*/

GLOBAL void drr_mdl_release_req (T_MDL_RELEASE_REQ * release_req)
{
  TRACE_FUNCTION ("drr_mdl_release_req()");

  if (release_req)
  {
    switch (release_req->sapi)
    {
    case DL_SAPI_0:
      dcch0_mdl_release_req ();
      break;
    case DL_SAPI_3:
      dcch3_mdl_release_req ();
      break;

    default:
      break;
    }
  }

  COM_FREE_POINTER (release_req);
}
#endif /* DL_2TO1*/
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)       MODULE  : DL_DRR                     |
| STATE   : code                ROUTINE : drr_dl_suspend_req         |
+--------------------------------------------------------------------+

  PURPOSE : Reception of a DL_SUSPEND_REQ primitive.

*/

GLOBAL void drr_dl_suspend_req (T_DL_SUSPEND_REQ * suspend_req)
{
  TRACE_FUNCTION ("drr_dl_suspend_req()");

  if (suspend_req)
  {

    switch (suspend_req->ch_type)
    {
    case L2_CHANNEL_FACCH_F:
    case L2_CHANNEL_FACCH_H:
    case L2_CHANNEL_SDCCH:
      dcch0_suspend_req (suspend_req);
      break;
    default:
      COM_FREE_POINTER (suspend_req);
      break;
    }


    DL_EM_LINK_SUSPENDED;

  }
}

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

  PURPOSE : Reception of a DL_DATA_REQ primitive.

*/

GLOBAL void drr_dl_data_req (T_DL_DATA_REQ * data_req)
{
  TRACE_FUNCTION ("drr_dl_data_req()");

  if (data_req)
  {
    switch (data_req->ch_type)
    {
    case L2_CHANNEL_FACCH_F:
    case L2_CHANNEL_FACCH_H:
    case L2_CHANNEL_SDCCH:
    case L2_CHANNEL_SACCH:
      if (data_req->sapi EQ 3)
      {
        dcch3_data_req (data_req);
      }
      else
      {
        dcch0_data_req (data_req);
      }
      break;

    default:
      COM_FREE_POINTER (data_req);
      break;
    }
  }

}

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

  PURPOSE : Send of a DL_DATA_IND primitive.

*/

GLOBAL void drr_dl_data_ind (UBYTE sapi, ULONG fn)
{
  GET_INSTANCE_DATA;
  TRACE_EVENT_WIN_P2 ("drr_dl_data_ind(,SAPI=%u): in_msg=%08x",
    sapi, (sapi EQ PS_SAPI_0) ? dl_data->dcch0_in_msg : dl_data->dcch3_in_msg);

  com_l3trace (TRACE_DOWNLINK, sapi,
    (UBYTE *)((sapi EQ PS_SAPI_0) ? dl_data->dcch0_in_msg : dl_data->dcch3_in_msg));

  TRACE_FUNCTION ("drr_dl_data_ind()");

  if (fn EQ NOT_PRESENT_32BIT)
    fn = dl_data->fn;

  if (sapi EQ PS_SAPI_0)
  {
    if (dl_data->dcch0_in_msg)
    {
      dl_data->dcch0_in_msg->fn  = fn;
      PSENDX (RR, dl_data->dcch0_in_msg);
      dl_data->dcch0_in_msg = NULL;
    }
    else
    {
      TRACE_EVENT_WIN ("dcch0_in_msg = NULL");
    }
  }
  else
  {
    if (dl_data->dcch3_in_msg)
    {
      dl_data->dcch3_in_msg->fn  = fn;
      PSENDX (RR, dl_data->dcch3_in_msg);
      dl_data->dcch3_in_msg = NULL;
    }
    else
    {
      TRACE_EVENT_WIN ("dcch3_in_msg = NULL");
    }
  }
}

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

  PURPOSE : Indicates the acknowledgement of an uplinked message by
            a DL_DATA_CNF primitive (only if it have been requested by L3).

*/

GLOBAL void drr_dl_data_cnf (UBYTE sapi)
{
  GET_INSTANCE_DATA;
#if defined(INVOKE_SIGNAL)
  if (dl_data->interrupt_context)
  {
    sig_invoke_drr_dl_data_cnf (sapi);
    return;
  }
  else
#endif  /* INVOKE_SIGNAL */
  {
    PALLOC (dl_data_cnf, DL_DATA_CNF);
    T_QUEUE * queue;

    TRACE_FUNCTION ("drr_dl_data_cnf()");

    if (sapi EQ PS_SAPI_0)
    {
      queue = &dl_data->dcch0_queue;
    }
    else
    {
      queue = &dl_data->dcch3_queue;
    }

    dl_data_cnf->ch_type = queue->sending_buffer->ch_type;
    dl_data_cnf->sapi = queue->sending_buffer->sapi;
    dl_data_cnf->cnf = queue->sending_buffer->cnf;
    PSENDX (RR, dl_data_cnf);

    COM_FREE_QUEUE_BUFFER (queue, INDEX_SENDING_BUFFER);
  }
}

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

  PURPOSE : Reception of a DL_UNITDATA_REQ primitive.

*/

GLOBAL void drr_dl_unitdata_req (T_DL_UNITDATA_REQ * unitdata_req)
{
  TRACE_FUNCTION ("drr_dl_unitdata_req()");

  if (unitdata_req)
  {
    GET_INSTANCE_DATA; 
    /*lint -e420 (Warning -- Apparent access beyond array) */
    memcpy (&dl_data->sacch_act_buffer, &unitdata_req->sdu, sizeof (T_FRAME));
    /*lint +e420 (Warning -- Apparent access beyond array) */
    dl_data->sacch_mode = 0;

    COM_FREE_POINTER (unitdata_req);
  }
}


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

  PURPOSE : Send of a DL_UNITDATA_IND primitive.

*/

GLOBAL void drr_dl_unitdata_ind (UBYTE error_flag, UBYTE * layer1head,
                                 UBYTE * layer3msg, UBYTE length, ULONG fn)
{
  GET_INSTANCE_DATA; 
#define UNITDATA_OFFSET 1
#if 0 /* happens in primitive context only */
#if defined(INVOKE_SIGNAL)
  if (dl_data->interrupt_context)
  {
    sig_invoke_drr_dl_unitdata_ind (dl_data, error_flag, layer1head, layer3msg, length, fn);
    return;
  }
#endif  /* INVOKE_SIGNAL */
#endif  /* 0 */

  TRACE_FUNCTION ("drr_dl_unitdata_ind()");

  /* limit length of UI frame, because they could be invalid */
  if (length > DL_N201_SACCH_A_B)
    length = DL_N201_SACCH_A_B;

  if ((layer3msg AND length) OR (error_flag NEQ VALID_BLOCK))
  {
    PALLOC_SDU (unitdata_ind, DL_UNITDATA_IND,
      (USHORT)(((USHORT)length + UNITDATA_OFFSET) * BITS_PER_BYTE));

    unitdata_ind->error_flag = error_flag;
    unitdata_ind->pwr_lev = layer1head[0];
    unitdata_ind->ta = layer1head[1];
    unitdata_ind->sdu.o_buf = UNITDATA_OFFSET * BITS_PER_BYTE;
    unitdata_ind->sdu.l_buf = length * BITS_PER_BYTE;
    memset (&unitdata_ind->sdu.buf[0], 0, UNITDATA_OFFSET);
#ifdef DL_2TO1
    /* build a pseudo length octet (for check in RR rr_msg_accept_sacch_normal) */
    unitdata_ind->sdu.buf[UNITDATA_OFFSET-1] = (length << 2) | 0x01;
#endif /* DL_2TO1 */
    if (error_flag EQ VALID_BLOCK)
      /*lint -e668 (Warning -- Possibly passing a null pointer) */
      /*lint -e669 (Warning -- Possible data overrun) */
      memcpy (&unitdata_ind->sdu.buf[UNITDATA_OFFSET], layer3msg, length);
      /*lint +e669 (Warning -- Possible data overrun) */
      /*lint +e668 (Warning -- Possibly passing a null pointer) */


    if (fn EQ NOT_PRESENT_32BIT)
      fn = dl_data->fn;
    unitdata_ind->fn  = fn;

    if (error_flag NEQ VALID_BLOCK)
    {
      DL_OFFLINE_TRACE(TRACE_DL_EVENT, C_DCCH0, L2_CHANNEL_SACCH, "inv UNITDATA_IND");
    }
    else
    {
      com_l3trace (TRACE_UACK_DN, L2_CHANNEL_SACCH, layer3msg);
    }

    PSENDX (RR, unitdata_ind);
  }

#undef UNITDATA_OFFSET
}


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

  PURPOSE : Reception of a DL_SHORT_UNITDATA_REQ primitive.

*/

GLOBAL void drr_dl_short_unitdata_req (T_DL_SHORT_UNITDATA_REQ * short_unitdata_req)
{
  TRACE_FUNCTION ("drr_dl_short_unitdata_req()");

  if (short_unitdata_req)
  {
    GET_INSTANCE_DATA; 
    /*lint -e420 (Warning -- Apparent access beyond array) */
    /*lint -e420 (Warning -- Apparent access beyond array) */
    memcpy (&dl_data->rr_short_pd_buffer, &short_unitdata_req->sdu, sizeof (T_FRAME));
    /*lint +e420 (Warning -- Apparent access beyond array) */
#ifndef DL_2TO1
    dl_data->rr_short_pd_ch_type = short_unitdata_req->ch_type;
#else
    dl_data->rr_short_pd_ch_type = short_unitdata_req->l2_channel;
#endif

    COM_FREE_POINTER (short_unitdata_req);
  }
}


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

  PURPOSE : Send of a DL_SHORT_UNITDATA_IND primitive.

*/

GLOBAL void drr_dl_short_unitdata_ind (UBYTE ch_type,
                                UBYTE error_flag, UBYTE * layer1head,
                                UBYTE * layer3msg, UBYTE length, ULONG fn)
{
  GET_INSTANCE_DATA;
#define SHORT_UNITDATA_OFFSET 1
#if defined(INVOKE_SIGNAL)
    if (dl_data->interrupt_context)
    {
      sig_invoke_drr_dl_short_unitdata_ind (ch_type, error_flag,
        layer1head, layer3msg, length, fn);
      return;
    }
#endif  /* INVOKE_SIGNAL */

  TRACE_FUNCTION ("drr_dl_short_unitdata_ind()");

  if (layer3msg)
  {
    PALLOC_SDU (short_unitdata_ind, DL_SHORT_UNITDATA_IND,
      (USHORT)((length + SHORT_UNITDATA_OFFSET) * BITS_PER_BYTE));

    short_unitdata_ind->ch_type = ch_type;
    short_unitdata_ind->error_flag = error_flag;
    if (ch_type EQ L2_CHANNEL_SACCH)
    {
      short_unitdata_ind->pwr_lev = layer1head[0];
      short_unitdata_ind->ta = layer1head[1];
    }
    else
    {
      short_unitdata_ind->pwr_lev = 0;
      short_unitdata_ind->ta = 0;
    }
    short_unitdata_ind->sdu.o_buf = SHORT_UNITDATA_OFFSET * BITS_PER_BYTE;
    short_unitdata_ind->sdu.l_buf = length * BITS_PER_BYTE;
    memset (&short_unitdata_ind->sdu.buf[0], 0, SHORT_UNITDATA_OFFSET);
    memcpy (&short_unitdata_ind->sdu.buf[SHORT_UNITDATA_OFFSET], layer3msg, length);

    if (fn EQ NOT_PRESENT_32BIT)
      fn = dl_data->fn;
    short_unitdata_ind->fn  = fn;
    if (error_flag NEQ VALID_BLOCK)
    {
      DL_OFFLINE_TRACE(TRACE_DL_EVENT, C_DCCH0, ch_type, "inv SHORT_UNITDATA_IND");
    }
    else
    {
      com_l3trace (TRACE_UACK_DN, ch_type, layer3msg);
    }
    PSENDX (RR, short_unitdata_ind);
  }

#undef SHORT_UNITDATA_OFFSET
}


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

  PURPOSE : Send of a DL_ESTABLISH_CNF primitive.

*/

GLOBAL void drr_dl_establish_cnf (UBYTE ch_type, UBYTE sapi)
{
  GET_INSTANCE_DATA;
#if defined(INVOKE_SIGNAL)
  if (dl_data->interrupt_context)
  {
    sig_invoke_drr_dl_establish_cnf (ch_type, sapi);
    return;
  }
  else
#endif  /* INVOKE_SIGNAL */
  {
    PALLOC (dl_establish_cnf, DL_ESTABLISH_CNF);

    TRACE_FUNCTION ("drr_dl_establish_cnf()");
    dl_establish_cnf->ch_type = ch_type;
    dl_establish_cnf->sapi    = sapi;
    dl_establish_cnf->indication = sapi EQ PS_SAPI_0 ?
                                   dl_data->dcch0_unserved : dl_data->dcch3_unserved;
    PSENDX (RR, dl_establish_cnf);

    DL_EM_CHANNEL_ESTABLISHMENT_PASSED;

    if (!dl_data->RR_dedicated)
    {
      /* first uplink on SACCH after the first establishment is an empty frame */
      if (sapi EQ PS_SAPI_0)
      {
        /* the SAPI value of the next SACCH frame depends on the next awaiting frame */
        TRACE_EVENT_WIN_P1 ("sacch_last_uplink_sapi:=%u->3", dl_data->sacch_last_uplink_sapi);
        dl_data->sacch_last_uplink_sapi = NOT_PRESENT_8BIT;
      }

      /* RR is entering the dedicated mode */
      dl_data->RR_dedicated = TRUE;
      DL_OFFLINE_TRACE(TRACE_DL_EVENT, sapi EQ PS_SAPI_0 ? C_DCCH0 : C_DCCH3,
                       ch_type, "RR_dedicated:=TRUE");
    }
  }
}/* endfunc drr_dl_establish_cnf */

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

  PURPOSE : Send of a DL_RELEASE_IND primitive.

*/

GLOBAL void drr_dl_release_ind (UBYTE ch_type,
                            UBYTE sapi, UBYTE cs, BOOL init)
{
  GET_INSTANCE_DATA;
#if defined(INVOKE_SIGNAL)
  if (dl_data->interrupt_context)
  {
    sig_invoke_drr_dl_release_ind (ch_type, sapi, cs, init);
    return;
  }
  else
#endif  /* INVOKE_SIGNAL */
  {
    PALLOC (dl_release_ind, DL_RELEASE_IND);/* T_DL_RELEASE_IND */

    TRACE_FUNCTION ("drr_dl_release_ind()");

    dl_release_ind->ch_type  = ch_type;
    dl_release_ind->sapi     = sapi;
#ifndef DL_2TO1
    dl_release_ind->cs = cs;
#else
    dl_release_ind->ps_cause.ctrl_value = CAUSE_is_from_dl;
    dl_release_ind->ps_cause.value.dl_cause = cs;
#endif /*DL_2TO1*/

#if defined (DL_TRACE_ENABLED)
    switch (ch_type)
    {
      case L2_CHANNEL_FACCH_F:
      case L2_CHANNEL_FACCH_H:
      case L2_CHANNEL_SDCCH:
        DL_OFFLINE_TRACE (TRACE_DL_EVENT,
          sapi EQ PS_SAPI_0 ? C_DCCH0 : C_DCCH3, ch_type, "Release Ind");
        break;
      case L2_CHANNEL_SACCH:
        DL_OFFLINE_TRACE (TRACE_DL_EVENT, sapi EQ PS_SAPI_0 ? C_DCCH0 : C_DCCH3, ch_type,
          sapi EQ PS_SAPI_0 ? "Release Ind" : "Release Ind SAPI=3");
        break;
    }
#endif /* DL_TRACE_ENABLED */

#if defined(DELAYED_RELEASE_IND)
    {
      GET_INSTANCE_DATA; 
      dl_data->release_ind_ch_type    = NOT_PRESENT_8BIT;
    }
#endif  /* DELAYED_RELEASE_IND */
    PSENDX (RR, dl_release_ind);

    if (init)
    {
      if (sapi EQ DL_SAPI_0)
      {
        dcch0_init_dl_data ();/* reset data link layer for SAPI=0 and 3 */
      }
      else if  (sapi EQ DL_SAPI_3)
      {
        dcch3_init_dl_data ();/* reset data link layer for SAPI=3 only */
      }
    }
  }

}/* endfunc drr_dl_release_ind */

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

  PURPOSE : Send of a DL_RELEASE_CNF primitive.

*/

GLOBAL void drr_dl_release_cnf (UBYTE ch_type,
                            UBYTE sapi, BOOL init)
{
  GET_INSTANCE_DATA;
#if defined(INVOKE_SIGNAL)
  if (dl_data->interrupt_context)
  {
    sig_invoke_drr_dl_release_cnf (ch_type, sapi, init);
    return;
  }
  else
#endif  /* INVOKE_SIGNAL */
  {
    PALLOC (dl_release_cnf, DL_RELEASE_CNF);

    TRACE_FUNCTION ("drr_dl_release_cnf()");
    dl_release_cnf->ch_type = ch_type;
    dl_release_cnf->sapi    = sapi;

    DL_EM_LINK_RELEASE;

    PSENDX (RR, dl_release_cnf);

    if (init)
    {
      if (sapi EQ DL_SAPI_0)
      {
        dcch0_init_dl_data ();/* reset data link layer for SAPI=0 and 3 */
      }
      else if  (sapi EQ DL_SAPI_3)
      {
        dcch3_init_dl_data ();/* reset data link layer for SAPI=3 only */
      }
    }
  }
}/* endfunc drr_dl_release_cnf */

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

   PURPOSE : Release after error.

*/

GLOBAL void drr_error_ind (UBYTE ch_type, UBYTE sapi)
{
  GET_INSTANCE_DATA;
#if defined(INVOKE_SIGNAL)
  if (dl_data->interrupt_context)
  {
    sig_invoke_drr_error_ind (ch_type, sapi);
    return;
  }
#endif  /* INVOKE_SIGNAL */

  TRACE_FUNCTION ("drr_error_ind()");
  DL_OFFLINE_TRACE (TRACE_DL_EVENT, TRACE_CH_UNKNOWN, ch_type, "error_ind ");

  /*
   * not a real error indication, instead a release ind to RR and release req for myself
   */
  drr_dl_release_ind (ch_type, sapi, NOT_PRESENT_8BIT, FALSE);
  if (((sapi EQ DL_SAPI_0) AND (dl_data->state[C_DCCH0] > STATE_IDLE_DL))
      OR
      ((sapi EQ DL_SAPI_3) AND (dl_data->state[C_DCCH3] > STATE_IDLE_DL)))
  {
    PALLOC (release_req, DL_RELEASE_REQ);
    release_req->ch_type = ch_type;
    release_req->sapi = sapi;
    release_req->mode = DL_NORMAL_RELEASE;
    drr_dl_release_req (release_req);
  }
}

#endif /* DL_DRR_C */