view src/g23m-aci/uart/uart_kers.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 53929b40109c
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 UART and implements all
|             functions to handles the incoming process internal signals as
|             described in the SDL-documentation (KER-statemachine)
+-----------------------------------------------------------------------------
*/

#ifndef UART_KERS_C
#define UART_KERS_C
#endif /* !UART_KERS_C */

#define ENTITY_UART

/*
 * Turn off spurious LINT warnings
 */
 /*lint -e415 access of out-of-bounds pointer */

/*==== 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 */
#include "dti.h"        /* to get dti lib */
#include "pei.h"        /* to get PEI interface */
#ifdef FF_MULTI_PORT
#include "gsi.h"        /* to get definitions of serial driver */
#else /* FF_MULTI_PORT */
#ifdef _TARGET_
#include "uart/serialswitch.h"
#include "uart/traceswitch.h"
#else /* _TARGET_ */
#include "serial_dat.h" /* to get definitions of serial driver */
#endif /* _TARGET_ */
#endif /* FF_MULTI_PORT */
#include "uart.h"       /* to get the global entity definitions */

#ifdef FF_MULTI_PORT
#include "uart_ptxs.h"  /* to get signal definitions for service TX */
#include "uart_prxs.h"  /* to get rx signals */
#else /* FF_MULTI_PORT */
#include "uart_txs.h"   /* to get signal definitions of service TX */
#include "uart_rxs.h"   /* to get signal definitions of service RX */
#endif /* FF_MULTI_PORT */
#include "uart_dtxs.h"  /* to get signal definitions of service DTX */
#include "uart_drxs.h"  /* to get signal definitions of service DRX */
#include "uart_kerf.h"  /* to get function definitions of service KER */
#include "uart_rts.h"   /* to get signal definitions of service RT */

#ifndef _TARGET_
#include <stdio.h>      /* to get sprintf */
#endif /* !_TARGET_ */
#include <string.h>      /* JK, delete warnings: to get memcpy */

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

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

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

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



/*
+------------------------------------------------------------------------------
| Function    : sig_drx_ker_line_states_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_DRX_KER_LINE_STATES_IND
|
| Parameters  : dlc_instance - dlc instance wich belongs to calling DRX
|               st_flow      - flow control state (X bit)
|               st_line_sa   - line state SA
|               st_line_sa   - line state SB
|               st_break_len - break state
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_drx_ker_line_states_ind(UBYTE  dlc_instance,
                                        UBYTE  st_flow,
                                        UBYTE  st_line_sa,
                                        UBYTE  st_line_sb,
                                        USHORT st_break_len)
{
  T_DLC*  dlc;
  ULONG   old_lines;
  ULONG   new_lines;

  TRACE_ISIG( "sig_drx_ker_line_states_ind" );

  /*
   * set DLC
   */
  dlc = &uart_data->dlc_table[dlc_instance];

  switch( GET_STATE( UART_SERVICE_KER ) )
  {
    case KER_READY:
      /*
       * check for changed line states
       */
      old_lines = dlc->lines & (UART_SA_TX_MASK |
                                UART_SB_TX_MASK |
                                UART_X_TX_MASK  |
                                UART_BRK_TX_MASK);
      new_lines = ((ULONG)st_line_sa << UART_SA_TX_POS) |
                   ((ULONG)st_line_sb << UART_SB_TX_POS) |
                   ((ULONG)st_flow    << UART_X_TX_POS);
      if(st_break_len NEQ DTI_BREAK_OFF)
      {
        TRACE_EVENT("send Break");
        new_lines|= UART_BRK_TX_MASK;
      }

      if(old_lines NEQ new_lines)
      {
        /*
         * trace changes
         */
        if(new_lines & UART_X_TX_MASK)
        {
          if(!(old_lines & UART_X_TX_MASK))
          {
            TRACE_EVENT("TX Flow Control: stop");
          }
        }
        else if(old_lines & UART_X_TX_MASK)
        {
          TRACE_EVENT("TX Flow Control: start");
        }

        if(new_lines & UART_SA_TX_MASK)
        {
          if(!(old_lines & UART_SA_TX_MASK))
          {
            TRACE_EVENT("DSR: off");
          }
        }
        else if(old_lines & UART_SA_TX_MASK)
        {
          TRACE_EVENT("DSR: on");
        }

        if(new_lines & UART_SB_TX_MASK)
        {
          if(!(old_lines & UART_SB_TX_MASK))
          {
            TRACE_EVENT("DCD: off");
          }
        }
        else if(old_lines & UART_SB_TX_MASK)
        {
          TRACE_EVENT("DCD: on");
        }

        /*
         * send new line states
         * but flush UART before
         */
        dlc->lines&= ~(UART_SA_TX_MASK  |
                       UART_SB_TX_MASK  |
                       UART_X_TX_MASK   |
                       UART_BRK_TX_MASK |
                       UART_BRKLEN_TX_MASK);

        if(st_break_len NEQ DTI_BREAK_OFF)
          new_lines|= ((ULONG)st_break_len << UART_BRKLEN_TX_POS);

        dlc->lines|= new_lines;

        dlc->received_prim|= UART_DTI_DATA_REQ_MASK;

        if(uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING)
        {
          uart_data->ker.flush_state = UART_KER_TX_FLUSH;
          sig_ker_tx_flush_req();
        }
      }
      break;

    case KER_MUX:
      /*
       * check for changed line states
       */
      old_lines = dlc->lines & (UART_CTS_MASK |
                                UART_DSR_MASK |
                                UART_DCD_MASK |
                                UART_BRK_TX_MASK);
      new_lines = ((ULONG)st_flow << UART_CTS_POS)    |
                  ((ULONG)st_line_sa << UART_DSR_POS) |
                  ((ULONG)st_line_sb << UART_DCD_POS);

      if(st_break_len NEQ DTI_BREAK_OFF)
      {
        TRACE_EVENT_P1("send Break - DLCI=%d", dlc->dlci);
        new_lines|= UART_BRK_TX_MASK;
      }

      if(old_lines NEQ new_lines)
      {
        /*
         * trace changes
         */
        if(new_lines & UART_CTS_MASK)
        {
          if(!(old_lines & UART_CTS_MASK))
          {
            TRACE_EVENT_P1("TX Flow Control: stop - DLCI=%d", dlc->dlci);
          }
        }
        else if(old_lines & UART_CTS_MASK)
        {
          TRACE_EVENT_P1("TX Flow Control: start - DLCI=%d", dlc->dlci);
        }

        if(new_lines & UART_DSR_MASK)
        {
          if(!(old_lines & UART_DSR_MASK))
          {
            TRACE_EVENT_P1("DSR: off - DLCI=%d", dlc->dlci);
          }
        }
        else if(old_lines & UART_DSR_MASK)
        {
          TRACE_EVENT_P1("DSR: on - DLCI=%d", dlc->dlci);
        }

        if(new_lines & UART_DCD_MASK)
        {
          if(!(old_lines & UART_DCD_MASK))
          {
            TRACE_EVENT_P1("DCD: off - DLCI=%d", dlc->dlci);
          }
        }
        else if(old_lines & UART_DCD_MASK)
        {
          TRACE_EVENT_P1("DCD: on - DLCI=%d", dlc->dlci);
        }
        /*
         * build and send MSC command
         */
        dlc->lines&= ~(UART_CTS_MASK    |
                       UART_DSR_MASK    |
                       UART_DCD_MASK    |
                       UART_BRK_TX_MASK |
                       UART_BRKLEN_TX_MASK);

        if(st_break_len NEQ DTI_BREAK_OFF)
          new_lines|= ((ULONG)st_break_len << UART_BRKLEN_TX_POS);

        dlc->lines|= new_lines;
        ker_mux_send_line_states(dlc_instance);
      }
      break;

    default:
      TRACE_ERROR( "SIG_DRX_KER_LINE_STATES_IND unexpected" );
      break;
  }
} /* sig_drx_ker_line_states_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_dtx_ker_enable_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_DTX_KER_ENABLE_IND
|
| Parameters  : dlc_instance - dlc instance wich belongs to calling DTX
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_dtx_ker_enable_ind (UBYTE dlc_instance)
{
  TRACE_ISIG( "sig_dtx_ker_enable_ind" );

  switch( GET_STATE( UART_SERVICE_KER ) )
  {
    case KER_MUX:
      /*
       * build and send MSC command
       * enable flow control in line states
       */
      uart_data->dlc_table[dlc_instance].lines&= ~UART_FC_TX_MASK;
      /*
       * send new line states
       */
      ker_mux_send_line_states(dlc_instance);
      break;

    case KER_READY:
      break;

    default:
      TRACE_ERROR( "SIG_DTX_KER_ENABLE_IND unexpected" );
      break;
  }
} /* sig_dtx_ker_enable_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_dtx_ker_disable_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_DTX_KER_DISABLE_IND
|
| Parameters  : dlc_instance - dlc instance wich belongs to calling DTX
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_dtx_ker_disable_ind (UBYTE dlc_instance)
{
  TRACE_ISIG( "sig_dtx_ker_disable_ind" );

  switch( GET_STATE( UART_SERVICE_KER ) )
  {
    case KER_MUX:
      /*
       * build and send MSC command
       * disable flow control in line states
       */
      uart_data->dlc_table[dlc_instance].lines|= UART_FC_TX_MASK;
      /*
       * send new line states
       */
      ker_mux_send_line_states(dlc_instance);
      break;

    case KER_READY:
      break;

    default:
      TRACE_ERROR( "SIG_DTX_KER_DISABLE_IND unexpected" );
      break;
  }
} /* sig_dtx_ker_disable_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_dtx_ker_escape_detected_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_DTX_KER_ESCAPE_DETECTED_IND
|
| Parameters  : dlc_instance - dlc instance wich belongs to calling DTX
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_dtx_ker_escape_detected_ind (U8 dlc_instance)
{
  T_DLC *dlc;

  TRACE_FUNCTION( "sig_dtx_ker_escape_detected_ind" );

  /*
   * set DLC
   */
  dlc = &uart_data->dlc_table[dlc_instance];
  {
    PALLOC (uart_detected_ind, UART_DETECTED_IND);
    uart_detected_ind->device = uart_data->device;
    uart_detected_ind->dlci   = dlc->dlci;
    uart_detected_ind->cause  = UART_DETECT_ESC;
    PSEND (hCommMMI, uart_detected_ind);
  }
} /* sig_dtx_ker_escape_detected_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_any_ker_flushed_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_ANY_KER_FLUSHED_IND
|
| Parameters  : dlc_instance - dlc instance wich belongs to this signal
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_any_ker_flushed_ind (UBYTE dlc_instance)
{
  T_DLC*  dlc;
  UBYTE   i;

  TRACE_ISIG( "sig_any_ker_flushed_ind" );

  /*
   * reset flush indicator
   */
  dlc          = &uart_data->dlc_table[dlc_instance];
  dlc->flushed = TRUE;
  /*
   * if the primitive which has triggered the flush belongs to the whole port
   * we will check each DLC for flush, if it only belongs to this DLC we start
   * TX flushing immediately
   */
  if(uart_data->ker.received_prim)
  {
    /*
     * check each DLC
     */
    for(i = 0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
    {
      dlc = &uart_data->dlc_table[i];
      if(dlc->flushed NEQ TRUE)
        return;
    }
  }
  /*
   * start TX flushing
   */
  uart_data->ker.flush_state = UART_KER_TX_FLUSH;
  sig_ker_tx_flush_req();
} /* sig_any_ker_flushed_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_tx_ker_flushed_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_TX_KER_FLUSHED_IND
|
| Parameters  : no parameters
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_tx_ker_flushed_ind ()
{
  T_DLC*  dlc;
  UBYTE   i;
#ifndef  _SIMULATION_
  USHORT  error_code;
#endif
  TRACE_ISIG( "sig_tx_ker_flushed_ind" );

  if(uart_data->ker.flush_state EQ UART_KER_TX_FLUSH)
  {
    /*
     * primitives of the port
     */
    /*
     * UART_PARAMETERS_REQ
     */
    if(uart_data->ker.received_prim & UART_PARAMETERS_REQ_MASK)
    {
      /*
       * disable UART while set new communication parameters
       */
#ifdef _SIMULATION_
      {
        /*
         * send DTI_GETDATA_REQ
         */
        PALLOC (dti_getdata_req, DTI2_GETDATA_REQ);
        dti_getdata_req->link_id = LINK_DISABLE_PORT_1; /* for disable */
        PSEND (hCommMMI, dti_getdata_req);
      }
#else /* _SIMULATION_ */
#ifndef FF_MULTI_PORT
      if((error_code = UF_Enable (uart_data->device, FALSE)) NEQ UF_OK)
      {
          TRACE_ERROR_P2("UF Driver: Can't disable UART, [%d], uart_kerp.c(%d)",
                                                           error_code,__LINE__);
      }
#endif /* !FF_MULTI_PORT */
#endif /* _SIMULATION */
      /*
       * set new parameters
       */
      ker_setupUart();
#ifdef _SIMULATION_
      {
        /*
         * send DTI_GETDATA_REQ
         */
        PALLOC (dti_getdata_req, DTI2_GETDATA_REQ);
        dti_getdata_req->link_id = LINK_ENABLE_PORT_1; /* for enable */
        PSEND (hCommMMI, dti_getdata_req);
      }
#else /* _SIMULATION_ */
#ifndef FF_MULTI_PORT
      if((error_code = UF_Enable (uart_data->device, TRUE)) NEQ UF_OK)
      {
          TRACE_ERROR_P2("UF Driver: Can't enable UART, [%d], uart_kerp.c(%d)",
                                                          error_code,__LINE__);
      }
#endif /* !FF_MULTI_PORT */
#endif /* _SIMULATION */
      /*
       * restart suspended read and write procedures
       */
      sig_ker_tx_restart_write_req();
      sig_ker_rx_restart_read_req();
      /*
       * send confirm primitive
       */
      {
        PALLOC (uart_parameters_cnf, UART_PARAMETERS_CNF);
        uart_parameters_cnf->device = uart_data->device;
        PSEND (hCommMMI, uart_parameters_cnf);
      }
    }

    /*
     * UART_DISABLE_REQ
     */
    if(uart_data->ker.received_prim & UART_DISABLE_REQ_MASK)
    {
      switch( GET_STATE( UART_SERVICE_KER ) )
      {
        case KER_MUX:
        case KER_MUX_ESTABLISH:
        case KER_MUX_DLC_CLOSING:
        case KER_MUX_CLOSING:
        case KER_MUX_CLOSED:
          /*
           * stop timers and
           * remove all DLC instances
           */
          ker_mux_close_down();
          break;

        case KER_READY:
          /*
           * close dlc channel
           */
          ker_mux_dlc_release(UART_CONTROL_INSTANCE);
          break;

        case KER_DEAD:
          break;

        default:
          TRACE_ERROR( "SIG_TX_KER_FLUSHED_IND unexpected" );
          break;
      }

      SET_STATE( UART_SERVICE_KER, KER_DEAD );

      /*
       * disable UART
       */
#ifdef _SIMULATION_
      {
        /*
         * send DTI_GETDATA_REQ
         */
        PALLOC (dti_getdata_req, DTI2_GETDATA_REQ);
        dti_getdata_req->link_id = LINK_DISABLE_PORT_1; /* for disable */
        PSEND (hCommMMI, dti_getdata_req);
      }
#else /* _SIMULATION_ */
#ifndef FF_MULTI_PORT
      if((error_code = UF_Enable (uart_data->device, FALSE)) NEQ UF_OK)
      {
          TRACE_ERROR_P2("UF Driver: Can't disable UART, [%d], uart_kerp.c(%d)",
                                                           error_code,__LINE__);
      }
#endif /* !FF_MULTI_PORT */
#endif /* _SIMULATION */
      sig_ker_rx_dead_mode_req();
      sig_ker_tx_dead_mode_req();
      /*
       * send confirm primitive
       */
      {
        PALLOC (uart_disable_cnf, UART_DISABLE_CNF);
        uart_disable_cnf->device = uart_data->device;
        PSEND (hCommMMI, uart_disable_cnf);
      }
    }

    /*
     * UART_MUX_START_REQ
     */
    if(uart_data->ker.received_prim & UART_MUX_START_REQ_MASK)
    {
      switch( GET_STATE( UART_SERVICE_KER ) )
      {
        case KER_READY:
          /*
           * close dlc channel
           */
          ker_mux_dlc_release(UART_CONTROL_INSTANCE);
          break;

        default:
          TRACE_ERROR( "SIG_TX_KER_FLUSHED_IND unexpected" );
          break;
      }

      SET_STATE( UART_SERVICE_KER, KER_MUX_ESTABLISH );

      /*
       * set RX and TX service in mux mode
       */
      sig_ker_rx_mux_mode_req();
      sig_ker_tx_mux_mode_req();
      /*
       * start reception
       */
      MALLOC(uart_data->ker.rx_data_desc, (USHORT)(sizeof(T_desc2) -
                                           1 +
                                           uart_data->n1 +
                                           2));
      uart_data->ker.rx_data_desc->next = (ULONG)NULL;
      uart_data->ker.rx_data_desc->len  = 0;
      sig_ker_rx_ready_to_receive_req(uart_data->ker.rx_data_desc,
                                      0,
                                      (USHORT)(uart_data->n1 + 2));
      /*
       * start timer
       */
      sig_ker_rt_start_t3_req();

      /*
       * send confirm primitive
       */
      {
        PALLOC (uart_mux_start_cnf, UART_MUX_START_CNF);
        uart_mux_start_cnf->device = uart_data->device;
        PSEND (hCommMMI, uart_mux_start_cnf);
      }
    }

    /*
     * UART_MUX_CLOSE_REQ
     */
    if(uart_data->ker.received_prim & UART_MUX_CLOSE_REQ_MASK)
    {
      switch( GET_STATE( UART_SERVICE_KER ) )
      {
        case KER_MUX_CLOSED:
          if(uart_data->ker.receiving_state NEQ UART_KER_RECEIVING)
          {
            PALLOC(uart_mux_close_ind, UART_MUX_CLOSE_IND);
            SET_STATE( UART_SERVICE_KER, KER_READY );
            /*
             * stop receiving
             */
            sig_ker_rx_not_ready_to_receive_req();
            MFREE_DESC2(uart_data->ker.rx_data_desc);
            uart_data->ker.rx_data_desc = NULL;
            /*
             * set dlc values
             */
            dlc           = &uart_data->dlc_table[UART_CONTROL_INSTANCE];
            dlc->drx      = &uart_data->drx_base[0];
            dlc->dtx      = &uart_data->dtx_base[0];
            dlc->dlci     = 0;
            dlc->priority = 0;
            /*
             * set RX and TX in ready mode
             */
            sig_ker_rx_ready_mode_req();
            sig_ker_tx_ready_mode_req();
            /*
             * set frame size for ready mode
             */
            uart_data->n1 = UART_N1_READY_MODE;
            /*
             * set DRX and DTX in ready mode
             */
            uart_data->dtx = dlc->dtx;
            uart_data->drx = dlc->drx;
            sig_ker_drx_ready_mode_req(UART_CONTROL_INSTANCE);
            sig_ker_dtx_ready_mode_req(UART_CONTROL_INSTANCE);
            /*
             * inform ACI about entering ready mode
             */
            uart_mux_close_ind->device = uart_data->device;
            PSEND(hCommMMI, uart_mux_close_ind);
          }
          break;

        default:
          TRACE_ERROR( "SIG_TX_KER_FLUSHED_IND unexpected" );
          break;
      }
    }

    /*
     * no more UART port related primitives
     * so clear all flags
     */
    uart_data->ker.received_prim = 0;

    /*
     * primitives of the DLC
     */
    for(i = 0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
    {
      dlc = &uart_data->dlc_table[i];
      if(dlc->received_prim)
      {
        /*
         * UART_RING_REQ
         * UART_DCD_REQ
         * DTI_DATA_REQ (line states)
         */
        if((dlc->received_prim & UART_RING_REQ_MASK)  ||
           (dlc->received_prim & UART_DCD_REQ_MASK)   ||
           (dlc->received_prim & UART_DTI_DATA_REQ_MASK))
        {
          /*
           * send new line states
           */
          switch( GET_STATE( UART_SERVICE_KER ) )
          {
            case KER_READY:
              sig_ker_tx_line_states_req(UART_CONTROL_INSTANCE);
              break;

            case KER_MUX:
              /*
               * send MSC frame to peer
               */
              ker_mux_send_line_states (uart_data->dlc_instance[dlc->dlci]);
              break;

            default:
              if(dlc->received_prim & UART_RING_REQ_MASK)
              {
                TRACE_ERROR( "UART_RING_REQ unexpected" );
              }
              if(dlc->received_prim & UART_DCD_REQ_MASK)
              {
                TRACE_ERROR( "UART_DCD_REQ unexpected" );
              }
              break;
          }
          /*
           * send confirm primitives
           */
          if(dlc->received_prim & UART_RING_REQ_MASK)
          {
            PALLOC (uart_ring_cnf, UART_RING_CNF);
            uart_ring_cnf->device = uart_data->device;
            uart_ring_cnf->dlci   = dlc->dlci;
            PSEND (hCommMMI, uart_ring_cnf);
          }
          if(dlc->received_prim & UART_DCD_REQ_MASK)
          {
            PALLOC (uart_dcd_cnf, UART_DCD_CNF);
            uart_dcd_cnf->device = uart_data->device;
            uart_dcd_cnf->dlci   = dlc->dlci;
            PSEND (hCommMMI, uart_dcd_cnf);
          }
        }
        /*
         * no more DLC related primitives
         * so clear all flags
         */
        dlc->received_prim = 0;
      }
    }
    uart_data->ker.flush_state = UART_KER_NOT_FLUSHING;
  }
} /* sig_tx_ker_flushed_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_tx_ker_sending_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_TX_KER_SENDING_IND
|
| Parameters  : no parameters
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_tx_ker_sending_ind ()
{
  TRACE_ISIG( "sig_tx_ker_sending_ind" );

  switch( GET_STATE( UART_SERVICE_KER ) )
  {
    case KER_MUX_ESTABLISH:
    case KER_MUX:
    case KER_MUX_DLC_CLOSING:
    case KER_MUX_CLOSING:
    case KER_MUX_CLOSED:
      uart_data->ker.sending_state = UART_KER_SENDING;
      break;

    default:
      TRACE_ERROR( "SIG_TX_KER_SENDING_IND unexpected" );
      break;
  }
} /* sig_tx_ker_sending_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_tx_ker_data_sent_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_TX_KER_DATA_SENT_IND
|
| Parameters  : rest_data - not yet sent data
|               write_pos - position where the not yet sent data starts
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_tx_ker_data_sent_ind (T_desc2* rest_data, USHORT read_pos)
{
  TRACE_ISIG( "sig_tx_ker_data_sent_ind" );

  /*
   * free sent data descriptor
   */
  MFREE_DESC2(uart_data->ker.tx_data_desc);
  uart_data->ker.tx_data_desc  = NULL;
  uart_data->ker.sending_state = UART_KER_NOT_SENDING;
  if(uart_data->ker.tx_data_waiting)
  {
    /*
     * send next descriptor in waiting queue
     */
    uart_data->ker.tx_data_desc    = uart_data->ker.tx_data_waiting;
    uart_data->ker.tx_data_waiting =
      (T_desc2*)uart_data->ker.tx_data_waiting->next;
    /*
     * only one descriptor is sent at a time
     */
    uart_data->ker.tx_data_desc->next = (ULONG)NULL;
    sig_ker_tx_data_available_req( uart_data->ker.tx_data_desc, 0);
  }
  else
  {
    switch( GET_STATE( UART_SERVICE_KER ) )
    {
      case KER_MUX_ESTABLISH:
      case KER_MUX:
      case KER_MUX_DLC_CLOSING:
      case KER_MUX_CLOSING:
        break;

      case KER_MUX_CLOSED:
        /*
         * flush UART before enter ready mode
         */
        uart_data->ker.received_prim|= UART_MUX_CLOSE_REQ_MASK;

        if(uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING)
        {
          uart_data->ker.flush_state = UART_KER_TX_FLUSH;
          sig_ker_tx_flush_req();
        }
        break;

      default:
        TRACE_ERROR( "SIG_TX_KER_DATA_SENT_IND unexpected" );
        break;
    }
  }
} /* sig_tx_ker_data_sent_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_rx_ker_receiving_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_RX_KER_RECEIVING_IND
|
| Parameters  : no parameters
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_rx_ker_receiving_ind ()
{
  TRACE_ISIG( "sig_rx_ker_receiving_ind" );

  switch( GET_STATE( UART_SERVICE_KER ) )
  {
    case KER_MUX_ESTABLISH:
    case KER_MUX:
    case KER_MUX_DLC_CLOSING:
    case KER_MUX_CLOSING:
    case KER_MUX_CLOSED:
      uart_data->ker.receiving_state = UART_KER_RECEIVING;
      break;
    default:
      TRACE_ERROR( "SIG_RX_KER_RECEIVING_IND unexpected" );
      break;
  }
} /* sig_rx_ker_receiving_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_rx_ker_data_received_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_RX_KER_DATA_RECEIVED_IND
|               which is used to process a received frame.
|
|               Precondition is that the frame has a length >2 without flags.
|
| Parameters  : received_data - received data
|               write_pos     - write position for the next reception
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_rx_ker_data_received_ind (T_desc2* received_data,
                                          USHORT write_pos)
{
  UBYTE   i;
  UBYTE   dlci;
  T_DLC*  dlc;
  ULONG   forward;
  BOOL    continuous;

  TRACE_ISIG( "sig_rx_ker_data_received_ind" );

#ifndef _TARGET_
  if(received_data->len)
  {
    USHORT  pos;
    char    buf[90];
    /*
     * trace output
     */
    TRACE_EVENT("======= IN");
    i   = 0;
    pos = 0;
    while(pos < received_data->len)
    {
      i+= sprintf(&buf[i], "0x%02x, ", received_data->buffer[pos]);
      pos++;
      if(i > 80)
      {
        TRACE_EVENT( buf );
        i = 0;
      }
      else if(pos >= received_data->len)
      {
        TRACE_EVENT( buf );
      }
    }
  }
#endif /* !_TARGET_ */

  uart_data->ker.receiving_state = UART_KER_NOT_RECEIVING;

  switch( GET_STATE( UART_SERVICE_KER ) )
  {
    case KER_MUX_ESTABLISH:
      if(received_data->len EQ 0)
      {
        /*
         * prepare next reception
         */
        sig_ker_rx_ready_to_receive_req(received_data,
                                        write_pos,
                                        (USHORT)(uart_data->n1 + 2));
        break;
      }
      dlci = received_data->buffer[UART_OFFSET_ADDRESS] >> UART_DLCI_POS;
      if((dlci EQ UART_DLCI_CONTROL) &&
         (received_data->buffer[UART_OFFSET_CONTROL] EQ UART_SABM_FRAME))
      {
        /*
         * analyze SABM frame
         */
        forward = 0;
        ker_receive_sabm_frame(&forward, received_data);
        /*
         * set dlc value
         */
        dlc = &uart_data->dlc_table[UART_CONTROL_INSTANCE];
        if((forward & UART_FORWARD_SABM) &&
           (dlc->connection_state EQ UART_CONNECTION_SABM_RCVD) &&
           (uart_data->dlc_instance[dlci] NEQ UART_CONTROL_INSTANCE))
        {
          SET_STATE( UART_SERVICE_KER, KER_MUX );
          /*
           * stop timer
           */
          sig_ker_rt_stop_t3_req();
          /*
           * setup dlc parameter
           */
          uart_data->dlc_instance[dlci] = UART_CONTROL_INSTANCE;
          dlc->connection_state         = UART_CONNECTION_OPEN;
          /*
           * set priority
           */
          dlc->priority = 0;
          /*
           * send response frame
           */
          if(forward & UART_FORWARD_RESPONSE)
          {
            ker_mux_send_frame(received_data);
            /*
             * prepare next reception
             */
            MALLOC(received_data, (USHORT)(sizeof(T_desc2) - 1
                                                          + uart_data->n1
                                                          + 2));
            received_data->next = (ULONG)NULL;
          }
        }
      }
      /*
       * prepare next reception
       */
      received_data->len = 0;
      uart_data->ker.rx_data_desc = received_data;
      sig_ker_rx_ready_to_receive_req(received_data,
                                      0,
                                      (USHORT)(uart_data->n1 + 2));
      break;

    case KER_MUX:
      if(received_data->len EQ 0)
      {
        /*
         * prepare next reception
         */
        sig_ker_rx_ready_to_receive_req(received_data,
                                        write_pos,
                                        (USHORT)(uart_data->n1 + 2));
        break;
      }
      /*
       * analyze frame and messages
       */
      forward = 0;
      switch(received_data->buffer[UART_OFFSET_CONTROL])
      {
        case UART_SABM_FRAME:
          ker_receive_sabm_frame(&forward, received_data);
          break;

        case UART_UA_FRAME:
          ker_receive_ua_frame(&forward, received_data);
          break;

        case UART_DM_CONTROL_FRAME:
        case UART_DM_DATA_FRAME:
          ker_receive_dm_frame(&forward, received_data);
          break;

        case UART_DISC_FRAME:
          ker_receive_disc_frame(&forward, received_data);
          break;

        case UART_UIH_CONTROL_FRAME:
          ker_receive_uih_control_frame(&forward, received_data);
          break;

        case UART_UIH_DATA_FRAME:
          ker_receive_uih_data_frame(&forward, received_data);
          break;

        default:
        {
          TRACE_EVENT_P2("Warning: Unexpected HDLC value: %d, uart_kers.c(%d)",
                         received_data->buffer[UART_OFFSET_CONTROL], __LINE__);
          break;
        }
      }
      /*
       * remove resonded frames and send next frames in command queue
       */
      for(i=0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
      {
        dlc = &uart_data->dlc_table[i];
        switch(dlc->connection_state)
        {
          case UART_CONNECTION_OPEN:
          case UART_CONNECTION_DISC_SENT:
            if((dlc->last_command NEQ NULL) &&
               (dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
                UART_UIH_CONTROL_FRAME) &&
               (dlc->last_command->len EQ UART_OFFSET_INFO))
            {
              /*
               * remove responded UIH frame
               */
              MFREE_DESC2(dlc->last_command);
              dlc->last_command = NULL;
              uart_data->ker.nr_t2--;
              if( uart_data->ker.nr_t2 EQ 0 )
                sig_ker_rt_stop_t2_req();
            }
            if((dlc->last_command  EQ NULL) &&
               (dlc->next_command NEQ NULL))
            {
              T_desc2* temp_desc;
              /*
               * transmit next command frame
               */
              dlc->last_command       = dlc->next_command;
              dlc->next_command       = (T_desc2*)dlc->next_command->next;
              dlc->last_command->next = (ULONG)NULL;

              MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1 +
                                dlc->last_command->len));
              temp_desc->next = (ULONG)NULL;
              temp_desc->len  = dlc->last_command->len;
              memcpy(temp_desc->buffer,
                     dlc->last_command->buffer,
                     dlc->last_command->len);

              dlc->retransmissions = 0;
              ker_mux_send_frame(temp_desc);

              if(dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
                 UART_UIH_CONTROL_FRAME)
              {
                uart_data->ker.nr_t2++;
                sig_ker_rt_start_t2_req();
              }
              else
              {
                uart_data->ker.nr_t1++;
                sig_ker_rt_start_t1_req();
              }
            }
            break;

          case UART_CONNECTION_DEAD:
            break;

          default:
          {
            TRACE_EVENT_P2("Unexpected DLC connection state: %d, uart_kers.c(%d)",
                                                 dlc->connection_state, __LINE__);
            break;
          }
        }
      }
      /*
       * process results of analysis
       */
      if(forward)
      {
        for(i=0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
        {
          if(i NEQ UART_CONTROL_INSTANCE)
          {
            /*
             * set dlc values
             */
            dlc  = &uart_data->dlc_table[i];
            dlci = dlc->dlci;
            /*
             * channel to open
             */
            if((forward & UART_FORWARD_SABM) &&
               (dlc->connection_state EQ UART_CONNECTION_SABM_RCVD) &&
               (uart_data->dlc_instance[dlci] NEQ i))
            {
              PALLOC(uart_mux_dlc_establish_ind, UART_MUX_DLC_ESTABLISH_IND);
              /*
               * setup dlc parameter
               */
              uart_data->dlc_instance[dlci] = i;
              dlc->drx = &uart_data->drx_base[i];
              dlc->dtx = &uart_data->dtx_base[i];
              /*
               * set priority
               */
              if(dlci < 8)
                dlc->priority = 7;
              else if(dlci < 16)
                dlc->priority = 15;
              else if(dlci < 24)
                dlc->priority = 23;
              else if(dlci < 32)
                dlc->priority = 31;
              else if(dlci < 40)
                dlc->priority = 39;
              else if(dlci < 48)
                dlc->priority = 47;
              else if(dlci < 56)
                dlc->priority = 55;
              else
                dlc->priority = 61;
              /*
               * store response frame and
               * clear appropriate bit in forward mask
               */
              dlc->next_command = received_data;
              forward          &= ~UART_FORWARD_RESPONSE;
              /*
               * create new reception frame
               */
              MALLOC(received_data, (USHORT)(sizeof(T_desc2) - 1
                                                            + uart_data->n1
                                                            + 2));
              received_data->next = (ULONG)NULL;
              /*
               * inform ACI about new DLC
               */
              uart_mux_dlc_establish_ind->device = uart_data->device;
              uart_mux_dlc_establish_ind->dlci   = dlci;
              uart_mux_dlc_establish_ind->
                                     convergence = UART_MUX_CONVERGENCE_UOS;
              uart_mux_dlc_establish_ind->n1     = uart_data->n1;
              uart_mux_dlc_establish_ind->
                                         service = UART_MUX_SERVICE_AT;
              PSEND (hCommMMI, uart_mux_dlc_establish_ind);
            }
            /*
             * channel to close
             */
            if((forward & UART_FORWARD_DLC_RELEASE) &&
               (dlc->connection_state EQ UART_CONNECTION_DEAD) &&
               (dlci NEQ UART_DLCI_INVALID))
            {
              PALLOC(uart_mux_dlc_release_ind, UART_MUX_DLC_RELEASE_IND);
              /*
               * release channel
               */
              ker_mux_dlc_release(i);
              /*
               * inform ACI about DLC release
               */
              uart_mux_dlc_release_ind->device = uart_data->device;
              uart_mux_dlc_release_ind->dlci   = dlci;
              PSEND(hCommMMI, uart_mux_dlc_release_ind);
            }
            /*
             * set Flow Control ON
             */
            if((forward & UART_FORWARD_FCON) &&
               (dlc->connection_state EQ UART_CONNECTION_OPEN) &&
               (!(dlc->lines & UART_FC_RX_MASK)))
            {
              uart_data->drx = dlc->drx;
              sig_ker_drx_enable_req();
            }
            /*
             * set Flow Control OFF
             */
            if((forward & UART_FORWARD_FCOFF) &&
               (dlc->connection_state EQ UART_CONNECTION_OPEN) &&
               (!(dlc->lines & UART_FC_RX_MASK)))
            {
              uart_data->drx = dlc->drx;
              sig_ker_drx_disable_req();
            }
            /*
             * send status lines
             */
            if((forward & UART_FORWARD_MSC) &&
               (dlc->connection_state EQ UART_CONNECTION_OPEN))
            {
              UBYTE st_flow;
              UBYTE st_line_sa;
              UBYTE st_break_len;
              /*
               * send primitive if DTR drop is detected
               */
              if(dlc->lines & UART_DTR_MASK)
              {
                PALLOC (uart_detected_ind, UART_DETECTED_IND);
                uart_detected_ind->device = uart_data->device;
                uart_detected_ind->dlci   = dlc->dlci;
                uart_detected_ind->cause  = UART_DETECT_DTR;
                PSEND (hCommMMI, uart_detected_ind);
              }
              /*
               * set line states
               */
              if(dlc->lines & UART_RTS_MASK)
                st_flow = DTI_FLOW_OFF;
              else
                st_flow = DTI_FLOW_ON;
              if(dlc->lines & UART_DTR_MASK)
                st_line_sa = DTI_SA_OFF;
              else
                st_line_sa = DTI_SA_ON;
              /*
               * set break
               */
              if(dlc->lines & UART_BRK_RX_MASK)
                st_break_len = (UBYTE)((dlc->lines & UART_BRKLEN_RX_MASK) >>
                                                     UART_BRKLEN_RX_POS);
              else
                st_break_len = DTI_BREAK_OFF;
              /*
               * send flow control signals
               */
              if(uart_data->ker.data_flow_tx EQ UART_FLOW_ENABLED)
              {
                uart_data->drx = dlc->drx;
                if(dlc->lines & UART_FC_RX_MASK)
                  sig_ker_drx_disable_req();
                else
                  sig_ker_drx_enable_req();
              }
              /*
               * send line states
               */
              uart_data->dtx = dlc->dtx;
              sig_ker_dtx_line_states_req(st_flow,
                                          st_line_sa,
                                          DTI_SB_ON,
                                          st_break_len);
            }
          }
        }
        /*
         * send response frame
         */
        if(forward & UART_FORWARD_RESPONSE)
        {
          ker_mux_send_frame(received_data);
          uart_data->ker.rx_data_desc = NULL;
        }
        /*
         * Close-Down multiplexer
         */
        if(forward & UART_FORWARD_CLD)
        {
          SET_STATE( UART_SERVICE_KER, KER_MUX_CLOSED );
          /*
           * stop timers and
           * remove all DLC instances
           */
          ker_mux_close_down();
          /*
           * flush UART before change the state
           */
          if(uart_data->ker.tx_data_desc EQ NULL)
          {
            uart_data->ker.received_prim|= UART_MUX_CLOSE_REQ_MASK;

            if(uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING)
            {
              uart_data->ker.flush_state = UART_KER_TX_FLUSH;
              sig_ker_tx_flush_req();
            }
          }
        }
      }
      /*
       * prepare next reception
       */
      if(forward & UART_FORWARD_RESPONSE)
      {
        MALLOC(received_data, (USHORT)(sizeof(T_desc2) - 1
                                                      + uart_data->n1
                                                      + 2));
        received_data->next = (ULONG)NULL;
      }
      received_data->len = 0;
      uart_data->ker.rx_data_desc = received_data;
      sig_ker_rx_ready_to_receive_req(received_data,
                                      0,
                                      (USHORT)(uart_data->n1 + 2));
      break;

    case KER_MUX_DLC_CLOSING:
      if(received_data->len EQ 0)
      {
        /*
         * prepare next reception
         */
        sig_ker_rx_ready_to_receive_req(received_data,
                                        write_pos,
                                        (USHORT)(uart_data->n1 + 2));
        break;
      }
      /*
       * analyze frame and messages
       */
      forward = 0;
      switch(received_data->buffer[UART_OFFSET_CONTROL])
      {
        case UART_SABM_FRAME:
          ker_receive_sabm_frame(&forward, received_data);
          break;

        case UART_UA_FRAME:
          ker_receive_ua_frame(&forward, received_data);
          break;

        case UART_DM_CONTROL_FRAME:
        case UART_DM_DATA_FRAME:
          ker_receive_dm_frame(&forward, received_data);
          break;

        case UART_DISC_FRAME:
          ker_receive_disc_frame(&forward, received_data);
          break;

        case UART_UIH_CONTROL_FRAME:
          ker_receive_uih_control_frame(&forward, received_data);
          break;

        case UART_UIH_DATA_FRAME:
          ker_receive_uih_data_frame(&forward, received_data);
          break;

        default:
        {
          TRACE_EVENT_P2("Warning: Unexpected HDLC value: %d, uart_kers.c(%d)",
                         received_data->buffer[UART_OFFSET_CONTROL], __LINE__);
          break;
        }
      }
      /*
       * remove resonded frames and send next frames in command queue
       */
      for(i=0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
      {
        dlc = &uart_data->dlc_table[i];
        switch(dlc->connection_state)
        {
          case UART_CONNECTION_OPEN:
          case UART_CONNECTION_DISC_SENT:
            if((dlc->last_command NEQ NULL) &&
               (dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
                UART_UIH_CONTROL_FRAME) &&
               (dlc->last_command->len EQ UART_OFFSET_INFO))
            {
              /*
               * remove responded UIH frame
               */
              MFREE_DESC2(dlc->last_command);
              dlc->last_command = NULL;
              uart_data->ker.nr_t2--;
              if( uart_data->ker.nr_t2 EQ 0 )
                sig_ker_rt_stop_t2_req();
            }
            if((dlc->last_command  EQ NULL) &&
               (dlc->next_command NEQ NULL))
            {
              T_desc2* temp_desc;
              /*
               * transmit next command frame
               */
              dlc->last_command       = dlc->next_command;
              dlc->next_command       = (T_desc2*)dlc->next_command->next;
              dlc->last_command->next = (ULONG)NULL;

              MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1 +
                                dlc->last_command->len));
              temp_desc->next = (ULONG)NULL;
              temp_desc->len  = dlc->last_command->len;
              memcpy(temp_desc->buffer,
                     dlc->last_command->buffer,
                     dlc->last_command->len);

              dlc->retransmissions = 0;
              ker_mux_send_frame(temp_desc);

              if(dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
                 UART_UIH_CONTROL_FRAME)
              {
                uart_data->ker.nr_t2++;
                sig_ker_rt_start_t2_req();
              }
              else
              {
                uart_data->ker.nr_t1++;
                sig_ker_rt_start_t1_req();
              }
            }
            break;

          case UART_CONNECTION_DEAD:
            break;

          default:
          {
            TRACE_EVENT_P2("Unexpected DLC connection state: %d, uart_kers.c(%d)",
                                                 dlc->connection_state, __LINE__);
            break;
          }
        }
      }
      /*
       * process results of analysis
       */
      if(forward)
      {
        continuous = FALSE;
        for(i=0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
        {
          if(i NEQ UART_CONTROL_INSTANCE)
          {
            /*
             * set dlc values
             */
            dlc  = &uart_data->dlc_table[i];
            dlci = dlc->dlci;
            /*
             * channel to open
             */
            if((forward & UART_FORWARD_SABM) &&
               (dlc->connection_state EQ UART_CONNECTION_SABM_RCVD))
            {
              /*
               * reject all attempts to open a channel
               */
              received_data->buffer[UART_OFFSET_CONTROL] =
                UART_DM_CONTROL_FRAME;
              /*
               * release channel
               */
              ker_mux_dlc_release(i);
            }
            /*
             * channel to close
             */
            if((forward & UART_FORWARD_DLC_RELEASE) &&
               (dlc->connection_state EQ UART_CONNECTION_DEAD) &&
               (dlci NEQ UART_DLCI_INVALID))
            {
              /*
               * release channel
               */
              ker_mux_dlc_release(i);
            }
            if(dlc->connection_state NEQ UART_CONNECTION_DEAD)
              continuous = TRUE;
          }
        }
        /*
         * send response frame
         */
        if(forward & UART_FORWARD_RESPONSE)
        {
          ker_mux_send_frame(received_data);
          uart_data->ker.rx_data_desc = NULL;
        }
        /*
         * Close-Down multiplexer
         */
        if(forward & UART_FORWARD_CLD)
        {
          SET_STATE( UART_SERVICE_KER, KER_MUX_CLOSED );
          /*
           * stop timers and
           * remove all DLC instances
           */
          ker_mux_close_down();
          /*
           * flush UART before change the state
           */
          if(uart_data->ker.tx_data_desc EQ NULL)
          {
            uart_data->ker.received_prim|= UART_MUX_CLOSE_REQ_MASK;

            if(uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING)
            {
              uart_data->ker.flush_state = UART_KER_TX_FLUSH;
              sig_ker_tx_flush_req();
            }
          }
        }
        /*
         * change state if all channels are closed
         */
        else if(continuous EQ FALSE)
        {
          SET_STATE( UART_SERVICE_KER, KER_MUX_CLOSING );
          /*
           * build and send CLD command frame:
           */
          ker_mux_send_close_down();
          /*
           * start timer
           */
          sig_ker_rt_start_t3_req();
        }
      }
      /*
       * prepare next reception
       */
      if(forward & UART_FORWARD_RESPONSE)
      {
        MALLOC(received_data, (USHORT)(sizeof(T_desc2) - 1
                                                      + uart_data->n1
                                                      + 2));
        received_data->next = (ULONG)NULL;
      }
      received_data->len = 0;
      uart_data->ker.rx_data_desc = received_data;
      sig_ker_rx_ready_to_receive_req(received_data,
                                      0,
                                      (USHORT)(uart_data->n1 + 2));
      break;

    case KER_MUX_CLOSING:
      if(received_data->len EQ 0)
      {
        /*
         * prepare next reception
         */
        sig_ker_rx_ready_to_receive_req(received_data,
                                        write_pos,
                                        (USHORT)(uart_data->n1 + 2));
        break;
      }
      /*
       * analyze frame and messages
       */
      forward = 0;
      switch(received_data->buffer[UART_OFFSET_CONTROL])
      {
        case UART_SABM_FRAME:
          ker_receive_sabm_frame(&forward, received_data);
          break;

        case UART_UA_FRAME:
          ker_receive_ua_frame(&forward, received_data);
          break;

        case UART_DM_CONTROL_FRAME:
        case UART_DM_DATA_FRAME:
          ker_receive_dm_frame(&forward, received_data);
          break;

        case UART_DISC_FRAME:
          ker_receive_disc_frame(&forward, received_data);
          break;

        case UART_UIH_CONTROL_FRAME:
          ker_receive_uih_control_frame(&forward, received_data);
          break;

        case UART_UIH_DATA_FRAME:
          ker_receive_uih_data_frame(&forward, received_data);
          break;

        default:
        {
          TRACE_EVENT_P2("Warning: Unexpected HDLC value: %d, uart_kers.c(%d)",
                         received_data->buffer[UART_OFFSET_CONTROL], __LINE__);
          break;
        }
      }
      /*
       * remove resonded frames and send next frames in command queue
       */
      for(i=0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
      {
        dlc = &uart_data->dlc_table[i];
        switch(dlc->connection_state)
        {
          case UART_CONNECTION_OPEN:
          case UART_CONNECTION_DISC_SENT:
            if((dlc->last_command NEQ NULL) &&
               (dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
                UART_UIH_CONTROL_FRAME) &&
               (dlc->last_command->len EQ UART_OFFSET_INFO))
            {
              /*
               * remove responded UIH frame
               */
              MFREE_DESC2(dlc->last_command);
              dlc->last_command = NULL;
              uart_data->ker.nr_t2--;
              if( uart_data->ker.nr_t2 EQ 0 )
                sig_ker_rt_stop_t2_req();
            }
            if((dlc->last_command  EQ NULL) &&
               (dlc->next_command NEQ NULL))
            {
              T_desc2* temp_desc;
              /*
               * transmit next command frame
               */
              dlc->last_command       = dlc->next_command;
              dlc->next_command       = (T_desc2*)dlc->next_command->next;
              dlc->last_command->next = (ULONG)NULL;

              MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1 +
                                dlc->last_command->len));
              temp_desc->next = (ULONG)NULL;
              temp_desc->len  = dlc->last_command->len;
              memcpy(temp_desc->buffer,
                     dlc->last_command->buffer,
                     dlc->last_command->len);

              dlc->retransmissions = 0;
              ker_mux_send_frame(temp_desc);

              if(dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
                 UART_UIH_CONTROL_FRAME)
              {
                uart_data->ker.nr_t2++;
                sig_ker_rt_start_t2_req();
              }
              else
              {
                uart_data->ker.nr_t1++;
                sig_ker_rt_start_t1_req();
              }
            }
            break;

          case UART_CONNECTION_DEAD:
            break;

          default:
          {
            TRACE_EVENT_P2("Unexpected DLC connection state: %d, uart_kers.c(%d)",
                                                  dlc->connection_state,__LINE__);
            break;
          }
        }
      }
      /*
       * process results of analysis
       */
      if(forward)
      {
        for(i=0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++)
        {
          if(i NEQ UART_CONTROL_INSTANCE)
          {
            /*
             * set dlc values
             */
            dlc  = &uart_data->dlc_table[i];
            dlci = dlc->dlci;
            /*
             * channel to open
             */
            if((forward & UART_FORWARD_SABM) &&
               (dlc->connection_state EQ UART_CONNECTION_SABM_RCVD))
            {
              /*
               * reject all attempts to open a channel
               */
              received_data->buffer[UART_OFFSET_CONTROL] =
                UART_DM_CONTROL_FRAME;
              /*
               * release channel
               */
              ker_mux_dlc_release(i);
            }
            /*
             * channel to close
             */
            if((forward & UART_FORWARD_DLC_RELEASE) &&
               (dlc->connection_state EQ UART_CONNECTION_DEAD) &&
               (dlci NEQ UART_DLCI_INVALID))
            {
              /*
               * release channel
               */
              ker_mux_dlc_release(i);
            }
          }
        }
        /*
         * send response frame
         */
        if(forward & UART_FORWARD_RESPONSE)
        {
          ker_mux_send_frame(received_data);
          uart_data->ker.rx_data_desc = NULL;
        }
        /*
         * Close-Down multiplexer
         */
        if(forward & UART_FORWARD_CLD)
        {
          SET_STATE( UART_SERVICE_KER, KER_MUX_CLOSED );
          /*
           * stop timers and
           * remove all DLC instances
           */
          ker_mux_close_down();
          /*
           * flush UART before change the state
           */
          if(uart_data->ker.tx_data_desc EQ NULL)
          {
            uart_data->ker.received_prim|= UART_MUX_CLOSE_REQ_MASK;

            if(uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING)
            {
              uart_data->ker.flush_state = UART_KER_TX_FLUSH;
              sig_ker_tx_flush_req();
            }
          }
        }
      }
      /*
       * prepare next reception
       */
      if(forward & UART_FORWARD_RESPONSE)
      {
        MALLOC(received_data, (USHORT)(sizeof(T_desc2) - 1
                                                      + uart_data->n1
                                                      + 2));
        received_data->next = (ULONG)NULL;
      }
      received_data->len = 0;
      uart_data->ker.rx_data_desc = received_data;
      sig_ker_rx_ready_to_receive_req(received_data,
                                      0,
                                      (USHORT)(uart_data->n1 + 2));
      break;

    case KER_MUX_CLOSED:
      if((uart_data->ker.tx_data_desc EQ NULL) &&
         (uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING))
      {
        PALLOC(uart_mux_close_ind, UART_MUX_CLOSE_IND);
        SET_STATE( UART_SERVICE_KER, KER_READY );
        /*
         * free receiving buffer
         */
        MFREE_DESC2(uart_data->ker.rx_data_desc);
        uart_data->ker.rx_data_desc = NULL;
        /*
         * set dlc values
         */
        dlc            = &uart_data->dlc_table[UART_CONTROL_INSTANCE];
        dlc->drx       = &uart_data->drx_base[0];
        dlc->dtx       = &uart_data->dtx_base[0];
        dlc->dlci      = 0;
        dlc->priority  = 0;
        /*
         * set RX and TX in ready mode
         */
        sig_ker_rx_ready_mode_req();
        sig_ker_tx_ready_mode_req();
        /*
         * set frame size for ready mode
         */
        uart_data->n1 = UART_N1_READY_MODE;
        /*
         * set DRX and DTX in ready mode
         */
        uart_data->dtx = dlc->dtx;
        uart_data->drx = dlc->drx;
        sig_ker_drx_ready_mode_req(UART_CONTROL_INSTANCE);
        sig_ker_dtx_ready_mode_req(UART_CONTROL_INSTANCE);
        /*
         * inform ACI about entering ready mode
         */
        uart_mux_close_ind->device = uart_data->device;
        PSEND(hCommMMI, uart_mux_close_ind);
      }
      else if(received_data->len EQ 0)
      {
        /*
         * prepare next reception
         */
        sig_ker_rx_ready_to_receive_req(received_data,
                                        write_pos,
                                        (USHORT)(uart_data->n1 + 2));
      }
      else
      {
        /*
         * prepare next reception
         */
        received_data->len = 0;
        sig_ker_rx_ready_to_receive_req(received_data,
                                        0,
                                        (USHORT)(uart_data->n1 + 2));
      }
      break;

    default:
      TRACE_ERROR( "SIG_RX_KER_DATA_RECEIVED_IND unexpected" );
      break;
  }
} /* sig_rx_ker_data_received_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_rx_ker_line_states_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_RX_KER_LINE_STATES_IND
|
| Parameters  : line_states - new line states
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_rx_ker_line_states_ind (ULONG line_states)
{
  T_DLC*  dlc;
  UBYTE   st_flow;
  UBYTE   st_line_sa;
  UBYTE   st_line_sb;
  UBYTE   st_break_len;

  TRACE_ISIG( "sig_rx_ker_line_states_ind" );

  /*
   * set DLC
   */
  dlc = &uart_data->dlc_table[UART_CONTROL_INSTANCE];
  /*
   * send primitive if escape sequence or DTR drop is detected
   */
  if(line_states & UART_ESC_RX_MASK)
  {
    PALLOC (uart_detected_ind, UART_DETECTED_IND);
    uart_detected_ind->device = uart_data->device;
    uart_detected_ind->dlci   = dlc->dlci;
    uart_detected_ind->cause  = UART_DETECT_ESC;
    PSEND (hCommMMI, uart_detected_ind);
  }
  if((line_states & UART_DTR_MASK) AND
     (!(dlc->lines & UART_DTR_MASK)))
  {
    PALLOC (uart_detected_ind, UART_DETECTED_IND);
    uart_detected_ind->device = uart_data->device;
    uart_detected_ind->dlci   = dlc->dlci;
    uart_detected_ind->cause  = UART_DETECT_DTR;
    PSEND (hCommMMI, uart_detected_ind);
  }

  switch( GET_STATE( UART_SERVICE_KER ) )
  {
    case KER_READY:
      /*
       * set line states
       */
      if(line_states & UART_X_RX_MASK)
        st_flow = DTI_FLOW_OFF;
      else
        st_flow = DTI_FLOW_ON;

      if(line_states & UART_SA_RX_MASK)
        st_line_sa = DTI_SA_OFF;
      else
        st_line_sa = DTI_SA_ON;

      if(line_states & UART_SB_RX_MASK)
        st_line_sb = DTI_SB_OFF;
      else
        st_line_sb = DTI_SB_ON;

      if(line_states & UART_BRK_RX_MASK)
        st_break_len = (UBYTE)((line_states & UART_BRKLEN_RX_MASK)
                               >> UART_BRKLEN_RX_POS);
      else
        st_break_len = DTI_BREAK_OFF;

      uart_data->dtx = dlc->dtx;
      sig_ker_dtx_line_states_req(st_flow,
                                  st_line_sa,
                                  st_line_sb,
                                  st_break_len);
      break;

    case KER_MUX_ESTABLISH:
    case KER_MUX:
    case KER_MUX_DLC_CLOSING:
    case KER_MUX_CLOSING:
    case KER_MUX_CLOSED:
      break;

    default:
      TRACE_ERROR( "SIG_RX_KER_LINE_STATES_IND unexpected" );
      break;
  }
  /*
   * store new line states
   */
  dlc->lines &= ~(UART_X_RX_MASK   |
                  UART_SA_RX_MASK  |
                  UART_SB_RX_MASK  |
                  UART_ESC_RX_MASK |
                  UART_BRK_RX_MASK |
                  UART_BRKLEN_RX_MASK);
  line_states&= ~(UART_ESC_RX_MASK |
                  UART_BRK_RX_MASK |
                  UART_BRKLEN_RX_MASK);
  dlc->lines |= line_states;
} /* sig_rx_ker_line_states_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_rt_ker_timeout_t1_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_RT_KER_TIMEOUT_T1_IND
|
| Parameters  : no parameters
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_rt_ker_timeout_t1_ind ()
{
  UBYTE   i;
  T_desc2* temp_desc;
  T_DLC*  dlc;
  UBYTE   j;
  UBYTE   dlci;
  ULONG   forward;
  BOOL    continuous;

  TRACE_ISIG( "sig_rt_ker_timeout_t1_ind" );

  for( i = 0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++ )
  {
    /*
     * set dlc value
     */
    dlc = &uart_data->dlc_table[i];
    switch(dlc->connection_state)
    {
      case UART_CONNECTION_OPEN:
      case UART_CONNECTION_DISC_SENT:
        /*
         * T1 is used for non UIH Control frames
         */
        if((dlc->last_command NEQ NULL) &&
           (dlc->last_command->buffer[UART_OFFSET_CONTROL] NEQ
             UART_UIH_CONTROL_FRAME))
        {
          if(dlc->retransmissions < uart_data->ker.n2)
          {
            /*
             * retransmission of Control frame
             */
            dlc->retransmissions++;
            MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1
              + dlc->last_command->len));

            temp_desc->next = (ULONG)NULL;
            temp_desc->len  = dlc->last_command->len;
            memcpy(temp_desc->buffer,
                   dlc->last_command->buffer,
                   dlc->last_command->len);

            ker_mux_send_frame( temp_desc );
          }
          else
          {
            /*
             * maximum number of retransmissions reached
             */
            switch( GET_STATE( UART_SERVICE_KER ) )
            {
              case KER_MUX:
                /*
                 * act as on reception of a DM frame
                 */
                /*
                 * create DM frame
                 */
                MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1 + 2));
                temp_desc->next = (ULONG)NULL;
                temp_desc->len  = 2;
                memcpy(temp_desc->buffer, dlc->last_command->buffer, 2)
                ;/*lint !e419 !e420 apparent data overrun and access beyond array*/
                temp_desc->buffer[UART_OFFSET_CONTROL] = UART_DM_CONTROL_FRAME;
                /*
                 * act as on reception of a DM frame
                 */
                forward = 0;
                ker_receive_dm_frame(&forward, temp_desc);
                /*
                 * process results of analysis
                 */
                if(forward)
                {
                  for(j=0; j <= UART_MAX_NUMBER_OF_CHANNELS; j++)
                  {
                    if(j NEQ UART_CONTROL_INSTANCE)
                    {
                      /*
                       * set dlc values
                       */
                      dlc  = &uart_data->dlc_table[j];
                      dlci = dlc->dlci;
                      /*
                       * channel to close
                       */
                      if((forward & UART_FORWARD_DLC_RELEASE) &&
                         (dlc->connection_state EQ UART_CONNECTION_DEAD) &&
                         (dlci NEQ UART_DLCI_INVALID))
                      {
                        PALLOC(uart_mux_dlc_release_ind,
                               UART_MUX_DLC_RELEASE_IND);
                        /*
                         * release channel
                         */
                        ker_mux_dlc_release(j);
                        /*
                         * inform ACI about DLC release
                         */
                        uart_mux_dlc_release_ind->device = uart_data->device;
                        uart_mux_dlc_release_ind->dlci   = dlci;
                        PSEND(hCommMMI, uart_mux_dlc_release_ind);
                      }
                    }
                  }
                }
                break;

              case KER_MUX_DLC_CLOSING:
                /*
                 * act as on reception of a DM frame
                 */
                /*
                 * create DM frame
                 */
                MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1 + 2));
                temp_desc->next = (ULONG)NULL;
                temp_desc->len  = 2;
                memcpy(temp_desc->buffer, dlc->last_command->buffer, 2)
                ;/*lint !e419 !e420 apparent data overrun and access beyond array*/
                temp_desc->buffer[UART_OFFSET_CONTROL] = UART_DM_CONTROL_FRAME;
                /*
                 * act as on reception of a DM frame
                 */
                forward = 0;
                ker_receive_dm_frame(&forward, temp_desc);
                /*
                 * process results of analysis
                 */
                if(forward)
                {
                  continuous = FALSE;
                  for(j=0; j <= UART_MAX_NUMBER_OF_CHANNELS; j++)
                  {
                    if(j NEQ UART_CONTROL_INSTANCE)
                    {
                      /*
                       * set dlc values
                       */
                      dlc  = &uart_data->dlc_table[j];
                      dlci = dlc->dlci;
                      /*
                       * channel to close
                       */
                      if((forward & UART_FORWARD_DLC_RELEASE) &&
                         (dlc->connection_state EQ UART_CONNECTION_DEAD) &&
                         (dlci NEQ UART_DLCI_INVALID))
                      {
                        /*
                         * release channel
                         */
                        ker_mux_dlc_release(j);
                      }
                      if(dlc->connection_state NEQ UART_CONNECTION_DEAD)
                        continuous = TRUE;
                    }
                  }
                  /*
                   * change state if all channels are closed
                   */
                  if(continuous EQ FALSE)
                  {
                    SET_STATE( UART_SERVICE_KER, KER_MUX_CLOSING );
                    /*
                     * build and send CLD command frame:
                     */
                    ker_mux_send_close_down();
                    /*
                     * start timer
                     */
                    sig_ker_rt_start_t3_req();
                  }
                }
                break;

              case KER_MUX_CLOSING:
                /*
                 * do not care about retransmission couter
                 * retransmission stops if T3 expires
                 */
                dlc->retransmissions++;
                MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1
                  + dlc->last_command->len));

                temp_desc->next = (ULONG)NULL;
                temp_desc->len  = dlc->last_command->len;
                memcpy(temp_desc->buffer,
                       dlc->last_command->buffer,
                       dlc->last_command->len);

                ker_mux_send_frame( temp_desc );
                break;

              default:
                TRACE_ERROR( "SIG_RT_KER_TIMEOUT_T1_IND unexpected" );
                break;
            }
          }
        }
        break;

      case UART_CONNECTION_DEAD:
        break;

      default:
      {
        TRACE_EVENT_P2("Unexpected DLC connection state: %d, uart_kers.c(%d)",
                                             dlc->connection_state, __LINE__);
        break;
      }
    }
  }
  if(uart_data->ker.nr_t1)
  {
    /*
     * restart timer t1
     */
    sig_ker_rt_start_t1_req();
  }
} /* sig_rt_ker_timeout_t1_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_rt_ker_timeout_t2_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_RT_KER_TIMEOUT_T2_IND
|
|               This signal means that no response to a sent command frame
|               was received within the allowed time. It is assumed that
|               the frame has been lost and a retransmission is done if the
|               maximum number of retransmissions is not reached yet.
|
| Parameters  : no parameters
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_rt_ker_timeout_t2_ind ()
{
  UBYTE   i;
  T_desc2* temp_desc;
  T_DLC*  dlc;

  TRACE_ISIG( "sig_rt_ker_timeout_t2_ind" );

  for( i = 0; i <= UART_MAX_NUMBER_OF_CHANNELS; i++ )
  {
    /*
     * set dlc value
     */
    dlc = &uart_data->dlc_table[i];
    switch(dlc->connection_state)
    {
      case UART_CONNECTION_OPEN:
      case UART_CONNECTION_DISC_SENT:
        /*
         * T2 is only used for UIH Control frames
         */
        if((dlc->last_command NEQ NULL) &&
           (dlc->last_command->buffer[UART_OFFSET_CONTROL] EQ
             UART_UIH_CONTROL_FRAME))
        {
          if(dlc->retransmissions < uart_data->ker.n2)
          {
            /*
             * retransmission of Control frame
             */
            dlc->retransmissions++;
            MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1
              + dlc->last_command->len));

            temp_desc->next = (ULONG)NULL;
            temp_desc->len  = dlc->last_command->len;
            memcpy(temp_desc->buffer,
                   dlc->last_command->buffer,
                   dlc->last_command->len);

            ker_mux_send_frame( temp_desc );
          }
          else
          {
            /*
             * maximum number of retransmissions reached
             */
            switch( GET_STATE( UART_SERVICE_KER ) )
            {
              case KER_MUX:
              case KER_MUX_DLC_CLOSING:
                /*
                 * skip this frame and send next frame
                 */
                /*
                 * remove current UIH frame
                 */
                MFREE_DESC2(dlc->last_command);
                dlc->last_command = NULL;
                uart_data->ker.nr_t2--;
                if(dlc->next_command)
                {
                  /*
                   * transmit next command frame
                   */
                  dlc->last_command       = dlc->next_command;
                  dlc->next_command       = (T_desc2*)dlc->next_command->next;
                  dlc->last_command->next = (ULONG)NULL;

                  MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1 +
                                    dlc->last_command->len));
                  temp_desc->next = (ULONG)NULL;
                  temp_desc->len  = dlc->last_command->len;
                  memcpy(temp_desc->buffer,
                         dlc->last_command->buffer,
                         dlc->last_command->len);

                  dlc->retransmissions = 0;
                  ker_mux_send_frame(temp_desc);
                  uart_data->ker.nr_t2++;
                }
                break;

              case KER_MUX_CLOSING:
                /*
                 * do not care about retransmission couter
                 * retransmission stops if T3 expires
                 */
                dlc->retransmissions++;
                MALLOC(temp_desc, (USHORT)(sizeof( T_desc2 ) - 1
                  + dlc->last_command->len));

                temp_desc->next = (ULONG)NULL;
                temp_desc->len  = dlc->last_command->len;
                memcpy(temp_desc->buffer,
                       dlc->last_command->buffer,
                       dlc->last_command->len);

                ker_mux_send_frame( temp_desc );
                break;

              default:
                TRACE_ERROR( "SIG_RT_KER_TIMEOUT_T2_IND unexpected" );
                break;
            }
          }
        }
        break;

      case UART_CONNECTION_DEAD:
        break;

      default:
      {
        TRACE_EVENT_P2("Unexpected DLC connection state: %d, uart_kers.c(%d)",
                                             dlc->connection_state, __LINE__);
        break;
      }
    }
  }
  if(uart_data->ker.nr_t2)
  {
    /*
     * restart timer t2
     */
    sig_ker_rt_start_t2_req();
  }
} /* sig_rt_ker_timeout_t2_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_rt_ker_timeout_t3_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_RT_KER_TIMEOUT_T3_IND
|
| Parameters  : no parameters
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_rt_ker_timeout_t3_ind ()
{
  TRACE_ISIG( "sig_rt_ker_timeout_t3_ind" );

  switch( GET_STATE( UART_SERVICE_KER ) )
  {
    case KER_MUX_ESTABLISH:
    case KER_MUX_CLOSING:
      SET_STATE( UART_SERVICE_KER, KER_MUX_CLOSED );
      /*
       * stop timers and
       * remove all DLC instances
       */
      ker_mux_close_down();
      if(uart_data->ker.tx_data_desc EQ NULL)
      {
        uart_data->ker.received_prim|= UART_MUX_CLOSE_REQ_MASK;

        if(uart_data->ker.flush_state EQ UART_KER_NOT_FLUSHING)
        {
          uart_data->ker.flush_state = UART_KER_TX_FLUSH;
          sig_ker_tx_flush_req();
        }
      }
      break;

    default:
      TRACE_ERROR( "SIG_RT_KER_TIMEOUT_T3_IND unexpected" );
      break;
  }
} /* sig_rt_ker_timeout_t3_ind() */


/*
+------------------------------------------------------------------------------
| Function    : sig_rt_ker_timeout_tesd_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_RT_KER_TIMEOUT_TESD_IND
|
|               This signal means that the trailing guard period has completed.
|
| Parameters  : no parameters
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_rt_ker_timeout_tesd_ind ()
{
  UBYTE   i;

  TRACE_ISIG( "sig_rt_ker_timeout_tesd_ind" );

  switch( GET_STATE( UART_SERVICE_KER ) )
  {
    case KER_READY:
    case KER_MUX:
      for( i = 0; i < UART_MAX_NUMBER_OF_CHANNELS; i++ )
      { /*
         * set current dtx
         */
        uart_data->dtx = &uart_data->dtx_base[i];
        sig_ker_dtx_timeout_tesd_req();
      }
      break;

    default:
      TRACE_ERROR( "SIG_RT_KER_TIMEOUT_TESD_IND unexpected" );
      break;
  }
} /* sig_rt_ker_timeout_tesd_ind() */