diff src/g23m-gprs/sndcp/sndcp_cias.c @ 183:219afcfc6250

src/g23m-gprs: initial import from TCS3.2/LoCosto
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 13 Oct 2016 04:24:13 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/g23m-gprs/sndcp/sndcp_cias.c	Thu Oct 13 04:24:13 2016 +0000
@@ -0,0 +1,2710 @@
+/*
++-----------------------------------------------------------------------------
+|  Project :  GPRS (8441)
+|  Modul   :  sndcp_cias.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.
+|
+|  These files implement Van Jacobson Compression algorithm which is taken from
+|  University of California Berkley's Implementation.
+|
+|
+|  "Copyright (c)1989 Regents of the University of California.
+|  All rights reserved.Redistribution and use in source and binary forms are
+|  permitted, provided that the above  copyright notice and this paragraph are
+|  duplicated in all such forms and that any documentation advertising materials,
+|  and  other materials related to such distributionand use acknowledge that the
+|  software was developed by the University of California, Berkeley.
+|  The name of the University may not be  used to endorse or promote products
+|  derived from this software without specific  prior written permission. 
+|  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+|  INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND 
+|  FITNESS FOR A PARTICULAR PURPOSE"
++-----------------------------------------------------------------------------
+|  Purpose :  This modul is part of the entity SNDCP and implements all
+|             functions to handles the incoming process internal signals as
+|             described in the SDL-documentation (CIA-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 <string.h>      /* to get memcpy() */
+#include "sndcp_cias.h"  /* to get the signals to service cia */
+#include "sndcp_ciap.h"  /* to get primitives to service cia */
+#include "sndcp_ciaf.h"  /* to get primitives to service cia */
+#include "sndcp_sdf.h"   /* to get sd functions */
+#include "sndcp_sdaf.h"  /* to get sda functions */
+#include "sndcp_sds.h"   /* to get sd signals */
+
+#ifdef TI_PS_FF_V42BIS
+#include "v42b_type.h"
+#include "v42b_dico.h"
+#include "v42b_enc.h"
+#include "v42b_dec.h"
+#include "v42b_debug.h"
+#endif /* TI_PS_FF_V42BIS */
+
+/*==== CONST ================================================================*/
+
+/*==== LOCAL VARS ===========================================================*/
+
+/*==== PRIVATE FUNCTIONS ====================================================*/
+
+/*
+ * Update connection state cs & send uncompressed packet ('uncompressed'
+ * means a regular ip/tcp packet but with the 'conversation id' we hope
+ * to use on future compressed packets in the protocol field).
+ */
+#define UNCOMPRESSED {\
+  memcpy(cs->cs_hdr, (UBYTE*)cbuf->c_hdr, tip_hlen);\
+  ip->ip_p = cs->cs_id;\
+  sndcp_data->cia.comp.last_xmit = cs->cs_id;\
+}
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : cia_vj_comp
++------------------------------------------------------------------------------
+| Description : compresses the TCP/IP header of the given packet
+|               (Van Jacobson algorithm). A part of this routine has been taken
+|               from implementation of University of California, Berkeley.
+|
+| Parameters  : com_buf - received packet, packet length, packet type
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+LOCAL UBYTE cia_vj_comp(struct comp_buf *cbuf)
+{
+  struct cstate            *cs  = sndcp_data->cia.comp.last_cs->cs_next;
+  T_SNDCP_TCP_HEADER       *oth, *oth_tmp;     /* last TCP header */
+  T_SNDCP_TCP_HEADER       *th;                /* current TCP header */
+  T_SNDCP_IP_HEADER        *ip;                /* current IP header */
+  USHORT                   ip_hlen, tip_hlen;  /* IP hdr len., TCP/IP hdr len*/
+  USHORT                   tmp1, tmp2;         /* general purpose tempories */
+  ULONG                    changes = 0;        /* change mask */
+  UBYTE                    new_seq[16];       /* changes from last to current*/
+  UBYTE                    *cp = new_seq;
+  UBYTE                    th_off, oth_off;
+  BOOL                     found = FALSE;
+  USHORT                   th_sum;
+  ULONG                    seq, o_seq;
+
+  ip      = (T_SNDCP_IP_HEADER *)cbuf->c_hdr;
+  ip_hlen = ip->ip_vhl & HL_MASK;            /* IP header length in integers */
+  th      = (T_SNDCP_TCP_HEADER *)&((ULONG *)cbuf->c_hdr)[ip_hlen];
+  th_off  = th->th_off >> 4;
+
+  TRACE_FUNCTION( "cia_vj_comp" );
+
+  /*
+   * Bail if this is an IP fragment or if the TCP packet isn't
+   * `compressible' (i.e., ACK isn't set or some other control bit is
+   * set).  (We assume that the caller has already made sure the
+   * packet is IP proto TCP).
+   */
+  if (ip->ip_off & 0xff3f)
+  {
+    TRACE_EVENT("INFO COMP: return TYPE_IP, packet is an IP fragment");
+    return (TYPE_IP);
+  }
+
+  if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK)
+  {
+    TRACE_EVENT("INFO COMP: return TYPE_IP, TH_ACK is not set");
+    return (TYPE_IP);
+  }
+  /*
+   * Packet is compressible -- we're going to send either a
+   * COMPRESSED_TCP or UNCOMPRESSED_TCP packet.  Either way we need
+   * to locate (or create) the connection state.  Special case the
+   * most recently used connection since it's most likely to be used
+   * again & we don't have to do any reordering if it's used.
+   */
+  oth_tmp  = (T_SNDCP_TCP_HEADER *)
+             &((ULONG *)cs->cs_hdr)[cs->cs_ip->ip_vhl & HL_MASK];
+  if ((ip->ip_src   != cs->cs_ip->ip_src) ||
+      (ip->ip_dst   != cs->cs_ip->ip_dst) ||
+      (*(ULONG *)th != *(ULONG *)oth_tmp)){
+    /*
+     * Wasn't the first -- search for it.
+     *
+     * States are kept in a circularly linked list with
+     * last_cs pointing to the end of the list.  The
+     * list is kept in lru order by moving a state to the
+     * head of the list whenever it is referenced.  Since
+     * the list is short and, empirically, the connection
+     * we want is almost always near the front, we locate
+     * states via linear search.  If we don't find a state
+     * for the datagram, the oldest state is (re-)used.
+     */
+    struct cstate *lcs;
+    struct cstate *lastcs = sndcp_data->cia.comp.last_cs;
+
+    do {
+      lcs = cs;
+      cs = cs->cs_next;
+      oth_tmp  = (T_SNDCP_TCP_HEADER *)
+                 &((ULONG *)cs->cs_hdr)[cs->cs_ip->ip_vhl & HL_MASK];
+      if ((ip->ip_src   == cs->cs_ip->ip_src) &&
+          (ip->ip_dst   == cs->cs_ip->ip_dst) &&
+          (*(ULONG *)th == *(ULONG *)oth_tmp)){
+        found = TRUE;
+        break;
+      }
+
+    } while (cs != lastcs);
+
+    if(found)
+    {
+      /*
+       * Found it -- move to the front on the connection list.
+       */
+      if (cs == lastcs)
+        sndcp_data->cia.comp.last_cs = lcs;
+      else {
+        lcs->cs_next = cs->cs_next;
+        cs->cs_next = lastcs->cs_next;
+        lastcs->cs_next = cs;
+      }
+    } else {
+      /*
+       * Didn't find it -- re-use oldest cstate.  Send an
+       * uncompressed packet that tells the other side what
+       * connection number we're using for this conversation.
+       * Note that since the state list is circular, the oldest
+       * state points to the newest and we only need to set
+       * last_cs to update the lru linkage.
+       */
+      sndcp_data->cia.comp.last_cs = lcs;
+      tip_hlen = (ip_hlen+th_off)<<2;
+      UNCOMPRESSED;
+      return (TYPE_UNCOMPRESSED_TCP);
+    }/*if din't find*/
+  }
+
+  /*
+   * Make sure that only what we expect to change changed. The first
+   * line of the `if' checks the IP protocol version, header length &
+   * type of service.  The 2nd line checks the "Don't fragment" bit.
+   * The 3rd line checks the time-to-live and protocol (the protocol
+   * check is unnecessary but costless).  The 4th line checks the TCP
+   * header length.  The 5th line checks IP options, if any.  The 6th
+   * line checks TCP options, if any.  If any of these things are
+   * different between the previous & current datagram, we send the
+   * current datagram `uncompressed'.
+   */
+  oth = (T_SNDCP_TCP_HEADER *)&((ULONG *)cs->cs_ip)[ip_hlen];
+  oth_off  = oth->th_off >> 4;
+  tip_hlen = (ip_hlen+th_off)<<2;
+
+  if (((USHORT *)ip)[0] != ((USHORT *)cs->cs_ip)[0] ||
+      ((USHORT *)ip)[3] != ((USHORT *)cs->cs_ip)[3] ||
+      ((USHORT *)ip)[4] != ((USHORT *)cs->cs_ip)[4] ||
+      (th_off           != oth_off)                 ||
+      ((ip_hlen > 5) && (memcmp(ip + 1, cs->cs_ip + 1, (ip_hlen - 5) << 2))) ||
+      ((th_off  > 5) && (memcmp(th + 1, oth + 1, (th_off - 5) << 2)))) {
+
+    UNCOMPRESSED;
+    return (TYPE_UNCOMPRESSED_TCP);
+  }
+
+  /*
+   * Figure out which of the changing fields changed.  The
+   * receiver expects changes in the order: urgent, window,
+   * ack, seq (the order minimizes the number of temporaries
+   * needed in this section of code).
+   */
+  if (th->th_flags & TH_URG) {
+    tmp1 = sndcp_swap2(th->th_urp);
+    if (tmp1 >= 256 || tmp1 == 0) {
+      *cp++ = 0;
+      cp[1] = (UBYTE)tmp1;
+      cp[0] = (tmp1 & 0xff00) >> 8;
+      cp += 2;
+    } else {
+      *cp++ = (UBYTE)tmp1;
+    }
+    changes |= NEW_U;
+  } else if (th->th_urp != oth->th_urp){
+    /* argh! URG not set but urp changed -- a sensible
+     * implementation should never do this but RFC793
+     * doesn't prohibit the change so we have to deal
+     * with it. */
+    UNCOMPRESSED;
+    return (TYPE_UNCOMPRESSED_TCP);
+  }
+  if ((tmp1 = sndcp_swap2(th->th_win) - sndcp_swap2(oth->th_win)) != 0) {
+    if (tmp1 >= 256) {
+      *cp++ = 0;
+      cp[1] = (UBYTE)tmp1;
+      cp[0] = (tmp1 & 0xff00) >> 8;
+      cp += 2;
+    } else {
+      *cp++ = (UBYTE)tmp1;
+    }
+    changes |= NEW_W;
+  }
+
+  if ((tmp2 = (USHORT)(sndcp_swap4(th->th_ack)-sndcp_swap4(oth->th_ack)))!=0){
+    if (tmp2 > MAX_CHANGE){
+      UNCOMPRESSED;
+      return (TYPE_UNCOMPRESSED_TCP);
+    }
+    if (tmp2 >= 256) {
+      *cp++ = 0;
+      cp[1] = (UBYTE)tmp2;
+      cp[0] = (tmp2 & 0xff00) >> 8;
+      cp += 2;
+    } else {
+      *cp++ = (UBYTE)tmp2;
+    }
+    changes |= NEW_A;
+  }
+
+  seq   = sndcp_swap4(th->th_seq);
+  o_seq = sndcp_swap4(oth->th_seq);
+  if(seq < o_seq) {
+    TRACE_EVENT("WARNING COMP: seq < o_seq, return UNCOMPRESSED_TCP ");
+    UNCOMPRESSED;
+    return (TYPE_UNCOMPRESSED_TCP);
+  } else if((tmp1 = (USHORT)(seq - o_seq)) != 0) {
+    if (tmp1 > MAX_CHANGE){
+      UNCOMPRESSED;
+      return (TYPE_UNCOMPRESSED_TCP);
+    }
+    if (tmp1 >= 256) {
+      *cp++ = 0;
+      cp[1] = (UBYTE)tmp1;
+      cp[0] = (tmp1 & 0xff00) >> 8;
+      cp += 2;
+    } else {
+      *cp++ = (UBYTE)tmp1;
+    }
+    changes |= NEW_S;
+  }
+
+  /* look for special case encodings. */
+  switch (changes) {
+
+  case 0:
+    /*
+     * Nothing changed. If this packet contains data and the
+     * last one didn't, this is probably a data packet following
+     * an ack (normal on an interactive connection) and we send
+     * it compressed.  Otherwise it's probably a retransmit,
+     * retransmitted ack or window probe.  Send it uncompressed
+     * in case the other side missed the compressed version.
+     */
+    if ((ip->ip_len != cs->cs_ip->ip_len) &&
+        (sndcp_swap2(cs->cs_ip->ip_len) == tip_hlen))
+      break;
+
+    /* (fall through) */
+
+  case SPECIAL_I:
+  case SPECIAL_D:
+    /*
+     * actual changes match one of our special case encodings --
+     * send packet uncompressed.
+     */
+    UNCOMPRESSED;
+    return (TYPE_UNCOMPRESSED_TCP);
+
+  case NEW_S|NEW_A:
+    if ((tmp1 == tmp2) &&
+        (tmp1 == sndcp_swap2(cs->cs_ip->ip_len) - tip_hlen)) {
+      /* special case for echoed terminal traffic */
+      changes = SPECIAL_I;
+      cp = new_seq;
+    }
+    break;
+
+  case NEW_S:
+    if (tmp1 == sndcp_swap2(cs->cs_ip->ip_len) - tip_hlen) {
+      /* special case for data xfer */
+      changes = SPECIAL_D;
+      cp = new_seq;
+    }
+    break;
+  }
+
+  tmp1 = sndcp_swap2(ip->ip_id) - sndcp_swap2(cs->cs_ip->ip_id);
+  if (tmp1 != 1) {
+    if ((tmp1 >= 256) || (tmp1 == 0)) {
+      *cp++ = 0;
+      cp[1] = (UBYTE)tmp1;
+      cp[0] = (tmp1 & 0xff00) >> 8;
+      cp += 2;
+    } else {
+      *cp++ = (UBYTE)tmp1;
+    }
+    changes |= NEW_I;
+  }
+
+  if (th->th_flags & TH_PUSH)
+    changes |= TCP_PUSH_BIT;
+  /*
+   * Grab the cksum before we overwrite it below.  Then update our
+   * state with this packet's header.
+   */
+  th_sum = sndcp_swap2(th->th_sum);
+  memcpy(cs->cs_ip, ip, tip_hlen);
+
+  /*
+   * We want to use the original packet as our compressed packet.
+   * (cp - new_seq) is the number of bytes we need for compressed
+   * sequence numbers.  In addition we need one byte for the change
+   * mask, one for the connection id and two for the tcp checksum.
+   * So, (cp - new_seq) + 4 bytes of header are needed.  hlen is how
+   * many bytes of the original packet to toss so subtract the two to
+   * get the new packet size.
+   */
+  tmp1 = cp - new_seq;
+  cp = (UBYTE *)ip;
+
+  /*
+   * we always send a "new" connection id so the receiver state
+   * stays synchronized.
+   */
+  sndcp_data->cia.comp.last_xmit = cs->cs_id;
+  tip_hlen -= tmp1 + 4;
+  cp       += tip_hlen;
+  *cp++ = (UBYTE)(changes | NEW_C);
+  *cp++ = cs->cs_id;
+
+  cbuf->pack_len -= tip_hlen;
+  cbuf->hdr_len  -= tip_hlen;
+  cbuf->c_hdr    += tip_hlen;
+  *cp++ = th_sum >> 8;
+  *cp++ = (UBYTE)(th_sum & 0x00ff);
+  memcpy(cp, new_seq, tmp1);
+  return (TYPE_COMPRESSED_TCP);
+}
+
+#endif /* CF_FAST_EXEC */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : cia_header_comp
++------------------------------------------------------------------------------
+| Description : compresses the TCP/IP header of the given packet
+|               (Van Jacobson algorithm)
+|
+| Parameters  : packet as desc_list, packet_type.
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+#ifdef _SNDCP_DTI_2_
+GLOBAL void cia_header_comp (T_desc_list2* dest_desc_list,
+                                T_desc_list2* src_desc_list,
+                                UBYTE* packet_type)
+#else /*_SNDCP_DTI_2_*/
+GLOBAL void cia_header_comp (T_desc_list* dest_desc_list,
+                                T_desc_list* src_desc_list,
+                                UBYTE* packet_type)
+#endif /*_SNDCP_DTI_2_*/
+{
+
+#ifdef _SNDCP_DTI_2_
+  T_desc2* src_desc = (T_desc2*)src_desc_list->first;
+  T_desc2* new_desc;
+  U8 *src_desc_buff = &src_desc->buffer[src_desc->offset];
+#else /*_SNDCP_DTI_2_*/
+  T_desc*  src_desc = (T_desc*)src_desc_list->first;
+  T_desc*  new_desc;
+  U8 *src_desc_buff = &src_desc->buffer[0];
+#endif /*_SNDCP_DTI_2_*/
+
+
+/*
+ * A struct mbuf is used in the call cia_vj_comp because that routine
+ * needs to modify both the start address and length if the incoming
+ * packet is compressed
+ */
+
+  struct comp_buf           cbuf;
+  T_SNDCP_IP_HEADER         *ip;
+  T_SNDCP_TCP_HEADER        *tcp;
+  USHORT                    hdr_len;
+  USHORT                    offset;
+
+  TRACE_FUNCTION( "cia_header_comp" );
+
+  if ((src_desc == NULL))
+  {
+    TRACE_EVENT("ERROR: Descriptor Pointer is a NULLPTR");
+    *packet_type = TYPE_ERROR;
+    return;
+  }
+
+  /*
+   * Verify protocol type and header length
+   */
+  ip = (T_SNDCP_IP_HEADER *)&src_desc_buff[0];
+  if((ip->ip_p == PROT_TCPIP))
+  {
+    hdr_len  = (ip->ip_vhl & HL_MASK) << 2;
+    tcp      = (T_SNDCP_TCP_HEADER *)&src_desc_buff[hdr_len];
+    hdr_len += (tcp->th_off >> 4) << 2;
+    if( (src_desc->len >= hdr_len) && (hdr_len >=40) ){
+      /*
+       * initialize comp_buf
+       */
+      cbuf.hdr_len  = hdr_len;       /* header len. passed to compr. routine*/
+      cbuf.pack_len = src_desc->len; /* descriptor length */
+      cbuf.p_type   = TYPE_IP;       /* set default packet type */
+      /* use temporary buffer to store TCP/IP header */
+      cbuf.c_hdr    = (ULONG)&sndcp_data->cia.comp.tcpip_hdr[0];
+      memcpy((UBYTE*)cbuf.c_hdr, &src_desc_buff[0], cbuf.hdr_len);
+      /*
+       * Call VJ header compression routine
+       */
+      *packet_type = cia_vj_comp(&cbuf);
+    }
+    else
+      *packet_type = TYPE_IP;
+
+  }/* if TCP_IP_PROTOKOL */
+  else{
+    *packet_type = TYPE_IP;
+    if(src_desc->len <40)
+      TRACE_EVENT("INFO COMP: Descriptor length < 40");
+  }
+
+  switch(*packet_type)
+  {
+    /*
+     * IP packet
+     */
+    case TYPE_IP:
+      /*
+       * if acknowledged mode
+       */
+      if(src_desc_list != dest_desc_list)
+      {
+        dest_desc_list->first = src_desc_list->first;
+        dest_desc_list->list_len = src_desc_list->list_len;
+      }
+      TRACE_EVENT("INFO COMP: Header Type TYPE_IP");
+      break;
+
+    /*
+     * Uncompressed TCP/IP packet
+     */
+    case TYPE_UNCOMPRESSED_TCP:
+      /*
+       * if acknowledged mode
+       */
+      if(src_desc_list != dest_desc_list)
+      {
+#ifdef _SNDCP_DTI_2_
+      MALLOC(new_desc, (USHORT)(sizeof(T_desc2)-1+src_desc->len));
+#else
+      MALLOC(new_desc, (USHORT)(sizeof(T_desc)-1+src_desc->len));
+#endif
+        /*
+         * Copy data packet to destination descriptor
+         */
+        memcpy(new_desc->buffer, src_desc_buff, src_desc->len);
+        /*
+         * store connection id
+         */
+        new_desc->buffer[PR_TYPE_POS] = ((UBYTE*)cbuf.c_hdr)[PR_TYPE_POS]
+        ;/*lint !e644 !e415 !e416 creation and access of out-of-bounds pointer*/
+        /*
+         * Build destination descriptor list
+         */
+        new_desc->next   = src_desc->next;
+        new_desc->len    = src_desc->len;
+#ifdef _SNDCP_DTI_2_
+        new_desc->offset = src_desc->offset;
+        new_desc->size   = src_desc->size;
+#endif
+        dest_desc_list->first    = (ULONG)new_desc;
+        dest_desc_list->list_len = src_desc_list->list_len;
+      }
+      else{
+       /*
+        * store connection id
+        */
+        src_desc_buff[PR_TYPE_POS] = ((UBYTE*)cbuf.c_hdr)[PR_TYPE_POS]
+        ;/*lint !e415 !e416 creation and access of out-of-bounds pointer */
+      }
+      TRACE_EVENT("INFO COMP: Header Type TYPE_UNCOMPRESSED_TCP");
+      break;
+
+
+    /*
+     * Compressed TCP/IP packet
+     */
+    case TYPE_COMPRESSED_TCP:
+      /* compute compressed header length */
+      offset = (USHORT)(src_desc->len - cbuf.pack_len);
+#ifdef _SNDCP_DTI_2_
+      MALLOC(new_desc, (USHORT)(sizeof(T_desc2) - 1 + cbuf.pack_len));
+#else
+      MALLOC(new_desc, (USHORT)(sizeof(T_desc) - 1 + cbuf.pack_len));
+#endif
+      /*
+       * Copy compressed header to new descriptor
+       */
+      memcpy(&new_desc->buffer[0], (UBYTE*)cbuf.c_hdr, cbuf.hdr_len);
+      /*
+       * Copy payload to new descriptor
+       */
+      memcpy(&new_desc->buffer[cbuf.hdr_len],
+             &src_desc_buff[hdr_len], cbuf.pack_len-cbuf.hdr_len)
+       ;/*lint !e644 !e662 Possible creation of out-of-bounds pointer */
+      /*
+       * Build destination descriptor list
+       */
+      new_desc->next   = src_desc->next;
+      new_desc->len    = (USHORT)cbuf.pack_len;
+#ifdef _SNDCP_DTI_2_
+      new_desc->offset = 0;
+      new_desc->size   = (USHORT)cbuf.pack_len;
+#endif
+      dest_desc_list->first    = (ULONG)new_desc;
+      dest_desc_list->list_len = src_desc_list->list_len - offset;
+      /*
+       * if unacknowledgement mode
+       */
+      if(src_desc_list == dest_desc_list)
+      {
+        /*
+         * Free source decsriptor
+         */
+        MFREE(src_desc);
+      }
+      TRACE_EVENT("INFO COMP: Header TYPE_COMPRESSED_TCP");
+      break;
+
+    default:
+      TRACE_EVENT("Header Type: TYPE_ERROR");
+      break;
+    }
+
+#ifdef SNDCP_TRACE_BUFFER
+    sndcp_trace_desc_list(dest_desc_list);
+#endif /* SNDCP_TRACE_BUFFER */
+
+} /* cia_header_comp*/
+
+#endif /* CF_FAST_EXEC */
+
+
+#ifndef _SNDCP_DTI_2_
+/*
++------------------------------------------------------------------------------
+| Function    : cia_su_cia_comp_req
++------------------------------------------------------------------------------
+| Description : Simulation for cia reaction to SIG_SU_CIA_DATA_REQ.
+|               Instead of sending the pdu to cia and then receiving
+|               1 or more CIA_COMP_IND.
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \
+   !defined(REL99)   || defined(SNDCP_2to1) */
+
+LOCAL void cia_su_cia_comp_req (T_SN_UNITDATA_REQ* sn_unitdata_req,
+                                USHORT npdu_number,
+                                UBYTE nsapi,
+                                UBYTE sapi,
+                                UBYTE packet_type
+                                )
+{
+  BOOL ready = FALSE;
+  USHORT header_size = SN_UNITDATA_PDP_HDR_LEN_BIG;
+  /*
+   * Bit offset in destination sdu.
+   */
+  USHORT bit_offset = ENCODE_OFFSET + (USHORT)(header_size << 3);
+  /*
+   * Offset in current desc.
+   */
+  USHORT desc_offset = 0;
+  USHORT sdu_len = 0;
+  UBYTE first = SEG_POS_FIRST;
+  UBYTE segment_number = 0;
+  T_desc_list* desc_list = &sn_unitdata_req->desc_list;
+
+  TRACE_FUNCTION( "cia_su_cia_comp_req" );
+
+  while (!ready && desc_list->first != NULL) {
+   /*
+    * How long will sdu be?
+    */
+    if (desc_list->list_len + header_size >= sndcp_data->su->n201_u) {
+      sdu_len = (USHORT)(sndcp_data->su->n201_u << 3);
+    } else {
+      sdu_len = (USHORT)((desc_list->list_len + header_size) << 3);
+    }
+    {
+      PALLOC_SDU(cia_comp_ind, CCI_COMP_IND, sdu_len);
+      /*
+       * Set parameters.
+       */
+
+      cia_comp_ind->sapi = sapi;
+      /*
+       * cia_qos is not yet used, set to 0.
+       */
+      cia_comp_ind->cia_qos.delay = 0;
+      cia_comp_ind->cia_qos.relclass = 0;
+      cia_comp_ind->cia_qos.peak = 0;
+      cia_comp_ind->cia_qos.preced = 0;
+      cia_comp_ind->cia_qos.mean = 0;
+      /*
+       * Will be changed as soon as more that 1 instance of V42.bis is used.
+       */
+      cia_comp_ind->algo_type = CIA_ALGO_V42;
+      cia_comp_ind->comp_inst = CIA_COMP_INST_V42_0;
+
+      cia_comp_ind->pdu_ref.ref_nsapi = nsapi;
+      cia_comp_ind->pdu_ref.ref_npdu_num = npdu_number;
+      cia_comp_ind->pdu_ref.ref_seg_num = segment_number;
+      segment_number ++;
+      if (desc_list->list_len + header_size <= sndcp_data->su->n201_u) {
+        cia_comp_ind->seg_pos = first + SEG_POS_LAST;
+      } else {
+        cia_comp_ind->seg_pos = first;
+      }
+      cia_comp_ind->packet_type = packet_type;
+      /*
+       * Copy descriptors to cia_comp_ind->sdu.
+       */
+      while (desc_list->first != NULL) {
+        T_desc* help = (T_desc*)desc_list->first;
+        USHORT cur_len = (((T_desc*)desc_list->first)->len - desc_offset);
+        if ((cur_len << 3) <=
+             cia_comp_ind->sdu.l_buf +
+             cia_comp_ind->sdu.o_buf -
+             bit_offset) {
+
+          /*
+           * Copy current desc to sdu.
+           */
+          if (cur_len>0)
+          {
+            memcpy(&cia_comp_ind->sdu.buf[bit_offset >> 3],
+                   &((T_desc*)desc_list->first)->buffer[desc_offset],
+                   cur_len);
+          }
+          bit_offset += (USHORT)(cur_len << 3);
+          desc_list->list_len -= cur_len;
+
+          /*
+           * Free read desc and go to next in list.
+           */
+          desc_list->first = help->next;
+          desc_offset = 0;
+          MFREE(help);
+          help = NULL;
+        } else {
+          /*
+           * Current desc does not fit completely in sdu.
+           */
+          USHORT part_len = (USHORT)(cia_comp_ind->sdu.l_buf +
+                                    cia_comp_ind->sdu.o_buf -
+                                    bit_offset)
+                            >> 3;
+          if (part_len > 0)
+          {
+            memcpy(&cia_comp_ind->sdu.buf[bit_offset >> 3],
+                   &((T_desc*)desc_list->first)->buffer[desc_offset],
+                   part_len);
+            desc_offset += part_len;
+          }
+          desc_list->list_len -= part_len;
+
+          header_size = SN_UNITDATA_PDP_HDR_LEN_SMALL;
+          bit_offset = ENCODE_OFFSET + (USHORT)(header_size << 3);
+
+          break;
+        }
+      } /* while (desc_list->first != NULL) { */
+      /*
+       * Instead of PSEND(SNDCP_handle, cia_comp_ind);
+       */
+      cia_cia_comp_ind(cia_comp_ind);
+      /*
+       * One segment sent, set 'first' to 'none'.
+       */
+      first = SEG_POS_NONE;
+    }
+    /*
+     * If the desc_list is empty now, leave.
+     */
+
+    if (sn_unitdata_req->desc_list.list_len == 0) {
+      PFREE(sn_unitdata_req);
+      sn_unitdata_req = NULL;
+      ready = TRUE;
+    }
+  }
+
+} /* cia_su_cia_comp_req() */
+/*#endif */ /* CF_FAST_EXEC || _SIMULATION_ || !REL99 || SNDCP_2to1 */
+
+#else /* _SNDCP_DTI_2_ */
+/*
++------------------------------------------------------------------------------
+| Function    : cia_su_cia_comp_req
++------------------------------------------------------------------------------
+| Description : This function is used, if no data compression is used in
+|               uplink. It does only the segmentation of the incoming data.
+| 
+|               Simulation for cia reaction to SIG_SU_CIA_DATA_REQ.
+|               Instead of sending the pdu to cia and then receiving
+|               1 or more CIA_COMP_IND.
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \
+   !defined(REL99)   || defined(SNDCP_2to1) */
+
+LOCAL void cia_su_cia_comp_req (T_SN_UNITDATA_REQ* sn_unitdata_req,
+                                USHORT npdu_number,
+                                UBYTE nsapi,
+                                UBYTE sapi,
+                                UBYTE packet_type
+                                )
+{
+  BOOL ready = FALSE;
+  U16 header_size = SN_UNITDATA_PDP_HDR_LEN_BIG;
+  U16 desc2_data_struct_offset = 0;
+  U8 first = SEG_POS_FIRST;
+  U8 segment_number = 0;
+  U32* segment_header;
+  T_desc_list2* desc_list2 = &sn_unitdata_req->desc_list2;
+  T_desc_list3 desc_list3;
+  T_desc3* desc3;
+  T_desc3* current_desc3;
+  /*
+   * Offset in current desc. Set the desc_offset to the offset of 
+   * the first desc in the list that is to be read.
+   */
+  U16 desc_offset = ((T_desc2*)desc_list2->first)->offset;
+
+  TRACE_FUNCTION( "cia_su_cia_comp_req" );
+
+  while (!ready && desc_list2->first != NULL)
+  {
+   /*
+    * How long will the segment be?
+    */
+    desc_list3.first = NULL;
+    desc_list3.list_len = 0;
+    if ((desc_list2->list_len + header_size) >= sndcp_data->su->n201_u)
+    {
+      desc_list3.list_len = (USHORT)sndcp_data->su->n201_u;
+    }
+    else
+    {
+      desc_list3.list_len = (USHORT)(desc_list2->list_len + header_size);
+    }
+
+    {
+      T_CIA_COMP_IND *cia_comp_ind;
+      MALLOC(cia_comp_ind, sizeof(T_CIA_COMP_IND));
+      /*
+       * Set parameters.
+       */
+
+      cia_comp_ind->sapi = sapi;
+      /*
+       * cia_qos is not yet used, set to 0.
+       */
+      cia_comp_ind->cia_qos.delay = 0;
+      cia_comp_ind->cia_qos.relclass = 0;
+      cia_comp_ind->cia_qos.peak = 0;
+      cia_comp_ind->cia_qos.preced = 0;
+      cia_comp_ind->cia_qos.mean = 0;
+      /*
+       * Will be changed as soon as more that 1 instance of V42.bis is used.
+       */
+      cia_comp_ind->algo_type = CIA_ALGO_V42;
+      cia_comp_ind->comp_inst = CIA_COMP_INST_V42_0;
+
+      cia_comp_ind->pdu_ref.ref_nsapi = nsapi;
+      cia_comp_ind->pdu_ref.ref_npdu_num = npdu_number;
+      cia_comp_ind->pdu_ref.ref_seg_num = segment_number;
+      segment_number ++;
+
+      /* Allocate memory for SNDCP header and LLC encode offset */
+      MALLOC (segment_header, (USHORT)(ENCODE_OFFSET_BYTE + header_size));
+
+      MALLOC (desc3, (U16)(sizeof(T_desc3)));
+      /*
+       * Fill desc3 descriptor control information.
+       */
+      desc3->next  = (U32)NULL;
+      desc3->len   = header_size;
+      desc3->offset = ENCODE_OFFSET_BYTE;
+      desc3->buffer = (U32)segment_header;
+      desc_list3.first = (U32)desc3;
+      current_desc3 = desc3;
+
+      if (desc_list2->list_len + header_size <= sndcp_data->su->n201_u)
+      {
+        cia_comp_ind->seg_pos = first + SEG_POS_LAST;
+      } else {
+        cia_comp_ind->seg_pos = first;
+      }
+      cia_comp_ind->packet_type = packet_type;
+      cia_comp_ind->desc_list3.first = desc_list3.first;
+      cia_comp_ind->desc_list3.list_len = desc_list3.list_len;
+
+      desc_list3.list_len = 0;
+      desc_list3.list_len += desc3->len;
+      /*
+       * Copy descriptors to cia_comp_ind->desc_list3, list may have to be built.
+       */
+      while (desc_list2->first != NULL)
+      {/* This while moves data from desc2 to segment defined by desc3 descriptors*/
+        T_desc2* help = (T_desc2*)desc_list2->first;
+        U16 cur_len = (((T_desc2*)desc_list2->first)->len - desc_offset);
+        desc2_data_struct_offset = offsetof(T_desc2, buffer);
+        if (cur_len <= (sndcp_data->su->n201_u - desc_list3.list_len))
+        {/* Is there room for all the desc2 data in the current segment */
+
+          /*
+           * describe current desc2 by desc3 descriptors.
+           */
+
+          MALLOC (desc3, (USHORT)(sizeof(T_desc3)));
+          /*
+           * Fill desc3 descriptor control information.
+           */
+          desc3->next  = (U32)NULL;
+          desc3->len   = cur_len;
+          desc3->offset = desc_offset + desc2_data_struct_offset;
+          desc3->buffer = (U32)desc_list2->first;
+          current_desc3->next = (U32)desc3;
+          current_desc3 = desc3;
+          desc_list3.list_len += desc3->len;
+
+          /* Attach desc3 to desc2 allocation, this is always the last
+             attach on a desc2 descriptor */
+          sndcp_cl_desc2_attach(help);
+
+          desc_list2->list_len -= cur_len;
+
+          /*
+           * Free read desc and go to next in list.
+           */
+          desc_list2->first = help->next;
+          /* 
+           * If another desc is present in the list to be read, then 
+           * set the desc_offset to the offset of the next desc in the 
+           * list that is to be read. Else set desc_offset to zero
+           */
+          if (desc_list2->first != NULL)
+          {
+            desc_offset = ((T_desc2*)desc_list2->first)->offset;
+          }
+          else
+          {
+            desc_offset = 0;
+          }
+          MFREE(help);
+          help = NULL;
+        } else {
+          /*
+           * Current desc does not fit completely in sdu.
+           */
+
+          USHORT part_len = (USHORT)(sndcp_data->su->n201_u - desc_list3.list_len);
+
+          if (part_len > 0)
+          {
+            MALLOC (desc3, (USHORT)(sizeof(T_desc3)));
+            /*
+             * Fill desc3 descriptor control information.
+             */
+            desc3->next  = (ULONG)NULL;
+            desc3->len   = part_len;
+            desc3->offset = desc_offset + desc2_data_struct_offset;
+            desc3->buffer = (ULONG)desc_list2->first;
+            current_desc3->next = (ULONG)desc3;
+            current_desc3 = desc3;
+            desc_list3.list_len += desc3->len;
+
+            /* Attach desc3 to desc2 allocation, this is an intermediate
+               attach on a desc2 descriptor */
+            sndcp_cl_desc2_attach(help);
+
+            desc_offset += part_len;
+          }
+          desc_list2->list_len -= part_len;
+
+          header_size = SN_UNITDATA_PDP_HDR_LEN_SMALL;
+          break;
+        }
+      } /* while (desc_list->first != NULL) { */
+
+      /*
+       * Instead of PSEND(SNDCP_handle, cia_comp_ind);
+       */
+      cia_cia_comp_ind(cia_comp_ind);
+      /*
+       * One segment sent, set 'first' to 'none'.
+       */
+      first = SEG_POS_NONE;
+    }
+    /*
+     * If the desc_list is empty now, leave.
+     */
+    if (sn_unitdata_req->desc_list2.list_len == 0) {
+
+      MFREE(sn_unitdata_req);
+      sn_unitdata_req = NULL;
+      ready = TRUE;
+    }
+  }
+} /* cia_su_cia_comp_req() */
+/*#endif */ /* CF_FAST_EXEC || _SIMULATION_ || !REL99 || SNDCP_2to1 */
+
+#ifdef TI_PS_FF_V42BIS
+/*
++------------------------------------------------------------------------------
+| Function    : cia_su_cci_comp_req
++------------------------------------------------------------------------------
+| Description : This function is used, if data compression is used in uplink
+|               direction. At first it calls the data compression function with
+|               parameters, that allow a segmentation without memcopy. Than it
+|               does the segmentation.
+|
+|               Simulation for CCI reaction to SIG_SU_CIA_DATA_REQ.
+|               Instead of sending the pdu to CCI and then receiving
+|               1 or more CCI_COMP_IND.
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \
+   !defined(REL99)   || defined(SNDCP_2to1) */
+   
+LOCAL void cia_su_cci_comp_req (T_SN_UNITDATA_REQ* sn_unitdata_req,
+                                          USHORT npdu_number,
+                                          UBYTE nsapi,
+                                          UBYTE sapi,
+                                          UBYTE packet_type
+                                        )
+{
+  BOOL ready = FALSE;
+  U16 header_size = SN_UNITDATA_PDP_HDR_LEN_BIG;
+  U16 desc2_data_struct_offset = offsetof(T_desc2, buffer);
+  U8 segment_position = SEG_POS_FIRST;
+  U8 segment_number = 0;
+  U32* segment_header;
+  T_desc_list2* desc_list2 = &sn_unitdata_req->desc_list2;
+  T_desc2* desc2;
+  T_desc_list3 desc_list3;
+  T_desc3* desc3;
+  T_desc3* current_desc3;
+  
+  U8 descs_per_seg = 5;
+  U8 i;
+  U16 desc_size = (sndcp_data->su->n201_u - header_size -
+                  (desc2_data_struct_offset + 1) * descs_per_seg) /
+                  descs_per_seg +
+                  desc2_data_struct_offset + 1;
+  
+  
+  
+  
+  
+  
+  TRACE_FUNCTION( "cia_su_cci_comp_req" );
+  TRACE_EVENT_P1("sn_unitdata_req in: %08x", sn_unitdata_req);
+  //TRACE_EVENT_P1("PacketType: %d",packet_type);
+
+  /*
+   * Reset V.42 context and call the encoder routine
+   */
+  //TRACE_EVENT_P1("V42 ENC: Input Uncompressed Packet, length %d", desc_list2->list_len);
+#ifdef SNDCP_TRACE_BUFFER
+  //sndcp_trace_desc_list(desc_list2);
+#endif
+  v42b_init(sndcp_data->cia.enc, 0, 0, 0, 0);
+  TRACE_FUNCTION ("as reinit in uplink");
+  /*
+   * the function can be called with 0s as parameters, because it was initialized
+   * befor what the function sees on the valid magic number
+   *
+   * the call replaces an independent reinit function
+   */
+  v42b_encoder(sndcp_data->cia.enc, desc_list2, NULL, desc_size);
+  //TRACE_EVENT_P1("V42 ENC: Output Compresset Packet, length %d", desc_list2->list_len);
+#ifdef SNDCP_TRACE_BUFFER
+  //sndcp_trace_desc_list(desc_list2);
+#endif
+
+
+  desc2 = (T_desc2*)desc_list2->first;
+
+  while (desc2)
+  {
+    
+    
+    
+    desc_list3.first = (U32) NULL;
+    desc_list3.list_len = 0;
+    
+
+    MALLOC(segment_header, (ENCODE_OFFSET_BYTE + header_size));
+    MALLOC(desc3,sizeof(T_desc3));
+
+    desc3->next = (U32) NULL;
+    desc3->len = header_size;
+    desc3->offset = ENCODE_OFFSET_BYTE;
+    desc3->buffer = (U32)segment_header;
+
+    desc_list3.first = (U32)desc3;
+    desc_list3.list_len = desc3->len;
+
+    current_desc3 = desc3;
+
+    for (i = 0; (i < descs_per_seg) && desc2; i++)
+    {
+      MALLOC(desc3,sizeof(T_desc3));
+
+      desc3->next = (U32) NULL;
+      desc3->len = desc2->len;
+      desc3->offset = desc2->offset + desc2_data_struct_offset;
+      desc3->buffer = (U32)desc2;
+
+      current_desc3->next = (U32) desc3;
+      current_desc3 = desc3;
+      desc_list3.list_len += desc3->len;
+
+      desc2 = (T_desc2*) desc2->next;
+    }
+    header_size = SN_UNITDATA_PDP_HDR_LEN_SMALL;
+
+    {
+      T_CIA_COMP_IND *cia_comp_ind;
+      MALLOC(cia_comp_ind, sizeof(T_CIA_COMP_IND));
+      /*
+       * Set parameters.
+       */
+
+      cia_comp_ind->sapi = sapi;
+      /*
+       * cci_qos is not yet used, set to 0.
+       */
+      cia_comp_ind->cia_qos.delay = 0;
+      cia_comp_ind->cia_qos.relclass = 0;
+      cia_comp_ind->cia_qos.peak = 0;
+      cia_comp_ind->cia_qos.preced = 0;
+      cia_comp_ind->cia_qos.mean = 0;
+      /*
+       * Will be changed as soon as more that 1 instance of V42.bis is used.
+       */
+      cia_comp_ind->algo_type = CCI_ALGO_V42;
+      cia_comp_ind->comp_inst = CCI_COMP_INST_V42_0;
+
+      cia_comp_ind->pdu_ref.ref_nsapi = nsapi;
+      cia_comp_ind->pdu_ref.ref_npdu_num = npdu_number;
+      cia_comp_ind->pdu_ref.ref_seg_num = segment_number;
+      segment_number ++;
+
+      if (desc2 != NULL)
+      {
+        cia_comp_ind->seg_pos = segment_position;
+      }
+      else
+      {
+        cia_comp_ind->seg_pos = segment_position | SEG_POS_LAST;
+      }
+
+      cia_comp_ind->packet_type = packet_type;
+      cia_comp_ind->desc_list3.first = desc_list3.first;
+      cia_comp_ind->desc_list3.list_len = desc_list3.list_len;
+
+      /*
+       * Instead of PSEND(SNDCP_handle, cci_comp_ind);
+       */
+      cia_cia_comp_ind(cia_comp_ind);
+      /*
+       * One segment sent, set 'first' to 'none'.
+       */
+      segment_position = SEG_POS_NONE;
+    }
+  }
+  /*
+   * If the desc_list2 is empty now, leave.
+   */
+  TRACE_EVENT_P1("sn_unitdata_req out: %08x", sn_unitdata_req);
+  MFREE(sn_unitdata_req);
+  sn_unitdata_req = NULL;
+}
+/*#endif */ /* FAST_EXEC */
+#endif /* TI_PS_FF_V42BIS */
+#endif /* _SNDCP_DTI_2_ */
+
+#ifdef _SNDCP_DTI_2_
+/*
++------------------------------------------------------------------------------
+| Function    : cia_sua_cia_comp_req
++------------------------------------------------------------------------------
+| Description : Simulation for cia reaction to SIG_SUA_CIA_DATA_REQ.
+|               Instead of sending the pdu to cia and then receiving
+|               1 or more CIA_COMP_IND.
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+LOCAL void cia_sua_cia_comp_req (T_desc_list2 dest_desc_list,
+                                 U8 npdu_number,
+                                 U8 nsapi,
+                                 U8 sapi,
+                                 U8 packet_type
+                                 )
+{
+  BOOL ready = FALSE;
+  U16 header_size = SN_DATA_PDP_HDR_LEN_BIG;
+  U16 desc2_data_struct_offset = 0;
+  U8 first = SEG_POS_FIRST;
+  U8 segment_number = 0;
+  U32* segment_header;
+  T_desc_list2* desc_list2 = &dest_desc_list;
+  T_desc_list3 desc_list3;
+  T_desc3* desc3;
+  T_desc3* current_desc3;
+  USHORT list_len = desc_list2->list_len;
+  T_desc2* help = (T_desc2*)desc_list2->first;
+  T_desc2* delhelp = NULL;
+
+  /* 
+   * Offset in current descriptor  Set the desc_offset to the offset of 
+   * the first desc in the list that is to be read.
+   */
+  U16 desc_offset = help->offset;
+
+  TRACE_FUNCTION( "cia_sua_cia_comp_req" );
+
+  while (!ready && help != NULL) {
+   /*
+    * How long will the segment be?
+    */
+    desc_list3.first = NULL;
+    desc_list3.list_len = 0;
+    if ((list_len + header_size) >= sndcp_data->sua->n201_i)
+    {
+      desc_list3.list_len = (U16)sndcp_data->sua->n201_i;
+    }
+    else
+    {
+      desc_list3.list_len = (U16)(list_len + header_size);
+    }
+
+    {
+      /*
+       * First desc in list must be header!!!
+       */
+      BOOL first_part = TRUE;
+
+      T_CIA_COMP_IND *cia_comp_ind;
+      MALLOC(cia_comp_ind, sizeof(T_CIA_COMP_IND));
+      /*
+       * Set parameters.
+       */
+      cia_comp_ind->sapi = sapi;
+      /*
+       * cia_qos is not yet used, set to 0.
+       */
+      cia_comp_ind->cia_qos.delay = 0;
+      cia_comp_ind->cia_qos.relclass = 0;
+      cia_comp_ind->cia_qos.peak = 0;
+      cia_comp_ind->cia_qos.preced = 0;
+      cia_comp_ind->cia_qos.mean = 0;
+      /*
+       * Will be changed as soon as more that 1 instance of V42.bis is used.
+       */
+      cia_comp_ind->algo_type = CIA_ALGO_V42;
+      cia_comp_ind->comp_inst = CIA_COMP_INST_V42_0;
+
+      cia_comp_ind->pdu_ref.ref_nsapi = nsapi;
+      cia_comp_ind->pdu_ref.ref_npdu_num = npdu_number;
+      cia_comp_ind->pdu_ref.ref_seg_num = segment_number;
+      segment_number ++;
+
+      /* Allocate memory for SNDCP header and LLC encode offset */
+      MALLOC (segment_header, (U16)(ENCODE_OFFSET_BYTE + header_size));
+
+      MALLOC (desc3, (U16)(sizeof(T_desc3)));
+      /*
+       * Fill desc3 descriptor control information.
+       */
+      desc3->next  = (U32)NULL;
+      desc3->len   = header_size;
+      desc3->offset = ENCODE_OFFSET_BYTE;
+      desc3->buffer = (U32)segment_header;
+      desc_list3.first = (U32)desc3;
+      current_desc3 = desc3;
+
+      if (list_len + header_size <= sndcp_data->sua->n201_i)
+      {
+        cia_comp_ind->seg_pos = first + SEG_POS_LAST;
+      } else {
+        cia_comp_ind->seg_pos = first;
+      }
+      cia_comp_ind->packet_type = packet_type;
+      cia_comp_ind->desc_list3.first = desc_list3.first;
+      cia_comp_ind->desc_list3.list_len = desc_list3.list_len;
+
+      desc_list3.list_len = 0;
+      desc_list3.list_len += desc3->len;
+      /*
+       * Copy descriptors to cia_comp_ind->desc_list3, list may have to be built.
+       */
+      while (help != NULL)
+      {/*
+        * This while moves data from desc2 to segment defined
+        * by desc3 descriptors
+        */
+        U16 cur_len = (help->len - desc_offset);
+        desc2_data_struct_offset = offsetof(T_desc2, buffer);
+        if (cur_len <= (sndcp_data->sua->n201_i - desc_list3.list_len))
+        {/* Is there room for all the desc2 data in the current segment */
+          /*
+           * describe current desc2 by desc3 descriptors.
+           */
+          if (cur_len>0)
+          {
+            MALLOC (desc3, (U16)(sizeof(T_desc3)));
+            /*
+             * Fill desc3 descriptor control information.
+             */
+            desc3->next  = (U32)NULL;
+            desc3->len   = cur_len;
+            desc3->offset = desc_offset + desc2_data_struct_offset;
+            desc3->buffer = (U32)help;
+            current_desc3->next = (ULONG)desc3;
+            current_desc3 = desc3;
+            desc_list3.list_len += desc3->len;
+
+            /* Attach desc3 to desc2 allocation, this is always the last
+               attach on a desc2 descriptor */
+            sndcp_cl_desc2_attach(help);
+
+          }
+          list_len -= cur_len;
+
+          /*
+           * Free read desc and go to next in list.
+           */
+          if (help != NULL)
+          {
+            delhelp = help;
+            help = (T_desc2*)help->next;
+          }
+          /* 
+           * If another desc is present in the list to be read, then 
+           * set the desc_offset to the offset of the next desc in the 
+           * list that is to be read. Else set desc_offset to zero
+           */
+          if (help != NULL)
+          {
+            desc_offset = help->offset;
+          }
+          else
+          {
+            desc_offset = 0;
+          }
+          if (delhelp != NULL &&
+              first_part &&
+              (packet_type == TYPE_COMPRESSED_TCP ||
+               packet_type == TYPE_UNCOMPRESSED_TCP)) {
+
+            MFREE(delhelp);
+            delhelp = NULL;
+            first_part = FALSE;
+          }
+        }
+        else
+        {
+          /*
+           * Current desc does not fit completely in sdu.
+           */
+
+          U16 part_len = (USHORT)(sndcp_data->sua->n201_i-desc_list3.list_len);
+
+          if (part_len>0)
+          {
+            MALLOC (desc3, (USHORT)(sizeof(T_desc3)));
+            /*
+             * Fill desc3 descriptor control information.
+             */
+            desc3->next  = (ULONG)NULL;
+            desc3->len   = part_len;
+            desc3->offset = desc_offset + desc2_data_struct_offset;
+            desc3->buffer = (ULONG)help;
+            current_desc3->next = (ULONG)desc3;
+            current_desc3 = desc3;
+            desc_list3.list_len += desc3->len;
+
+            /* Attach desc3 to desc2 allocation, this is an intermediate
+               attach on a desc2 descriptor */
+            sndcp_cl_desc2_attach(help);
+
+            desc_offset += part_len;
+          }
+          list_len -= part_len;
+
+          header_size = SN_DATA_PDP_HDR_LEN_SMALL;
+          break;
+        }
+      }
+      /*
+       * Instead of PSEND(SNDCP_handle, cia_comp_ind);
+       */
+      cia_cia_comp_ind(cia_comp_ind);
+      /*
+       * One segment sent, set 'first' to 'none'.
+       */
+      first = SEG_POS_NONE;
+    }
+    /*
+     * If the desc_list is empty now, leave.
+     */
+    if (list_len == 0) {
+      ready = TRUE;
+    }
+  }
+} /* cia_sua_cia_comp_req() */
+
+#endif /* CF_FAST_EXEC */
+
+#else /* _SNDCP_DTI_2_ */
+/*
++------------------------------------------------------------------------------
+| Function    : cia_sua_cia_comp_req
++------------------------------------------------------------------------------
+| Description : Simulation for cia reaction to SIG_SUA_CIA_DATA_REQ.
+|               Instead of sending the pdu to cia and then receiving
+|               1 or more CIA_COMP_IND.
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+LOCAL void cia_sua_cia_comp_req (T_desc_list dest_desc_list,
+                                 UBYTE npdu_number,
+                                 UBYTE nsapi,
+                                 UBYTE sapi,
+                                 UBYTE packet_type
+                                 )
+{
+  BOOL ready = FALSE;
+  USHORT header_size = SN_DATA_PDP_HDR_LEN_BIG;
+  USHORT bit_offset = ENCODE_OFFSET + (USHORT)(header_size << 3);
+  USHORT desc_offset = 0;
+  USHORT sdu_len = 0;
+  UBYTE first = SEG_POS_FIRST;
+  UBYTE segment_number = 0;
+  T_desc_list* desc_list = &dest_desc_list;
+  USHORT list_len = desc_list->list_len;
+  T_desc* help = (T_desc*)desc_list->first;
+  T_desc* delhelp = NULL;
+
+  USHORT help_buffer_offset = 0;
+
+  TRACE_FUNCTION( "cia_sua_cia_comp_req" );
+
+  while (!ready && help != NULL) {
+   /*
+    * How long will sdu be?
+    */
+    if (list_len + header_size >= sndcp_data->sua->n201_i) {
+      sdu_len = (USHORT)(sndcp_data->sua->n201_i << 3);
+    } else {
+      sdu_len = (USHORT)((list_len + header_size) << 3);
+    }
+    {
+      /*
+       * First desc in list must be header!!!
+       */
+      BOOL first_part = TRUE;
+
+      PALLOC_SDU(cia_comp_ind, CCI_COMP_IND, sdu_len);   
+      /*
+       * Set parameters.
+       */
+      cia_comp_ind->sapi = sapi;
+      /*
+       * cia_qos is not yet used, set to 0.
+       */
+      cia_comp_ind->cia_qos.delay = 0;
+      cia_comp_ind->cia_qos.relclass = 0;
+      cia_comp_ind->cia_qos.peak = 0;
+      cia_comp_ind->cia_qos.preced = 0;
+      cia_comp_ind->cia_qos.mean = 0;
+      /*
+       * Will be changed as soon as more that 1 instance of V42.bis is used.
+       */
+      cia_comp_ind->algo_type = CIA_ALGO_V42;
+      cia_comp_ind->comp_inst = CIA_COMP_INST_V42_0;
+
+      cia_comp_ind->pdu_ref.ref_nsapi = nsapi;
+      cia_comp_ind->pdu_ref.ref_npdu_num = npdu_number;
+      cia_comp_ind->pdu_ref.ref_seg_num = segment_number;
+      segment_number ++;
+      if (list_len + header_size <= sndcp_data->sua->n201_i) {
+        cia_comp_ind->seg_pos = first + SEG_POS_LAST;
+      } else {
+        cia_comp_ind->seg_pos = first;
+      }
+      cia_comp_ind->packet_type = packet_type;
+      /*
+       * Copy descriptors to cia_comp_ind->sdu.
+       */
+      while (help != NULL) {
+        USHORT cur_len = (help->len - desc_offset);
+
+        if ((cur_len << 3) <=
+             cia_comp_ind->sdu.l_buf +
+             cia_comp_ind->sdu.o_buf -
+             bit_offset) {
+
+          /*
+           * Copy current desc to sdu.
+           */
+          if (cur_len>0)
+          {
+            memcpy(&cia_comp_ind->sdu.buf[bit_offset >> 3],
+                   &help->buffer[desc_offset],
+                   cur_len);
+          }
+          bit_offset += (USHORT)(cur_len << 3);
+          list_len -= cur_len;
+
+          /*
+           * Free read desc and go to next in list.
+           */
+          if (help != NULL) {
+            delhelp = help;
+            help = (T_desc*)help->next;
+          }
+          help_buffer_offset = 0;
+          desc_offset = 0;
+          if (delhelp != NULL &&
+              first_part &&
+              (packet_type == TYPE_COMPRESSED_TCP ||
+               packet_type == TYPE_UNCOMPRESSED_TCP)) {
+
+            MFREE(delhelp);
+            delhelp = NULL;
+            first_part = FALSE;
+          }
+        } else {
+          /*
+           * Current desc does not fit completely in sdu.
+           */
+          desc_offset = (USHORT)(cia_comp_ind->sdu.l_buf +
+                                 cia_comp_ind->sdu.o_buf -
+                                 bit_offset)
+                         >> 3;
+          if (desc_offset>0)
+          {
+            memcpy(&cia_comp_ind->sdu.buf[bit_offset >> 3],
+                   &help->buffer[help_buffer_offset],
+                   desc_offset);
+            help_buffer_offset += (desc_offset);
+          }
+          list_len -= desc_offset;
+
+          header_size = SN_DATA_PDP_HDR_LEN_SMALL;
+          bit_offset = ENCODE_OFFSET + (USHORT)(header_size << 3);
+          break;
+        }
+      }
+      /*
+       * Instead of PSEND(SNDCP_handle, cia_comp_ind);
+       */
+      cia_cia_comp_ind(cia_comp_ind);
+      /*
+       * One segment sent, set 'first' to 'none'.
+       */
+      first = SEG_POS_NONE;
+    }
+    /*
+     * If the desc_list is empty now, leave.
+     */
+    if (list_len == 0) {
+      ready = TRUE;
+    }
+  }
+
+} /* cia_sua_cia_comp_req() */
+
+#endif /* CF_FAST_EXEC */
+
+#endif /*_SNDCP_DTI_2_*/
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : cia_sd_cia_decomp_req
++------------------------------------------------------------------------------
+| Description : This Function does the defragmentation for noncompressed data.
+| 
+| Simulation for cia reaction to SIG_SD_CIA_TRANSFER_REQ.
+| If (cur_seg_pos & SEG_POS_FIRST > 0) then a new CIA_DECOMP_IND is allocated.
+| T_desc is allocated with the length of the sdu included in the
+| ll_unitdata_ind. The sdu data is copied to the desc and the desc is added to
+| the currently assembled desc_list in the current CIA_DECOMP_IND.
+| If (cur_seg_pos & SEG_POS_LAST > 0) then a the CIA_DECOMP_IND is now complete
+| and is "sent to this service" by calling the cia function cia_cia_decomp_ind.
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \
+   !defined(REL99)   || defined(SNDCP_2to1) */
+
+GLOBAL void cia_sd_cia_decomp_req(T_LL_UNITDATA_IND* ll_unitdata_ind)
+{
+  USHORT length = 0;
+  USHORT header_len = SN_UNITDATA_PDP_HDR_LEN_SMALL;
+  USHORT sdu_index = 0;
+  T_CIA_DECOMP_IND *cur_cia_decomp_ind;
+  UBYTE nsapi;
+#ifdef _SNDCP_DTI_2_
+  T_desc2* help = NULL;
+  T_desc2* descriptor = NULL;
+#else /*_SNDCP_DTI_2_*/
+  T_desc* help = NULL;
+  T_desc* descriptor = NULL;
+#endif /*_SNDCP_DTI_2_*/
+
+  TRACE_FUNCTION( "cia_sd_cia_decomp_req" );
+
+  nsapi = (ll_unitdata_ind->sdu.buf[(ll_unitdata_ind->sdu.o_buf / 8)]) & 0xf;
+  cur_cia_decomp_ind = sndcp_data->cia.cur_cia_decomp_ind[nsapi];
+  
+  /*
+   * In case of first segment allocate new N-PDU.
+   */
+  if ((sndcp_data->cur_seg_pos[nsapi] & SEG_POS_FIRST) > 0) {
+    {
+
+      T_CIA_DECOMP_IND *cia_decomp_ind;
+      MALLOC(cia_decomp_ind, sizeof(T_CIA_DECOMP_IND));
+
+#ifdef SNDCP_TRACE_ALL
+
+      sndcp_data->cia.cia_decomp_ind_number[nsapi] ++;
+      TRACE_EVENT_P1("number of cia_decomp_ind: % d",
+                     sndcp_data->cia.cia_decomp_ind_number[nsapi]);
+#endif /* SNDCP_TRACE_ALL */
+
+
+      /*
+       * if there is an unfinished cur_cia_decomp_ind deallocate it together
+       * with the allocated descriptors
+       */
+      if (cur_cia_decomp_ind NEQ NULL)
+      {
+        MFREE_PRIM(cur_cia_decomp_ind);
+        TRACE_EVENT("Deallocate unfinished cur_cia_decomp_ind");
+      }
+      cur_cia_decomp_ind = cia_decomp_ind;
+      /*
+       * Will be changed as soon as more that 1 instance of V42.bis is used.
+       */
+      cur_cia_decomp_ind->algo_type = CIA_ALGO_V42;
+      cur_cia_decomp_ind->comp_inst = CIA_COMP_INST_V42_0;
+
+      cur_cia_decomp_ind->pdu_ref = sndcp_data->cur_pdu_ref[nsapi];
+      cur_cia_decomp_ind->desc_list2.first = (ULONG)NULL;
+      cur_cia_decomp_ind->desc_list2.list_len = 0;
+
+      header_len = SN_UNITDATA_PDP_HDR_LEN_BIG;
+      cia_decomp_ind->pcomp =
+        ll_unitdata_ind->sdu.buf[(ll_unitdata_ind->sdu.o_buf >> 3) + 1] & 0xf;
+    }
+  }
+  /*
+   * If big header has been received in state != RECEIVE_FIRST_SEGMENT
+   */
+  if (sndcp_data->big_head[nsapi]) {
+    header_len = SN_UNITDATA_PDP_HDR_LEN_BIG;
+  }
+  sdu_index = (ll_unitdata_ind->sdu.o_buf >> 3) + header_len;
+  length = (ll_unitdata_ind->sdu.l_buf >> 3) - header_len;
+  /*
+   * Allocate new descriptor and copy sdu data.
+   */
+#ifdef _SNDCP_DTI_2_
+  MALLOC (descriptor, (USHORT)(sizeof(T_desc2) - 1 + length));
+#else /*_SNDCP_DTI_2_*/
+  MALLOC (descriptor, (USHORT)(sizeof(T_desc) - 1 + length));
+#endif /*_SNDCP_DTI_2_*/
+
+  /*
+   * Fill descriptor control information.
+   */
+  descriptor->next  = (ULONG)NULL;
+  descriptor->len   = length;
+#ifdef _SNDCP_DTI_2_
+  descriptor->offset = 0;
+  descriptor->size = descriptor->len;
+#endif
+
+  /*
+   * Add length of descriptor data to list length.
+   */
+  cur_cia_decomp_ind->desc_list2.list_len += length;
+
+  /*
+   * Copy user data from SDU to descriptor.
+   */
+  if (length>0)
+  {
+    memcpy (descriptor->buffer,
+            &ll_unitdata_ind->sdu.buf[sdu_index],
+            length);
+  }
+
+  /*
+   * Add desc to desc_list.
+   */
+#ifdef _SNDCP_DTI_2_
+  help = (T_desc2*)cur_cia_decomp_ind->desc_list2.first;
+#else /*_SNDCP_DTI_2_*/
+  help = (T_desc*)cur_cia_decomp_ind->desc_list2.first;
+#endif /*_SNDCP_DTI_2_*/
+  if (help == NULL) {
+    cur_cia_decomp_ind->desc_list2.first = (ULONG)descriptor;
+  } else {
+    if (help->next == NULL) {
+      help->next = (ULONG) descriptor;
+    } else {
+      while (help->next != NULL) {
+#ifdef _SNDCP_DTI_2_
+        help = (T_desc2*)help->next;
+#else /*_SNDCP_DTI_2_*/
+        help = (T_desc*)help->next;
+#endif /*_SNDCP_DTI_2_*/
+      }
+      help->next = (ULONG)descriptor;
+    }
+  }
+
+  /*
+   * If this is the last segment, send it to this same service with a simulated
+   * primitive.
+   */
+  if ((sndcp_data->cur_seg_pos[nsapi] & SEG_POS_LAST) > 0) {
+    /*
+     * By now algo_type, cia_qos and comp_inst are not evaluated.
+     */
+    cur_cia_decomp_ind->pdu_ref = sndcp_data->cur_pdu_ref[nsapi];
+    cia_cia_decomp_ind(cur_cia_decomp_ind);
+    cur_cia_decomp_ind = NULL;
+  } else {
+    /*
+     * Request next segment.
+     */
+    sd_get_unitdata_if_nec(ll_unitdata_ind->sapi);
+  }
+  /*
+   * Update global current CIA_DECOMP_IND
+   */
+  sndcp_data->cia.cur_cia_decomp_ind[nsapi] = cur_cia_decomp_ind;
+  /*
+   * Free incoming prim.
+   */
+  if (ll_unitdata_ind != NULL) {
+    PFREE (ll_unitdata_ind);
+    ll_unitdata_ind = NULL;
+  }
+} /* cia_sd_cia_decomp_req() */
+
+/*#endif */ /* CF_FAST_EXEC || _SIMULATION_ || !REL99 || SNDCP_2to1 */
+
+#ifdef TI_PS_FF_V42BIS
+/*
++------------------------------------------------------------------------------
+| Function    : cia_sd_cci_decomp_req
++------------------------------------------------------------------------------
+| Description : This function does the desegmentation and decomressoin for 
+|               compressed data.
+|
+| Simulation for CCI reaction to SIG_SD_CIA_TRANSFER_REQ.
+| If (cur_seg_pos & SEG_POS_FIRST > 0) then a new CCI_DECOMP_IND is allocated.
+| T_desc is allocated with the length of the sdu included in the
+| ll_unitdata_ind. The sdu data is copied to the desc and the desc is added to
+| the currently assembled desc_list in the current CCI_DECOMP_IND.
+| If (cur_seg_pos & SEG_POS_LAST > 0) then a the CCI_DECOMP_IND is now complete
+| and is "sent to this service" by calling the cia function cia_cci_decomp_ind.
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \
+   !defined(REL99)   || defined(SNDCP_2to1) */
+
+LOCAL void cia_sd_cci_decomp_req (/*T_pdu_ref pdu_ref,
+                                  USHORT cur_seg_pos,
+                                  */T_LL_UNITDATA_IND* ll_unitdata_ind
+                                  )
+{
+
+  USHORT length = 0;
+  USHORT header_len = SN_UNITDATA_PDP_HDR_LEN_SMALL;
+  USHORT sdu_index = 0;
+  T_CIA_DECOMP_IND *cur_cia_decomp_ind;
+  UBYTE nsapi;
+#ifdef _SNDCP_DTI_2_
+  T_desc2* help = NULL;
+  T_desc2* descriptor = NULL;
+#else /*_SNDCP_DTI_2_*/
+  T_desc* help = NULL;
+  T_desc* descriptor = NULL;
+#endif /*_SNDCP_DTI_2_*/
+
+  TRACE_FUNCTION( "cia_sd_cci_decomp_req" );
+  
+  nsapi = (ll_unitdata_ind->sdu.buf[(ll_unitdata_ind->sdu.o_buf / 8)]) & 0xf;
+  cur_cia_decomp_ind = sndcp_data->cia.cur_cia_decomp_ind[nsapi];
+  
+  /*
+   * In case of first segment allocate new N-PDU.
+   */
+  if ((sndcp_data->cur_seg_pos[nsapi] & SEG_POS_FIRST) > 0) 
+  {
+    {
+      T_CIA_DECOMP_IND *cia_decomp_ind;
+      MALLOC(cia_decomp_ind, sizeof(T_CIA_DECOMP_IND));
+
+#ifdef SNDCP_TRACE_ALL
+
+      sndcp_data->cia.cia_decomp_ind_number[nsapi] ++;
+      TRACE_EVENT_P1("number of cia_decomp_ind: % d",
+                     sndcp_data->cia.cia_decomp_ind_number[nsapi]);
+#endif /* SNDCP_TRACE_ALL */
+
+
+      /*
+       * if there is an unfinished cur_cia_decomp_ind deallocate it together
+       * with the allocated descriptors
+       */
+      if (cur_cia_decomp_ind NEQ NULL)
+      {
+        MFREE_PRIM(cur_cia_decomp_ind);
+        TRACE_EVENT("Deallocate unfinished cur_cia_decomp_ind");
+      }
+      cur_cia_decomp_ind = cia_decomp_ind;
+      /*
+       * Will be changed as soon as more that 1 instance of V42.bis is used.
+       */
+      cur_cia_decomp_ind->algo_type = CIA_ALGO_V42;
+      cur_cia_decomp_ind->comp_inst = CIA_COMP_INST_V42_0;
+
+      cur_cia_decomp_ind->pdu_ref = sndcp_data->cur_pdu_ref[nsapi];
+      cur_cia_decomp_ind->desc_list2.first = (ULONG)NULL;
+      cur_cia_decomp_ind->desc_list2.list_len = 0;
+
+      header_len = SN_UNITDATA_PDP_HDR_LEN_BIG;
+      cia_decomp_ind->pcomp =
+        ll_unitdata_ind->sdu.buf[(ll_unitdata_ind->sdu.o_buf >> 3) + 1] & 0xf;
+    }
+  }
+  /*
+   * If big header has been received in state != RECEIVE_FIRST_SEGMENT
+   */
+  if (sndcp_data->big_head[nsapi]) {
+    header_len = SN_UNITDATA_PDP_HDR_LEN_BIG;
+  }
+  sdu_index = (ll_unitdata_ind->sdu.o_buf >> 3) + header_len;
+  length = (ll_unitdata_ind->sdu.l_buf >> 3) - header_len;
+  /*
+   * Allocate new descriptor and copy sdu data.
+   */
+#ifdef _SNDCP_DTI_2_
+  MALLOC (descriptor, (USHORT)(sizeof(T_desc2) - 1 + length));
+#else /*_SNDCP_DTI_2_*/
+  MALLOC (descriptor, (USHORT)(sizeof(T_desc) - 1 + length));
+#endif /*_SNDCP_DTI_2_*/
+
+  /*
+   * Fill descriptor control information.
+   */
+  descriptor->next  = (ULONG)NULL;
+  descriptor->len   = length;
+#ifdef _SNDCP_DTI_2_
+  descriptor->offset = 0;
+  descriptor->size = descriptor->len;
+#endif
+
+  /*
+   * Add length of descriptor data to list length.
+   */
+  cur_cia_decomp_ind->desc_list2.list_len += length;
+
+  /*
+   * Copy user data from SDU to descriptor.
+   */
+  if (length>0)
+  {
+    memcpy (descriptor->buffer,
+            &ll_unitdata_ind->sdu.buf[sdu_index],
+            length);
+  }
+
+  /*
+   * Add desc to desc_list.
+   */
+#ifdef _SNDCP_DTI_2_
+  help = (T_desc2*)cur_cia_decomp_ind->desc_list2.first;
+#else /*_SNDCP_DTI_2_*/
+  help = (T_desc*)cur_cia_decomp_ind->desc_list2.first;
+#endif /*_SNDCP_DTI_2_*/
+  if (help == NULL) {
+    cur_cia_decomp_ind->desc_list2.first = (ULONG)descriptor;
+  } else {
+    if (help->next == NULL) {
+      help->next = (ULONG) descriptor;
+    } else {
+      while (help->next != NULL) {
+#ifdef _SNDCP_DTI_2_
+        help = (T_desc2*)help->next;
+#else /*_SNDCP_DTI_2_*/
+        help = (T_desc*)help->next;
+#endif /*_SNDCP_DTI_2_*/
+      }
+      help->next = (ULONG)descriptor;
+    }
+  }
+
+  /*
+   * If this is the last segment, send it to this same service with a simulated
+   * primitive.
+   */
+  if ((sndcp_data->cur_seg_pos[nsapi] & SEG_POS_LAST) > 0) 
+  {
+    T_desc_list2 desc_list2;
+    /*
+     * By now algo_type, cci_qos and comp_inst are not evaluated.
+     */
+    cur_cia_decomp_ind->pdu_ref = sndcp_data->cur_pdu_ref[nsapi];
+
+    desc_list2.first = cur_cia_decomp_ind->desc_list2.first;
+    desc_list2.list_len = cur_cia_decomp_ind->desc_list2.list_len;
+
+    /*
+     * Reset V.42 context and call the decoder routine.
+     */
+    TRACE_EVENT_P1("V42 DEC: Input Compresset Packet, length %d", desc_list2.list_len);
+#ifdef SNDCP_TRACE_BUFFER
+    sndcp_trace_desc_list(&desc_list2);
+
+    sndcp_data->cia.trabu[0] = 0;///////////////////////////////////////////////////////////////
+
+#endif
+    v42b_init(sndcp_data->cia.dec, 0, 0, 0, 0);
+    TRACE_EVENT ("as reinit in downlink");
+    /*
+     * the function can be called with 0s as parameters, because it was initialized
+     * befor what the function sees on the valid magic number
+     *
+     * the call replaces an independent reinit function
+     */
+    v42b_decoder(sndcp_data->cia.dec, &desc_list2, NULL, 100);
+    if (!IS_ERROR(sndcp_data->cia.dec))
+    {
+      TRACE_EVENT_P1("V42 DEC: Output Decompressed Packet, length %d", desc_list2.list_len);
+#ifdef SNDCP_TRACE_BUFFER
+      sndcp_trace_desc_list(&desc_list2);
+#endif
+
+      cur_cia_decomp_ind->desc_list2.first = desc_list2.first;
+      cur_cia_decomp_ind->desc_list2.list_len = desc_list2.list_len;
+      
+      cia_cia_decomp_ind(cur_cia_decomp_ind);
+      cur_cia_decomp_ind = NULL;
+    } 
+    else 
+    {
+      MFREE_PRIM (cur_cia_decomp_ind);
+      cur_cia_decomp_ind = NULL;
+      TRACE_EVENT("Deallocate corrupted V.42 bis packet");
+
+      /*
+       * Request next segment.
+       */
+      sd_get_unitdata_if_nec(ll_unitdata_ind->sapi);
+    }
+  } 
+  else 
+  {
+    /*
+     * Request next segment.
+     */
+    sd_get_unitdata_if_nec(ll_unitdata_ind->sapi);
+  }
+  /*
+   * Update global current CIA_DECOMP_IND
+   */
+   sndcp_data->cia.cur_cia_decomp_ind[nsapi] = cur_cia_decomp_ind;
+  /*
+   * Free incoming prim.
+   */
+  if (ll_unitdata_ind != NULL) {
+    PFREE (ll_unitdata_ind);
+    ll_unitdata_ind = NULL;
+  }
+} /* cia_sd_cci_decomp_req_sim() */
+
+/* #endif *//* CF_FAST_EXEC || _SIMULATION_ || !REL99 || SNDCP_2to1 */
+#endif /* TI_PS_FF_V42BIS */
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_sda_cia_cia_decomp_req
++------------------------------------------------------------------------------
+| Description : Simulation for cia reaction to SIG_SDA_CIA_TRANSFER_REQ.
+| If (cur_seg_pos & SEG_POS_FIRST > 0) then a new CIA_DECOMP_IND is allocated.
+| T_desc is allocated with the length of the sdu included in the
+| ll_data_ind. The sdu data is copied to the desc and the desc is added to
+| the currently assembled desc_list in the current CCI_DECOMP_IND.
+| If (cur_seg_pos & SEG_POS_LAST > 0) then a the CIA_DECOMP_IND is now complete
+| and is "sent to this service" by calling the cia function cia_cia_decomp_ind.
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+GLOBAL void sig_sda_cia_cia_decomp_req ( T_LL_DATA_IND* ll_data_ind )
+{
+  USHORT length = 0;
+  USHORT header_len = SN_DATA_PDP_HDR_LEN_SMALL;
+  USHORT sdu_index = 0;
+  T_CIA_DECOMP_IND *cur_cia_decomp_ind;
+  UBYTE nsapi = 0;
+#ifdef _SNDCP_DTI_2_
+  T_desc2* help = NULL;
+  T_desc2* local_desc = NULL;
+#else /*_SNDCP_DTI_2_*/
+  T_desc* help = NULL;
+  T_desc* local_desc = NULL;
+#endif /*_SNDCP_DTI_2_*/
+
+  TRACE_FUNCTION( "cia_sig_sda_cia_cia_decomp_req_sim" );
+
+  nsapi = (ll_data_ind->sdu.buf[(ll_data_ind->sdu.o_buf / 8)]) & 0xf;
+  cur_cia_decomp_ind = sndcp_data->cia.cur_cia_decomp_ind[nsapi];
+
+  /*
+   * In case of first segment allocate new N-PDU.
+   */
+  if ((sndcp_data->cur_seg_pos[nsapi] & SEG_POS_FIRST) > 0) {
+
+    T_CIA_DECOMP_IND *cia_decomp_ind;
+    MALLOC(cia_decomp_ind, sizeof(T_CIA_DECOMP_IND));
+
+#ifdef SNDCP_TRACE_ALL
+    sndcp_data->cia.cia_decomp_ind_number[nsapi] ++;
+    TRACE_EVENT_P1("number of cia_decomp_ind: % d",
+                   sndcp_data->cia.cia_decomp_ind_number[nsapi]);
+#endif
+
+    if (cur_cia_decomp_ind NEQ NULL)
+    {
+      MFREE_PRIM(cur_cia_decomp_ind);
+      TRACE_EVENT("Deallocate unfinished cur_cia_decomp_ind");
+    }
+
+    cur_cia_decomp_ind = cia_decomp_ind;
+
+    /*
+     * Will be changed as soon as more that 1 instance of V42.bis is used.
+     */
+    cur_cia_decomp_ind->algo_type = CIA_ALGO_V42;
+    cur_cia_decomp_ind->comp_inst = CIA_COMP_INST_V42_0;
+
+    cur_cia_decomp_ind->pdu_ref = sndcp_data->cur_pdu_ref[nsapi];
+    cur_cia_decomp_ind->desc_list2.first = (ULONG)NULL;
+    cur_cia_decomp_ind->desc_list2.list_len = 0;
+
+    header_len = SN_DATA_PDP_HDR_LEN_BIG;
+    cia_decomp_ind->pcomp =
+      ll_data_ind->sdu.buf[(ll_data_ind->sdu.o_buf >> 3) + 1] & 0xf;
+
+  }
+  /*
+   * If big header has been received in state != RECEIVE_FIRST_SEGMENT
+   */
+  if (sndcp_data->big_head[nsapi]) {
+    header_len = SN_DATA_PDP_HDR_LEN_BIG;
+  }
+  sdu_index = (ll_data_ind->sdu.o_buf >> 3) + header_len;
+  
+  if ((ll_data_ind->sdu.l_buf >> 3) < header_len){
+     /*This condition is added as part of fix for GCF 46.1.2.2.3.2 failure because of wrong length*/
+     TRACE_ERROR("SNDCP: Unexpected Length of N-PDU");
+     PFREE (ll_data_ind);
+     ll_data_ind = NULL;
+     return;
+  }else{
+
+     length = (ll_data_ind->sdu.l_buf >> 3) - header_len;
+  }
+
+  /*
+   * Allocate new descriptor and copy sdu data.
+   */
+#ifdef _SNDCP_DTI_2_
+  MALLOC (local_desc, (USHORT)(sizeof(T_desc2) - 1 + length));
+#else /*_SNDCP_DTI_2_*/
+  MALLOC (local_desc, (USHORT)(sizeof(T_desc) - 1 + length));
+#endif /*_SNDCP_DTI_2_*/
+
+  /*
+   * Fill descriptor control information.
+   */
+  local_desc->next  = (ULONG)NULL;
+  local_desc->len   = length;
+#ifdef _SNDCP_DTI_2_
+  local_desc->offset = 0;
+  local_desc->size = local_desc->len;
+#endif
+  /*
+   * Add length of descriptor data to list length.
+   */
+  cur_cia_decomp_ind->desc_list2.list_len += length;
+
+  /*
+   * Copy user data from SDU to descriptor.
+   */
+  if (length>0)
+  {
+    memcpy (local_desc->buffer, &ll_data_ind->sdu.buf[sdu_index], length);
+  }
+
+  /*
+   * Add desc to desc_list.
+   */
+#ifdef _SNDCP_DTI_2_
+  help = (T_desc2*)cur_cia_decomp_ind->desc_list2.first;
+#else /*_SNDCP_DTI_2_*/
+  help = (T_desc*)cur_cia_decomp_ind->desc_list2.first;
+#endif /*_SNDCP_DTI_2_*/
+  if (help == NULL) {
+    cur_cia_decomp_ind->desc_list2.first = (ULONG)local_desc;
+  } else {
+    if (help->next == NULL) {
+      help->next = (ULONG) local_desc;
+    } else {
+      while (help->next != NULL) {
+#ifdef _SNDCP_DTI_2_
+        help = (T_desc2*)help->next;
+#else /*_SNDCP_DTI_2_*/
+        help = (T_desc*)help->next;
+#endif /*_SNDCP_DTI_2_*/
+      }
+      help->next = (ULONG)local_desc;
+    }
+  }
+  /*
+   * If this is the last segment, send it to this same service with a simulated
+   * primitive.
+   */
+  if ((sndcp_data->cur_seg_pos[nsapi] & SEG_POS_LAST) > 0) {
+    /*
+     * By now algo_type and comp_inst are not evaluated.
+     */
+    cur_cia_decomp_ind->pdu_ref = sndcp_data->cur_pdu_ref[nsapi];
+    cia_cia_decomp_ind(cur_cia_decomp_ind);
+    cur_cia_decomp_ind = NULL;
+    /*
+     * Reset the Current Segment Counter to zero, since we have received the 
+     * last segment 
+     */
+    sndcp_data->cur_segment_number[nsapi] = 0;
+  } else {
+    /*
+     * Check the Current Segment Number whether we have received more than 
+     * SNDCP_MAX_SEGMENT_NUMBER segments or not. If we have received more than 
+     * SNDCP_MAX_SEGMENT_NUMBER segments in a single NPDU, then we will discard
+     * the stored segments and also the remaining segments of this NPDU, till 
+     * we receive that last segment of this NPDU.
+     * This has been done in order to encounter the PARTITION problem which
+     * we will face if we keep on storing the segments in SNDCP.
+     */
+    sndcp_data->cur_segment_number[nsapi] ++;
+    if (sndcp_data-> cur_segment_number[nsapi] > SNDCP_MAX_SEGMENT_NUMBER)
+    {
+      TRACE_EVENT("Segment Number in Single NPDU exceeds max segment number");
+
+      /* Deleting the stored segments */
+      sig_mg_cia_delete_npdus(nsapi);
+
+      /* Change the state to SDA_ACK_DISCARD */
+      sndcp_set_nsapi_rec_state(nsapi, SDA_ACK_DISCARD);
+    }
+
+    /*
+     * Request next segment.
+     */
+    sda_get_data_if_nec(ll_data_ind->sapi);
+  }
+  /*
+   * Update global current CIA_DECOMP_IND
+   */
+  sndcp_data->cia.cur_cia_decomp_ind[nsapi] = cur_cia_decomp_ind;
+  /*
+   * Free incoming prim.
+   */
+  if (ll_data_ind != NULL) {
+    PFREE (ll_data_ind);
+    ll_data_ind = NULL;
+  }
+} /* cia_sig_sda_cia_cia_decomp_req_sim() */
+
+#endif /* CF_FAST_EXEC */
+
+
+/*==== PUBLIC FUNCTIONS =====================================================*/
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_mg_cia_reset_ind
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_MG_CIA_RESET_IND
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+GLOBAL void sig_mg_cia_reset_ind (void)
+{
+  TRACE_ISIG( "sig_mg_cia_reset_ind" );
+
+  switch( GET_STATE(CIA) )
+  {
+    case CIA_DEFAULT:
+      sndcp_reset_xid_block(&sndcp_data->cia.cur_xid_block);
+      break;
+    default:
+      TRACE_ERROR( "SIG_MG_CIA_RESET_IND unexpected" );
+      break;
+  }
+} /* sig_mg_cia_reset_ind() */
+
+#endif /* CF_FAST_EXEC */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_su_cia_cia_comp_req
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_SU_CIA_CIA_COMP_REQ
+|               This function makes a decision whether we are using data
+|               compression in uplink direction and calls the according
+|               function.
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \
+   defined(SNDCP_2to1) */
+
+GLOBAL void sig_su_cia_cia_comp_req (T_SN_UNITDATA_REQ* sn_unitdata_req,
+                                 USHORT npdu_number,
+                                 UBYTE nsapi,
+                                 UBYTE sapi
+                                 )
+{
+  U8 direction = 0;
+  BOOL compressed = FALSE;
+  UBYTE packet_type = TYPE_IP;
+  TRACE_ISIG( "sig_su_cia_cia_comp_req" );
+
+  switch( GET_STATE(CIA) )
+  {
+    case CIA_DEFAULT:
+      sndcp_is_nsapi_header_compressed(nsapi, &compressed);
+      if (compressed) {
+#ifdef _SNDCP_DTI_2_
+        cia_header_comp(&sn_unitdata_req->desc_list2,
+                        &sn_unitdata_req->desc_list2,
+                        &packet_type);
+#else /*_SNDCP_DTI_2_*/
+        cia_header_comp(&sn_unitdata_req->desc_list,
+                        &sn_unitdata_req->desc_list,
+                        &packet_type);
+#endif /*_SNDCP_DTI_2_*/
+      }
+
+      sndcp_is_nsapi_data_compressed(nsapi, &compressed);
+      if (sndcp_data->cia.cur_xid_block.v42.is_set)
+      {
+        if (sndcp_data->cia.cur_xid_block.v42.p0_set)
+        {
+          direction = sndcp_data->cia.cur_xid_block.v42.p0;
+          TRACE_EVENT_P1("dir: %d",direction);
+        }
+      }
+      if (compressed && (direction & 0x01)) { /* datacompr. in uplink ? */
+#ifdef TI_PS_FF_V42BIS
+
+        cia_su_cci_comp_req(sn_unitdata_req,
+                            npdu_number,
+                            nsapi,
+                            sapi,
+                            packet_type);
+
+#else  /* !TI_PS_FF_V42BIS */
+        TRACE_EVENT("INFO CIA: Data compression is not implemented yet!");
+        MFREE_PRIM(sn_unitdata_req);
+        sn_unitdata_req = NULL;
+
+#endif /* TI_PS_FF_V42BIS */
+      } else { /* if (compressed)  */
+        cia_su_cia_comp_req(sn_unitdata_req,
+                                    npdu_number,
+                                    nsapi,
+                                    sapi,
+                                    packet_type);
+      }
+      break;
+    default:
+      TRACE_ERROR( "SIG_SU_CIA_CIA_COMP_REQ unexpected" );
+#ifdef _SNDCP_DTI_2_
+      MFREE_PRIM(sn_unitdata_req);
+#else /*_SNDCP_DTI_2_*/
+      PFREE_DESC(sn_unitdata_req);
+#endif /*_SNDCP_DTI_2_*/
+      break;
+  }
+} /* sig_su_cia_cia_comp_req() */
+
+/*#endif */ /* CF_FAST_EXEC || _SIMULATION_ || !REL99 || SNDCP_2to1 */
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_sua_cia_cia_comp_req
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_SUA_CIA_CIA_COMP_REQ
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+GLOBAL void sig_sua_cia_cia_comp_req (T_SN_DATA_REQ* sn_data_req,
+                                 UBYTE npdu_number,
+                                 UBYTE nsapi,
+                                 UBYTE sapi
+                                 )
+{
+  BOOL compressed = FALSE;
+  UBYTE packet_type = TYPE_IP;
+  /*
+   * define desc_list for comp header. Is initialized later.
+   */
+#ifdef _SNDCP_DTI_2_
+  T_desc_list2 dest_desc_list;
+#else /*_SNDCP_DTI_2_*/
+  T_desc_list dest_desc_list;
+#endif /*_SNDCP_DTI_2_*/
+
+  TRACE_ISIG( "sig_sua_cia_cia_comp_req" );
+
+  switch( GET_STATE(CIA) )
+  {
+    case CIA_DEFAULT:
+      sndcp_is_nsapi_header_compressed(nsapi, &compressed);
+      if (compressed) {
+#ifdef _SNDCP_DTI_2_
+        cia_header_comp(&dest_desc_list,
+                        &sn_data_req->desc_list2,
+                        &packet_type);
+      } else {
+        dest_desc_list = sn_data_req->desc_list2;
+#else /*_SNDCP_DTI_2_*/
+        cia_header_comp(&dest_desc_list,
+                        &sn_data_req->desc_list,
+                        &packet_type);
+      } else {
+        dest_desc_list = sn_data_req->desc_list;
+#endif /*_SNDCP_DTI_2_*/
+      }
+
+      sndcp_is_nsapi_data_compressed(nsapi, &compressed);
+      if (compressed) {
+
+       /*
+        * The data compression routine shall be invoked here.
+        */
+        TRACE_EVENT("INFO CIA: Data compression is not implemented yet!");
+        MFREE_PRIM(sn_data_req);
+        sn_data_req = NULL;
+
+      } else { /* if (compressed) */
+        cia_sua_cia_comp_req(dest_desc_list,
+                                     npdu_number,
+                                     nsapi,
+                                     sapi,
+                                     packet_type);
+      }
+      /*
+       * free comp header
+       */
+      if (compressed && dest_desc_list.first != 0) {
+        MFREE(dest_desc_list.first);
+        dest_desc_list.first = 0;
+      }
+      break;
+    default:
+      TRACE_ERROR( "SIG_SUA_CIA_CIA_COMP_REQ unexpected" );
+#ifdef _SNDCP_DTI_2_
+      MFREE_PRIM(sn_data_req);
+#else /*_SNDCP_DTI_2_*/
+      PFREE_DESC(sn_data_req);
+#endif /*_SNDCP_DTI_2_*/      
+      break;
+  }
+} /* sig_sua_cia_cia_comp_req() */
+
+#endif /* CF_FAST_EXEC */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_mg_cia_delete_npdus
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_MG_CIA_DELETE_NPDUS
+|
+| Parameters  : nsapi
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+GLOBAL void sig_mg_cia_delete_npdus (UBYTE nsapi)
+{
+  TRACE_ISIG( "sig_mg_cia_delete_npdus" );
+
+  switch( GET_STATE(CIA) )
+  {
+    case CIA_DEFAULT:
+      if (sndcp_data->cia.cur_cia_decomp_ind[nsapi] != NULL) {
+#ifdef SNDCP_TRACE_ALL
+        sndcp_data->cia.cia_decomp_ind_number[nsapi] --;
+        TRACE_EVENT_P1("number of cia_decomp_ind: % d",
+                       sndcp_data->cia.cia_decomp_ind_number[nsapi]);
+#endif /* SNDCP_TRACE_ALL */
+          /*
+           * Currently assembled pdu is for given nsapi.
+           */
+        MFREE_PRIM(sndcp_data->cia.cur_cia_decomp_ind[nsapi]);
+        sndcp_data->cia.cur_cia_decomp_ind[nsapi] = NULL;
+      }
+      break;
+    default:
+      TRACE_ERROR( "SIG_MG_CIA_DELETE_XID unexpected" );
+      break;
+  }
+} /* SIG_MG_CIA_DELETE_NPDUS() */
+
+#endif /* CF_FAST_EXEC */
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_mg_cia_new_xid
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_MG_CIA_NEW_XID
+|
+| Parameters  : new T_XID_BLOCK
+|
++------------------------------------------------------------------------------
+*/
+#ifndef CF_FAST_EXEC
+
+GLOBAL void sig_mg_cia_new_xid (T_XID_BLOCK* new_xid)
+{
+#ifdef TI_PS_FF_V42BIS
+  T_XID_BLOCK* old_xid;
+  U8  p0 = SNDCP_V42_DEFAULT_DIRECTION;
+  U16 p1 = SNDCP_V42_DEFAULT_P1;
+  U8  p2 = SNDCP_V42_DEFAULT_P2;
+
+  old_xid = &(sndcp_data->cia.cur_xid_block);
+#endif
+
+  TRACE_ISIG( "sig_mg_cia_new_xid" );
+
+  switch( GET_STATE(CIA) )
+  {
+    case CIA_DEFAULT:
+      if (new_xid->vj.is_set) {
+        if (new_xid->vj.s0_m_1_set) {
+          cia_compress_init((UBYTE)(new_xid->vj.s0_m_1));
+        }
+      }
+#ifdef TI_PS_FF_V42BIS
+      if (new_xid->v42.is_set)
+      {
+        /* block is valid */
+        if (new_xid->v42.p0_set)
+        {
+          p0 = new_xid->v42.p0;
+          /* what have we to do, if p0 is not set? */
+        }
+        if (new_xid->v42.p1_set)
+        {
+          p1 = new_xid->v42.p1;
+          /* what have we to do, if p1 is not set? */
+        }
+        if (new_xid->v42.p2_set)
+        {
+          p2 = new_xid->v42.p2;
+          /* what have we to do, if p2 is not set? */
+        }            
+        
+        if (new_xid->v42.nsapis_set && new_xid->v42.nsapis == 0)
+        {
+          /* no applicable NSAPI
+           * turn off data compression in either direction
+           */
+          if (old_xid->v42.p0_set && old_xid->v42.p0 & 0x1) /* uplink */
+          {
+            TRACE_EVENT_P1("1 enc dico:%08x",sndcp_data->cia.enc);
+            v42b_deinit(sndcp_data->cia.enc);
+            MFREE(sndcp_data->cia.enc);
+            TRACE_EVENT("uplink deinit");
+          }
+          if (old_xid->v42.p0_set && old_xid->v42.p0 & 0x2) /* downlink */
+          {
+            TRACE_EVENT_P1("1 dec dico:%08x",sndcp_data->cia.dec);
+            v42b_deinit(sndcp_data->cia.dec);
+            MFREE(sndcp_data->cia.dec);
+            TRACE_EVENT("downlink deinit");
+          }
+        }
+        else if (old_xid->v42.is_set)
+        {
+          /* currently we have a valid xid-block for data compression
+           * we have to check the parameters 
+           */
+          
+          /* we have to check the parameters */
+          if (old_xid->v42.p0 != p0 ||
+              old_xid->v42.p1 != p1 ||
+              old_xid->v42.p2 != p2)
+          {
+            /* parameters have changed */
+            if (old_xid->v42.p0_set && old_xid->v42.p0 & 0x1) /* uplink */
+            {
+              TRACE_EVENT_P1("2 enc dico:%08x",sndcp_data->cia.enc);
+              v42b_deinit(sndcp_data->cia.enc);
+              MFREE(sndcp_data->cia.enc);
+              TRACE_EVENT("uplink deinit");
+            }
+            if (old_xid->v42.p0_set && old_xid->v42.p0 & 0x2) /* downlink */
+            {
+              TRACE_EVENT_P1("2 dec dico:%08x",sndcp_data->cia.dec);
+              v42b_deinit(sndcp_data->cia.dec);
+              MFREE(sndcp_data->cia.dec);
+              TRACE_EVENT("uplink deinit");
+            }
+            /* we have to init with new parameters */
+            if (p0 & 0x1)/* uplink */
+            {
+              TRACE_EVENT_P1("DICO_SIZE:%d",sizeof(T_V42B_DICO));
+              MALLOC(sndcp_data->cia.enc, sizeof(T_V42B_DICO));
+              TRACE_EVENT_P1("enc dico:%08x",sndcp_data->cia.enc);
+              v42b_init(sndcp_data->cia.enc, p1, p2, 50, BANK_SIZE_512);
+              TRACE_EVENT("uplink init");
+            }
+            if (p0 & 0x2)/* downlink */
+            {
+              TRACE_EVENT_P1("DICO_SIZE:%d",sizeof(T_V42B_DICO));
+              MALLOC(sndcp_data->cia.dec, sizeof(T_V42B_DICO));
+              v42b_init(sndcp_data->cia.dec, p1, p2, 0, BANK_SIZE_512);
+              TRACE_EVENT_P1("dec dico:%08x",sndcp_data->cia.dec);
+              TRACE_EVENT("downlink init");
+            }     
+          }
+        }
+        else
+        {
+          /* currently we have no valid xid-block for data comprssion */
+          if (p0 & 0x1)/* uplink */
+          {
+            TRACE_EVENT_P1("DICO_SIZE:%d",sizeof(T_V42B_DICO));
+            MALLOC(sndcp_data->cia.enc, sizeof(T_V42B_DICO));
+            TRACE_EVENT_P1("enc dico:%08x",sndcp_data->cia.enc);
+            v42b_init(sndcp_data->cia.enc, p1, p2, 50, BANK_SIZE_512);
+            TRACE_EVENT("uplink init");
+          }
+          if (p0 & 0x2)/* downlink */
+          {
+            TRACE_EVENT_P1("DICO_SIZE:%d",sizeof(T_V42B_DICO));
+            MALLOC(sndcp_data->cia.dec, sizeof(T_V42B_DICO));
+            TRACE_EVENT_P1("dec dico:%08x",sndcp_data->cia.dec);
+            v42b_init(sndcp_data->cia.dec, p1, p2, 0, BANK_SIZE_512);
+            TRACE_EVENT("downlink init");
+          }          
+        }
+      }
+      else
+      {
+        if (old_xid->v42.is_set && old_xid->v42.nsapis_set && old_xid->v42.nsapis != 0)
+        {
+          /* we have no XID with V42 set */
+          if (old_xid->v42.p0_set && old_xid->v42.p0 & 0x1) /* uplink */
+          {
+            TRACE_EVENT_P1("3 enc dico:%08x",sndcp_data->cia.enc);
+            v42b_deinit(sndcp_data->cia.enc);
+            MFREE(sndcp_data->cia.enc);
+            TRACE_EVENT("uplink deinit");
+          }
+          if (old_xid->v42.p0_set && old_xid->v42.p0 & 0x2) /* downlink */
+          {
+            TRACE_EVENT_P1("3 dec dico:%08x",sndcp_data->cia.dec);
+            v42b_deinit(sndcp_data->cia.dec);
+            MFREE(sndcp_data->cia.dec);
+            TRACE_EVENT("downlink deinit");
+          }
+        }
+      }
+#endif /* TI_PS_FF_V42BIS */
+      sndcp_data->cia.cur_xid_block = *new_xid;
+      break;
+    default:
+      TRACE_ERROR( "SIG_MG_CIA_NEW_XID unexpected" );
+      break;
+  }
+} /* SIG_MG_CIA_NEW_XID() */
+
+#endif /* CF_FAST_EXEC */
+
+/*
++------------------------------------------------------------------------------
+| Function    : sig_sd_cia_cia_decomp_req
++------------------------------------------------------------------------------
+| Description : Handles the internal signal SIG_SD_CIA_TRANSFER_REQ
+|               This function mekes a decision whether we are using data 
+|               compression in downlink direction and calls the according
+|               function.
+|
+| Parameters  :
+|
++------------------------------------------------------------------------------
+*/
+/*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \
+   defined(SNDCP_2to1) */
+
+GLOBAL void sig_sd_cia_cia_decomp_req (T_LL_UNITDATA_IND* ll_unitdata_ind)/*UBYTE dcomp,
+                                     T_pdu_ref pdu_ref,
+                                     USHORT cur_seg_pos,
+                                     T_LL_UNITDATA_IND* ll_unitdata_ind
+                                    )*/
+{
+#ifdef TI_PS_FF_V42BIS
+  U8 direction = 0;
+  U8 nsapi;
+#endif /* TI_PS_FF_V42BIS */
+  TRACE_ISIG( "sig_sd_cia_cia_decomp_req" );
+#ifdef TI_PS_FF_V42BIS  
+  nsapi = (ll_unitdata_ind->sdu.buf[(ll_unitdata_ind->sdu.o_buf / 8)]) & 0xf;
+#endif /* TI_PS_FF_V42BIS */   
+  switch( GET_STATE(CIA) )
+  {
+    case CIA_DEFAULT:
+#ifdef TI_PS_FF_V42BIS
+      if (sndcp_data->cia.cur_xid_block.v42.is_set)
+      {
+        if (sndcp_data->cia.cur_xid_block.v42.p0_set)
+        {
+          direction = sndcp_data->cia.cur_xid_block.v42.p0;
+          TRACE_EVENT_P1("dir: %d",direction);
+        }
+      }
+      /*
+       * Is dcomp in sdu equal to dcomp in cur_xid_block and downlink?
+       */
+      TRACE_EVENT_P1("our dcomp value: %d", sndcp_data->cia.cur_xid_block.v42.dcomp);
+      TRACE_EVENT_P1("receipt dcomp value: %d", sndcp_data->cur_dcomp[nsapi]);
+      if (sndcp_data->cur_dcomp[nsapi] == sndcp_data->cia.cur_xid_block.v42.dcomp && (direction & 0x2))
+      {
+        /*
+         * Compression used
+         */
+        cia_sd_cci_decomp_req(/*pdu_ref, cur_seg_pos, */ll_unitdata_ind);
+
+      } else {
+        /*
+         * No compression used, request will not be sent to CCI, but handled
+         * in cia service.
+         */
+        cia_sd_cia_decomp_req (/*pdu_ref, cur_seg_pos, */ll_unitdata_ind);
+      }
+#else /* ! TI_PS_FF_V42BIS */
+      cia_sd_cia_decomp_req (/*pdu_ref, cur_seg_pos, */ll_unitdata_ind);
+#endif /* TI_PS_FF_V42BIS */
+
+      break;
+    default:
+      TRACE_ERROR( "SIG_SD_CIA_TRANSFER_REQ unexpected" );
+      break;
+  }
+} /* sig_sd_cia_cia_decomp_req() */
+/*#endif */