view src/g23m-gprs/sndcp/sndcp_mgf.c @ 268:f2e52cab0a73

abb_inth.c: check all interrupt causes, not just one The original code used if - else if - else if etc constructs, thus the first detected interrupt was the only one handled. However, Iota ITSTATREG is a clear-on-read register, thus if we only handle the first detected interrupt and skip checking the others, then the other interrupts will be lost, if more than one interrupt happened to occur in one ABB interrupt handling cycle - a form of rare race condition. Change the code to check all interrupts that were read in this cycle.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 13 Jun 2021 18:17:53 +0000
parents fa8dc04885d8
children
line wrap: on
line source

/*
+-----------------------------------------------------------------------------
|  Project :  GPRS (8441)
|  Modul   :  sndcp_mgf.c
+-----------------------------------------------------------------------------
|  Copyright 2002 Texas Instruments Berlin, AG
|                 All rights reserved.
|
|                 This file is confidential and a trade secret of Texas
|                 Instruments Berlin, AG
|                 The receipt of or possession of this file does not convey
|                 any rights to reproduce or disclose its contents or to
|                 manufacture, use, or sell anything it may describe, in
|                 whole, or in part, without the specific written consent of
|                 Texas Instruments Berlin, AG.
+-----------------------------------------------------------------------------
|  Purpose :  This modul is part of the entity SNDCP and implements all
|             procedures and functions as described in the
|             SDL-documentation (MG-statemachine)
+-----------------------------------------------------------------------------
*/


#define ENTITY_SNDCP

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

#include "typedefs.h"    /* to get Condat data types */
#include "vsi.h"        /* to get a lot of macros */
#include "macdef.h"
#include "gsm.h"        /* to get a lot of macros */
#include "prim.h"       /* to get the definitions of used SAP and directions */

#include "dti.h"

#include "sndcp.h"        /* to get the global entity definitions */
#include "sndcp_f.h"       /* to get the functions to access the global arrays*/

#include "sndcp_cias.h"    /* to get the signals to service cia */
#include "sndcp_nds.h"    /* to get the signals to service nd */
#include "sndcp_nus.h"    /* to get the signals to service nu */
#include "sndcp_nuf.h"    
#include "sndcp_sus.h"    /* to get the signals to service su */
#include "sndcp_suas.h"    /* to get the signals to service su */
#include "sndcp_sds.h"    /* to get the signals to service sd */
#include "sndcp_sdas.h"    /* to get the signals to service sda */

#include "sndcp_mgf.h"      /* to get ths file */
#include "sndcp_nup.h"      /* nu_sn_[unit]data_req is called from
                               sig_callback().*/

#include <string.h>

/*==== CONST ================================================================*/

/*==== LOCAL VARS ===========================================================*/

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

LOCAL void mg_get_sapi_dcomp_dntt (UBYTE sapi, UBYTE dcomp, UBYTE* dntt);

LOCAL void mg_get_sapi_dntt_nsapi (UBYTE sapi, UBYTE dntt, UBYTE nsapi, BOOL* used);

LOCAL void mg_get_sapi_dntt_state (UBYTE sapi, UBYTE dntt, UBYTE* state);

LOCAL void mg_get_sapi_dcomp_state (UBYTE sapi, UBYTE dcomp, UBYTE* stat);

LOCAL void mg_get_sapi_pcomp_state (UBYTE sapi, UBYTE pcomp, UBYTE* stat);

LOCAL void mg_get_sapi_pntt_state (UBYTE sapi, UBYTE pntt, UBYTE* state);

LOCAL void mg_set_sapi_dntt_nsapi (UBYTE sapi, UBYTE dntt, UBYTE nsapi, BOOL used);

LOCAL void mg_set_sapi_dcomp_state (UBYTE sapi, UBYTE dcomp, UBYTE stat);

LOCAL void mg_set_sapi_dcomp_dntt (UBYTE sapi, UBYTE dcomp, UBYTE dntt);

LOCAL void mg_set_sapi_dntt_rej (UBYTE sapi, UBYTE dntt, BOOL rej);

LOCAL void mg_set_sapi_dntt_state (UBYTE sapi, UBYTE dntt, UBYTE state);

LOCAL void mg_set_sapi_pntt_nsapi (UBYTE sapi, UBYTE pntt, UBYTE nsapi, BOOL used);

LOCAL void mg_set_sapi_pcomp_state (UBYTE sapi, UBYTE pcomp, UBYTE stat);

LOCAL void mg_set_sapi_pcomp_pntt (UBYTE sapi, UBYTE pcomp, UBYTE pntt);

LOCAL void mg_set_sapi_pntt_rej (UBYTE sapi, UBYTE pntt, BOOL rej);

LOCAL void mg_set_sapi_pntt_state (UBYTE sapi, UBYTE pntt, UBYTE state);

/*
+------------------------------------------------------------------------------
| Function    : mg_get_sapi_dcomp_dntt
+------------------------------------------------------------------------------
| Description : The procedures indicates the dntt assigned to a given dcomp
|               for a given sapi.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN dcomp UBYTE,
|               IN/OUT dntt UBYTE
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_get_sapi_dcomp_dntt (UBYTE sapi, UBYTE dcomp, UBYTE* dntt)
{
  TRACE_FUNCTION( "mg_get_sapi_dcomp_dntt" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    *dntt = sndcp_data->mg.sapi_dcomp_dntt_ra[sapi_index][dcomp];
  }
} /* mg_get_sapi_dcomp_dntt() */

/*
+------------------------------------------------------------------------------
| Function    : mg_get_sapi_dntt_nsapi
+------------------------------------------------------------------------------
| Description : The procedure informs if a given nsapi uses a given dntt on a
|               given sapi.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN dntt UBYTE,
|               IN nsapi UBYTE,
|               IN/OUT used BOOL
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_get_sapi_dntt_nsapi (UBYTE sapi, UBYTE dntt, UBYTE nsapi, BOOL* used)
{
  TRACE_FUNCTION( "mg_get_sapi_dntt_nsapi" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    *used = sndcp_data->mg.sapi_dntt_nsapi_set_ra[sapi_index][dntt][nsapi];
  }
} /* mg_get_sapi_dntt_nsapi() */

/*
+------------------------------------------------------------------------------
| Function    : mg_get_sapi_dcomp_state
+------------------------------------------------------------------------------
| Description : The procedures informs about the state of a given dcomp on a
|               given SAPI.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN dcomp UBYTE,
|               IN/OUT stat UBYTE
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_get_sapi_dcomp_state (UBYTE sapi, UBYTE dcomp, UBYTE* stat)
{
  TRACE_FUNCTION( "mg_get_sapi_dcomp_state" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    *stat = sndcp_data->mg.sapi_dcomp_state_ra[sapi_index][dcomp];
  }
} /* mg_get_sapi_dcomp_state() */

/*
+------------------------------------------------------------------------------
| Function    : mg_get_sapi_dntt_state
+------------------------------------------------------------------------------
| Description : The procedures informs about the state of a given data
|               compression entity on a given SAPI.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN dntt UBYTE,
|               IN/OUT state UBYTE
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_get_sapi_dntt_state (UBYTE sapi, UBYTE dntt, UBYTE* state)
{
  TRACE_FUNCTION( "mg_get_sapi_dntt_state" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    *state = sndcp_data->mg.sapi_dntt_state_ra[sapi_index][dntt];
  }



} /* mg_get_sapi_dntt_state() */

/*
+------------------------------------------------------------------------------
| Function    : mg_get_sapi_pcomp_state
+------------------------------------------------------------------------------
| Description : The procedures informs about the state of a given pcomp on a
|               given SAPI.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN pcomp UBYTE,
|               IN/OUT stat UBYTE
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_get_sapi_pcomp_state (UBYTE sapi, UBYTE pcomp, UBYTE* stat)
{
  TRACE_FUNCTION( "mg_get_sapi_pcomp_state" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    *stat = sndcp_data->mg.sapi_pcomp_state_ra[sapi_index][pcomp];
  }
} /* mg_get_sapi_pcomp_state() */

/*
+------------------------------------------------------------------------------
| Function    : mg_get_sapi_pntt_state
+------------------------------------------------------------------------------
| Description : The procedures informs about the state of a given header
|               compression entity on a given SAPI.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN pntt UBYTE,
|               IN/OUT state UBYTE
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_get_sapi_pntt_state (UBYTE sapi, UBYTE pntt, UBYTE* state)
{
  TRACE_FUNCTION( "mg_get_sapi_pntt_state" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    *state = sndcp_data->mg.sapi_pntt_state_ra[sapi_index][pntt];
  }
} /* mg_get_sapi_pntt_state() */




/*
+------------------------------------------------------------------------------
| Function    : mg_check_sense_bitwise
+------------------------------------------------------------------------------
| Description : Checks, if "small" is bitwise smaller than or equal to "big"
|
| Parameters  : USHORT small, big, BOOL wrong is set to TRUE, if small > big
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_ushort_sense_bitwise (USHORT small,
                                    USHORT big,
                                    BOOL* wrong) {
  UBYTE bit = 0;
  TRACE_FUNCTION( "mg_check_sense_bitwise" );
  *wrong = TRUE;
  for (bit = 0; bit < 8 * sizeof(USHORT); bit++) {
    if ((small & (1 << bit)) > (big & (1 << bit))) {
      return;
    }
  }
  *wrong = FALSE;
} /* mg_check_sense_bitwise() */

/*
+------------------------------------------------------------------------------
| Function    : mg_check_sense_bitwise
+------------------------------------------------------------------------------
| Description : Checks, if "small" is bitwise smaller than "big"
|
| Parameters  : UBYTE small, big, BOOL wrong is set to TRUE, if small > big
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_ubyte_sense_bitwise (UBYTE small,
                                    UBYTE big,
                                    BOOL* wrong) {
  UBYTE bit = 0;
  TRACE_FUNCTION( "mg_check_sense_bitwise" );
  *wrong = TRUE;
  for (bit = 0; bit < 8 * sizeof(UBYTE); bit++) {
    if ((small & (1 << bit)) > (big & (1 << bit))) {
      return;
    }
  }
  *wrong = FALSE;
} /* mg_check_sense_bitwise() */

/*
+------------------------------------------------------------------------------
| Function    : mg_decode_v42
+------------------------------------------------------------------------------
| Description : decodes the v42 part of given sdu to given xid block
|
| Parameters  : source sdu,
|               index in sdu,
|               field index in sdu (sub index in compression fields,
|               destination xid block,
|               success ok
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_decode_v42 (T_sdu* sdu,
                           USHORT* index,
                           USHORT* field_index,
                           T_XID_BLOCK* xid_block,
                           BOOL* ok,
                           UBYTE p_bit) {
#define CHECK_XID_BUFFER_LEN2 if (*index + *field_index >= ((sdu->l_buf) >> 3)) return

  USHORT field_length = 0;
  TRACE_FUNCTION( "mg_decode_v42" );
  *ok = FALSE;

  /*
   * Set field_index to length of field octet.
   */
  (*field_index)++;
  CHECK_XID_BUFFER_LEN2;
  field_length = sdu->buf[*index + *field_index];
  /*
   * NSAPIS parameter and followers omitted?
   */
  if (p_bit == SNDCP_P_BIT_1) {
    if (field_length == MG_DATA_P_1_NSAPIS_OM) {
      *ok = TRUE;
      return;
    }
  } else {
    if (field_length == MG_DATA_P_0_NSAPIS_OM) {
      *ok = TRUE;
      return;
    }
  }
  /*
   * If p bit set to 1, set field_index to dcomp field.
   */
  if (p_bit == SNDCP_P_BIT_1) {
    (*field_index)++;
    CHECK_XID_BUFFER_LEN2;
    xid_block->v42.dcomp =
      ((USHORT)sdu->buf[*index + *field_index]) >> 4;
  }
  /*
   * Set field_index to MSB of applicable nsapis short.
   */
  (*field_index)++;
  CHECK_XID_BUFFER_LEN2;
  xid_block->v42.nsapis =
    ((USHORT)sdu->buf[*index + *field_index]) << 8;
  xid_block->v42.nsapis_set = TRUE;
  /*
   * Set field_index to LSB of applicable nsapis short.
   */
  (*field_index)++;
  CHECK_XID_BUFFER_LEN2;
  xid_block->v42.nsapis +=
    ((USHORT)sdu->buf[*index + *field_index]);
  /*
   * P0 parameter and followers omitted?
   */
  if (p_bit == SNDCP_P_BIT_1) {
    if (field_length == MG_DATA_P_1_P0_OM) {
      *ok = TRUE;
      return;
    }
  } else {
    if (field_length == MG_DATA_P_0_P0_OM) {
      *ok = TRUE;
      return;
    }
  }
  /*
   * Set field_index to p0.
   */
  (*field_index)++;
  CHECK_XID_BUFFER_LEN2;
  xid_block->v42.p0 =
    sdu->buf[*index + *field_index];
  xid_block->v42.p0_set = TRUE;
  /*
   * P1 parameter and followers omitted?
   */
  if (p_bit == SNDCP_P_BIT_1) {
    if (field_length == MG_DATA_P_1_P1_OM) {
      *ok =TRUE;
      return;
    }
  } else {
    if (field_length == MG_DATA_P_0_P1_OM) {
      *ok =TRUE;
      return;
    }
  }
  /*
   * Set field_index to MSB of p1.
   */
  (*field_index)++;
  CHECK_XID_BUFFER_LEN2;
  xid_block->v42.p1 =
    ((USHORT)sdu->buf[*index + *field_index]) << 8;
  xid_block->v42.p1_set = TRUE;
  /*
   * Set field_index to LSB of p1.
   */
  (*field_index)++;
  CHECK_XID_BUFFER_LEN2;
  xid_block->v42.p1 +=
    ((USHORT)sdu->buf[*index + *field_index]);
  /*
   * P2 parameter and followers omitted?
   */
  if (p_bit == SNDCP_P_BIT_1) {
    if (field_length == MG_DATA_P_1_P2_OM) {
      *ok = TRUE;
      return;
    }
  } else {
    if (field_length == MG_DATA_P_0_P2_OM) {
      *ok = TRUE;
      return;
    }
  }
  /*
   * Set field_index to p2.
   */
  (*field_index)++;
  CHECK_XID_BUFFER_LEN2;
  xid_block->v42.p2 =
    sdu->buf[*index + *field_index];
  xid_block->v42.p2_set = TRUE;

  /*
   * If length of v42 field is longer than specified, ignore the rest.
   */
  while (*field_index < field_length) {
    CHECK_XID_BUFFER_LEN2;
    (*field_index)++;
  }

  *ok = TRUE;

} /* mg_decode_v42() */

/*
+------------------------------------------------------------------------------
| Function    : mg_decode_vj
+------------------------------------------------------------------------------
| Description : decodes the vj part of given sdu to given xid block
|
| Parameters  : source sdu,
|               index in sdu,
|               field index in sdu (sub index in compression fields,
|               destination xid block,
|               success ok
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_decode_vj (T_sdu* sdu,
                           USHORT* index,
                           USHORT* field_index,
                           T_XID_BLOCK* xid_block,
                           BOOL* ok,
                           UBYTE p_bit) {
#define CHECK_XID_BUFFER_LEN3 if (*index + *field_index >= ((sdu->l_buf) >> 3)) return

  USHORT field_length = 0;
  TRACE_FUNCTION( "mg_decode_vj" );

  /*
   * Set field_index to length of field octet.
   */
  (*field_index)++;
  CHECK_XID_BUFFER_LEN3;
  field_length = sdu->buf[*index + *field_index];
  /*
   * NSAPIS parameter and followers omitted?
   */
  if (p_bit == SNDCP_P_BIT_1) {
    if (field_length == MG_HEADER_P_1_NSAPIS_OM) {
      *ok = TRUE;
      return;
    }
  } else {
    if (field_length == MG_HEADER_P_0_NSAPIS_OM) {
      *ok = TRUE;
      return;
    }
  }
  /*
   * If p bit set to 1, set field_index to dcomp field.
   */
  if (p_bit == SNDCP_P_BIT_1) {
    (*field_index)++;
    CHECK_XID_BUFFER_LEN3;
    xid_block->vj.pcomp1 =
      ((USHORT)sdu->buf[*index + *field_index]) >> 4;
    xid_block->vj.pcomp2 =
      ((USHORT)sdu->buf[*index + *field_index]) & 0xf;
  }

  /*
   * Set field_index to MSB of applicable nsapis short.
   */
  (*field_index)++;
  CHECK_XID_BUFFER_LEN3;
  xid_block->vj.nsapis =
    ((USHORT)sdu->buf[*index + *field_index]) << 8;
  xid_block->vj.nsapis_set = TRUE;
  /*
   * Set field_index to LSB of applicable nsapis short.
   */
  (*field_index)++;
  CHECK_XID_BUFFER_LEN3;
  xid_block->vj.nsapis +=
    ((USHORT)sdu->buf[*index + *field_index]);
  /*
   * S0_M_1 parameter omitted?
   */
  if (p_bit == SNDCP_P_BIT_1) {
    if (field_length == MG_HEADER_P_1_S0_M_1_OM) {
      *ok = TRUE;
      return;
    }
  } else {
    if (field_length == MG_HEADER_P_0_S0_M_1_OM) {
      *ok = TRUE;
      return;
    }
  }
  /*
   * Set field_index to "s0 - 1" Parameter
   */
  (*field_index)++;
  CHECK_XID_BUFFER_LEN3;
  xid_block->vj.s0_m_1 = sdu->buf[*index + *field_index];
  xid_block->vj.s0_m_1_set = TRUE;

  /*
   * If length of vj field is longer than specified, ignore the rest.
   */
  while (*field_index < field_length) {
    CHECK_XID_BUFFER_LEN3;
    (*field_index)++;
  }


  *ok = TRUE;

} /* mg_decode_vj() */

/*
+------------------------------------------------------------------------------
| Function    : mg_detect_mode_clash
+------------------------------------------------------------------------------
| Description : Unacknowledged and acknowledged contexts may not share the same
| compressor entity. This procdure detects possible violations of that rule.
|
| Parameters  : the set of nsapis given as USHORT bit mask,
|               violation detected, TRUE if at least 1 acknowledged and 1
|               unacknowledged context share the same compressor.
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_detect_mode_clash (USHORT nsapis, BOOL* vio)
{
  UBYTE nsapi = 0;
  BOOL unack_found = FALSE;
  BOOL ack_found = FALSE;
  BOOL ack = FALSE;
  TRACE_FUNCTION( "mg_detect_mode_clash" );
  /*
   * Find affected nsapis.
   */
  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
    if ((nsapis & (1 << nsapi)) > 0) {
      sndcp_get_nsapi_ack(nsapi, &ack);
      if (ack) {
        ack_found = TRUE;
      } else {
        unack_found = TRUE;
      }
    }
  }
  *vio = unack_found && ack_found;


} /* mg_detect_mode_clash() */


/*
+------------------------------------------------------------------------------
| Function    : mg_respond_if_nec
+------------------------------------------------------------------------------
| Description : All nsapis connected to the given sapi
|               that are in state MG_ACT are sent an
|               SNSM_ACTIVATE_RES.
|
| Parameters  : sapi
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_respond_if_nec (UBYTE sapi) {
  UBYTE nsapi = 0;
  UBYTE sapi_index = 0;
#ifdef SNDCP_UPM_INCLUDED
  BOOL ack = FALSE;
#endif /* SNDCP_UPM_INCLUDED */

  TRACE_FUNCTION( "mg_respond_if_nec" );

  sndcp_get_sapi_index(sapi, &sapi_index);
  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
    USHORT nsapi_state = MG_IDLE;
    USHORT sapi_state = MG_IDLE;
    UBYTE local_sapi = 0;
    sndcp_get_nsapi_state(nsapi, &nsapi_state);
    sndcp_get_nsapi_sapi(nsapi, &local_sapi);
    sndcp_get_sapi_state(local_sapi, &sapi_state);
    if (((nsapi_state & MG_ACT) > 0)
        &&
        ((sapi_state & MG_XID) == 0)
        &&
        ((sapi_state & MG_EST) == 0)
        &&
        (local_sapi == sapi)) {

      /*
       * Open DTI connection.
       */
#ifndef SNDCP_UPM_INCLUDED
      mg_dti_open(nsapi);
#else 
      sndcp_get_nsapi_ack(nsapi, &ack);
      if (ack) {
        nu_ready_ind_if_nec(nsapi);
      } else {
        nu_unitready_ind_if_nec(nsapi);
      }
#endif

      mg_send_snsm_activate_res(nsapi);
      /*
       * Set nsapi state to MG_IDLE.
       */
      sndcp_unset_nsapi_state (nsapi, MG_ACT);
    }

    if (((nsapi_state & MG_DEACT) > 0)
        &&
        ((sapi_state & MG_XID) == 0)
        &&
        ((sapi_state & MG_REL) == 0)
        &&
        (local_sapi == sapi)) {

#ifdef SNDCP_UPM_INCLUDED 
      PALLOC(snsm_deactivate_res, SN_DEACTIVATE_CNF);
#else
      PALLOC(snsm_deactivate_res, SNSM_DEACTIVATE_RES);
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
      /*
       * Now the NSAPI is not in use anymore:
       */
      sndcp_set_nsapi_used(nsapi, FALSE);
      sndcp_set_nsapi_ack(nsapi, FALSE);

      snsm_deactivate_res->nsapi = nsapi;
      sndcp_unset_nsapi_state(nsapi, MG_DEACT);
#ifdef SNDCP_UPM_INCLUDED
      PSEND(hCommUPM, snsm_deactivate_res);
#else
      PSEND(hCommSM, snsm_deactivate_res);
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
    }

  }

} /* mg_respond_if_nec */



/*
+------------------------------------------------------------------------------
| Function    : mg_set_ntt_comp
+------------------------------------------------------------------------------
| Description : Sets ntt and comp values acc. to req_xid_block.
|
| Parameters  : UBYTE sapi, BOOL is this a renegotiation?
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_set_ntt_comp (UBYTE sapi) {
  UBYTE sapi_index = 0;
  UBYTE nsapi = 0;
  TRACE_FUNCTION( "mg_set_ntt_comp" );
  sndcp_get_sapi_index(sapi, &sapi_index);

  if (sndcp_data->mg.req_xid_block[sapi_index].v42.is_set) {
    mg_set_sapi_dntt_state(sapi,
                          sndcp_data->mg.req_xid_block[sapi_index].v42.ntt,
                          MG_SELECTED);
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      if ((sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis & (1 << nsapi))
           > 0) {
        mg_set_sapi_dntt_nsapi(sapi,
                               sndcp_data->mg.req_xid_block[sapi_index].v42.ntt,
                               nsapi,
                               TRUE);
      }
    }
    mg_set_sapi_dcomp_state(sapi,
                            sndcp_data->mg.req_xid_block[sapi_index].v42.dcomp,
                            MG_SELECTED);
    mg_set_sapi_dcomp_dntt(sapi,
                           sndcp_data->mg.req_xid_block[sapi_index].v42.dcomp,
                           sndcp_data->mg.req_xid_block[sapi_index].v42.ntt);
  }
  if (sndcp_data->mg.req_xid_block[sapi_index].vj.is_set) {
    mg_set_sapi_pntt_state(sapi,
                          sndcp_data->mg.req_xid_block[sapi_index].vj.ntt,
                          MG_SELECTED);
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      if ((sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis & (1 << nsapi))
           > 0) {
        mg_set_sapi_pntt_nsapi(sapi,
                               sndcp_data->mg.req_xid_block[sapi_index].vj.ntt,
                               nsapi,
                               TRUE);
      }
    }
    mg_set_sapi_pcomp_state(sapi,
                            sndcp_data->mg.req_xid_block[sapi_index].vj.pcomp1,
                            MG_SELECTED);
    mg_set_sapi_pcomp_state(sapi,
                            sndcp_data->mg.req_xid_block[sapi_index].vj.pcomp2,
                            MG_SELECTED);
    mg_set_sapi_pcomp_pntt(sapi,
                           sndcp_data->mg.req_xid_block[sapi_index].vj.pcomp1,
                           sndcp_data->mg.req_xid_block[sapi_index].vj.ntt);
    mg_set_sapi_pcomp_pntt(sapi,
                           sndcp_data->mg.req_xid_block[sapi_index].vj.pcomp2,
                           sndcp_data->mg.req_xid_block[sapi_index].vj.ntt);
  }


} /* mg_set_ntt_comp() */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_sapi_dntt_nsapi
+------------------------------------------------------------------------------
| Description : The procedure  stores the info that a given nsapi uses a given
|               dntt on a given sapi.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN dntt UBYTE,
|               IN nsapi UBYTE,
|               IN used BOOL
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_set_sapi_dntt_nsapi (UBYTE sapi, UBYTE dntt, UBYTE nsapi, BOOL used)
{
  TRACE_FUNCTION( "mg_set_sapi_dntt_nsapi" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    sndcp_data->mg.sapi_dntt_nsapi_set_ra[sapi_index][dntt][nsapi] = used;
  }
} /* mg_set_sapi_dntt_nsapi() */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_sapi_dcomp_state
+------------------------------------------------------------------------------
| Description : The procedures sets the state of a given dcomp on a given SAPI.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN dcomp UBYTE,
|               IN stat UBYTE
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_set_sapi_dcomp_state (UBYTE sapi, UBYTE dcomp, UBYTE stat)
{
  TRACE_FUNCTION( "mg_set_sapi_dcomp_state" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    sndcp_data->mg.sapi_dcomp_state_ra[sapi_index][dcomp] = stat;
  }
} /* mg_set_sapi_dcomp_state() */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_sapi_dcomp_dntt
+------------------------------------------------------------------------------
| Description : The procedures sets the dntt assigned to a given dcomp
|               for a given sapi.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN dcomp UBYTE,
|               IN dntt UBYTE
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_set_sapi_dcomp_dntt (UBYTE sapi, UBYTE dcomp, UBYTE dntt)
{
  TRACE_FUNCTION( "mg_set_sapi_dcomp_dntt" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    sndcp_data->mg.sapi_dcomp_dntt_ra[sapi_index][dcomp] = dntt;
  }
} /* mg_set_sapi_dcomp_dntt() */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_sapi_dntt_rej
+------------------------------------------------------------------------------
| Description : The procedures stores if a given data
|               compression entity on a given SAPI is to be rejected in
|               LL_XID_REQ because it cannot be set up.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN dntt UBYTE,
|               IN rej BOOL
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_set_sapi_dntt_rej (UBYTE sapi, UBYTE dntt, BOOL rej)
{
  TRACE_FUNCTION( "mg_set_sapi_dntt_rej" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    sndcp_data->mg.sapi_dntt_rej_ra[sapi_index][dntt] = rej;
  }
} /* mg_set_sapi_dntt_rej() */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_sapi_dntt_state
+------------------------------------------------------------------------------
| Description : The procedures sets the state of a given data
|               compression entity on a given SAPI.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN dntt UBYTE,
|               IN state UBYTE
| Note        : sapi dntt rej will be set ti FALSE if state is UNASSIGNED
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_set_sapi_dntt_state (UBYTE sapi, UBYTE dntt, UBYTE state)
{
  TRACE_FUNCTION( "mg_set_sapi_dntt_state" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    sndcp_data->mg.sapi_dntt_state_ra[sapi_index][dntt] = state;

    if (state == MG_UNASSIGNED) {
      mg_set_sapi_dntt_rej(sapi, dntt, FALSE);
    }
  }
} /* mg_set_sapi_dntt_state() */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_sapi_pntt_nsapi
+------------------------------------------------------------------------------
| Description : The procedure  stores the info that a given nsapi uses a given
|               pntt on a given sapi.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN pntt UBYTE,
|               IN nsapi UBYTE,
|               IN used BOOL
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_set_sapi_pntt_nsapi (UBYTE sapi, UBYTE pntt, UBYTE nsapi, BOOL used)
{
  TRACE_FUNCTION( "mg_set_sapi_pntt_nsapi" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    sndcp_data->mg.sapi_pntt_nsapi_set_ra[sapi_index][pntt][nsapi] = used;
  }
} /* mg_set_sapi_pntt_nsapi() */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_sapi_pcomp_state
+------------------------------------------------------------------------------
| Description : The procedures sets the state of a given pcomp on a given SAPI.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN pcomp UBYTE,
|               IN stat UBYTE
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_set_sapi_pcomp_state (UBYTE sapi, UBYTE pcomp, UBYTE stat)
{
  TRACE_FUNCTION( "mg_set_sapi_pcomp_state" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    sndcp_data->mg.sapi_pcomp_state_ra[sapi_index][pcomp] = stat;
  }
} /* mg_set_sapi_pcomp_state() */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_sapi_pcomp_pntt
+------------------------------------------------------------------------------
| Description : The procedures sets the pntt assigned to a given pcomp
|               for a given sapi.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN pcomp UBYTE,
|               IN pntt UBYTE
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_set_sapi_pcomp_pntt (UBYTE sapi, UBYTE pcomp, UBYTE pntt)
{
  TRACE_FUNCTION( "mg_set_sapi_pcomp_pntt" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    sndcp_data->mg.sapi_pcomp_pntt_ra[sapi_index][pcomp] = pntt;
  }
} /* mg_get_sapi_pcomp_pntt() */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_sapi_pntt_rej
+------------------------------------------------------------------------------
| Description : The procedures stores if a given data
|               compression entity on a given SAPI is to be rejected in
|               LL_XID_REQ because it cannot be set up.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN pntt UBYTE,
|               IN rej BOOL
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_set_sapi_pntt_rej (UBYTE sapi, UBYTE pntt, BOOL rej)
{
  TRACE_FUNCTION( "mg_set_sapi_pntt_rej" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    sndcp_data->mg.sapi_pntt_rej_ra[sapi_index][pntt] = rej;
  }
} /* mg_set_sapi_pntt_rej() */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_sapi_pntt_state
+------------------------------------------------------------------------------
| Description : The procedures sets the state of a given header
|               compression entity on a given SAPI.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN pntt UBYTE,
|               IN state UBYTE
| Note        : sapi pntt rej will be set ti FALSE if state is UNASSIGNED
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_set_sapi_pntt_state (UBYTE sapi, UBYTE pntt, UBYTE state)
{
  TRACE_FUNCTION( "mg_set_sapi_pntt_state" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    sndcp_data->mg.sapi_pntt_state_ra[sapi_index][pntt] = state;

    if (state == MG_UNASSIGNED) {
      mg_set_sapi_pntt_rej(sapi, pntt, FALSE);
    }
  }
} /* mg_set_sapi_pntt_state() */

#ifndef NCONFIG 
/*
+------------------------------------------------------------------------------
| Function    : mg_config_delay
+------------------------------------------------------------------------------
| Description : after config prim DELAY each new context activation will be
|               computed with a delay.
|
| Parameters  : delay in milliseconds
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_config_delay (USHORT millis)
{

  TRACE_FUNCTION("mg_config_delay");

  sndcp_data->millis = millis;

} /* mg_config_delay() */
#endif


/*
+------------------------------------------------------------------------------
| Function    : mg_reset_compressors
+------------------------------------------------------------------------------
| Description : All compressors used by this nsapi are reset.
|
| Parameters  : nsapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_reset_compressors (UBYTE nsapi)
{
  BOOL compressed = FALSE;
  TRACE_FUNCTION( "mg_reset_compressors" );

  sndcp_is_nsapi_data_compressed(nsapi, &compressed);
  if (compressed) {
    /*
     * Must be added when data compression is added.
     */
  }

  sndcp_is_nsapi_header_compressed(nsapi, &compressed);
  if (compressed) {
    UBYTE sapi = 0;
    UBYTE sapi_index = 0;
    /*
     * This is implementation dependent and only works as long as only 1
     * header compressor is used in cia service.
     */
    sndcp_get_nsapi_sapi(nsapi, &sapi);
    sndcp_get_sapi_index(sapi, &sapi_index);
    sig_mg_cia_new_xid(&sndcp_data->mg.cur_xid_block[sapi_index]);
  }

} /* mg_reset_compressors() */



/*
+------------------------------------------------------------------------------
| Function    : mg_reset_comp_ack
+------------------------------------------------------------------------------
| Description : all compression entities using
|               acknowledged peer-to-peer LLC operation on this SAPI are reset.
|
| Parameters  : sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_reset_comp_ack (UBYTE sapi) {
  UBYTE nsapi = 0;
  TRACE_FUNCTION( "mg_reset_comp_ack" );
  /*
   * All nsapis at this sapi that use ack mode reset their compressors.
   */
  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi ++) {
    UBYTE s = 0;
    BOOL ack = FALSE;
    BOOL used = FALSE;
    sndcp_is_nsapi_used(nsapi, &used);
    if (!used) {
      continue;
    }
    sndcp_get_nsapi_sapi(nsapi, &s);
    sndcp_get_nsapi_ack(nsapi, &ack);
    if (ack && s == sapi) {
      mg_reset_compressors(nsapi);
    }
  } /* for all nsapis */

} /* mg_reset_comp_ack() */


/*
+------------------------------------------------------------------------------
| Function    : mg_reset_states_n_rej
+------------------------------------------------------------------------------
| Description : Resets all states for ntts and p/dcomp to "unassigned".
|               Resets the arrays with information on rejcted entities.
|
| Parameters  : index of the affected sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_reset_states_n_rej (UBYTE sapi_index)
{

  UBYTE ntt = 0;
  UBYTE nsapi = 0;
  UBYTE dcomp = 0;
  UBYTE pcomp = 0;
  TRACE_FUNCTION( "mg_reset_states_n_rej" );

  for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) {
    sndcp_data->mg.sapi_dntt_state_ra[sapi_index][ntt] = MG_UNASSIGNED;
    sndcp_data->mg.sapi_pntt_state_ra[sapi_index][ntt] = MG_UNASSIGNED;
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      sndcp_data->mg.sapi_dntt_nsapi_set_ra[sapi_index][ntt][nsapi] = FALSE;
      sndcp_data->mg.sapi_pntt_nsapi_set_ra[sapi_index][ntt][nsapi] = FALSE;
    }
    sndcp_data->mg.sapi_dntt_rej_ra[sapi_index][ntt] = FALSE;
    sndcp_data->mg.sapi_pntt_rej_ra[sapi_index][ntt] = FALSE;
  }
  for (dcomp = 0; dcomp < MG_MAX_DCOMP; dcomp++) {
    sndcp_data->mg.sapi_dcomp_state_ra[sapi_index][dcomp] = MG_UNASSIGNED;
  }
  for (pcomp = 0; pcomp < MG_MAX_PCOMP; pcomp++) {
    sndcp_data->mg.sapi_pcomp_state_ra[sapi_index][pcomp] = MG_UNASSIGNED;
  }
  /*
   * sapi_dcomp_dntt_ra, sapi_pcomp_pntt_ra not initialized.
   */

} /* mg_reset_states_n_rej() */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_xid_nsapis
+------------------------------------------------------------------------------
| Description : AN LL_XID_IND has delivered a desired set of nsapis for
| a V42.bis or VJ compressor entity. Now this is compared to a possibly
| already existing set of nsapis connected to the given entity.
| Also the rules in GSM 4.65, 6.8.x are checked.
|
| Parameters  : a flag telling if we work on V42 or VanJacobson 'nsapis':
|            MG_XID_V42_NSAPIS or MG_XID_VJ_NSAPIS.
|            affected sapi,
|
+------------------------------------------------------------------------------
*/
LOCAL void mg_set_xid_nsapis (UBYTE sapi, UBYTE p_type)
{
  USHORT* cur_nsapis = 0;
  USHORT* ind_nsapis = 0;
  USHORT* res_nsapis = 0;
  BOOL* ind_nsapis_set = NULL;
  UBYTE sapi_index = 0;
  UBYTE* p_bit = NULL;
  UBYTE ntt_state = MG_UNASSIGNED;
  U8 nsapi = 0;
  U8 s0_m_1_min = 0;


  TRACE_FUNCTION( "mg_set_xid_nsapis" );

  sndcp_get_sapi_index(sapi, &sapi_index);

  /*
   * V42.bis or VanJacobson?
   */
  if (p_type == MG_XID_V42_NSAPIS) {
    cur_nsapis = &(sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis);
    ind_nsapis = &(sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis);
    res_nsapis = &(sndcp_data->mg.res_xid_block[sapi_index].v42.nsapis);
    ind_nsapis_set =
      &(sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis_set);
    p_bit = &(sndcp_data->mg.ind_xid_block[sapi_index].v42.p_bit);

    *res_nsapis = 0;
    /*
     * Only those nsapis will be set in the response for which the user
     * requested compression. 
     * Note: te other params are not yet set, must be implemented later.
     */
    sndcp_data->mg.res_xid_block[sapi_index].v42.nsapis_set = FALSE;
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      if ((((1 << nsapi) & sndcp_data->mg.user_xid_block[nsapi].v42.nsapis) > 
           0) && 
           (((1 << nsapi) & 
            sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis) > 0)) {

        *res_nsapis |= (1 << nsapi);
        sndcp_data->mg.res_xid_block[sapi_index].v42.nsapis_set = TRUE;

      }
    } /* for nsapi */

  } else {
    cur_nsapis = &(sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis);
    ind_nsapis = &(sndcp_data->mg.ind_xid_block[sapi_index].vj.nsapis);
    res_nsapis = &(sndcp_data->mg.res_xid_block[sapi_index].vj.nsapis);
    ind_nsapis_set =
      &(sndcp_data->mg.ind_xid_block[sapi_index].vj.nsapis_set);
    p_bit = &(sndcp_data->mg.ind_xid_block[sapi_index].vj.p_bit);

    *res_nsapis = 0;
    /*
     * Only those nsapis will be set in the response for which the user
     * requested compression. 
     * In the same loop we set the s0_m_1 to the minimum of
     * the indicated value and the values requested by the user.
     * Also the direction is set to the minimum of all requested
     * directions.
     */
    if (sndcp_data->mg.ind_xid_block[sapi_index].vj.s0_m_1 > 0) {
      s0_m_1_min = sndcp_data->mg.ind_xid_block[sapi_index].vj.s0_m_1;
    } else if (sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1 > 0) {
      s0_m_1_min = sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1;
    } else {
      s0_m_1_min = SNDCP_VJ_DEFAULT_S0_M_1;
    }
 #ifdef SNDCP_UPM_INCLUDED 
    sndcp_data->mg.res_xid_block[sapi_index].vj.direction = 
      NAS_HCOMP_BOTH_DIRECT;
#else
    sndcp_data->mg.res_xid_block[sapi_index].vj.direction = 
      SNSM_COMP_BOTH_DIRECT;
#endif 
    
    sndcp_data->mg.res_xid_block[sapi_index].vj.nsapis_set = FALSE;
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      if (((1 << nsapi) & sndcp_data->mg.user_xid_block[nsapi].vj.nsapis) > 
          0 && 
           (((1 << nsapi) & 
            sndcp_data->mg.ind_xid_block[sapi_index].vj.nsapis) > 0)) {

        *res_nsapis |= (1 << nsapi);
        sndcp_data->mg.res_xid_block[sapi_index].vj.nsapis_set = TRUE;
        if (sndcp_data->mg.user_xid_block[nsapi].vj.s0_m_1 < s0_m_1_min) {
          s0_m_1_min = sndcp_data->mg.user_xid_block[nsapi].vj.s0_m_1;
        }
        sndcp_data->mg.res_xid_block[sapi_index].vj.direction &=
          sndcp_data->mg.user_xid_block[nsapi].vj.direction;
      }
    } /* for nsapi */
    sndcp_data->mg.res_xid_block[sapi_index].vj.s0_m_1 = s0_m_1_min;
    if (s0_m_1_min > 0) {
      sndcp_data->mg.res_xid_block[sapi_index].vj.s0_m_1_set = TRUE;
    } else {
      sndcp_data->mg.res_xid_block[sapi_index].vj.direction = 0;
    }
  }

    

  /*
   * Rules in GSM 4.65, 6.8.1: acknowledged and unacknowlegded contexts may not
   * share the same compressor. If that is demanded by the indication, reset
   * nsapis parameter to the ones currently used.
   */
  if (*ind_nsapis_set &&
      *ind_nsapis > 0) {
    BOOL vio = FALSE;
    mg_detect_mode_clash(*ind_nsapis, &vio);
    if (!vio) {
      /*
       * Modes are the same, set cur to res.
       */
      *cur_nsapis = *res_nsapis;
    } else {
      *res_nsapis = *cur_nsapis;
    }
  }

  /*
   * Also from 6.8.3: If an unassigned entity number is included with the
   * p bit set to 0, then the Applicable NSAPIs field shall be set to 0.
   */
  if (p_type == MG_XID_V42_NSAPIS) {
    mg_get_sapi_dntt_state
      (sapi, sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt, &ntt_state);
  } else {
    mg_get_sapi_pntt_state
      (sapi, sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt, &ntt_state);
  }
  if (ntt_state == MG_UNASSIGNED && *p_bit == 0) {
      *cur_nsapis = 0;
      *res_nsapis = 0;
  }

} /* mg_set_xid_nsapis() */


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


/*
+------------------------------------------------------------------------------
| Function    : mg_check_cnf_xid
+------------------------------------------------------------------------------
| Description : The confirmation of a requested XID negotiation has been
|               received. The answer is now checked.
|               A main issue is the comparison with the service variable
|               req_xid_block which holds the requested xid block sent to the
|               network.
|               Detected errors:
| - SNDCP version number not correct
| - incorrect entity number (must be proposed one)
| - incorrect sense of negotiation for each parameter (down mainly,
|   NSAPI down bitwise)
| - an entity is included in the cnf that was not requested, does not exist
| Not checked:
| - out of range value of parameters (must be in range if sense ofnegotiation was right.
| - parameters with duplicated instances.
| If one of these errors occurs ret is set to MG_XID_BAD_CONTENT, else
| MG_XID_OK.
|
| Parameters  : ret, affected sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_check_cnf_xid (UBYTE* ret, UBYTE sapi)
{
  UBYTE sapi_index = 0;
  BOOL wrong = FALSE;
  TRACE_FUNCTION( "mg_check_cnf_xid" );
  sndcp_get_sapi_index(sapi, &sapi_index);
  *ret = MG_XID_BAD_CONTENT;
  /*
   * Check SNDCP version.
   */
  if (sndcp_data->mg.cnf_xid_block[sapi_index].version_set) {
    if (sndcp_data->mg.cnf_xid_block[sapi_index].version !=
        SNDCP_XID_VERSION) {
      return;
    }
  }
  /*
   * If an entity is included that has not been requested / does not exist:
   * bad content!
   */
  if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.is_set &&
      ! sndcp_data->mg.req_xid_block[sapi_index].v42.is_set &&
      ! sndcp_data->mg.cur_xid_block[sapi_index].v42.is_set) {

    return;
  }
  if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.is_set &&
      ! sndcp_data->mg.req_xid_block[sapi_index].vj.is_set &&
      ! sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) {

    return;
  }

  /*
   * Check V42 parameters, if they are set.
   */
  if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.is_set) {
    if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p_bit == 1) {
      return;
    }
    if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.ntt !=
        sndcp_data->mg.req_xid_block[sapi_index].v42.ntt) {
      return;
    }
    /*
     * Sense of negotiation. If cnf value has been set, but req has not been
     * set then cnf value will be compared with cur value. This
     * is not applied to "applicable nsapis".
     */
    if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.nsapis_set) {
      if (sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis_set) {
        mg_ushort_sense_bitwise
          (sndcp_data->mg.cnf_xid_block[sapi_index].v42.nsapis,
           sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis,
           &wrong);
      }
      if (wrong) {
        return;
      }
    }
    if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p0_set) {
      if (sndcp_data->mg.req_xid_block[sapi_index].v42.p0_set) {
        mg_ubyte_sense_bitwise(sndcp_data->mg.cnf_xid_block[sapi_index].v42.p0,
                               sndcp_data->mg.req_xid_block[sapi_index].v42.p0,
                               &wrong);
      } else {
        mg_ubyte_sense_bitwise(sndcp_data->mg.cnf_xid_block[sapi_index].v42.p0,
                               sndcp_data->mg.cur_xid_block[sapi_index].v42.p0,
                               &wrong);
      }
      if (wrong) {
        return;
      }
    }
    if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p1_set) {
      if (sndcp_data->mg.req_xid_block[sapi_index].v42.p1_set) {
        if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p1 >
          sndcp_data->mg.req_xid_block[sapi_index].v42.p1) {
          return;
        }
      } else {
        if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p1 >
          sndcp_data->mg.cur_xid_block[sapi_index].v42.p1) {
          return;
        }
      }
    }
    if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p2_set) {
      if (sndcp_data->mg.req_xid_block[sapi_index].v42.p2_set) {
        if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p2 >
          sndcp_data->mg.req_xid_block[sapi_index].v42.p2) {
          return;
        }
      } else {
        if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p2 >
          sndcp_data->mg.cur_xid_block[sapi_index].v42.p2) {
          return;
        }
      }
    }
  }
  /*
   * Check VJ parameters, if they are set.
   */
  if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.is_set) {
    if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.p_bit == 1) {
      return;
    }
    if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.ntt !=
        sndcp_data->mg.req_xid_block[sapi_index].vj.ntt) {
      return;
    }
    /*
     * Sense of negotiation.
     */
    if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.nsapis_set) {
      if (sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis_set) {
        mg_ushort_sense_bitwise(sndcp_data->mg.cnf_xid_block[sapi_index].vj.nsapis,
                                sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis,
                                &wrong);
      }
      if (wrong) {
        return;
      }
    }
    if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.s0_m_1_set) {
      if (sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1_set) {
        if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.s0_m_1 >
          sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1) {
          return;
        }
      } else {
        if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.s0_m_1 >
          sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1) {
          return;
        }
      }
    }
  }
  *ret = MG_XID_OK;

} /* mg_check_cnf_xid() */

/*
+------------------------------------------------------------------------------
| Function    : mg_check_ind_xid
+------------------------------------------------------------------------------
| Description : Service variable ind_xid_block holds the xid block indicated
| by the peer. The ind_xid_block is now checked: (from 4.65 6.8.2).
| Criterium 1:
| If the indicated ntt is already used and pcomp or dcomp values are different,
| ret is set to MG_XID_BAD_CONTENT.
| Criterium 2:
| If the indicated algorithm type is already used and pcomp or dcomp values
| are different, ret is set to MG_XID_BAD_CONTENT.
|
| Note: implementation dependent: if data compression is proposed, it will
| be rejected.
|
| Otherwise ret is set to MG_XID_OK.
| Parameters  : ret, affected sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_check_ind_xid (UBYTE* ret, UBYTE sapi)
{
  UBYTE sapi_index = 0;
  UBYTE status = MG_UNASSIGNED;
  TRACE_FUNCTION( "mg_check_ind_xid" );
  sndcp_get_sapi_index(sapi, &sapi_index);
  *ret = MG_XID_OK;

  /*
   * Check criterium 1.
   */
  if (sndcp_data->mg.ind_xid_block[sapi_index].v42.is_set &&
      sndcp_data->mg.ind_xid_block[sapi_index].v42.p_bit == SNDCP_P_BIT_1) {
    mg_get_sapi_dntt_state
      (sapi, sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt, &status);
    if (status == MG_ASSIGNED) {
      /*
       * Entity already used. DCOMP values differ?
       */
      mg_get_sapi_dcomp_state
        (sapi, sndcp_data->mg.ind_xid_block[sapi_index].v42.dcomp, &status);
      if (status != MG_ASSIGNED) {
        /*
         * The indicated dcomp is not assigned. Error.
         */
        mg_set_sapi_dntt_rej(sapi,
                             sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt,
                             TRUE);
        *ret = MG_XID_BAD_CONTENT;
      } else {
        UBYTE dntt = 0;
        mg_get_sapi_dcomp_dntt
          (sapi, sndcp_data->mg.ind_xid_block[sapi_index].v42.dcomp, &dntt);
        if (dntt != sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt) {
          /*
           * Dcomp values differ, Error.
           */
          mg_set_sapi_dntt_rej(sapi,
                               sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt,
                               TRUE);
          *ret = MG_XID_BAD_CONTENT;
        }
      }
    }
  }
  if (sndcp_data->mg.ind_xid_block[sapi_index].vj.is_set &&
      sndcp_data->mg.ind_xid_block[sapi_index].vj.p_bit == SNDCP_P_BIT_1) {
    mg_get_sapi_pntt_state
      (sapi, sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt, &status);
    if (status == MG_ASSIGNED) {
      /*
       * Entity already used. PCOMP values differ?
       */
      /*
       * PCOMP 1.
       */
      mg_get_sapi_pcomp_state
        (sapi, sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp1, &status);
      if (status != MG_ASSIGNED) {
        /*
         * The indicated pcomp is not assigned. Error.
         */
        mg_set_sapi_pntt_rej(sapi,
                             sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt,
                             TRUE);
        *ret = MG_XID_BAD_CONTENT;
      } else {
        UBYTE pntt = 0;
        mg_get_sapi_pcomp_pntt
          (sapi, sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp1, &pntt);
        if (pntt != sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt) {
          /*
           * Pcomp values differ, Error.
           */
          mg_set_sapi_pntt_rej(sapi,
                               sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt,
                               TRUE);
          *ret = MG_XID_BAD_CONTENT;
        }
      }
      /*
       * PCOMP 2.
       */
      mg_get_sapi_pcomp_state
        (sapi, sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp1, &status);
      if (status != MG_ASSIGNED) {
        /*
         * The indicated pcomp is not assigned. Error.
         */
        mg_set_sapi_pntt_rej(sapi,
                             sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt,
                             TRUE);
        *ret = MG_XID_BAD_CONTENT;
      } else {
        UBYTE pntt = 0;
        mg_get_sapi_pcomp_pntt
          (sapi, sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp1, &pntt);
        if (pntt != sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt) {
          /*
           * Dcomp values differ, Error.
           */
          mg_set_sapi_pntt_rej(sapi,
                               sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt,
                               TRUE);
          *ret = MG_XID_BAD_CONTENT;
        }
      }
    }
  }

  /*
   * Check criterium 2.
   * Since in the current implementation there is only SNDCP_XID_VJ and
   * SNDCP_XID_V42, and only 1 instance of each,
   * it will be sufficient to compare the proposed values for pcomp/dcomp
   * with the ones in cur_xid_block.
   * An error may only occur if cur and ind are set.
   */
  if (sndcp_data->mg.ind_xid_block[sapi_index].v42.is_set &&
      sndcp_data->mg.cur_xid_block[sapi_index].v42.is_set &&
      sndcp_data->mg.ind_xid_block[sapi_index].v42.p_bit == SNDCP_P_BIT_1) {
    if (sndcp_data->mg.ind_xid_block[sapi_index].v42.dcomp !=
      sndcp_data->mg.cur_xid_block[sapi_index].v42.dcomp) {
      mg_set_sapi_dntt_rej(sapi,
                           sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt,
                           TRUE);
      *ret = MG_XID_BAD_CONTENT;
    }
  }
  if (sndcp_data->mg.ind_xid_block[sapi_index].vj.is_set &&
      sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set &&
      sndcp_data->mg.ind_xid_block[sapi_index].v42.p_bit == SNDCP_P_BIT_1) {
    if (sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp1 !=
      sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp1) {
      mg_set_sapi_pntt_rej(sapi,
                           sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt,
                           TRUE);
      *ret = MG_XID_BAD_CONTENT;
    }
    if (sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp2 !=
      sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp2) {
      mg_set_sapi_pntt_rej(sapi,
                           sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt,
                           TRUE);
      *ret = MG_XID_BAD_CONTENT;
    }
  }

#ifndef TI_PS_FF_V42BIS
  /*
   * Implementation dependent: If data compression is proposed, reject it!
   */
  if (sndcp_data->mg.ind_xid_block[sapi_index].v42.is_set) {
    mg_set_sapi_dntt_rej(sapi,
                         sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt,
                         TRUE);
  }
#endif /* !TI_PS_FF_V42BIS */
} /* mg_check_ind_xid() */


/*
+------------------------------------------------------------------------------
| Function    : mg_clean_xid
+------------------------------------------------------------------------------
| Description : Cleans up the XID organizing arrays for nsapis and ntts
|
| Parameters  :
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_clean_xid (UBYTE sapi) {
  UBYTE nsapi = 0;
  UBYTE sapi_index = 0;
  UBYTE stat = MG_UNASSIGNED;
  TRACE_FUNCTION( "mg_clean_xid" );
  sndcp_get_sapi_index(sapi, &sapi_index);


  /*
   * NSAPIs that were assigned to a compressor unit but are not any more.
   */
  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
    BOOL connected =
      ((1 << nsapi) & (sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis)) > 0;
    mg_set_sapi_dntt_nsapi(sapi,
                           sndcp_data->mg.cur_xid_block[sapi_index].v42.ntt,
                           nsapi,
                           connected);
    connected =
      ((1 << nsapi) & (sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis)) > 0;
    mg_set_sapi_pntt_nsapi(sapi,
                           sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt,
                           nsapi,
                           connected);


  }

  /*
   * Formerly assigned ntts that are now unassigned are cleaned.
   * Implemented here: the one dntt and the one pntt in cur_xid_block are now
   * checked. If they are in state MG_ASSIGNED but the affected 'nsapis'
   * element is set to all '0' then the entities enter state MG_UNASSIGNED,
   * all nsapis re set to FALSE in the sapi_?ntt_nsapi_ra, all
   * affected pcomp/dcomp values are set to MG_UNASSIGNED.
   */
  mg_get_sapi_dntt_state(sapi,
                         sndcp_data->mg.cur_xid_block[sapi_index].v42.ntt,
                         &stat);
  if (stat == MG_ASSIGNED &&
      sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis == 0) {
    /*
     * Reset dntt state.
     */
    mg_set_sapi_dntt_state(sapi,
                           sndcp_data->mg.cur_xid_block[sapi_index].v42.ntt,
                           MG_UNASSIGNED);

    /*
     * reset nsapi connections.
     */
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      mg_set_sapi_dntt_nsapi(sapi,
                             sndcp_data->mg.cur_xid_block[sapi_index].v42.ntt,
                             nsapi,
                             FALSE);
    }
    /*
     * Reset dcomp.
     */
    mg_set_sapi_dcomp_state(sapi,
                            sndcp_data->mg.cur_xid_block[sapi_index].v42.dcomp,
                            MG_UNASSIGNED);
  }


  /*
   * The same for header compresion.
   */
  mg_get_sapi_pntt_state(sapi,
                         sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt,
                         &stat);
  if (stat == MG_ASSIGNED &&
      sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis == 0) {
    /*
     * Reset pntt state.
     */
    mg_set_sapi_pntt_state(sapi,
                           sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt,
                           MG_UNASSIGNED);
    /*
     * reset nsapi connections.
     */
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      mg_set_sapi_pntt_nsapi(sapi,
                             sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt,
                             nsapi,
                             FALSE);
    }
    /*
     * Reset pcomps.
     */
    mg_set_sapi_pcomp_state(sapi,
                            sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp1,
                            MG_UNASSIGNED);
    mg_set_sapi_pcomp_state(sapi,
                            sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp2,
                            MG_UNASSIGNED);
  }



} /* mg_clean_xid() */

/*
+------------------------------------------------------------------------------
| Function    : mg_col_no_re
+------------------------------------------------------------------------------
| Description : The function mg_col_no_re represents  the SDL label
|               COL_NO_RE: an LL_ESTABLISH_IND has been received, we do
|               have a collision situation like given in [GSM 4.65, 6.2.1.4],
|               we do not have a re-establishment situation.
|
| Parameters  : the received LL_ESTABLISH_IND
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_col_no_re (T_LL_ESTABLISH_IND* ll_establish_ind)
{
  TRACE_FUNCTION( "mg_col_no_re" );

  /*
   * Resume data transfer suspended due to pending establishment;
   */
  sig_mg_su_resume(ll_establish_ind->sapi);
  sig_mg_sua_resume(ll_establish_ind->sapi);
  mg_resume_affected_nus(ll_establish_ind->sapi);

  /*
   * Now proceed like without collision.
   */
  mg_no_col_no_re(ll_establish_ind);


} /* mg_col_no_re() */


/*
+------------------------------------------------------------------------------
| Function    : mg_col_re
+------------------------------------------------------------------------------
| Description : The function mg_col_re represents  the SDL label
|               COL_RE: an LL_ESTABLISH_IND has been received, we do
|               have a collision situation like given in [GSM 4.65, 6.2.1.4],
|               we do have a re-establishment situation.
|
| Parameters  : the received LL_ESTABLISH_IND
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_col_re (T_LL_ESTABLISH_IND* ll_establish_ind)
{
  TRACE_FUNCTION( "mg_col_re" );
  /*
   * Resume data transfer suspended due to pending establishment;
   */
  sig_mg_su_resume(ll_establish_ind->sapi);
  sig_mg_sua_resume(ll_establish_ind->sapi);
  mg_resume_affected_nus(ll_establish_ind->sapi);
  /*
   * Now proceed like without collision.
   */
  mg_no_col_re(ll_establish_ind);
} /* mg_col_re() */

/*
+------------------------------------------------------------------------------
| Function    : mg_decode_xid
+------------------------------------------------------------------------------
| Description : Implementation dependent.
|               The entity number
|               Works only for algorithm types 0
|               (V42 for data and VanJacobson for header).
|               This procedure reads the given xid block (in form of an sdu)
|               and writes the fields to the given xid_block variable, if
|               compression fields for algorithms 0 (V42 or VanJacobson) are
|               given.
|               If the parsed sdu starts a negotiation then the p bit will be
|               set to 1 and the "algorithm type" field will be included. If
|               the parsed sdu ends a negotiation then the p bit will be set
|               to 0 and the "algorithm type" field will not be included.
|               In this case it will be checked if the "entity number" field
|               corresponds with the entity number set in req_xid_block.
|
|               Note: This procedure only re-formats the xid_block. The content
|               of the xid_block are not checked. This will be done in a later
|               procedure on the basis of the xid_block filled in here.
|               The only error possibly detected is returned, if the byte format
|               of the given xid block sdu is not correct: MG_XID_BAD_FORMAT.
|               Then parameter type 1 list is read. If a data comp field has
|               an algorithm of type 0 (V42bis) then its values are written
|               to the given xid_block. If the algorithm is not 0 (V42bis) then
|               the entity is rejected.
|               The same for parameter type 2, here only algorithm type 0
|               (VanJacobson) is written to the xid_block.
|               Note: it is assumed here that the parameters come in line 0, 1, 2.
|               If that will no be the case, the parsing will have to modified
|               slightly.
|               If an unknown parameter type (not 0, 1, 2) is detected, an
|               MG_XID_BAD_FORMAT is returned.
|
| Parameters  : the sdu to be parsed, is negotiation started here?, the 
|               destination T_XID_BLOCK, a return value that should be MG_XID_OK
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_decode_xid (T_sdu* sdu,
                           T_XID_BLOCK* xid_block,
                           UBYTE* ret,
                           UBYTE sapi)
{

#define CHECK_XID_BUFFER_LEN if (index + field_index >= ((sdu->l_buf) >> 3)) return
  UBYTE sapi_index = 0;
  /*
   * Index for the whole sdu.
   */
  USHORT index = sdu->o_buf / 8;
  /*
   * Sub index used in compression fields.
   */
  USHORT field_index = 0;
  /*
   * This is the index where the parameter 2 for header compression begins.
   */
  USHORT beginning_of_header_comp = 0;
  /*
   * Length of complete parameter blocks of type 1 or 2.
   */
  USHORT length = 0;
  /*
   * Was decoding successful?
   */
  BOOL ok = FALSE;

  TRACE_FUNCTION( "mg_decode_xid" );

  /*
   * Reset xid_block.
   */
  sndcp_reset_xid_block(xid_block);

  sndcp_get_sapi_index(sapi, &sapi_index);
  *ret = MG_XID_BAD_FORMAT;

  /*
   * If end is reached, return with ok.
   */
  if (sdu->l_buf == 0) {
    *ret = MG_XID_OK;
    return;
  }
  /*
   * If parameter type 0 is included, store it.
   */
  CHECK_XID_BUFFER_LEN;
  if (sdu->buf[index] == SNDCP_XID_PARAM_TYPE_0) {
    index++;
    xid_block->version_set = TRUE;
    /*
     * Length should be SNDCP_XID_0_LEN, but is not checked.
     */
    CHECK_XID_BUFFER_LEN;
    length = sdu->buf[index];

    index++;
    /*
     * Set the version in xid_block.
     */
    CHECK_XID_BUFFER_LEN;
    xid_block->version = sdu->buf[index];
    index+= length;
  }

  /*
   * If end is reached, return with ok.
   */
  if (index == ((sdu->l_buf) >> 3)) {
    *ret = MG_XID_OK;
    return;
  }

  /*
   * If parameter type 1 is included, store it.
   */
  if (sdu->buf[index] == SNDCP_XID_PARAM_TYPE_1) {
    /*
     * Length of all data compression parameters.
     */
    index++;
    CHECK_XID_BUFFER_LEN;
    length = sdu->buf[index];
    /*
     * This is the index where the parameter 2 infos for header compression
     * begin.
     */
    beginning_of_header_comp = index + length + 1;

    /*
     * Search data compression parameters for algorithm type 1.
     */
    while (length > 0) {
      /*
       * Index is now on p-bit-entity-octet for one field.
       * If the p bit is set to 1 then we read the algorithm
       * type and drop the field if it is not SNDCP_XID_V42.
       * If the p bit is not set to 1 then we read the
       * entity number and drop the field if it is not the entity number
       * proposed in req_xid_block.
       */

      /*
       * Set field_index to beginning of next data compression field.
       */
      field_index++;

      CHECK_XID_BUFFER_LEN;
      if ((sdu->buf[index + field_index] & 0x80) > 0) {
        /*
         * P bit set to 1. Check algorithm type and drop field if
         * type is not known.
         * Set ntt.
         */
        xid_block->v42.ntt = sdu->buf[index + field_index] & 0x1F;
        /*
         * Set field_index to algorithm type.
         */
        field_index ++;
        CHECK_XID_BUFFER_LEN;
        if ((sdu->buf[index + field_index] & 0xf) != SNDCP_XID_V42) {
          /*
           * Wrong algorithm type. Add the ntt to list of rejected ones.
           */
          mg_set_sapi_dntt_rej(sapi, xid_block->v42.ntt, TRUE);
          /*
           * Set index to length octet.
           */
          field_index ++;
          /*
           * Set index to next field. Check field length.
           */
          CHECK_XID_BUFFER_LEN;
          field_index += sdu->buf[index + field_index];
          if (field_index > length) {
            /*
             * Field is too long, bad format.
             */
            return;
          }
          if (field_index == length) {
            /*
             * Field is completed but entity number has not been found because in
             * that case the loop would have been left with break;
             */
            xid_block->v42.is_set = FALSE;
            break;
          }
          continue;
        } else {
          /*
           * Correct algorithm type.
           */
          if (xid_block->v42.is_set == FALSE) {
            /*
             * This is the first occurrence.
             */
            xid_block->v42.is_set = TRUE;
            xid_block->v42.p_bit = 1;


            mg_decode_v42(sdu,
                          &index,
                          &field_index,
                          xid_block,
                          &ok,
                          SNDCP_P_BIT_1);
            if (!ok) {
              /*
               * Decoding was not successful.
               */
              return;
            }
          } else {
            /*
             * There has been an occurrence of this algorithm.
             */
            /*
             * Set index to length octet.
             */
            field_index ++;
            /*
             * Set index to next field. Check field length.
             */
            CHECK_XID_BUFFER_LEN;
            field_index += sdu->buf[index + field_index];
            if (field_index > length) {
              /*
               * Field is too long, bad format.
               */
              return;
            }
            if (field_index == length) {
              /*
               * Field is completed.
               */
              break;
            }

          }
          /*
           * If all data parameters are read, go ahead for header ones.
           */
          if (field_index == length) {
            break;
          }
        }
      } else {
        /*
         * P bit set to 0.
         * Check entity number and drop field if it is not the proposed one or
         * V42 has not been proposed yet.
         * field_index is already on p-bit-entity-octet.
         */
        CHECK_XID_BUFFER_LEN;
        if (((sdu->buf[index + field_index] & 0x1f) !=
            xid_block->v42.ntt) && xid_block->v42.is_set) {
          /*
           * Wrong entity number.
           */
          /*
           * Set field_index to length octet.
           */
          field_index ++;
          /*
           * Set index to next field. Check field length.
           */
          CHECK_XID_BUFFER_LEN;
          field_index += sdu->buf[index + field_index];
          if (field_index > length) {
            /*
             * Field is too long, bad format.
             */
            return;
          }
          if (field_index == length) {
            /*
             * Field is completed but entity number has not been found because in
             * that case the loop would have been left with break;
             */
            xid_block->v42.is_set = FALSE;
            break;
          }
          continue;
        } else {
          /*
           * The entity number of this field equals the entity number in
           * ththat is already in the xid block or there is no entity in
           * the xid block yet.
           */
          xid_block->v42.is_set = TRUE;
          xid_block->v42.p_bit = 0;
          xid_block->v42.ntt =
            (sdu->buf[index + field_index] & 0x1f);

          mg_decode_v42(sdu,
                        &index,
                        &field_index,
                        xid_block,
                        &ok,
                        SNDCP_P_BIT_0);
          if (!ok) {
            /*
             * Decoding was not successful.
             */
            return;
          }

          /*
           * If all data parameters are read, go ahead for header ones.
           */
          if (field_index == length) {
            break;
          }
        }
      } /* p bit set to 0 */
    } /* while  */
    field_index = 0;
    index = beginning_of_header_comp;
  }

  /*
   * Now comes the header compression parameter type 2.
   * Is it omitted?
   */
  if (index == ((sdu->l_buf) >> 3)) {
    *ret = MG_XID_OK;
    return;
  }

  /*
   * Parameter type should be SNDCP_XID_PARAM_TYPE_2.
   */
  CHECK_XID_BUFFER_LEN;
  if (sdu->buf[index] != SNDCP_XID_PARAM_TYPE_2) {
    return;
  }
  /*
   * Length of all header compression parameters.
   */
  index++;
  CHECK_XID_BUFFER_LEN;
  length = sdu->buf[index];


  /*
   * Search header compression parameters for algorithm type 2.
   */
  while (length > 0) {
    /*
     * Index is now on p-bit-entity-octet for one field.
     * If the p bit is set to 1 then we read the algorithm
     * type and drop the field if it is not SNDCP_XID_VJ.
     * If the p bit is not set to 1 then we read the
     * entity number and drop the field if it is not the entity number
     * proposed in req_xid_block.
     */
    /*
     * Set field_index to beginning of next header compression field.
     */
    field_index++;
    CHECK_XID_BUFFER_LEN;
    if ((sdu->buf[index + field_index] & 0x80) > 0) {
      UBYTE ntt = 0;
      /*
       * P bit set to 1. Check algorithm type and drop field if
       * type is not known.
       * Set ntt.
       */
      ntt = sdu->buf[index + field_index] & 0x1F;

      /*
       * Set index to algorithm type.
       */
      field_index ++;
      CHECK_XID_BUFFER_LEN;
      if (((sdu->buf[index + field_index] & 0xf) != SNDCP_XID_VJ)
          ||
          ((sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) &&
           (xid_block->vj.is_set == FALSE) &&
           (ntt != sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt)
          )
         ) {
        /*
         * Wrong algorithm type or
         * vj comp is currently used and proposed ntt is not equal to currently
         * used one.
         * Add ntt to list of rejected ones.
         */
        mg_set_sapi_pntt_rej(sapi, ntt, TRUE);
        /*
         * Set index to length octet.
         */
        field_index ++;
        /*
         * Set index to next field. Check field length.
         */
        CHECK_XID_BUFFER_LEN;
        field_index += sdu->buf[index + field_index];
        if (field_index > length) {
          /*
           * Field is too long, bad format.
           */
          return;
        }
        if (field_index == length) {
          /*
           * Field is completed but entity number has not been found because in
           * that case the loop would have been left with break;
           */
          xid_block->vj.is_set = FALSE;
          break;
        }
        continue;
      }
      /*
       * Correct algorithm type and vj requested.
       */
      /*
       * If no vj comp is currently used and xid_block.vj is not set yet, take
       * the proposed one.
       * Also if vj comp is currently used and xid block is not yet set and
       * proposed ntt is equal to currently used one.
       */
      if (((! sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) &&
           (xid_block->vj.is_set == FALSE))
          ||
          ((sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) &&
           (xid_block->vj.is_set == FALSE) &&
           (ntt == sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt))) {

        xid_block->vj.is_set = TRUE;
        xid_block->vj.p_bit = 1;
        xid_block->vj.ntt = ntt;

        mg_decode_vj (sdu,
                      &index,
                      &field_index,
                      xid_block,
                      &ok,
                      SNDCP_P_BIT_1);
        if (!ok) {
          /*
           * Decoding was not successful.
           */
          return;
        }
        /*
         * If all header parameters are read, go ahead for header ones.
         */
        if (field_index == length) {
          break;
        }
        continue;
      }
      /*
       * This is not the first occurrence. Ignore.
       */
      /*
       * Set index to length octet.
       */
      field_index ++;
      /*
       * Set index to next field. Check field length.
       */
      CHECK_XID_BUFFER_LEN;
      field_index += sdu->buf[index + field_index];
      if (field_index > length) {
        /*
         * Field is too long, bad format.
         */
        return;
      }
      if (field_index == length) {
        /*
         * Field is completed.
         */
        break;
      }

    } else {
      /*
       * P bit set to 0.
       * Check entity number and drop field if it is not the proposed one or
       * VJ has not been proposed yet.
       * Index is already on p-bit-entity-octet.
       */
      CHECK_XID_BUFFER_LEN;
      if (((sdu->buf[index + field_index] & 0x1f) !=
          xid_block->vj.ntt) && xid_block->vj.is_set) {
        /*
         * Wrong entity number.
         * Set index to length octet.
         */
        field_index ++;
        /*
         * Set index to next field. Check field length.
         */
        CHECK_XID_BUFFER_LEN;
        field_index += sdu->buf[index + field_index];
        if (field_index > length) {
          /*
           * Field is too long, bad format.
           */
          return;
        }
        if (field_index == length) {
          /*
           * Field is completed but entity number has not been found because in
           * that case the loop would have been left with break;
           */
          break;
        }
        continue;
      } else {
        /*
         * The entity number of this field equals the entity number in
         * that is already in the xid_block or there is no entity number
         * in the block yet.
         */
        xid_block->vj.is_set = TRUE;
        xid_block->vj.p_bit = 0;
        xid_block->vj.ntt =
          (sdu->buf[index + field_index] & 0x1f);

        mg_decode_vj (sdu,
                      &index,
                      &field_index,
                      xid_block,
                      &ok,
                      SNDCP_P_BIT_0);
        if (!ok) {
          /*
           * Decoding was not successful.
           */
          return;
        }
        /*
         * The one field with same entity number as in req_xid_block has been
         * found and loop of data compression field may be left.
         * If errors in not used fields are to be detected then we must continue here!
         */
        /*
         * If all header parameters are read, leave.
         */
        if (field_index == length) {
          break;
        }
      }
    }
  } /* while */
  /*
   * It is not checked here whether the sdu is completely read.
   */
  *ret = MG_XID_OK;

} /* mg_decode_xid() */


/*
+------------------------------------------------------------------------------
| Function    : mg_dti_close
+------------------------------------------------------------------------------
| Description : Closes DTI connection
| Parameters  : nsapi
+------------------------------------------------------------------------------
*/
GLOBAL void mg_dti_close (UBYTE nsapi)
{

#ifdef _SNDCP_DTI_2_
  UBYTE interfac = SNDCP_INTERFACE_UNACK;
#ifndef SNDCP_UPM_INCLUDED
  sndcp_get_nsapi_interface(nsapi, &interfac);
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
  dti_close(sndcp_data->hDTI, /* DTI_HANDLE *hDTI, */
            0, /* U8 instance, */
            interfac, /* U8 interface, */
            nsapi,
            NULL/* U8 channel); */
           );
#else /*_SNDCP_DTI_2_*/
  UBYTE interfac = SNDCP_INTERFACE_UNACK;

  sndcp_get_nsapi_interface(nsapi, &interfac);
  dti_close(sndcp_data->hDTI, /* DTI_HANDLE *hDTI, */
            0, /* U8 instance, */
            interfac, /* U8 interface, */
            nsapi /* U8 channel); */

           );
#endif /*_SNDCP_DTI_2_*/

  /*
   * The following is done in any case since the callback will not be called.
   */
  nu_connection_state(nsapi, FALSE);
   
  /*FIXME ! Added newly. To be verified.*/
#ifdef SNDCP_UPM_INCLUDED 
  {
    U32 linkid = 0;
    PALLOC (sn_dti_cnf, SN_DTI_CNF);
    sndcp_get_nsapi_linkid(nsapi, &linkid);
    sn_dti_cnf->dti_linkid = linkid;
    sn_dti_cnf->dti_conn = NAS_DISCONNECT_DTI;
    PSEND(hCommMMI, sn_dti_cnf);
  }
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
} /* mg_dti_close() */

/*
+------------------------------------------------------------------------------
| Function    : mg_dti_open
+------------------------------------------------------------------------------
| Description : Opens DTI connection
| Parameters  : nsapi
+------------------------------------------------------------------------------
*/
GLOBAL void mg_dti_open (UBYTE nsapi)
{
#ifdef _SNDCP_DTI_2_
  UBYTE* neighbor = NULL;
  ULONG linkid = 0;
#ifndef SNDCP_UPM_INCLUDED
  BOOL ack = FALSE;
#endif 
  U8 direction = DTI_CHANNEL_TO_LOWER_LAYER;
  UBYTE interfac = SNDCP_INTERFACE_UNACK;

  sndcp_get_nsapi_linkid(nsapi, &linkid);
  sndcp_get_nsapi_neighbor(nsapi, &neighbor);
#ifndef SNDCP_UPM_INCLUDED
  sndcp_get_nsapi_ack(nsapi, &ack);
#endif 
  sndcp_get_nsapi_direction(nsapi, &direction);
#ifndef SNDCP_UPM_INCLUDED
  if (ack) {
    interfac = SNDCP_INTERFACE_ACK;
    sndcp_set_nsapi_interface(nsapi, interfac);
  }
#endif

  dti_open(sndcp_data->hDTI, /* DTI_HANDLE hDTI */
           0, /* U8 instance */
           interfac, /* U8 interface */
           nsapi, /* U8 channel */
           0, /* U8 queue_size */
           direction, /* U8 direction */
           DTI_QUEUE_WATERMARK, /* U8 link options */
           DTI_VERSION_10, /* U32 version */
           neighbor, /* U8 *neighbor_entity */
           linkid/* U32 link_id */
           );
#else /*_SNDCP_DTI_2_*/
  UBYTE* neighbor = NULL;
  ULONG linkid = 0;
  BOOL ack = FALSE;
  BOOL direction = HOME;
  UBYTE interfac = SNDCP_INTERFACE_UNACK;

  sndcp_get_nsapi_linkid(nsapi, &linkid);
  sndcp_get_nsapi_neighbor(nsapi, &neighbor);
  sndcp_get_nsapi_ack(nsapi, &ack);
  sndcp_get_nsapi_direction(nsapi, &direction);
#ifndef SNDCP_UPM_INCLUDED
  if (ack) {
    interfac = SNDCP_INTERFACE_ACK;
    sndcp_set_nsapi_interface(nsapi, interfac);
  }
#endif 

  dti_open(sndcp_data->hDTI, /* DTI_HANDLE *hDTI */
           0, /* U8 instance */
           interfac, /* U8 interface */
           nsapi, /* U8 channel */
           0, /* U8 queue_size */
           direction, /* BOOL direction */
           FLOW_CNTRL_ENABLED, /* U8 comm_type */
           DTI_VERSION_10, /* U32 version */
           neighbor, /* U8 *neighbor_entity */
           linkid/* U32 link_id */
           );

#endif /*_SNDCP_DTI_2_*/
} /* mg_dti_open() */

/*
+------------------------------------------------------------------------------
| Function    : mg_init
+------------------------------------------------------------------------------
| Description : The function mg_init() ....
|
| Parameters  :
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_init (void)
{

  UBYTE sapi_index = 0;
  UBYTE nsapi = 0;
  TRACE_FUNCTION( "mg_init" );
  INIT_STATE(MG, MG_DEFAULT);
  /*
   * req_xid_block, cnf_xid_block, cur_xid_block not initialized.
   */
  for (sapi_index = 0; sapi_index < SNDCP_NUMBER_OF_SAPIS; sapi_index++) {

    mg_reset_states_n_rej(sapi_index);
    /*
     * Init renegotiation counter and cur_xid_block with default values.
     */
    sndcp_data->mg.renego[sapi_index] = 0;

    sndcp_reset_xid_block(&sndcp_data->mg.req_xid_block[sapi_index]);
    sndcp_reset_xid_block(&sndcp_data->mg.cnf_xid_block[sapi_index]);
    sndcp_reset_xid_block(&sndcp_data->mg.ind_xid_block[sapi_index]);
    sndcp_reset_xid_block(&sndcp_data->mg.res_xid_block[sapi_index]);
    sndcp_reset_xid_block(&sndcp_data->mg.cur_xid_block[sapi_index]);
    sndcp_reset_xid_block(&sndcp_data->mg.new_xid_block[sapi_index]);

  }
  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
    sndcp_reset_xid_block(&sndcp_data->mg.user_xid_block[nsapi]);
    sndcp_data->mg.user_xid_block[nsapi].vj.s0_m_1 = 0;
    sndcp_data->cur_pcomp[nsapi] = 0;
    sndcp_data->cur_dcomp[nsapi] = 0;
    sndcp_data->cur_seg_pos[nsapi] = 0;
    sndcp_data->cur_pdu_ref[nsapi].ref_nsapi = 0;
    sndcp_data->cur_pdu_ref[nsapi].ref_npdu_num = 0;
    sndcp_data->cur_pdu_ref[nsapi].ref_seg_num = 0;
    sndcp_data->big_head[nsapi] = FALSE;
  }


  sndcp_data->mg.mod_expects = MG_MOD_X_NONE;
  sndcp_data->mg.waiting_nsapis = 0;
  sndcp_data->mg.suspended_nsapis = 0;

} /* mg_init() */



/*
+------------------------------------------------------------------------------
| Function    : mg_is_ack
+------------------------------------------------------------------------------
| Description : This procedure takes the snsm_qos!rely
|               information:
|
| 0 SNSM_RELCLASS_SUB Subscribed reliability class
| 1 SNSM_GTP_LLC_RLC_PROT Acknowledged GTP, LLC, and RLC; Protected data
| 2 SNSM_LLC_RLC_PROT Unacknowledged GTP; Acknowledged LLC and RLC, Protected data
| 3 SNSM_RLC_PROT Unacknowledged GTP and LLC; Acknowledged RLC, Protected data
| 4 SNSM_PROT Unacknowledged GTP, LLC, and RLC, Protected data
| 5 SNSM_NO_REL Unacknowledged GTP, LLC, and RLC, Unprotected data
|
| and sets "spec" to TRUE, "b" to TRUE in case of SNSM_GTP_LLC_RLC_PROT or
| SNSM_LLC_RLC_PROT,
| [should be, is not:["spec" to FALSE in case of SNSM_RELCLASS_SUB]] and "spec"
| to TRUE, "b" to FALSE else.
|
| Important note: in case of SNSM_RELCLASS_SUB "spec" will actually be set to
| to TRUE, "b" to FALSE, to be robust in case of downlink protocol error!
|
| Parameters  : snsm_qos
|                       BOOL* spec (FALSE for REL_CLASS_SUB),
|                       BOOL* b)
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_is_ack (T_snsm_qos snsm_qos,
                       BOOL* spec,
                       BOOL* b)
{
  TRACE_FUNCTION( "mg_is_ack" );


#ifdef SNDCP_UPM_INCLUDED 
  if (snsm_qos.relclass ==  PS_GTP_LLC_RLC_PROT ||
    snsm_qos.relclass == PS_LLC_RLC_PROT) {
#else
  if (snsm_qos.relclass ==  SNSM_GTP_LLC_RLC_PROT ||
    snsm_qos.relclass == SNSM_LLC_RLC_PROT) {
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
    *spec = TRUE;
    *b = TRUE;
   /*  } else if (snsm_qos.relclass == SNSM_RELCLASS_SUB) {
    *spec = FALSE;
    */
  } else {
    *spec = TRUE;
    *b = FALSE;
  }


} /* mg_is_ack() */

/*
+------------------------------------------------------------------------------
| Function    : mg_no_col_no_re
+------------------------------------------------------------------------------
| Description : The function mg_no_col_no_re represents  the SDL label
|               NO_COL_NO_RE: an LL_ESTABLISH_IND has been received, we do not
|               have a collision situation like given in [GSM 4.65, 6.2.1.4],
|               we do not have a re-establishment situation.
|
| Parameters  : the received LL_ESTABLISH_IND
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_no_col_no_re (T_LL_ESTABLISH_IND* ll_establish_ind)
{
  UBYTE dec_ret = 0;
  UBYTE check_ret = 0;
  UBYTE sapi_index = 0;
  U8 nsapi = 0;
  TRACE_FUNCTION( "mg_no_col_no_re" );
  sndcp_get_sapi_index(ll_establish_ind->sapi, &sapi_index);

  TRACE_EVENT_P3("l3_valid?: %d, N201_I: %d, N201_U: %d", 
                  ll_establish_ind->xid_valid, ll_establish_ind->n201_i, 
                  ll_establish_ind->n201_u);
  /*
   * Set N201 values in uplink services.
   */
  sig_mg_su_n201(ll_establish_ind->sapi, ll_establish_ind->n201_u);
  sig_mg_sua_n201(ll_establish_ind->sapi, ll_establish_ind->n201_i);
  /*
   * If SNDCP XID block is not valid, we are ready.
   */
  if (ll_establish_ind->xid_valid == LL_XID_INVALID) {

    PALLOC_SDU (ll_establish_res, LL_ESTABLISH_RES, 0);
    /*
     * Set sapi in ll_establish_res.
     */
    ll_establish_res->sapi = ll_establish_ind->sapi;
    ll_establish_res->xid_valid = ll_establish_ind->xid_valid;
    ll_establish_res->sdu.l_buf = 0;

    /*
     * Mark the affected sapi as MG_XID_IDLE.
     */
    sndcp_unset_sapi_state(ll_establish_ind->sapi, MG_EST);

    sig_mg_sda_end_est(ll_establish_res->sapi, TRUE);

    sndcp_set_sapi_ack(ll_establish_res->sapi, TRUE);

    PSEND(hCommLLC, ll_establish_res);

    /*
     * All nsapis at this sapi that use ack mode, enter recovery state.
     */
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi ++) {
      UBYTE sapi = 0;
      BOOL ack = FALSE;

      sndcp_get_nsapi_sapi(nsapi, &sapi);
      sndcp_get_nsapi_ack(nsapi, &ack);
      if (ack && (sapi == ll_establish_ind->sapi)) {
        sig_mg_cia_delete_npdus(nsapi);
        sig_mg_sua_delete_pdus(nsapi, sapi, FALSE);
        sig_mg_nu_recover(nsapi);
        sig_mg_nd_recover(nsapi);
      }
    } /* for all nsapis */

    return;
  }
  /*
   * SNDCP XID block is valid and checked now.
   */
  mg_decode_xid(&(ll_establish_ind->sdu),
                &(sndcp_data->mg.ind_xid_block[sapi_index]),
                &dec_ret,
                ll_establish_ind->sapi);
  if (dec_ret == MG_XID_OK) {
    mg_check_ind_xid(&check_ret, ll_establish_ind->sapi);
    if (check_ret == MG_XID_OK) {
      /*
       * Label MG_IND_OK_EST
       */
      USHORT res_sdu_bit_len = 0;
      UBYTE ntt = 0;
      BOOL v42_rej = FALSE;
      BOOL vj_rej = FALSE;

      mg_set_res_cur_xid_block(ll_establish_ind->sapi, &res_sdu_bit_len);
      /*
       * Add the extra space for ntts with nsapis == 0.
       */
      for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) {
        BOOL rej = FALSE;
        mg_get_sapi_dntt_rej(ll_establish_ind->sapi, ntt, &rej);
        if (rej) {
          /*
           * length of ntt octet and nsapis.
           */
          res_sdu_bit_len += 32;
          v42_rej = TRUE;
        }
        mg_get_sapi_pntt_rej(ll_establish_ind->sapi, ntt, &rej);
        if (rej) {
          /*
           * length of ntt octet and nsapis.
           */
          res_sdu_bit_len += 32;
          vj_rej = TRUE;
        }
      }
      if (! sndcp_data->mg.res_xid_block[sapi_index].v42.is_set &&
          v42_rej) {
        /*
         * Add length of parameter type and length.
         */
        res_sdu_bit_len += 16;
      }
      if (! sndcp_data->mg.res_xid_block[sapi_index].vj.is_set &&
          vj_rej) {
        /*
         * Add length of parameter type and length.
         */
        res_sdu_bit_len += 16;
      }

      /*
       * SDL Label MG_CNF_OK_ACK
       */

      {

        USHORT sapi_state = MG_IDLE;

        PALLOC_SDU (ll_establish_res, LL_ESTABLISH_RES, res_sdu_bit_len);
        /*
         * Set sapi in ll_establish_res.
         */
        ll_establish_res->sapi = ll_establish_ind->sapi;
        ll_establish_res->xid_valid = ll_establish_ind->xid_valid;
        /*
         * Write res_xid_block struct to sdu byte buffer. Implementation dep..
         */
        mg_set_res_xid_params(&ll_establish_res->sdu, ll_establish_res->sapi);

        /*
         * Mark the affected nsapis and sapi as MG_XID_IDLE.
         */
        sndcp_unset_sapi_state(ll_establish_ind->sapi, MG_XID);
        sndcp_unset_sapi_state(ll_establish_ind->sapi, MG_EST);

        sig_mg_sda_end_est(ll_establish_res->sapi, TRUE);

        sndcp_set_sapi_ack(ll_establish_res->sapi, TRUE);

        PSEND(hCommLLC, ll_establish_res);

        /*
         * All nsapis at this sapi that use ack mode, enter recovery state.
         */
        for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi ++) {
          UBYTE sapi = 0;
          BOOL ack = FALSE;

          sndcp_get_nsapi_sapi(nsapi, &sapi);
          sndcp_get_nsapi_ack(nsapi, &ack);
          if (ack && (sapi == ll_establish_ind->sapi)) {
            sig_mg_cia_delete_npdus(nsapi);
            sig_mg_sua_delete_pdus(nsapi, sapi, FALSE);
            sig_mg_nu_recover(nsapi);
            sig_mg_nd_recover(nsapi);
          }
        } /* for all nsapis */

        /*
         * Reset nsapis or ntts that were assigned, but are not any more.
         */
        mg_clean_xid(ll_establish_ind->sapi);
        /*
         * If there was a collision and xid has not been negotiated
         * sufficiently.
         */
        mg_resend_xid_if_nec(ll_establish_ind->sapi);

        /*
         * If nsapi has been in state xid_pending or est_pending then
         * an snsm_activate_res will be sent now.!!!
         */
        mg_respond_if_nec(ll_establish_ind->sapi);
        sndcp_get_sapi_state(ll_establish_ind->sapi, &sapi_state);
        if ((sapi_state & MG_XID) == 0) {
          mg_xid_cnf_ok_res(ll_establish_ind->sapi);
        }


      }

    } else {
      /*
       * not (check_ret == MG_IND_XID_OK)
       */
      /*
       * Label MG_CHECK_FAIL_EST
       */
      USHORT res_sdu_bit_len = 0;
      UBYTE ntt = 0;
      BOOL v42_rej = FALSE;
      BOOL vj_rej = FALSE;
      /*
       * Add the extra space for ntts with nsapis == 0.
       */
      for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) {
        BOOL rej = FALSE;
        mg_get_sapi_dntt_rej(ll_establish_ind->sapi, ntt, &rej);
        if (rej) {
          /*
           * length of ntt octet and nsapis.
           */
          res_sdu_bit_len += 32;
          v42_rej = TRUE;
        }
        mg_get_sapi_pntt_rej(ll_establish_ind->sapi, ntt, &rej);
        if (rej) {
          /*
           * length of ntt octet and nsapis.
           */
          res_sdu_bit_len += 32;
          vj_rej = TRUE;
        }
      }
      if (v42_rej) {
        /*
         * Add length of parameter type and length.
         */
        res_sdu_bit_len += 16;
      }
      if (vj_rej) {
        /*
         * Add length of parameter type and length.
         */
        res_sdu_bit_len += 16;
      }
      /*
       * Allocate response and send it.
       */
      {

        PALLOC_SDU (ll_establish_res, LL_ESTABLISH_RES, res_sdu_bit_len);
        /*
         * Reset res_xid_block, ind_xid_block.
         */
        sndcp_reset_xid_block(&sndcp_data->mg.res_xid_block[sapi_index]);
        sndcp_reset_xid_block(&sndcp_data->mg.ind_xid_block[sapi_index]);
        /*
         * Set sapi in ll_establish_res.
         */
        ll_establish_res->sapi = ll_establish_ind->sapi;
        ll_establish_res->xid_valid = ll_establish_ind->xid_valid;
        /*
         * Write res_xid_block struct to sdu byte buffer. Implementation dep..
         */
        mg_set_res_xid_params(&ll_establish_res->sdu, ll_establish_ind->sapi);
        /*
         * Modify the affected sapi state.
         */
        sndcp_unset_sapi_state(ll_establish_ind->sapi, MG_XID);
        sndcp_unset_sapi_state(ll_establish_ind->sapi, MG_EST);

        sndcp_set_sapi_ack(ll_establish_res->sapi, TRUE);
        /*
         * Send the XID block to LLC.
         */
        PSEND(hCommLLC, ll_establish_res);
                /*
         * All nsapis at this sapi that use ack mode, enter recovery state.
         */
        for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi ++) {
          UBYTE sapi = 0;
          BOOL ack = FALSE;

          sndcp_get_nsapi_sapi(nsapi, &sapi);
          sndcp_get_nsapi_ack(nsapi, &ack);
          if (ack && (sapi == ll_establish_ind->sapi)) {
            sig_mg_cia_delete_npdus(nsapi);
            sig_mg_sua_delete_pdus(nsapi, sapi, FALSE);
            sig_mg_nu_recover(nsapi);
            sig_mg_nd_recover(nsapi);
          }
        } /* for all nsapis */

      }

      /*
       * Reset nsapis or ntts that were assigned before
       * but are not anymore.
       */
      sndcp_reset_xid_block(&sndcp_data->mg.cur_xid_block[sapi_index]);
      mg_clean_xid(ll_establish_ind->sapi);
      /*
       * Allocate status req and send it  (label MG_SEND_STATUS_REQ_EST).
       */
      {
#ifdef SNDCP_UPM_INCLUDED 
        PALLOC (snsm_status_req, SN_STATUS_IND);
#else
        PALLOC (snsm_status_req, SNSM_STATUS_REQ);
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
        snsm_status_req->sapi = ll_establish_ind->sapi;
#ifdef SNDCP_UPM_INCLUDED 
        snsm_status_req->ps_cause.ctrl_value = CAUSE_is_from_sndcp;
        snsm_status_req->ps_cause.value.sn_cause = CAUSE_SN_INVALID_XID;
        PSEND (hCommUPM, snsm_status_req);
#else
        snsm_status_req->status_cause = SNSM_RELCS_INVALID_XID;
        PSEND (hCommSM, snsm_status_req);
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
      }
    }
  } else { /* not if (dec_ret == MG_XID_OK_EST) */
    /*
     * Reset nsapis or ntts that were assigned before
     * but are not anymore.
     */
    sndcp_reset_xid_block(&sndcp_data->mg.cur_xid_block[sapi_index]);
    mg_clean_xid(ll_establish_ind->sapi);
    /*
     * Decoding of ll_establish_ind failed (label MG_SEND_STATUS_REQ).
     * Allocate status req and send it.
     */

    {
#ifdef SNDCP_UPM_INCLUDED 
      PALLOC (snsm_status_req, SN_STATUS_IND);
      snsm_status_req->sapi = ll_establish_ind->sapi;
      snsm_status_req->ps_cause.ctrl_value = CAUSE_is_from_sndcp;
      snsm_status_req->ps_cause.value.sn_cause = CAUSE_SN_INVALID_XID;
      PSEND (hCommUPM, snsm_status_req);
#else
      PALLOC (snsm_status_req, SNSM_STATUS_REQ);
      snsm_status_req->sapi = ll_establish_ind->sapi;
      snsm_status_req->status_cause = SNSM_RELCS_INVALID_XID;
      PSEND (hCommSM, snsm_status_req);
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
    }

  }

} /* mg_no_col_no_re() */

/*
+------------------------------------------------------------------------------
| Function    : mg_no_col_re
+------------------------------------------------------------------------------
| Description : The function mg_no_col_no_re represents  the SDL label
|               NO_COL_RE: an LL_ESTABLISH_IND has been received, we do not
|               have a collision situation like given in [GSM 4.65, 6.2.1.4],
|               we do have a re-establishment situation.
|
| Parameters  : the received LL_ESTABLISH_IND
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_no_col_re (T_LL_ESTABLISH_IND* ll_establish_ind)
{

  TRACE_FUNCTION( "mg_no_col_re" );
  /*
   * Do the same things as without collision.
   */
  mg_no_col_no_re (ll_establish_ind);

} /* mg_no_col_re() */

/*
+------------------------------------------------------------------------------
| Function    : mg_re_negotiate
+------------------------------------------------------------------------------
| Description : The answer to the sent LL_XID_REQ has been invalid
| (bad format or content). If service var renego < MG_MAX_RENEGO then
| same LL_XID_REQ is resent, else SNSM_STATUS_REQ is sent.
| This function represents the SDl label MG_RE_NEGOTIATE.
|
| Parameters  : the affected sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_re_negotiate (UBYTE sapi) {
  UBYTE sapi_index = 0;

  TRACE_FUNCTION( "mg_re_negotiate" );
  sndcp_get_sapi_index(sapi, &sapi_index);

  /*
   * If number of re-negotiations is reached, deactivate all pdp contexts for
   * the affected sapi.
   */
  if (sndcp_data->mg.renego[sapi_index] < MG_MAX_RENEGO) {
    PALLOC_SDU(ll_xid_req, LL_XID_REQ, SNDCP_XID_BLOCK_BIT_LEN);
    /*
     * Set sapi in ll_xid_req.
     */
    ll_xid_req->sapi = sapi;

    /*
     * Fill the XID block. Implementation dependent.
     */
    mg_set_xid_params(ll_xid_req->sapi,
                      &ll_xid_req->sdu,
                      sndcp_data->mg.req_xid_block[sapi_index]);
    /*
     * Send the XID block to LLC.
     */

    sndcp_unset_sapi_state(sapi, MG_XID_NEC);
    sndcp_set_sapi_state(ll_xid_req->sapi, MG_XID);
    PSEND(hCommLLC, ll_xid_req);
    /*
     * Increment renegotiation counter.
     */
    sndcp_data->mg.renego[sapi_index]++;
  } else {

#ifdef SNDCP_UPM_INCLUDED 
    PALLOC (snsm_status_req, SN_STATUS_IND);
#else
    PALLOC (snsm_status_req, SNSM_STATUS_REQ);
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
    /*
     * Set all ntts and dcomp/pcomp states to "unassigned".
     */
    mg_reset_states_n_rej(sapi_index);
    /*
     * Set prim parameters.
     */
#ifdef SNDCP_UPM_INCLUDED 
    snsm_status_req->sapi = sapi;
    snsm_status_req->ps_cause.ctrl_value = CAUSE_is_from_sndcp;
    snsm_status_req->ps_cause.value.sn_cause = CAUSE_SN_INVALID_XID;
#else
    snsm_status_req->sapi = sapi;
    snsm_status_req->status_cause = SNSM_RELCS_INVALID_XID;
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/

    sndcp_data->mg.renego[sapi_index] = 0;
    /*
     * Reset cur_xid_block.
     */
    sndcp_reset_xid_block(&sndcp_data->mg.cur_xid_block[sapi_index]);
    /*
     * Reset all compression entities for the affected sapi.
     */
    mg_clean_xid(sapi);

#ifdef SNDCP_UPM_INCLUDED 
    PSEND (hCommUPM, snsm_status_req);
#else
    PSEND (hCommSM, snsm_status_req);
#endif 
  }


} /* mg_re_negotiate() */

/*
+------------------------------------------------------------------------------
| Function    : mg_re_negotiate_ack
+------------------------------------------------------------------------------
| Description : The answer to the sent LL_ESTABLISH_REQ has been invalid
| (bad format or content). If service var renego < MG_MAX_RENEGO then
| same LL_ESTABLISH_REQ is resent, else SNSM_STATUS_REQ is sent.
| This function represents the SDl label MG_RE_NEGOTIATE_ACK.
|
| Parameters  : the affected sapi, cause
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_re_negotiate_ack (UBYTE sapi, U16 cause) {
  UBYTE sapi_index = 0;

  TRACE_FUNCTION( "mg_re_negotiate_ack" );
  sndcp_get_sapi_index(sapi, &sapi_index);

  /*
   * If number of re-negotiations is reached, deactivate all pdp contexts for
   * the affected sapi.
   */
  if (sndcp_data->mg.renego[sapi_index] < MG_MAX_RENEGO) {
    PALLOC_SDU(ll_establish_req,
               LL_ESTABLISH_REQ,
               SNDCP_XID_BLOCK_BIT_LEN);
    /*
     * Set sapi in ll_establish_req.
     */
    ll_establish_req->sapi = sapi;

    /*
     * Fill the XID block. Implementation dependent.
     */
    mg_set_xid_params(ll_establish_req->sapi,
                      &ll_establish_req->sdu,
                      sndcp_data->mg.req_xid_block[sapi_index]);
    /*
     * Send the XID block to LLC, with establish request.
     */
    sig_mg_sda_start_est(sapi);

    PSEND(hCommLLC, ll_establish_req);
    /*
     * Increment renegotiation counter.
     */
    sndcp_data->mg.renego[sapi_index]++;
  } else {

#ifdef SNDCP_UPM_INCLUDED
    PALLOC (snsm_status_req, SN_STATUS_IND);
#else
    PALLOC (snsm_status_req, SNSM_STATUS_REQ);
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
    /*
     * Service sda may now leave state SDA_ESTABLISH_REQUESTED.
     */
    sig_mg_sda_end_est(sapi, FALSE);
    /*
     * Set all ntts and dcomp/pcomp states to "unassigned".
     */
    mg_reset_states_n_rej(sapi_index);
    /*
     * Set prim parameters.
     */
#ifdef SNDCP_UPM_INCLUDED 
    snsm_status_req->sapi = sapi;
    snsm_status_req->ps_cause.ctrl_value = CAUSE_is_from_sndcp;
#else
    snsm_status_req->sapi = sapi;
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/

    sndcp_data->mg.renego[sapi_index] = 0;
    /*
     * Reset cur_xid_block.
     */
    sndcp_reset_xid_block(&sndcp_data->mg.cur_xid_block[sapi_index]);
    sndcp_reset_xid_block(&sndcp_data->mg.req_xid_block[sapi_index]);
    /*
     * Reset all compression entities for the affected sapi.
     */
    mg_clean_xid(sapi);
    /*
     * The renegotiation is failed. If the cause is NO_PEER_RESPONSE
     * or DM_RECEIVED, set it to RELCS_NORMAL to make SM deactivate
     * PDP context. Otherwise the cause is forwarded to SM and the SM
     * will deactivate PDP context depending on cause.
     */
#ifdef SNDCP_UPM_INCLUDED 
    if((cause == CAUSE_SN_NO_PEER_RESPONSE) ||
       (cause == CAUSE_SN_DM_RECEIVED) ){
      snsm_status_req->ps_cause.value.sn_cause = CAUSE_SN_NORMAL_RELEASE;
#else /* SNDCP_UPM_INCLUDED */    
#ifdef _SNDCP_DTI_2_
    if((cause == LL_RELCS_NO_PEER_RES) ||
       (cause == LL_RELCS_DM_RECEIVED) ){
      snsm_status_req->ps_cause.value.sn_cause = LL_RELCS_NORMAL;
#else
    if((cause == CAUSE_SN_NO_PEER_RESPONSE) ||
       (cause == CAUSE_SN_DM_RECEIVED) ){
      snsm_status_req->ps_cause.value.sn_cause = CAUSE_SN_NORMAL_RELEASE;
#endif 
#endif  /* SNDCP_UPM_INCLUDED */
      sig_mg_su_resume(sapi);
      sig_mg_sua_resume(sapi);
      mg_resume_affected_nus(sapi);
      sndcp_unset_sapi_state (sapi, MG_EST);
    } else {
#ifdef SNDCP_UPM_INCLUDED 
      snsm_status_req->ps_cause.value.sn_cause = cause;
#else      
      snsm_status_req->status_cause = cause;
#endif 
    }
	
#ifdef SNDCP_UPM_INCLUDED 
    PSEND (hCommUPM, snsm_status_req);
#else
    PSEND (hCommSM, snsm_status_req);
#endif 

  }

} /* mg_re_negotiate_ack() */


/*
+------------------------------------------------------------------------------
| Function    : mg_resend_xid_if_nec
+------------------------------------------------------------------------------
| Description : This procedure will be called after reception and computation
| of an LL_XID_IND or LL_ESTABLISH_IND in case of a collision
| or after receiving LL_XID_CNF or LL_ESTABLISH_CNF and does the
| following:
| (GSM 04.65 version 6.5.1 Release 1997), 6.2.1.4:
| If the
| LL-ESTABLISH.request or LL-XID.request contains one or more XID parameters,
| or one or more compression fields
| in an XID parameter, or one or more parameters in a compression field,
| that are not negotiated as part of the collision
| resolution, then negotiation of these XID parameters shall be performed at
| the earliest opportunity after conclusion of
| the collision resolution.
|
| Parameters  : Affected sapi, out: was LL_XID_REQ sent?
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_resend_xid_if_nec (UBYTE sapi) {
  UBYTE sapi_index = 0;
  BOOL resend_necessary = FALSE;
  USHORT sapi_state = MG_IDLE;
  T_XID_BLOCK* req_xid_block = NULL;
  T_XID_BLOCK* cur_xid_block = NULL;
  T_XID_BLOCK* new_xid_block = NULL;

  TRACE_FUNCTION( "mg_resend_xid_if_nec" );

  sndcp_get_sapi_index(sapi, &sapi_index);
  req_xid_block = &sndcp_data->mg.req_xid_block[sapi_index];
  cur_xid_block = &sndcp_data->mg.cur_xid_block[sapi_index];
  new_xid_block = &sndcp_data->mg.new_xid_block[sapi_index];

  /*
   * Data compression.
   */
  /*
   * If a context is deactivated, maybe compressors must be switched off.
   */
  if (cur_xid_block->v42.is_set) {
    USHORT nsapis = cur_xid_block->v42.nsapis;
    UBYTE nsapi = 0;

    /*
     * XID renegotiation will only be necessary if one of the nsapis
     * that are requested to use the data compression is in state
     * MG_DEACT.
     */
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      if (((1 << nsapi) & nsapis) > 0) {
        USHORT state = MG_IDLE;
        sndcp_get_nsapi_state(nsapi, &state);
        if ((state & MG_DEACT) > 0) {
          UBYTE dntt = cur_xid_block->v42.ntt;
          resend_necessary = TRUE;
          mg_set_sapi_dntt_rej(sapi, dntt, TRUE);
        }
      }
    }
  }

  if (req_xid_block->v42.is_set && ! cur_xid_block->v42.is_set) {
    UBYTE sapi_index_local = 0;
    BOOL used = FALSE;
    /*
     * If one instance of v42 is used at a different sapi,
     * we may not use another one here.
     */
    for (sapi_index_local = 0;
         sapi_index_local < SNDCP_NUMBER_OF_SAPIS;
         sapi_index_local++) {

      if (sndcp_data->mg.cur_xid_block[sapi_index_local].v42.is_set) {
        used = TRUE;
      }
    }
    if (! used) {
      USHORT nsapis = req_xid_block->v42.nsapis;
      UBYTE nsapi = 0;

      /*
       * XID renegotiation will only be necessary if one of the nsapis
       * that are requested to use the data compression are not all in state
       * MG_DEACT.
       */
      for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
        if (((1 << nsapi) & nsapis) > 0) {
          USHORT state = MG_IDLE;
          sndcp_get_nsapi_state(nsapi, &state);
          if ((state & MG_DEACT) == 0) {
            resend_necessary = TRUE;
          }
        }
      }

    }
  }
  /*
   * Header compression.
   */
  /*
   * If a context is deactivated, maybe compressors must be switched off.
   */
  if (cur_xid_block->vj.is_set) {
    USHORT nsapis = cur_xid_block->vj.nsapis;
    UBYTE nsapi = 0;

    /*
     * XID renegotiation will only be necessary if one of the nsapis
     * that are requested to use the header compression is in state
     * MG_DEACT.
     */
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      if (((1 << nsapi) & nsapis) > 0) {
        USHORT state = MG_IDLE;
        sndcp_get_nsapi_state(nsapi, &state);
        if ((state & MG_DEACT) > 0) {
          UBYTE pntt = cur_xid_block->vj.ntt;
          resend_necessary = TRUE;
          mg_set_sapi_pntt_rej(sapi, pntt, TRUE);
        }
      }
    }

  }
  /*
   * If a compressor is requested and not yet negotiated it must be requested
   * now.
   */
  if (req_xid_block->vj.is_set && !cur_xid_block->vj.is_set) {
    USHORT nsapis = req_xid_block->vj.nsapis;
    UBYTE nsapi = 0;

    req_xid_block->vj.p_bit = 1;

    /*
     * XID renegotiation will only be necessary if the affected nsapis
     * is not currently being deactivated.
     */
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      if (((1 << nsapi) & nsapis) > 0) {
        USHORT state = MG_IDLE;
        sndcp_get_nsapi_state(nsapi, &state);
        if ((state & MG_DEACT) == 0) {
          resend_necessary = TRUE;
        }
      }
    }

  }

  /*
   * If in the meantime more compression has been requested,
   * or compressors must be deactivated,
   * re-negotiate.
   */
  if (new_xid_block->v42.is_set) {
    if ((! req_xid_block->v42.is_set) ||
        (req_xid_block->v42.is_set &&
         (new_xid_block->v42.nsapis != req_xid_block->v42.nsapis))) {

      *req_xid_block = *new_xid_block;
      resend_necessary = TRUE;
    }
  }

  /*
   * If in the meantime more compression has been requested,
   * or compressors must be deactivated,
   * re-negotiate.
   */
  if (new_xid_block->vj.is_set) {
    if ((! req_xid_block->vj.is_set) ||
        (req_xid_block->vj.is_set &&
         (new_xid_block->vj.nsapis != req_xid_block->vj.nsapis))) {

      *req_xid_block = *new_xid_block;
      resend_necessary = TRUE;
    }
  }


  sndcp_get_sapi_state(sapi, &sapi_state);
  /*
   * If re-negotiation is necessary but not possible because MG_REL or
   * MG_XID, set MG_XID_NEC.
   */
  if (resend_necessary
      &&
      ((sapi_state & (MG_REL + MG_XID)) > 0))
  {
    sndcp_set_sapi_state(sapi, MG_XID_NEC);
    mg_set_cur_xid_block(sapi);
    return;
  }


  /*
   * If renegotiation of XID is necessary, send LL_XID_REQ.
   */
  if (! resend_necessary) {
//    mg_set_cur_xid_block(sapi);
    return;
  }


  /*
   * Now req_xid_block is in good shape. Send it.
   */
  {
    PALLOC_SDU(ll_xid_req, LL_XID_REQ, SNDCP_XID_BLOCK_BIT_LEN);
    /*
     * Set sapi in ll_xid_req.
     */
    ll_xid_req->sapi = sapi;
    /*
     * Write data from snsm_activate_ind to service variable req_xid_block.
     */
    mg_set_ntt_comp(sapi);
    /*
     * Fill the XID block. Implementation dependent.
     */
    mg_set_xid_params(ll_xid_req->sapi,
                      &ll_xid_req->sdu,
                      sndcp_data->mg.req_xid_block[sapi_index]);
    /*
     * Mark the affected sapi as MG_XID.
     */
    sndcp_set_sapi_state(sapi, MG_XID);
    sndcp_unset_sapi_state(sapi, MG_XID_NEC);

    /*
     * Uplink data transfer on SAPI is completely suspended.
     */
    sig_mg_su_suspend(sapi);
    sig_mg_sua_suspend(sapi);
    mg_suspend_affected_nus(sapi);
    /*
     * Send the XID block to LLC.
     */

    sndcp_unset_sapi_state(sapi, MG_XID_NEC);
    sndcp_set_sapi_state(ll_xid_req->sapi, MG_XID);
    PSEND(hCommLLC, ll_xid_req);
  }

} /* mg_resend_xid_if_nec() */



/*
+------------------------------------------------------------------------------
| Function    : mg_resume_affected_nus
+------------------------------------------------------------------------------
| Description : Resumes all nu service instances affected by
|               If nsapi is waiting for SNSM_SEQUENCE_IND, fct. returns.
|
| Parameters  : sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_resume_affected_nus (UBYTE sapi) {
  UBYTE nsapi = 0;
  TRACE_FUNCTION( "mg_resume_affected_nus" );
  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
    UBYTE local_sapi = 0;
    sndcp_get_nsapi_sapi(nsapi, &local_sapi);
    if (local_sapi == sapi) {
      USHORT nsapi_state = 0;
      sndcp_get_nsapi_state(nsapi, &nsapi_state);
      if ((nsapi_state & MG_SEQ) > 0) {
        return;
      }
      if (((1 << nsapi) & sndcp_data->mg.suspended_nsapis) > 0) {
        sig_mg_nu_resume(nsapi);
        sndcp_data->mg.suspended_nsapis &= (~ (ULONG)(1 << nsapi));
      }
    }
  }
} /* mg_resume_affected_nus() */


/*
+------------------------------------------------------------------------------
| Function    : mg_is_rel_comp_nec
+------------------------------------------------------------------------------
| Description : This function will be called in course of the deactivation of
|               the given nsapi. If the nsapi used a certain compressor,
|               but has been the only one to do this, then with the
|               compressor entity will also have to
|               be deactivated and all affected
|               arrays will be modified.
| Parameters  : UBYTE nsapi -- the given nsapi
|               BOOL* nec,  a compressor
| Post        : An "mg_set_sapi_[p/d]ntt_rej(sapi, pntt, TRUE);" will be called
|               for
|               each entity to be released. Later this information may be used
|               to build up the right xid negotiation.
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_is_rel_comp_nec (UBYTE nsapi, BOOL* nec)
{
  UBYTE dntt = 0;
  UBYTE pntt = 0;
  UBYTE sapi = 0;
  UBYTE nsp = 0;

  TRACE_FUNCTION( "mg_is_rel_comp_nec" );

  sndcp_get_nsapi_sapi(nsapi, &sapi);


  /*
   * Which pntt is used?
   */
  for (pntt = 0; pntt < MG_MAX_ENTITIES; pntt++) {
    UBYTE state = MG_UNASSIGNED;
    BOOL used = FALSE;
    BOOL another = FALSE;
    BOOL rej_known = FALSE;
    /*
     * Is pntt already known to be deactivated?
     */
    mg_get_sapi_pntt_rej(sapi, pntt, &rej_known);
    if (rej_known) {
      *nec = TRUE;
      continue;
    }
    /*
     * Is ntt used?
     */
    mg_get_sapi_pntt_state(sapi, pntt, &state);
    if (state == MG_UNASSIGNED) {
      continue;
    }
    /*
     * Does the given nsapi use it?
     */
    mg_get_sapi_pntt_nsapi(sapi, pntt, nsapi, &used);
    if (! used) {
      continue;
    }
    /*
     * Is the given nsapi the only user?
     */
    for (nsp = 0; nsp < SNDCP_NUMBER_OF_NSAPIS; nsp++) {
      mg_get_sapi_pntt_nsapi(sapi, pntt, nsp, &used);
      if (used && nsapi != nsp) {
        another = TRUE;
      }
    }
    if (another) {
      continue;
    }
    mg_set_sapi_pntt_rej(sapi, pntt, TRUE);
    *nec = TRUE;
  }

  /*
   * Which dntt is used?
   */
  for (dntt = 0; dntt < MG_MAX_ENTITIES; dntt++) {
    UBYTE state = MG_UNASSIGNED;
    BOOL used = FALSE;
    BOOL another = FALSE;
    BOOL rej_known = FALSE;
    /*
     * Is pntt already known to be deactivated?
     */
    mg_get_sapi_dntt_rej(sapi, dntt, &rej_known);
    if (rej_known) {
      *nec = TRUE;
      continue;
    }
    /*
     * Is ntt used?
     */
    mg_get_sapi_dntt_state(sapi, dntt, &state);
    if (state == MG_UNASSIGNED) {
      continue;
    }
    /*
     * Does the given nsapi use it?
     */
    mg_get_sapi_dntt_nsapi(sapi, dntt, nsapi, &used);
    if (! used) {
      continue;
    }
    /*
     * Is the given nsapi the only user?
     */
    for (nsp = 0; nsp < SNDCP_NUMBER_OF_NSAPIS; nsp++) {
      mg_get_sapi_dntt_nsapi(sapi, dntt, nsp, &used);
      if (used && nsapi != nsp) {
        another = TRUE;
      }
    }
    if (another) {
      continue;
    }

    mg_set_sapi_dntt_rej(sapi, dntt, TRUE);
    *nec = TRUE;
  }

} /* mg_is_rel_comp_nec() */


/*
+------------------------------------------------------------------------------
| Function    : mg_rel_nsapi_nec
+------------------------------------------------------------------------------
| Description : The SAPI connected to this NSAPI shall release acknowledged LLC
|               operation mode if the indicated NSAPI is the last one using
|               acknowledged mode on this SAPI. If an LL_RELEASE_REQ is sent
|               then the given NSAPI (the one in parameter!) shall enter state
|               MG_REL and wait for an LL_RELEASE_CNF. If the affected
|               NSAPI doesn't use ack mode then the procedure just returns.
|               If the affected sapi does not use acknowledged LLC operation
|               mode then the procedure just returns.
|               If an LL_ESTABLISH_REQ or LL_XID_REQ for the affected sapi is
|               pending, no LL_RELEASE_REQ primitive will be sent, but the
|               flag MG_REL_NEC_LOC will be set.
| Pre         : This procedure is called after receipt of an
|               SNSM_DEACTIVATE_IND, so the "local" parameter in an
|               LL_RELEASE_REQ will be set to LL_REL_LOCAL.
|               The procedure will only be called if the given nsapi is
|               currently using acknowledged LLC operation mode, so this
|               does not have to be checked.
| Parameters  : UBYTE nsapi -- the given nsapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_rel_nsapi_nec (UBYTE nsapi)
{
  UBYTE sapi = 0;
  UBYTE npi = 0;
  UBYTE spi = 0;
  USHORT sapi_state = MG_IDLE;
  /*
   * Are there other contexts using acknowledged mode on the same SAPI?
   */
  BOOL another_ack = FALSE;
  BOOL sack = FALSE;
  TRACE_FUNCTION( "mg_rel_nsapi_nec" );
  /*
   * Which SAPI is connected to the given NSAPI?
   */
  sndcp_get_nsapi_sapi(nsapi, &sapi);
  sndcp_get_sapi_ack(sapi, &sack);
  sndcp_get_sapi_state(sapi, &sapi_state);

  if(!sack){
    if ((sapi_state & MG_EST) != 0) {
      sndcp_set_sapi_state(sapi, MG_REL_NEC_LOC);
    }
    return;
  }
  /*
   * If release is pending, no need to send an other release.
   */
  if ((sapi_state & MG_REL) > 0) {
    return;
  }
  /*
   * Are there other contexts using acknowledged mode on the same SAPI?
   */
  for (npi = 0; npi < SNDCP_NUMBER_OF_NSAPIS; npi++) {
    BOOL used = FALSE;
    sndcp_is_nsapi_used(npi, &used);
    if (!used) {
      continue;
    }
    sndcp_get_nsapi_sapi(npi, &spi);
    if (spi == sapi && npi != nsapi) {
      BOOL is_ack = FALSE;
      sndcp_get_nsapi_ack(npi, &is_ack);
      if (is_ack) {
        another_ack = TRUE;
      }
      break;
    }
  }
  if (!another_ack) {

    if (((sapi_state & MG_EST) == 0)
        &&
        ((sapi_state & MG_XID) == 0))
    {
      /*
       * No LL_ESTABLISH_REQ or LL_XID_REQ pending.
       * LL_RELEASE_REQ may be sent.
       */

      PALLOC(ll_release_req, LL_RELEASE_REQ);
      ll_release_req->sapi = sapi;
      /*
       * Note: this is always set to TRUE because the preconditions include that
       * this procedure has been called after an SNSM_DEACTIVATE_IND.
       * If this precondition changes the local flag will have to be a parameter.
       * (GSM 4.65, 6.2.2.2).
       */
      ll_release_req->local = TRUE;
      /*
       * Set the "state" for the affected sapi to MG_REL.
       */
      sndcp_set_sapi_state(sapi, MG_REL);
      sndcp_unset_sapi_state(sapi, MG_EST);

      PSEND(hCommLLC, ll_release_req);

    } else {
      /*
       * LL_ESTABLISH_REQ or LL_XID_REQ pending.
       * LL_RELEASE_REQ may not be sent.
       */
      sndcp_set_sapi_state(sapi, MG_REL_NEC_LOC);

    }
  } /* if (!another_ack)  */


} /* mg_rel_nsapi_nec() */

/*
+------------------------------------------------------------------------------
| Function    : mg_send_empty_xid_req
+------------------------------------------------------------------------------
| Description : This procedure sets the pending-states of the affected sapi
|               and nsapi to MG_XID_PENDING and sends an LL_XID_REQ with
|               the sapi from the given snsm_activate_ind and an empty XID
|               block.
|
| Parameters  : the SNSM_ACTIVATE_IND
|
+------------------------------------------------------------------------------
*/
#ifdef SNDCP_UPM_INCLUDED
GLOBAL void mg_send_empty_xid_req (T_SN_ACTIVATE_REQ* snsm_activate_ind)
#else
GLOBAL void mg_send_empty_xid_req (T_SNSM_ACTIVATE_IND* snsm_activate_ind)
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
{
  TRACE_FUNCTION( "mg_send_empty_xid_req" );
  {
    PALLOC_SDU(ll_xid_req, LL_XID_REQ, SNDCP_XID_BLOCK_BIT_LEN);
    /*
     * Set sapi in ll_xid_req.
     */
    ll_xid_req->sapi = snsm_activate_ind->sapi;
    ll_xid_req->sdu.l_buf = 0;

    /*
     * Mark sapi as pending.
     */
    sndcp_set_sapi_state(snsm_activate_ind->sapi, MG_XID);
    /*
     * Send the XID block to LLC.
     */

    sndcp_unset_sapi_state(ll_xid_req->sapi, MG_XID_NEC);
    sndcp_set_sapi_state(ll_xid_req->sapi, MG_XID);
    PSEND(hCommLLC, ll_xid_req);
  }
} /* mg_send_xid_req() */

/*
+------------------------------------------------------------------------------
| Function    : mg_send_snsm_activate_res
+------------------------------------------------------------------------------
| Description : Allocates prim, sets parameters and sends prim
|
| Parameters  : the affected nsapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_send_snsm_activate_res (UBYTE nsapi)
{

  TRACE_FUNCTION( "mg_send_snsm_activate_res" );
  {
    UBYTE sapi_index = 0;
    UBYTE sapi = 0;

#ifdef SNDCP_UPM_INCLUDED 
    PALLOC(snsm_activate_res, SN_ACTIVATE_CNF);
#else
    PALLOC(snsm_activate_res, SNSM_ACTIVATE_RES); 
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/

    sndcp_get_nsapi_sapi(nsapi, &sapi);
    sndcp_get_sapi_index(sapi, &sapi_index);

    snsm_activate_res->nsapi = nsapi;

    /*
     * If nsapi uses data compressor, set dcomp parameter
     * in snsm_activate_res.
     */
    if (sndcp_data->mg.cur_xid_block[sapi_index].v42.is_set &&
        ((sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis &
         (1 << nsapi)) > 0)) {

#ifdef SNDCP_UPM_INCLUDED 
      snsm_activate_res->comp_params.dcomp = 
        sndcp_data->mg.cur_xid_block[sapi_index].v42.p0;
#else
      snsm_activate_res->dcomp =
        sndcp_data->mg.cur_xid_block[sapi_index].v42.p0; 
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
    } else
    {
#ifdef SNDCP_UPM_INCLUDED 
    snsm_activate_res->comp_params.dcomp = 0;
#else
    snsm_activate_res->dcomp = 0; 
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
    } 

    /*
     * If nsapi uses header compressor, set hcomp parameter
     * and msid field in snsm_activate_res.
     */

#ifdef SNDCP_UPM_INCLUDED 
    if (sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set &&
        ((sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis &
         (1 << nsapi)) > 0)) {
      snsm_activate_res->comp_params.msid = 
        sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1 + 1;
      /*
       * How is that one negotiated?
       * Missing in VJ XID block.
       */
      snsm_activate_res->comp_params.hcomp = 
        sndcp_data->mg.cur_xid_block[sapi_index].vj.direction;
    } else {
      snsm_activate_res->comp_params.hcomp = 0;
      snsm_activate_res->comp_params.msid = 0;
    }

    PSEND(hCommUPM, snsm_activate_res);
#else  /*#ifdef SNDCP_UPM_INCLUDED*/
      if (sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set &&
        ((sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis &
         (1 << nsapi)) > 0)) {
      snsm_activate_res->msid =
        sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1 + 1; 
      /*
       * How is that one negotiated?
       * Missing in VJ XID block.
       */
      snsm_activate_res->hcomp =
        sndcp_data->mg.cur_xid_block[sapi_index].vj.direction;
    } else {
      snsm_activate_res->hcomp = 0;
      snsm_activate_res->msid = 0;
    }
    PSEND(hCommSM, snsm_activate_res); 
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
}
  } /* mg_send_snsm_activate_res() */



/*
+------------------------------------------------------------------------------
| Function    : mg_send_xid_req
+------------------------------------------------------------------------------
| Description : This procedure sets the pending-states of the affected sapi
|               and nsapi to MG_XID_PENDING and sends an LL_XID_REQ with
|               parameters set according to the compression informations in
|               the given snsm_activate_ind and according to constants that
|               determine the capabilities of the data compression entity.
|               The part of this procedure that deals with the constant
|               compressor capabilities is implementation dependent.
|
| Parameters  : the SNSM_ACTIVATE_IND
|
+------------------------------------------------------------------------------
*/
#ifdef SNDCP_UPM_INCLUDED 
GLOBAL void mg_send_xid_req (T_SN_ACTIVATE_REQ* snsm_activate_ind)
#else
GLOBAL void mg_send_xid_req (T_SNSM_ACTIVATE_IND* snsm_activate_ind)
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
{
  UBYTE sapi_index = 0;
  TRACE_FUNCTION( "mg_send_xid_req" );
  sndcp_get_sapi_index(snsm_activate_ind->sapi, &sapi_index);
  {
    PALLOC_SDU(ll_xid_req, LL_XID_REQ, SNDCP_XID_BLOCK_BIT_LEN);
    /*
     * Set sapi in ll_xid_req.
     */
    ll_xid_req->sapi = snsm_activate_ind->sapi;
    /*
     * Write data from snsm_activate_ind to service variable req_xid_block.
     */

    mg_set_req_xid_block(snsm_activate_ind);
    /*
     * Fill the XID block. Implementation dependent.
     */
    mg_set_xid_params(ll_xid_req->sapi,
                      &ll_xid_req->sdu,
                      sndcp_data->mg.req_xid_block[sapi_index]);
    /*
     * Mark the affected sapi as xid pending
     */

    sndcp_set_sapi_state(snsm_activate_ind->sapi, MG_XID);

    /*
     * Trace xid block.
     */
#ifdef SNDCP_TRACE_ALL
    TRACE_EVENT("outcoming xid block:");
    sndcp_trace_sdu(&ll_xid_req->sdu);
#endif
    /*
     * Send the XID block to LLC.
     */

    sndcp_unset_sapi_state(ll_xid_req->sapi, MG_XID_NEC);
    sndcp_set_sapi_state(ll_xid_req->sapi, MG_XID);
    PSEND(hCommLLC, ll_xid_req);
  }
} /* mg_send_xid_req() */

/*
+------------------------------------------------------------------------------
| Function    : mg_send_xid_req_del
+------------------------------------------------------------------------------
| Description : If mg_get_sapi_pntt_rej() or mg_get_sapi_dntt_rej() indicate
|               that compressors must be removed, this function will
|               send an LL_XID_REQ which does this, or if an XID is pending,
|               the information about the rejected compressors will be stored
|               to new_xid_block and the MG_XID_NEC will be set.
|
| Parameters  : the SNSM_ACTIVATE_IND
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_send_xid_req_del (UBYTE sapi)
{
  UBYTE sapi_index = 0;
  UBYTE ntt = 0;
  T_XID_BLOCK mt_xid_block;
  /*
   * Only length of parameter type 0.
   */
  USHORT res_sdu_bit_len = 24;
  BOOL v42_rej = FALSE;
  BOOL vj_rej = FALSE;

  TRACE_FUNCTION( "mg_send_xid_req_del" );

  sndcp_reset_xid_block(&mt_xid_block);

  sndcp_get_sapi_index(sapi, &sapi_index);
  /*
   * How long will xid_block be?
   */
  /*
   * Add the extra space for ntts with nsapis == 0.
   */
  for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) {
    BOOL rej = FALSE;
    mg_get_sapi_dntt_rej(sapi, ntt, &rej);
    if (rej) {
      /*
       * length of ntt octet and nsapis.
       */
      res_sdu_bit_len += 32;
      v42_rej = TRUE;
      /*
       * Change new_xid_block.
       */
      sndcp_data->mg.new_xid_block[sapi_index].v42.nsapis = 0;
      sndcp_data->mg.new_xid_block[sapi_index].v42.nsapis_set = TRUE;
      sndcp_data->mg.new_xid_block[sapi_index].v42.is_set = TRUE;
    }

    mg_get_sapi_pntt_rej(sapi, ntt, &rej);
    if (rej) {
      /*
       * length of ntt octet and nsapis.
       */
      res_sdu_bit_len += 32;
      vj_rej = TRUE;
      /*
       * Change req_xid_block.
       */
      sndcp_data->mg.new_xid_block[sapi_index].vj.nsapis = 0;
      sndcp_data->mg.new_xid_block[sapi_index].vj.nsapis_set = TRUE;
      sndcp_data->mg.new_xid_block[sapi_index].vj.is_set = TRUE;

    }
  }
  if (v42_rej) {
    /*
     * Add length of parameter type and length.
     */
    res_sdu_bit_len += 16;
  }
  if (vj_rej) {
    /*
     * Add length of parameter type and length.
     */
    res_sdu_bit_len += 16;
  }

  if (v42_rej || vj_rej) {

    USHORT state = MG_IDLE;

    sndcp_get_sapi_state(sapi, &state);
    if ((state & MG_XID) == 0) {

      PALLOC_SDU(ll_xid_req, LL_XID_REQ, res_sdu_bit_len);

      sndcp_data->mg.req_xid_block[sapi_index] =
        sndcp_data->mg.new_xid_block[sapi_index];
      /*
       * Set sapi in ll_xid_req.
       */
      ll_xid_req->sapi = sapi;
      /*
       * Write data from snsm_activate_ind to service variable req_xid_block.
       */
      sndcp_reset_xid_block(&mt_xid_block);
      sndcp_reset_xid_block(&sndcp_data->mg.new_xid_block[sapi_index]);
      /*
       * Fill the XID block. Implementation dependent.
       */
      mg_set_xid_params(ll_xid_req->sapi,
                        &ll_xid_req->sdu,
                        mt_xid_block);
      /*
       * Mark the affected sapi as MG_DEL_XID_PENDING.
       */
      sndcp_set_sapi_state(sapi, MG_XID);
      /*
       * Send the XID block to LLC.
       */

      sndcp_unset_sapi_state(sapi, MG_XID_NEC);
      sndcp_set_sapi_state(ll_xid_req->sapi, MG_XID);
      PSEND(hCommLLC, ll_xid_req);
    } else {
      sndcp_set_sapi_state(sapi, MG_XID_NEC);
    }
  }
} /* mg_send_xid_req_del() */


/*
+------------------------------------------------------------------------------
| Function    : mg_set_cur_xid_block
+------------------------------------------------------------------------------
| Description : This procedure sets the cur_xid_block service variable
| according to the values given in req_xid_block and cnf_xid_block.
| It also sets the unassigned, selected, assigned states of the affected
| dcomp, pcomp, ntt.
| The p bit in the req_xid_block is unset, if affected.
| See GSM 4.65, 6.8.2.
|
| Parameters  : the affected sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_set_cur_xid_block (UBYTE sapi) {
  UBYTE sapi_index = 0;
  T_XID_BLOCK* cur_xid_block;
  T_XID_BLOCK* req_xid_block;
  T_XID_BLOCK* cnf_xid_block;
  TRACE_FUNCTION( "mg_set_cur_xid_block" );
  sndcp_get_sapi_index(sapi, &sapi_index);
  cur_xid_block = &sndcp_data->mg.cur_xid_block[sapi_index];
  req_xid_block = &sndcp_data->mg.req_xid_block[sapi_index];
  cnf_xid_block = &sndcp_data->mg.cnf_xid_block[sapi_index];
  /*
   * SNDCP version has been tested to be SNDCP_XID_VERSION.
   */
  cur_xid_block->version = SNDCP_XID_VERSION;

  /*
   * V42bis parameters.
   */
  if (req_xid_block->v42.is_set) {
    cur_xid_block->v42.is_set = TRUE;
    cur_xid_block->v42.ntt = req_xid_block->v42.ntt;
    mg_set_sapi_dntt_state(sapi,
                           req_xid_block->v42.ntt,
                           MG_ASSIGNED);
    req_xid_block->v42.p_bit = SNDCP_P_BIT_0;

    /*
     * Algorithm type and DCOMP are only set in req.
     */
    cur_xid_block->v42.algo_type = req_xid_block->v42.algo_type;
    cur_xid_block->v42.dcomp = req_xid_block->v42.dcomp;
    mg_set_sapi_dcomp_state(sapi,
                            req_xid_block->v42.dcomp,
                            MG_ASSIGNED);

    if (cnf_xid_block->v42.is_set) {

      if (cnf_xid_block->v42.nsapis_set) {
        cur_xid_block->v42.nsapis = cnf_xid_block->v42.nsapis;
        cur_xid_block->v42.nsapis_set = TRUE;
      } else if (req_xid_block->v42.nsapis_set) {
        cur_xid_block->v42.nsapis = req_xid_block->v42.nsapis;
        cur_xid_block->v42.nsapis_set = TRUE;
      }
      if (cnf_xid_block->v42.p0_set) {
        cur_xid_block->v42.p0 = cnf_xid_block->v42.p0;
        cur_xid_block->v42.p0_set = TRUE;
      } else if (req_xid_block->v42.p0_set) {
        cur_xid_block->v42.p0 = req_xid_block->v42.p0;
        cur_xid_block->v42.p0_set = TRUE;
      }
      if (cnf_xid_block->v42.p1_set) {
        cur_xid_block->v42.p1 = cnf_xid_block->v42.p1;
        cur_xid_block->v42.p1_set = TRUE;
      } else if (req_xid_block->v42.p1_set) {
        cur_xid_block->v42.p1 = req_xid_block->v42.p1;
        cur_xid_block->v42.p1_set = TRUE;
      }
      if (cnf_xid_block->v42.p2_set) {
        cur_xid_block->v42.p2 = cnf_xid_block->v42.p2;
        cur_xid_block->v42.p2_set = TRUE;
      } else if (req_xid_block->v42.p2_set) {
        cur_xid_block->v42.p2 = req_xid_block->v42.p2;
        cur_xid_block->v42.p2_set = TRUE;
      }

    } else {
      /*
       * NOT cnf_xid_block->v42.is_set.
       */

      if (req_xid_block->v42.nsapis_set) {
        cur_xid_block->v42.nsapis = req_xid_block->v42.nsapis;
        cur_xid_block->v42.nsapis_set = TRUE;
      }
      if (req_xid_block->v42.p0_set) {
        cur_xid_block->v42.p0 = req_xid_block->v42.p0;
        cur_xid_block->v42.p0_set = TRUE;
      }
      if (req_xid_block->v42.p1_set) {
        cur_xid_block->v42.p1 = req_xid_block->v42.p1;
        cur_xid_block->v42.p1_set = TRUE;
      }
      if (req_xid_block->v42.p2_set) {
        cur_xid_block->v42.p2 = req_xid_block->v42.p2;
        cur_xid_block->v42.p2_set = TRUE;
      }

    }
  } else {
    /*
     * NOT req_xid_block->v42.is_set.
     */
    if (cnf_xid_block->v42.is_set) {

      cur_xid_block->v42.is_set = TRUE;
      if (cnf_xid_block->v42.nsapis_set) {
        cur_xid_block->v42.nsapis = cnf_xid_block->v42.nsapis;
        cur_xid_block->v42.nsapis_set = TRUE;
      }
      if (cnf_xid_block->v42.p0_set) {
        cur_xid_block->v42.p0 = cnf_xid_block->v42.p0;
        cur_xid_block->v42.p0_set = TRUE;
      }
      if (cnf_xid_block->v42.p1_set) {
        cur_xid_block->v42.p1 = cnf_xid_block->v42.p1;
        cur_xid_block->v42.p1_set = TRUE;
      }
      if (cnf_xid_block->v42.p2_set) {
        cur_xid_block->v42.p2 = cnf_xid_block->v42.p2;
        cur_xid_block->v42.p2_set = TRUE;
      }

    } else {
      /*
       * Req and cnf are not set, cur_xid_block keeps its values.
       */
    }
  }


  /*
   * VJ parameters.
   */
  if (req_xid_block->vj.is_set) {
    cur_xid_block->vj.is_set = TRUE;
    cur_xid_block->vj.ntt = req_xid_block->vj.ntt;
    mg_set_sapi_pntt_state(sapi,
                           req_xid_block->vj.ntt,
                           MG_ASSIGNED);
    req_xid_block->vj.p_bit = SNDCP_P_BIT_0;
    /*
     * Algorithm type and PCOMPs are only set in req.
     * The direction is only set in req.
     */
    cur_xid_block->vj.algo_type = req_xid_block->vj.algo_type;
    cur_xid_block->vj.pcomp1 = req_xid_block->vj.pcomp1;
    mg_set_sapi_pcomp_state(sapi,
                            req_xid_block->vj.pcomp1,
                            MG_ASSIGNED);
    cur_xid_block->vj.pcomp2 = req_xid_block->vj.pcomp2;
    mg_set_sapi_pcomp_state(sapi,
                            req_xid_block->vj.pcomp2,
                            MG_ASSIGNED);
    cur_xid_block->vj.direction = req_xid_block->vj.direction;
    if (cnf_xid_block->vj.is_set) {
      if (cnf_xid_block->vj.nsapis_set) {
        cur_xid_block->vj.nsapis = cnf_xid_block->vj.nsapis;
        cur_xid_block->vj.nsapis_set = TRUE;
      } else {
        cur_xid_block->vj.nsapis = req_xid_block->vj.nsapis;
        cur_xid_block->vj.nsapis_set = TRUE;
      }
      if (cnf_xid_block->vj.s0_m_1_set) {
        cur_xid_block->vj.s0_m_1 = cnf_xid_block->vj.s0_m_1;
        cur_xid_block->vj.s0_m_1_set = TRUE;
      } else {
        cur_xid_block->vj.s0_m_1 = req_xid_block->vj.s0_m_1;
        cur_xid_block->vj.s0_m_1_set = TRUE;
      }
    } else {
      if (req_xid_block->vj.nsapis_set) {
        cur_xid_block->vj.nsapis = req_xid_block->vj.nsapis;
        cur_xid_block->vj.nsapis_set = TRUE;
      }
      if (req_xid_block->vj.s0_m_1_set) {
        cur_xid_block->vj.s0_m_1 = req_xid_block->vj.s0_m_1;
        cur_xid_block->vj.s0_m_1_set = TRUE;
      }
    }
  } else {
    /*
     * NOT req_xid_block->vj.es_set.
     */
    if (cnf_xid_block->vj.is_set) {
      cur_xid_block->vj.is_set = TRUE;
      if (cnf_xid_block->vj.nsapis_set) {
        cur_xid_block->vj.nsapis = cnf_xid_block->vj.nsapis;
        cur_xid_block->vj.nsapis_set = TRUE;
      }
      if (cnf_xid_block->vj.s0_m_1_set) {
        cur_xid_block->vj.s0_m_1 = cnf_xid_block->vj.s0_m_1;
        cur_xid_block->vj.s0_m_1_set = TRUE;
      }
    } else {
      /*
       * Req and cnf are not set, cur_xid_block keeps it's values.
       */
    }
  }

  /*
   * If nsapis are 0, deactivate compressor.
   */
  if (cur_xid_block->v42.nsapis == 0 ||
      cur_xid_block->v42.nsapis_set == FALSE) {

    /*
     * Find the affected compressor entity.
     */
    UBYTE dntt = 0;
    mg_get_sapi_dcomp_dntt(sapi, req_xid_block->v42.dcomp, &dntt);

    cur_xid_block->v42.is_set = FALSE;
    mg_set_sapi_dcomp_state(sapi,
                            req_xid_block->v42.dcomp,
                            MG_UNASSIGNED);
    mg_set_sapi_dntt_state(sapi,
                           dntt,
                           MG_UNASSIGNED);
    /*
     * One compressor less, something like sndcp_data->v42_count--;
     * should come here!
     */

  }
  if (cur_xid_block->vj.nsapis == 0 ||
      cur_xid_block->vj.nsapis_set == FALSE) {

    /*
     * Find the affected compressor entity.
     */
    UBYTE pntt = 0;
    mg_get_sapi_pcomp_pntt(sapi, req_xid_block->vj.pcomp1, &pntt);
    mg_get_sapi_pcomp_pntt(sapi, req_xid_block->vj.pcomp2, &pntt);
    cur_xid_block->vj.is_set = FALSE;
    mg_set_sapi_pcomp_state(sapi,
                            req_xid_block->vj.pcomp1,
                            MG_UNASSIGNED);
    mg_set_sapi_pcomp_state(sapi,
                            req_xid_block->vj.pcomp2,
                            MG_UNASSIGNED);
    mg_set_sapi_pntt_state(sapi,
                           pntt,
                           MG_UNASSIGNED);
    /*
     * One compressor less.
     */
    if (sndcp_data->vj_count > 0) {
      sndcp_data->vj_count--;
    }
  }


  /*
   * Send new block to service cia.
   */
  sig_mg_cia_new_xid(cur_xid_block);

} /* mg_set_cur_xid_block() */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_new_xid_block
+------------------------------------------------------------------------------
| Description : This procedure reads data from the given snsm_activate_ind and
|               from the already requested xid block and
|               writes them to the service variable new_xid_block.
|               When the pending establishment or xid negotiation is finished
|               this new_xid_block will be newly evaluated.
|
| Parameters  :
|               the new SNSM_ACTIVATE_IND
|
+------------------------------------------------------------------------------
*/
#ifdef SNDCP_UPM_INCLUDED
GLOBAL void mg_set_new_xid_block (T_SN_ACTIVATE_REQ* snsm_activate_ind)
#else
GLOBAL void mg_set_new_xid_block (T_SNSM_ACTIVATE_IND* snsm_activate_ind)
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
{
  UBYTE sapi_index = 0;
  TRACE_FUNCTION( "mg_set_new_xid_block" );
  sndcp_get_sapi_index(snsm_activate_ind->sapi, &sapi_index);
  /*
   * Set the version number.
   */
  sndcp_data->mg.new_xid_block[sapi_index].version = SNDCP_XID_VERSION;
  /*
   * Set the V42.bis parameters,
   */
#ifdef TI_PS_FF_V42BIS
  sndcp_data->mg.new_xid_block[sapi_index].v42.is_set =
#ifdef SNDCP_UPM_INCLUDED
    (snsm_activate_ind->comp_params.dcomp != NAS_DCOMP_NEITHER_DIRECT);
#else
    (snsm_activate_ind->dcomp != SNSM_COMP_NEITHER_DIRECT);
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
  sndcp_data->mg.new_xid_block[sapi_index].v42.p_bit = SNDCP_P_BIT_1;
  sndcp_data->mg.new_xid_block[sapi_index].v42.ntt = SNDCP_NTT_0;
  sndcp_data->mg.new_xid_block[sapi_index].v42.algo_type = SNDCP_XID_V42;
  sndcp_data->mg.new_xid_block[sapi_index].v42.dcomp = SNDCP_DCOMP1;
  sndcp_data->mg.new_xid_block[sapi_index].v42.nsapis =
    1 << (snsm_activate_ind->nsapi);
  sndcp_data->mg.new_xid_block[sapi_index].v42.nsapis_set = TRUE;
#ifdef SNDCP_UPM_INCLUDED
  sndcp_data->mg.new_xid_block[sapi_index].v42.p0 = snsm_activate_ind->comp_params.dcomp;
#else
  sndcp_data->mg.new_xid_block[sapi_index].v42.p0 = snsm_activate_ind->dcomp;
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
  sndcp_data->mg.new_xid_block[sapi_index].v42.p0_set = TRUE;

  /*
   * Set p1 and p2 to default values.
   */
  sndcp_data->mg.new_xid_block[sapi_index].v42.p1 = SNDCP_V42_DEFAULT_P1;
  sndcp_data->mg.new_xid_block[sapi_index].v42.p1_set = TRUE;
  sndcp_data->mg.new_xid_block[sapi_index].v42.p2 =
    SNDCP_V42_DEFAULT_P2;
  sndcp_data->mg.new_xid_block[sapi_index].v42.p2_set = TRUE;

  /*
   * Set affected entities and dcomp/pcomp values.
   */
  mg_set_ntt_comp(snsm_activate_ind->sapi);

#else /* !TI_PS_FF_V42BIS */


  sndcp_data->mg.new_xid_block[sapi_index].v42.is_set = FALSE;

  sndcp_data->mg.new_xid_block[sapi_index].v42.nsapis = 0;

  sndcp_data->mg.new_xid_block[sapi_index].v42.nsapis_set = FALSE;
  sndcp_data->mg.new_xid_block[sapi_index].v42.p0_set = FALSE;

  /*
   * Set p1 and p2 to default values.
   */
  sndcp_data->mg.new_xid_block[sapi_index].v42.p1 = SNDCP_V42_DEFAULT_P1;
  sndcp_data->mg.new_xid_block[sapi_index].v42.p1_set = TRUE;
  sndcp_data->mg.new_xid_block[sapi_index].v42.p2 =
    SNDCP_V42_DEFAULT_P2;
  sndcp_data->mg.new_xid_block[sapi_index].v42.p2_set = TRUE;

#endif /* TI_PS_FF_V42BIS */

  /*
   * Set the Van Jacobson parameters,
   */
  sndcp_data->mg.new_xid_block[sapi_index].vj.is_set =
#ifdef SNDCP_UPM_INCLUDED 
    (snsm_activate_ind->comp_params.hcomp != NAS_HCOMP_OFF) ||
#else
    (snsm_activate_ind->hcomp != SNSM_COMP_NEITHER_DIRECT) ||
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
    sndcp_data->mg.new_xid_block[sapi_index].vj.is_set ||
    sndcp_data->mg.req_xid_block[sapi_index].vj.is_set;

  if (! sndcp_data->mg.req_xid_block[sapi_index].vj.is_set) {
    sndcp_data->mg.new_xid_block[sapi_index].vj.p_bit = SNDCP_P_BIT_1;
  } else {
    sndcp_data->mg.new_xid_block[sapi_index].vj.p_bit = SNDCP_P_BIT_0;
  }

  sndcp_data->mg.new_xid_block[sapi_index].vj.ntt = SNDCP_NTT_0;
  sndcp_data->mg.new_xid_block[sapi_index].vj.algo_type = SNDCP_XID_VJ;
  sndcp_data->mg.new_xid_block[sapi_index].vj.pcomp1 = SNDCP_PCOMP1;
  sndcp_data->mg.new_xid_block[sapi_index].vj.pcomp2 = SNDCP_PCOMP2;

  sndcp_data->mg.new_xid_block[sapi_index].vj.nsapis |=
    (sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis |
     1 << (snsm_activate_ind->nsapi));
  sndcp_data->mg.new_xid_block[sapi_index].vj.nsapis_set = TRUE;
  
#ifdef SNDCP_UPM_INCLUDED
  sndcp_data->mg.new_xid_block[sapi_index].vj.s0_m_1 = 
    snsm_activate_ind->comp_params.msid - 1;
#else
  sndcp_data->mg.new_xid_block[sapi_index].vj.s0_m_1 =
    snsm_activate_ind->msid - 1;
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
  sndcp_data->mg.new_xid_block[sapi_index].vj.s0_m_1_set = TRUE;
  /*
   * Only used internally, not in XID block.
   * Not: it is assumed that the indicated values match the existing ones!
   */
#ifdef SNDCP_UPM_INCLUDED
  sndcp_data->mg.new_xid_block[sapi_index].vj.direction = 
    snsm_activate_ind->comp_params.hcomp;
#else
  sndcp_data->mg.new_xid_block[sapi_index].vj.direction = 
    snsm_activate_ind->hcomp;
#endif /*#ifdef SNDCP_UPM_INCLUDED*/

} /* mg_set_new_xid_block() */



/*
+------------------------------------------------------------------------------
| Function    : mg_set_req_xid_block
+------------------------------------------------------------------------------
| Description : This procedure reads data from the given snsm_activate_ind and
|               writes it to the service variable req_xid_block.
|
| Parameters  :
|               the SNSM_ACTIVATE_IND that caused the negotiation.
|
+------------------------------------------------------------------------------
*/
#ifdef SNDCP_UPM_INCLUDED
GLOBAL void mg_set_req_xid_block (T_SN_ACTIVATE_REQ* snsm_activate_ind)
#else
GLOBAL void mg_set_req_xid_block (T_SNSM_ACTIVATE_IND* snsm_activate_ind)
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
{
  UBYTE sapi_index = 0;
  BOOL vio;
  TRACE_FUNCTION( "mg_set_req_xid_block" );
  sndcp_get_sapi_index(snsm_activate_ind->sapi, &sapi_index);
  /*
   * Set the version number.
   */
  sndcp_data->mg.req_xid_block[sapi_index].version = SNDCP_XID_VERSION;
  /*
   * Set the V42.bis parameters,
   */
#ifdef TI_PS_FF_V42BIS

#ifdef SNDCP_UPM_INCLUDED
    sndcp_data->mg.req_xid_block[sapi_index].v42.is_set =
      (snsm_activate_ind->comp_params.dcomp != NAS_DCOMP_NEITHER_DIRECT);
#else
    sndcp_data->mg.req_xid_block[sapi_index].v42.is_set = 
      (snsm_activate_ind->dcomp != SNSM_COMP_NEITHER_DIRECT);
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
    sndcp_data->mg.req_xid_block[sapi_index].v42.p_bit = SNDCP_P_BIT_1;
    sndcp_data->mg.req_xid_block[sapi_index].v42.ntt = SNDCP_NTT_0;
    sndcp_data->mg.req_xid_block[sapi_index].v42.algo_type = SNDCP_XID_V42;
    sndcp_data->mg.req_xid_block[sapi_index].v42.dcomp = SNDCP_DCOMP1;

    sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis =
      1 << (snsm_activate_ind->nsapi);
    sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis_set = TRUE;
#ifdef SNDCP_UPM_INCLUDED
    sndcp_data->mg.req_xid_block[sapi_index].v42.p0 = snsm_activate_ind->comp_params.dcomp;
#else
    sndcp_data->mg.req_xid_block[sapi_index].v42.p0 = snsm_activate_ind->dcomp;
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
    sndcp_data->mg.req_xid_block[sapi_index].v42.p0_set = TRUE;

    /*
     * Set p1 and p2 to default values.
     */
    sndcp_data->mg.req_xid_block[sapi_index].v42.p1 = SNDCP_V42_DEFAULT_P1;
    sndcp_data->mg.req_xid_block[sapi_index].v42.p1_set = TRUE;
    sndcp_data->mg.req_xid_block[sapi_index].v42.p2 =
      SNDCP_V42_DEFAULT_P2;
    sndcp_data->mg.req_xid_block[sapi_index].v42.p2_set = TRUE;
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.is_set =
  #ifdef SNDCP_UPM_INCLUDED
      (snsm_activate_ind->comp_params.dcomp != NAS_DCOMP_NEITHER_DIRECT);
  #else
      (snsm_activate_ind->dcomp != SNSM_COMP_NEITHER_DIRECT);
  #endif /*#ifdef SNDCP_UPM_INCLUDED*/
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p_bit = SNDCP_P_BIT_1;
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.ntt = SNDCP_NTT_0;
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.algo_type = SNDCP_XID_V42;
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.dcomp = SNDCP_DCOMP1;
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.nsapis =
      1 << (snsm_activate_ind->nsapi);
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.nsapis_set = TRUE;
  #ifdef SNDCP_UPM_INCLUDED
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p0 = snsm_activate_ind->comp_params.dcomp;
  #else
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p0 = snsm_activate_ind->dcomp;
  #endif /*#ifdef SNDCP_UPM_INCLUDED*/
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p0_set = TRUE;

    /*
     * Set p1 and p2 to default values.
     */
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p1 = SNDCP_V42_DEFAULT_P1;
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p1_set = TRUE;
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p2 =
      SNDCP_V42_DEFAULT_P2;
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p2_set = TRUE;

    /*
     * Set affected entities and dcomp/pcomp values.
     */
    mg_set_ntt_comp(snsm_activate_ind->sapi);


#else /* !TI_PS_FF_V42BIS */

    sndcp_data->mg.req_xid_block[sapi_index].v42.is_set = FALSE;

    sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis = 0;

    sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis_set = FALSE;
    sndcp_data->mg.req_xid_block[sapi_index].v42.p0_set = FALSE;

    /*
     * Set p1 and p2 to default values.
     */
    sndcp_data->mg.req_xid_block[sapi_index].v42.p1 = SNDCP_V42_DEFAULT_P1;
    sndcp_data->mg.req_xid_block[sapi_index].v42.p1_set = TRUE;
    sndcp_data->mg.req_xid_block[sapi_index].v42.p2 =
      SNDCP_V42_DEFAULT_P2;
    sndcp_data->mg.req_xid_block[sapi_index].v42.p2_set = TRUE;

#endif /* TI_PS_FF_V42BIS */

  /*
   * Set the Van Jacobson parameters.
   * Note:
   * If number of state slots is set to 0, do not request VJ in XID request.
   */
#ifdef SNDCP_UPM_INCLUDED
  if (snsm_activate_ind->comp_params.msid == 0) {
#else
  if (snsm_activate_ind->msid == 0) {
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
    sndcp_data->mg.req_xid_block[sapi_index].vj.is_set = FALSE;
    return;
  }

  sndcp_data->mg.req_xid_block[sapi_index].vj.is_set =
  #ifdef SNDCP_UPM_INCLUDED 
    (snsm_activate_ind->comp_params.hcomp != NAS_HCOMP_OFF);
  #else
    (snsm_activate_ind->hcomp != SNSM_COMP_NEITHER_DIRECT);
  #endif  /*#ifdef SNDCP_UPM_INCLUDED*/
  if (!sndcp_data->mg.req_xid_block[sapi_index].vj.is_set) {
    return;
  }
  /*
   * This function will only be called after snsm_activate_ind. So the
   * user_xid_block will be set for the affected nsapi.
   */
  if (sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) {
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.p_bit = 
      SNDCP_P_BIT_0;
  } else {
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.p_bit = 
      SNDCP_P_BIT_1;
  }
    
  sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.ntt = 
    SNDCP_NTT_0;
  sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.algo_type = 
    SNDCP_XID_VJ;
  sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.pcomp1 = 
    SNDCP_PCOMP1;
  sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.pcomp2 = 
    SNDCP_PCOMP2;
  sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.nsapis +=
    1 << (snsm_activate_ind->nsapi);
  sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.nsapis_set = TRUE;
#ifdef SNDCP_UPM_INCLUDED
  if (snsm_activate_ind->comp_params.msid > SNDCP_MAX_NUMBER_OF_VJ_SLOTS) { 
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.s0_m_1 = 
      SNDCP_MAX_NUMBER_OF_VJ_SLOTS - 1;
  } else {
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.s0_m_1 = 
      snsm_activate_ind->comp_params.msid - 1;
  }
#else
  if (snsm_activate_ind->msid > SNDCP_MAX_NUMBER_OF_VJ_SLOTS) {
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.s0_m_1 =
      SNDCP_MAX_NUMBER_OF_VJ_SLOTS - 1;
  } else {
    sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.s0_m_1 =
      snsm_activate_ind->msid - 1;
  }
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
  sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.s0_m_1_set = TRUE;
  /*
   * Only used internally, not in XID block.
   */
#ifdef SNDCP_UPM_INCLUDED
  sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.direction = 
    snsm_activate_ind->comp_params.hcomp;
#else
   sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.direction = 
   snsm_activate_ind->hcomp;
#endif /*#ifdef SNDCP_UPM_INCLUDED*/

  /*
   * Set affected entities and dcomp/pcomp values.
   */
  mg_set_ntt_comp(snsm_activate_ind->sapi);

  mg_detect_mode_clash ((USHORT)
                         (sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis +
                         (1 << (snsm_activate_ind->nsapi))),
                        &vio);
  if (vio) {
    return;
  }

  if (sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) {
    sndcp_data->mg.req_xid_block[sapi_index].vj.p_bit = SNDCP_P_BIT_0;
  } else {
    sndcp_data->mg.req_xid_block[sapi_index].vj.p_bit = SNDCP_P_BIT_1;
  }
  sndcp_data->mg.req_xid_block[sapi_index].vj.ntt = SNDCP_NTT_0;
  sndcp_data->mg.req_xid_block[sapi_index].vj.algo_type = SNDCP_XID_VJ;
  sndcp_data->mg.req_xid_block[sapi_index].vj.pcomp1 = SNDCP_PCOMP1;
  sndcp_data->mg.req_xid_block[sapi_index].vj.pcomp2 = SNDCP_PCOMP2;

  /*
   * All the nsapis that currently use the compressor and the new one
   * shall be set in the nsapis field of the XID block.
   */
  sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis = 
    (sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis | 
     (1 << (snsm_activate_ind->nsapi)));

  sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis_set = TRUE;
#ifdef SNDCP_UPM_INCLUDED
  if (snsm_activate_ind->comp_params.msid > SNDCP_MAX_NUMBER_OF_VJ_SLOTS) { 
    sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1 = 
      SNDCP_MAX_NUMBER_OF_VJ_SLOTS - 1;
  } else {
    sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1 = 
      snsm_activate_ind->comp_params.msid - 1;
  }
#else
  if (snsm_activate_ind->msid > SNDCP_MAX_NUMBER_OF_VJ_SLOTS) {
    sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1 =
      SNDCP_MAX_NUMBER_OF_VJ_SLOTS - 1;
  } else {
    sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1 =
      snsm_activate_ind->msid - 1;
  }
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
  sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1_set = TRUE;
  /*
   * Only used internally, not in XID block.
   */
#ifdef SNDCP_UPM_INCLUDED
  sndcp_data->mg.req_xid_block[sapi_index].vj.direction = 
    snsm_activate_ind->comp_params.hcomp;
#else
  sndcp_data->mg.req_xid_block[sapi_index].vj.direction = 
    snsm_activate_ind->hcomp;
#endif /*#ifdef SNDCP_UPM_INCLUDED*/
  /*
   * Set affected entities and dcomp/pcomp values.
   */
  mg_set_ntt_comp(snsm_activate_ind->sapi);

} /* mg_set_req_xid_block() */


/*
+------------------------------------------------------------------------------
| Function    : mg_set_res_cur_xid_block
+------------------------------------------------------------------------------
| Description : This procedure sets the service variables res_xid_block and
| cur_xid_block. The needed data comes from the service variable ind_xid_block,
| and from default settings.
| Note: if the indicated compressors do not match with compressors requested
| or currently used then they will be unset by adding them to the list of
| rejected compressors.
|
|
| Parameters  :
|               the affected sapi,
|               the necessary bit length of an sdu that will later store the
|               xid block derived from res_xid_block.
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_set_res_cur_xid_block (UBYTE sapi, USHORT* res_sdu_bit_len)
{
  UBYTE sapi_index = 0;
  UBYTE nsapi = 0;
  /*
   * Which compressors are indicated?
   */
  BOOL v42_ind, vj_ind;
  /*
   * Which compressors are possible?
   * (The indicated set of nsapis must overlap with the
   * currently used one.)
   */
  BOOL v42_possible, vj_possible;
  /*
   * Is compressor going to rejected? In this case the compressor should not
   * be requested.
   */
  BOOL v42_rejected, vj_rejected;

  TRACE_FUNCTION( "mg_set_res_cur_xid_block" );

  sndcp_get_sapi_index(sapi, &sapi_index);
  sndcp_reset_xid_block(&(sndcp_data->mg.res_xid_block[sapi_index]));

  /*
   * Set bit length to "only version", 3 bytes.
   */
  *res_sdu_bit_len = 24;
  /*
   * Set the version number.
   */
  sndcp_data->mg.res_xid_block[sapi_index].version = SNDCP_XID_VERSION;

  v42_ind = sndcp_data->mg.ind_xid_block[sapi_index].v42.is_set;
  v42_possible = FALSE;
  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
    if ((sndcp_data->mg.user_xid_block[nsapi].v42.nsapis & 
        sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis) > 0) {

      U8 local_sapi = 0;
      sndcp_get_nsapi_sapi(nsapi, &local_sapi);
      if (local_sapi == sapi) {
        v42_possible = TRUE;
      }
    }
  }


  if (v42_ind && ! v42_possible) {
    sndcp_data->mg.res_xid_block[sapi_index].v42.is_set = FALSE;
    mg_set_sapi_dntt_rej (sapi,
                          sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt,
                          TRUE);
  }

  mg_get_sapi_dntt_rej (sapi,
                        sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt,
                        &v42_rejected);


  if (v42_ind && ! v42_rejected) {
    /*
     * Data compression will be included, increment bit len (+ 10 bytes).
     */
    *res_sdu_bit_len += 80;

    /*
     * Set the V42.bis parameters,
     */
    sndcp_data->mg.res_xid_block[sapi_index].v42.is_set = TRUE;

    sndcp_data->mg.res_xid_block[sapi_index].v42.p_bit = SNDCP_P_BIT_0;

    sndcp_data->mg.res_xid_block[sapi_index].v42.ntt =
      sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt;


    sndcp_data->mg.res_xid_block[sapi_index].v42.algo_type = SNDCP_XID_V42;

    sndcp_data->mg.res_xid_block[sapi_index].v42.dcomp =
      sndcp_data->mg.ind_xid_block[sapi_index].v42.dcomp;

    /*
     * Set the 'nsapis' parameter in res_xid_block:
     * Check rules in 4.65, subclause 6.8.1, compare with cur_xid_block.
     */
    mg_set_xid_nsapis(sapi, MG_XID_V42_NSAPIS);

    /*
     * It is assumed that the values desired by the user / the
     * values possible with the current implementation are written in
     * req_xid_block, the responded values are then the minimum of
     * req and ind values:
     */
    /*
     * For the direction parameter p0 take the logical AND:
     */
    sndcp_data->mg.res_xid_block[sapi_index].v42.p0 =
      (sndcp_data->mg.req_xid_block[sapi_index].v42.p0 &
       sndcp_data->mg.ind_xid_block[sapi_index].v42.p0);
    sndcp_data->mg.res_xid_block[sapi_index].v42.p0_set = TRUE;

    /*
     * For p1 and p2 take minimum.
     */
    sndcp_data->mg.res_xid_block[sapi_index].v42.p1 =
      (sndcp_data->mg.req_xid_block[sapi_index].v42.p1 <
       sndcp_data->mg.ind_xid_block[sapi_index].v42.p1)?
       sndcp_data->mg.req_xid_block[sapi_index].v42.p1 :
        sndcp_data->mg.ind_xid_block[sapi_index].v42.p1;
    sndcp_data->mg.res_xid_block[sapi_index].v42.p1_set = TRUE;

    sndcp_data->mg.res_xid_block[sapi_index].v42.p2 =
      (sndcp_data->mg.req_xid_block[sapi_index].v42.p2 <
       sndcp_data->mg.ind_xid_block[sapi_index].v42.p2)?
       sndcp_data->mg.req_xid_block[sapi_index].v42.p2 :
        sndcp_data->mg.ind_xid_block[sapi_index].v42.p2;
    sndcp_data->mg.res_xid_block[sapi_index].v42.p2_set = TRUE;

  } /* v42.is_set */


  /*
   * Header compression,
   */

  
  vj_ind = sndcp_data->mg.ind_xid_block[sapi_index].vj.is_set;
  vj_possible = FALSE;
  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
    if ((sndcp_data->mg.user_xid_block[nsapi].vj.nsapis & 
        sndcp_data->mg.ind_xid_block[sapi_index].vj.nsapis) > 0) {

      U8 local_sapi = 0;
      sndcp_get_nsapi_sapi(nsapi, &local_sapi);
      if (local_sapi == sapi) {
        vj_possible = TRUE;
      }
    }
  }

  if (vj_ind && ! vj_possible) {
    sndcp_data->mg.res_xid_block[sapi_index].vj.is_set = FALSE;
    mg_set_sapi_pntt_rej (sapi,
                          sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt,
                          TRUE);
  }

  mg_get_sapi_pntt_rej (sapi,
                        sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt,
                        &vj_rejected);

  if (vj_ind && ! vj_rejected) {
    /*
     * Header compression will be included, increment bit len (+ 7 bytes).
     */
    *res_sdu_bit_len += 56;

    /*
     * Set the VJ parameters,
     */
    sndcp_data->mg.res_xid_block[sapi_index].vj.is_set = TRUE;

    sndcp_data->mg.res_xid_block[sapi_index].vj.p_bit = SNDCP_P_BIT_0;

    sndcp_data->mg.res_xid_block[sapi_index].vj.ntt =
      sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt;

    sndcp_data->mg.res_xid_block[sapi_index].vj.algo_type = SNDCP_XID_VJ;

    if (sndcp_data->mg.ind_xid_block[sapi_index].vj.p_bit == SNDCP_P_BIT_1) {
      sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp1 =
        sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp1;
      sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp2 =
        sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp2;
    } else {
      sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp1 =
        sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp1;
      sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp2 =
        sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp2;
    }

    /*
     * Set the 'nsapis' parameter in res_xid_block:
     * Check rules in 4.65, subclause 6.8.1, compare with cur_xid_block.
     * State slots and direction are also set here.
     */
    mg_set_xid_nsapis(sapi, MG_XID_VJ_NSAPIS);


  } /* vj.is_set */


  /*
   * Set affected entities and dcomp/pcomp values.
   */
  if (v42_ind && v42_possible) {
    mg_set_sapi_dntt_state(sapi,
                           sndcp_data->mg.res_xid_block[sapi_index].v42.ntt,
                           MG_ASSIGNED);

    mg_set_sapi_dcomp_state(sapi,
                            sndcp_data->mg.res_xid_block[sapi_index].v42.dcomp,
                            MG_ASSIGNED);
    mg_set_sapi_dcomp_dntt(sapi,
                           sndcp_data->mg.res_xid_block[sapi_index].v42.dcomp,
                           sndcp_data->mg.res_xid_block[sapi_index].v42.ntt);
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      if (((1 << nsapi) & sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis) > 0) {
        mg_set_sapi_dntt_nsapi(sapi,
                              sndcp_data->mg.res_xid_block[sapi_index].v42.ntt,
                               nsapi,
                               TRUE);
      } /* if nsapi is selected */
    } /* for loop over all nsapis */

  }
  /*
   * If VJ is indicated and possible, switch on compressor.
   */
  if (vj_ind && vj_possible) {
    mg_set_sapi_pntt_state(sapi,
                           sndcp_data->mg.res_xid_block[sapi_index].vj.ntt,
                           MG_ASSIGNED);
    mg_set_sapi_pcomp_state(sapi,
                            sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp1,
                            MG_ASSIGNED);
    mg_set_sapi_pcomp_state(sapi,
                            sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp2,
                            MG_ASSIGNED);
    mg_set_sapi_pcomp_pntt(sapi,
                           sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp1,
                           sndcp_data->mg.res_xid_block[sapi_index].vj.ntt);
    mg_set_sapi_pcomp_pntt(sapi,
                           sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp2,
                           sndcp_data->mg.res_xid_block[sapi_index].vj.ntt);
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      if (((1 << nsapi) & sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis) > 0) {
        mg_set_sapi_pntt_nsapi(sapi,
                             sndcp_data->mg.res_xid_block[sapi_index].vj.ntt,
                             nsapi,
                             TRUE);
      } /* if nsapi is selected */
    } /* for loop over all nsapis */
  }

  /*
   * If VJ has been switched on and is now indicated to be switched off:
   * switch off compressor.
   */
  if (vj_ind
      &&
      sndcp_data->mg.ind_xid_block[sapi_index].vj.nsapis == 0
      &&
      sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis > 0)
  {
    mg_set_sapi_pntt_state(sapi,
                           sndcp_data->mg.res_xid_block[sapi_index].vj.ntt,
                           MG_UNASSIGNED);
    mg_set_sapi_pcomp_state(sapi,
                            sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp1,
                            MG_UNASSIGNED);
    mg_set_sapi_pcomp_state(sapi,
                            sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp2,
                            MG_UNASSIGNED);
/*    mg_set_sapi_pcomp_pntt(sapi,
                           sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp1,
                           sndcp_data->mg.res_xid_block[sapi_index].vj.ntt);
    mg_set_sapi_pcomp_pntt(sapi,
                           sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp2,
                           sndcp_data->mg.res_xid_block[sapi_index].vj.ntt);
*/
    for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
      if (((1 << nsapi) & sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis) > 0) {
        mg_set_sapi_pntt_nsapi(sapi,
                             sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt,
                             nsapi,
                             FALSE);
      } /* if nsapi is selected */
    } /* for loop over all nsapis */
  }


  /*
   * Add same values for cur_xid_block.
   */

  if (sndcp_data->mg.res_xid_block[sapi_index].v42.is_set) {
    if (sndcp_data->mg.cur_xid_block[sapi_index].v42.is_set) {
      sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis =
        sndcp_data->mg.res_xid_block[sapi_index].v42.nsapis;
      if (sndcp_data->mg.cur_xid_block[sapi_index].v42.p0_set) {
        sndcp_data->mg.cur_xid_block[sapi_index].v42.p0 =
          sndcp_data->mg.res_xid_block[sapi_index].v42.p0;
      }
      if (sndcp_data->mg.cur_xid_block[sapi_index].v42.p1_set) {
        sndcp_data->mg.cur_xid_block[sapi_index].v42.p1 =
          sndcp_data->mg.res_xid_block[sapi_index].v42.p1;
      }
      if (sndcp_data->mg.cur_xid_block[sapi_index].v42.p2_set) {
        sndcp_data->mg.cur_xid_block[sapi_index].v42.p2 =
          sndcp_data->mg.res_xid_block[sapi_index].v42.p2;
      }
    } else {
      sndcp_data->mg.cur_xid_block[sapi_index].v42 =
        sndcp_data->mg.res_xid_block[sapi_index].v42;
    }
  }

  if (sndcp_data->mg.res_xid_block[sapi_index].vj.is_set) {
    if (sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) {
      sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis =
        sndcp_data->mg.res_xid_block[sapi_index].vj.nsapis;
      if (sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1_set) {
        sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1 =
          sndcp_data->mg.res_xid_block[sapi_index].vj.s0_m_1;
      }
    } else {
      sndcp_data->mg.cur_xid_block[sapi_index].vj =
        sndcp_data->mg.res_xid_block[sapi_index].vj;
    }
  }


  if (vj_rejected) {
    sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis = 0;
  }
  if (sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis == 0) {
    sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set = FALSE;
  }

  if (v42_rejected) {
    sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis = 0;
  }
  if (sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis == 0) {
    sndcp_data->mg.cur_xid_block[sapi_index].v42.is_set = FALSE;
  }

  sig_mg_cia_new_xid(& sndcp_data->mg.cur_xid_block[sapi_index]);


} /* mg_set_res_cur_xid_block */

/*
+------------------------------------------------------------------------------
| Function    : mg_set_res_xid_params
+------------------------------------------------------------------------------
| Description : This procedure fills the XID block. It is implementation
|               dependent. In the current version V42bis and VanJacobson
|               header compression are applied.
|
| Parameters  :
|               the sdu that will be filled,
| Post        : Reset arrays with reject information to all FALSE.
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_set_res_xid_params (T_sdu* sdu, UBYTE sapi)
{
  /*
   * Byte index in destination sdu.
   */
  UBYTE index = 3;
  UBYTE type_2_header_index = 0;
  UBYTE sapi_index = 0;
  UBYTE ntt = 0;
  BOOL type_1_header_set = FALSE;
  BOOL type_2_header_set = FALSE;
  TRACE_FUNCTION( "mg_set_res_xid_params" );
  sndcp_get_sapi_index(sapi, &sapi_index);
  /*
   * Set the values for parameter type 0 (version number).
   */
  sdu->buf[0] = SNDCP_XID_PARAM_TYPE_0;
  /*lint -e{415} (Warning -- access of out-of-bounds pointer)*/
  sdu->buf[1] = SNDCP_XID_0_LEN;
  /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer)*/
  sdu->buf[2] =
    sndcp_data->mg.res_xid_block[sapi_index].version;

  sdu->l_buf = 3 * 8;
  sdu->o_buf = 0;
  /*
   * Set the values for data compression, if necessary.
   */
  /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer)*/
  if (sndcp_data->mg.res_xid_block[sapi_index].v42.is_set) {
    sdu->buf[3] = SNDCP_XID_PARAM_TYPE_1;
    sdu->buf[4] = SNDCP_XID_1_LEN_RES;
    sdu->buf[5] =
      (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].v42.p_bit << 7) +
            sndcp_data->mg.res_xid_block[sapi_index].v42.ntt;
    sdu->buf[6] = SNDCP_XID_V42_LEN_RES;
    sdu->buf[7] =
      (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].v42.nsapis >> 8);
    sdu->buf[8] =
      (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].v42.nsapis & 0xff);
    sdu->buf[9] = sndcp_data->mg.res_xid_block[sapi_index].v42.p0;
    sdu->buf[10] =
      (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].v42.p1 >> 8);
    sdu->buf[11] =
      (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].v42.p1 & 0xff);
    sdu->buf[12] = sndcp_data->mg.res_xid_block[sapi_index].v42.p2;

    index = 13;
    sdu->l_buf = 13 * 8;

    type_1_header_set = TRUE;
  }
  /*
   * Add rejected data compression entities.
   */
  for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) {
    BOOL rej = FALSE;
    mg_get_sapi_dntt_rej(sapi, ntt, &rej);
    /*lint -e{661, 662} (Warning -- Possible access/creation of out-of-bounds pointer)*/
    if (rej) {
      if (! type_1_header_set) {
        sdu->buf[index] = SNDCP_XID_PARAM_TYPE_1;
        index++;
        sdu->buf[index] = 0;
        index++;
        type_1_header_set = TRUE;
        sdu->l_buf += 16;
      }

      sdu->buf[index] = ntt;
      index++;
      /*
       * Length of field.
       */
      sdu->buf[index] = 2;
      index++;
      /*
       * Set 2 'nsapis' octets to 0.
       */
      sdu->buf[index] = 0;
      index++;
      sdu->buf[index] = 0;
      index++;
      /*
       * Increment sdu length.
       */
      sdu->l_buf = sdu->l_buf + 32;
      /*
       * Increment parameter type 1 length octet.
       */
       /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer)*/
      sdu->buf[4] += 4;
    }
  }
  type_2_header_index = index;

  /*
   * Set the values for header compression, if requested.
   */
   /*lint -e{661, 662} (Warning -- Possible access/creation of out-of-bounds pointer)*/
  if (sndcp_data->mg.res_xid_block[sapi_index].vj.is_set) {
    sdu->buf[index] = SNDCP_XID_PARAM_TYPE_2;
    index++;
    sdu->buf[index] = SNDCP_XID_2_LEN_RES;
    index++;
    sdu->buf[index] =
      (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].vj.p_bit << 7) +
       sndcp_data->mg.res_xid_block[sapi_index].vj.ntt;
    index++;
    sdu->buf[index] = SNDCP_XID_VJ_LEN_RES;
    index++;
    sdu->buf[index] =
      (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].vj.nsapis >> 8);
    index++;
    sdu->buf[index] =
      (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].vj.nsapis & 0xff);
    index++;
    sdu->buf[index] =
      sndcp_data->mg.res_xid_block[sapi_index].vj.s0_m_1;
    index++;

    sdu->l_buf = sdu->l_buf + 7 * 8;

    type_2_header_set = TRUE;
  }
  /*
   * Add rejected header compression entities.
   */
   /*lint -e{661, 662} (Warning -- Possible access/creation of out-of-bounds pointer)*/
  for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) {
    BOOL rej = FALSE;
    mg_get_sapi_pntt_rej(sapi, ntt, &rej);
    if (rej) {
      if (! type_2_header_set) {
        sdu->buf[index] = SNDCP_XID_PARAM_TYPE_2;
        index++;
        sdu->buf[index] = 0;
        index++;
        type_2_header_set = TRUE;
        sdu->l_buf += 16;
      }
      sdu->buf[index] = ntt;
      index++;
      /*
       * Length of field.
       */
      sdu->buf[index] = 2;
      index++;
      /*
       * Set 2 'nsapis' octets to 0.
       */
      sdu->buf[index] = 0;
      index++;
      sdu->buf[index] = 0;
      index++;
      /*
       * Increment sdu length.
       */
      sdu->l_buf = sdu->l_buf + 32;
      /*
       * Increment parameter type 2 length octet.
       */
      sdu->buf[type_2_header_index + 1] += 4;
    }
  }
  /*
   * Set sdu offset to 0.
   */
  sdu->o_buf = 0;
  /*
   * Reset the arrays with rejected params to all FALSE.
   */
  for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) {
    sndcp_data->mg.sapi_dntt_rej_ra[sapi_index][ntt] = FALSE;
    sndcp_data->mg.sapi_pntt_rej_ra[sapi_index][ntt] = FALSE;
  }

} /* mg_set_res_xid_params() */


/*
+------------------------------------------------------------------------------
| Function    : mg_set_xid_params
+------------------------------------------------------------------------------
| Description : This procedure fills the XID block. It is implementation
|               dependent. In the current version V42bis and VanJacobson
|               header compression are applied.
|
| Parameters  :
|               sapi and sdu from the LL_XID_REQ that will be filled and
|               xid_block that defines the desired compressors
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_set_xid_params (UBYTE sapi, T_sdu* sdu, T_XID_BLOCK xid_block)
{
  /*
   * Byte index in destination sdu.
   */
  UBYTE index = 3;
  UBYTE sapi_index = 0;
  UBYTE ntt = 0;
  BOOL type_1_header_set = FALSE;
  BOOL type_2_header_set = FALSE;
  UBYTE type_2_header_index = 0;
  UBYTE type_1_header_index = 3;
  USHORT p1 = SNDCP_V42_DEFAULT_P1;
  TRACE_FUNCTION( "mg_set_xid_params" );
  sndcp_get_sapi_index(sapi, &sapi_index);
  /*
   * Set the values for parameter type 0 (version number).
   */
  sdu->buf[0] = SNDCP_XID_PARAM_TYPE_0;
  /*lint -e{415} (Warning -- access of out-of-bounds pointer)*/
  sdu->buf[1] = SNDCP_XID_0_LEN;
  /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer)*/
  sdu->buf[2] = SNDCP_XID_VERSION;

  sdu->l_buf = 24; /* 3 * 8 */
  sdu->o_buf = 0;
  /*
   * Set the values for data compression, if necessary.
   */
   /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer)*/
  if (xid_block.v42.is_set &&
      #ifdef SNDCP_UPM_INCLUDED 
       xid_block.v42.p0 != NAS_DCOMP_OFF &&
      #else
       xid_block.v42.p0 != SNSM_COMP_NEITHER_DIRECT &&
      #endif  /*#ifdef SNDCP_UPM_INCLUDED*/
      xid_block.v42.nsapis_set &&
      xid_block.v42.nsapis > 0) {

    if (xid_block.v42.p_bit > 0) {
      sdu->buf[3] = SNDCP_XID_PARAM_TYPE_1;
      sdu->buf[4] = SNDCP_XID_1_LEN;
      sdu->buf[5] = (UBYTE)(xid_block.v42.p_bit << 7) + xid_block.v42.ntt;
      sdu->buf[6] = xid_block.v42.algo_type;
      sdu->buf[7] = SNDCP_XID_V42_LEN;
      sdu->buf[8] = (UBYTE)(xid_block.v42.dcomp << 4);
      sdu->buf[9] = (UBYTE)(xid_block.v42.nsapis >> 8);
      sdu->buf[10] = (UBYTE)(xid_block.v42.nsapis & 0xff);
      sdu->buf[11] = xid_block.v42.p0;
      /*
       * P1, P2
       */
      sdu->buf[12] = (p1 & 0xff00) >> 8;
      sdu->buf[13] = p1 & 0x00ff;
      sdu->buf[14] = SNDCP_V42_DEFAULT_P2;

      index = 15;
      sdu->l_buf = 15 * 8;
    } else {
      sdu->buf[3] = SNDCP_XID_PARAM_TYPE_1;
      sdu->buf[4] = SNDCP_XID_1_LEN_RES;
      sdu->buf[5] = xid_block.v42.ntt;
      sdu->buf[6] = SNDCP_XID_V42_LEN_RES;
      sdu->buf[7] = (UBYTE)(xid_block.v42.nsapis >> 8);
      sdu->buf[8] = (UBYTE)(xid_block.v42.nsapis & 0xff);
      sdu->buf[9] = xid_block.v42.p0;
      /*
       * P1, P2
       */
      sdu->buf[10] = (p1 & 0xff00) >> 8;
      sdu->buf[11] = p1 & 0x00ff;
      sdu->buf[12] = SNDCP_V42_DEFAULT_P2;

      index = 13;
      sdu->l_buf = 13 * 8;

    }
  }
  type_2_header_index = index;
  /*
   * Set the values for header compression, if requested.
   */
   /*lint -e{661, 662} (Warning -- Possible access/creation of out-of-bounds pointer)*/
  if (xid_block.vj.is_set &&
      #ifdef SNDCP_UPM_INCLUDED
       xid_block.vj.direction != NAS_HCOMP_OFF &&
      #else
       xid_block.vj.direction != SNSM_COMP_NEITHER_DIRECT &&
      #endif  /*#ifdef SNDCP_UPM_INCLUDED*/
      xid_block.vj.nsapis_set &&
      xid_block.vj.nsapis > 0) {

    if (xid_block.vj.p_bit > 0) {

      sdu->buf[index] = SNDCP_XID_PARAM_TYPE_2;
      sdu->buf[index + 1] = SNDCP_XID_2_LEN;
      sdu->buf[index + 2] =
        (UBYTE)(xid_block.vj.p_bit << 7) + xid_block.vj.ntt;
      sdu->buf[index + 3] = SNDCP_XID_VJ;
      sdu->buf[index + 4] = SNDCP_XID_VJ_LEN;
      sdu->buf[index + 5] =
        (UBYTE)(xid_block.vj.pcomp1 << 4) + xid_block.vj.pcomp2;
      sdu->buf[index + 6] =
        (UBYTE)(xid_block.vj.nsapis >> 8);
      sdu->buf[index + 7] =
        (UBYTE)(xid_block.vj.nsapis & 0xff);
      sdu->buf[index + 8] = xid_block.vj.s0_m_1;

      sdu->l_buf = sdu->l_buf + 9 * 8;

      type_2_header_set = TRUE;
    } else {
      sdu->buf[index] = SNDCP_XID_PARAM_TYPE_2;
      sdu->buf[index + 1] = SNDCP_XID_2_LEN_RES;
      sdu->buf[index + 2] = xid_block.vj.ntt;

      sdu->buf[index + 3] = SNDCP_XID_VJ_LEN_RES;

      sdu->buf[index + 4] =
        (UBYTE)(xid_block.vj.nsapis >> 8);
      sdu->buf[index + 5] =
        (UBYTE)(xid_block.vj.nsapis & 0xff);
      sdu->buf[index + 6] = xid_block.vj.s0_m_1;

      sdu->l_buf = sdu->l_buf + 7 * 8;

      type_2_header_set = TRUE;
    }
  }
  /*
   * Add rejected data compression entities.
   */
   /*lint -e{661, 662} (Warning -- Possible access/creation of out-of-bounds pointer)*/
  for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) {
    BOOL rej = FALSE;
    mg_get_sapi_dntt_rej(sapi, ntt, &rej);
    if (rej) {
      if (! type_1_header_set) {
        sdu->buf[index] = SNDCP_XID_PARAM_TYPE_1;
        index++;
        sdu->buf[index] = 0;
        index++;
        type_1_header_set = TRUE;
        sdu->l_buf += 16;
      }
      sdu->buf[index] = ntt;
      index++;
      /*
       * Length of field.
       */
      sdu->buf[index] = 2;
      index++;
      /*
       * Set 2 'nsapis' octets to 0.
       */
      sdu->buf[index] = 0;
      index++;
      sdu->buf[index] = 0;
      index++;
      /*
       * Increment sdu length.
       */
      sdu->l_buf = sdu->l_buf + 32;
      /*
       * Increment parameter type 2 length octet.
       */
       /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer)*/
      sdu->buf[type_1_header_index + 1] += 4;
    }
  } /* for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++)  */
  /*
   * Add rejected header compression entities.
   */
   /*lint -e{661, 662} (Warning -- Possible access/creation of out-of-bounds pointer)*/
  for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) {
    BOOL rej = FALSE;
    mg_get_sapi_pntt_rej(sapi, ntt, &rej);
    if (rej) {
      if (! type_2_header_set) {
        sdu->buf[index] = SNDCP_XID_PARAM_TYPE_2;
        index++;
        sdu->buf[index] = 0;
        index++;
        type_2_header_set = TRUE;
        sdu->l_buf += 16;
      }
      sdu->buf[index] = ntt;
      index++;
      /*
       * Length of field.
       */
      sdu->buf[index] = 2;
      index++;
      /*
       * Set 2 'nsapis' octets to 0.
       */
      sdu->buf[index] = 0;
      index++;
      sdu->buf[index] = 0;
      index++;
      /*
       * Increment sdu length.
       */
      sdu->l_buf = sdu->l_buf + 32;
      /*
       * Increment parameter type 2 length octet.
       */
      sdu->buf[type_2_header_index + 1] += 4;
    }
  } /* for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++)  */
  /*
   * Set sdu offset to 0.
   */
  sdu->o_buf = 0;
  /*
   * Reset the arrays with rejected params to all FALSE.
   */
  for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) {
    sndcp_data->mg.sapi_dntt_rej_ra[sapi_index][ntt] = FALSE;
    sndcp_data->mg.sapi_pntt_rej_ra[sapi_index][ntt] = FALSE;
  }

} /* mg_set_xid_params() */



/*
+------------------------------------------------------------------------------
| Function    : mg_del_comp_pdus_ack
+------------------------------------------------------------------------------
| Description : The function mg_del_comp_pdus_ack()
|               GSM 4.65, 5.1.2.7:
|               "compressed N-PDUs queuing to be forwarded to the affected
|               SAPI are deleted from the SNDCP layer."
|               Assumption: It is assumed here that acknowledged and
|               unacknowledged npdus are deleted the same.
|
| Parameters  : UBYTE sapi: the affected sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_del_comp_pdus_ack (UBYTE sapi)
{
  UBYTE nsapi = 0;

  TRACE_FUNCTION( "mg_del_comp_pdus_ack" );

  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
    UBYTE sp = 0;
    sndcp_get_nsapi_sapi(nsapi, &sp);
    if (sp == sapi) {
      sig_mg_cia_delete_npdus(nsapi);
      sig_mg_su_delete_pdus(nsapi, sapi);
      sig_mg_sua_delete_pdus(nsapi, sapi, TRUE);
      sig_mg_sd_delete_npdus(nsapi, sapi);
      sig_mg_sda_delete_npdus(nsapi, sapi);
    }
  }
} /* mg_del_comp_pdus_ack() */

/*
+------------------------------------------------------------------------------
| Function    : mg_delete_npdus
+------------------------------------------------------------------------------
| Description : The function mg_delete_npdus() sends signals to all affected
|               services to delete the buffered npdus.
|
| Parameters  : UBYTE nsapi: the affected nsapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_delete_npdus (UBYTE nsapi)
{
  UBYTE sapi = 0;
  TRACE_FUNCTION( "mg_delete_npdus" );
  sndcp_get_nsapi_sapi(nsapi, &sapi);

  sig_mg_cia_delete_npdus(nsapi);
  sig_mg_su_delete_pdus(nsapi, sapi);
  sig_mg_sua_delete_pdus(nsapi, sapi, TRUE);
  sig_mg_sd_delete_npdus(nsapi, sapi);
  sig_mg_sda_delete_npdus(nsapi, sapi);

  sig_mg_nu_delete_npdus(nsapi);

} /* mg_delete_npdus() */


/*
+------------------------------------------------------------------------------
| Function    : mg_suspend_affected_nus
+------------------------------------------------------------------------------
| Description : Suspends all nu service instances affected by XID negotiation
|               Sets service variable 'suspended_nsapis'.
|
| Parameters  : sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_suspend_affected_nus (UBYTE sapi) {
  UBYTE nsapi = 0;
  UBYTE sapi_index = 0;
  TRACE_FUNCTION( "mg_resume_affected_nus" );
  sndcp_get_sapi_index(sapi, &sapi_index);
  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
    if (1 << nsapi & sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis ||
        1 << nsapi & sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis ||
        1 << nsapi & sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis ||
        1 << nsapi & sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis) {

      sndcp_data->mg.suspended_nsapis |= (1 << nsapi);
      sig_mg_nu_suspend(nsapi);
    }
  }
} /* mg_suspend_affected_nus() */






/*
 * Getters and setters for the organizing arrays.
 */
/*
+------------------------------------------------------------------------------
| Function    : mg_get_sapi_dntt_rej
+------------------------------------------------------------------------------
| Description : The procedures informs about if a given data
|               compression entity on a given SAPI is to be rejected in
|               LL_XID_REQ because it cannot be set up.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN dntt UBYTE,
|               IN/OUT rej BOOL
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_get_sapi_dntt_rej (UBYTE sapi, UBYTE dntt, BOOL* rej)
{
  TRACE_FUNCTION( "mg_get_sapi_dntt_rej" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    *rej = sndcp_data->mg.sapi_dntt_rej_ra[sapi_index][dntt];
  }
} /* mg_get_sapi_dntt_rej() */

/*
+------------------------------------------------------------------------------
| Function    : mg_get_sapi_pntt_rej
+------------------------------------------------------------------------------
| Description : The procedures informs about if a given header
|               compression entity on a given SAPI is to be rejected in
|               LL_XID_REQ because it cannot be set up.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN pntt UBYTE,
|               IN/OUT rej BOOL
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_get_sapi_pntt_rej (UBYTE sapi, UBYTE pntt, BOOL* rej)
{
  TRACE_FUNCTION( "mg_get_sapi_pntt_rej" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    *rej = sndcp_data->mg.sapi_pntt_rej_ra[sapi_index][pntt];
  }
} /* mg_get_sapi_pntt_rej() */




/*
+------------------------------------------------------------------------------
| Function    : mg_get_sapi_pntt_nsapi
+------------------------------------------------------------------------------
| Description : The procedure informs if a given nsapi uses a given pntt on a
|               given sapi.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN pntt UBYTE,
|               IN nsapi UBYTE,
|               IN/OUT used BOOL
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_get_sapi_pntt_nsapi (UBYTE sapi, UBYTE pntt, UBYTE nsapi, BOOL* used)
{
  TRACE_FUNCTION( "mg_get_sapi_pntt_nsapi" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    *used = sndcp_data->mg.sapi_pntt_nsapi_set_ra[sapi_index][pntt][nsapi];
  }
} /* mg_get_sapi_pntt_nsapi() */




/*
+------------------------------------------------------------------------------
| Function    : mg_get_sapi_pcomp_pntt
+------------------------------------------------------------------------------
| Description : The procedures indicates the pntt assigned to a given pcomp
|               for a given sapi.
|
| Parameters  : FPAR IN sapi UBYTE,
|               IN pcomp UBYTE,
|               IN/OUT dntt UBYTE
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_get_sapi_pcomp_pntt (UBYTE sapi, UBYTE pcomp, UBYTE* pntt)
{
  TRACE_FUNCTION( "mg_get_sapi_pcomp_pntt" );
  {
    UBYTE sapi_index = 0;
    sndcp_get_sapi_index(sapi, &sapi_index);
    *pntt = sndcp_data->mg.sapi_pcomp_pntt_ra[sapi_index][pcomp];
  }
} /* mg_get_sapi_pcomp_pntt() */



/*
+------------------------------------------------------------------------------
| Function    : mg_xid_cnf_ok_res
+------------------------------------------------------------------------------
| Description :
| After an LL_XID_REQ has been sent there are contexts in state MG_XID.
| These are now reset after reception of the LL_XID_CNF.
| The "applicable nsapis" in req_xid_block.v42 and req_xid_block.vj, each one
| only once.
| SIG_MG_NU_RESET(nsapi, discard_ready) is used.
| In every nu instance: N-PDU number is set to 0 for this instance and an
| SN_UNITREADY_IND is sent. State is set to NU_UNACK_SU_RECEPTIVE
| Then the SNSM_ACTIVATE_RES is sent for each one of these.
|
| Parameters  : affected sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_xid_cnf_ok_res (UBYTE sapi)
{
  UBYTE nsapi = 0;

  TRACE_FUNCTION( "mg_xid_cnf_ok_res" );
  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) {
    USHORT nsapi_state = MG_IDLE;
    USHORT sapi_state = MG_IDLE;
    UBYTE sapi_index = 0;
    UBYTE func_sapi = 0;
    sndcp_get_nsapi_sapi(nsapi, &func_sapi);
    if (func_sapi != sapi) {
      continue;
    }
    sndcp_get_sapi_index(sapi, &sapi_index);
    sndcp_get_nsapi_state(nsapi, &nsapi_state);
    sndcp_get_sapi_state(func_sapi, &sapi_state);


    if (((sapi_state & MG_XID_NEC) > 0)
        &&
        ((sapi_state & MG_REL) == 0)) {
      mg_resend_xid_if_nec(sapi);

      sndcp_get_sapi_state(func_sapi, &sapi_state);
      /*
       * If now XID is sent, no further actions for this nsapi.
       */
      if ((sapi_state & MG_XID) > 0) {
        continue;
      }

    } else if ((nsapi_state & MG_ACT) > 0 &&
        (sapi_state & MG_EST) == 0) {

      BOOL ack = FALSE;

      sndcp_get_nsapi_ack(nsapi, &ack);
      /*
       * Open DTI connection.
       */
#ifndef SNDCP_UPM_INCLUDED 
      mg_dti_open(nsapi);
#endif 
      if (ack) {
        sig_mg_nu_reset_ack(nsapi, 0, 0, FALSE);
        sig_mg_sda_getdata(sapi, nsapi);
      } else {
        sig_mg_nu_reset(nsapi, FALSE);
        sig_mg_sd_getunitdata(sapi, nsapi);
      }

      if ((sapi_state & MG_XID) == 0) {
        mg_send_snsm_activate_res(nsapi);
        /*
         * Set nsapi state to MG_IDLE.
         */
        sndcp_unset_nsapi_state(nsapi, MG_ACT);
      }
    } /* if state is MG_ACT and not MG_EST  */

    if ((nsapi_state & MG_DEACT) > 0) {

      USHORT local_sapi_state = MG_IDLE;

      sndcp_get_sapi_state(sapi, &local_sapi_state);

      if ((local_sapi_state &
            (MG_REL_NEC_LOC + MG_REL_NEC_PEER + MG_XID_NEC + MG_XID))
          == 0)
      {
        /*
         * No LL_RELEASE_REQ necessary. Notify sndcp.
         */
#ifdef SNDCP_UPM_INCLUDED 
        PALLOC(snsm_deactivate_res, SN_DEACTIVATE_CNF);
#else
        PALLOC(snsm_deactivate_res, SNSM_DEACTIVATE_RES);
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
        /*
         * Now the NSAPI is not in use anymore:
         */
        sndcp_set_nsapi_used(nsapi, FALSE);
        sndcp_set_nsapi_ack(nsapi, FALSE);

        snsm_deactivate_res->nsapi = nsapi;
        sndcp_unset_nsapi_state(nsapi, MG_DEACT);
#ifdef SNDCP_UPM_INCLUDED 
        PSEND(hCommUPM, snsm_deactivate_res);
#else
        PSEND(hCommSM, snsm_deactivate_res);
#endif  /*#ifdef SNDCP_UPM_INCLUDED*/
        /*
         * Resume nsapi.
         */
        mg_resume_affected_nus(sapi);

      } else if ((local_sapi_state & (MG_REL_NEC_LOC + MG_REL_NEC_PEER)) > 0) {
        /*
         * LL_RELEASE_REQ must be sent.
         */

        PALLOC(ll_release_req, LL_RELEASE_REQ);

        sndcp_unset_sapi_state(sapi, MG_REL_NEC_LOC);
        ll_release_req->sapi = sapi;
        ll_release_req->local = TRUE;
        /*
         * Set the "state" for the affected and sapi to MG_REL_PENDING.
         */
        sndcp_set_sapi_state(sapi, MG_REL);

        PSEND(hCommLLC, ll_release_req);
      } else {

        UBYTE local_sapi = 0;
        UBYTE local_nsapi = 0;
        BOOL local_nec = FALSE;
        for (local_nsapi = 0;
             local_nsapi < SNDCP_NUMBER_OF_NSAPIS;
             local_nsapi++) {

          sndcp_get_nsapi_sapi(local_nsapi, &local_sapi);
          if (sapi == local_sapi) {
            /*
             * is compressor deactivation necessary?
             */
            sndcp_get_nsapi_state(local_nsapi, &nsapi_state);
            if ((nsapi_state & MG_DEACT) > 0) {
              mg_is_rel_comp_nec(local_nsapi, &local_nec);
            }
          }
        }

        /*
         * Negotiate possible deactivation of compressors.
         */
        if (local_nec) {
          mg_send_xid_req_del(sapi);
        }
      }

    }

  }

} /* mg_xid_cnf_ok_res */


#ifdef TI_DUAL_MODE
/*
+------------------------------------------------------------------------------
| Function    : mg_get_unsent_unconfirmed_npdus
+------------------------------------------------------------------------------
| Description : This procedure retrieves any unsent or unconfirmed acknowledged
|               NPDU from SNDCP's internal buffers. ANY retrieved NPDU is packed
|               the primitive SN_GET_PENDING_PDU_CNF data.
|
| Parameters  : nsapi, pointer to the primitive.
|
+------------------------------------------------------------------------------
*/
GLOBAL T_SN_GET_PENDING_PDU_CNF* mg_get_unsent_unconfirmed_npdus
                             (U8 nsapi, 
                              T_SN_GET_PENDING_PDU_CNF* sn_get_pending_pdu_cnf)
{

  int count = 0;
  U8 used_sapi=0, sapi_index=0;
  T_NPDU_BUFFER* help = NULL;

  TRACE_FUNCTION( "mg_get_unsent_unconfirmed_npdus" );

  /*
   * set service instance according to nsapi in primitive
   */
  sndcp_data->nu = & sndcp_data->nu_base[nsapi];

  /*
   * Find number of unconfirmed NPDUs
   */
  help = sndcp_data->nu->first_buffered_npdu;
  while(help != NULL)
  {
    count++;
    help = help->next;
  }

  sn_get_pending_pdu_cnf->ul_pdus[nsapi].ptr_desc_list2 = 
           (T_SN_desc_list2*)DRP_ALLOC( count * sizeof( T_SN_desc_list2 ), 0 );

  sn_get_pending_pdu_cnf->ul_pdus[nsapi].nsapi = nsapi;
  sn_get_pending_pdu_cnf->ul_pdus[nsapi].dl_sequence_number = 
                                           sndcp_data->nu->rec_npdu_number_ack;
  sn_get_pending_pdu_cnf->ul_pdus[nsapi].c_desc_list2 = count;

  count = 0;

  /*
   * Check if there are buffered any acknowledged type NPDUs.
   */
  help = sndcp_data->nu->first_buffered_npdu;
  while(help != NULL)
  {

    sn_get_pending_pdu_cnf->ul_pdus[nsapi].ptr_desc_list2[count].first = 
                                        help->sn_data_req->desc_list2.first;
    sn_get_pending_pdu_cnf->ul_pdus[nsapi].ptr_desc_list2[count].list_len = 
                                        help->sn_data_req->desc_list2.list_len;
    count++;
    help = help->next;
  }
  return sn_get_pending_pdu_cnf;
}

/*
+------------------------------------------------------------------------------
| Function    : mg_clean_ack_npdu_queues_leave_data
+------------------------------------------------------------------------------
| Description : This procedure deletes SNDCP's internal buffers containing
|               unconfirmed acknowledged type NPDU's.
|               The data stored in the queues are not deleted.
|
| Parameters  : nsapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_clean_ack_npdu_queues_leave_data(U8 nsapi)
{

  U8 used_sapi=0, sapi_index=0;
  T_NPDU_BUFFER* help = NULL;
  T_SN_DATA_REQ* sn_data_req = NULL;

  TRACE_FUNCTION( "mg_clean_ack_npdu_queues_leave_data" );

   /*
    * set service instance according to sapi
    */
  sndcp_get_nsapi_sapi(nsapi, &used_sapi);
  sndcp_get_sapi_index(used_sapi, &sapi_index);
  sndcp_data->sua = & sndcp_data->sua_base[sapi_index];

  if (sndcp_data->sua->sn_data_q_write != sndcp_data->sua->sn_data_q_read) 
  {
    /*
     * remove unhandled sn_data_req from queue.
     */
    sn_data_req = sndcp_data->sua->sn_data_q[sndcp_data->sua->sn_data_q_read];
    FREE(sn_data_req);
  }

  /*
   * set service instance according to nsapi
   */

  sndcp_data->nu = & sndcp_data->nu_base[nsapi];

  /*
   * clean buffer with unconfirmed NPDUs
   */

  while(sndcp_data->nu->first_buffered_npdu != NULL)
  {
    help = sndcp_data->nu->first_buffered_npdu;
    sndcp_data->nu->first_buffered_npdu = help->next;
    MFREE(help->sn_data_req);
    MFREE(help);
  }
}


/*
+------------------------------------------------------------------------------
| Function    : mg_clean_unack_npdu_queues_including_data
+------------------------------------------------------------------------------
| Description : This procedure deletes SNDCP's internal buffers containing
|               unacknowledged type NPDU's.
|               The data stored in the queues are also deleted.
|
| Parameters  : nsapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void mg_clean_unack_npdu_queues_including_data(U8 nsapi)
{
  /*
   * Delete affected N-PDUS from sn_unitdata_q.
   */
  BOOL still = TRUE;
  U8 index = sndcp_data->su->sn_unitdata_q_read;

  while (still) 
  {
    if (index == sndcp_data->su->sn_unitdata_q_write) {
      break;
    }
    if (sndcp_data->su->sn_unitdata_q[index]->nsapi == nsapi) {
      /*
       * The index for the prims to be shifted when 1 entry is deleted.
       */
      U8 i = 0;

      if (sndcp_data->su->sn_unitdata_q[index] != NULL) {
        PFREE_DESC2(sndcp_data->su->sn_unitdata_q[index]);
        sndcp_data->su->sn_unitdata_q[index] = NULL;
      }

      for (i = index;
           i != sndcp_data->su->sn_unitdata_q_write;
           i = (i + 1) % SN_UNITDATA_Q_LEN) 
           {
              sndcp_data->su->sn_unitdata_q[i] =
                sndcp_data->su->sn_unitdata_q[(i + 1) % SN_UNITDATA_Q_LEN];

              sndcp_data->su->sn_unitdata_q[(i + 1) % SN_UNITDATA_Q_LEN]=NULL;
           }
      sndcp_data->su->sn_unitdata_q_write =
        (sndcp_data->su->sn_unitdata_q_write - 1
         + SN_UNITDATA_Q_LEN) % SN_UNITDATA_Q_LEN;
    } 
    else 
    {
      index = (index + 1) % SN_UNITDATA_Q_LEN;
    } /* else (sndcp_data->su->sn_unitdata_q[index]->nsapi == nsapi) */
  }
}

/*
+------------------------------------------------------------------------------
| Function    : sm_make_test_pending_pdu_cnf
+------------------------------------------------------------------------------
| Description : Initialize SN_TEST_GET_PENDING_PDU_CNF primitive
| Parameters  : sn_get_pending_pdu_cnf - primitive  
|               sn_test_get_pending_pdu_cnf - primitive 
|
+------------------------------------------------------------------------------
*/

GLOBAL void sm_make_test_pending_pdu_cnf
                   (T_SN_GET_PENDING_PDU_CNF* sn_get_pending_pdu_cnf,
                    T_SN_TEST_GET_PENDING_PDU_CNF* sn_test_get_pending_pdu_cnf)
{
  int i,j;

  for (i = 0; i < SN_SIZE_NSAPI; i++) {
    sn_test_get_pending_pdu_cnf->c_test_ul_pdus = 
                         sn_get_pending_pdu_cnf->c_ul_pdus;
    sn_test_get_pending_pdu_cnf->test_ul_pdus[i].nsapi = 
                         sn_get_pending_pdu_cnf->ul_pdus[i].nsapi;
    sn_test_get_pending_pdu_cnf->test_ul_pdus[i].test_dl_sequence_number = 
                         sn_get_pending_pdu_cnf->ul_pdus[i].dl_sequence_number;
    sn_test_get_pending_pdu_cnf->test_ul_pdus[i].c_test_desc_list2 = 
                         sn_get_pending_pdu_cnf->ul_pdus[i].c_desc_list2;

    if (sn_get_pending_pdu_cnf->ul_pdus[i].c_desc_list2) {
      for(j = 0; j < sn_get_pending_pdu_cnf->ul_pdus[i].c_desc_list2; j++) {
        sn_test_get_pending_pdu_cnf->test_ul_pdus[i].c_test_desc_list2 = 
                 sn_get_pending_pdu_cnf->ul_pdus[i].c_desc_list2;
        sn_test_get_pending_pdu_cnf->test_ul_pdus[i].test_desc_list2[j].c_test_pending_pdu = 
             (U8)sn_get_pending_pdu_cnf->ul_pdus[i].ptr_desc_list2[j].list_len;
        memcpy(
          sn_test_get_pending_pdu_cnf->test_ul_pdus[i].test_desc_list2[j].test_pending_pdu,
          ((T_desc2 *)sn_get_pending_pdu_cnf->ul_pdus[i].ptr_desc_list2[j].first)->buffer, 
          sn_get_pending_pdu_cnf->ul_pdus[i].ptr_desc_list2[j].list_len);
      }
    }
  }
}

#endif /*#ifdef TI_DUAL_MODE*/