FreeCalypso > hg > fc-tourmaline
diff src/g23m-aci/uart/uart_kers.c @ 1:fa8dc04885d8
src/g23m-*: import from Magnetite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:25:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/g23m-aci/uart/uart_kers.c Fri Oct 16 06:25:50 2020 +0000 @@ -0,0 +1,2473 @@ +/* ++----------------------------------------------------------------------------- +| 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() */ +