view src/g23m-fad/ppp/ppp_frxf.c @ 682:17b7b92e7dba

uartfax.c: fix for old Openmoko bug with Auto-CTS Openmoko made the change of enabling hardware assisted CTS flow control in the UART when RTS/CTS flow control is used - it is a change which we have retained in FreeCalypso - but they forgot to turn this hw mode off if RTS/CTS flow control is deselected at the application level. We (FreeCalypso) are now fixing the latter defect ourselves.
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 26 Jun 2020 02:53:02 +0000
parents 90eb61ecd093
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  
|  Modul   :  
+----------------------------------------------------------------------------- 
|  Copyright 2002 Texas Instruments Berlin, AG 
|                 All rights reserved. 
| 
|                 This file is confidential and a trade secret of Texas 
|                 Instruments Berlin, AG 
|                 The receipt of or possession of this file does not convey 
|                 any rights to reproduce or disclose its contents or to 
|                 manufacture, use, or sell anything it may describe, in 
|                 whole, or in part, without the specific written consent of 
|                 Texas Instruments Berlin, AG. 
+----------------------------------------------------------------------------- 
|  Purpose :  This modul 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 */