diff gsm-fw/g23m-aci/uart/uart_txf.c @ 775:eedbf248bac0

gsm-fw/g23m-aci subtree: initial import from LoCosto source
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 12 Oct 2014 01:45:14 +0000
parents
children f54080301c98
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gsm-fw/g23m-aci/uart/uart_txf.c	Sun Oct 12 01:45:14 2014 +0000
@@ -0,0 +1,856 @@
+/*
++-----------------------------------------------------------------------------
+|  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 UART and implements all
+|             procedures and functions as described in the
+|             SDL-documentation (TX-statemachine)
++-----------------------------------------------------------------------------
+*/
+
+#ifndef UART_TXF_C
+#define UART_TXF_C
+#endif /* !UART_TXF_C */
+
+#define ENTITY_UART
+
+#ifndef FF_MULTI_PORT
+/*==== INCLUDES =============================================================*/
+
+#ifdef WIN32
+#include "nucleus.h"
+#endif /* WIN32 */
+#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"
+#include "gsm.h"        /* to get a lot of macros */
+#include "cnf_uart.h"   /* to get cnf-definitions */
+#include "mon_uart.h"   /* to get mon-definitions */
+#include "prim.h"       /* to get the definitions of used SAP and directions */
+#ifdef DTILIB
+#include "dti.h"        /* to get dti lib */
+#endif /* DTILIB */
+#include "pei.h"        /* to get PEI interface */
+#ifdef _TARGET_
+#include "uart/serialswitch.h"
+#include "uart/traceswitch.h"
+#else /* _TARGET_ */
+#include "serial_dat.h" /* to get definitions of serial driver */
+#endif /* _TARGET_ */
+#include "uart.h"       /* to get the global entity definitions */
+
+#ifdef _SIMULATION_
+#include <stdio.h>      /* to get sprintf */
+#endif /* _SIMULATION_ */
+#include <string.h>    /* JK, delete warnings: to get memcpy */
+
+/*==== CONST ================================================================*/
+
+/*==== LOCAL VARS ===========================================================*/
+
+/*==== PRIVATE FUNCTIONS ====================================================*/
+
+/*==== PUBLIC FUNCTIONS =====================================================*/
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : tx_proc_output
++------------------------------------------------------------------------------
+| Description : The function tx_proc_output() is the actual callback function
+|               to write data into the send buffer.
+|
+| Parameters  : uart_device - database for the affected UART device
+|
++------------------------------------------------------------------------------
+*/
+LOCAL void tx_proc_output(T_UART_DATA* uart_device)
+{
+  USHORT  i, len, pos;
+  T_DLC   *dlc;           /* used Data Link Connection */
+  UBYTE   transmit_state; /* state of transmission */
+  T_desc2* cur_desc;       /* currently used descriptor */
+  UBYTE   temp_field;     /* multi purpose value */
+  UBYTE   frame_size;     /* numbr of octets in Information field */
+  UBYTE   fcs;            /* Frame Check Sequence */
+  SHORT   error_code;     /* Error code returned from a function */
+
+  TRACE_FUNCTION( "tx_proc_output" );
+
+  if(uart_device->tx.dlc_instance EQ UART_EMPTY_INSTANCE)
+  {
+    /*
+     * Raw Data
+     */
+    /*
+     * use entry 0 for raw data
+     */
+    dlc      = &uart_device->dlc_table[UART_CONTROL_INSTANCE];
+    cur_desc = dlc->transmit_data;
+    /*
+     * search next descriptor that includes data
+     */
+    while((cur_desc) &&
+          (dlc->transmit_pos >= cur_desc->len))
+    {
+      cur_desc          = (T_desc2*)cur_desc->next;
+      dlc->transmit_pos = 0;
+    }
+    /*
+     * for each ring buffer segment
+     */
+    for (i=0; i < uart_device->tx.ndest; i++)
+    {
+      pos = 0;
+      /*
+       * while ring buffer segment is not yet full and
+       * there are still data to send
+       */
+      while((uart_device->tx.size[i] > 0) && (cur_desc))
+      {
+        /*
+         * determine length to copy
+         */
+        len = cur_desc->len - dlc->transmit_pos;
+        if(len > uart_device->tx.size[i])
+          len = uart_device->tx.size[i];
+        /*
+         * copy data
+         */
+        memcpy((char*) &uart_device->tx.dest[i][pos],
+               (char*) &cur_desc->buffer[dlc->transmit_pos],
+               len);
+        /*
+         * updata values
+         */
+        uart_device->tx.size[i]-= len;
+        dlc->transmit_pos      += len;
+        pos                    += len;
+        /*
+         * if current descriptor completly send
+         * then move to next descriptor
+         */
+        while((cur_desc) &&
+              (dlc->transmit_pos >= cur_desc->len))
+        {
+          cur_desc          = (T_desc2*)cur_desc->next;
+          dlc->transmit_pos = 0;
+        }
+      }
+    }
+  }
+  else
+  {
+    /*
+     * Multiplexer Data
+     */
+    dlc        = &uart_device->dlc_table[uart_device->tx.dlc_instance];
+    cur_desc   = dlc->transmit_data;
+    temp_field = 0;
+    /*
+     * search next descriptor that includes data
+     */
+    while((cur_desc) &&
+          (dlc->transmit_pos >= cur_desc->len))
+    {
+      cur_desc          = (T_desc2*)cur_desc->next;
+      dlc->transmit_pos = 0;
+    }
+    if(cur_desc)
+    {
+      /*
+       * initiailze destination values
+       */
+      i = 0;
+      while((i < uart_device->tx.ndest) && (uart_device->tx.size[i] EQ 0))
+      {
+        i++;
+      }
+      pos = 0;
+      /*
+       * send start HDLC Flag
+       */
+      uart_device->tx.dest[i][pos] = UART_HDLC_FLAG;
+      fcs                          = UART_INITFCS;
+      transmit_state               = UART_TX_ADDRESS;
+      frame_size                   = 0;
+      /*
+       * increase destination position
+       */
+      pos++;
+      uart_device->tx.size[i]--;
+      while((i < uart_device->tx.ndest) &&
+            (uart_device->tx.size[i] EQ 0))
+      {
+        pos = 0;
+        i++;
+      }
+      while(transmit_state NEQ UART_TX_END)
+      {
+        switch(transmit_state)
+        {
+          case UART_TX_ADDRESS:
+            /*
+             * send Address field
+             */
+            if(uart_device->tx.dlc_instance EQ UART_CONTROL_INSTANCE)
+            {
+              /*
+               * at Control Channel the address field
+               * is included in source data
+               */
+              temp_field = cur_desc->buffer[dlc->transmit_pos];
+              /*
+               * if current descriptor completly send
+               * then move to next descriptor
+               */
+              dlc->transmit_pos++;
+              while((cur_desc) &&
+                    (dlc->transmit_pos >= cur_desc->len))
+              {
+                cur_desc          = (T_desc2*)cur_desc->next;
+                dlc->transmit_pos = 0;
+              }
+            }
+            else
+            {
+              /*
+               * at Data Channel the address field
+               * is calculated with the DLCI
+               */
+              temp_field = (dlc->dlci << UART_DLCI_POS) | UART_EA;
+            }
+            /*
+             * calculate FCS
+             */
+            fcs = uart_device->fcstab[fcs ^ temp_field];
+            /*
+             * next field is Control field
+             */
+            transmit_state = UART_TX_CONTROL;
+            break;
+
+          case UART_TX_CONTROL:
+            /*
+             * send Control field
+             */
+            if(uart_device->tx.dlc_instance EQ UART_CONTROL_INSTANCE)
+            {
+              /*
+               * at Control Channel the control field
+               * is included in source data
+               */
+              temp_field = cur_desc->buffer[dlc->transmit_pos];
+              /*
+               * if current descriptor completly send
+               * then move to next descriptor
+               */
+              dlc->transmit_pos++;
+              while((cur_desc) &&
+                    (dlc->transmit_pos >= cur_desc->len))
+              {
+                cur_desc          = (T_desc2*)cur_desc->next;
+                dlc->transmit_pos = 0;
+              }
+            }
+            else
+            {
+              /*
+               * at Data Channel the control field
+               * is always an UIH frame with P/F bit set to 0
+               */
+              temp_field = UART_UIH_DATA_FRAME;
+            }
+            /*
+             * calculate FCS
+             */
+            fcs = uart_device->fcstab[fcs ^ temp_field];
+            /*
+             * if there are still data to send the
+             * next field is Information field
+             * otherwise next field is FCS field
+             */
+            if(cur_desc)
+              transmit_state = UART_TX_INFORMATION;
+            else
+              transmit_state = UART_TX_FCS;
+            break;
+
+          case UART_TX_INFORMATION:
+            /*
+             * send Information field
+             */
+            temp_field = cur_desc->buffer[dlc->transmit_pos];
+            /*
+             * check if there is still data in the current descriptor and
+             * the maximum frame size is not yet reached
+             */
+            dlc->transmit_pos++;
+            frame_size++;
+            if((frame_size >= uart_device->n1) ||
+               (dlc->transmit_pos >= cur_desc->len))
+            {
+              /*
+               * if current descriptor completly send
+               * then move to next descriptor
+               */
+              while((cur_desc) &&
+                    (dlc->transmit_pos >= cur_desc->len))
+              {
+                cur_desc          = (T_desc2*)cur_desc->next;
+                dlc->transmit_pos = 0;
+              }
+              /*
+               * if no more data to send available or
+               * maximum frame size is reached then
+               * the next field is FCS field
+               */
+              if((frame_size >= uart_device->n1) ||
+                 (cur_desc EQ NULL))
+                transmit_state = UART_TX_FCS;
+            }
+            break;
+
+          case UART_TX_FCS:
+            /*
+             * send FCS field
+             */
+#ifdef _SIMULATION_
+            /*
+             * clear FCS field in simulation mode
+             */
+            temp_field = UART_GOODFCS;
+#else /* _SIMULATION_ */
+            temp_field = (0xff - fcs);
+#endif /* _SIMULATION_ */
+            /*
+             * frame complete
+             */
+            transmit_state = UART_TX_END;
+            break;
+          default:
+            TRACE_EVENT_P1("Warning: Unexpected TX ISR state %d", transmit_state);
+            break;
+        }
+        if((temp_field EQ UART_HDLC_FLAG)   ||
+           (temp_field EQ UART_HDLC_ESCAPE) ||
+           (temp_field EQ uart_device->xon) ||
+           (temp_field EQ uart_device->xoff))
+        {
+          /*
+           * send Control Escape and map character
+           */
+          /*lint -e661 (Warning -- access of out-of-bounds pointer) */
+          uart_device->tx.dest[i][pos] = UART_HDLC_ESCAPE;
+          /*lint +e661 (Warning -- access of out-of-bounds pointer) */
+          temp_field                  ^= 0x20;
+          /*
+           * increase destination position
+           */
+          pos++;
+          uart_device->tx.size[i]--;
+          while((i < uart_device->tx.ndest) &&
+                (uart_device->tx.size[i] EQ 0))
+          {
+            pos = 0;
+            i++;
+          }
+        }
+        /*
+         * send character
+         */
+        /*lint -e661 -e662 (Warning -- access/creation of out-of-bounds pointer) */
+        uart_device->tx.dest[i][pos] = temp_field;
+        /*lint +e661 +e662 (Warning -- access/creation of out-of-bounds pointer) */
+        /*
+         * increase destination position
+         */
+        pos++;
+        uart_device->tx.size[i]--;
+        while((i < uart_device->tx.ndest) &&
+              (uart_device->tx.size[i] EQ 0))
+        {
+          pos = 0;
+          i++;
+        }
+      }
+      /*
+       * send stop HDLC Flag
+       */
+      /*lint -e661 -e662 (Warning -- access/creation of out-of-bounds pointer) */
+      uart_device->tx.dest[i][pos] = UART_HDLC_FLAG;
+      /*lint +e661 +e662 (Warning -- access/creation of out-of-bounds pointer) */
+      /*
+       * update size value
+       */
+      uart_device->tx.size[i]--;
+    }
+  }
+  /*
+   * write current descriptor back to table
+   */
+  dlc->transmit_data = cur_desc;
+
+#ifndef _SIMULATION_
+  PSIGNAL(hCommUART, UART_DRIVER_SENT_IND, uart_device);
+#endif /* !_SIMULATION_ */
+  *uart_device->tx.reInstall = rm_noInstall;
+
+  /*
+   * update pointer in UART driver
+   */
+  if((error_code = UF_OutpAvail (uart_device->device)) < 0)
+  {
+    TRACE_ERROR_P2("UF Driver: data pointer update failed, [%d], uart_txf.c(%d)",
+                                               error_code, __LINE__);
+  }
+
+} /* tx_proc_output() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : tx_init
++------------------------------------------------------------------------------
+| Description : The function tx_init() initializes the TX service.
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void tx_init ()
+{
+#ifndef _SIMULATION_
+#ifdef WIN32
+#ifndef _TARGET_
+  char    buf[80];
+#endif /* !_TARGET_ */
+  STATUS  sts;
+#endif /* WIN32 */
+#endif /* !_SIMULATION_ */
+
+  TRACE_FUNCTION( "tx_init" );
+
+#ifndef _SIMULATION_
+#ifdef WIN32
+  sts = NU_Create_HISR (&uart_data->tx.tx_HISR,
+                        "TX_HISR",
+                        tx_proc_output,
+                        2,
+                        uart_data->HISR_stack,
+                        HISR_STACK_SIZE);
+#ifndef _TARGET_
+  sprintf (buf, "NU_Create_HISR(TX) = %d", sts);
+  TRACE_EVENT (buf);
+#endif /* !_TARGET_ */
+#endif /* WIN32 */
+#endif /* !_SIMULATION_ */
+
+  uart_data->tx.lines         = 0x80000000; /* invalid */
+  uart_data->tx.dlc_instance  = UART_EMPTY_INSTANCE;
+  uart_data->tx.p_zero        = 0;
+  uart_data->tx.send_state    = UART_TX_NOT_SENDING;
+
+  INIT_STATE( UART_SERVICE_TX , TX_DEAD );
+} /* tx_init() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : tx_flushUart
++------------------------------------------------------------------------------
+| Description : The function tx_flushUart() flush the output buffer of the
+|               UART driver.
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void tx_flushUart ()
+{
+#ifndef _TARGET_
+  USHORT  oa;             /* output available */
+#endif /* !_TARGET_ */
+#ifndef ALR
+  T_UFRET mt;
+#endif /* ALR */
+  USHORT  counter;
+
+  TRACE_FUNCTION( "tx_flushUart" );
+
+  counter = 0;
+  while(
+#ifndef ALR
+        ((mt = UF_CheckXEmpty(uart_data->device)) == UF_NOT_READY) ||
+#endif /* !ALR */
+        (UF_OutpAvail (uart_data->device) < UF_MAX_BUFFER_SIZE))
+  {
+#ifndef _TARGET_
+    oa = UF_OutpAvail (uart_data->device);
+    TRACE_EVENT_P1("waiting - output not flushed oa:%d",oa);
+#endif /* !_TARGET_ */
+    /*
+     * poll permanent in the first 500ms
+     * after that poll 1 minute only every second
+     * after that give up
+     */
+    if(counter < 50)
+    {
+      if(vsi_t_sleep (VSI_CALLER ONE_FRAME) NEQ VSI_OK)
+      {
+        TRACE_ERROR_P1("VSI entity: Can't suspend thread, uart_txf.c(%d)", 
+                                                                __LINE__);
+      }
+    }
+    else if(counter < 110)
+    {
+      if(vsi_t_sleep (VSI_CALLER 1000) NEQ VSI_OK)
+      {
+        TRACE_ERROR_P1("VSI entity: Can't suspend thread, uart_txf.c(%d)", 
+                                                                __LINE__);
+      }
+    }
+    else
+    {
+      break;
+    }
+    counter++;
+  }
+} /* tx_flushUart() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : tx_next_send_allowed
++------------------------------------------------------------------------------
+| Description : The function tx_next_send_allowed() determines which dlc is the
+|               next dlc allow to send. The result of the calculation is stored
+|               in dlc_instance.
+|
+| Parameters  : no parameters
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void tx_next_send_allowed ()
+{
+  UBYTE   diff;
+  UBYTE   inst;
+  UBYTE   next_inst;
+  T_DLC*  dlc;
+
+  TRACE_FUNCTION( "tx_next_send_allowed" );
+
+  diff = 255;
+  next_inst = UART_EMPTY_INSTANCE;
+  for(inst = 0; inst <= UART_MAX_NUMBER_OF_CHANNELS; inst++)
+  {
+    dlc = &uart_data->dlc_table[inst];
+    if(dlc->transmit_data)
+    {
+      if(dlc->p_counter EQ uart_data->tx.p_zero)
+      {
+        uart_data->tx.dlc_instance = inst;
+        return;
+      }
+      if(diff > (dlc->p_counter - uart_data->tx.p_zero))
+      {
+        diff = dlc->p_counter - uart_data->tx.p_zero;
+        next_inst = inst;
+      }
+    }
+  }
+  uart_data->tx.p_zero+= diff;
+  uart_data->tx.dlc_instance = next_inst;
+} /* tx_next_send_allowed() */
+
+
+
+/*
++------------------------------------------------------------------------------
+| Function    : tx_writeInFunc_0
++------------------------------------------------------------------------------
+| Description : The function tx_writeInFunc_0() is the official callback
+|               function to write data into the send buffer of UART device 0.
+|               It just copies the parameters and calls then the actual
+|               function.
+|
+| Parameters  : cldFromIrq - called from interrupt
+|               reInstall  - reinstallation mode
+|               ndest      - number of destination pointers
+|               dest       - array of destination pointers
+|               size       - array of sizes for every destinition pointer
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void tx_writeInFunc_0 (BOOL           cldFromIrq,
+                              T_reInstMode  *reInstall,
+                              UBYTE          ndest,
+                              UBYTE         *dest[],
+                              USHORT        *size)
+{
+#ifndef _SIMULATION_
+#ifndef _TARGET_
+  char buf[40];
+#endif /* !_TARGET_ */
+#endif /* !_SIMULATION_ */
+  T_UART_DATA* uart_device;
+
+  TRACE_FUNCTION( "tx_writeInFunc_0" );
+
+  /*
+   * select UART device 0
+   */
+  uart_device = &(uart_data_base[0]);
+
+  /*
+   * store parameters
+   */
+  uart_device->tx.cldFromIrq = cldFromIrq;
+  uart_device->tx.ndest      = ndest;
+  uart_device->tx.dest[0]    = dest[0];
+  uart_device->tx.dest[1]    = dest[1];
+  uart_device->tx.size       = size;
+  uart_device->tx.reInstall  = reInstall;
+
+#ifndef _SIMULATION_
+#ifdef WIN32
+  if (cldFromIrq)
+  {
+    STATUS sts;
+    /*
+     * interrupt context of the UART driver -> activate the HISR
+     */
+    sts = NU_Activate_HISR (&uart_device->tx.tx_HISR);
+#ifndef _TARGET_
+    sprintf (buf, "NU_Activate_HISR(TX) = %d", sts);
+    TRACE_EVENT (buf);
+#endif /* !_TARGET_ */
+  }
+  else
+#endif /* WIN32 */
+#endif /* !_SIMULATION_ */
+  {
+    /*
+     * normal callback from UF_WriteData
+     */
+    tx_proc_output(uart_device);
+
+#ifdef _SIMULATION_
+    {
+      /*
+       * trace output
+       */
+      UBYTE*  trace_dest[2];
+      USHORT  trace_size[2];
+      USHORT  i;
+      USHORT  pos;
+      char    buf[90];
+
+
+      trace_dest[0] = dest[0];
+      trace_dest[1] = dest[1];
+
+      trace_size[0] = size[0];
+      trace_size[1] = size[1];
+
+      trace_size[0]-= uart_device->tx.size[0];
+      trace_size[1]-= uart_device->tx.size[1];
+
+      if((trace_size[0]) ||
+         (trace_size[1]))
+      {
+
+        TRACE_EVENT("=== OUTRAW");
+        i   = 0;
+        pos = 0;
+        while(pos < trace_size[0])
+        {
+          i+= sprintf(&buf[i], "0x%02x, ", trace_dest[0][pos]);
+          pos++;
+          if(i > 80)
+          {
+            TRACE_EVENT( buf );
+            i = 0;
+          }
+          else if(pos >= trace_size[0])
+          {
+            TRACE_EVENT( buf );
+          }
+        }
+        i   = 0;
+        pos = 0;
+        while(pos < trace_size[1])
+        {
+          i+= sprintf(&buf[i], "0x%02x, ", trace_dest[1][pos]);
+          pos++;
+          if(i > 80)
+          {
+            TRACE_EVENT( buf );
+            i = 0;
+          }
+          else if(pos >= trace_size[1])
+          {
+            TRACE_EVENT( buf );
+          }
+        }
+      }
+    }
+#endif /* _SIMULATION_ */
+  }
+} /* tx_writeInFunc_0() */
+
+
+
+#ifdef FF_TWO_UART_PORTS
+/*
++------------------------------------------------------------------------------
+| Function    : tx_writeInFunc_1
++------------------------------------------------------------------------------
+| Description : The function tx_writeInFunc_1() is the official callback
+|               function to write data into the send buffer of UART device 0.
+|               It just copies the parameters and calls then the actual
+|               function.
+|
+| Parameters  : cldFromIrq - called from interrupt
+|               reInstall  - reinstallation mode
+|               ndest      - number of destination pointers
+|               dest       - array of destination pointers
+|               size       - array of sizes for every destinition pointer
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void tx_writeInFunc_1 (BOOL           cldFromIrq,
+                              T_reInstMode  *reInstall,
+                              UBYTE          ndest,
+                              UBYTE         *dest[],
+                              USHORT        *size)
+{
+#ifndef _SIMULATION_
+#ifndef _TARGET_
+  char buf[40];
+#endif /* !_TARGET_ */
+#endif /* !_SIMULATION_ */
+  T_UART_DATA* uart_device;
+
+  TRACE_FUNCTION( "tx_writeInFunc_1" );
+
+  /*
+   * select UART device 1
+   */
+  uart_device = &(uart_data_base[1]);
+
+  /*
+   * store parameters
+   */
+  uart_device->tx.cldFromIrq = cldFromIrq;
+  uart_device->tx.ndest      = ndest;
+  uart_device->tx.dest[0]    = dest[0];
+  uart_device->tx.dest[1]    = dest[1];
+  uart_device->tx.size       = size;
+  uart_device->tx.reInstall  = reInstall;
+
+#ifndef _SIMULATION_
+#ifdef WIN32
+  if (cldFromIrq)
+  {
+    STATUS sts;
+    /*
+     * interrupt context of the UART driver -> activate the HISR
+     */
+    sts = NU_Activate_HISR (&uart_device->tx.tx_HISR);
+#ifndef _TARGET_
+    sprintf (buf, "NU_Activate_HISR(TX) = %d", sts);
+    TRACE_EVENT (buf);
+#endif /* !_TARGET_ */
+  }
+  else
+#endif /* WIN32 */
+#endif /* !_SIMULATION_ */
+  {
+    /*
+     * normal callback from UF_WriteData
+     */
+    tx_proc_output(uart_device);
+
+#ifdef _SIMULATION_
+    {
+      /*
+       * trace output
+       */
+      UBYTE*  trace_dest[2];
+      USHORT  trace_size[2];
+      USHORT  i;
+      USHORT  pos;
+      char    buf[90];
+
+
+      trace_dest[0] = dest[0];
+      trace_dest[1] = dest[1];
+
+      trace_size[0] = size[0];
+      trace_size[1] = size[1];
+
+      trace_size[0]-= uart_device->tx.size[0];
+      trace_size[1]-= uart_device->tx.size[1];
+
+      if((trace_size[0]) ||
+         (trace_size[1]))
+      {
+
+        TRACE_EVENT("=== OUTRAW");
+        i   = 0;
+        pos = 0;
+        while(pos < trace_size[0])
+        {
+          i+= sprintf(&buf[i], "0x%02x, ", trace_dest[0][pos]);
+          pos++;
+          if(i > 80)
+          {
+            TRACE_EVENT( buf );
+            i = 0;
+          }
+          else if(pos >= trace_size[0])
+          {
+            TRACE_EVENT( buf );
+          }
+        }
+        i   = 0;
+        pos = 0;
+        while(pos < trace_size[1])
+        {
+          i+= sprintf(&buf[i], "0x%02x, ", trace_dest[1][pos]);
+          pos++;
+          if(i > 80)
+          {
+            TRACE_EVENT( buf );
+            i = 0;
+          }
+          else if(pos >= trace_size[1])
+          {
+            TRACE_EVENT( buf );
+          }
+        }
+      }
+    }
+#endif /* _SIMULATION_ */
+  }
+} /* tx_writeInFunc_1() */
+#endif /* FF_TWO_UART_PORTS */
+#endif /* !FF_MULTI_PORT */