FreeCalypso > hg > freecalypso-sw
changeset 853:ae254ffeaec3
AT command interface works!
The cause of the breakage was the same Nucleus API issue with NU_Create_Timer()
which we encountered at the very beginning of this project with Riviera timers:
the code in uartfax.c from TCS211 was passing 0 as the initial dummy value for
the timer duration, and our FreeNucleus version doesn't like it. The fix is
the same: pass 1 as the initial dummy value instead.
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Thu, 30 Apr 2015 01:46:26 +0000 |
parents | fc713944bd1c |
children | acc9e473e93f |
files | gsm-fw/gpf/conf/gsmcomp.c gsm-fw/serial/debug-chases/serialswitch.c gsm-fw/serial/debug-chases/uartfax.c gsm-fw/serial/uartfax.c |
diffstat | 4 files changed, 8600 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- a/gsm-fw/gpf/conf/gsmcomp.c Sun Apr 26 03:06:32 2015 +0000 +++ b/gsm-fw/gpf/conf/gsmcomp.c Thu Apr 30 01:46:26 2015 +0000 @@ -428,22 +428,26 @@ /* * Partitions pool configuration for test interface communication + * + * FreeCalypso: I bumped the configuration up from what TI had in their + * (likely unmaintained) gsmcomp.c as I expect we'll be doing a lot of + * debugging. - Space Falcon */ -#define TESTPOOL_0_PARTITIONS 1 /* 10 */ -#define TESTPOOL_1_PARTITIONS 15 /* 50 */ -#define TESTPOOL_2_PARTITIONS 0 /* 2 */ +#define TESTPOOL_0_PARTITIONS 10 /* was 1 */ +#define TESTPOOL_1_PARTITIONS 50 /* was 15 */ +#define TESTPOOL_2_PARTITIONS 2 /* was 0 */ #define TSTSND_QUEUE_ENTRIES (TESTPOOL_0_PARTITIONS+TESTPOOL_1_PARTITIONS+TESTPOOL_2_PARTITIONS) #define TSTRCV_QUEUE_ENTRIES 50 -#define TEST_PARTITION_0_SIZE 16 /* 80 */ +#define TEST_PARTITION_0_SIZE 80 /* was 16 */ #ifdef _TARGET_ #define TEST_PARTITION_1_SIZE 160 #else #define TEST_PARTITION_1_SIZE 260 #endif /* else, #ifdef _TARGET_ */ -#define TEST_PARTITION_2_SIZE 0 /* 1600 */ +#define TEST_PARTITION_2_SIZE 1600 const USHORT TST_SndQueueEntries = TSTSND_QUEUE_ENTRIES; const USHORT TST_RcvQueueEntries = TSTRCV_QUEUE_ENTRIES; @@ -453,10 +457,13 @@ char pool21 [ POOL_SIZE(TESTPOOL_1_PARTITIONS,ALIGN_SIZE(TEST_PARTITION_1_SIZE)) ] __attribute__ ((section ("ext.ram"))); +char pool22 [ POOL_SIZE(TESTPOOL_2_PARTITIONS,ALIGN_SIZE(TEST_PARTITION_2_SIZE)) ] __attribute__ ((section ("ext.ram"))); + const T_FRM_PARTITION_POOL_CONFIG test_grp_config[] = { { TESTPOOL_0_PARTITIONS, ALIGN_SIZE(TEST_PARTITION_0_SIZE), &pool20 }, { TESTPOOL_1_PARTITIONS, ALIGN_SIZE(TEST_PARTITION_1_SIZE), &pool21 }, + { TESTPOOL_2_PARTITIONS, ALIGN_SIZE(TEST_PARTITION_2_SIZE), &pool22 }, { 0 , 0 , NULL } };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/serial/debug-chases/serialswitch.c Thu Apr 30 01:46:26 2015 +0000 @@ -0,0 +1,3416 @@ +/******************************************************************************* + * + * SERIALSWITCH.C + * + * This module allows managing the use of the serial ports of TI GSM Evaluation + * Boards. + * An application may have to send several serial data flows. The board on which + * the application is running may have one or several devices. The purpose of + * this module is to establish connections between the serial data flows and the + * serial devices at runtime, when the application is started. + * + * (C) Texas Instruments 1999 - 2003 + * + ******************************************************************************/ + +#define __SERIALSWITCH_C__ + +#define __STANDARD_H__ /* Avoid to define UBYTE, SYS_UWORD16 and UINT32. */ + +#include "../include/config.h" +#include "../include/sys_types.h" +#include "../riviera/rv/rv_general.h" +#include "../riviera/rvf/rvf_api.h" +#include "../nucleus/nucleus.h" + +#include "serialswitch.h" + +#include "uart.h" +#include "uartfax.h" + +#include "../bsp/mem.h" + +#include <string.h> /* needed for memcmp & memset */ + +#if SERIAL_DYNAMIC_SWITCH + #include "ffs/ffs.h" + #include "rvf/rvf_api.h" + #include "inth/iq.h" + #include "rvt/rvt_def_i.h" /* needed for Riviera/Layer1 Trace's callback function */ +#endif + +#if defined(BTEMOBILE) + #include "hci_ser.h" +#endif + +#define DUMMY_DEVICE (0) + +#define IIR (0x02) /* UART interrupt ident. register - Read only */ +#define SCR (0x10) /* UART suppl. control register - Read/Write */ +#define SSR (0x11) /* UART suppl. status register - Read only */ + +/* + * Interrupt identification register. + * Bit 0 is set to 0 if an IT is pending. + * Bits 1 and 2 are used to identify the IT. + */ + +#define IIR_BITS_USED (0x07) +#define IT_NOT_PENDING (0x01) + +/* + * Supplementary Control Register + */ + +#define RX_CTS_WAKE_UP_ENABLE_BIT (4) + +/* + * Supplementary Status Register + */ + +#define RX_CTS_WAKE_UP_STS (0x02) /* Wake-up interrupt occurred */ + +/* + * This macro allows to read an UART register. + */ + +#define READ_UART_REGISTER(UART,REG) \ + *((volatile SYS_UWORD8 *) ((UART)->base_address + (REG))) + + +/* + * This macro allows to disable the UART's wake-up interrupt. + */ + +#define DISABLE_WAKE_UP_INTERRUPT(UART) \ + *((volatile SYS_UWORD8 *) ((UART)->base_address + SCR)) &= \ + ~(1 << (RX_CTS_WAKE_UP_ENABLE_BIT)); + +/* + * Wake-up time duration in seconds and in number of TDMAs. + * 1 TDMA = (6 / 1300) s = 0.004615 s (= 4.615 ms). + */ + +#define WAKE_UP_TIME_DURATION (10) /* 10 seconds */ +#define WAKE_UP_TIME_IN_TDMA (WAKE_UP_TIME_DURATION * 1300 / 6) + + +/* + * Global uartswitch variable as read from FFS. + * It is supposed that NUMBER_OF_TR_UART, NUMBER_OF_FD_UART + * and NUMBER_OF_BT_UART have the same values. + */ + +#define DUMMY ('0') +#define G23_PANEL ('G') +#define RIVIERA_TRACE_MUX ('R') +#define FD_AT_COMMAND ('D') +#define BLUETOOTH_HCI ('B') + +#if (CHIPSET == 12) + char ser_cfg_info[NUMBER_OF_TR_UART] = {DUMMY, DUMMY, DUMMY}; +#else + char ser_cfg_info[NUMBER_OF_TR_UART] = {DUMMY, DUMMY}; +#endif +static SYS_UWORD16 serial_cfg = 0x0048; /* All dummies */ + +#if SERIAL_DYNAMIC_SWITCH + /* + * Global variables used for Dynamic Switch. + */ + + static char ser_new_cfg[NUMBER_OF_TR_UART] = {DUMMY, DUMMY}; + const static char uart_config_file[] = "/sys/uartswitch"; + static SYS_BOOL dynamic_switch = 0; + + /* Import Serial Info structure. */ + extern T_AppliSerialInfo appli_ser_cfg_info; +#endif + +/* + * Types of flows supported. + */ + +typedef enum { + TRACE_FLOW, + FAX_DATA_FLOW, + BLUETOOTH_HCI_FLOW +} t_flow_type; + +/* + * For each serial data flow, a set of function pointers allows calling the + * functions associated to a serial device. + */ + +typedef struct s_tr_functions { + + T_tr_UartId device; + + void (*tr_Init) (T_tr_UartId device, + T_tr_Baudrate baudrate, + void (callback_function (void))); + + SYS_UWORD32 (*tr_ReadNChars) (T_tr_UartId device, + char *buffer, + SYS_UWORD32 chars_to_read); + + SYS_UWORD32 (*tr_ReadNBytes) (T_tr_UartId device, + char *buffer, + SYS_UWORD32 chars_to_read, + SYS_BOOL *eof_detected); + + SYS_UWORD32 (*tr_WriteNChars) (T_tr_UartId device, + char *buffer, + SYS_UWORD32 chars_to_write); + + SYS_UWORD32 (*tr_EncapsulateNChars) (T_tr_UartId device, + char *buffer, + SYS_UWORD32 chars_to_write); + + SYS_UWORD32 (*tr_WriteNBytes) (T_tr_UartId device, + SYS_UWORD8 *buffer, + SYS_UWORD32 chars_to_write); + + void (*tr_WriteChar) (T_tr_UartId device, + char character); + + void (*tr_WriteString) (T_tr_UartId device, + char *buffer); + + SYS_BOOL (*tr_EnterSleep) (T_tr_UartId device); + + void (*tr_WakeUp) (T_tr_UartId device); + +} t_tr_functions; + +/* + * Set of function pointers for fax & data functions. + */ + +typedef struct s_fd_functions { + + T_fd_UartId device; + + T_FDRET (*fd_Initialize) (T_fd_UartId device); + + T_FDRET (*fd_Enable) (T_fd_UartId device, + SYS_BOOL enable); + + T_FDRET (*fd_SetComPar) (T_fd_UartId device, + T_baudrate baudrate, + T_bitsPerCharacter bpc, + T_stopBits sb, + T_parity parity); + + T_FDRET (*fd_SetBuffer) (T_fd_UartId device, + SYS_UWORD16 bufSize, + SYS_UWORD16 rxThreshold, + SYS_UWORD16 txThreshold); + + T_FDRET (*fd_SetFlowCtrl) (T_fd_UartId device, + T_flowCtrlMode fcMode, + SYS_UWORD8 XON, + SYS_UWORD8 XOFF); + + T_FDRET (*fd_SetEscape) (T_fd_UartId device, + SYS_UWORD8 escChar, + SYS_UWORD16 guardPeriod); + + T_FDRET (*fd_InpAvail) (T_fd_UartId device); + + T_FDRET (*fd_OutpAvail) (T_fd_UartId device); + + T_FDRET (*fd_EnterSleep) (T_fd_UartId device); + + T_FDRET (*fd_WakeUp) (T_fd_UartId device); + + T_FDRET (*fd_ReadData) (T_fd_UartId device, + T_suspendMode suspend, + void (readOutFunc (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 nsource, + SYS_UWORD8 *source[], + SYS_UWORD16 size[], + SYS_UWORD32 state))); + + T_FDRET (*fd_WriteData) (T_fd_UartId device, + T_suspendMode suspend, + void (writeInFunc (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 ndest, + SYS_UWORD8 *dest[], + SYS_UWORD16 size[]))); + + T_FDRET (*fd_StopRec) (T_fd_UartId device); + + T_FDRET (*fd_StartRec) (T_fd_UartId device); + + T_FDRET (*fd_GetLineState) (T_fd_UartId device, + SYS_UWORD32 *state); + + T_FDRET (*fd_SetLineState) (T_fd_UartId device, + SYS_UWORD32 state, + SYS_UWORD32 mask); + + T_FDRET (*fd_CheckXEmpty) (T_fd_UartId device); + +} t_fd_functions; + +#ifdef BTEMOBILE + /* + * Set of function pointers for Bluetooth HCI functions. + */ + + typedef struct s_bt_functions { + + T_bt_UartId device; + + T_HCI_RET (*bt_Init) (T_bt_UartId uart_device); + + T_HCI_RET (*bt_Start) (void); + + T_HCI_RET (*bt_Stop) (void); + + T_HCI_RET (*bt_Kill) (void); + + T_HCI_RET (*bt_SetBaudrate) (UINT8 baudrate); + + T_HCI_RET (*bt_TransmitPacket) (void *uart_tx_buffer); + + SYS_BOOL (*bt_EnterSleep) (void); + + void (*bt_WakeUp) (void); + + } t_bt_functions; +#endif + +/* + * Prototypes of dummy functions. + * Dummy functions for Trace. + */ + +static void dummy_tr_Init (T_tr_UartId device, + T_tr_Baudrate baudrate, + void (callback_function (void))); + +static SYS_UWORD32 dummy_tr_ReadNChars (T_tr_UartId device, + char *buffer, + SYS_UWORD32 chars_to_read); + +static SYS_UWORD32 dummy_tr_ReadNBytes (T_tr_UartId device, + char *buffer, + SYS_UWORD32 chars_to_read, + SYS_BOOL *eof_detected); + +static SYS_UWORD32 dummy_tr_WriteNChars (T_tr_UartId device, + char *buffer, + SYS_UWORD32 chars_to_write); + +static SYS_UWORD32 dummy_tr_EncapsulateNChars (T_tr_UartId device, + char *buffer, + SYS_UWORD32 chars_to_write); + +static SYS_UWORD32 dummy_tr_WriteNBytes (T_tr_UartId device, + SYS_UWORD8 *buffer, + SYS_UWORD32 chars_to_write); + +static void dummy_tr_WriteChar (T_tr_UartId device, + char character); + +static void dummy_tr_WriteString (T_tr_UartId device, + char *buffer); + +static SYS_BOOL dummy_tr_EnterSleep (T_tr_UartId device); + +static void dummy_tr_WakeUp (T_tr_UartId device); + +/* + * Dummy functions for Fax & Data. + */ + +static T_FDRET dummy_fd_Init (T_fd_UartId device); + +static T_FDRET dummy_fd_Enable (T_fd_UartId device, + SYS_BOOL enable); + +static T_FDRET dummy_fd_SetComPar (T_fd_UartId device, + T_baudrate baudrate, + T_bitsPerCharacter bpc, + T_stopBits sb, + T_parity parity); + +static T_FDRET dummy_fd_SetBuffer (T_fd_UartId device, + SYS_UWORD16 bufSize, + SYS_UWORD16 rxThreshold, + SYS_UWORD16 txThreshold); + +static T_FDRET dummy_fd_SetFlowCtrl (T_fd_UartId device, + T_flowCtrlMode fcMode, + SYS_UWORD8 XON, + SYS_UWORD8 XOFF); + +static T_FDRET dummy_fd_SetEscape (T_fd_UartId device, + SYS_UWORD8 escChar, + SYS_UWORD16 guardPeriod); + +static T_FDRET dummy_fd_InpAvail (T_fd_UartId device); + +static T_FDRET dummy_fd_OutpAvail (T_fd_UartId device); + +static T_FDRET dummy_fd_EnterSleep (T_fd_UartId device); + +static T_FDRET dummy_fd_WakeUp (T_fd_UartId device); + +static T_FDRET dummy_fd_ReadData (T_fd_UartId device, + T_suspendMode suspend, + void (readOutFunc (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 nsource, + SYS_UWORD8 *source[], + SYS_UWORD16 size[], + SYS_UWORD32 state))); + +static T_FDRET dummy_fd_WriteData (T_fd_UartId device, + T_suspendMode suspend, + void (writeInFunc (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 ndest, + SYS_UWORD8 *dest[], + SYS_UWORD16 size[]))); + +static T_FDRET dummy_fd_StopRec (T_fd_UartId device); + +static T_FDRET dummy_fd_StartRec (T_fd_UartId device); + +static T_FDRET dummy_fd_GetLineState (T_fd_UartId device, + SYS_UWORD32 *state); + +static T_FDRET dummy_fd_SetLineState (T_fd_UartId device, + SYS_UWORD32 state, + SYS_UWORD32 mask); + +static T_FDRET dummy_fd_CheckXEmpty (T_fd_UartId device); + +#ifdef BTEMOBILE + /* + * Dummy functions for Bluetooth HCI. + */ + + static T_HCI_RET dummy_bt_Init (T_bt_UartId uart_device); + + static T_HCI_RET dummy_bt_Start (void); + + static T_HCI_RET dummy_bt_Stop (void); + + static T_HCI_RET dummy_bt_Kill (void); + + static T_HCI_RET dummy_bt_SetBaudrate (UINT8 baudrate); + + static T_HCI_RET dummy_bt_TransmitPacket (void *uart_tx_buffer); + + static SYS_BOOL dummy_bt_EnterSleep (void); + + static void dummy_bt_WakeUp (void); + +#endif + +/* + * Constants tables representing the various possible configurations + * for Trace, Fax & Data and Bluetooth HCI according to the different devices. + * Constant table for Trace using no device. + */ + +static const t_tr_functions dummy_trace = { + + DUMMY_DEVICE, + dummy_tr_Init, + dummy_tr_ReadNChars, + dummy_tr_ReadNBytes, + dummy_tr_WriteNChars, + dummy_tr_EncapsulateNChars, + dummy_tr_WriteNBytes, + dummy_tr_WriteChar, + dummy_tr_WriteString, + dummy_tr_EnterSleep, + dummy_tr_WakeUp +}; + +/* + * Constant table for Trace using UART IrDA. + */ + +static const t_tr_functions uart_irda_trace = { + + UA_UART_0, + UA_Init, + UA_ReadNChars, + UA_ReadNBytes, + UA_WriteNChars, + UA_EncapsulateNChars, + UA_WriteNBytes, + UA_WriteChar, + UA_WriteString, + UA_EnterSleep, + UA_WakeUp +}; + +/* + * Constant table for Trace using UART Modem. + */ + +static const t_tr_functions uart_modem_trace = { + + UA_UART_1, + UA_Init, + UA_ReadNChars, + UA_ReadNBytes, + UA_WriteNChars, + UA_EncapsulateNChars, + UA_WriteNBytes, + UA_WriteChar, + UA_WriteString, + UA_EnterSleep, + UA_WakeUp +}; + +#if (CHIPSET == 12) + /* + * Constant table for Trace using UART Modem2. + */ + + static const t_tr_functions uart_modem2_trace = { + + UA_UART_2, + UA_Init, + UA_ReadNChars, + UA_ReadNBytes, + UA_WriteNChars, + UA_EncapsulateNChars, + UA_WriteNBytes, + UA_WriteChar, + UA_WriteString, + UA_EnterSleep, + UA_WakeUp + }; +#endif + +/* + * Constant table for Fax & Data using no device. + */ + +static const t_fd_functions dummy_fax_data = { + + DUMMY_DEVICE, + dummy_fd_Init, + dummy_fd_Enable, + dummy_fd_SetComPar, + dummy_fd_SetBuffer, + dummy_fd_SetFlowCtrl, + dummy_fd_SetEscape, + dummy_fd_InpAvail, + dummy_fd_OutpAvail, + dummy_fd_EnterSleep, + dummy_fd_WakeUp, + dummy_fd_ReadData, + dummy_fd_WriteData, + dummy_fd_StopRec, + dummy_fd_StartRec, + dummy_fd_GetLineState, + dummy_fd_SetLineState, + dummy_fd_CheckXEmpty +}; + +/* + * Constant table for Fax & Data using UART Modem. + */ + +#if CONFIG_FDMODEM +static const t_fd_functions uart_modem_fax_data = { + + UAF_UART_1, + UAF_Init, + UAF_Enable, + UAF_SetComPar, + UAF_SetBuffer, + UAF_SetFlowCtrl, + UAF_SetEscape, + UAF_InpAvail, + UAF_OutpAvail, + UAF_EnterSleep, + UAF_WakeUp, + UAF_ReadData, + UAF_WriteData, + UAF_StopRec, + UAF_StartRec, + UAF_GetLineState, + UAF_SetLineState, + UAF_CheckXEmpty +}; +#endif + +#ifdef BTEMOBILE + /* + * Constant table for BT HCI using no device. + */ + + static const t_bt_functions dummy_bt_hci = { + + DUMMY_DEVICE, + dummy_bt_Init, + dummy_bt_Start, + dummy_bt_Stop, + dummy_bt_Kill, + dummy_bt_SetBaudrate, + dummy_bt_TransmitPacket, + dummy_bt_EnterSleep, + dummy_bt_WakeUp + }; + + /* + * Constant table for BT HCI using UART IrDA. + */ + + static const t_bt_functions uart_irda_bt_hci = { + + UABT_UART_0, + hciu_init, + hciu_start, + hciu_stop, + hciu_kill, + hciu_set_baudrate, + hciu_transmit_packet, + hciu_enter_sleep, + hciu_wakeup + }; + + /* + * Constant table for BT HCI using UART Modem. + */ + + static const t_bt_functions uart_modem_bt_hci = { + + UABT_UART_1, + hciu_init, + hciu_start, + hciu_stop, + hciu_kill, + hciu_set_baudrate, + hciu_transmit_packet, + hciu_enter_sleep, + hciu_wakeup + }; + + #if (CHIPSET == 12) + /* + * Constant table for BT HCI using UART Modem2. + */ + + static const t_bt_functions uart_modem2_bt_hci = { + + UABT_UART_2, + hciu_init, + hciu_start, + hciu_stop, + hciu_kill, + hciu_set_baudrate, + hciu_transmit_packet, + hciu_go_to_sleep, + hciu_wakeup + }; + #endif +#endif + +#if SERIAL_DYNAMIC_SWITCH + /* + * Structure used to store initialization parameters related to the AT-Cmd/F&D flow. + * Numbers of paramaters (in case of multiple calls) have been figured out from + * Condat AT-Command/F&D flow initialization. + */ + + typedef struct s_data_flow { + + /* + * Parameters related to SER_fd_SetComPar (2 calls) + */ + T_baudrate baudrate[2]; + T_bitsPerCharacter bpc[2]; + T_stopBits sb[2]; + T_parity parity[2]; + + /* + * Parameters related to SER_fd_SetBuffer + */ + SYS_WORD16 bufSize; + SYS_WORD16 rxThreshold; + SYS_WORD16 txThreshold; + + /* + * Parameters related to SER_fd_SetFlowCtrl (2 calls) + */ + T_flowCtrlMode fcMode[2]; + SYS_UWORD8 XON[2]; + SYS_UWORD8 XOFF[2]; + + /* + * Parameters related to SER_fd_SetEscape (2 calls) + */ + SYS_UWORD8 escChar[2]; + SYS_UWORD16 guardPeriod[2]; + + /* + * Parameters related to SER_fd_SetLineState (4 calls) + */ + SYS_UWORD32 state[4]; + SYS_UWORD32 mask[4]; + + /* + * Parameters related to SER_fd_ReadData + */ + T_suspendMode suspend_rd; + void (*readOutFunc) (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 nsource, + SYS_UWORD8 *source[], + SYS_UWORD16 size[], + SYS_UWORD32 state); + /* + * Parameters related to SER_fd_WriteData + */ + T_suspendMode suspend_wr; + void (*writeInFunc) (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 ndest, + SYS_UWORD8 *dest[], + SYS_UWORD16 size[]); + + } t_data_flow; +#endif /* (defined BTEMOBILE && (CHIPSET != 12)) */ + +/* + * UART structure used for UARTs. + */ + +typedef struct s_uart { + + SYS_UWORD32 base_address; + SYS_BOOL device_used; + SYS_BOOL deep_sleep_set_up; + t_flow_type flow_type; + SYS_WORD16 flow_id; + void (*interrupt_handler) (int uart_id, + SYS_UWORD8 interrupt_status); + +} t_uart; + +static const t_tr_functions *tr_functions[SER_MAX_NUMBER_OF_FLOWS]; +static const t_fd_functions *fd_functions; + +#ifdef BTEMOBILE + static const t_bt_functions *bt_functions; +#endif + +#if SERIAL_DYNAMIC_SWITCH + static SYS_BOOL uart_fd_initialized = 0; +#endif + +static SYS_UWORD8 fd_buffer[FD_MAX_BUFFER_SIZE]; +static SYS_BOOL fd_driver_enabled; + +#if SERIAL_DYNAMIC_SWITCH + static t_data_flow data_flow_parameters; +#else + static SYS_WORD16 bufSize; +#endif + +#if SERIAL_DYNAMIC_SWITCH + /* + * Variables used to count calls to SER_fd_XXX functions. + */ + + static SYS_UWORD8 fd_UAF_SetBuffer = 0; + static SYS_UWORD8 fd_UAF_SetEscape = 0; + static SYS_UWORD8 fd_UAF_SetComPar = 0; + static SYS_UWORD8 fd_UAF_SetFlowCtrl = 0; + static SYS_UWORD8 fd_UAF_ReadData = 0; + static SYS_UWORD8 fd_UAF_SetLineState = 0; + static SYS_UWORD8 fd_UAF_WriteData = 0; +#endif + +/* + * Timer used for duration control when UARTs are waked up by an interrupt or + * each time any new incoming characters are received; This timer prevents the + * system to enter deep sleep mode. + */ + +static NU_TIMER uart_sleep_timer; + SYS_BOOL uart_sleep_timer_enabled; + +/* + * HISR used to reset and restart the sleep timer from an UART use by a Trace + * flow in case of incoming characters. + */ + +#define TIMER_HISR_PRIORITY (2) +#define TIMER_HISR_STACK_SIZE (512) /* Bytes. */ + +static NU_HISR timer_hisr_ctrl_block; +static char timer_hisr_stack[TIMER_HISR_STACK_SIZE]; + +/* + * For next arrays, it is supposed that NUMBER_OF_TR_UART, NUMBER_OF_FD_UART + * and NUMBER_OF_BT_UART have the same values. + * An index on an internal uart for trace, fax & data or bluetooth hci reffers + * to the same uart device. + */ + +static t_uart int_uart[NUMBER_OF_TR_UART]; + +#if ((CHIPSET == 2) || (CHIPSET == 3)) + static SYS_UWORD32 uart_spurious_interrupts; +#elif ((CHIPSET == 4) || (CHIPSET == 5) || (CHIPSET == 6) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12)) + static SYS_UWORD32 uart_modem_spurious_interrupts; + static SYS_UWORD32 uart_irda_spurious_interrupts; +#endif +#if (CHIPSET == 12) + static SYS_UWORD32 uart_modem2_spurious_interrupts; +#endif + +static const SYS_UWORD32 uart_base_address[NUMBER_OF_TR_UART] = +{ + MEM_UART_IRDA, + MEM_UART_MODEM + #if (CHIPSET == 12) + , MEM_UART_MODEM2 + #endif +}; + + +/******************************************************************************* + * + * dummy_tr_Init + * + * Purpose: No action. + * + * Parameters: See SER_tr_Init. + * + * Return: none + * + ******************************************************************************/ + +static void +dummy_tr_Init (T_tr_UartId device, + T_tr_Baudrate baudrate, + void (callback_function (void))) +{ + /* + * No action. + */ +} + +/******************************************************************************* + * + * dummy_tr_ReadNChars + * + * Purpose: No action. + * + * Parameters: See SER_tr_ReadNChars. + * + * Return: 0 + * + ******************************************************************************/ + +static SYS_UWORD32 +dummy_tr_ReadNChars (T_tr_UartId device, + char *buffer, + SYS_UWORD32 chars_to_read) +{ + return (0); +} + +/******************************************************************************* + * + * dummy_tr_ReadNBytes + * + * Purpose: No action. + * + * Parameters: See SER_tr_ReadNBytes. + * + * Return: 0 + * + ******************************************************************************/ + +static SYS_UWORD32 +dummy_tr_ReadNBytes (T_tr_UartId device, + char *buffer, + SYS_UWORD32 chars_to_read, + SYS_BOOL *eof_detected) +{ + return (0); +} + +/******************************************************************************* + * + * dummy_tr_WriteNChars + * + * Purpose: No action. + * + * Parameters: See SER_tr_WriteNChars. + * + * Return: The number of character to write. + * + ******************************************************************************/ + +static SYS_UWORD32 +dummy_tr_WriteNChars (T_tr_UartId device, + char *buffer, + SYS_UWORD32 chars_to_write) +{ + return (chars_to_write); +} + +/******************************************************************************* + * + * dummy_tr_EncapsulateNChars + * + * Purpose: No action. + * + * Parameters: See SER_tr_EncapsulateNChars. + * + * Return: The number of character to write. + * + ******************************************************************************/ + +static SYS_UWORD32 +dummy_tr_EncapsulateNChars (T_tr_UartId device, + char *buffer, + SYS_UWORD32 chars_to_write) +{ + return (chars_to_write); +} + +/******************************************************************************* + * + * dummy_tr_WriteNBytes + * + * Purpose: No action. + * + * Parameters: See SER_tr_WriteNBytes. + * + * Return: The number of byte to write. + * + ******************************************************************************/ + +static SYS_UWORD32 +dummy_tr_WriteNBytes (T_tr_UartId device, + SYS_UWORD8 *buffer, + SYS_UWORD32 chars_to_write) +{ + return (chars_to_write); +} + +/******************************************************************************* + * + * dummy_tr_WriteChar + * + * Purpose: No action. + * + * Parameters: See SER_tr_WriteChar. + * + * Return: none + * + ******************************************************************************/ + +static void +dummy_tr_WriteChar (T_tr_UartId device, + char character) +{ + /* + * No action. + */ +} + +/******************************************************************************* + * + * dummy_tr_WriteString + * + * Purpose: No action. + * + * Parameters: See SER_tr_WriteString. + * + * Return: none + * + ******************************************************************************/ + +static void +dummy_tr_WriteString (T_tr_UartId device, + char *buffer) +{ + /* + * No action. + */ +} + +/******************************************************************************* + * + * dummy_tr_EnterSleep + * + * Purpose: No action. + * + * Parameters: See SER_tr_EnterSleep. + * + * Return: 1 + * + ******************************************************************************/ + +static SYS_BOOL +dummy_tr_EnterSleep (T_tr_UartId device) +{ + return (1); +} + +/******************************************************************************* + * + * dummy_tr_WakeUp + * + * Purpose: No action. + * + * Parameters: See SER_tr_WakeUp. + * + * Return: none + * + ******************************************************************************/ + +static void +dummy_tr_WakeUp (T_tr_UartId device) +{ + /* + * No action. + */ +} + +/******************************************************************************* + * + * dummy_fd_Init + * + * Purpose: Sets the size of the circular buffer to the maximum value and the + * state of the driver to 'disabled'. + * + * Parameters: See SER_fd_Init. + * + * Return: FD_OK: Successful operation. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_Init (T_fd_UartId device) +{ + #if SERIAL_DYNAMIC_SWITCH + data_flow_parameters.bufSize = FD_MAX_BUFFER_SIZE; + #else + bufSize = FD_MAX_BUFFER_SIZE; + #endif + fd_driver_enabled = 0; + + return (FD_OK); +} + +/******************************************************************************* + * + * dummy_fd_Enable + * + * Purpose: Stores the state of the driver. + * + * Parameters: See SER_fd_Enable. + * + * Return: FD_OK: Successful operation. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_Enable (T_fd_UartId device, + SYS_BOOL enable) +{ + fd_driver_enabled = enable; + + return (FD_OK); +} + +/******************************************************************************* + * + * dummy_fd_SetComPar + * + * Purpose: No action. + * + * Parameters: See SER_fd_SetComPar. + * + * Return: FD_OK: Successful operation. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_SetComPar (T_fd_UartId device, + T_baudrate baudrate, + T_bitsPerCharacter bpc, + T_stopBits sb, + T_parity parity) +{ + return (FD_OK); +} + +/******************************************************************************* + * + * dummy_fd_SetBuffer + * + * Purpose: No action. + * + * Parameters: See SER_fd_SetBuffer. + * + * Return: FD_OK: Successful operation. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_SetBuffer (T_fd_UartId device, + SYS_UWORD16 bufSize, + SYS_UWORD16 rxThreshold, + SYS_UWORD16 txThreshold) +{ + return (FD_OK); +} + +/******************************************************************************* + * + * dummy_fd_SetFlowCtrl + * + * Purpose: No action. + * + * Parameters: See SER_fd_SetFlowCtrl. + * + * Return: FD_OK: Successful operation. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_SetFlowCtrl (T_fd_UartId device, + T_flowCtrlMode fcMode, + SYS_UWORD8 XON, + SYS_UWORD8 XOFF) +{ + return (FD_OK); +} + +/******************************************************************************* + * + * dummy_fd_SetEscape + * + * Purpose: No action. + * + * Parameters: See SER_fd_SetEscape. + * + * Return: FD_OK: Successful operation. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_SetEscape (T_fd_UartId device, + SYS_UWORD8 escChar, + SYS_UWORD16 guardPeriod) +{ + return (FD_OK); +} + +/******************************************************************************* + * + * dummy_fd_InpAvail + * + * Purpose: No action. + * + * Parameters: See SER_fd_InpAvail. + * + * Return: The size of the circular buffer. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_InpAvail (T_fd_UartId device) +{ + #if SERIAL_DYNAMIC_SWITCH + return (data_flow_parameters.bufSize); + #else + return (bufSize); + #endif +} + +/******************************************************************************* + * + * dummy_fd_OutpAvail + * + * Purpose: No action. + * + * Parameters: See SER_fd_OutpAvail. + * + * Return: The size of the circular buffer. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_OutpAvail (T_fd_UartId device) +{ + #if SERIAL_DYNAMIC_SWITCH + return (data_flow_parameters.bufSize); + #else + return (bufSize); + #endif +} + +/******************************************************************************* + * + * dummy_fd_EnterSleep + * + * Purpose: No action. + * + * Parameters: See SER_tr_EnterSleep. + * + * Return: 1 + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_EnterSleep (T_fd_UartId device) +{ + return (1); +} + +/******************************************************************************* + * + * dummy_fd_WakeUp + * + * Purpose: No action. + * + * Parameters: See SER_tr_WakeUp. + * + * Return: FD_OK: Successful operation. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_WakeUp (T_fd_UartId device) +{ + return (FD_OK); +} + +/******************************************************************************* + * + * dummy_fd_ReadData + * + * Purpose: No action. + * + * Parameters: See SER_fd_ReadData. + * + * Return: 0 if the suspend parameter is set to 'sm_noSuspend'. + * FD_SUSPENDED if the suspend parameter is set to 'sm_suspend'. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_ReadData (T_fd_UartId device, + T_suspendMode suspend, + void (readOutFunc (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 nsource, + SYS_UWORD8 *source[], + SYS_UWORD16 size[], + SYS_UWORD32 state))) +{ + T_FDRET result; + + if (suspend == sm_noSuspend) + result = 0; + else + result = FD_SUSPENDED; + + return (result); +} + +/******************************************************************************* + * + * dummy_fd_WriteData + * + * Purpose: The user's function is called with: + * - cldFromIrq = 0 + * - ndest = 1 + * - dest[0] is a SYS_UWORD8 pointer on the beginning address of a local + * buffer + * - size[0] is set to data_flow_parameters.bufSize. + * + * Parameters: See SER_fd_WriteData. + * + * Return: The number of bytes written in the local buffer. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_WriteData (T_fd_UartId device, + T_suspendMode suspend, + void (writeInFunc (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 ndest, + SYS_UWORD8 *dest[], + SYS_UWORD16 size[]))) +{ + T_reInstMode dummyInstall; + SYS_UWORD8 *destination[2]; + SYS_UWORD16 buffer_size[2]; + + destination[0] = &(fd_buffer[0]); + #if SERIAL_DYNAMIC_SWITCH + buffer_size[0] = data_flow_parameters.bufSize; + #else + buffer_size[0] = bufSize; + #endif + + (*writeInFunc) (0, &dummyInstall, 1, &(destination[0]), &(buffer_size[0])); + + #if SERIAL_DYNAMIC_SWITCH + return ((T_FDRET) (data_flow_parameters.bufSize - buffer_size[0])); + #else + return ((T_FDRET) (bufSize - buffer_size[0])); + #endif +} + +/******************************************************************************* + * + * dummy_fd_StopRec + * + * Purpose: No action. + * + * Parameters: See SER_fd_StopRec. + * + * Return: FD_OK: Successful operation. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_StopRec (T_fd_UartId device) +{ + return (FD_OK); +} + +/******************************************************************************* + * + * dummy_fd_StartRec + * + * Purpose: No action. + * + * Parameters: See SER_fd_StartRec. + * + * Return: FD_OK: Successful operation. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_StartRec (T_fd_UartId device) +{ + return (FD_OK); +} + +/******************************************************************************* + * + * dummy_fd_GetLineState + * + * Purpose: Sets the RXBLEV field to the bufSize value. + * + * Parameters: See SER_fd_GetLineState. + * + * Return: FD_OK: Successful operation. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_GetLineState (T_fd_UartId device, + SYS_UWORD32 *state) +{ + #if SERIAL_DYNAMIC_SWITCH + *state = data_flow_parameters.bufSize << RXBLEV; + #else + *state = bufSize << RXBLEV; + #endif + + return (FD_OK); +} + +/******************************************************************************* + * + * dummy_fd_SetLineState + * + * Purpose: No action. + * + * Parameters: See SER_fd_SetLineState. + * + * Return: FD_OK: Successful operation. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_SetLineState (T_fd_UartId device, + SYS_UWORD32 state, + SYS_UWORD32 mask) +{ + return (FD_OK); +} + +/******************************************************************************* + * + * dummy_fd_CheckXEmpty + * + * Purpose: No action. + * + * Parameters: See SER_fd_CheckXEmpty. + * + * Return: FD_OK: Successful operation. + * + ******************************************************************************/ + +static T_FDRET +dummy_fd_CheckXEmpty (T_fd_UartId device) +{ + return (FD_OK); +} + +#ifdef BTEMOBILE +/******************************************************************************* + * + * dummy_bt_Init + * + * Purpose: No action. + * + * Parameters: See SER_bt_Init. + * + * Return: HCI_OK: Successful operation. + * + ******************************************************************************/ + +static T_HCI_RET +dummy_bt_Init (T_bt_UartId uart_device) +{ + return (HCI_OK); +} + +/******************************************************************************* + * + * dummy_bt_Start + * + * Purpose: No action. + * + * Parameters: See SER_bt_Start. + * + * Return: HCI_OK: Successful operation. + * + ******************************************************************************/ + +static T_HCI_RET +dummy_bt_Start (void) +{ + return (HCI_OK); +} + +/******************************************************************************* + * + * dummy_bt_Stop + * + * Purpose: No action. + * + * Parameters: See SER_bt_Stop. + * + * Return: HCI_OK: Successful operation. + * + ******************************************************************************/ + +static T_HCI_RET +dummy_bt_Stop (void) +{ + return (HCI_OK); +} + +/******************************************************************************* + * + * dummy_bt_Kill + * + * Purpose: No action. + * + * Parameters: See SER_bt_Kill. + * + * Return: HCI_OK: Successful operation. + * + ******************************************************************************/ + +static T_HCI_RET +dummy_bt_Kill (void) +{ + return (HCI_OK); +} + +/******************************************************************************* + * + * dummy_bt_SetBaudrate + * + * Purpose: No action. + * + * Parameters: See SER_bt_SetBaudrate. + * + * Return: HCI_OK: Successful operation. + * + ******************************************************************************/ + +static T_HCI_RET +dummy_bt_SetBaudrate (UINT8 baudrate) +{ + return (HCI_OK); +} + +/******************************************************************************* + * + * dummy_bt_TransmitPacket + * + * Purpose: No action. + * + * Parameters: See SER_bt_TransmitPacket. + * + * Return: HCI_OK: Successful operation. + * + ******************************************************************************/ + +static T_HCI_RET dummy_bt_TransmitPacket (void *uart_tx_buffer) + +{ + return (HCI_OK); +} + +/******************************************************************************* + * + * dummy_bt_EnterSleep + * + * Purpose: No action. + * + * Parameters: See SER_bt_EnterSleep. + * + * Return: TRUE. + * + ******************************************************************************/ + +static SYS_BOOL +dummy_bt_EnterSleep (void) +{ + return (TRUE); +} + +/******************************************************************************* + * + * dummy_bt_WakeUp + * + * Purpose: No action. + * + * Parameters: See SER_bt_WakeUp + * + * Return: HCI_OK: none + * + ******************************************************************************/ + +static void +dummy_bt_WakeUp (void) +{ + /* + * No action. + */ +} + +#endif /* BTEMOBILE */ + +/******************************************************************************* + * + * analyze_uart_sleep_timer_expiration + * + * Purpose : The timer has just expired. If requested, UARTs can again be set + * up to enter Deep Sleep. + * + * Arguments: In : id: parameter not used. + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static VOID +analyze_uart_sleep_timer_expiration (UNSIGNED id) +{ + /* + * Timer has expired. + * UARTs can again be set up for Deep Sleep. + */ + + (void) NU_Control_Timer (&uart_sleep_timer, + NU_DISABLE_TIMER); + + uart_sleep_timer_enabled = 0; +} + +/******************************************************************************* + * + * start_uart_sleep_timer + * + * Purpose : Starts the sleep timer once UARTs have been waked-up by an + * interrupt or if new incoming characters have been received. + * + * Arguments: In : none + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static void +start_uart_sleep_timer (void) +{ + /* + * UART sleep timer is started. + * UARTs can't no more be set up for Deep Sleep until the timer expires. + */ + + (void) NU_Reset_Timer (&uart_sleep_timer, + &analyze_uart_sleep_timer_expiration, + WAKE_UP_TIME_IN_TDMA, + 0, /* The timer expires once. */ + NU_DISABLE_TIMER); + + (void) NU_Control_Timer (&uart_sleep_timer, + NU_ENABLE_TIMER); +} + +/******************************************************************************* + * + * set_flow_functions + * + * Purpose: Initializes a serial data flow functions set with the set of + * functions of the selected device. + * + * Parameters: In : flow : index of the serial data flow + * serial_driver: allows knowing which set of functions must + * be selected + * Out: none + * + * Return: none + * + ******************************************************************************/ + +static void +set_flow_functions (int flow, + T_SerialDriver serial_driver) +{ + + switch (serial_driver) { + + case UART_MODEM_FAX_DATA: + +#if CONFIG_FDMODEM + fd_functions = &uart_modem_fax_data; + int_uart[fd_functions->device].device_used = 1; + int_uart[fd_functions->device].flow_type = FAX_DATA_FLOW; + int_uart[fd_functions->device].flow_id = flow; + int_uart[fd_functions->device].interrupt_handler = + UAF_InterruptHandler; + break; +#endif + + case DUMMY_FAX_DATA: + + fd_functions = &dummy_fax_data; + break; + + + case UART_IRDA_TRACE: + case UART_MODEM_TRACE: + #if (CHIPSET == 12) + case UART_MODEM2_TRACE: + #endif + + if (serial_driver == UART_IRDA_TRACE) + tr_functions[flow] = &uart_irda_trace; + else { + #if (CHIPSET == 12) + if (serial_driver == UART_MODEM2_TRACE) + tr_functions[flow] = &uart_modem2_trace; + else + #endif + tr_functions[flow] = &uart_modem_trace; + } + + int_uart[tr_functions[flow]->device].device_used = 1; + int_uart[tr_functions[flow]->device].flow_type = TRACE_FLOW; + int_uart[tr_functions[flow]->device].flow_id = flow; + int_uart[tr_functions[flow]->device].interrupt_handler = + UA_InterruptHandler; + break; + + case DUMMY_TRACE: + + tr_functions[flow] = &dummy_trace; + break; + + case DUMMY_BT_HCI: + + /* + * if serial_driver = DUMMY_BT_HCI & if BTEMOBILE is not defined + * no action is performed. + */ + +#ifdef BTEMOBILE + bt_functions = &dummy_bt_hci; + break; + + case UART_IRDA_BT_HCI: + case UART_MODEM_BT_HCI: + #if (CHIPSET == 12) + case UART_MODEM2_BT_HCI: + #endif + + if (serial_driver == UART_IRDA_BT_HCI) + bt_functions = &uart_irda_bt_hci; + else { + #if (CHIPSET == 12) + if (serial_driver == UART_MODEM2_BT_HCI) + bt_functions = &uart_modem2_bt_hci; + else + #endif + bt_functions = &uart_modem_bt_hci; + } + + int_uart[bt_functions->device].device_used = 1; + int_uart[bt_functions->device].flow_type = BLUETOOTH_HCI_FLOW; + int_uart[bt_functions->device].flow_id = flow; + int_uart[bt_functions->device].interrupt_handler = + hciu_interrupt_handler; +#endif /* BTEMOBILE */ + break; + } +} + +/******************************************************************************* + * + * SER_InitSerialConfig + * + * Purpose: The parameter serial_info allows knowing all serial information + * necessary to set up the serial configuration of an application. + * From this information, the function is able to determine if the + * current serial configuration read out from the flash memory is + * valid. If it does not correspond to an allowed configuration, the + * default configuration is selected. This function must be called at + * the application's initialization, but never after. + * + * Parameters: In : serial_info: application serial information like the default + * configuration and all allowed configurations. + * Out: none + * + * Return: none + * + ******************************************************************************/ + +void +SER_InitSerialConfig (const T_AppliSerialInfo *serial_info) +{ + int uart_id; + int flow; + SYS_UWORD16 serial_driver; + SYS_UWORD16 *allowed_config; + SYS_UWORD8 nb_allowed_config; + SYS_BOOL valid_config_selected; + SYS_BOOL uart_used; + SYS_BOOL uart_used_for_trace; + SYS_UWORD16 current_config; + SYS_UWORD16 *pt_current_config = &(current_config); + + /* + * Basic UARTs initializations. + */ + + for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) { + + int_uart[uart_id].base_address = uart_base_address[uart_id]; + int_uart[uart_id].device_used = 0; + int_uart[uart_id].deep_sleep_set_up = 0; + } + +#if ((CHIPSET == 2) || (CHIPSET == 3)) + uart_spurious_interrupts = 0; +#elif ((CHIPSET == 4) || (CHIPSET == 5) || (CHIPSET == 6) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12)) + uart_modem_spurious_interrupts = 0; + uart_irda_spurious_interrupts = 0; +#endif +#if (CHIPSET == 12) + uart_modem2_spurious_interrupts = 0; +#endif + uart_sleep_timer_enabled = 0; + + /* + * Compute the current serial configuration. + */ + + for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) { + + switch (ser_cfg_info[uart_id]) { + + case G23_PANEL: + serial_cfg = serial_cfg + + ((uart_id + 1) << (12 - (4 * SER_PROTOCOL_STACK))); + break; + + case RIVIERA_TRACE_MUX: + serial_cfg = serial_cfg + + ((uart_id + 1) << (12 - (4 * SER_LAYER_1))); + break; + + case FD_AT_COMMAND: + serial_cfg = serial_cfg + + ((uart_id + 1) << (12 - (4 * SER_FAX_DATA))); + break; + + case BLUETOOTH_HCI: + serial_cfg = serial_cfg + + ((uart_id + 1) << (12 - (4 * SER_BLUETOOTH_HCI))); + break; + + case DUMMY: + break; + } + } + + current_config = serial_cfg; + valid_config_selected = 0; + nb_allowed_config = serial_info->num_config; + + /* + * Checks if the current serial config is one of the allowed. + */ + + while ((nb_allowed_config > 0) && !valid_config_selected) { + + nb_allowed_config--; + allowed_config = (SYS_UWORD16 *) + &(serial_info->allowed_config[nb_allowed_config]); + + if (*pt_current_config == *allowed_config) + valid_config_selected = 1; + } + + /* + * If not, the default configuration is selected. + */ + + if (!valid_config_selected) { + + pt_current_config = (SYS_UWORD16 *)&(serial_info->default_config); + + #if SERIAL_DYNAMIC_SWITCH + /* + * Setup the global variable accordingly. + * The following default value are identical to the ones defined at + * the application initialization in init.c. + */ + + #ifdef BT_UART_USED_MODEM + memcpy (ser_cfg_info, "RB", NUMBER_OF_TR_UART); + #else + memcpy (ser_cfg_info, "BR", NUMBER_OF_TR_UART); + #endif + #endif + } + + /* + * The serial data flow functions set is initialized. + */ + + flow = 0; + while (flow < SER_MAX_NUMBER_OF_FLOWS) { + + serial_driver = (T_SerialDriver) + (((*pt_current_config) >> (12 - flow * 4)) & 0x000F); + + set_flow_functions (flow, serial_driver); + flow++; + } + + /* + * Checks if both UARTs are used. + * If not, performs minimum initialization including Sleep Mode. + * Checks also if at least one UART is used by a Trace flow. + * If so, create a HISR in order to reset and restart the sleep timer + * in case of incoming characters. + */ + + uart_used = 0; + uart_used_for_trace = 0; + for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) { + + if (!(int_uart[uart_id].device_used)) + initialize_uart_sleep (uart_id); + + else { /* if (int_uart[uart_id].device_used) */ + + uart_used = 1; /* At least one UART is used */ + + if (int_uart[uart_id].flow_type == TRACE_FLOW) { + + /* At least one UART used by a Trace flow */ + uart_used_for_trace = 1; + } + } + } + + /* + * If at least one uart is used, create a timer to figure out if the system + * can enter deep sleep mode regarding the UARTs. + */ + + if (uart_used) { + + (void) NU_Create_Timer ( + &uart_sleep_timer, + "Sleep", + &analyze_uart_sleep_timer_expiration, + 0, /* Parameter supplied to the routine: not used. */ + WAKE_UP_TIME_IN_TDMA, + 0, /* The timer expires once. */ + NU_DISABLE_TIMER); + + /* + * If at least one uart is used by a Trace flow, create a HISR to reset + * and restart the sleep timer. + */ + + if (uart_used_for_trace) { + + /* + * The stack is entirely filled with the pattern 0xFE. + */ + + memset (&(timer_hisr_stack[0]), 0xFE, TIMER_HISR_STACK_SIZE); + + /* + * The HISR entry function is the same function than the one called + * by the Rx HISR of the UARTFAX, since the only aim is to reset + * and restart the sleep timer in case of incoming characters on + * the Trace UART. + */ + + (void) NU_Create_HISR ( + &timer_hisr_ctrl_block, + "Tim_HISR", + SER_restart_uart_sleep_timer, + TIMER_HISR_PRIORITY, + &(timer_hisr_stack[0]), + TIMER_HISR_STACK_SIZE); + } + } +} + + +/******************************************************************************* + * + * SER_WriteConfig + * + * Purpose: TBD + * + * Parameters: In : new_config: TBD + * write_to_flash: TBD + * Out: none + * + * Return: 0 (FALSE) : In case of error while trying to write file in FFS + * >= 1 (TRUE) : Successful operation. + * + ******************************************************************************/ + +SYS_BOOL +SER_WriteConfig (char *new_config, + SYS_BOOL write_to_flash) +{ +#if SERIAL_DYNAMIC_SWITCH + int uart_id; + SYS_BOOL status = 1; + + for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) + ser_new_cfg[uart_id] = *new_config++; + + /* + * Write in flash the new serial configuration if requested. + */ + + if (write_to_flash) { + if (ffs_fwrite (uart_config_file, + ser_new_cfg, + NUMBER_OF_TR_UART) < EFFS_OK) { + status = 0; + } + } + + return (status); +#else + /* + * Real Dynamic Switch is only available with Bluetooth AND all chips but + * Calypso+. + */ + + return (1); +#endif +} + +/******************************************************************************* + * + * SER_ImmediateSwitch + * + * Purpose: TBD + * + * Parameters: In : none + * Out: none + * + * Return: 0 (FALSE) : In case of error. + * >= 1 (TRUE) : Successful operation. + * + ******************************************************************************/ + +SYS_BOOL +SER_ImmediateSwitch (void) +{ +#if SERIAL_DYNAMIC_SWITCH + int uart_id; + SYS_BOOL valid_config = 0; + T_AppliSerialInfo *serial_info = &appli_ser_cfg_info; + SYS_UWORD8 nb_allowed_config = serial_info->num_config; + SYS_UWORD16 *allowed_config; + int flow; + T_SerialDriver serial_flows[SER_MAX_NUMBER_OF_FLOWS]; + T_tr_UartId uart_nb; + + /* + * First check if the new serial configuration is actually different from + * the previous one. A return is used to simplify the code. + */ + + if (!memcmp (ser_new_cfg, + ser_cfg_info, + NUMBER_OF_TR_UART)) + return (1); /* new config and old config are identical => nothing to do */ + + /* + * Then check if the new serial config is valid or not. + * At that point, we assume that a serial config is valid if and only if the + * Bluetooth HCI flow is still enabled and still uses the same UART. + * Reset the current serial config, and compute the new one. + */ + + serial_cfg = 0x0048; /* All dummies */ + for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) { + + switch (ser_new_cfg[uart_id]) { + + case G23_PANEL: + serial_cfg = serial_cfg + + ((uart_id + 1) << (12 - (4 * SER_PROTOCOL_STACK))); + break; + + case RIVIERA_TRACE_MUX: + serial_cfg = serial_cfg + + ((uart_id + 1) << (12 - (4 * SER_LAYER_1))); + break; + + case FD_AT_COMMAND: + serial_cfg = serial_cfg + + ((uart_id + 1) << (12 - (4 * SER_FAX_DATA))); + break; + + case BLUETOOTH_HCI: + serial_cfg = serial_cfg + + ((uart_id + 1) << (12 - (4 * SER_BLUETOOTH_HCI))); + + /* + * Check if the Bluetooth HCI flow is enabled on the same UART. + */ + + if (ser_cfg_info[uart_id] == BLUETOOTH_HCI) + valid_config = 1; + + break; + + case DUMMY: + break; + } + } + + if (!valid_config) + return (0); /* Bluetooth HCI flow not enabled in the new serial config, + or enabled but using a different UART. */ + + /* + * Finally check if the new serial config is allowed by the application. + */ + + valid_config = 0; + while ((nb_allowed_config > 0) && !valid_config) { + + nb_allowed_config--; + allowed_config = (SYS_UWORD16 *) + &(serial_info->allowed_config[nb_allowed_config]); + + if (serial_cfg == *allowed_config) + valid_config = 1; + } + + if (!valid_config) /* the new config is not allowed by the application */ + return (0); + + /* + * From now on, Dynamic Switch is being processed. + */ + + dynamic_switch = 1; + + /* + * Disable UART interrupts until new serial config setup is complete. + */ + + #if ((CHIPSET == 4) || (CHIPSET == 5) || (CHIPSET == 6) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11)) + IQ_Mask (IQ_UART_IRDA_IT); + #endif + IQ_Mask (IQ_UART_IT); + + /* + * Reset UARTs set-up. + */ + + for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) { + + int_uart[uart_id].device_used = 0; + int_uart[uart_id].deep_sleep_set_up = 0; + int_uart[uart_id].interrupt_handler = NULL; + } + + /* + * All function pointers are set to dummy functions. + */ + + rvf_disable (21); /* beginning of the critical section */ + + for (flow = 0; flow < SER_MAX_NUMBER_OF_FLOWS; flow++) + tr_functions[flow] = &dummy_trace; + + fd_functions = &dummy_fax_data; + bt_functions = &dummy_bt_hci; + + rvf_enable (); /* end of the critical section */ + + /* + * Calls the Exit function of the UARTFAX driver if it was previously used. + */ + + if (uart_fd_initialized) { + + /* + * UART IrDA can't be used for F&D/AT-Cmd flow => UART Modem was used + * by the F&D/AT-Cmd flow. + */ + + if (UAF_Exit (UAF_UART_1) == FD_OK) { + uart_fd_initialized = 0; + } + } + else { + + /* + * AT that point, since the Bluetooth HCI flow already uses one UART, + * and since the second UART was not used by the F&D/AT-Cmd flow, we + * assume it was used by a Trace flow. Therefore, the HISR used to + * reset and restart the sleep timer is deleted. + */ + + (void) NU_Delete_HISR (&timer_hisr_ctrl_block); + } + + /* + * Initialization of the new flows (Only AT-Cmd/F&D or Riviera/Layer1 Trace) + * and their associated UARTs HW (Irda or Modem) & SW (Trace or Fax&Data). + */ + + for (flow = 0; flow < SER_MAX_NUMBER_OF_FLOWS; flow++) { + + serial_flows[flow] = (T_SerialDriver) + ((serial_cfg >> (12 - flow * 4)) & 0x000F); + + switch (serial_flows[flow]) { + + /* + * For Riviera/Layer1 Trace flow, default baudrate is 115200 bps + * and callback function is defined in rvt_def_i.h. + */ + + case UART_IRDA_TRACE: + case UART_MODEM_TRACE: + + if (serial_flows[flow] == UART_IRDA_TRACE) + uart_nb = UA_UART_0; + else /* if (serial_flows[flow] == UART_MODEM_TRACE) */ + uart_nb = UA_UART_1; + + if (flow == SER_LAYER_1) { + + UA_Init (uart_nb, + TR_BAUD_CONFIG, + rvt_activate_RX_HISR); + + /* + * Create the HISR used to reset and restart the sleep + * timer in case of incoming characters on the Trace flow. + * The stack is entirely filled with the pattern 0xFE. + */ + + memset (&(timer_hisr_stack[0]), + 0xFE, + TIMER_HISR_STACK_SIZE); + + (void) NU_Create_HISR ( + &timer_hisr_ctrl_block, + "Tim_HISR", + SER_restart_uart_sleep_timer, + TIMER_HISR_PRIORITY, + &(timer_hisr_stack[0]), + TIMER_HISR_STACK_SIZE); + } + else /* Other Trace flows are disabled */ + initialize_uart_sleep (uart_nb); + break; + + /* + * For At-Cmd/F&D flow, functions are called in the appropriate + * order with the saved parameters. + * This has been figured out from the G23 initialization. + */ + + case UART_MODEM_FAX_DATA: + + /* Global Initialization */ + if (UAF_Init (UAF_UART_1) == FD_OK) { + uart_fd_initialized = 1; + } + + /* Disable the driver */ + UAF_Enable (UAF_UART_1, + 0); + + /* Set the SW Buffers parameters */ + UAF_SetBuffer (UAF_UART_1, + data_flow_parameters.bufSize, + data_flow_parameters.rxThreshold, + data_flow_parameters.txThreshold); + + /* Set the Escape Sequence parameters (1st call) */ + UAF_SetEscape (UAF_UART_1, + data_flow_parameters.escChar[0], + data_flow_parameters.guardPeriod[0]); + + /* Set the Communication parameters (1st call) */ + UAF_SetComPar (UAF_UART_1, + data_flow_parameters.baudrate[0], + data_flow_parameters.bpc[0], + data_flow_parameters.sb[0], + data_flow_parameters.parity[0]); + + /* Set the Flow Control parameters (1st call) */ + UAF_SetFlowCtrl (UAF_UART_1, + data_flow_parameters.fcMode[0], + data_flow_parameters.XON[0], + data_flow_parameters.XOFF[0]); + + /* Set the Communication parameters (2nd call) */ + UAF_SetComPar (UAF_UART_1, + data_flow_parameters.baudrate[1], + data_flow_parameters.bpc[1], + data_flow_parameters.sb[1], + data_flow_parameters.parity[1]); + + /* Set the Flow Control parameters (2nd call) */ + UAF_SetFlowCtrl (UAF_UART_1, + data_flow_parameters.fcMode[1], + data_flow_parameters.XON[1], + data_flow_parameters.XOFF[1]); + + /* Set the Escape Sequence parameters (2nd call) */ + UAF_SetEscape (UAF_UART_1, + data_flow_parameters.escChar[1], + data_flow_parameters.guardPeriod[1]); + + /* Enable the driver */ + UAF_Enable (UAF_UART_1, + 1); + + /* Get the number of input bytes available */ + UAF_InpAvail (UAF_UART_1); + + /* Set the readOutFunc and the suspend mode */ + UAF_ReadData (UAF_UART_1, + data_flow_parameters.suspend_rd, + data_flow_parameters.readOutFunc); + + /* Get the number of output bytes available (1st call) */ + UAF_OutpAvail (UAF_UART_1); + + /* Set the states of the V.24 status lines (1st call) */ + UAF_SetLineState (UAF_UART_1, + data_flow_parameters.state[0], + data_flow_parameters.mask[0]); + + /* Set the states of the V.24 status lines (2nd call) */ + UAF_SetLineState (UAF_UART_1, + data_flow_parameters.state[1], + data_flow_parameters.mask[1]); + + /* Set the states of the V.24 status lines (3rd call) */ + UAF_SetLineState (UAF_UART_1, + data_flow_parameters.state[2], + data_flow_parameters.mask[2]); + + /* Set the states of the V.24 status lines (4th call) */ + UAF_SetLineState (UAF_UART_1, + data_flow_parameters.state[3], + data_flow_parameters.mask[3]); + + /* Set the writeInFunc and the suspend mode */ + UAF_WriteData (UAF_UART_1, + data_flow_parameters.suspend_wr, + data_flow_parameters.writeInFunc); + + /* Get the number of output bytes available (2nd call) */ + UAF_OutpAvail (UAF_UART_1); + + break; + + case UART_IRDA_BT_HCI: + case UART_MODEM_BT_HCI: + /* + * Nothing to initialize for Bluetooth HCI flow since it does + * use the same UART. + */ + + case DUMMY_TRACE: + case DUMMY_FAX_DATA: + case DUMMY_BT_HCI: + /* + * Of course nothing to perform for Dummy flows. + */ + + break; + } + } + + /* + * All function pointers are set to the appropriate functions set. + */ + + for (flow = 0; flow < SER_MAX_NUMBER_OF_FLOWS; flow++){ + + /* + * For Dummy flows, pointers to dummy functions are already set. + */ + + if ((serial_flows[flow] != DUMMY_TRACE) && + (serial_flows[flow] != DUMMY_FAX_DATA) && + (serial_flows[flow] != DUMMY_BT_HCI)) { + + rvf_disable (21); /* beginning of the critical section */ + set_flow_functions (flow, serial_flows[flow]); + rvf_enable (); /* end of the critical section */ + } + } + + /* + * Dynamic Switch has been processed. + * The new serial config is actually stored. + */ + + dynamic_switch = 0; + for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) + ser_cfg_info[uart_id] = ser_new_cfg[uart_id]; + + /* + * Re-enable UART interrupts. + */ + + #if ((CHIPSET == 4) || (CHIPSET == 5) || (CHIPSET == 6) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11)) + IQ_Unmask (IQ_UART_IRDA_IT); + #endif + IQ_Unmask (IQ_UART_IT); + +#endif + /* + * Real Dynamic Switch is only available with Bluetooth AND all chips but + * Calypso+. + */ + + return (1); +} + +/******************************************************************************* + * + * All functions SER_tr_xxx and SER_fd_xxx call a function of the UART trace + * driver or the UART fax & data driver. + * All functions SER_bt_xxx call a function of the UART Bluetooth HCI driver. + * See the function call for parameters and return values. + * + ******************************************************************************/ + +void +SER_tr_Init (int serial_data_flow, + T_tr_Baudrate baudrate, + void (callback_function (void))) +{ + tr_functions[serial_data_flow]->tr_Init ( + tr_functions[serial_data_flow]->device, baudrate, callback_function); +} + +SYS_UWORD32 +SER_tr_ReadNChars (int serial_data_flow, + char *buffer, + SYS_UWORD32 chars_to_read) +{ + return (tr_functions[serial_data_flow]->tr_ReadNChars ( + tr_functions[serial_data_flow]->device, buffer, chars_to_read)); +} + +SYS_UWORD32 +SER_tr_ReadNBytes (int serial_data_flow, + char *buffer, + SYS_UWORD32 chars_to_read, + SYS_BOOL *eof_detected) +{ + return (tr_functions[serial_data_flow]->tr_ReadNBytes ( + tr_functions[serial_data_flow]->device, buffer, chars_to_read, eof_detected)); +} + +SYS_UWORD32 +SER_tr_WriteNChars (int serial_data_flow, + char *buffer, + SYS_UWORD32 chars_to_write) +{ + return (tr_functions[serial_data_flow]->tr_WriteNChars ( + tr_functions[serial_data_flow]->device, buffer, chars_to_write)); +} + +SYS_UWORD32 +SER_tr_EncapsulateNChars (int serial_data_flow, + char *buffer, + SYS_UWORD32 chars_to_write) +{ + return (tr_functions[serial_data_flow]->tr_EncapsulateNChars ( + tr_functions[serial_data_flow]->device, buffer, chars_to_write)); +} + +SYS_UWORD32 +SER_tr_WriteNBytes (int serial_data_flow, + SYS_UWORD8 *buffer, + SYS_UWORD32 chars_to_write) +{ + return (tr_functions[serial_data_flow]->tr_WriteNBytes ( + tr_functions[serial_data_flow]->device, buffer, chars_to_write)); +} + +void +SER_tr_WriteChar (int serial_data_flow, + char character) +{ + tr_functions[serial_data_flow]->tr_WriteChar ( + tr_functions[serial_data_flow]->device, character); +} + +void +SER_tr_WriteString (int serial_data_flow, + char *buffer) +{ + tr_functions[serial_data_flow]->tr_WriteString ( + tr_functions[serial_data_flow]->device, buffer); +} + +SYS_BOOL +SER_tr_EnterSleep (int serial_data_flow) +{ + return (tr_functions[serial_data_flow]->tr_EnterSleep ( + tr_functions[serial_data_flow]->device)); +} + +void +SER_tr_WakeUp (int serial_data_flow) +{ + tr_functions[serial_data_flow]->tr_WakeUp ( + tr_functions[serial_data_flow]->device); +} + +/* Dummy function for backward compatibility. */ +T_FDRET +SER_fd_Init (void) +{ + return (FD_OK); +} + +T_FDRET +SER_fd_Initialize (void) +{ + T_FDRET status; + + #if SERIAL_DYNAMIC_SWITCH + data_flow_parameters.bufSize = FD_MAX_BUFFER_SIZE; + #else + bufSize = FD_MAX_BUFFER_SIZE; + #endif + status = fd_functions->fd_Initialize (fd_functions->device); + + #if SERIAL_DYNAMIC_SWITCH + /* + * Check if the UARTFAX driver has actually been initialized. + */ + + if ((fd_functions->fd_Initialize == UAF_Init) && + (status = FD_OK)) { + + uart_fd_initialized = 1; + } + #endif + + return (status); +} + +static void +fd_dbgtrace(char *msg, UINT32 val) +{ + rvf_send_trace(msg, strlen(msg), val, RV_TRACE_LEVEL_DEBUG_HIGH, 0); +} + +T_FDRET +SER_fd_Enable (SYS_BOOL enable) +{ + T_FDRET rc; + + fd_dbgtrace("SER_fd_Enable called", enable); + rc = fd_functions->fd_Enable (fd_functions->device, enable); + fd_dbgtrace("fd_Enable returned", rc); + return rc; +} + +T_FDRET +SER_fd_SetComPar (T_baudrate baudrate, + T_bitsPerCharacter bpc, + T_stopBits sb, + T_parity parity) +{ + T_FDRET rc; + char trbuf[80]; + + sprintf(trbuf, "SER_fd_SetComPar(%d, %d, %d, %d)", + baudrate, bpc, sb, parity); + fd_dbgtrace(trbuf, NULL_PARAM); + rc = (fd_functions->fd_SetComPar ( + fd_functions->device, baudrate, bpc, sb, parity)); + fd_dbgtrace("fd_SetComPar returned", rc); + return rc; +} + +T_FDRET +SER_fd_SetBuffer (SYS_UWORD16 bufSize, + SYS_UWORD16 rxThreshold, + SYS_UWORD16 txThreshold) +{ + T_FDRET rc; + char trbuf[80]; + + sprintf(trbuf, "SER_fd_SetBuffer(%u, %u, %u)", + bufSize, rxThreshold, txThreshold); + fd_dbgtrace(trbuf, NULL_PARAM); + rc = (fd_functions->fd_SetBuffer ( + fd_functions->device, bufSize, rxThreshold, txThreshold)); + fd_dbgtrace("fd_SetBuffer returned", rc); + return rc; +} + +T_FDRET +SER_fd_SetFlowCtrl (T_flowCtrlMode fcMode, + SYS_UWORD8 XON, + SYS_UWORD8 XOFF) +{ + T_FDRET rc; + char trbuf[80]; + + sprintf(trbuf, "SER_fd_SetFlowCtrl(%d, %02x, %02x)", fcMode, XON, XOFF); + fd_dbgtrace(trbuf, NULL_PARAM); + rc = (fd_functions->fd_SetFlowCtrl ( + fd_functions->device, fcMode, XON, XOFF)); + fd_dbgtrace("fd_SetFlowCtrl returned", rc); + return rc; +} + +T_FDRET +SER_fd_SetEscape (char escChar, + SYS_UWORD16 guardPeriod) +{ + T_FDRET rc; + char trbuf[80]; + + sprintf(trbuf, "SER_fd_SetEscape(%02x, %u)", escChar, guardPeriod); + fd_dbgtrace(trbuf, NULL_PARAM); + rc = (fd_functions->fd_SetEscape ( + fd_functions->device, escChar, guardPeriod)); + fd_dbgtrace("fd_SetEscape returned", rc); + return rc; +} + +T_FDRET +SER_fd_InpAvail (void) +{ + T_FDRET rc; + + fd_dbgtrace("SER_fd_InpAvail called", NULL_PARAM); + rc = (fd_functions->fd_InpAvail (fd_functions->device)); + fd_dbgtrace("fd_InpAvail returned", rc); + return rc; +} + +T_FDRET +SER_fd_OutpAvail (void) +{ + T_FDRET rc; + + fd_dbgtrace("SER_fd_OutpAvail called", NULL_PARAM); + rc = (fd_functions->fd_OutpAvail (fd_functions->device)); + fd_dbgtrace("fd_OutpAvail returned", rc); + return rc; +} + +T_FDRET +SER_fd_EnterSleep (void) +{ + return (fd_functions->fd_EnterSleep (fd_functions->device)); +} + +T_FDRET +SER_fd_WakeUp (void) +{ + return (fd_functions->fd_WakeUp (fd_functions->device)); +} + +T_FDRET +SER_fd_ReadData (T_suspendMode suspend, + void (readOutFunc (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 nsource, + SYS_UWORD8 *source[], + SYS_UWORD16 size[], + SYS_UWORD32 state))) +{ + T_FDRET rc; + + fd_dbgtrace("SER_fd_ReadData called", suspend); + rc = (fd_functions->fd_ReadData ( + fd_functions->device, suspend, readOutFunc)); + fd_dbgtrace("fd_ReadData returned", rc); + return rc; +} + +T_FDRET +SER_fd_WriteData (T_suspendMode suspend, + void (writeInFunc (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 ndest, + SYS_UWORD8 *dest[], + SYS_UWORD16 size[]))) +{ + T_FDRET rc; + + fd_dbgtrace("SER_fd_WriteData called", suspend); + rc = (fd_functions->fd_WriteData ( + fd_functions->device, suspend, writeInFunc)); + fd_dbgtrace("fd_WriteData returned", rc); + return rc; +} + +T_FDRET +SER_fd_StopRec (void) +{ + T_FDRET rc; + + fd_dbgtrace("SER_fd_StopRec called", NULL_PARAM); + rc = (fd_functions->fd_StopRec (fd_functions->device)); + fd_dbgtrace("fd_StopRec returned", rc); + return rc; +} + +T_FDRET +SER_fd_StartRec (void) +{ + T_FDRET rc; + + fd_dbgtrace("SER_fd_StartRec called", NULL_PARAM); + rc = (fd_functions->fd_StartRec (fd_functions->device)); + fd_dbgtrace("fd_StartRec returned", rc); + return rc; +} + +T_FDRET +SER_fd_GetLineState (SYS_UWORD32 *state) +{ + T_FDRET rc; + char trbuf[80]; + + fd_dbgtrace("SER_fd_GetLineState called", NULL_PARAM); + rc = (fd_functions->fd_GetLineState (fd_functions->device, state)); + sprintf(trbuf, "fd_GetLineState returned %d, %x", rc, *state); + fd_dbgtrace(trbuf, NULL_PARAM); + return rc; +} + +T_FDRET +SER_fd_SetLineState (SYS_UWORD32 state, + SYS_UWORD32 mask) +{ + T_FDRET rc; + char trbuf[80]; + + sprintf(trbuf, "SER_fd_SetLineState(%x, %x)", state, mask); + fd_dbgtrace(trbuf, NULL_PARAM); + rc = (fd_functions->fd_SetLineState (fd_functions->device, state, mask)); + fd_dbgtrace("fd_SetLineState returned", rc); + return rc; +} + +T_FDRET +SER_fd_CheckXEmpty (void) +{ + T_FDRET rc; + + fd_dbgtrace("SER_fd_CheckXEmpty called", NULL_PARAM); + rc = (fd_functions->fd_CheckXEmpty (fd_functions->device)); + fd_dbgtrace("fd_CheckXEmpty returned", rc); + return rc; +} + +#ifdef BTEMOBILE +T_HCI_RET +SER_bt_Init (void) +{ + return (bt_functions->bt_Init (bt_functions->device)); +} + +T_HCI_RET +SER_bt_Start (void) +{ + return (bt_functions->bt_Start ()); +} + +T_HCI_RET +SER_bt_Stop (void) +{ + return (bt_functions->bt_Stop ()); +} + +T_HCI_RET +SER_bt_Kill (void) +{ + return (bt_functions->bt_Kill ()); +} + +T_HCI_RET +SER_bt_SetBaudrate (UINT8 baudrate) +{ + return (bt_functions->bt_SetBaudrate (baudrate)); +} + +T_HCI_RET SER_bt_TransmitPacket (void *uart_tx_buffer) +{ + return (bt_functions->bt_TransmitPacket (uart_tx_buffer)); +} + +SYS_BOOL SER_bt_EnterSleep (void) +{ + return (bt_functions->bt_EnterSleep()); +} + +void SER_bt_WakeUp (void) +{ + bt_functions->bt_WakeUp(); +} +#endif /* BTEMOBILE */ + +/******************************************************************************* + * + * SER_UartSleepStatus + * + * Purpose: This function checks if both UARTs are ready to enter Deep Sleep. + * + * Parameters: In : none + * Out: none + * + * Return: 0 : Deep Sleep is not possible. + * >= 1 : Deep Sleep is possible. + * + ******************************************************************************/ + +SYS_BOOL +SER_UartSleepStatus (void) +{ + t_uart *uart; + int uart_id; + SYS_BOOL status; + + /* + * Check first if the sleep timer is active or if a Dynamic Switch is + * being processed. A return is used to simplify the code. + */ + +#if SERIAL_DYNAMIC_SWITCH + if (uart_sleep_timer_enabled || dynamic_switch) +#else + if (uart_sleep_timer_enabled) +#endif + return (0); + + /* + * Check if both UARTs are ready to enter Deep Sleep. + */ + + status = 1; + uart_id = 0; + while ((uart_id < NUMBER_OF_TR_UART) && + (status)) { + + uart = &(int_uart[uart_id]); + + /* + * Check if the specified UART is actually used. + */ + + if (uart->device_used) { + + /* + * Check if the specified UART is used by a Trace or + * by a Fax & Data flow. + */ + + if (uart->flow_type == TRACE_FLOW) + status = SER_tr_EnterSleep (uart->flow_id); + + else + if (uart->flow_type == FAX_DATA_FLOW) + status = (SYS_BOOL) SER_fd_EnterSleep (); +#ifdef BTEMOBILE + else + if (uart->flow_type == BLUETOOTH_HCI_FLOW) + status = SER_bt_EnterSleep(); +#endif + else + status = 0; + + if (status) { + + /* + * The specified UART is now set up for Deep Sleep. + */ + + uart->deep_sleep_set_up = 1; + + } + } + + uart_id++; + } + + /* + * Check if Deep Sleep is finally possible. + * If not revert eventual Deep Sleep settings. + */ + + if (!status) { + + for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) { + + uart = &(int_uart[uart_id]); + + /* + * If the specified used UART has already been set up for + * Deep Sleep, revert these settings. + */ + + if ((uart->device_used) && + (uart->deep_sleep_set_up)) { + + /* + * Check if the specified UART is used by a Trace or + * by a Fax & Data flow. + * Bluetooth HCI can not yet handled Deep Sleep Mode. + */ + + if (uart->flow_type == TRACE_FLOW) + SER_tr_WakeUp (uart->flow_id); + + else + if (uart->flow_type == FAX_DATA_FLOW) + SER_fd_WakeUp (); +#ifdef BTEMOBILE + else + if (uart->flow_type == BLUETOOTH_HCI_FLOW) + SER_bt_WakeUp (); +#endif + uart->deep_sleep_set_up = 0; + + } + } + } + + return (status); +} + + +/******************************************************************************* + * + * SER_WakeUpUarts + * + * Purpose: This function wakes up used UARTs after Deep Sleep. + * + * Parameters: In : none + * Out: none + * + * Return: none + * + ******************************************************************************/ + +void +SER_WakeUpUarts (void) +{ + t_uart *uart; + int uart_id; + + if (uart_sleep_timer_enabled) + start_uart_sleep_timer (); + + for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) { + + uart = &(int_uart[uart_id]); + + /* + * Check if the specified UART is actually used, and has not yet + * been waked up. + */ + + if ((uart->device_used) && + (uart->deep_sleep_set_up)) { + + /* + * Check if the specified UART is used by a Trace or + * by a Fax & Data flow. + * Bluetooth HCI can not yet handled Deep Sleep Mode. + */ + + if (uart->flow_type == TRACE_FLOW) + SER_tr_WakeUp (uart->flow_id); + + else + if (uart->flow_type == FAX_DATA_FLOW) + SER_fd_WakeUp (); +#ifdef BTEMOBILE + else + if (uart->flow_type == BLUETOOTH_HCI_FLOW) + SER_bt_WakeUp (); +#endif + /* + * The specified UART is no more set up for Deep Sleep. + */ + + uart->deep_sleep_set_up = 0; + + } + } +} + + +/******************************************************************************* + * + * SER_restart_uart_sleep_timer + * + * Purpose : Resets and restarts the sleep timer each time some characters are + * received. + * + * Arguments: In : none + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +void +SER_restart_uart_sleep_timer (void) +{ + /* + * First disable the timer. + */ + + (void) NU_Control_Timer (&uart_sleep_timer, + NU_DISABLE_TIMER); + + /* + * Then start again this timer for a new period. + */ + + start_uart_sleep_timer (); +} + + +/******************************************************************************* + * + * SER_activate_timer_hisr + * + * Purpose : Activates the timer HISR to reset and restart the sleep timer + * each time some characters are received. + * + * Arguments: In : none + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +void +SER_activate_timer_hisr (void) +{ + (void) NU_Activate_HISR (&timer_hisr_ctrl_block); +} + + +#if ((CHIPSET == 2) || (CHIPSET == 3)) + +/******************************************************************************* + * + * SER_uart_handler + * + * Purpose : UART interrupt handler. + * + * Arguments: In : none + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +void +SER_uart_handler (void) +{ + SYS_UWORD8 interrupt_status; + t_uart *uart; + int uart_id; + SYS_BOOL it_identified; + + it_identified = 0; + + /* + * Check first for a wake-up interrupt. + */ + + uart_id = 0; + while ((uart_id < NUMBER_OF_TR_UART) && + (!it_identified)) { + + uart = &(int_uart[uart_id]); + interrupt_status = READ_UART_REGISTER (uart, SSR); + + if (interrupt_status & RX_CTS_WAKE_UP_STS) { /* Wake-up IT has occurred */ + + it_identified = 1; + uart_sleep_timer_enabled = 1; + DISABLE_WAKE_UP_INTERRUPT (uart); + } + + uart_id++; + } + + /* + * If no wake-up interrupt has been detected, check then systematically + * both UARTs for other interrupt causes. + */ + + if (!it_identified) { + + for (uart_id = 0; uart_id < NUMBER_OF_TR_UART; uart_id++) { + + uart = &(int_uart[uart_id]); + interrupt_status = READ_UART_REGISTER (uart, IIR) & IIR_BITS_USED; + + if (!(interrupt_status & IT_NOT_PENDING)) { + + it_identified = 1; + (*(uart->interrupt_handler)) (uart_id, interrupt_status); + + } else { + + if ((uart_id == UA_UART_1) && (!it_identified)) + uart_spurious_interrupts++; + } + } + } +} + +#elif ((CHIPSET == 4) || (CHIPSET == 5) || (CHIPSET == 6) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12)) + +/******************************************************************************* + * + * SER_uart_modem_handler + * + * Purpose : UART MODEM interrupt handler. + * + * Arguments: In : none + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +void +SER_uart_modem_handler (void) +{ + SYS_UWORD8 interrupt_status; + t_uart *uart; + SYS_BOOL it_wakeup_identified; + + it_wakeup_identified = 0; + uart = &(int_uart[UA_UART_1]); + + /* + * Check first for a wake-up interrupt. + */ + + interrupt_status = READ_UART_REGISTER (uart, SSR); + + if (interrupt_status & RX_CTS_WAKE_UP_STS) { /* Wake-up IT has occurred */ + + it_wakeup_identified = 1; + uart_sleep_timer_enabled = 1; +#ifdef BTEMOBILE + if (uart->flow_type == BLUETOOTH_HCI_FLOW) + { + interrupt_status = READ_UART_REGISTER (uart, IIR) & IIR_BITS_USED; + (*(uart->interrupt_handler)) (UA_UART_1, interrupt_status); + } +#endif /* BTEMOBILE */ + DISABLE_WAKE_UP_INTERRUPT (uart); + } + + /* + * If no wake-up interrupt has been detected, check UART for other + * interrupt causes. + */ + + if (!it_wakeup_identified) { + + interrupt_status = READ_UART_REGISTER (uart, IIR) & IIR_BITS_USED; + + if (!(interrupt_status & IT_NOT_PENDING)) + (*(uart->interrupt_handler)) (UA_UART_1, interrupt_status); + + else + uart_modem_spurious_interrupts++; + } +} + + +/******************************************************************************* + * + * SER_uart_irda_handler + * + * Purpose : UART IrDA interrupt handler. + * + * Arguments: In : none + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +void +SER_uart_irda_handler (void) +{ + SYS_UWORD8 interrupt_status; + t_uart *uart; + SYS_BOOL it_wakeup_identified; + + it_wakeup_identified = 0; + uart = &(int_uart[UA_UART_0]); + + /* + * Check first for a wake-up interrupt. + */ + + interrupt_status = READ_UART_REGISTER (uart, SSR); + + if (interrupt_status & RX_CTS_WAKE_UP_STS) { /* Wake-up IT has occurred */ + + it_wakeup_identified = 1; + uart_sleep_timer_enabled = 1; +#ifdef BTEMOBILE + if (uart->flow_type == BLUETOOTH_HCI_FLOW) + { + interrupt_status = READ_UART_REGISTER (uart, IIR) & IIR_BITS_USED; + (*(uart->interrupt_handler)) (UA_UART_0, interrupt_status); + } +#endif /* BTEMOBILE */ + DISABLE_WAKE_UP_INTERRUPT (uart); + } + + /* + * If no wake-up interrupt has been detected, check UART for other + * interrupt causes. + */ + + if (!it_wakeup_identified) { + + interrupt_status = READ_UART_REGISTER (uart, IIR) & IIR_BITS_USED; + + if (!(interrupt_status & IT_NOT_PENDING)) + (*(uart->interrupt_handler)) (UA_UART_0, interrupt_status); + + else + uart_irda_spurious_interrupts++; + } +} + +#endif + +#if (CHIPSET == 12) + /******************************************************************************* + * + * SER_uart_modem2_handler + * + * Purpose : UART IrDA interrupt handler. + * + * Arguments: In : none + * Out: none + * + * Returns : none + * + ******************************************************************************/ + + void + SER_uart_modem2_handler (void) + { + SYS_UWORD8 interrupt_status; + t_uart *uart; + SYS_BOOL it_wakeup_identified; + + it_wakeup_identified = 0; + uart = &(int_uart[UA_UART_2]); + + /* + * Check first for a wake-up interrupt. + */ + + interrupt_status = READ_UART_REGISTER (uart, SSR); + + if (interrupt_status & RX_CTS_WAKE_UP_STS) { /* Wake-up IT has occurred */ + + it_wakeup_identified = 1; + uart_sleep_timer_enabled = 1; +#ifdef BTEMOBILE + if (uart->flow_type == BLUETOOTH_HCI_FLOW) + { + interrupt_status = READ_UART_REGISTER (uart, IIR) & IIR_BITS_USED; + (*(uart->interrupt_handler)) (UA_UART_2, interrupt_status); + } +#endif /* BTEMOBILE */ + DISABLE_WAKE_UP_INTERRUPT (uart); + } + + /* + * If no wake-up interrupt has been detected, check UART for other + * interrupt causes. + */ + + if (!it_wakeup_identified) { + + interrupt_status = READ_UART_REGISTER (uart, IIR) & IIR_BITS_USED; + + if (!(interrupt_status & IT_NOT_PENDING)) + (*(uart->interrupt_handler)) (UA_UART_2, interrupt_status); + + else + uart_modem2_spurious_interrupts++; + } + } + +#endif + +/* + * Temporary functions. + * + * FreeCalypso note: I'll put them back in if they are actually needed. + */ + +#if 0 + +void +UT_Init (int device_id, + int baudrate, + void (callback_function (void))) +{ + SER_tr_Init (SER_PROTOCOL_STACK, baudrate, callback_function); +} + +SYS_UWORD32 +UT_ReadNChars (int device_id, + char *buffer, + SYS_UWORD32 chars_to_read) +{ + return (SER_tr_ReadNChars (SER_PROTOCOL_STACK, buffer, chars_to_read)); +} + +SYS_UWORD32 +UT_WriteNChars (int device_id, + char *buffer, + SYS_UWORD32 chars_to_write) +{ + return (SER_tr_WriteNChars (SER_PROTOCOL_STACK, buffer, chars_to_write)); +} + +void +UT_WriteChar (int device_id, + char character) +{ + SER_tr_WriteChar (SER_PROTOCOL_STACK, character); +} + +void +UT_WriteString (int device_id, + char *buffer) +{ + SER_tr_WriteString (SER_PROTOCOL_STACK, buffer); +} + +short +UF_Init (SYS_UWORD8 deviceNo) +{ + return (SER_fd_Init ()); +} + +short +UF_Enable (SYS_UWORD8 deviceNo, + SYS_BOOL enable) +{ + return (SER_fd_Enable (enable)); +} + +short +UF_SetComPar (SYS_UWORD8 deviceNo, + T_baudrate baudrate, + T_bitsPerCharacter bpc, + T_stopBits sb, + T_parity parity) +{ + return (SER_fd_SetComPar (baudrate, + bpc, + sb, + parity)); +} + +short +UF_SetBuffer (SYS_UWORD8 deviceNo, + SYS_UWORD16 bufSize, + SYS_UWORD16 rxThreshold, + SYS_UWORD16 txThreshold) +{ + return (SER_fd_SetBuffer (bufSize, rxThreshold, txThreshold)); +} + +short +UF_SetFlowCtrl (SYS_UWORD8 deviceNo, + T_flowCtrlMode fcMode, + SYS_UWORD8 XON, + SYS_UWORD8 XOFF) +{ + return (SER_fd_SetFlowCtrl (fcMode, XON, XOFF)); +} + +short +UF_SetEscape (SYS_UWORD8 deviceNo, + SYS_UWORD8 escChar, + SYS_UWORD16 guardPeriod) +{ + return (SER_fd_SetEscape (escChar, guardPeriod)); +} + +short +UF_InpAvail (SYS_UWORD8 deviceNo) +{ + return (SER_fd_InpAvail ()); +} + +short +UF_OutpAvail (SYS_UWORD8 deviceNo) +{ + return (SER_fd_OutpAvail ()); +} + +short +UF_ReadData (SYS_UWORD8 deviceNo, + T_suspendMode suspend, + void (readOutFunc (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 nsource, + SYS_UWORD8 *source[], + SYS_UWORD16 size[], + SYS_UWORD32 state))) +{ + return (SER_fd_ReadData (suspend, readOutFunc)); +} + +short +UF_WriteData (SYS_UWORD8 deviceNo, + T_suspendMode suspend, + void (writeInFunc (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 ndest, + SYS_UWORD8 *dest[], + SYS_UWORD16 size[]))) +{ + return (SER_fd_WriteData (suspend, writeInFunc)); +} + +short +UF_StopRec (SYS_UWORD8 deviceNo) +{ + return (SER_fd_StopRec ()); +} + +short +UF_StartRec (SYS_UWORD8 deviceNo) +{ + return (SER_fd_StartRec ()); +} + +short +UF_GetLineState (SYS_UWORD8 deviceNo, + SYS_UWORD32 *state) +{ + return (SER_fd_GetLineState (state)); +} + +short +UF_SetLineState (SYS_UWORD8 deviceNo, + SYS_UWORD32 state, + SYS_UWORD32 mask) +{ + return (SER_fd_SetLineState (state, mask)); +} + +short +UF_CheckXEmpty (SYS_UWORD8 deviceNo) +{ + return (SER_fd_CheckXEmpty ()); +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/serial/debug-chases/uartfax.c Thu Apr 30 01:46:26 2015 +0000 @@ -0,0 +1,5161 @@ +/******************************************************************************* + * + * UARTFAX.C + * + * This driver allows to control the UARTs of chipset 1.5 for fax and data + * services. It performs flow control: RTS/CTS, XON/XOFF. + * + * On C & D-Sample, DCD and DTR signals are supported on UART modem only with 2 + * I/Os. + * + * On E-Sample, DCD and DTR signals are directly handled by Calypso+. + * + * On Calypso, RTS and CTS are supported on both UARTs. + * + * On Calypso+, RTS and CTS are supported on UART Modem1 & IrDA. UART Modem2 is + * not available through DB9 connector on E-Sample. + * + * (C) Texas Instruments 1999 - 2003 + * + ******************************************************************************/ + +/* + * E-Sample + * + * UART Modem1 UART Irda + * + * DB9 Calypso+ DB9 Calypso+ + * + * 1 DCD DCD output 1 1, 6 and 4 are connected together on DB9 + * 2 RX TX output 2 RX TX2 output + * 3 TX RX input 3 TX RX2 input + * 4 DTR DSR input 4 + * 5 GND 5 GND + * 6 NC 6 + * 7 RTS CTS input 7 RTS CTS2 input + * 8 CTS RTS output 8 CTS RTS2 output + * 9 NC 9 NC + * + */ + +/* + * C & D-Sample + * + * UART Modem UART Irda + * + * DB9 Calypso DB9 Calypso + * + * 1 DCD I/O 2 output 1 1, 6 and 4 are connected together on DB9 + * 2 RX TX output 2 RX TX2 output + * 3 TX RX input 3 TX RX2 input + * 4 DTR I/O 3 input 4 + * 5 GND 5 GND + * 6 NC 6 + * 7 RTS CTS input 7 RTS CTS2 input + * 8 CTS RTS output 8 CTS RTS2 output + * 9 NC 9 NC + * + */ + +/* + * B-Sample + * + * UART Modem UART Irda + * + * DB9 Ulysse DB9 Ulysse + * + * 1 1, 6 and 4 are connected together on DB9 (Modem and Irda) + * 2 RX TX 2 RX TX + * 3 TX RX 3 TX RX + * 4 4 + * 5 GND 5 GND + * 6 6 + * 7 RTS CTS 7 7 and 8 are connected together on DB9 + * 8 CTS RTS 8 + * 9 NC 9 NC + * + */ + +#include "../include/config.h" + +#include <string.h> + +/* + * rv_general.h is needed for macros Min & Min3. + */ +#include "../riviera/rv/rv_general.h" +#include "../nucleus/nucleus.h" + +#include "../include/sys_types.h" +#include "faxdata.h" +#include "uartfax.h" + +/* + * Needed to reset and restart the sleep timer in case of incoming characters. + */ + +#include "serialswitch.h" +extern SYS_BOOL uart_sleep_timer_enabled; + +#include "../bsp/mem.h" + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41)) + #include "../bsp/armio.h" +#endif + +#define HighGPIO AI_SetBit +#define LowGPIO AI_ResetBit + +/* + * Maximal value for an unsigned 32 bits. + */ + +#define MAX_UNSIGNED_32 (4294967295) + +#define FIFO_SIZE (64) /* In bytes. */ + + +/* + * TLR is used to program the RX FIFO trigger levels. FCR[7:4] are not used. + * No trigger level used for TX FIFO. THR_IT generated on TX FIFO empty. + */ + +#define RX_FIFO_TRIGGER_LEVEL (12 << 4) + + +/* + * 16750 addresses. Registers accessed when LCR[7] = 0. + */ + +#define RHR (0x00) /* Rx buffer register - Read access */ +#define THR (0x00) /* Tx holding register - Write access */ +#define IER (0x01) /* Interrupt enable register */ + +/* + * 16750 addresses. Registers accessed when LCR[7] = 1. + */ + +#define DLL (0x00) /* Divisor latch (LSB) */ +#define DLM (0x01) /* Divisor latch (MSB) */ + + +/* + * EFR is accessed when LCR[7:0] = 0xBF. + */ + +#define EFR (0x02) /* Enhanced feature register */ + + +/* + * 16750 addresses. Bit 5 of the FCR register is accessed when LCR[7] = 1. + */ + +#define IIR (0x02) /* Interrupt ident. register - Read only */ +#define FCR (0x02) /* FIFO control register - Write only */ +#define LCR (0x03) /* Line control register */ +#define MCR (0x04) /* Modem control register */ +#define LSR (0x05) /* Line status register */ +#define MSR (0x06) /* Modem status register */ +#define TCR (0x06) /* Transmission control register */ +#define TLR (0x07) /* Trigger level register */ +#define MDR1 (0x08) /* Mode definition register 1 */ +#define SCR (0x10) /* Supplementary Control register */ +#define SSR (0x11) /* Supplementary Status register */ +#define UASR (0x0E) /* Autobauding Status register */ + +/* + * Supplementary control register. + */ + +#define TX_EMPTY_CTL_IT (0x08) +#define RX_CTS_WAKE_UP_ENABLE_BIT (4) /* Use RESET_BIT and SET_BIT macros. */ +#define DSR_IT_BIT (5) /* Use RESET_BIT and SET_BIT macros. */ + +/* + * Enhanced feature register. + */ + +#define ENHANCED_FEATURE_BIT (4) /* Use RESET_BIT and SET_BIT macros. */ +#define AUTO_CTS_BIT (7) /* Transmission is halted when the CTS pin is high (inactive). */ + +/* + * Mode definition register 1. + */ + +#define UART_MODE (0x00) +#define SIR_MODE (0x01) +#define UART_MODE_AUTOBAUDING (0x02) /* Reserved in UART/IrDA. */ +#define RESET_DEFAULT_STATE (0x07) +#define IR_SLEEP_DISABLED (0x00) +#define IR_SLEEP_ENABLED (0x08) +#define SIR_TX_WITHOUT_ACREG2 (0x00) /* Reserved in UART/modem. */ +#define SIR_TX_WITH_ACREG2 (0x20) /* Reserved in UART/modem. */ +#define FRAME_LENGTH_METHOD (0x00) /* Reserved in UART/modem. */ +#define EOT_BIT_METHOD (0x80) /* Reserved in UART/modem. */ + +/* + * Supplementary Status Register + */ + +#define TX_FIFO_FULL (0x01) + + +/* + * Interrupt enable register. + */ + +#define ERBI (0x01) /* Enable received data available interrupt */ +#define ETBEI (0x02) /* Enable transmitter holding register empty interrupt */ +#define ELSI (0x04) /* Enable receiver line status interrupt */ +#define EDSSI (0x08) /* Enable modem status interrupt */ +#define IER_SLEEP (0x10) /* Enable sleep mode */ + +/* + * Modem control register. + */ + +#define MDCD (0x01) /* Data Carrier Detect. */ +#define MRTS (0x02) /* Request To Send. */ +#define TCR_TLR_BIT (6) + +/* + * Line status register. + */ + +#define DR (0x01) /* Data ready */ +#define OE (0x02) /* Overrun error */ +#define PE (0x04) /* Parity error */ +#define FE (0x08) /* Framing error */ +#define BI (0x10) /* Break interrupt */ +#define THRE (0x20) /* Transmitter holding register (FIFO empty) */ +#define TEMT (0x40) /* Transmitter empty (FIFO and TSR both empty) */ + +#define BYTE_ERROR (OE | PE | FE | BI) + +/* + * Interrupt identification register. + * Bit 0 is set to 0 if an IT is pending. + * Bits 1 and 2 are used to identify the IT. + */ + +#define IIR_BITS_USED (0x07) +#define IT_PENDING (0x01) +#define RX_DATA (0x04) +#define TX_EMPTY (0x02) +#define MODEM_STATUS (0x00) + +/* + * Modem status register. + */ + +#define DELTA_CTS (0x01) +#define DELTA_DSR (0x02) +#define MCTS (0x10) /* Clear to send */ +#define MDSR (0x20) /* Data set ready */ + +/* + * Line control register. + */ + +#define WLS_5 (0x00) /* Word length: 5 bits */ +#define WLS_6 (0x01) /* Word length: 6 bits */ +#define WLS_7 (0x02) /* Word length: 7 bits */ +#define WLS_8 (0x03) /* Word length: 8 bits */ +#define STB (0x04) /* Number of stop bits: 0: 1, 1: 1,5 or 2 */ +#define PEN (0x08) /* Parity enable */ +#define EPS (0x10) /* Even parity select */ +#define BREAK_CONTROL (0x40) /* Enable a break condition */ +#define DLAB (0x80) /* Divisor latch access bit */ + +/* + * FIFO control register. + */ + +#define FIFO_ENABLE (0x01) +#define RX_FIFO_RESET (0x02) +#define TX_FIFO_RESET (0x04) + +/* + * These constants define the states of the escape sequence detection. + */ + +#define INITIALIZATION (0) +#define NO_ESCAPE_SEQUENCE (1) +#define ONE_CHAR_DETECTED (2) +#define TWO_CHARS_DETECTED (3) +#define THREE_CHARS_DETECTED (4) + +#define CHARACTERS_IN_ESC_SEQ (3) +#define DEFAULT_ESC_SEQ_CHARACTER '+' +#define DEFAULT_GUARD_PERIOD (1000) /* 1 second. */ + +/* + * 3 HISR are used to avoid to execute operations from the LISR. + */ + +#define RX_HISR_PRIORITY (2) + + + + +// NGENGE increase hisr stack otherwise overflows with multiple callbacks +//#define RX_HISR_STACK_SIZE (512) /* Bytes. */ +#define RX_HISR_STACK_SIZE (768) /* Bytes. */ + + + + +#define TX_HISR_PRIORITY (2) + + + +// NGENGE increase hisr stack otherwise overflows with multiple callbacks +//#define TX_HISR_STACK_SIZE (512) /* Bytes. */ +#define TX_HISR_STACK_SIZE (768) /* Bytes. */ + + + + +#define V24_HISR_PRIORITY (2) +#define V24_HISR_STACK_SIZE (512) /* Bytes. */ + +/* + * When the break interrupt indicator (BI) is set in the line status register + * (LSR), it indicates that the received data input was held in the low state + * for longer than a full-word transmission time. In the FIFO mode, when a break + * occurs, only one 0 character is loaded into the FIFO. The next character + * transfer is enabled after SIN goes to the marking state for at least two RCLK + * samples and then receives the next valid start bit. + * This constant defined a defined break length returned by the US_GetLineState + * function. + */ + +#define MINIMAL_BREAK_LENGTH (2) + +#define BREAK_HISR_PRIORITY (2) +#define BREAK_HISR_STACK_SIZE (512) /* Bytes. */ + +/* + * These macros allow to read and write a UART register. + */ + +#define READ_UART_REGISTER(UART,REG) \ + *((volatile SYS_UWORD8 *) ((UART)->base_address + (REG))) + +#define WRITE_UART_REGISTER(UART,REG,VALUE) \ + *((volatile SYS_UWORD8 *) ((UART)->base_address + (REG))) = (VALUE) + +#define RESET_BIT(UART,REG,BIT) \ + (WRITE_UART_REGISTER ( \ + UART, REG, READ_UART_REGISTER (UART, REG) & ~(1 << (BIT)))) + +#define SET_BIT(UART,REG,BIT) \ + (WRITE_UART_REGISTER ( \ + UART, REG, READ_UART_REGISTER (UART, REG) | (1 << (BIT)))) + + +/* + * These macros allow to enable or disable the wake-up interrupt. + */ + +#define ENABLE_WAKEUP_INTERRUPT(UART) \ + SET_BIT(UART, SCR, RX_CTS_WAKE_UP_ENABLE_BIT); + +#define DISABLE_WAKEUP_INTERRUPT(UART) \ + RESET_BIT(UART, SCR, RX_CTS_WAKE_UP_ENABLE_BIT); + + +/* + * These macros allow to enable or disable the DSR interrupt. + */ + +#define ENABLE_DSR_INTERRUPT(UART) \ + SET_BIT(UART, SCR, DSR_IT_BIT); + +#define DISABLE_DSR_INTERRUPT(UART) \ + RESET_BIT(UART, SCR, DSR_IT_BIT); + + +/* + * The transmitter is disabled only when the application disables the driver. + * To disable the driver, the receiver and the transmitter are disabled by the + * application. The transmitter is disabled first to test if the driver is + * disabled. + */ + +#define DRIVER_DISABLED(UART) ((UART)->tx_stopped_by_application) + +#define DISABLE_DRIVER(UART) \ + { \ + (UART)->tx_stopped_by_application = 1; \ + (UART)->rx_stopped_by_application = 1; \ + } + +#define ENABLE_DRIVER(UART) \ + { \ + (UART)->rx_stopped_by_application = 0; \ + (UART)->tx_stopped_by_application = 0; \ + } + +/* + * Low and high watermarks for the RX buffer. If it is enabled, the flow + * control is activated or deactivated according to these values. + * The high watermark value allows to copy an array filled with the RX FIFO + * into the RX buffer. + */ + +#define RX_LOW_WATERMARK(RX_BUFFER_SIZE) (FIFO_SIZE) +#define RX_HIGH_WATERMARK(RX_BUFFER_SIZE) ((RX_BUFFER_SIZE) - 2 * FIFO_SIZE) + +/* + * This macro allows to know if the RX buffer is full. It must be called only + * from the RX HISR. If it is called from the application, the rx_in and + * rx_fifo_in pointers may be updated if a RX interrupt occurs or if the + * RX HISR is activated. + */ + +#define RX_BUFFER_FULL(UART) \ + (((UART)->rx_in == (UART)->rx_out - 1) || \ + ((UART)->rx_in == (UART)->rx_out + (UART)->buffer_size)) + +/* + * This macro allows to know if the TX buffer is empty. + */ + +#define TX_BUFFER_EMPTY(UART) \ + ((UART)->tx_in == (UART)->tx_out) + +/* + * This macro is used to convert a time (unit: ms) into a number of TDMA. + * 1 TDMA = 4.6 ms (23/5). + */ + +#define CONVERT_TIME_IN_TDMA(TIME) (((TIME) * 5) / 23) + +/* + * This structure describes an UART compatible with the UART 16750 and + * contains some fields to manage this UART. + */ + +typedef struct s_uart { + + SYS_UWORD32 base_address; + + /* + * HISR executed from the RX/TX interrupt handler. + */ + + NU_HISR rx_hisr_ctrl_block; + NU_HISR tx_hisr_ctrl_block; + NU_HISR v24_hisr_ctrl_block; + + char rx_hisr_stack[RX_HISR_STACK_SIZE]; + char tx_hisr_stack[TX_HISR_STACK_SIZE]; + char v24_hisr_stack[V24_HISR_STACK_SIZE]; + + /* + * 2 arrays are used to store bytes read in RX FIFO. A UART RX interrupt + * may occur while executing RX operations in RX HISR. To avoid overwriting + * the array in which received bytes are stored, a second array is used. + */ + + SYS_UWORD8 *rx_buffer_used_by_rx_lisr; + SYS_UWORD8 *rx_buffer_used_by_rx_hisr; + SYS_UWORD8 rx_fifo_byte_1[FIFO_SIZE]; + SYS_UWORD8 rx_fifo_byte_2[FIFO_SIZE]; + SYS_UWORD16 bytes_in_rx_buffer_1; + SYS_UWORD16 bytes_in_rx_buffer_2; + + /* + * RX and TX buffers. + * One character is not used in each buffer to allow to know if the buffer + * is empty or not (See macro RX_BUFFER_FULL). If buffers are empty, + * rx_in = rx_out and tx_in = tx_out. It is impossible to use fields to + * count the number of bytes in each buffer because these fields may be + * updated from the application and from the interrupt handlers. That avoids + * to have conflicts. + */ + + SYS_UWORD16 buffer_size; + SYS_UWORD16 rx_threshold_level; + SYS_UWORD16 tx_threshold_level; + SYS_UWORD8 rx_buffer[FD_MAX_BUFFER_SIZE + 1]; + SYS_UWORD8 tx_buffer[FD_MAX_BUFFER_SIZE + 1]; + SYS_UWORD8 *rx_in; + SYS_UWORD8 *rx_out; + SYS_UWORD8 *tx_in; + SYS_UWORD8 *tx_out; + + /* + * Escape sequence. + * the field esc_seq_modified may have 2 values: + * - 0: No modification. + * - 1: Parameters are in the process of modification: The detection + * is stopped. + */ + + NU_TIMER guard_period_timer_ctrl_block; + SYS_UWORD8 esc_seq_modified; + SYS_UWORD8 esc_seq_detection_state; + SYS_UWORD8 esc_seq_character; + UNSIGNED guard_period; + UNSIGNED current_time; + UNSIGNED previous_time; + + /* + * Flow control. + */ + + T_flowCtrlMode flow_control_mode; + SYS_BOOL send_xon_xoff; + SYS_UWORD8 xon_xoff_to_send; + SYS_UWORD8 xon_character; + SYS_UWORD8 xoff_character; + SYS_BOOL rx_stopped_by_application; + SYS_BOOL rx_stopped_by_driver; + SYS_BOOL rx_stopped_by_lisr; + SYS_BOOL tx_stopped_by_application; + SYS_BOOL tx_stopped_by_driver; + /* SYS_BOOL tx_stopped_by_lisr;*/ + + /* + * Break. + */ + + SYS_BOOL break_received; + SYS_BOOL break_to_send; + SYS_BOOL break_in_progress; + NU_HISR break_hisr_ctrl_block; + char break_hisr_stack[BREAK_HISR_STACK_SIZE]; + NU_TIMER break_timer_ctrl_block; + UNSIGNED baudrate; + UNSIGNED autobauding; + UNSIGNED bits_per_char; /* Including start, stop and parity bits. */ + UNSIGNED break_length; /* In bytes. */ + UNSIGNED time_without_character; + + /* + * Callback (UAF_ReadData and UAF_WriteData). + * rd: read, wr: write. + */ + + SYS_BOOL esc_seq_received; + SYS_UWORD8 rts_level; /* RTS on RS232 side, CTS on chipset side. + 1: The RS232 line is deactivated (low). */ + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + SYS_UWORD8 dtr_level; /* Controlled with an I/O on C & D-Sample and + handled by Calypso+ on E-Sample. + 1: The RS232 line is deactivated (low). */ + /* + * When the DTR interrupt is detected the user's Rx callback function must + * be called but if the Rx FIFO is not empty the Rx HISR must be activated + * to read the bytes received in the Rx FIFO and to put them into the Rx + * buffer before to call the user's Rx callback function. + * If the Rx HISR is activated due to a Rx interrupt the user's Rx callback + * function will be called if conditions to call it are fulfilled. If it is + * activated due to the DTR interrupt the user's Rx callback function must + * be called without any conditions. + * Because the Rx HISR may have been activated but not executed before the + * DTR interrupt we must be sure that the user's Rx callback function will + * be called for each Rx HISR activation. Call is done for Rx HISR activated + * on Rx interrupt if conditions are fulfilled. + * A circular buffer of 2 elements is used to memorize the source of + * interrupt. Before the activation of the Rx HISR, the source of interrupt + * is memorized into this array. When the code of the Rx HISR is executed + * the user's Rx callback function is called if the source of interrupt was + * the DTR interrupt regardless of the other conditions. + * The level of DTR is saved to provide the level detected on Rx interrupt + * or DTR interrupt in the 'state' parameter of the user's Rx callback + * function. + */ + + SYS_BOOL dtr_change_detected[2]; + SYS_UWORD8 dtr_level_saved[2]; + SYS_UWORD8 index_it; + SYS_UWORD8 index_hisr; +#endif /* BOARD 8 or 9 or 40 or 41 or CHIPSET 12 */ + + SYS_BOOL reading_suspended; + SYS_BOOL writing_suspended; + SYS_BOOL rd_call_from_hisr_in_progress; + SYS_BOOL wr_call_from_hisr_in_progress; + T_reInstMode rd_call_setup; + T_reInstMode wr_call_setup; + SYS_UWORD8 *rd_address[2]; + SYS_UWORD8 *wr_address[2]; + SYS_UWORD16 rd_size_before_call[2]; + SYS_UWORD16 rd_size_after_call[2]; + SYS_UWORD16 wr_size_before_call[2]; + SYS_UWORD16 wr_size_after_call[2]; + + void (*readOutFunc) (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 nsource, + SYS_UWORD8 *source[], + SYS_UWORD16 size[], + SYS_UWORD32 state); + + void (*writeInFunc) (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 ndest, + SYS_UWORD8 *dest[], + SYS_UWORD16 size[]); + + /* + * These fields are used to store the state defined in UAF_GetLineState.The + * first field is used when UAF_GetLineState and UAF_ReadData are not called. + * When one of these functions is called the second field is used. That + * avoids to lose events when UAF_GetLineState or UAF_ReadData resets the + * first field. + */ + + SYS_UWORD32 state_1; + SYS_UWORD32 state_2; + SYS_UWORD32 *state; + + /* + * Errors counters. + */ + + SYS_UWORD32 framing_error; + SYS_UWORD32 parity_error; + SYS_UWORD32 overrun_error; + SYS_UWORD32 spurious_interrupts; + + SYS_UWORD16 max_rx_fifo_level; + +} t_uart; + + +static t_uart uart_parameters; + + +static const SYS_UWORD32 base_address[NUMBER_OF_FD_UART] = +{ + MEM_UART_IRDA, + MEM_UART_MODEM + #if (CHIPSET == 12) + , MEM_UART_MODEM2 + #endif +}; + + +/* + * DLL (LSB) and DLH (MSB) registers values using the 13 MHz clock. + */ + +static const SYS_UWORD8 dll[] = +{ + 0, /* Auto baud: */ + 81, /* 75 baud. */ + 40, /* 150 baud. */ + 148, /* 300 baud. */ + 74, /* 600 baud. */ + 165, /* 1200 baud. */ + 83, /* 2400 baud. */ + 169, /* 4800 baud. */ + 113, /* 7200 baud. */ + 84, /* 9600 baud. */ + 56, /* 14400 baud. */ + 42, /* 19200 baud. */ + 28, /* 28800 baud. */ + 24, /* 33900 baud: not supported. */ + 21, /* 38400 baud. */ + 14, /* 57600 baud. */ + 7, /* 115200 baud. */ + 0, /* 203125 baud: not supported. */ + 0, /* 406250 baud: not supported. */ + 0 /* 812500 baud: not supported. */ +}; + +static const SYS_UWORD8 dlh[] = +{ + 0, /* Auto baud: */ + 42, /* 75 baud. */ + 21, /* 150 baud. */ + 10, /* 300 baud. */ + 5, /* 600 baud. */ + 2, /* 1200 baud. */ + 1, /* 2400 baud. */ + 0, /* 4800 baud. */ + 0, /* 7200 baud. */ + 0, /* 9600 baud. */ + 0, /* 14400 baud. */ + 0, /* 19200 baud. */ + 0, /* 28800 baud. */ + 0, /* 33900 baud: not supported. */ + 0, /* 38400 baud. */ + 0, /* 57600 baud. */ + 0, /* 115200 baud. */ + 0, /* 203125 baud: not supported. */ + 0, /* 406250 baud: not supported. */ + 0 /* 812500 baud: not supported. */ +}; + +static const UNSIGNED baudrate_value[] = +{ + 1, + 75, + 150, + 300, + 600, + 1200, + 2400, + 4800, + 7200, + 9600, + 14400, + 19200, + 28800, + 0, /* Not supported. */ + 38400, + 57600, + 115200, + 0, /* Not supported. */ + 0, /* Not supported. */ + 0 /* Not supported. */ +}; + + + + +/******************************************************************************* + * + * get_bytes_in_rx_buffer + * + * Purpose : Gets the number of bytes in the RX buffer. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : The number of bytes in the RX buffer. + * + ******************************************************************************/ + +static SYS_UWORD16 +get_bytes_in_rx_buffer (t_uart *uart) +{ + SYS_UWORD16 bytes_in_rx_buffer; + volatile SYS_UWORD8 *rx_in; + + rx_in = uart->rx_in; + + if (uart->rx_out <= rx_in) + bytes_in_rx_buffer = (SYS_UWORD16) (rx_in - uart->rx_out); + else + bytes_in_rx_buffer = + (SYS_UWORD16) (rx_in - uart->rx_out + uart->buffer_size + 1); + + return (bytes_in_rx_buffer); +} + +/******************************************************************************* + * + * get_bytes_in_tx_buffer + * + * Purpose : Gets the number of bytes in the TX buffer. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : The number of bytes in the TX buffer. + * + ******************************************************************************/ + +static SYS_UWORD16 +get_bytes_in_tx_buffer (t_uart *uart) +{ + SYS_UWORD16 bytes_in_tx_buffer; + volatile SYS_UWORD8 *tx_out; + + tx_out = uart->tx_out; + + if (tx_out <= uart->tx_in) + bytes_in_tx_buffer = (SYS_UWORD16) (uart->tx_in - tx_out); + else + bytes_in_tx_buffer = + (SYS_UWORD16) (uart->tx_in - tx_out + uart->buffer_size + 1); + + return (bytes_in_tx_buffer); +} + +/******************************************************************************* + * + * compute_break_time + * + * Purpose : Computes a number of TDMA from 3 parameters: + * - baudrate, + * - bits per character including start bit, stop bits and parity, + * - number of characters. + * Due to the TDMA value (4.6 ms), a minimal value is sent: 2 TDMA. + * + * Arguments: In : baudrate + * bits_per_char + * number_of_chars + * Out: none + * + * Returns : The number of TDMA. + * + ******************************************************************************/ + +static UNSIGNED +compute_break_time (UNSIGNED baudrate, + UNSIGNED bits_per_char, + UNSIGNED number_of_chars) +{ + UNSIGNED number_of_tdma; + + number_of_tdma = CONVERT_TIME_IN_TDMA ( + 1000 * bits_per_char * number_of_chars / baudrate); + + if (number_of_tdma == 0) + number_of_tdma = 1; + + number_of_tdma++; + + return (number_of_tdma); +} + +/******************************************************************************* + * + * update_reading_callback + * + * Purpose : Updates the sizes array and the addresses array and get and builds + * the state parameter defined in UAF_GetLineState to call the + * readOutFunc function. + * + * Arguments: In : uart : Pointer on the UART structure. + * call_source: 0: application, 1: HISR (Rx or V24), 3: Rx HISR + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static void +update_reading_callback (t_uart *uart, + SYS_BOOL call_source) +{ + SYS_UWORD32 state; + SYS_UWORD8 dtr_level; + SYS_UWORD8 fragments_number; + SYS_UWORD16 bytes_in_rx_buffer; + volatile SYS_UWORD8 *rx_in; + + /* + * Update the sizes array and the addresses array. + * A copy of rx_in is used because it may be updated by the interrupt + * handler if this function is called from the application. + */ + + rx_in = uart->rx_in; + + if (uart->rx_out < rx_in) { + + fragments_number = 1; + + uart->rd_address[0] = uart->rx_out; + uart->rd_size_before_call[0] = (SYS_UWORD16) (rx_in - uart->rx_out); + uart->rd_size_after_call[0] = uart->rd_size_before_call[0]; + + uart->rd_size_before_call[1] = 0; + uart->rd_size_after_call[1] = 0; + + bytes_in_rx_buffer = uart->rd_size_before_call[0]; + + } else if (rx_in == uart->rx_out) { /* RX buffer empty. */ + + fragments_number = 1; + + uart->rd_address[0] = uart->rx_out; + uart->rd_size_before_call[0] = 0; + uart->rd_size_after_call[0] = 0; + + uart->rd_size_before_call[1] = 0; + uart->rd_size_after_call[1] = 0; + + bytes_in_rx_buffer = 0; + + } else { + + fragments_number = 2; + + uart->rd_address[0] = uart->rx_out; + uart->rd_size_before_call[0] = + uart->buffer_size + 1 - (SYS_UWORD16) (uart->rx_out - + &(uart->rx_buffer[0])); + uart->rd_size_after_call[0] = uart->rd_size_before_call[0]; + + uart->rd_address[1] = &(uart->rx_buffer[0]); + uart->rd_size_before_call[1] = (SYS_UWORD16) (rx_in - + &(uart->rx_buffer[0])); + uart->rd_size_after_call[1] = uart->rd_size_before_call[1]; + + bytes_in_rx_buffer = + uart->rd_size_before_call[0] + uart->rd_size_before_call[1]; + + if (!uart->rd_size_before_call[1]) + fragments_number = 1; + } + + /* + * Build the state parameter defined in UAF_GetLineState. + * The field state_2 is used when state_1 is set to 0 to avoid to + * lose events detected in the RX interrupt handler. + */ + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + if (call_source == 3) /* Call from Rx HISR */ + dtr_level = uart->dtr_level_saved[uart->index_hisr]; + else + dtr_level = uart->dtr_level; +#endif + + state = uart->state_2; + uart->state_2 = 0; + uart->state = &(uart->state_2); + + state |= uart->state_1; + uart->state_1 = 0; + uart->state = &(uart->state_1); + + state |= ((((SYS_UWORD32) uart->rts_level) << RTS) | + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + (((SYS_UWORD32) dtr_level) << DTR) | +#endif + + (((SYS_UWORD32) (uart->tx_stopped_by_application | + uart->tx_stopped_by_driver)) << TXSTP) | + + (((SYS_UWORD32) (uart->rx_stopped_by_application | + uart->rx_stopped_by_driver)) << RXSTP) | + + (((SYS_UWORD32) (uart->buffer_size - bytes_in_rx_buffer)) << RXBLEV)); + + /* + * Fields SA, SB and X are set according to the flow control: + * + * None RTS/CTS XON/XOFF + * SA DTR DTR DTR + * SB RTS 0 RTS + * X 0 RTS XON:0 XOFF:1 (transmitter) + * + * DTR is supported on C, D & E-Sample. + */ + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + state |= (((SYS_UWORD32) uart->dtr_level) << SA); +#endif + + if (uart->flow_control_mode != fc_rts) + state |= (((SYS_UWORD32) uart->rts_level) << SB); + + if (uart->flow_control_mode == fc_rts) + state |= (((SYS_UWORD32) uart->rts_level) << X); + + else if ((uart->flow_control_mode == fc_xoff) && + (uart->tx_stopped_by_application || + uart->tx_stopped_by_driver)) + state |= (1 << X); + + /* + * Call the readOutFunc function with these parameters. + */ + + uart->rd_call_setup = rm_notDefined; + + (*(uart->readOutFunc)) (call_source & 0x01, /* From HISR or application */ + &(uart->rd_call_setup), + fragments_number, + &(uart->rd_address[0]), + &(uart->rd_size_after_call[0]), + state); +} + +/******************************************************************************* + * + * update_writing_callback + * + * Purpose : Updates the sizes array and the addresses array to call the + * writeInFunc function. + * + * Arguments: In : uart : Pointer on the UART structure. + * call_source: 0: application, 1: HISR + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static void +update_writing_callback (t_uart *uart, + SYS_BOOL call_source) +{ + SYS_UWORD8 fragments_number; + volatile SYS_UWORD8 *tx_out; + + /* + * Update the array of sizes and the array of addresses. + * A copy of tx_out is used because it may be updated by the interrupt + * handler if this function is called from the application. + */ + + tx_out = uart->tx_out; + + if (uart->tx_in < tx_out) { + + fragments_number = 1; + + uart->wr_address[0] = uart->tx_in; + uart->wr_size_before_call[0] = + (SYS_UWORD16) (tx_out - uart->tx_in - 1); + uart->wr_size_after_call[0] = uart->wr_size_before_call[0]; + + uart->wr_size_before_call[1] = 0; + uart->wr_size_after_call[1] = 0; + + } else if (tx_out == &(uart->tx_buffer[0])) { + + fragments_number = 1; + + uart->wr_address[0] = uart->tx_in; + uart->wr_size_before_call[0] = + uart->buffer_size - + (SYS_UWORD16) (uart->tx_in - &(uart->tx_buffer[0])); + uart->wr_size_after_call[0] = uart->wr_size_before_call[0]; + + uart->wr_size_before_call[1] = 0; + uart->wr_size_after_call[1] = 0; + + } else { + + fragments_number = 2; + + uart->wr_address[0] = uart->tx_in; + uart->wr_size_before_call[0] = + uart->buffer_size + 1 - + (SYS_UWORD16) (uart->tx_in - &(uart->tx_buffer[0])); + uart->wr_size_after_call[0] = uart->wr_size_before_call[0]; + + uart->wr_address[1] = &(uart->tx_buffer[0]); + uart->wr_size_before_call[1] = + (SYS_UWORD16) (tx_out - &(uart->tx_buffer[0]) - 1); + uart->wr_size_after_call[1] = uart->wr_size_before_call[1]; + + if (!uart->wr_size_before_call[1]) + fragments_number = 1; + } + + /* + * Call the writeInFunc function with these parameters; + */ + + uart->wr_call_setup = rm_notDefined; + + (*(uart->writeInFunc)) (call_source, + &(uart->wr_call_setup), + fragments_number, + &(uart->wr_address[0]), + &(uart->wr_size_after_call[0])); +} + +/******************************************************************************* + * + * stop_break + * + * Purpose : The timer is activated to expire when a time corresponding to the + * sending time of 2 characters at least has elapsed. After a break, + * no character may be sent during this period. + * + * Arguments: In : id: parameter not used. + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static VOID +stop_break (UNSIGNED id) +{ + t_uart *uart; + + uart = &uart_parameters; + + uart->break_to_send = 0; + uart->break_in_progress = 0; + +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Disable sleep mode. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); +#endif + + /* + * Unmask Tx interrupt. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI); +} + +/******************************************************************************* + * + * hisr_start_break + * + * Purpose : Enables the timer used to control the time without character. + * + * Arguments: In : none + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static VOID +hisr_start_break (VOID) +{ + t_uart *uart; + + uart = &uart_parameters; + + (void) NU_Control_Timer (&(uart->break_timer_ctrl_block), + NU_DISABLE_TIMER); + + (void) NU_Reset_Timer (&(uart->break_timer_ctrl_block), + stop_break, + uart->time_without_character, + 0, /* The timer expires once. */ + NU_DISABLE_TIMER); + + (void) NU_Control_Timer (&(uart->break_timer_ctrl_block), + NU_ENABLE_TIMER); +} + +/******************************************************************************* + * + * stop_receiver + * + * Purpose : Activates DTR or RTS or sends XOFF. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static void +stop_receiver (t_uart *uart) +{ +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Disable sleep mode. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); +#endif + + switch (uart->flow_control_mode) { + + case fc_rts: + + /* + * CTS (RTS on UART side) is deactivated (high). + */ + + WRITE_UART_REGISTER ( + uart, MCR, READ_UART_REGISTER (uart, MCR) & ~MRTS); + break; + + case fc_xoff: + + uart->xon_xoff_to_send = uart->xoff_character; + uart->send_xon_xoff = 1; + + /* + * Unmask Tx interrupt. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI); + break; + } +} + +/******************************************************************************* + * + * start_receiver + * + * Purpose : Deactivates DTR or RTS or sends XON. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static void +start_receiver (t_uart *uart) +{ +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Disable sleep mode. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); +#endif + + switch (uart->flow_control_mode) { + + case fc_rts: + + /* + * CTS (RTS on UART side) is activated (low). + */ + + WRITE_UART_REGISTER ( + uart, MCR, READ_UART_REGISTER (uart, MCR) | MRTS); + break; + + case fc_xoff: + + uart->xon_xoff_to_send = uart->xon_character; + uart->send_xon_xoff = 1; + + /* + * Unmask Tx interrupt. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI); + break; + } +} + +/******************************************************************************* + * + * add_esc_seq_char_in_rx_buffer + * + * Purpose : Writes one escape sequence character in the RX buffer. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static void +add_esc_seq_char_in_rx_buffer (t_uart *uart) +{ + /* + * IF the RX buffer is not full, write an escape sequence character in the + * RX buffer and check wrap-around. + */ + + if (!RX_BUFFER_FULL (uart)) { + + *(uart->rx_in++) = uart->esc_seq_character; + + if (uart->rx_in == &(uart->rx_buffer[0]) + uart->buffer_size + 1) + uart->rx_in = &(uart->rx_buffer[0]); + } +} + +/******************************************************************************* + * + * analyze_guard_period_timer_expiration + * + * Purpose : According to the state of the escape sequence detection, 1 or 2 + * escape sequence characters may be written into the TX buffer or + * the escape sequence is declared as detected. + * If 1 or 2 escape sequence characters have been detected the + * guard period must not expire. + * If 3 characters have been detected the escape sequence must + * expire. + * + * Arguments: In : id: parameter not used. + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static VOID +analyze_guard_period_timer_expiration (UNSIGNED id) +{ + t_uart *uart; + SYS_UWORD16 bytes_in_rx_buffer; + + uart = &uart_parameters; + + switch (uart->esc_seq_detection_state) { + + case ONE_CHAR_DETECTED: + + /* + * 1 escape sequence character has been detected. The guard period has + * ellapsed. This character is written into the TX buffer. + */ + + add_esc_seq_char_in_rx_buffer (uart); + break; + + case TWO_CHARS_DETECTED: + + /* + * 2 escape sequence characters have been detected. The guard period has + * ellapsed. These characters are written into the TX buffer. + */ + + add_esc_seq_char_in_rx_buffer (uart); + add_esc_seq_char_in_rx_buffer (uart); + + break; + + case THREE_CHARS_DETECTED: + + /* + * 3 escape sequence characters have been detected and the guard period + * has ellapsed. The escape sequence is detected. + */ + + uart->esc_seq_received = 1; + *(uart->state) |= (1 << ESC); + + break; + } + + uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE; + + /* + * If the high watermark is reached, RTS is activated or XOFF is sent + * according to the flow control mode. + */ + + bytes_in_rx_buffer = get_bytes_in_rx_buffer (uart); + + if ((uart->flow_control_mode != fc_none) && + (bytes_in_rx_buffer >= RX_HIGH_WATERMARK (uart->buffer_size))) { + + /* + * Check if receipt must be stopped. + */ + + if (!uart->rx_stopped_by_driver) { + + uart->rx_stopped_by_driver = 1; + if (!uart->rx_stopped_by_application) + stop_receiver (uart); + } + } + + /* + * If a reading was suspended or if the callback function is installed, + * it is called if one of these conditions is fulfiled: + * - the RX threshold level is reached, + * - a break has been detected, + * - an escape sequence has been detected, + */ + + if ((!uart->rd_call_from_hisr_in_progress) && + (uart->reading_suspended || + (uart->rd_call_setup == rm_reInstall))) { + + if ((bytes_in_rx_buffer >= uart->rx_threshold_level) || + uart->break_received || + uart->esc_seq_received) { + + uart->rd_call_from_hisr_in_progress = 1; + update_reading_callback (uart, 1); /* 1: call from HISR. */ + + uart->reading_suspended = 0; + uart->break_received = 0; + uart->esc_seq_received = 0; + } + } +} + +/******************************************************************************* + * + * stop_guard_period_timer + * + * Purpose : Stops the timer used to detect the guard period expiration. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static void +stop_guard_period_timer (t_uart *uart) +{ + (void) NU_Control_Timer (&(uart->guard_period_timer_ctrl_block), + NU_DISABLE_TIMER); +} + +/******************************************************************************* + * + * start_guard_period_timer + * + * Purpose : Starts a timer which expires if the guard period has ellapsed. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static void +start_guard_period_timer (t_uart *uart) +{ + (void) NU_Control_Timer (&(uart->guard_period_timer_ctrl_block), + NU_DISABLE_TIMER); + + (void) NU_Reset_Timer (&(uart->guard_period_timer_ctrl_block), + analyze_guard_period_timer_expiration, + uart->guard_period, + 0, /* The timer expires once. */ + NU_DISABLE_TIMER); + + (void) NU_Control_Timer (&(uart->guard_period_timer_ctrl_block), + NU_ENABLE_TIMER); +} + +/******************************************************************************* + * + * detect_escape_sequence + * + * Purpose : The state machine used to detect an escape sequence is updated + * according to the array of bytes to analyse. If the state machine + * goes to the initial state due to a break in the sequence + * detection, the previous characters are put into the RX buffer. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : 0: Break in detection or a sequence has been detected. + * 1: A sequence may be detected. + * + ******************************************************************************/ + +static int +detect_escape_sequence (t_uart *uart) +{ + int detection_result; + SYS_UWORD8 *rx_fifo_byte; + SYS_UWORD16 bytes_in_rx_buffer; + UNSIGNED elapsed_time; + + detection_result = 0; + + rx_fifo_byte = uart->rx_buffer_used_by_rx_hisr; + if (rx_fifo_byte == &(uart->rx_fifo_byte_1[0])) + bytes_in_rx_buffer = uart->bytes_in_rx_buffer_1; + else + bytes_in_rx_buffer = uart->bytes_in_rx_buffer_2; + + if (uart->current_time > uart->previous_time) + elapsed_time = uart->current_time - uart->previous_time; + else + elapsed_time = + MAX_UNSIGNED_32 - uart->previous_time + uart->current_time; + + switch (uart->esc_seq_detection_state) { + + case INITIALIZATION: + + /* + * It is the first character received. It may be the first character + * of an escape sequence. The elapsed_time variable is set to the + * guard period value to consider this character as the first character + * of an escape sequence. + */ + + if (!uart->esc_seq_modified) { + + elapsed_time = uart->guard_period; + uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE; + } + + /* No break! */ + + case NO_ESCAPE_SEQUENCE: + + /* + * To go to the next state (one, two or three characters detected): + * - a guard period must have elapsed since the last receipt, + * - the characters must belong to the escape sequence. + */ + + if ((elapsed_time >= uart->guard_period) && + (!uart->esc_seq_modified)) { + + switch (bytes_in_rx_buffer) { + + case 1: + + if (*rx_fifo_byte++ == uart->esc_seq_character) { + + uart->esc_seq_detection_state = ONE_CHAR_DETECTED; + start_guard_period_timer (uart); + detection_result = 1; + } + + break; + + case 2: + + if ((*rx_fifo_byte++ == uart->esc_seq_character) && + (*rx_fifo_byte++ == uart->esc_seq_character)) { + + uart->esc_seq_detection_state = TWO_CHARS_DETECTED; + start_guard_period_timer (uart); + detection_result = 1; + } + + break; + + case 3: + + if ((*rx_fifo_byte++ == uart->esc_seq_character) && + (*rx_fifo_byte++ == uart->esc_seq_character) && + (*rx_fifo_byte++ == uart->esc_seq_character)) { + + uart->esc_seq_detection_state = THREE_CHARS_DETECTED; + start_guard_period_timer (uart); + detection_result = 1; + } + + break; + + default: + + /* + * No action. + */ + + break; + } + } + + uart->previous_time = uart->current_time; + + break; + + case ONE_CHAR_DETECTED: + + /* + * To go to the next state (two or three characters detected): + * - the difference between the current time and the previous time + * must be less than the guard period, + * - the characters must belong to the escape sequence. + * Otherwise, an escape sequence character is written in the RX buffer. + */ + + if (!uart->esc_seq_modified) { + + switch (bytes_in_rx_buffer) { + + case 1: + + if (*rx_fifo_byte++ == uart->esc_seq_character) { + + uart->esc_seq_detection_state = TWO_CHARS_DETECTED; + detection_result = 1; + } + + break; + + case 2: + + if ((*rx_fifo_byte++ == uart->esc_seq_character) && + (*rx_fifo_byte++ == uart->esc_seq_character)) { + + start_guard_period_timer (uart); /* Reset the timer. */ + + uart->esc_seq_detection_state = THREE_CHARS_DETECTED; + detection_result = 1; + } + + break; + + default: + + /* + * No action. + */ + + break; + } + } + + if (!detection_result) { + + add_esc_seq_char_in_rx_buffer (uart); + + uart->previous_time = uart->current_time; + uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE; + } + + break; + + case TWO_CHARS_DETECTED: + + /* + * To go to the next state (three chars detected): + * - the difference between the current time and the previous time + * must be less than the guard period, + * - the character must belong to the escape sequence. + * Otherwise, 2 escape sequence characters are written in the RX buffer. + */ + + if (!uart->esc_seq_modified) { + + switch (bytes_in_rx_buffer) { + + case 1: + + if (*rx_fifo_byte++ == uart->esc_seq_character) { + + start_guard_period_timer (uart); /* Reset the timer. */ + + uart->esc_seq_detection_state = THREE_CHARS_DETECTED; + detection_result = 1; + } + + break; + + default: + + /* + * No action. + */ + + break; + } + } + + if (!detection_result) { + + add_esc_seq_char_in_rx_buffer (uart); + add_esc_seq_char_in_rx_buffer (uart); + + uart->previous_time = uart->current_time; + uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE; + } + + break; + + case THREE_CHARS_DETECTED: + + /* + * An escape sequence is detected if a guard period has elapsed since + * the last receipt. Otherwise, 3 escape sequence characters are + * written in the RX buffer. + */ + + stop_guard_period_timer (uart); + + add_esc_seq_char_in_rx_buffer (uart); + add_esc_seq_char_in_rx_buffer (uart); + add_esc_seq_char_in_rx_buffer (uart); + + uart->previous_time = uart->current_time; + uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE; + + break; + } + + return (detection_result); +} + +/******************************************************************************* + * + * send_break + * + * Purpose : This function may only called if the TX FIFO is empty. + * Null characters are written in the TX FIFO. The number of bytes to + * write has been defined with UAF_SetLineState. Enables the break + * condition. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : Number of bytes sent. + * + ******************************************************************************/ + +static SYS_UWORD16 +send_break (t_uart *uart) +{ + SYS_UWORD16 bytes_in_tx_fifo; + + bytes_in_tx_fifo = 0; + uart->break_in_progress = 1; + +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Disable sleep mode. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); +#endif + + WRITE_UART_REGISTER ( + uart, LCR, READ_UART_REGISTER (uart, LCR) | BREAK_CONTROL); + +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Re-enable sleep mode. + */ + +/* BELOW LINES WERE COMMENTED TO DISABLE SLEEP MODE IN DRIVER */ +/* + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP); + + */ +#endif + + while (uart->break_length) { + + WRITE_UART_REGISTER (uart, THR, 0x00); + uart->break_length--; + bytes_in_tx_fifo++; + } + + return (bytes_in_tx_fifo); +} + +/******************************************************************************* + * + * build_rx_fifo_array + * + * Purpose : Reads the RX FIFO to build an array with bytes read. + * A byte is written in this array if no error is detected. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : The number of bytes in RX FIFO. + * + ******************************************************************************/ + +static SYS_UWORD16 +build_rx_fifo_array (t_uart *uart) +{ + SYS_UWORD8 status; + SYS_UWORD8 *first_byte; + SYS_UWORD8 *current_byte; + SYS_UWORD16 *bytes_in_rx_buffer; + SYS_UWORD16 bytes_received; + SYS_UWORD8 cbyte; + + volatile int x; + + x = 1; + + bytes_received = 0; + + + /* + * Switch to the other buffer. + */ + + first_byte = uart->rx_buffer_used_by_rx_lisr; + if (first_byte == &(uart->rx_fifo_byte_1[0])) { + + first_byte = &(uart->rx_fifo_byte_2[0]); + bytes_in_rx_buffer = &(uart->bytes_in_rx_buffer_2); + + } else { + + first_byte = &(uart->rx_fifo_byte_1[0]); + bytes_in_rx_buffer = &(uart->bytes_in_rx_buffer_1); + } + + current_byte = first_byte; + + if (*bytes_in_rx_buffer) { + + + /* The Rx buffer is not empty and is being used by HISR ! */ + /* Hence stop the flow control */ + stop_receiver (uart); + + /* + * Reset LCR[7] (DLAB) to have access to the RBR, THR and IER registers. + */ + WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB); + + /* Mask The Rx and interrupt */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & + ~(ERBI | EDSSI)); + + uart->rx_stopped_by_lisr = 1; + return (bytes_received); + + } + + uart->rx_buffer_used_by_rx_lisr = first_byte; + + status = READ_UART_REGISTER (uart, LSR); + + /* + * Build an array with the bytes contained in the RX FIFO. + */ + + while (status & DR) { /* While RX FIFO is not empty... */ + + *current_byte = READ_UART_REGISTER (uart, RHR); + + /* + * Check if a parity error or a framing error is associated with the + * received data. If there is an error the byte is not copied into the + * bytes array. + */ + + if (status & BYTE_ERROR) { + + if (status & OE) + uart->overrun_error++; + + if (status & PE) + uart->parity_error++; + + if (status & FE) + uart->framing_error++; + + /* + * Check break detection. + */ + + if (status & BI) { + + uart->break_received = 1; + *(uart->state) |= + ((1 << BRK) | (MINIMAL_BREAK_LENGTH << BRKLEN)); + } + + } else /* No error */ + current_byte++; + + status = READ_UART_REGISTER (uart, LSR); + } + + bytes_received = (SYS_UWORD16) (current_byte - first_byte); + *bytes_in_rx_buffer = bytes_received; + + /* + * Re-switch to the other buffer if no valid character has been received. + */ + + if (!bytes_received) { + + if (uart->rx_buffer_used_by_rx_lisr == &(uart->rx_fifo_byte_1[0])) + uart->rx_buffer_used_by_rx_lisr = &(uart->rx_fifo_byte_2[0]); + + else + uart->rx_buffer_used_by_rx_lisr = &(uart->rx_fifo_byte_1[0]); + } + + if (bytes_received > uart->max_rx_fifo_level) + uart->max_rx_fifo_level = bytes_received; + + return (bytes_received); +} + +/******************************************************************************* + * + * empty_rx_fifo + * + * Purpose : Read the RX FIFO. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static void +empty_rx_fifo (t_uart *uart) +{ + SYS_UWORD16 bytes_in_rx_fifo; + volatile SYS_UWORD8 dummy_byte; + + bytes_in_rx_fifo = 0; + + while (READ_UART_REGISTER (uart, LSR) & DR) { + + dummy_byte = READ_UART_REGISTER (uart, RHR); + bytes_in_rx_fifo++; + } + + if (bytes_in_rx_fifo > uart->max_rx_fifo_level) + uart->max_rx_fifo_level = bytes_in_rx_fifo; +} + +/******************************************************************************* + * + * hisr_execute_rx_operations + * + * Purpose : If an escape sequence is detected or if a break in the detection + * has occured RX FIFO bytes are written in the RX buffer. + * If the software flow control is used bytes are analyzed to know + * if a XON or a XOFF character is received to stop or start the + * transmitter. + * If a flow control is used and if the high watermark of the RX + * buffer is reached the receiver is stopped. + * If the RX threshold level is reached the callback mechanism is + * activated. + * + * Arguments: In : none + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static VOID +hisr_execute_rx_operations (VOID) +{ + SYS_UWORD16 bytes_free_in_rx_buffer; + SYS_UWORD16 wrap_around_counter; + SYS_UWORD16 bytes_in_rx_buffer; + SYS_UWORD16 bytes_read; + SYS_UWORD16 bytes_to_copy; + SYS_UWORD8 *current_byte; + SYS_UWORD8 xon_xoff_detected; + t_uart *uart; + + uart = &uart_parameters; + + /* + * Since new characters have been received, the sleep timer is reset then + * restarted preventing the system to enter deep-sleep for a new period of + * time. + */ + + SER_restart_uart_sleep_timer (); + uart_sleep_timer_enabled = 1; + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + uart->index_hisr = (uart->index_hisr + 1) & 0x01; /* 0 or 1 */ +#endif + + xon_xoff_detected = 0; + + /* + * Switch to the other buffer. + */ + + current_byte = uart->rx_buffer_used_by_rx_hisr; + if (current_byte == &(uart->rx_fifo_byte_1[0])) { + + current_byte = &(uart->rx_fifo_byte_2[0]); + bytes_read = uart->bytes_in_rx_buffer_2; + + } else { + + current_byte = &(uart->rx_fifo_byte_1[0]); + bytes_read = uart->bytes_in_rx_buffer_1; + } + + uart->rx_buffer_used_by_rx_hisr = current_byte; + + /* + * All bytes are copied into the RX buffer only if an escape sequence has + * been detected or a break in the detection has occured. + */ + + if (!detect_escape_sequence (uart)) { + + if (uart->rx_out > uart->rx_in) + bytes_free_in_rx_buffer = (SYS_UWORD16) (uart->rx_out - uart->rx_in - 1); + else + bytes_free_in_rx_buffer = + (SYS_UWORD16) (uart->buffer_size + uart->rx_out - uart->rx_in); + + wrap_around_counter = uart->buffer_size + 1 - + (SYS_UWORD16) (uart->rx_in - &(uart->rx_buffer[0])); + + if (uart->flow_control_mode == fc_xoff) { + + /* + * For SW Flow Control, need to further investigate the processing + * in order to improve the performance of the driver, and in order + * to avoid managing the wrap around of the circular buffer each + * time a character is copied. + */ + + while (bytes_read && bytes_free_in_rx_buffer) { + + /* + * If the data received is XON or XOFF, the transmitter is + * enabled (XON) or disabled (XOFF). + */ + + if (*current_byte == uart->xoff_character) { + + uart->tx_stopped_by_driver = 1; + xon_xoff_detected = 1; + + } else if (*current_byte == uart->xon_character) { + + uart->tx_stopped_by_driver = 0; + xon_xoff_detected = 1; + +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Disable sleep mode. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); +#endif + + /* + * Unmask Tx interrupt. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI); + + } else { + + *(uart->rx_in++) = *current_byte; + + wrap_around_counter--; + if (!wrap_around_counter) { + + uart->rx_in = &(uart->rx_buffer[0]); + wrap_around_counter = uart->buffer_size + 1; + } + + bytes_free_in_rx_buffer--; + } + + current_byte++; + bytes_read--; + } + } else { /* No Flow Control or HW Flow Control */ + + /* + * Figure out the most restricting condition. + */ + + bytes_to_copy = + Min3 (bytes_free_in_rx_buffer, wrap_around_counter, bytes_read); + + /* + * Copy characters into the circular Rx buffer. + */ + + memcpy (uart->rx_in, current_byte, bytes_to_copy); + + /* + * Update first the variables associated to blocking conditions: + * if (bytes_read = 0) OR + * (bytes_free_in_rx_buffer = 0) => No more characters to copy. + */ + + bytes_free_in_rx_buffer -= bytes_to_copy; + bytes_read -= bytes_to_copy; + + wrap_around_counter -= bytes_to_copy; + if (!wrap_around_counter) + uart->rx_in = &(uart->rx_buffer[0]); + else + uart->rx_in += bytes_to_copy; + + /* + * Check if there are still some characters to copy. + */ + + if (bytes_read && bytes_free_in_rx_buffer) { + + /* + * Update the remaining variables and figure out again the + * most restricting condition. Since (bytes_read = 0) and + * (bytes_free_in_rx_buffer = 0) are blocking conditions, if + * we reach that point it means that the wrap around condition + * has just occurred and it is not needed to manage it again. + */ + + current_byte += bytes_to_copy; + bytes_to_copy = Min (bytes_read, bytes_free_in_rx_buffer); + + /* + * Copy characters into the circular Rx buffer and update + * current pointer. + */ + + memcpy (uart->rx_in, current_byte, bytes_to_copy); + + uart->rx_in += bytes_to_copy; + + /* + * bytes_free_in_rx_buffer not updated since not used anymore. + */ + bytes_read -= bytes_to_copy; + + } + else { + bytes_read = 0; + } + } /* end if (uart->flow_control_mode == fc_xoff) */ + + + /* + * If the high watermark is reached, RTS is activated or XOFF is + * sent according to the flow control mode. + */ + + bytes_in_rx_buffer = get_bytes_in_rx_buffer (uart); + + if ((uart->flow_control_mode != fc_none) && + (bytes_in_rx_buffer >= RX_HIGH_WATERMARK (uart->buffer_size))) { + + /* + * Check if receipt must be stopped. + */ + + if (!uart->rx_stopped_by_driver) { + + uart->rx_stopped_by_driver = 1; + if (!uart->rx_stopped_by_application) + stop_receiver (uart); + } + } + + /* + * If a reading was suspended or if the callback function is installed, + * it is called if one of these conditions is fulfiled: + * - the RX threshold level is reached, + * - a break has been detected, + */ + + if ((!uart->rd_call_from_hisr_in_progress) && + (uart->reading_suspended || + (uart->rd_call_setup == rm_reInstall))) { + + if ((bytes_in_rx_buffer >= uart->rx_threshold_level) || +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + uart->dtr_change_detected[uart->index_hisr] || +#endif + uart->break_received || + xon_xoff_detected) { + + + uart->rd_call_from_hisr_in_progress = 1; + update_reading_callback (uart, 3); /* 3: call from Rx HISR. */ + + uart->reading_suspended = 0; + uart->break_received = 0; + uart->esc_seq_received = 0; +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + uart->dtr_change_detected[uart->index_hisr] = 0; +#endif + } + } + + } + + + + WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB); + + /* Mask The Rx and Modem status interrupt */ + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & + ~(ERBI | EDSSI)); + + if ((uart->rx_buffer_used_by_rx_hisr) == &(uart->rx_fifo_byte_1[0])) { + + uart->bytes_in_rx_buffer_1 = 0; + + } else { + + uart->bytes_in_rx_buffer_2 = 0; + } + + + WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB); + + /* Unmask The Rx and Modem status interrupt*/ + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | + (ERBI | EDSSI)); + + if(uart->rx_stopped_by_lisr ) { + if (!uart->rx_stopped_by_driver) { + + + uart->rx_stopped_by_lisr = 0; + + /* + * Reset LCR[7] (DLAB) to have access to the RBR, THR and IER registers. + */ + WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB); + + + /* UnMask The Rx interrupt */ + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | + (ERBI | EDSSI)); + + start_receiver (uart); + + } + } + +} + +/******************************************************************************* + * + * hisr_execute_v24_operations + * + * Purpose : The user's function is called if all conditions to call it are + * fulfiled. + * + * Arguments: In : none + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static VOID +hisr_execute_v24_operations (VOID) +{ + t_uart *uart; + + uart = &uart_parameters; + + /* + * If a reading was suspended or if the callback function is installed, + * it is called. + */ + + if ((!DRIVER_DISABLED (uart)) && + (!uart->rd_call_from_hisr_in_progress) && + (uart->reading_suspended || (uart->rd_call_setup == rm_reInstall))) { + + uart->rd_call_from_hisr_in_progress = 1; + update_reading_callback (uart, 1); /* 1: call from HISR. */ + uart->reading_suspended = 0; + uart->break_received = 0; + uart->esc_seq_received = 0; + } + +} + +/******************************************************************************* + * + * hisr_execute_tx_operations + * + * Purpose : Writes bytes from the TX buffer to the TX FIFO. + * The user's function is called if all conditions to call it are + * fulfiled. + * + * Arguments: In : none + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static VOID +hisr_execute_tx_operations (VOID) +{ + SYS_UWORD16 bytes_in_tx_buffer; + SYS_UWORD16 bytes_in_tx_fifo; + SYS_UWORD16 wrap_around_counter; + SYS_UWORD16 bytes_to_write; + t_uart *uart; + int counter; + + + uart = &uart_parameters; + + /* + * A TX interrupt may have occured during the previous TX HISR. This case + * may appear when a HISR having a higher priority has been activated when + * the TX HISR was activated. When the next TX HISR is activated, the TX + * FIFO may not be empty. Nothing is done until a TX interrupt will occur. + * The RX HISR will be activated again and the TX FIFO will be empty. + */ + + if (READ_UART_REGISTER (uart, LSR) & THRE) { + + bytes_in_tx_fifo = 0; + + /* + * A request to send a XON/XOFF character may have been done by the + * RX interrupt handler. The byte can be written because we are sure + * that the TX FIFO is not full. + */ + + if (uart->send_xon_xoff) { + + WRITE_UART_REGISTER (uart, THR, uart->xon_xoff_to_send); + uart->send_xon_xoff = 0; + bytes_in_tx_fifo++; + } + + if ((!uart->tx_stopped_by_application) && + (!uart->tx_stopped_by_driver)) { + + bytes_in_tx_buffer = get_bytes_in_tx_buffer (uart); + wrap_around_counter = + uart->buffer_size + 1 - (SYS_UWORD16) (uart->tx_out - + &(uart->tx_buffer[0])); + + /* + * Figure out the most restricting condition. + */ + +#if ((CHIPSET == 3) || (CHIPSET == 4) || (CHIPSET == 5) || (CHIPSET == 6)) + /* + * Loading of only (FIFO_SIZE - 1) characters in the Tx FIFO to + * avoid the generation of a spurious Tx FIFO almost empty + * interrupt (Ulysse bug report #35). + */ + + bytes_to_write = + Min3 (bytes_in_tx_buffer, wrap_around_counter, + (FIFO_SIZE - 1 - bytes_in_tx_fifo)); +#elif ((CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12)) + /* + * Bug corrected on Calypso rev. A, rev. B, C035, Ulysse C035, + * Calypso Lite & Calypso+. + */ + + bytes_to_write = + Min3 (bytes_in_tx_buffer, wrap_around_counter, + (FIFO_SIZE - bytes_in_tx_fifo)); +#endif + + /* + * Write characters into the Tx FIFO. + */ + + for (counter = 0; counter < bytes_to_write; counter++) + WRITE_UART_REGISTER (uart, THR, *(uart->tx_out++)); + + /* + * Update the variables associated to blocking conditions: + * if (bytes_in_tx_buffer = 0) OR + * (bytes_in_tx_fifo = FIFO_SIZE) => No more characters to copy. + */ + + bytes_in_tx_buffer -= bytes_to_write; + bytes_in_tx_fifo += bytes_to_write; + + wrap_around_counter -= bytes_to_write; + if (!wrap_around_counter) + uart->tx_out = &(uart->tx_buffer[0]); + + /* + * Check if there are still some characters to write. + */ + + if (bytes_in_tx_buffer && +#if ((CHIPSET == 3) || (CHIPSET == 4) || (CHIPSET == 5) || (CHIPSET == 6)) + (bytes_in_tx_fifo < (FIFO_SIZE - 1))) { +#elif ((CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12)) + (bytes_in_tx_fifo < FIFO_SIZE)) { +#endif + + /* + * Figure out again the most restricting condition. Since + * (bytes_in_tx_buffer = 0) and (bytes_in_tx_fifo = FIFO_SIZE) + * are blocking conditions, if we reach that point it means + * that the wrap around condition has just occurred and it is + * not needed to manage it again. + */ + +#if ((CHIPSET == 3) || (CHIPSET == 4) || (CHIPSET == 5) || (CHIPSET == 6)) + bytes_to_write = + Min (bytes_in_tx_buffer, + (FIFO_SIZE - 1 - bytes_in_tx_fifo)); +#elif ((CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12)) + bytes_to_write = + Min (bytes_in_tx_buffer, + (FIFO_SIZE - bytes_in_tx_fifo)); +#endif + + /* + * Write characters into the Tx FIFO and update associated + * variables. + */ + + for (counter = 0; counter < bytes_to_write; counter++) + WRITE_UART_REGISTER (uart, THR, *(uart->tx_out++)); + + bytes_in_tx_buffer += bytes_to_write; + bytes_in_tx_fifo += bytes_to_write; + } + + /* + * If a writing was suspended or if the callback function is + * installed, it is called if the TX threshold level is reached. + */ + + if ((!DRIVER_DISABLED (uart)) && + (!uart->wr_call_from_hisr_in_progress) && + (bytes_in_tx_buffer <= uart->tx_threshold_level) && + ((uart->wr_call_setup == rm_reInstall) || + uart->writing_suspended)) { + + uart->writing_suspended = 0; + + uart->wr_call_from_hisr_in_progress = 1; + update_writing_callback (uart, 1); /* 1: call from HISR. */ + } + } /* end if ((!uart->tx_stopped_by_application) && */ + /* (!uart->tx_stopped_by_driver)) */ + + if (bytes_in_tx_fifo) + + /* + * Unmask Tx interrupt. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI); + + else { + + if ((!bytes_in_tx_fifo) && (uart->break_to_send)) + bytes_in_tx_fifo = send_break (uart); + } + +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Re-enable the sleep mode. + */ + +/* BELOW LINES WERE COMMENTED TO DISABLE SLEEP MODE IN DRIVER */ +/* + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP); + + */ +#endif + } +} + +/******************************************************************************* + * + * read_rx_fifo + * + * Purpose : Reads the RX FIFO. If the driver is enabled bytes are written in + * an array to be analyzed by the RX HISR. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static void +read_rx_fifo (t_uart *uart) +{ + + /* + * If the driver is disabled the RX FIFO is read to acknoledge the + * interrupt else bytes received are written into an array which will be + * analyzed from the RX HISR. + */ + + if (DRIVER_DISABLED (uart)) + empty_rx_fifo (uart); + + else if (build_rx_fifo_array (uart)){ + (void) NU_Activate_HISR (&(uart->rx_hisr_ctrl_block)); + + } + + +} + +/******************************************************************************* + * + * check_v24_input_lines + * + * Purpose : Check the V.24 input lines. According to the states of the input + * lines and to the flow control mode selected, the transmitter is + * enabled or disabled. The reading callback function is called if + * it is installed and if all conditions are fulfiled. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static void +check_v24_input_lines (t_uart *uart) +{ + SYS_BOOL v24_input_line_changed; + volatile SYS_UWORD8 modem_status; + + modem_status = READ_UART_REGISTER (uart, MSR); + v24_input_line_changed = 0; + + if (modem_status & DELTA_CTS) { + + v24_input_line_changed = 1; + + if (modem_status & MCTS) + uart->rts_level = 0; + else + uart->rts_level = 1; + } + +#if (CHIPSET == 12) + else if (modem_status & DELTA_DSR) { + v24_input_line_changed = 1; + + if (modem_status & MDSR) + { + uart->dtr_level = 0; + if (uart->flow_control_mode != fc_dtr && uart->baudrate == baudrate_value[FD_BAUD_AUTO]) + UAF_SetComPar (UAF_UART_1, FD_BAUD_AUTO, bpc_8, sb_1, pa_none); /* switch back to autobaud */ + } + else + uart->dtr_level = 1; + + /* + * The reading callback function has to be called. But bytes received before + * the change of state of DTR must be copied into the RX buffer before to + * call it. + */ + + if (READ_UART_REGISTER (uart, LSR) & DR) { /* If Rx FIFO is not empty */ + + /* + * The Rx FIFO will be read to fill one of the two buffers and the Rx + * HISR will be activated. + */ + + uart->index_it = (uart->index_it + 1) & 0x01; /* 0 or 1 */ + uart->dtr_change_detected[uart->index_it] = 1; + uart->dtr_level_saved[uart->index_it] = uart->dtr_level; + read_rx_fifo (uart); + + } else + v24_input_line_changed = 1; + } +#endif + + /* + * When the hardware flow control is selected, if the RS 232 input signal is + * deactivated (low), the transmitter is stopped. + */ + + if (uart->flow_control_mode == fc_rts) { + + if (uart->rts_level) { + uart->tx_stopped_by_driver = 1; + } + + else { + + uart->tx_stopped_by_driver = 0; + LowGPIO(1); + +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Disable sleep mode. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); +#endif + + /* + * Unmask Tx interrupt. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI); + + } + } + + if (v24_input_line_changed) + (void) NU_Activate_HISR (&(uart->v24_hisr_ctrl_block)); +} + +/******************************************************************************* + * + * fill_tx_fifo + * + * Purpose : If the TX buffer is not empty, and if there is no break in + * progress, bytes are written into the TX FIFO until the TX FIFO is + * full or the TX buffer is empty. Else, if there is a break to send + * an all 0s character is written into the TX FIFO and a break is + * declared in progress to avoid to fill the TX FIFO on the next + * interrupt. + * When the TX FIFO is empty and if a break is in progress, the break + * length is programmed: all 0s characters are written into the TX + * FIFO. The number of bytes has been defined previously with the + * UAF_SetLineState function. The break condition is enabled. + * When the TX FIFO and the transmitter shift register (TSR) are both + * empty and if a break is in progress, the break condition is + * disabled. + * When bytes are written from the TX buffer to the TX FIFO, the + * writing callback function is called if it is installed and if all + * conditions are fulfiled. + * + * Arguments: In : uart: Pointer on the UART structure. + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +static void +fill_tx_fifo (t_uart *uart) +{ +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Disable sleep mode. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); +#endif + + /* + * Mask Tx interrupt. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~ETBEI); + + /* + * If a break is in progress, bytes of the TX buffer are not written into + * the TX FIFO. + */ + + if (!uart->break_in_progress) + (void) NU_Activate_HISR (&(uart->tx_hisr_ctrl_block)); + + else { + + /* + * The break HISR is activated and the break condition is cleared. + */ + + WRITE_UART_REGISTER ( + uart, LCR, READ_UART_REGISTER (uart, LCR) & ~BREAK_CONTROL); + + (void) NU_Activate_HISR (&(uart->break_hisr_ctrl_block)); + } +} + +/******************************************************************************* + * + * UAF_Init + * + * Purpose : Initializes the UART hardware and installs interrupt handlers. + * The parameters are set to the default values: + * - 19200 baud, + * - 8 bits / character, + * - no parity, + * - 1 stop bit, + * - no flow control. + * All functionalities of the UART driver are disabled. + * + * Arguments: In : uartNo: Used UART. + * Out: none + * + * Returns : FD_OK : Successful operation. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_INTERNAL_ERR : Internal problem. + * + ******************************************************************************/ + +T_FDRET +UAF_Init (T_fd_UartId uartNo) +{ + t_uart *uart; + volatile SYS_UWORD8 status; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + uart = &uart_parameters; + + /* + * Create the 3 HISR actived in the RX/TX and V24 interrupt handlers. + * A return is used to simplify the code if an error occurs. + * All stacks are entirely filled with the pattern 0xFE. + */ + + memset (&(uart->rx_hisr_stack[0]), 0xFE, RX_HISR_STACK_SIZE); + + if (NU_Create_HISR (&(uart->rx_hisr_ctrl_block), + "UAF_Rx", + hisr_execute_rx_operations, + RX_HISR_PRIORITY, + &(uart->rx_hisr_stack[0]), + RX_HISR_STACK_SIZE) != NU_SUCCESS) + + return (FD_INTERNAL_ERR); + + memset (&(uart->tx_hisr_stack[0]), 0xFE, TX_HISR_STACK_SIZE); + + if (NU_Create_HISR (&(uart->tx_hisr_ctrl_block), + "UAF_Tx", + hisr_execute_tx_operations, + TX_HISR_PRIORITY, + &(uart->tx_hisr_stack[0]), + TX_HISR_STACK_SIZE) != NU_SUCCESS) + + return (FD_INTERNAL_ERR); + + memset (&(uart->v24_hisr_stack[0]), 0xFE, V24_HISR_STACK_SIZE); + + if (NU_Create_HISR (&(uart->v24_hisr_ctrl_block), + "UAF_V24", + hisr_execute_v24_operations, + V24_HISR_PRIORITY, + &(uart->v24_hisr_stack[0]), + V24_HISR_STACK_SIZE) != NU_SUCCESS) + + return (FD_INTERNAL_ERR); + + /* + * Create the HISR used to send a break. + * A return is used to simplify the code if an error occurs. + * The stack is entirely filled with the pattern 0xFE. + */ + + memset (&(uart->break_hisr_stack[0]), 0xFE, BREAK_HISR_STACK_SIZE); + + if (NU_Create_HISR (&(uart->break_hisr_ctrl_block), + "UAF_Brk", + hisr_start_break, + BREAK_HISR_PRIORITY, + &(uart->break_hisr_stack[0]), + BREAK_HISR_STACK_SIZE) != NU_SUCCESS) + + return (FD_INTERNAL_ERR); + + /* + * Create a timer used in the break HISR. + * A return is used to simplify the code if an error occurs. + */ + + if (NU_Create_Timer (&(uart->break_timer_ctrl_block), + "Break", + stop_break, + 0, /* Parameter supplied to the routine: not used. */ + 0, /* This parameter is set when the timer is reset. */ + 0, /* The timer expires once. */ + NU_DISABLE_TIMER) != NU_SUCCESS) + + return (FD_INTERNAL_ERR); + + /* + * Create a timer used in the detection of the escape sequence. + * A return is used to simplify the code if an error occurs. + */ + + if (NU_Create_Timer (&(uart->guard_period_timer_ctrl_block), + "Esc seq", + analyze_guard_period_timer_expiration, + 0, /* Parameter supplied to the routine: not used. */ + 0, /* This parameter is set when the timer is reset. */ + 0, /* The timer expires once. */ + NU_DISABLE_TIMER) != NU_SUCCESS) + + return (FD_INTERNAL_ERR); + + /* + * These data are used to send a break. + * A character has: 8 data bits + 1 start bit + 1 stop bit = 10 bits. + */ + + uart->baudrate = baudrate_value[FD_BAUD_19200]; + uart->autobauding = 0; + uart->bits_per_char = 10; + + /* + * UART base address. + */ + + uart->base_address = base_address[uartNo]; + + /* + * Select the current array used to store received bytes. + */ + + uart->rx_buffer_used_by_rx_lisr = &(uart->rx_fifo_byte_2[0]); + uart->rx_buffer_used_by_rx_hisr = &(uart->rx_fifo_byte_2[0]); + + /* + * RX and TX buffers. + */ + + uart->buffer_size = FD_MAX_BUFFER_SIZE; + uart->rx_threshold_level = 1; + uart->tx_threshold_level = 0; + uart->rx_in = &(uart->rx_buffer[0]); + uart->rx_out = &(uart->rx_buffer[0]); + uart->tx_in = &(uart->tx_buffer[0]); + uart->tx_out = &(uart->tx_buffer[0]); + + /* + * Escape sequence. + */ + + uart->esc_seq_modified = 0; + uart->esc_seq_detection_state = INITIALIZATION; + uart->esc_seq_character = DEFAULT_ESC_SEQ_CHARACTER; + uart->guard_period = CONVERT_TIME_IN_TDMA ( + DEFAULT_GUARD_PERIOD); + + /* + * Flow control. + */ + + uart->flow_control_mode = fc_none; + uart->send_xon_xoff = 0; + uart->rx_stopped_by_application = 1; + uart->rx_stopped_by_driver = 0; + uart->rx_stopped_by_lisr = 0; + uart->tx_stopped_by_application = 1; + uart->tx_stopped_by_driver = 0; + + /* + * Break. + */ + + uart->break_received = 0; + uart->break_to_send = 0; + uart->break_in_progress = 0; + + /* + * Callback (UAF_ReadData and UAF_WriteData). + */ + + uart->esc_seq_received = 0; + + uart->reading_suspended = 0; + uart->writing_suspended = 0; + uart->rd_call_from_hisr_in_progress = 0; + uart->wr_call_from_hisr_in_progress = 0; + uart->rd_call_setup = rm_noInstall; + uart->wr_call_setup = rm_noInstall; + + /* + * State defined in UAF_GetLineState. + */ + + uart->state_1 = 0; + uart->state_2 = 0; + uart->state = &(uart->state_1); + + /* + * Errors counters. + */ + + uart->framing_error = 0; + uart->parity_error = 0; + uart->overrun_error = 0; + uart->spurious_interrupts = 0; + + uart->max_rx_fifo_level = 0; + + /* + * Mask all interrupts causes and disable sleep mode and low power mode. + */ + + WRITE_UART_REGISTER (uart, IER, 0x00); + + /* + * Reset UART mode configuration. + */ + + WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE | + IR_SLEEP_DISABLED | + SIR_TX_WITHOUT_ACREG2 | + FRAME_LENGTH_METHOD); + + /* + * FIFO configuration. + * EFR[4] = 1 to allow to program FCR[5:4] and MCR[7:5]. + */ + + WRITE_UART_REGISTER (uart, LCR, 0xBF); + SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT); + + /* + * Select the word length, the number of stop bits , the parity and set + * LCR[7] (DLAB) to allow to program FCR, DLL and DLM. + */ + + WRITE_UART_REGISTER (uart, LCR, WLS_8 | DLAB); + + /* + * Program the trigger levels. + * MCR[6] must be set to 1. + */ + + SET_BIT (uart, MCR, TCR_TLR_BIT); + WRITE_UART_REGISTER (uart, TCR, 0x0F); + WRITE_UART_REGISTER (uart, TLR, RX_FIFO_TRIGGER_LEVEL); + RESET_BIT (uart, MCR, TCR_TLR_BIT); + + /* + * Force the generation of THR_IT on TX FIFO empty: SCR[3] = 1. + */ + + WRITE_UART_REGISTER ( + uart, SCR, READ_UART_REGISTER (uart, SCR) | TX_EMPTY_CTL_IT); + + /* + * Program the FIFO control register. Bit 0 must be set when other FCR bits + * are written to or they are not programmed. + * FCR is a write-only register. It will not be modified. + */ + + WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE | + RX_FIFO_RESET | /* self cleared */ + TX_FIFO_RESET); /* self cleared */ + + /* + * Program the baud generator. + */ + + WRITE_UART_REGISTER (uart, DLL, dll[FD_BAUD_19200]); + WRITE_UART_REGISTER (uart, DLM, dlh[FD_BAUD_19200]); + + /* + * Reset LCR[7] (DLAB) to have access to the RBR, THR and IER registers. + */ + + WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB); + + /* + * Select UART mode. + */ + + WRITE_UART_REGISTER (uart, MDR1, UART_MODE | + IR_SLEEP_DISABLED | + SIR_TX_WITHOUT_ACREG2 | + FRAME_LENGTH_METHOD); + + /* + * Read the state of RTS (RTS on RS232, CTS on chipset). + */ + + status = READ_UART_REGISTER (uart, MSR); + + if (status & MCTS) + uart->rts_level = 0; + else + uart->rts_level = 1; + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41)) + /* + * On C & D-Sample, 2 I/O are used to control DCD and DTR on UART Modem. + * DCD: I/O 2 (output) + * DTR: I/O 3 (input) + */ + + #define EXTENDED_MCU_REG (0xFFFEF006) /* Extended MCU register */ + #define ASIC_CONFIG_REG (0xFFFEF008) /* Asic Configuration register */ + + #define IO_DTR (10) /* I/O 3; bit 10 of Asic Configuration register */ + #define IO_DCD ( 6) /* I/O 2; bit 6 of Extended MCU register */ + + /* + * Select I/O for DCD and configure it as output. + * DCD should start HIGH (not asserted). + */ + + *((volatile SYS_UWORD16 *) EXTENDED_MCU_REG) &= ~(1 << IO_DCD); + AI_ConfigBitAsOutput (ARMIO_DCD); + AI_SetBit (ARMIO_DCD); + + /* + * Select I/O for DTR and configure it as input. + * An interrupt is used to detect a change of state of DTR. Falling edge + * or rising edge is selected according to the state of DTR. + */ + + *((volatile SYS_UWORD16 *) ASIC_CONFIG_REG) &= ~(1 << IO_DTR); + AI_ConfigBitAsInput (ARMIO_DTR); + uart->dtr_level = AI_ReadBit (ARMIO_DTR); + + if (uart->dtr_level) + AI_SelectIOForIT (ARMIO_DTR, ARMIO_FALLING_EDGE); + else + AI_SelectIOForIT (ARMIO_DTR, ARMIO_RISING_EDGE); + + AI_UnmaskIT (ARMIO_MASKIT_GPIO); + + /* + * Reset the 2 indexes of the circular buffer of 2 elements. + * The circular buffer does not need to be initialized. + */ + + uart->index_it = 0; + uart->index_hisr = 0; +#elif (CHIPSET == 12) + /* + * DCD and DTR are directly handled by Calypso+. + * Force DCD pin to HIGH + */ + + WRITE_UART_REGISTER (uart, MCR, READ_UART_REGISTER(uart, MCR) & ~MDCD); + + /* + * Read the state of DTR (DTR on RS232, DSR on chipset). + */ + + status = READ_UART_REGISTER (uart, MSR); + + if (status & MDSR) + uart->dtr_level = 0; + else + uart->dtr_level = 1; + + /* + * Reset the 2 indexes of the circular buffer of 2 elements. + * The circular buffer does not need to be initialized. + */ + + uart->index_it = 0; + uart->index_hisr = 0; +#endif /* BOARD == 8, 9, 40 or 41, CHIPSET == 12 */ + + /* + * Unmask RX interrupt and the modem status interrupt. + */ + + WRITE_UART_REGISTER (uart, IER, ERBI | EDSSI); + +#if (CHIPSET == 12) + /* + * Unmask DSR interrupt in order to detect a change of state of DTR. + */ + + ENABLE_DSR_INTERRUPT (uart); +#endif + + return (FD_OK); +} + +/******************************************************************************* + * + * UAF_Enable + * + * Purpose : The functionalities of the UART driver are disabled or enabled. + * In the deactivated state, all information about the communication + * parameters should be stored and recalled if the driver is again + * enabled. When the driver is enabled the RX and TX buffers are + * cleared. + * + * Arguments: In : uartNo: Used UART. + * : enable: 1: enable the driver + * 0: disable the driver + * Out: none + * + * Returns : FD_OK : Successful operation. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_INTERNAL_ERR : Internal problem with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_Enable (T_fd_UartId uartNo, + SYS_BOOL enable) +{ + t_uart *uart; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + */ + + uart = &uart_parameters; + + if (enable) { + + uart->rx_stopped_by_driver = 0; + + ENABLE_DRIVER (uart); + start_receiver (uart); + + } else { + + DISABLE_DRIVER (uart); + stop_receiver (uart); + + uart->tx_in = &(uart->tx_buffer[0]); + uart->rx_in = &(uart->rx_buffer[0]); + uart->tx_out = uart->tx_in; + uart->rx_out = uart->rx_in; + } + + return (FD_OK); +} + +/******************************************************************************* + * + * UAF_SetComPar + * + * Purpose : Sets up the communication parameters: baud rate, bits per + * character, number of stop bits, parity. + * + * Arguments: In : uartNo : Used UART. + * baudrate: Used baud rate. + * bpc : Used bits per character. + * sb : Used stop bits. + * parity : Used parity. + * Out: none + * + * Returns : FD_OK : Successful operation. + * FD_NOT_SUPPORTED: The specified parameters don't fit to the + * capabilities of the UART or wrong UART number. + * FD_INTERNAL_ERR : Internal problem with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_SetComPar (T_fd_UartId uartNo, + T_baudrate baudrate, + T_bitsPerCharacter bpc, + T_stopBits sb, + T_parity parity) +{ + t_uart *uart; + volatile SYS_UWORD8 mcr_value; + volatile SYS_UWORD8 status; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + * pa_space is not supported. Some baudrates are not supported too. + * A return is used to simplify the code. + */ + + if ((!baudrate_value[baudrate]) || + (parity == pa_space)) + + return (FD_NOT_SUPPORTED); + + uart = &uart_parameters; + + /* + * Mask all interrupts causes and disable sleep mode and low power mode. + */ + + WRITE_UART_REGISTER (uart, IER, 0x00); + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41)) + AI_MaskIT (ARMIO_MASKIT_GPIO); +#elif (CHIPSET == 12) + DISABLE_DSR_INTERRUPT (uart); +#endif + + /* + * Reset UART mode configuration. + */ + + WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE | + IR_SLEEP_DISABLED | + SIR_TX_WITHOUT_ACREG2 | + FRAME_LENGTH_METHOD); + + /* + * FIFO configuration. + * EFR[4] = 1 to allow to program FCR[5:4] and MCR[7:5]. + */ + + WRITE_UART_REGISTER (uart, LCR, 0xBF); + SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT); + + /* + * Select the word length, the number of stop bits , the parity and set + * LCR[7] (DLAB) to allow to program FCR, DLL and DLM. + */ + + uart->baudrate = baudrate_value[baudrate]; + uart->autobauding = (baudrate == FD_BAUD_AUTO); /* if autobauding enable trigger */ + uart->bits_per_char = 1; /* Start bit. */ + mcr_value = DLAB; + + if (bpc == bpc_7) { + + mcr_value |= WLS_7; + uart->bits_per_char += 7; + + } else { + + mcr_value |= WLS_8; + uart->bits_per_char += 8; + } + + if (sb == sb_2) { + + mcr_value |= STB; + uart->bits_per_char += 2; + + } else + uart->bits_per_char += 1; + + switch (parity) { + + case pa_even: + + mcr_value |= (PEN | EPS); + uart->bits_per_char += 1; + + break; + + case pa_odd: + + mcr_value |= PEN; + uart->bits_per_char += 1; + + break; + + default: + + /* + * There is nothing to do. + */ + + break; + } + + WRITE_UART_REGISTER (uart, LCR, mcr_value); + + /* + * Program the trigger levels. + * MCR[6] must be set to 1. + */ + + SET_BIT (uart, MCR, TCR_TLR_BIT); + WRITE_UART_REGISTER (uart, TCR, 0x0F); + WRITE_UART_REGISTER (uart, TLR, RX_FIFO_TRIGGER_LEVEL); + RESET_BIT (uart, MCR, TCR_TLR_BIT); + + /* + * Force the generation of THR_IT on TX FIFO empty: SCR[3] = 1. + */ + + WRITE_UART_REGISTER ( + uart, SCR, READ_UART_REGISTER (uart, SCR) | TX_EMPTY_CTL_IT); + + /* + * Program the FIFO control register. Bit 0 must be set when other FCR bits + * are written to or they are not programmed. + * FCR is a write-only register. It will not be modified. + */ + + WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE | + RX_FIFO_RESET | /* self cleared */ + TX_FIFO_RESET); /* self cleared */ + + /* + * Program the baud generator. + */ + + WRITE_UART_REGISTER (uart, DLL, dll[baudrate]); + WRITE_UART_REGISTER (uart, DLM, dlh[baudrate]); + + /* + * Reset LCR[7] (DLAB) to have access to the RBR, THR and IER registers. + */ + + WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB); + + /* + * Select UART mode. + */ + + WRITE_UART_REGISTER (uart, MDR1, ((baudrate==FD_BAUD_AUTO)? + UART_MODE_AUTOBAUDING: + UART_MODE) | + IR_SLEEP_DISABLED | + SIR_TX_WITHOUT_ACREG2 | + FRAME_LENGTH_METHOD); + + /* + * Read the state of RTS (RTS on RS232, CTS on chipset). + */ + + status = READ_UART_REGISTER (uart, MSR); + + if (status & MCTS) + uart->rts_level = 0; + else + uart->rts_level = 1; + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41)) + /* + * Read the state of DTR and select the edge. + */ + + uart->dtr_level = AI_ReadBit (ARMIO_DTR); + + if (uart->dtr_level) + AI_SelectIOForIT (ARMIO_DTR, ARMIO_FALLING_EDGE); + else + AI_SelectIOForIT (ARMIO_DTR, ARMIO_RISING_EDGE); + + AI_UnmaskIT (ARMIO_MASKIT_GPIO); +#elif (CHIPSET == 12) + /* + * Read the state of DTR - No need to reload MSR register since its value + * is still stored in the "status" local variable. + */ + + if (status & MDSR) + uart->dtr_level = 0; + else + uart->dtr_level = 1; +#endif + +#if ((CHIPSET == 5) || (CHIPSET == 6)) + /* + * Unmask RX and TX interrupts and the modem status interrupt. + */ + + WRITE_UART_REGISTER (uart, IER, ERBI | ETBEI | EDSSI); +#elif (CHIPSET == 12) + /* + * Unmask RX and TX interrupts and the modem status interrupt... + */ + + WRITE_UART_REGISTER (uart, IER, ERBI | ETBEI | EDSSI); + + /* + * ... Then, unmask DSR interrupt... + */ + + ENABLE_DSR_INTERRUPT (uart); + + /* + * ... And finally allow sleep mode. + */ + + /* BELOW LINES WERE COMMENTED TO DISABLE SLEEP MODE IN DRIVER */ + /* + WRITE_UART_REGISTER (uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP); + */ +#else + /* + * Unmask RX and TX interrupts and the modem status interrupt + * and allow sleep mode. + */ + /* BELOW LINES WERE COMMENTED TO DISABLE SLEEP MODE IN DRIVER */ + + /* WRITE_UART_REGISTER (uart, IER, ERBI | ETBEI | EDSSI | IER_SLEEP);*/ + + WRITE_UART_REGISTER (uart, IER, ERBI | ETBEI | EDSSI); +#endif + + + return (FD_OK); +} + +/******************************************************************************* + * + * UAF_SetBuffer + * + * Purpose : Sets up the size of the circular buffers to be used in the UART + * driver. This function may be called only if the UART is disabled + * with UAF_Enable. + * + * Arguments: In : uartNo : Used UART. + * bufSize : Specifies the size of the circular buffer. + * rxThreshold: Amount of received bytes that leads to a call + * to suspended read-out function which is passed + * to the function UAF_ReadData. + * txThreshold: Amount of bytes in the TX buffer to call the + * suspended write-in function which is passed to + * the function UAF_WriteData + * Out: none + * + * Returns : FD_OK : Successful operation. + * FD_NOT_SUPPORTED: bufSize exceeds the maximal possible + * capabilities of the driver or the threshold + * values don't correspond to the bufSize or + * wrong UART number. + * FD_INTERNAL_ERR : Internal problem with the hardware or the + * function has been called while the UART is + * enabled. + * + ******************************************************************************/ + +T_FDRET +UAF_SetBuffer (T_fd_UartId uartNo, + SYS_UWORD16 bufSize, + SYS_UWORD16 rxThreshold, + SYS_UWORD16 txThreshold) +{ + T_FDRET result; + t_uart *uart; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + if ((bufSize > FD_MAX_BUFFER_SIZE) || + (rxThreshold > FD_MAX_BUFFER_SIZE) || + (txThreshold > FD_MAX_BUFFER_SIZE)) + + result = FD_NOT_SUPPORTED; + + else { + + uart = &uart_parameters; + + if (!DRIVER_DISABLED (uart)) + result = FD_INTERNAL_ERR; + + else if (RX_HIGH_WATERMARK (bufSize) < RX_LOW_WATERMARK (bufSize)) + result = FD_NOT_SUPPORTED; + + else { + + uart->buffer_size = bufSize; + uart->rx_threshold_level = rxThreshold; + uart->tx_threshold_level = txThreshold; + + result = FD_OK; + } + } + + return (result); +} + +/******************************************************************************* + * + * UAF_SetFlowCtrl + * + * Purpose : Changes the flow control mode of the UART driver. + * If a flow control is activated, DTR is activated or XOFF is sent + * if the RX buffer is not able to store the received characters else + * DTR is deactivated or XON is sent. + * + * Arguments: In : uartNo: Used UART. + * fcMode: flow control mode (none, DTR/DSR, RTS/CTS, XON/XOFF). + * XON : ASCII code of the XON character. + * XOFF : ASCII code of the XOFF character. + * Out: none + * + * Returns : FD_OK : Successful operation. + * FD_NOT_SUPPORTED: The flow control mode is not supported or wrong + * UART number. + * FD_INTERNAL_ERR : Internal problem with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_SetFlowCtrl (T_fd_UartId uartNo, + T_flowCtrlMode fcMode, + SYS_UWORD8 XON, + SYS_UWORD8 XOFF) +{ + T_FDRET result; + t_uart *uart; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + * The DTR/DSR protocol is not supported. + */ + + if (fcMode == fc_dtr) + result = FD_NOT_SUPPORTED; + + else { + + uart = &uart_parameters; + + uart->tx_stopped_by_driver = 0; + + + uart->xon_character = XON; + uart->xoff_character = XOFF; + uart->flow_control_mode = fcMode; + +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Disable sleep mode. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); +#endif + + WRITE_UART_REGISTER ( + uart, MCR, READ_UART_REGISTER (uart, MCR) | MRTS); + +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Re-enable sleep mode. + */ + /* BELOW LINES WERE COMMENTED TO DISABLE SLEEP MODE IN DRIVER */ + /* + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP); + */ +#endif + + if (fcMode == fc_rts) { +#if 1 // Dmitriy: enable hardware assisted CTS + volatile SYS_UWORD8 oldValue; + + oldValue = READ_UART_REGISTER (uart, LCR); + + // LCR value to allow acces to EFR + + WRITE_UART_REGISTER (uart, LCR, 0xBF); + + // enable hardware assisted CTS + + SET_BIT (uart, EFR, AUTO_CTS_BIT); + + WRITE_UART_REGISTER (uart, LCR, oldValue); +#endif + if (uart->rts_level) + uart->tx_stopped_by_driver = 1; + } + + /* + * If the high watermark is reached, RTS is activated or XOFF is sent + * according to the flow control mode. Else, RTS is deactivated or XON + * is sent. + */ + + if (fcMode != fc_none) { + + if (get_bytes_in_rx_buffer (uart) >= RX_HIGH_WATERMARK ( + uart->buffer_size)) { + + uart->rx_stopped_by_driver = 1; + stop_receiver (uart); + + } else if (!DRIVER_DISABLED (uart)) { + + uart->rx_stopped_by_driver = 0; + start_receiver (uart); + } + + } else { + + uart->rx_stopped_by_driver = 0; + uart->tx_stopped_by_driver = 0; + } + + result = FD_OK; + } + + return (result); +} + +/******************************************************************************* + * + * UAF_SetEscape + * + * Purpose : To return to the command mode at the ACI while a data connection + * is established, an escape sequence has to be detected. + * To distinguish between user data and the escape sequence a + * defined guard period is necessary before and after this sequence. + * + * Arguments: In: uartNo : Used UART. + * escChar : ASCII character which could appear three times + * as an escape sequence. + * guardPeriod: Denotes the minimal duration of the rest before + * the first and after the last character of the + * escape sequence, and the maximal receiving + * duration of the whole escape string. This value + * is expressed in ms. + * Out: none + * + * Returns : FD_OK : Successful operation. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_INTERNAL_ERR : Internal problem with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_SetEscape (T_fd_UartId uartNo, + SYS_UWORD8 escChar, + SYS_UWORD16 guardPeriod) +{ + t_uart *uart; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + */ + + uart = &uart_parameters; + + uart->esc_seq_modified = 1; + uart->esc_seq_character = escChar; + uart->guard_period = CONVERT_TIME_IN_TDMA ((UNSIGNED) guardPeriod); + uart->esc_seq_modified = 0; /* Set to 0 by the RX interrupt handler. */ + + return (FD_OK); +} + +/******************************************************************************* + * + * UAF_InpAvail + * + * Purpose : Returns the number of characters available in the RX buffer of the + * driver. If the driver is disabled the function returns 0. + * + * Arguments: In : uartNo: Used UART. + * Out: none + * + * Returns : >= 0 : The returned value is the amount of data in the + * RX buffer. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_NOT_READY : The function is called while the callback of the + * readOutFunc function is activated and still not + * terminated. + * FD_INTERNAL_ERR : Internal problem with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_InpAvail (T_fd_UartId uartNo) +{ + T_FDRET result; + t_uart *uart; + SYS_UWORD16 bytes_read; + SYS_UWORD16 bytes_in_rx_buffer; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + */ + + uart = &uart_parameters; + + if (uart->rd_call_setup == rm_notDefined) + result = FD_NOT_READY; + + else if (DRIVER_DISABLED (uart)) + result = 0; + + else { + + bytes_in_rx_buffer = get_bytes_in_rx_buffer (uart); + + /* + * Update reading pointer of the RX buffer if a callback from LISR + * has been done. + */ + + if (uart->rd_call_from_hisr_in_progress) { + + bytes_read = uart->rd_size_before_call[0] - + uart->rd_size_after_call[0] + + uart->rd_size_before_call[1] - + uart->rd_size_after_call[1]; + + uart->rx_out += bytes_read; + + if (uart->rx_out >= &(uart->rx_buffer[0]) + uart->buffer_size + 1) + uart->rx_out = uart->rx_out - uart->buffer_size - 1; + + /* + * Check if the low watermark is reached to enable the receiver. + */ + + bytes_in_rx_buffer = get_bytes_in_rx_buffer (uart); + + if ((uart->flow_control_mode != fc_none) && + (bytes_in_rx_buffer <= RX_LOW_WATERMARK (uart->buffer_size))) { + + if ((!uart->rx_stopped_by_application) && + uart->rx_stopped_by_driver) + start_receiver (uart); + + uart->rx_stopped_by_driver = 0; + } + + uart->rd_call_from_hisr_in_progress = 0; + } + + result = (T_FDRET) bytes_in_rx_buffer; + } + + return (result); +} + +/******************************************************************************* + * + * UAF_OutpAvail + * + * Purpose : Returns the number of free characters in TX buffer of the driver. + * If the driver is disabled the function returns 0. + * + * Arguments: In : uartNo: Used UART. + * Out: none + * + * Returns : >= 0 : The returned value is the amount of data in the + * TX buffer. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_NOT_READY : The function is called while the callback of the + * writeInFunc function is activated and still not + * terminated. + * FD_INTERNAL_ERR : Internal problem with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_OutpAvail (T_fd_UartId uartNo) +{ + T_FDRET result; + t_uart *uart; + SYS_UWORD16 bytes_written; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + */ + + uart = &uart_parameters; + + if (uart->wr_call_setup == rm_notDefined) + result = FD_NOT_READY; + + else if (DRIVER_DISABLED (uart)) + result = 0; + + else { + + /* + * Update reading pointer of the TX buffer if a callback from LISR + * has been done. + */ + + if (uart->wr_call_from_hisr_in_progress) { + + bytes_written = uart->wr_size_before_call[0] - + uart->wr_size_after_call[0] + + uart->wr_size_before_call[1] - + uart->wr_size_after_call[1]; + + uart->tx_in += bytes_written; + + if (uart->tx_in >= &(uart->tx_buffer[0]) + uart->buffer_size + 1) + uart->tx_in = uart->tx_in - uart->buffer_size - 1; + + uart->wr_call_from_hisr_in_progress = 0; + + /* + * if the TX FIFO is empty, unmask TX empty interrupt. + */ + + if (!uart->tx_stopped_by_driver && + (READ_UART_REGISTER (uart, LSR) & THRE)) + { +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Disable sleep mode. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); +#endif + + /* + * Unmask Tx interrupt. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI); + } + } + + result = (T_FDRET) (uart->buffer_size - get_bytes_in_tx_buffer (uart)); + } + + return (result); +} + +/******************************************************************************* + * + * UAF_EnterSleep + * + * Purpose : Checks if UART is ready to enter Deep Sleep. If ready, enables + * wake-up interrupt. + * + * Arguments: In : uartNo: Used UART. + * Out: none + * + * Returns : 0 : Deep Sleep is not possible. + * >= 1 : Deep Sleep is possible. + * FD_NOT_SUPPORTED: Wrong UART number. + * + * Warning: Parameters are not verified. + * + ******************************************************************************/ + +T_FDRET +UAF_EnterSleep (T_fd_UartId uartNo) +{ + t_uart *uart; + SYS_BOOL deep_sleep; + volatile SYS_UWORD8 status; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + uart = &uart_parameters; + deep_sleep = 0; + + /* + * Check if RX & TX FIFOs are both empty + */ + + status = READ_UART_REGISTER (uart, LSR); + + if (!(status & DR) && + (status & TEMT)) { + +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Disable sleep mode. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); +#endif + +#if (CHIPSET == 12) + /* + * Mask DSR interrupt. + */ + + DISABLE_DSR_INTERRUPT (uart); +#endif + + /* + * Mask RX, TX and the modem status interrupts. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & + ~(ERBI | ETBEI | EDSSI)); + + /* + * Enable the wake-up interrupt. + */ + + ENABLE_WAKEUP_INTERRUPT (uart); + + deep_sleep = 1; + } + + return (deep_sleep); +} + +/******************************************************************************* + * + * UAF_WakeUp + * + * Purpose : Wakes up UART after Deep Sleep. + * + * Arguments: In : uartNo: Used UART. + * Out: none + * + * Returns : FD_OK : Successful operation. + * FD_NOT_SUPPORTED: Wrong UART number. + * + * Warning: Parameters are not verified. + * + ******************************************************************************/ + +T_FDRET +UAF_WakeUp (T_fd_UartId uartNo) +{ + t_uart *uart; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + uart = &uart_parameters; + + /* + * Disable the wake-up interrupt. + */ + + DISABLE_WAKEUP_INTERRUPT (uart); + + /* + * Unmask RX and modem status interrupts. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | (ERBI | EDSSI)); + +#if (CHIPSET == 12) + /* + * Unmask DSR interrupt. + */ + + ENABLE_DSR_INTERRUPT (uart); +#endif + +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Allow sleep mode. + */ + /* BELOW LINES WERE COMMENTED TO DISABLE SLEEP MODE IN DRIVER */ + /* + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP); + */ +#endif + + return (FD_OK); +} + +/******************************************************************************* + * + * UAF_ReadData + * + * Purpose : To read the received characters out of the RX buffer the address + * of a function is passed. If characters are available, the driver + * calls this function and pass the address and the amount of + * readable characters. Because the RX buffer is circular, the + * callback function may be called with more than one address of + * buffer fragment. + * The readOutFunc function modifies the contents of the size array + * to return the driver the number of processed characters. Each + * array entry is decremented by the number of bytes read in the + * fragment. + * If the UAF_ReadData is called while the RX buffer is empty, it + * depends on the suspend parameter to suspend the call-back or to + * leave without any operation. In the case of suspension, the + * return value of UAF_ReadData is UAF_SUSPENDED. A delayed call-back + * will be performed if: + * - the RX buffer reachs the adjusted threshold (rxThreshold of + * UAF_SetBuffer), + * - the state of a V.24 input line has changed, + * - a break is detected, + * - an escape sequence is detected. + * If no suspension is necessary the function returns the number of + * processed bytes. + * + * Arguments: In : uartNo : Used UART. + * suspend : mode of suspension in case of RX buffer empty. + * readOutFunc: Callback function. + * cldFromIrq: The driver sets this parameter to 1 + * if the callback function is called + * from an interrupt service routine. + * reInstall : The call-back function sets this + * parameter to rm_reInstall if the + * driver must call again the callback + * function when the RX threshold level + * is reached. Else it will be set to + * rm_noInstall. Before to call the + * readOutFunc function this parameter + * is set to rm_notDefined. + * nsource : Informed the callback function about + * the number of fragments which are + * ready to copy from the circular RX + * buffer. + * source : Array which contains the addresses + * of the fragments. + * size : Array which contains the sizes of + * each fragments. + * state : The state parameter is the status + * of the V.24 lines and the break / + * escape detection. The state + * parameter is described in the + * specification of UAF_GetLineState. + * Out: none + * + * Returns : >= 0 : Succesful operation. Amount of processed bytes. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_SUSPENDED : The callback is suspended until the buffer or + * state condition changed. + * FD_NOT_READY : The function is called while the callback is + * activated and still not terminated. + * FD_INTERNAL_ERR : Internal problems with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_ReadData (T_fd_UartId uartNo, + T_suspendMode suspend, + void (readOutFunc (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 nsource, + SYS_UWORD8 *source[], + SYS_UWORD16 size[], + SYS_UWORD32 state))) +{ + T_FDRET result; + t_uart *uart; + SYS_UWORD16 bytes_read; + SYS_UWORD16 bytes_in_rx_buffer; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + */ + + uart = &uart_parameters; + + if (uart->rd_call_setup == rm_notDefined) + result = FD_NOT_READY; + + else if (get_bytes_in_rx_buffer (uart) || uart->esc_seq_received) { + + uart->readOutFunc = readOutFunc; + update_reading_callback (uart, 0); /* 0: call from application. */ + + bytes_read = uart->rd_size_before_call[0] - + uart->rd_size_after_call[0] + + uart->rd_size_before_call[1] - + uart->rd_size_after_call[1]; + + uart->rx_out += bytes_read; + + if (uart->rx_out >= &(uart->rx_buffer[0]) + uart->buffer_size + 1) + uart->rx_out = uart->rx_out - uart->buffer_size - 1; + + /* + * Check if the low watermark is reached to enable the receiver. + */ + + if ((uart->flow_control_mode != fc_none) && + (get_bytes_in_rx_buffer (uart) <= RX_LOW_WATERMARK ( + uart->buffer_size))) { + + if ((!uart->rx_stopped_by_application) && + uart->rx_stopped_by_driver && (!uart->rx_stopped_by_lisr)) + start_receiver (uart); + + uart->rx_stopped_by_driver = 0; + } + + uart->esc_seq_received = 0; + result = (T_FDRET) bytes_read; + + } else if (suspend == sm_suspend) { + + uart->readOutFunc = readOutFunc; + uart->reading_suspended = 1; + result = FD_SUSPENDED; + + } else { + + /* + * The previous callback function is deinstalled. + */ + + uart->rd_call_setup = rm_noInstall; + uart->reading_suspended = 0; + result = 0; /* 0 byte read. */ + } + + return (result); +} + +/******************************************************************************* + * + * UAF_WriteData + * + * Purpose : To write characters into the TX buffer the address of a function + * is passed. If free space is available in the buffer, the driver + * calls this function and passes the destination address and the + * amount of space. Because the TX buffer is circular, the callback + * function may be called with more than one address of buffer + * fragment. + * The writeInFunc function modifies the contents of the size array + * to return the driver the number of processed bytes. Each array + * entry is decremented by the number of bytes written in this + * fragment. + * If the UAF_WriteData function is called while the TX buffer is + * full, it depends on the suspend parameter to suspend the + * call-back or to leave this function without any operation. In the + * case of suspension the returned value of the UAF_WriteData is + * UAF_SUSPENDED. A delayed call-back will be performed if the TX + * buffer reaches the adjusted threshold (txThreshold of + * UAF_SetBuffer). If no suspension is necessary the function returns + * the number of processed bytes. + * + * Arguments: In : uartNo : Used UART. + * suspend : mode of suspension in case of TX buffer empty. + * writeInFunc: Callback function. + * cldFromIrq: The driver sets this parameter to 1 + * if the call-back function is called + * from an interrupt service routine. + * reInstall : The callback function sets this + * parameter to rm_reInstall if the + * driver must call again the callback + * function when the TX threshold level + * is reached. Else it will be set to + * rm_noInstall. Before to call the + * writeInFunc function this parameter + * is set to rm_notDefined. + * ndest : Informed the callback function about + * the number of fragments which are + * available in the TX buffer. + * dest : Array which contains the addresses + * of the fragments. + * size : Array which contains the sizes of + * each fragments. + * Out: none + * + * Returns : >= 0 : Succesful operation. Amount of processed bytes. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_SUSPENDED : The callback is suspended until the buffer + * condition changed. + * FD_NOT_READY : The function is called while the callback is + * activated and still not terminated. + * FD_INTERNAL_ERR : Internal problems with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_WriteData (T_fd_UartId uartNo, + T_suspendMode suspend, + void (writeInFunc (SYS_BOOL cldFromIrq, + T_reInstMode *reInstall, + SYS_UWORD8 ndest, + SYS_UWORD8 *dest[], + SYS_UWORD16 size[]))) +{ + T_FDRET result; + t_uart *uart; + SYS_UWORD16 bytes_written; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + */ + + uart = &uart_parameters; + + if (uart->wr_call_setup == rm_notDefined) + result = FD_NOT_READY; + + else if ((!DRIVER_DISABLED (uart)) && + (get_bytes_in_tx_buffer (uart) < uart->buffer_size)) { + + uart->writeInFunc = writeInFunc; + update_writing_callback (uart, 0); /* 0: call from application. */ + + bytes_written = uart->wr_size_before_call[0] - + uart->wr_size_after_call[0] + + uart->wr_size_before_call[1] - + uart->wr_size_after_call[1]; + + uart->tx_in += bytes_written; + + if (uart->tx_in >= &(uart->tx_buffer[0]) + uart->buffer_size + 1) + uart->tx_in = uart->tx_in - uart->buffer_size - 1; + + /* If we have been stopped due to high RTS, we have to + * wake up application processor by IRQ via IO1 -HW */ + if (uart->tx_stopped_by_driver) + HighGPIO(1); + + /* + * If: + * - there is no break to send, + * - the flow control is not activated, + * unmask the TX empty interrupt to be able to send characters. + */ + if (!uart->break_to_send && + !uart->tx_stopped_by_driver) + { +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Disable sleep mode. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); +#endif + + /* + * Unmask Tx interrupt. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI); + } + + result = (T_FDRET) bytes_written; + + } else if (suspend == sm_suspend) { + + uart->writeInFunc = writeInFunc; + uart->writing_suspended = 1; + result = FD_SUSPENDED; + + } else { + + /* + * The previous callback function is deinstalled. + */ + + uart->wr_call_setup = rm_noInstall; + uart->writing_suspended = 0; + result = 0; + } + + return (result); +} + +/******************************************************************************* + * + * UAF_StopRec + * + * Purpose : If a flow control mode is set, this function tells the terminal + * equipment that no more data can be received. + * XON/XOFF: XOFF is sent. + * DTR/DSR : DTR is desactivated. + * RTS/CTS : RTS is deactivated. + * + * Arguments: In : uartNo: Used UART. + * Out: none + * + * Returns : FD_OK : Successful operation. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_INTERNAL_ERR : Internal problem with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_StopRec (T_fd_UartId uartNo) +{ + t_uart *uart; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + */ + + uart = &uart_parameters; + + if (uart->flow_control_mode != fc_none) + stop_receiver (uart); + + uart->rx_stopped_by_application = 1; + + return (FD_OK); +} + +/******************************************************************************* + * + * UAF_StartRec + * + * Purpose : If a flow control mode is set, this function tells the terminal + * equipment that the receiver is again able to receive more data. + * If the buffer has already reached the high water mark the driver + * sends the signal only if the buffer drains to a low water mark. + * XON/XOFF: XON is sent. + * DTR/DSR : DTR is activated. + * RTS/CTS : RTS is activated. + * + * Arguments: In : uartNo: Used UART. + * Out: none + * + * Returns : FD_OK : Successful operation. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_INTERNAL_ERR : Internal problem with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_StartRec (T_fd_UartId uartNo) +{ + t_uart *uart; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + */ + + uart = &uart_parameters; + + if ((uart->flow_control_mode != fc_none) && (!uart->rx_stopped_by_driver)) + start_receiver (uart); + + uart->rx_stopped_by_application = 0; + + return (FD_OK); +} + +/******************************************************************************* + * + * UAF_GetLineState + * + * Purpose : Returns the state of the V.24 lines, the flow control state and + * the result of the break/escape detection process as a bit field. + * + * Arguments: In : uartNo: Used UART. + * Out: state : State of the V.24 lines, the flow control state and + * the result of the break/escape sequence detection + * process as a bit field. + * + * Returns : FD_OK : Successful operation. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_NOT_READY : The function is called while the callback of + * the readOutFunc function is activated and still + * not terminated. + * FD_INTERNAL_ERR : Internal problem with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_GetLineState (T_fd_UartId uartNo, + SYS_UWORD32 *state) +{ + T_FDRET result; + t_uart *uart; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + * Signals not supported are reported as 0. + */ + + uart = &uart_parameters; + + if (uart->rd_call_setup == rm_notDefined) + result = FD_NOT_READY; + + else { + + /* + * The field state_2 is used when state_1 is set to 0 to avoid to + * lose events detected in the RX interrupt handler. + * Fields BRK and BRKLEN are set when a break is detected. + * The field ESC is set when an escape sequence is detected. + */ + + *state = uart->state_2; + uart->state_2 = 0; + uart->state = &(uart->state_2); + + *state |= uart->state_1; + uart->state_1 = 0; + uart->state = &(uart->state_1); + + *state |= ((((SYS_UWORD32) uart->rts_level) << RTS) | + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + (((SYS_UWORD32) uart->dtr_level) << DTR) | +#endif + + (((SYS_UWORD32) (uart->tx_stopped_by_application | + uart->tx_stopped_by_driver)) << TXSTP) | + + (((SYS_UWORD32) (uart->rx_stopped_by_application | + uart->rx_stopped_by_driver)) << RXSTP) | + + (((SYS_UWORD32) (uart->buffer_size - + get_bytes_in_rx_buffer (uart))) << RXBLEV)); + + /* + * Fields SA, SB and X are set according to the flow control: + * + * None RTS/CTS XON/XOFF + * SA DTR DTR DTR + * SB RTS 0 RTS + * X 0 RTS XON:0 XOFF:1 (transmitter) + * + * DTR is supported on C, D & E-Sample. + */ + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + *state |= (((SYS_UWORD32) uart->dtr_level) << SA); +#endif + + if (uart->flow_control_mode != fc_rts) + *state |= (((SYS_UWORD32) uart->rts_level) << SB); + + if (uart->flow_control_mode == fc_rts) + *state |= (((SYS_UWORD32) uart->rts_level) << X); + + else if ((uart->flow_control_mode == fc_xoff) && + (uart->tx_stopped_by_application || + uart->tx_stopped_by_driver)) + *state |= (1 << X); + + result = FD_OK; + } + + return (result); +} + +/******************************************************************************* + * + * UAF_SetLineState + * + * Purpose : Sets the states of the V.24 status lines according to the bit + * field of the parameter state. + * + * Arguments: In : uartNo: Used UART. + * state : Bit field. Only the signals which are marked with + * the 'set' access can be used to change the state of + * the signal. + * mask : Bit field with the same structure as state. Each bit + * in state corresponds to a bit in mask. Settabled + * bits marked by a 1 are manipulated by the driver. + * Out: none + * + * Returns : FD_OK : Successful operation. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_INTERNAL_ERR : Internal problem with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_SetLineState (T_fd_UartId uartNo, + SYS_UWORD32 state, + SYS_UWORD32 mask) +{ + t_uart *uart; + UNSIGNED break_length; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + uart = &uart_parameters; + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + * DCD is supported on C, D & E-Sample. The SA field is not supported because + * DSR is not supported on all platforms. + */ + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + if (mask & (1 << SA)) +#else + if ((mask & (1 << SA)) || (mask & (1 << DCD))) +#endif + return (FD_NOT_SUPPORTED); /* Return used to simplify the code */ + + /* + * Check if a break has to be sent. + */ + + uart->break_length = (UNSIGNED) ((state >> BRKLEN) & 0xFF); + + if (state & (1 << BRK) && (mask & (1 << BRK))) { + + if (uart->break_length > FIFO_SIZE) + return (FD_NOT_SUPPORTED); /* Return used to simplify the code */ + + else { + + uart->time_without_character = + compute_break_time (uart->baudrate, uart->bits_per_char, 3); + + uart->break_to_send = 1; + + /* + * If the TX FIFO is empty the break is send from this function + * else the interrupt handler will send the break. + */ + + if (READ_UART_REGISTER (uart, LSR) & TEMT) + send_break(uart); + } + } + +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Disable sleep mode. + */ + + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP); +#endif + + /* + * The CTS field is ignored if the X bit in the mask is set. In this case + * the X bit controls CTS. + */ + + if (mask & (1 << CTS)) { + + if (uart->flow_control_mode != fc_rts) { + + /* + * As the RTS/CTS flow control is not selected, the X bit does not + * control CTS. CTS needs only to be activated or deactivated + * according to the value of the CTS field. + */ + + if (state & (1 << CTS)) + WRITE_UART_REGISTER ( + uart, MCR, READ_UART_REGISTER (uart, MCR) | MRTS); + + else + WRITE_UART_REGISTER ( + uart, MCR, READ_UART_REGISTER (uart, MCR) & ~MRTS); + + } else if (!(mask & (1 << X))) { + + /* + * The RTS/CTS flow control is selected but the X bit in the mask + * is null. Then the CTS bit controls CTS and the receiver must be + * stopped or started according to the state of the CTS bit. + * The receiver is started only if it was not stopped by the driver + * and if it was stopped by the application. + */ + + if (state & (1 << CTS)) { + + if (!uart->rx_stopped_by_application) { + + if (!uart->rx_stopped_by_driver) + stop_receiver (uart); + + uart->rx_stopped_by_application = 1; + } + + } else { + + if ((!uart->rx_stopped_by_driver) && + uart->rx_stopped_by_application) + start_receiver (uart); + + uart->rx_stopped_by_application = 0; + } + } + } + + /* + * The DCD field is ignored if the SB bit of the mask is set. + */ + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + + if (!(mask & (1 << SB)) && (mask & (1 << DCD))) { + + if (state & (1 << DCD)) { + /* Turn on DCD */ + #if (CHIPSET == 12) + WRITE_UART_REGISTER (uart, MCR, READ_UART_REGISTER(uart, MCR) | MDCD); + #else + AI_ResetBit (ARMIO_DCD); + #endif + } else { + /* Turn off DCD */ + #if (CHIPSET == 12) + WRITE_UART_REGISTER (uart, MCR, READ_UART_REGISTER(uart, MCR) & ~MDCD); + #else + AI_SetBit (ARMIO_DCD); + #endif + } + } + +#endif /* BOARD 8 or 9 or 40 or 41 or CHIPSET 12 */ + + /* + * Signals are set according to fields SA, SB and X states and flow + * control: + * + * None RTS/CTS XON/XOFF + * SA 0 (ns) 0 (ns) 0 (ns) + * SB DCD DCD DCD + * X ignore CTS XON:0 XOFF:1 (receiver) + * + * ns: signal not supported. + * DCD is supported on C, D & E-Sample. + */ + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + + if (mask & (1 << SB)) { + + if (state & (1 << SB)) { + /* Turn on DCD */ + #if (CHIPSET == 12) + WRITE_UART_REGISTER (uart, MCR, READ_UART_REGISTER(uart, MCR) | MDCD); + #else + AI_ResetBit (ARMIO_DCD); + #endif + } else { + /* Turn off DCD */ + #if (CHIPSET == 12) + WRITE_UART_REGISTER (uart, MCR, READ_UART_REGISTER(uart, MCR) & ~MDCD); + #else + AI_SetBit (ARMIO_DCD); + #endif + } + } + +#endif /* BOARD 8 or 9 or 40 or 41 or CHIPSET 12 */ + + if ((mask & (1 << X)) && + (uart->flow_control_mode != fc_none)) { + + if (state & (1 << X)) { + + if (!uart->rx_stopped_by_application) { + + if (!uart->rx_stopped_by_driver) + stop_receiver (uart); + + uart->rx_stopped_by_application = 1; + } + + } else { + + /* + * The receiver is started only if it is not stopped by the driver + * and if it is stopped by the application. + */ + + if ((!uart->rx_stopped_by_driver) && + uart->rx_stopped_by_application) + start_receiver (uart); + + uart->rx_stopped_by_application = 0; + } + } + +#if ((CHIPSET != 5) && (CHIPSET != 6)) + /* + * Re-enable sleep mode. + */ + /* BELOW LINES WERE COMMENTED TO DISABLE SLEEP MODE IN DRIVER */ + /* + WRITE_UART_REGISTER ( + uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP); + */ +#endif + + return (FD_OK); +} + +/******************************************************************************* + * + * UAF_InterruptHandler + * + * Purpose : Interrupt handler. + * + * Arguments: In : uart_id : origin of interrupt + * interrupt_status: source of interrupt + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +void +UAF_InterruptHandler (T_fd_UartId uart_id, + SYS_UWORD8 interrupt_status) +{ + + t_uart *uart; + + /* + * uart_id is not used. + */ + + uart = &uart_parameters; + + uart->current_time = NU_Retrieve_Clock (); + + /* + * Causes of interrupt: + * - trigger level reached, + * - character time-out indication, + * - transmitter holding register empty, + * - modem status. + */ + + switch (interrupt_status) { + + case RX_DATA: + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (CHIPSET == 12)) + uart->index_it = (uart->index_it + 1) & 0x01; /* 0 or 1 */ + uart->dtr_change_detected[uart->index_it] = 0; + uart->dtr_level_saved[uart->index_it] = uart->dtr_level; +#endif + read_rx_fifo (uart); + + // Disable Autobaud and lock baudrate upon first received character + if (uart->autobauding != 0) + { + /* MSMSMSMS */ + SYS_UWORD8 uasr; + T_baudrate baudrate; + T_bitsPerCharacter bpc; + T_parity parity; + + WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) | DLAB); + + + uasr = READ_UART_REGISTER (uart, UASR); + + switch (uasr & 0x1F) + { + case 0x01: baudrate = FD_BAUD_115200; break; + case 0x02: baudrate = FD_BAUD_57600; break; + case 0x03: baudrate = FD_BAUD_38400; break; + case 0x04: baudrate = FD_BAUD_28800; break; + case 0x05: baudrate = FD_BAUD_19200; break; + case 0x06: baudrate = FD_BAUD_14400; break; + case 0x07: baudrate = FD_BAUD_9600; break; + case 0x08: baudrate = FD_BAUD_4800; break; + case 0x09: baudrate = FD_BAUD_2400; break; + case 0x0A: baudrate = FD_BAUD_1200; break; + default: /* no baudrate detected, abort for now */ + return; + } + + switch (uasr>>5 & 0x01) + { + case 0x00: bpc = bpc_7; break; + case 0x01: bpc = bpc_8; break; + } + + switch (uasr>>6 & 0x03) + { + case 0x00: parity = pa_none; break; + case 0x01: parity = pa_space; break; + case 0x02: parity = pa_even; break; + case 0x03: parity = pa_odd; break; + } + + UAF_SetComPar (UAF_UART_1, + baudrate, + bpc, + sb_1, + parity); + + uart->baudrate = baudrate_value[FD_BAUD_AUTO]; /* remember autobauding */ + } + + break; + + case TX_EMPTY: + + fill_tx_fifo (uart); + break; + + case MODEM_STATUS: + + check_v24_input_lines (uart); + break; + } +} + +/******************************************************************************* + * + * UAF_CheckXEmpty + * + * Purpose : Checks the empty condition of the Transmitter. + * + * Arguments: In : uartNo: Used UART. + * Out: none + * + * Returns : FD_OK : Empty condition OK. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_NOT_READY : Empty condition not OK. + * FD_INTERNAL_ERR : Internal problem with the hardware. + * + ******************************************************************************/ + +T_FDRET +UAF_CheckXEmpty (T_fd_UartId uartNo) +{ + T_FDRET result; + t_uart *uart; + SYS_UWORD8 status; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + /* + * There is no case where FD_INTERNAL_ERR may be returned. + */ + + result = FD_OK; + + uart = &uart_parameters; + status = READ_UART_REGISTER (uart, LSR); + + /* + * Checks if: + * - the TX SW Buffer is empty, + * - the TX HW FIFO is empty (THRE), + * - the Transmitter Shift Register is empty (TEMT). + */ + + if (!(TX_BUFFER_EMPTY (uart)) || + !(status & THRE) || + !(status & TEMT)) + + result = FD_NOT_READY; + + return (result); +} + +#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41)) +/******************************************************************************* + * + * UAF_DTRInterruptHandler + * + * Purpose : This function is only used on C & D-Sample. On this platform, the + * DTR signal is controlled with an I/O. A change of state of this + * signal is detected with an interrupt. This function is called when + * this interrupt occurs. + * + * Arguments: In : none + * Out: none + * + * Returns : none + * + ******************************************************************************/ + +void +UAF_DTRInterruptHandler (void) +{ + t_uart *uart; + + uart = &uart_parameters; + + /* + * Read the state of DTR and change the edge to detect the next change + * of DTR. + */ + + uart->dtr_level = AI_ReadBit (ARMIO_DTR); + + if (uart->dtr_level) + { + AI_SelectIOForIT (ARMIO_DTR, ARMIO_FALLING_EDGE); + if (uart->flow_control_mode != fc_dtr && uart->baudrate == baudrate_value[FD_BAUD_AUTO]) + UAF_SetComPar (UAF_UART_1, FD_BAUD_AUTO, bpc_8, sb_1, pa_none); + } + else + AI_SelectIOForIT (ARMIO_DTR, ARMIO_RISING_EDGE); + + /* + * The reading callback function has to be called. But bytes received before + * the change of state of DTR must be copied into the RX buffer before to + * call it. + */ + + if (READ_UART_REGISTER (uart, LSR) & DR) { /* If Rx FIFO is not empty */ + + /* + * The Rx FIFO will be read to fill one of the two buffers and the Rx + * HISR will be activated. + */ + + uart->index_it = (uart->index_it + 1) & 0x01; /* 0 or 1 */ + uart->dtr_change_detected[uart->index_it] = 1; + uart->dtr_level_saved[uart->index_it] = uart->dtr_level; + read_rx_fifo (uart); + + } else + (void) NU_Activate_HISR (&(uart->v24_hisr_ctrl_block)); + +} +#endif /* BOARD 8 or 9 or 40 or 41 */ + +#if (defined BTEMOBILE && (CHIPSET != 12)) +/******************************************************************************* + * + * UAF_Exit + * + * Purpose : + * + * Arguments: In : uartNo: Used UART. + * Out: none + * + * Returns : FD_OK : Successful operation. + * FD_NOT_SUPPORTED: Wrong UART number. + * FD_INTERNAL_ERR : Internal problem. + * + ******************************************************************************/ + +T_FDRET +UAF_Exit (T_fd_UartId uartNo) +{ + t_uart *uart; + + /* + * Check UART number. + * A return is used to simplify the code. + * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware + * flow control is not supported. + * DCD and DTR are not supported on UART Irda on C & D-Sample. + * DCD and DTR are not supported on UART Irda & Modem2 on E-Sample. + */ + + if (uartNo != UAF_UART_1) + return (FD_NOT_SUPPORTED); + + uart = &uart_parameters; + + /* + * Delete the 3 HISR actived in the RX/TX and V24 interrupt handlers. + * A return is used to simplify the code if an error occurs. + */ + + if (NU_Delete_HISR (&(uart->rx_hisr_ctrl_block)) != NU_SUCCESS) + return (FD_INTERNAL_ERR); + + if (NU_Delete_HISR (&(uart->tx_hisr_ctrl_block)) != NU_SUCCESS) + return (FD_INTERNAL_ERR); + + if (NU_Delete_HISR (&(uart->v24_hisr_ctrl_block)) != NU_SUCCESS) + return (FD_INTERNAL_ERR); + + /* + * Delete the HISR used to send a break. + * A return is used to simplify the code if an error occurs. + */ + + if (NU_Delete_HISR (&(uart->break_hisr_ctrl_block)) != NU_SUCCESS) + return (FD_INTERNAL_ERR); + + /* + * Disable and then delete the timer used in the break HISR + * A return is used to simplify the code if an error occurs. + */ + + (void) NU_Control_Timer (&(uart->break_timer_ctrl_block), + NU_DISABLE_TIMER); + + if (NU_Delete_Timer (&(uart->break_timer_ctrl_block)) != NU_SUCCESS) + return (FD_INTERNAL_ERR); + + /* + * Disable and then delete the timer used in the detection of the escape + * sequence. A return is used to simplify the code if an error occurs. + */ + + (void) NU_Control_Timer (&(uart->guard_period_timer_ctrl_block), + NU_DISABLE_TIMER); + + if (NU_Delete_Timer (&(uart->guard_period_timer_ctrl_block)) != NU_SUCCESS) + return (FD_INTERNAL_ERR); + + /* + * At that point, all HISRs and Timers have been successfully deleted. + */ + + return (FD_OK); +} +#endif /* (defined BTEMOBILE && (CHIPSET != 12)) */ + +
--- a/gsm-fw/serial/uartfax.c Sun Apr 26 03:06:32 2015 +0000 +++ b/gsm-fw/serial/uartfax.c Thu Apr 30 01:46:26 2015 +0000 @@ -331,7 +331,7 @@ #define READ_UART_REGISTER(UART,REG) \ *((volatile SYS_UWORD8 *) ((UART)->base_address + (REG))) -#define WRITE_UART_REGISTER(UART,REG,VALUE) \ +#define WRITE_UART_REGISTER(UART,REG,VALUE) \ *((volatile SYS_UWORD8 *) ((UART)->base_address + (REG))) = (VALUE) #define RESET_BIT(UART,REG,BIT) \ @@ -2173,26 +2173,21 @@ uart, IER, READ_UART_REGISTER (uart, IER) & ~(ERBI | EDSSI)); - if ((uart->rx_buffer_used_by_rx_hisr) == &(uart->rx_fifo_byte_1[0])) { - - uart->bytes_in_rx_buffer_1 = 0; - - } else { - - uart->bytes_in_rx_buffer_2 = 0; - } + if ((uart->rx_buffer_used_by_rx_hisr) == &(uart->rx_fifo_byte_1[0])) + uart->bytes_in_rx_buffer_1 = 0; + else + uart->bytes_in_rx_buffer_2 = 0; - WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB); + WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB); - /* Unmask The Rx and Modem status interrupt*/ - WRITE_UART_REGISTER ( + /* Unmask The Rx and Modem status interrupt*/ + WRITE_UART_REGISTER ( uart, IER, READ_UART_REGISTER (uart, IER) | (ERBI | EDSSI)); - if(uart->rx_stopped_by_lisr ) { + if(uart->rx_stopped_by_lisr ) { if (!uart->rx_stopped_by_driver) { - uart->rx_stopped_by_lisr = 0; @@ -2769,7 +2764,7 @@ "Break", stop_break, 0, /* Parameter supplied to the routine: not used. */ - 0, /* This parameter is set when the timer is reset. */ + 1, /* This parameter is set when the timer is reset. */ 0, /* The timer expires once. */ NU_DISABLE_TIMER) != NU_SUCCESS) @@ -2784,7 +2779,7 @@ "Esc seq", analyze_guard_period_timer_expiration, 0, /* Parameter supplied to the routine: not used. */ - 0, /* This parameter is set when the timer is reset. */ + 1, /* This parameter is set when the timer is reset. */ 0, /* The timer expires once. */ NU_DISABLE_TIMER) != NU_SUCCESS)