diff src/g23m-fad/ppp/ppp_frxf.c @ 174:90eb61ecd093

src/g23m-fad: initial import from TCS3.2/LoCosto
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 12 Oct 2016 05:40:46 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/g23m-fad/ppp/ppp_frxf.c	Wed Oct 12 05:40:46 2016 +0000
@@ -0,0 +1,1365 @@
+/* 
++----------------------------------------------------------------------------- 
+|  Project :  
+|  Modul   :  
++----------------------------------------------------------------------------- 
+|  Copyright 2002 Texas Instruments Berlin, AG 
+|                 All rights reserved. 
+| 
+|                 This file is confidential and a trade secret of Texas 
+|                 Instruments Berlin, AG 
+|                 The receipt of or possession of this file does not convey 
+|                 any rights to reproduce or disclose its contents or to 
+|                 manufacture, use, or sell anything it may describe, in 
+|                 whole, or in part, without the specific written consent of 
+|                 Texas Instruments Berlin, AG. 
++----------------------------------------------------------------------------- 
+|  Purpose :  This modul is part of the entity PPP and implements all 
+|             procedures and functions as described in the 
+|             SDL-documentation (FRX-statemachine)
++----------------------------------------------------------------------------- 
+*/ 
+
+#define ENTITY_PPP
+
+/*==== INCLUDES =============================================================*/
+
+#include "typedefs.h"   /* to get Condat data types */
+#include "vsi.h"        /* to get a lot of macros */
+#include "macdef.h"     /* to get a lot of macros */
+#include "custom.h"     /* to get a lot of macros */
+/*lint -efile(766,gsm.h) */
+#include "gsm.h"        /* to get a lot of macros */
+/*lint -efile(766,cnf_ppp.h) */
+#include "cnf_ppp.h"    /* to get cnf-definitions */
+/*lint -efile(766,mon_ppp.h) */
+#include "mon_ppp.h"    /* to get mon-definitions */
+#include "prim.h"       /* to get the definitions of used SAP and directions */
+#include "dti.h"        /* to get the DTILIB definitions */
+#include "ppp.h"        /* to get the global entity definitions */
+#include "ppp_ptxs.h"   /* to get signal interface from ptx */
+
+#include "ppp_arbf.h"   /* to get arb functions */
+
+#include <string.h>     /* to get memcpy */
+
+#ifdef PPP_HDLC_TRACE
+#include <stdio.h>      /* to get sprintf */
+#endif /* PPP_HDLC_TRACE */
+/*==== CONST ================================================================*/
+
+/*==== LOCAL VARS ===========================================================*/
+
+/*==== PRIVATE FUNCTIONS ====================================================*/
+
+/*==== PUBLIC FUNCTIONS =====================================================*/
+
+
+
+#ifndef PPP_INT_RAM
+/*
++------------------------------------------------------------------------------
+| Function    : frx_init
++------------------------------------------------------------------------------
+| Description : The function frx_init() initializes Frame Receive (FRX)
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void frx_init ()
+{ 
+  TRACE_FUNCTION( "frx_init" );
+
+  ppp_data->frx.frame_complete   = FALSE;
+  ppp_data->frx.stored_packet    = NULL;
+  ppp_data->frx.received_data    = NULL;
+  ppp_data->frx.store_state      = FRX_ADD_ERROR;
+  ppp_data->frx.data_flow_state  = FRX_DATA_FLOW_DEAD;
+
+#ifdef PPP_HDLC_TRACE
+  ppp_data->frx.hdlc_frame     = NULL;
+#endif /* PPP_HDLC_TRACE */
+  
+  INIT_STATE( PPP_SERVICE_FRX , FRX_DEAD );
+} /* frx_init() */
+#endif  /* PPP_INT_RAM */
+
+
+#ifndef PPP_FLASH_ROM
+/*
++------------------------------------------------------------------------------
+| Function    : frx_add_desc
++------------------------------------------------------------------------------
+| Description : The function frx_add_desc() appends the given 
+|               generic data descriptor to the already received descriptors.
+|               The function removes transparent characters and calculates
+|               the fcs.
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void frx_add_desc ()
+{
+  UBYTE    store_state;
+  UBYTE    currentbyte;
+  USHORT   fcs;
+  UBYTE    escape;
+  USHORT   s_offset;
+  USHORT   s_size;
+  UBYTE*   destination;
+  USHORT   d_offset;
+  USHORT   d_size;
+  USHORT*  fcstab;
+  T_desc2* source_desc;
+  T_desc2* temp_desc;
+  USHORT   packet_len;
+#ifdef PPP_HDLC_TRACE
+  T_desc2* trace_desc;
+  T_desc2* trace_desc2;
+  T_desc2* trace_desc3;
+  USHORT   trace_pos;
+  char     buf[100];
+  USHORT   i;
+#endif /* PPP_HDLC_TRACE */
+
+  TRACE_FUNCTION( "frx_add_desc" );
+
+#ifdef PPP_HDLC_TRACE
+  /*
+   * trace HDLC frame
+   * the goal is to trace out only erroneous PPP frames
+   * if a correct PPP frame is received 
+   * we just release the stored copy of this frame without tracing
+   */
+  /*
+   * set source pointer
+   */
+  trace_desc = ppp_data->frx.received_data;
+  trace_pos  = ppp_data->frx.proceed_data;
+  switch(ppp_data->frx.store_state)
+  {
+    case FRX_ADD_ERROR:
+      /*
+       * we trace out each byte til the first HDLC flag
+       */
+      /*
+       * release old stored HDLC frame
+       * this should not be necessary
+       */
+      MFREE_DESC2(ppp_data->frx.hdlc_frame);
+      ppp_data->frx.hdlc_frame = NULL;
+      /*
+       * trace incomming data until the first HDLC flag
+       */
+      while((trace_desc) && (trace_pos >= trace_desc->len))
+      {
+        trace_desc = (T_desc2*)trace_desc->next;
+        trace_pos  = 0;
+      }
+      if((trace_desc) &&
+         (trace_desc->buffer[trace_pos] NEQ PPP_HDLC_FLAG))
+      {
+        TRACE_EVENT("waiting for next HDLC flag:");
+        i = 0;
+        do
+        {
+          i+= sprintf(&buf[i], "0x%02x, ", trace_desc->buffer[trace_pos]);
+          trace_pos++;
+          while((trace_desc) && (trace_pos >= trace_desc->len))
+          {
+            trace_desc = (T_desc2*)trace_desc->next;
+            trace_pos  = 0;
+          }
+          if(i > 80)
+          {
+            TRACE_EVENT( buf );
+            i = 0;
+          }
+        }
+        while((trace_desc) &&
+              (trace_desc->buffer[trace_pos] NEQ PPP_HDLC_FLAG));
+        if(i > 0)
+        {
+          TRACE_EVENT( buf );
+          i = 0;
+        }
+      }
+      break;
+
+    case FRX_ADD_HDLC_BEGIN:
+      /*
+       * we store just the first HDLC flag and fall through 
+       * to the default case to store the complete PPP frame
+       */
+      /*
+       * release old stored HDLC frame
+       */
+      MFREE_DESC2(ppp_data->frx.hdlc_frame);
+      ppp_data->frx.hdlc_frame = NULL;
+
+      if(trace_desc)
+      {
+        /*
+         * allocate first descriptor to store new HDLC frame
+         */
+        MALLOC(trace_desc2,
+               (USHORT)(sizeof(T_desc2) - 1 + FRX_ADD_SMALL_PACKET_SIZE));
+        trace_desc2->len         = 0;
+        trace_desc2->next        = (ULONG)NULL;
+        ppp_data->frx.hdlc_frame = trace_desc2;
+
+        /*
+         * store first HDLC flag
+         */
+        TRACE_EVENT_P2("start flag found in desc=0x%08x: pos=%d", 
+                       trace_desc, 
+                       trace_pos);
+        trace_desc2->buffer[trace_desc2->len] = trace_desc->buffer[trace_pos];
+        trace_desc2->len++;
+        trace_pos++;
+        while((trace_desc) && (trace_pos >= trace_desc->len))
+        {
+          trace_desc = (T_desc2*)trace_desc->next;
+          trace_pos  = 0;
+        }
+      }
+      /* fall through */
+    default:
+      /*
+       * to store the complete PPP frame
+       */
+      /*
+       * set destination pointer
+       */
+      trace_desc2 = ppp_data->frx.hdlc_frame;
+      while(trace_desc2->next NEQ (ULONG)NULL)
+      {
+        trace_desc2 = (T_desc2*)trace_desc2->next;
+      }
+
+      /*
+       * set source pointer
+       */
+      while((trace_desc) && (trace_pos >= trace_desc->len))
+      {
+        trace_desc = (T_desc2*)trace_desc->next;
+        trace_pos  = 0;
+      }
+
+      if(trace_desc)
+      {
+        /*
+         * store HDLC frame
+         */
+        while((trace_desc) &&
+              (trace_desc->buffer[trace_pos] NEQ PPP_HDLC_FLAG))
+        {
+          if(trace_desc2->len >= FRX_ADD_SMALL_PACKET_SIZE)
+          {
+            MALLOC(trace_desc3, (USHORT)(sizeof(T_desc2) - 1 + 
+                                  FRX_ADD_SMALL_PACKET_SIZE));
+            trace_desc3->len  = 0;
+            trace_desc3->next = (ULONG)NULL;
+            trace_desc2->next = (ULONG)trace_desc3;
+            trace_desc2       = trace_desc3;
+          }
+          trace_desc2->buffer[trace_desc2->len] = 
+            trace_desc->buffer[trace_pos];
+          trace_desc2->len++;
+          trace_pos++;
+          while((trace_desc) && (trace_pos >= trace_desc->len))
+          {
+            trace_desc = (T_desc2*)trace_desc->next;
+            trace_pos  = 0;
+          }
+        }
+        /*
+         * store last HDLC flag
+         */
+        if(trace_desc)
+        {
+          if(trace_desc2->len >= FRX_ADD_SMALL_PACKET_SIZE)
+          {
+            MALLOC(trace_desc3, (USHORT)(sizeof(T_desc2) - 1 + 
+                                  FRX_ADD_SMALL_PACKET_SIZE));
+            trace_desc3->len  = 0;
+            trace_desc3->next = (ULONG)NULL;
+            trace_desc2->next = (ULONG)trace_desc3;
+            trace_desc2       = trace_desc3;
+          }
+          TRACE_EVENT_P2("stop flag found in desc=0x%08x pos=%d", 
+                         trace_desc, 
+                         trace_pos);
+          trace_desc2->buffer[trace_desc2->len] = 
+            trace_desc->buffer[trace_pos];
+          trace_desc2->len++;
+          trace_pos++;
+        }
+      }
+      break;
+  }
+#endif /* PPP_HDLC_TRACE */
+  /*
+   * copy all important values into local variables
+   */
+  store_state = ppp_data->frx.store_state;
+  fcs         = ppp_data->frx.calc_fcs;
+  escape      = ppp_data->frx.escape;
+  source_desc = ppp_data->frx.received_data;
+  s_offset    = ppp_data->frx.proceed_data;
+  fcstab      = ppp_data->fcstab;
+  /*
+   * set destination pointer
+   */
+  destination = NULL;
+  d_offset    = 0;
+  d_size      = 0;
+  switch(store_state)
+  {
+    case FRX_ADD_INFORMATION:
+    case FRX_ADD_FCS1:
+    case FRX_ADD_FCS2:
+      destination = ppp_data->frx.cur_desc->buffer;
+      d_offset    = ppp_data->frx.cur_desc->len;
+      d_size      = ppp_data->frx.cur_desc_size;
+      break;
+  } /*lint !e744 switch statement has no default */
+  /*
+   * while there is still data to analyze and 
+   * a complete packet is not yet received
+   */
+  while((source_desc) && (ppp_data->frx.frame_complete EQ FALSE))
+  {
+    /*
+     * while the current descriptor is not yet complete analyzed.
+     * if a complete packet is analyzed we leave the loop via break command
+     */
+    for(s_size = source_desc->len; s_offset < s_size; s_offset++)
+    {
+      /*
+       * set current byte
+       */
+      currentbyte = source_desc->buffer[s_offset];
+      /*
+       * detect HDLC flag
+       */
+      if(currentbyte EQ PPP_HDLC_FLAG)
+      {
+        if(store_state EQ FRX_ADD_ERROR)
+        {
+#ifdef PPP_HDLC_TRACE
+          /*
+           * store next HDLC frame
+           */
+          /*
+           * release old stored HDLC frame
+           */
+          MFREE_DESC2(ppp_data->frx.hdlc_frame);
+          ppp_data->frx.hdlc_frame = NULL;
+          /*
+           * set source pointer
+           */
+          trace_desc = source_desc;
+          trace_pos  = s_offset;
+          /*
+           * allocate first descriptor to store new HDLC frame
+           */
+          MALLOC(trace_desc2, (USHORT)(sizeof(T_desc2) - 1 + 
+                                FRX_ADD_SMALL_PACKET_SIZE));
+          trace_desc2->len         = 0;
+          trace_desc2->next        = (ULONG)NULL;
+          ppp_data->frx.hdlc_frame = trace_desc2;
+
+          /*
+           * store first HDLC flag
+           */
+          TRACE_EVENT_P2("start flag found in desc=0x%08x pos=%d", 
+                         trace_desc, 
+                         trace_pos);
+          trace_desc2->buffer[trace_desc2->len] = 
+            trace_desc->buffer[trace_pos];
+          trace_desc2->len++;
+          trace_pos++;
+          while((trace_desc) && (trace_pos >= trace_desc->len))
+          {
+            trace_desc = (T_desc2*)trace_desc->next;
+            trace_pos  = 0;
+          }
+          if(trace_desc)
+          {
+            /*
+             * store HDLC frame
+             */
+            while((trace_desc) &&
+                  (trace_desc->buffer[trace_pos] NEQ PPP_HDLC_FLAG))
+            {
+              if(trace_desc2->len >= FRX_ADD_SMALL_PACKET_SIZE)
+              {
+                MALLOC(trace_desc3, (USHORT)(sizeof(T_desc2) - 1 + 
+                                      FRX_ADD_SMALL_PACKET_SIZE));
+                trace_desc3->len  = 0;
+                trace_desc3->next = (ULONG)NULL;
+                trace_desc2->next = (ULONG)trace_desc3;
+                trace_desc2       = trace_desc3;
+              }
+              trace_desc2->buffer[trace_desc2->len] = 
+                trace_desc->buffer[trace_pos];
+              trace_desc2->len++;
+              trace_pos++;
+              while((trace_desc) && (trace_pos >= trace_desc->len))
+              {
+                trace_desc = (T_desc2*)trace_desc->next;
+                trace_pos  = 0;
+              }
+            }
+            /*
+             * store last HDLC flag
+             */
+            if(trace_desc)
+            {
+              if(trace_desc2->len >= FRX_ADD_SMALL_PACKET_SIZE)
+              {
+                MALLOC(trace_desc3, (USHORT)(sizeof(T_desc2) - 1 + 
+                                      FRX_ADD_SMALL_PACKET_SIZE));
+                trace_desc3->len  = 0;
+                trace_desc3->next = (ULONG)NULL;
+                trace_desc2->next = (ULONG)trace_desc3;
+                trace_desc2       = trace_desc3;
+              }
+              TRACE_EVENT_P2("stop flag found in desc=0x%08x pos=%d", 
+                             trace_desc, 
+                             trace_pos);
+              trace_desc2->buffer[trace_desc2->len] = 
+                trace_desc->buffer[trace_pos];
+              trace_desc2->len++;
+              trace_pos++;
+            }
+          }
+#endif /* PPP_HDLC_TRACE */
+          store_state = FRX_ADD_HDLC_BEGIN;
+        }
+        /*
+         * begin of frame detected
+         */
+        if(store_state EQ FRX_ADD_HDLC_BEGIN)
+        {
+          /*
+           * initialize new packet
+           */
+          ppp_data->frx.stored_len   = 0;
+          d_offset                   = 0;
+          ppp_data->frx.stored_ptype = 0x0000;
+          fcs                        = PPP_INITFCS;
+          escape                     = FALSE;
+          store_state                = FRX_ADD_ADDRESS;
+        }
+        /*
+         * end of frame detected
+         * no error occured, frame complete
+         * if we are in INFORMATION state we have to keep in mind the FCS at MRU check
+         */
+        else if(((ppp_data->frx.stored_len + d_offset) >= 4) && 
+                (((ppp_data->frx.stored_len + d_offset) <= ppp_data->mru) ||
+                 (((ppp_data->frx.stored_len + d_offset) <= 
+                   (ppp_data->mru + 2)) && 
+                  (store_state EQ FRX_ADD_INFORMATION))) &&
+                (fcs EQ PPP_GOODFCS))
+        {
+          /* 
+           * determine the length of the packet
+           */
+          packet_len                  = 0;
+          ppp_data->frx.stored_len   += d_offset;
+          ppp_data->frx.cur_desc->len = d_offset;
+          switch(store_state)
+          {
+            case FRX_ADD_INFORMATION:
+              packet_len = ppp_data->frx.stored_len - 2;
+              break;
+
+            case FRX_ADD_FCS1:
+              packet_len = ppp_data->frx.stored_len - 1;
+              break;
+
+            case FRX_ADD_FCS2:
+              packet_len = ppp_data->frx.stored_len;
+              break;
+          } /*lint !e744 switch statement has no default */
+          if(packet_len < ppp_data->frx.stored_len)
+          {
+            /*
+             * remove FCS
+             */
+            ppp_data->frx.stored_len = packet_len;
+            temp_desc                = ppp_data->frx.stored_packet;
+            while(packet_len > temp_desc->len)
+            {
+              packet_len-= temp_desc->len;
+              temp_desc  = (T_desc2*)temp_desc->next;
+            }
+            temp_desc->len = packet_len;
+            /*
+             * free the rest of packet
+             */
+            arb_discard_packet((T_desc2*)temp_desc->next);
+            temp_desc->next = (ULONG)NULL;
+          }
+#ifdef PPP_HDLC_TRACE
+          /*
+           * remove stored HDLC frame because of correct reception
+           * the storage of the next PPP frame is done
+           * in the next call of frx_add_desc()
+           */
+          MFREE_DESC2(ppp_data->frx.hdlc_frame);
+          ppp_data->frx.hdlc_frame = NULL;
+#endif /* PPP_HDLC_TRACE */
+          /*
+           * esape loop
+           */
+          ppp_data->frx.frame_complete = TRUE;
+          store_state                  = FRX_ADD_HDLC_BEGIN;
+          break;
+        }
+        /*
+         * end of frame detected
+         * error occured, discard frame
+         */
+        else
+        {
+          /*
+           * error traces
+           */
+          if(((ppp_data->frx.stored_len + d_offset) >= 4) &&
+             (fcs NEQ PPP_GOODFCS))
+          {
+            TRACE_EVENT("ERROR HDLC PACKET PPP FCS FAULT");
+          }
+          else if((ppp_data->frx.stored_len + d_offset) > ppp_data->mru)
+          {
+            TRACE_EVENT_P3("ERROR PPP PACKET TO LONG stored_len=%d  d_offset=%d  mru=%d",
+                           ppp_data->frx.stored_len,
+                           d_offset,
+                           ppp_data->mru);
+          }
+#ifdef PPP_HDLC_TRACE
+          if((ppp_data->frx.stored_len + d_offset) > 0)
+          {
+            /*
+             * trace HDLC frame and store next frame
+             */
+            TRACE_EVENT("wrong HDLC frame:");
+            i           = 0;
+            trace_pos   = 0;
+            trace_desc2 = ppp_data->frx.hdlc_frame;
+            while(trace_desc2)
+            {
+              i+= sprintf(&buf[i], 
+                          "0x%02x, ", 
+                          trace_desc2->buffer[trace_pos]);
+              trace_pos++;
+              if(trace_desc2->len <= trace_pos)
+              {
+                trace_desc2 = (T_desc2*)trace_desc2->next;
+                trace_pos   = 0;
+              }
+              if(i > 80)
+              {
+                TRACE_EVENT( buf );
+                i = 0;
+              }
+            }
+            if(i > 0)
+            {
+              TRACE_EVENT( buf );
+              i = 0;
+            }
+          }
+          /*
+           * release stored HDLC frame
+           */
+          MFREE_DESC2(ppp_data->frx.hdlc_frame);
+          ppp_data->frx.hdlc_frame = NULL;
+          /*
+           * store next HDLC frame
+           */
+          /*
+           * set source pointer
+           */
+          trace_desc = source_desc;
+          trace_pos  = s_offset;
+          /*
+           * allocate first descriptor to store new HDLC frame
+           */
+          MALLOC(trace_desc2, (USHORT)(sizeof(T_desc2) - 1 + 
+                                FRX_ADD_SMALL_PACKET_SIZE));
+          trace_desc2->len         = 0;
+          trace_desc2->next        = (ULONG)NULL;
+          ppp_data->frx.hdlc_frame = trace_desc2;
+
+          /*
+           * store first HDLC flag
+           */
+          TRACE_EVENT_P2("start flag found in desc=0x%08x pos=%d", 
+                         trace_desc, 
+                         trace_pos);
+          trace_desc2->buffer[trace_desc2->len] = 
+            trace_desc->buffer[trace_pos];
+          trace_desc2->len++;
+          trace_pos++;
+          while((trace_desc) && (trace_pos >= trace_desc->len))
+          {
+            trace_desc = (T_desc2*)trace_desc->next;
+            trace_pos  = 0;
+          }
+          if(trace_desc)
+          {
+            /*
+             * store HDLC frame
+             */
+            while((trace_desc) &&
+                  (trace_desc->buffer[trace_pos] NEQ PPP_HDLC_FLAG))
+            {
+              if(trace_desc2->len >= FRX_ADD_SMALL_PACKET_SIZE)
+              {
+                MALLOC(trace_desc3, (USHORT)(sizeof(T_desc2) - 1 + 
+                                      FRX_ADD_SMALL_PACKET_SIZE));
+                trace_desc3->len  = 0;
+                trace_desc3->next = (ULONG)NULL;
+                trace_desc2->next = (ULONG)trace_desc3;
+                trace_desc2       = trace_desc3;
+              }
+              trace_desc2->buffer[trace_desc2->len] = 
+                trace_desc->buffer[trace_pos];
+              trace_desc2->len++;
+              trace_pos++;
+              while((trace_desc) && (trace_pos >= trace_desc->len))
+              {
+                trace_desc = (T_desc2*)trace_desc->next;
+                trace_pos  = 0;
+              }
+            }
+            /*
+             * store last HDLC flag
+             */
+            if(trace_desc)
+            {
+              if(trace_desc2->len >= FRX_ADD_SMALL_PACKET_SIZE)
+              {
+                MALLOC(trace_desc3, (USHORT)(sizeof(T_desc2) - 1 + 
+                                      FRX_ADD_SMALL_PACKET_SIZE));
+                trace_desc3->len  = 0;
+                trace_desc3->next = (ULONG)NULL;
+                trace_desc2->next = (ULONG)trace_desc3;
+                trace_desc2       = trace_desc3;
+              }
+              TRACE_EVENT_P2("stop flag found in desc=0x%08x pos=%d", 
+                             trace_desc, 
+                             trace_pos);
+              trace_desc2->buffer[trace_desc2->len] = 
+                trace_desc->buffer[trace_pos];
+              trace_desc2->len++;
+              trace_pos++;
+            }
+          }
+#endif /* PPP_HDLC_TRACE */
+          /*
+           * remove receiced packet because of an error
+           * decrease source offset beacause the HDLC end flag 
+           * can also be the HDLC start flag of the next frame
+           */
+          s_offset--;
+          arb_discard_packet(ppp_data->frx.stored_packet);
+          ppp_data->frx.stored_packet = NULL;
+          store_state                 = FRX_ADD_HDLC_BEGIN;
+        }
+      }
+      /*
+       * detect Control Escape octet 
+       */
+      else if((currentbyte EQ PPP_HDLC_ESCAPE) && (escape EQ FALSE))
+      {
+        escape = TRUE;
+      }
+      /*
+       * usual octet
+       */
+      else
+      {
+        /*
+         * bit 5 complement for the octet followed by Control Escape
+         */
+        if(escape EQ TRUE)
+        {
+          currentbyte^= 0x20;
+          escape      = FALSE;
+        }
+        /*
+         * calculate FCS 
+         */
+#ifdef _SIMULATION_
+        fcs = (fcs << 8) + currentbyte; /*lint !e734 Loss of precision */
+#else /* _SIMULATION_ */
+        fcs = (fcs >> 8) ^ fcstab[(fcs ^ currentbyte) & 0xff];
+#endif /* _SIMULATION_ */
+        /*
+         * store the packet and determine the protocol 
+         */
+        switch(store_state)
+        {
+          case FRX_ADD_INFORMATION:
+            if(d_offset >= d_size)
+            {
+              if((ppp_data->frx.stored_len + d_offset) < ppp_data->mru)
+              {
+                /*
+                 * allocate new descriptor
+                 */
+                switch(ppp_data->frx.stored_ptype)
+                {
+                  case DTI_PID_LCP:
+                  case DTI_PID_PAP:
+                  case DTI_PID_CHAP:
+                  case DTI_PID_IPCP:
+                    /*
+                     * allocate a big descriptor, copy the data into the new
+                     * one and free the small descriptor
+                     */
+                    MALLOC (ppp_data->frx.stored_packet, 
+                            (USHORT)(sizeof(T_desc2) - 1 + ppp_data->mru));
+                    memcpy(ppp_data->frx.stored_packet->buffer, 
+                           destination, 
+                           d_offset); /*lint !e668 Possibly passing a null pointer */
+                    MFREE(ppp_data->frx.cur_desc);
+                    ppp_data->frx.cur_desc       = ppp_data->frx.stored_packet;
+                    ppp_data->frx.cur_desc->next = (ULONG)NULL;
+                    destination = ppp_data->frx.cur_desc->buffer;
+                    d_size      = ppp_data->mru;
+                    break;
+
+                  default:
+                    /*
+                     * allocate a new small descriptor
+                     */
+                    MALLOC (temp_desc, (USHORT)(sizeof(T_desc2) - 1 + 
+                                        FRX_ADD_SMALL_PACKET_SIZE));
+                    ppp_data->frx.cur_desc->next = (ULONG)temp_desc;
+                    ppp_data->frx.cur_desc->len  = d_offset;
+                    ppp_data->frx.cur_desc       = temp_desc;
+                    ppp_data->frx.cur_desc->next = (ULONG)NULL;
+                    ppp_data->frx.stored_len    += d_offset;
+                    destination = ppp_data->frx.cur_desc->buffer;
+                    d_offset    = 0;
+                    d_size      = FRX_ADD_SMALL_PACKET_SIZE;
+                    break;
+                }
+              }
+              else if((ppp_data->frx.stored_len + d_offset) >= 
+                      (ppp_data->mru + 2))
+              {
+                /*
+                 * remove receiced packet because it is to long
+                 */
+                arb_discard_packet(ppp_data->frx.stored_packet);
+                ppp_data->frx.stored_packet = NULL;
+                store_state = FRX_ADD_ERROR;
+
+                TRACE_EVENT("ERROR PPP: HDLC packet to long");
+#ifdef PPP_HDLC_TRACE
+                /*
+                 * trace HDLC frame
+                 */
+                TRACE_EVENT("wrong HDLC frame:");
+                i           = 0;
+                trace_pos   = 0;
+                trace_desc2 = ppp_data->frx.hdlc_frame;
+                while(trace_desc2)
+                {
+                  i+= sprintf(&buf[i], 
+                              "0x%02x, ", 
+                              trace_desc2->buffer[trace_pos]);
+                  trace_pos++;
+                  if(trace_desc2->len <= trace_pos)
+                  {
+                    trace_desc2 = (T_desc2*)trace_desc2->next;
+                    trace_pos   = 0;
+                  }
+                  if(i > 80)
+                  {
+                    TRACE_EVENT( buf );
+                    i = 0;
+                  }
+                }
+                if(i > 0)
+                {
+                  TRACE_EVENT( buf );
+                  i = 0;
+                }
+                /*
+                 * release stored HDLC frame
+                 */
+                MFREE_DESC2(ppp_data->frx.hdlc_frame);
+                ppp_data->frx.hdlc_frame = NULL;
+#endif /* PPP_HDLC_TRACE */
+                break;
+              }
+              else if((ppp_data->frx.stored_len + d_offset) >= 
+                      (ppp_data->mru + 1))
+              {
+                d_offset--;
+                store_state = FRX_ADD_FCS2;
+                break;
+              }
+              else
+              {
+                store_state = FRX_ADD_FCS1;
+                break;
+              }
+            }
+            /*
+             * copy data
+             */
+            destination[d_offset] = currentbyte; /*lint !e613 Possible use of null pointer */
+            /*
+             * increase destination offset
+             */
+            d_offset++;
+            break;
+
+          case FRX_ADD_CONTROL:
+            if(currentbyte EQ 0x03)
+              store_state = FRX_ADD_PROTOCOL1;
+            else
+            {
+              TRACE_EVENT("ERROR PPP: wrong HDLC control field");
+#ifdef PPP_HDLC_TRACE
+              /*
+               * trace HDLC frame
+               */
+              TRACE_EVENT("wrong HDLC frame:");
+              i           = 0;
+              trace_pos   = 0;
+              trace_desc2 = ppp_data->frx.hdlc_frame;
+              while(trace_desc2)
+              {
+                i+= sprintf(&buf[i], "0x%02x, ", trace_desc2->buffer[trace_pos]);
+                trace_pos++;
+                if(trace_desc2->len <= trace_pos)
+                {
+                  trace_desc2 = (T_desc2*)trace_desc2->next;
+                  trace_pos   = 0;
+                }
+                if(i > 80)
+                {
+                  TRACE_EVENT( buf );
+                  i = 0;
+                }
+              }
+              if(i > 0)
+              {
+                TRACE_EVENT( buf );
+                i = 0;
+              }
+              /*
+               * release stored HDLC frame
+               */
+              MFREE_DESC2(ppp_data->frx.hdlc_frame);
+              ppp_data->frx.hdlc_frame = NULL;
+#endif /* PPP_HDLC_TRACE */
+              store_state = FRX_ADD_ERROR;
+            }
+            break;
+
+          case FRX_ADD_ADDRESS:
+            if(currentbyte EQ 0xff)
+            {
+              store_state = FRX_ADD_CONTROL;
+              break;
+            }
+            /*
+             * address and control field compression detected
+             */
+            /* fall through */
+          case FRX_ADD_PROTOCOL1:
+            if((currentbyte & 0x01) EQ 0)
+            {
+              ppp_data->frx.stored_ptype = currentbyte;
+              ppp_data->frx.stored_ptype = (ppp_data->frx.stored_ptype << 8); /*lint !e734 Loss of precision */
+              store_state = FRX_ADD_PROTOCOL2;
+              break;
+            }
+            /*
+             * protocol field compression detected
+             */
+            /* fall through */
+          case FRX_ADD_PROTOCOL2:
+            if(currentbyte & 0x01)
+            {
+              /*
+               * store protocol
+               */
+              ppp_data->frx.stored_ptype|= currentbyte;
+              /*
+               * allocate new packet
+               */
+              d_size = FRX_ADD_SMALL_PACKET_SIZE;
+              /*
+               * Allocate the necessary size for the data descriptor. 
+               * The size is calculated as follows:
+               * - take the size of a descriptor structure
+               * - subtract one because of the array buffer[1] to get
+               *   the size of descriptor control information
+               * - add number of octets of descriptor data
+               */
+              MALLOC (ppp_data->frx.stored_packet, 
+                      (USHORT)(sizeof(T_desc2) - 1 + d_size));
+              ppp_data->frx.cur_desc       = ppp_data->frx.stored_packet;
+              ppp_data->frx.cur_desc->next = (ULONG)NULL;
+              destination = ppp_data->frx.cur_desc->buffer;
+              d_offset    = 0;
+              store_state = FRX_ADD_INFORMATION;
+            }
+            else
+            {
+              TRACE_EVENT("ERROR PPP: wrong HDLC protocol field");
+#ifdef PPP_HDLC_TRACE
+              /*
+               * trace HDLC frame
+               */
+              TRACE_EVENT("wrong HDLC frame:");
+              i           = 0;
+              trace_pos   = 0;
+              trace_desc2 = ppp_data->frx.hdlc_frame;
+              while(trace_desc2)
+              {
+                i+= sprintf(&buf[i], "0x%02x, ", trace_desc2->buffer[trace_pos]);
+                trace_pos++;
+                if(trace_desc2->len <= trace_pos)
+                {
+                  trace_desc2 = (T_desc2*)trace_desc2->next;
+                  trace_pos   = 0;
+                }
+                if(i > 80)
+                {
+                  TRACE_EVENT( buf );
+                  i = 0;
+                }
+              }
+              if(i > 0)
+              {
+                TRACE_EVENT( buf );
+                i = 0;
+              }
+              /*
+               * release stored HDLC frame
+               */
+              MFREE_DESC2(ppp_data->frx.hdlc_frame);
+              ppp_data->frx.hdlc_frame = NULL;
+#endif /* PPP_HDLC_TRACE */
+              store_state = FRX_ADD_ERROR;
+            }
+            break;
+
+          case FRX_ADD_FCS1:
+            store_state = FRX_ADD_FCS2;
+            break;
+
+          case FRX_ADD_FCS2:
+            /*
+             * remove receiced packet because its to long
+             */
+            arb_discard_packet(ppp_data->frx.stored_packet);
+            ppp_data->frx.stored_packet = NULL;
+            store_state = FRX_ADD_ERROR;
+            
+            TRACE_EVENT("ERROR PPP: HDLC packet to long");
+#ifdef PPP_HDLC_TRACE
+            /*
+             * trace HDLC frame
+             */
+            TRACE_EVENT("wrong HDLC frame:");
+            i           = 0;
+            trace_pos   = 0;
+            trace_desc2 = ppp_data->frx.hdlc_frame;
+            while(trace_desc2)
+            {
+              i+= sprintf(&buf[i], "0x%02x, ", trace_desc2->buffer[trace_pos]);
+              trace_pos++;
+              if(trace_desc2->len <= trace_pos)
+              {
+                trace_desc2 = (T_desc2*)trace_desc2->next;
+                trace_pos   = 0;
+              }
+              if(i > 80)
+              {
+                TRACE_EVENT( buf );
+                i = 0;
+              }
+            }
+            if(i > 0)
+            {
+              TRACE_EVENT( buf );
+              i = 0;
+            }
+            /*
+             * release stored HDLC frame
+             */
+            MFREE_DESC2(ppp_data->frx.hdlc_frame);
+            ppp_data->frx.hdlc_frame = NULL;
+#endif /* PPP_HDLC_TRACE */
+            break;
+
+          case FRX_ADD_ERROR:
+            /*
+             * we wait for the next HDLC flag
+             */
+            break;
+
+          case FRX_ADD_HDLC_BEGIN:
+            TRACE_ERROR("ERROR: frx_add_desc(): in FRX_ADD_HDLC_BEGIN state without HDLC flag");
+            break;
+
+          default:
+            TRACE_ERROR("ERROR: frx_add_desc(): wrong state");
+            break;
+        }
+      }
+    }
+    /*
+     * check if current descriptor is complete analyzed
+     */
+    if(s_offset >= s_size)
+    {
+      temp_desc = (T_desc2*)source_desc->next;
+      MFREE(source_desc);
+      source_desc = temp_desc;
+      s_offset    = 0;
+    }
+  }
+  /*
+   * store important values in global variables
+   */
+  switch(store_state)
+  {
+    case FRX_ADD_INFORMATION:
+    case FRX_ADD_FCS1:
+    case FRX_ADD_FCS2:
+      ppp_data->frx.cur_desc->len = d_offset;
+      break;
+  } /*lint !e744 switch statement has no default */
+  ppp_data->frx.store_state   = store_state;
+  ppp_data->frx.calc_fcs      = fcs;
+  ppp_data->frx.escape        = escape;
+  ppp_data->frx.received_data = source_desc;
+  ppp_data->frx.cur_desc_size = d_size;
+  ppp_data->frx.proceed_data  = s_offset;
+} /*lint !e550 fcstab not accessed in _SIMULATION_ frx_add_desc() */
+#endif /* PPP_FLASH_ROM */
+
+
+
+#ifndef PPP_INT_RAM
+/*
++------------------------------------------------------------------------------
+| Function    : frx_detect_frame
++------------------------------------------------------------------------------
+| Description : The function frx_detect_frame() detects begin and end of 
+|               PPP frames.
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void frx_detect_frame ()
+{
+  UBYTE*   source;
+  UBYTE*   destination;
+  T_desc2* temp_desc1;
+  T_desc2* temp_desc2;
+  
+  TRACE_FUNCTION( "frx_detect_frame" );
+
+  /*
+   * copy received data stream pointer
+   */
+  temp_desc1 = ppp_data->frx.received_data;
+  /*
+   * set destination pointer if necessary
+   */
+  if(ppp_data->frx.store_state EQ FRX_ADD_INFORMATION)
+  {
+    /*
+     * to avoid erroneuos code generation of target compiler,
+     * it is written in two lines instead of one
+     */
+    destination = ppp_data->frx.cur_desc->buffer;
+    destination+= ppp_data->frx.cur_desc->len;
+  }
+
+  /*
+   * while there is still data to analyze and 
+   * a complete frame is not yet received
+   */
+  while((temp_desc1) && (ppp_data->frx.frame_complete EQ FALSE))
+  {
+    /*
+     * set source pointer
+     */
+    source = &temp_desc1->buffer[ppp_data->frx.proceed_data];
+    /*
+     * We count down the length of the current descriptor.
+     * while the current descriptor is not yet complete analyzed and 
+     * a complete frame is not yet received
+     */
+    while((temp_desc1->len) && (ppp_data->frx.frame_complete EQ FALSE))
+    {
+      switch(ppp_data->frx.store_state)
+      {
+        case FRX_ADD_ERROR:
+          /*
+           * search for next HDLC flag
+           */
+          while((temp_desc1->len) &&
+                (*source NEQ PPP_HDLC_FLAG))
+          {
+            /*
+             * increase source pointer
+             */
+            source++;
+            temp_desc1->len--;
+            ppp_data->frx.proceed_data++;
+          }
+          if(temp_desc1->len EQ 0) /*lint !e661 Possible access of out-of-bounds pointer */
+            /*
+             * end of descriptor reached
+             * analyze next descriptor
+             */
+            break;
+          ppp_data->frx.store_state = FRX_ADD_HDLC_BEGIN;
+          /* fall through */
+        case FRX_ADD_HDLC_BEGIN:
+          /*
+           * create new packet (frame) to store detected frame
+           */
+          ppp_data->frx.stored_len    = 0;
+          ppp_data->frx.stored_ptype  = DTI_PID_UOS;
+          ppp_data->frx.cur_desc_size = FRX_ADD_SMALL_PACKET_SIZE;
+          /*
+           * Allocate the necessary size for the data descriptor. The size is 
+           * calculated as follows:
+           * - take the size of a descriptor structure
+           * - subtract one because of the array buffer[1] to get the size of
+           *   descriptor control information
+           * - add number of octets of descriptor data
+           */
+          MALLOC (ppp_data->frx.stored_packet,
+                  (USHORT)(sizeof(T_desc2) - 1 + FRX_ADD_SMALL_PACKET_SIZE));
+          ppp_data->frx.cur_desc       = ppp_data->frx.stored_packet;
+          ppp_data->frx.cur_desc->len  = 0;
+          ppp_data->frx.cur_desc->next = (ULONG)NULL;
+          destination = ppp_data->frx.cur_desc->buffer;
+
+          *destination = *source; /*lint !e613 Possible use of null pointer */
+          /*
+           * increase source pointer
+           */
+          source++; /*lint !e613 Possible use of null pointer */
+          temp_desc1->len--;
+          ppp_data->frx.proceed_data++;
+          /*
+           * increase destination pointer
+           */
+          ppp_data->frx.stored_len++;
+          destination++;
+          ppp_data->frx.cur_desc->len++;
+
+          ppp_data->frx.store_state = FRX_ADD_INFORMATION;
+          break;
+
+        case FRX_ADD_INFORMATION:
+          /*
+           * copy data
+           */
+          while((temp_desc1->len) &&
+                (ppp_data->frx.stored_len < ppp_data->mru) &&
+                (ppp_data->frx.cur_desc->len < ppp_data->frx.cur_desc_size) &&
+                (*source NEQ PPP_HDLC_FLAG))
+          {
+            /*
+             * copy data
+             */
+            *destination = *source; /*lint !e644 destination may not have been initialized */
+            /*
+             * increase source pointer
+             */
+            source++;
+            temp_desc1->len--;
+            ppp_data->frx.proceed_data++;
+            /*
+             * increase destination pointer
+             */
+            ppp_data->frx.stored_len++;
+            destination++;
+            ppp_data->frx.cur_desc->len++;
+          }
+          /*
+           * analyze why the loop is left
+           */
+          if(ppp_data->frx.stored_len < ppp_data->mru) /*lint !e661 Possible access of out-of-bounds pointer */
+          {
+            if(ppp_data->frx.cur_desc->len >= ppp_data->frx.cur_desc_size)
+            {
+              /*
+               * allocate a new small descriptor
+               */
+              MALLOC (temp_desc2, (USHORT)(sizeof(T_desc2) - 1 + 
+                                  FRX_ADD_SMALL_PACKET_SIZE));
+              ppp_data->frx.cur_desc->next = (ULONG)temp_desc2;
+              ppp_data->frx.cur_desc       = 
+                (T_desc2*)ppp_data->frx.cur_desc->next;
+              ppp_data->frx.cur_desc->len  = 0;
+              ppp_data->frx.cur_desc->size = 0;
+              ppp_data->frx.cur_desc->offset = 0;
+              ppp_data->frx.cur_desc->next = (ULONG)NULL;
+              ppp_data->frx.cur_desc_size  = FRX_ADD_SMALL_PACKET_SIZE;
+              destination = ppp_data->frx.cur_desc->buffer;
+            }
+            if((temp_desc1->len) &&
+               (*source EQ PPP_HDLC_FLAG)) /*lint !e613 Possible use of null pointer */
+            {
+              /*
+               * end of frame detected
+               */
+              ppp_data->frx.store_state = FRX_ADD_HDLC_BEGIN;
+              /*
+               * copy HDLC flag
+               */
+              *destination = *source; /*lint !e613 Possible use of null pointer */
+              /*
+               * increase length values
+               */
+              ppp_data->frx.stored_len++;
+              ppp_data->frx.cur_desc->len++;
+              /*
+               * check for correct length
+               */
+              if(ppp_data->frx.stored_len > 2)
+              {
+                /*
+                 * no error occured, frame complete
+                 */
+                ppp_data->frx.frame_complete = TRUE;
+              }
+              else
+              {
+                /*
+                 * remove receiced packet because its to short
+                 */
+                arb_discard_packet(ppp_data->frx.stored_packet);
+                ppp_data->frx.stored_packet = NULL;
+              }
+            }
+          }
+          else
+          {
+            /*
+             * remove receiced packet because its to long
+             */
+            arb_discard_packet(ppp_data->frx.stored_packet);
+            ppp_data->frx.stored_packet  = NULL;
+            ppp_data->frx.store_state    = FRX_ADD_ERROR;
+          }
+          break;
+      } /*lint !e744 switch statement has no default */
+    }
+    if(temp_desc1->len EQ 0)
+    {
+      temp_desc2 = (T_desc2*)temp_desc1->next;
+      MFREE(temp_desc1);
+      temp_desc1                 = temp_desc2;
+      ppp_data->frx.proceed_data = 0;
+    }
+  }
+  /*
+   * store received data stream pointer
+   */
+  ppp_data->frx.received_data = temp_desc1;
+} /* frx_detect_frame() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : frx_send_pack_ready_mode()
++------------------------------------------------------------------------------
+| Description : send as many packets to ptx as can be extracted from received frame.
+|               Frx is in ready mode.
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+
+GLOBAL void frx_send_pack_ready_mode ()
+{
+  T_desc2* temp_desc;
+
+  TRACE_FUNCTION( "frx_send_pack_ready_mode ()" );
+
+  while( ppp_data->frx.frame_complete   EQ TRUE            AND
+         ppp_data->frx.data_flow_state  EQ FRX_DATA_FLOW_READY)
+  {
+    /*
+     * to avoid any side effects
+     * first reset all necessary variables and then call the signal 
+     */
+    ppp_data->frx.frame_complete = FALSE;
+    temp_desc                    = ppp_data->frx.stored_packet;
+    ppp_data->frx.stored_packet  = NULL;
+    sig_frx_ptx_packet_ind(ppp_data->frx.stored_ptype, 
+                           ppp_data->frx.stored_len,
+                           temp_desc);
+    frx_add_desc();
+  }
+}
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : frx_send_pack_transp_mode
++------------------------------------------------------------------------------
+| Description : send as many packets to ptx as can be extracted from received frame.
+|               Frx is in transparent mode .
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+
+GLOBAL void frx_send_pack_transp_mode ()
+{
+  T_desc2* temp_desc;
+
+  TRACE_FUNCTION( "frx_send_pack_transp_mode ()" );
+
+  while( ppp_data->frx.frame_complete  EQ TRUE            AND
+         ppp_data->frx.data_flow_state EQ FRX_DATA_FLOW_READY)
+  {
+    /*
+     * to avoid any side effects
+     * first reset all necessary variables and then call the signal 
+     */
+    ppp_data->frx.frame_complete = FALSE;
+    temp_desc                    = ppp_data->frx.stored_packet;
+    ppp_data->frx.stored_packet  = NULL;
+    sig_frx_ptx_packet_ind(ppp_data->frx.stored_ptype, 
+                           ppp_data->frx.stored_len,
+                           temp_desc);
+    frx_detect_frame();
+  }
+
+}
+
+#endif  /* PPP_INT_RAM */
+