comparison src/cs/drivers/drv_app/uart/uartfax_dp.c @ 0:b6a5e36de839

src/cs: initial import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 15 Jul 2018 04:39:26 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:b6a5e36de839
1 /*******************************************************************************
2 *
3 * UARTFAX.C
4 *
5 * This driver allows to control the UARTs of chipset 1.5 for fax and data
6 * services. It performs flow control: RTS/CTS, XON/XOFF.
7 *
8 * (C) Texas Instruments 1999
9 *
10 ******************************************************************************/
11
12 /*
13 * DB9 16750
14 *
15 * 1 DCD DTR output
16 * 2 RX SOUT output
17 * 3 TX SIN input
18 * 4 DTR DSR input
19 * 5 GND
20 * 6 DSR (connected to DTR (DB9) if J1 is used)
21 * 7 RTS CTS input
22 * 8 CTS RTS output
23 * 9 nc
24 */
25 #include <string.h>
26 #include "nucleus.h"
27
28 #include "config/chipset.cfg"
29 #include "config/board.cfg"
30
31 #include "main/sys_types.h"
32 #include "uart/faxdata.h"
33 #include "uart/uartfax.h"
34 #include "memif/mem.h"
35
36
37 short uart_initialized = 0;
38
39
40 /*
41 * Maximal value for an unsigned 32 bits.
42 */
43
44 #define MAX_UNSIGNED_32 (4294967295)
45
46 #define FIFO_SIZE (64) /* In bytes. */
47
48
49 /*
50 * TLR is used to program the RX FIFO trigger levels. FCR[7:4] are not used.
51 * No trigger level used for TX FIFO. THR_IT generated on TX FIFO empty.
52 */
53
54 #define RX_FIFO_TRIGGER_LEVEL (12 << 4)
55
56
57 /*
58 * 16750 addresses. Registers accessed when LCR[7] = 0.
59 */
60
61 #define RHR (0x00) /* Rx buffer register - Read access */
62 #define THR (0x00) /* Tx holding register - Write access */
63 #define IER (0x01) /* Interrupt enable register */
64
65 /*
66 * 16750 addresses. Registers accessed when LCR[7] = 1.
67 */
68
69 #define DLL (0x00) /* Divisor latch (LSB) */
70 #define DLM (0x01) /* Divisor latch (MSB) */
71
72
73 /*
74 * EFR is accessed when LCR[7:0] = 0xBF.
75 */
76
77 #define EFR (0x02) /* Enhanced feature register */
78
79
80 /*
81 * 16750 addresses. Bit 5 of the FCR register is accessed when LCR[7] = 1.
82 */
83
84 #define IIR (0x02) /* Interrupt ident. register - Read only */
85 #define FCR (0x02) /* FIFO control register - Write only */
86 #define LCR (0x03) /* Line control register */
87 #define MCR (0x04) /* Modem control register */
88 #define LSR (0x05) /* Line status register */
89 #define MSR (0x06) /* Modem status register */
90 #define TCR (0x06) /* Transmission control register */
91 #define TLR (0x07) /* Trigger level register */
92 #define MDR1 (0x08) /* Mode definition register 1 */
93 #define SCR (0x10) /* Supplementary Control register */
94 #define SSR (0x11) /* Supplementary Status register */
95
96
97 /*
98 * Supplementary control register.
99 */
100
101 #define TX_EMPTY_CTL_IT (0x08)
102 #define RX_CTS_WAKE_UP_ENABLE_BIT (4) /* Use RESET_BIT and SET_BIT macros. */
103
104 /*
105 * Enhanced feature register.
106 */
107
108 #define ENHANCED_FEATURE_BIT (4) /* Use RESET_BIT and SET_BIT macros. */
109
110 /*
111 * Mode definition register 1.
112 */
113
114 #define UART_MODE (0x00)
115 #define SIR_MODE (0x01)
116 #define UART_MODE_AUTOBAUDING (0x02) /* Reserved in UART/IrDA. */
117 #define RESET_DEFAULT_STATE (0x07)
118 #define IR_SLEEP_DISABLED (0x00)
119 #define IR_SLEEP_ENABLED (0x08)
120 #define SIR_TX_WITHOUT_ACREG2 (0x00) /* Reserved in UART/modem. */
121 #define SIR_TX_WITH_ACREG2 (0x20) /* Reserved in UART/modem. */
122 #define FRAME_LENGTH_METHOD (0x00) /* Reserved in UART/modem. */
123 #define EOT_BIT_METHOD (0x80) /* Reserved in UART/modem. */
124
125 /*
126 * Supplementary Status Register
127 */
128
129 #define TX_FIFO_FULL (0x01)
130
131
132 /*
133 * Interrupt enable register.
134 */
135
136 #define ERBI (0x01) /* Enable received data available interrupt */
137 #define ETBEI (0x02) /* Enable transmitter holding register empty interrupt */
138 #define ELSI (0x04) /* Enable receiver line status interrupt */
139 #define EDSSI (0x08) /* Enable modem status interrupt */
140 #define IER_SLEEP (0x00) /* Enable sleep mode */
141
142 /*
143 * Modem control register.
144 */
145
146 #define MDTR (0x01) /* Data terminal ready. */
147 #define MRTS (0x02) /* Request to send. */
148 #define TCR_TLR_BIT (6)
149
150 /*
151 * Line status register.
152 */
153
154 #define DR (0x01) /* Data ready */
155 #define OE (0x02) /* Overrun error */
156 #define PE (0x04) /* Parity error */
157 #define FE (0x08) /* Framing error */
158 #define BI (0x10) /* Break interrupt */
159 #define THRE (0x20) /* Transmitter holding register (FIFO empty) */
160 #define TEMT (0x40) /* Transmitter empty (FIFO and TSR both empty) */
161
162 #define BYTE_ERROR (OE | PE | FE | BI)
163
164 /*
165 * Interrupt identification register.
166 * Bit 0 is set to 0 if an IT is pending.
167 * Bits 1 and 2 are used to identify the IT.
168 */
169
170 #define IIR_BITS_USED (0x07)
171 #define IT_PENDING (0x01)
172 #define RX_DATA (0x04)
173 #define TX_EMPTY (0x02)
174 #define MODEM_STATUS (0x00)
175
176 /*
177 * Modem status register.
178 */
179
180 #define DELTA_CTS (0x01)
181 #define DELTA_DSR (0x02)
182 #define MCTS (0x10) /* Clear to send */
183 #define MDSR (0x20) /* Data set ready */
184
185 /*
186 * Line control register.
187 */
188
189 #define WLS_5 (0x00) /* Word length: 5 bits */
190 #define WLS_6 (0x01) /* Word length: 6 bits */
191 #define WLS_7 (0x02) /* Word length: 7 bits */
192 #define WLS_8 (0x03) /* Word length: 8 bits */
193 #define STB (0x04) /* Number of stop bits: 0: 1, 1: 1,5 or 2 */
194 #define PEN (0x08) /* Parity enable */
195 #define EPS (0x10) /* Even parity select */
196 #define BREAK_CONTROL (0x40) /* Enable a break condition */
197 #define DLAB (0x80) /* Divisor latch access bit */
198
199 /*
200 * FIFO control register.
201 */
202
203 #define FIFO_ENABLE (0x01)
204 #define RX_FIFO_RESET (0x02)
205 #define TX_FIFO_RESET (0x04)
206
207 /*
208 * These constants define the states of the escape sequence detection.
209 */
210
211 #define INITIALIZATION (0)
212 #define NO_ESCAPE_SEQUENCE (1)
213 #define ONE_CHAR_DETECTED (2)
214 #define TWO_CHARS_DETECTED (3)
215 #define THREE_CHARS_DETECTED (4)
216
217 #define CHARACTERS_IN_ESC_SEQ (3)
218 #define DEFAULT_ESC_SEQ_CHARACTER '+'
219 #define DEFAULT_GUARD_PERIOD (1000) /* 1 second. */
220
221 /*
222 * 3 HISR are used to avoid to execute operations from the LISR.
223 */
224
225 #define RX_HISR_PRIORITY (2)
226 #define RX_HISR_STACK_SIZE (512) /* Bytes. */
227 #define TX_HISR_PRIORITY (2)
228 #define TX_HISR_STACK_SIZE (512) /* Bytes. */
229 #define V24_HISR_PRIORITY (2)
230 #define V24_HISR_STACK_SIZE (512) /* Bytes. */
231
232 /*
233 * When the break interrupt indicator (BI) is set in the line status register
234 * (LSR), it indicates that the received data input was held in the low state
235 * for longer than a full-word transmission time. In the FIFO mode, when a break
236 * occurs, only one 0 character is loaded into the FIFO. The next character
237 * transfer is enabled after SIN goes to the marking state for at least two RCLK
238 * samples and then receives the next valid start bit.
239 * This constant defined a defined break length returned by the US_GetLineState
240 * function.
241 */
242
243 #define MINIMAL_BREAK_LENGTH (2)
244
245 #define BREAK_HISR_PRIORITY (2)
246 #define BREAK_HISR_STACK_SIZE (512) /* Bytes. */
247
248 /*
249 * These macros allow to read and write a UART register.
250 */
251
252 #define READ_UART_REGISTER(UART,REG) \
253 *((volatile SYS_UWORD8 *) ((UART)->base_address + (REG)))
254
255 #define WRITE_UART_REGISTER(UART,REG,VALUE) \
256 *((volatile SYS_UWORD8 *) ((UART)->base_address + (REG))) = (VALUE)
257
258 #define RESET_BIT(UART,REG,BIT) \
259 (WRITE_UART_REGISTER ( \
260 UART, REG, READ_UART_REGISTER (UART, REG) & ~(1 << (BIT))))
261
262 #define SET_BIT(UART,REG,BIT) \
263 (WRITE_UART_REGISTER ( \
264 UART, REG, READ_UART_REGISTER (UART, REG) | (1 << (BIT))))
265
266
267 /*
268 * These macros allow to enable or disable the wake-up interrupt.
269 */
270
271 #define ENABLE_WAKEUP_INTERRUPT(UART) \
272 SET_BIT(UART, SCR, RX_CTS_WAKE_UP_ENABLE_BIT);
273
274 #define DISABLE_WAKEUP_INTERRUPT(UART) \
275 RESET_BIT(UART, SCR, RX_CTS_WAKE_UP_ENABLE_BIT);
276
277
278 /*
279 * This macro is used to simplify the code in detect_escape_sequence.
280 */
281
282 #define CHECK_RX_FIFO_OUT_WRAP_AROUND(UART) \
283 { \
284 if (rx_fifo_out == \
285 &((UART)->rx_fifo_byte[0]) + (UART)->rx_fifo_buffer_size + 1) \
286 rx_fifo_out = &((UART)->rx_fifo_byte[0]); \
287 }
288
289 /*
290 * This macro is created to simplify the code. It allows to write a byte from
291 * the TX buffer to the TX FIFO.
292 * The tx_out pointer is incremented before to write the character into the
293 * TX FIFO because an interrupt may occur between the two operations.
294 */
295
296 #define WRITE_ONE_TX_BUFFER_BYTE_IN_TX_FIFO(UART) \
297 { \
298 SYS_UWORD8 buffer_byte; \
299 \
300 if (get_bytes_in_tx_buffer (UART)) { \
301 \
302 buffer_byte = *((UART)->tx_out++); \
303 WRITE_UART_REGISTER (UART, THR, buffer_byte); \
304 \
305 if ((UART)->tx_out == \
306 &((UART)->tx_buffer[0]) + (UART)->buffer_size + 1) \
307 \
308 (UART)->tx_out = &((UART)->tx_buffer[0]); \
309 } \
310 }
311
312 /*
313 * The transmitter is disabled only when the application disables the driver.
314 * To disable the driver, the receiver and the transmitter are disabled by the
315 * application. The transmitter is disabled first to test if the driver is
316 * disabled.
317 */
318
319 #define DRIVER_DISABLED(UART) ((UART)->tx_stopped_by_application)
320
321 #define DISABLE_DRIVER(UART) \
322 { \
323 (UART)->tx_stopped_by_application = 1; \
324 (UART)->rx_stopped_by_application = 1; \
325 }
326
327 #define ENABLE_DRIVER(UART) \
328 { \
329 (UART)->rx_stopped_by_application = 0; \
330 (UART)->tx_stopped_by_application = 0; \
331 }
332
333 /*
334 * Low and high watermarks for the RX buffer. If it is enabled, the flow
335 * control is activated or deactivated according to these values.
336 * The high watermark value allows to copy an array filled with the RX FIFO
337 * into the RX buffer.
338 */
339
340 #define RX_LOW_WATERMARK(RX_BUFFER_SIZE) (FIFO_SIZE)
341 #define RX_HIGH_WATERMARK(RX_BUFFER_SIZE) ((RX_BUFFER_SIZE) - 2 * FIFO_SIZE)
342
343 /*
344 * This macro allows to know if the RX buffer is full. It must be called only
345 * from the RX HISR. If it is called from the application, the rx_in and
346 * rx_fifo_in pointers may be updated if a RX interrupt occurs or if the
347 * RX HISR is activated.
348 */
349
350 #define RX_BUFFER_FULL(UART) \
351 (((UART)->rx_in == (UART)->rx_out - 1) || \
352 ((UART)->rx_in == (UART)->rx_out + (UART)->buffer_size))
353
354 /*
355 * This macro allows to know if the TX buffer is empty.
356 */
357
358 #define TX_BUFFER_EMPTY(UART) \
359 ((UART)->tx_in == (UART)->tx_out)
360
361 /*
362 * This macro is used to convert a time (unit: ms) into a number of TDMA.
363 * 1 TDMA = 4.6 ms (23/5).
364 */
365
366 #define CONVERT_TIME_IN_TDMA(TIME) (((TIME) * 5) / 23)
367
368 /*
369 * Size of the intermediate circular buffer used to store RX FIFO bytes before
370 * to analyze them from the RX HISR.
371 */
372
373 #define RX_FIFO_BUFFER_SIZE (2 * FIFO_SIZE)
374
375
376
377 typedef void (*T_HISR_ENTRY)(void);
378 typedef void (*T_TIMER_FUNCTION)(UNSIGNED);
379
380 static void hisr_execute_rx_entry_point_1(void);
381 static void hisr_execute_rx_entry_point_2(void);
382 static void hisr_execute_tx_entry_point_1(void);
383 static void hisr_execute_tx_entry_point_2(void);
384 static void hisr_execute_v24_entry_point_1(void);
385 static void hisr_execute_v24_entry_point_2(void);
386 static void hisr_start_break_entry_point_1(void);
387 static void hisr_start_break_entry_point_2(void);
388 static void stop_break_entry_point_1(UNSIGNED);
389 static void stop_break_entry_point_2(UNSIGNED);
390 static void analyze_guard_period_timer_expiration_entry_1(UNSIGNED);
391 static void analyze_guard_period_timer_expiration_entry_2(UNSIGNED);
392
393
394 const T_TIMER_FUNCTION analyze_guard_period_timer_expiration_tab[NUMBER_OF_FD_UART] =
395 {
396 analyze_guard_period_timer_expiration_entry_1,
397 analyze_guard_period_timer_expiration_entry_2
398 };
399
400 const T_TIMER_FUNCTION stop_break_tab[NUMBER_OF_FD_UART] =
401 {
402 stop_break_entry_point_1,
403 stop_break_entry_point_2
404 };
405
406 const T_HISR_ENTRY hisr_execute_rx_tab[NUMBER_OF_FD_UART] =
407 {
408 hisr_execute_rx_entry_point_1,
409 hisr_execute_rx_entry_point_2
410 };
411
412 const T_HISR_ENTRY hisr_execute_tx_tab[NUMBER_OF_FD_UART] =
413 {
414 hisr_execute_tx_entry_point_1,
415 hisr_execute_tx_entry_point_2
416 };
417
418 const T_HISR_ENTRY hisr_execute_v24_tab[NUMBER_OF_FD_UART] =
419 {
420 hisr_execute_v24_entry_point_1,
421 hisr_execute_v24_entry_point_2
422 };
423
424 const T_HISR_ENTRY hisr_start_break_tab[NUMBER_OF_FD_UART] =
425 {
426 hisr_start_break_entry_point_1,
427 hisr_start_break_entry_point_2
428 };
429
430
431
432 /*
433 * This structure describes an UART compatible with the UART 16750 and
434 * contains some fields to manage this UART.
435 */
436
437 typedef struct s_uart {
438
439 SYS_UWORD32 base_address;
440
441 /*
442 * HISR executed from the RX/TX interrupt handler.
443 */
444
445 NU_HISR rx_hisr_ctrl_block;
446 NU_HISR tx_hisr_ctrl_block;
447 NU_HISR v24_hisr_ctrl_block;
448 char rx_hisr_stack[RX_HISR_STACK_SIZE];
449 char tx_hisr_stack[TX_HISR_STACK_SIZE];
450 char v24_hisr_stack[V24_HISR_STACK_SIZE];
451
452 /*
453 * 2 arrays are used to store bytes read in RX FIFO. A UART RX interrupt
454 * may occur while executing RX operations in RX HISR. To avoid overwriting
455 * the array in which received bytes are stored, a second array is used.
456 */
457
458 SYS_UWORD8 *rx_buffer_used_by_rx_lisr;
459 SYS_UWORD8 *rx_buffer_used_by_rx_hisr;
460 SYS_UWORD8 rx_fifo_byte_1[FIFO_SIZE];
461 SYS_UWORD8 rx_fifo_byte_2[FIFO_SIZE];
462 SYS_UWORD16 bytes_in_rx_buffer_1;
463 SYS_UWORD16 bytes_in_rx_buffer_2;
464
465 /*
466 * RX and TX buffers.
467 * One character is not used in each buffer to allow to know if the buffer
468 * is empty or not (See macro RX_BUFFER_FULL). If buffers are empty,
469 * rx_in = rx_out and tx_in = tx_out. It is impossible to use fields to
470 * count the number of bytes in each buffer because these fields may be
471 * updated from the application and from the interrupt handlers. That avoids
472 * to have conflicts.
473 */
474
475 SYS_UWORD16 buffer_size;
476 SYS_UWORD16 rx_threshold_level;
477 SYS_UWORD16 tx_threshold_level;
478 SYS_UWORD8 rx_buffer[FD_MAX_BUFFER_SIZE + 1];
479 SYS_UWORD8 tx_buffer[FD_MAX_BUFFER_SIZE + 1];
480 SYS_UWORD8 *rx_in;
481 SYS_UWORD8 *rx_out;
482 SYS_UWORD8 *tx_in;
483 SYS_UWORD8 *tx_out;
484
485 /*
486 * Escape sequence.
487 * the field esc_seq_modified may have 2 values:
488 * - 0: No modification.
489 * - 1: Parameters are in the process of modification: The detection
490 * is stopped.
491 */
492
493 NU_TIMER guard_period_timer_ctrl_block;
494 SYS_UWORD8 esc_seq_modified;
495 SYS_UWORD8 esc_seq_detection_state;
496 SYS_UWORD8 esc_seq_character;
497 UNSIGNED guard_period;
498 UNSIGNED current_time;
499 UNSIGNED previous_time;
500
501 /*
502 * Flow control.
503 */
504
505 T_flowCtrlMode flow_control_mode;
506 SYS_BOOL send_xon_xoff;
507 SYS_UWORD8 xon_xoff_to_send;
508 SYS_UWORD8 xon_character;
509 SYS_UWORD8 xoff_character;
510 SYS_BOOL rx_stopped_by_application;
511 SYS_BOOL rx_stopped_by_driver;
512 SYS_BOOL tx_stopped_by_application;
513 SYS_BOOL tx_stopped_by_driver;
514
515 /*
516 * Break.
517 */
518
519 SYS_BOOL break_received;
520 SYS_BOOL break_to_send;
521 SYS_BOOL break_in_progress;
522 NU_HISR break_hisr_ctrl_block;
523 char break_hisr_stack[BREAK_HISR_STACK_SIZE];
524 NU_TIMER break_timer_ctrl_block;
525 UNSIGNED baudrate;
526 UNSIGNED bits_per_char; /* Including start, stop and parity bits. */
527 UNSIGNED break_length; /* In bytes. */
528 UNSIGNED time_without_character;
529
530 /*
531 * Callback (UAF_ReadData and UAF_WriteData).
532 * rd: read, wr: write.
533 */
534
535 SYS_UWORD8 cts_level; /* 1: The RS232 line is deactivated (low). */
536 SYS_BOOL esc_seq_received;
537
538 SYS_BOOL reading_suspended;
539 SYS_BOOL writing_suspended;
540 SYS_BOOL rd_call_from_hisr_in_progress;
541 SYS_BOOL wr_call_from_hisr_in_progress;
542 T_reInstMode rd_call_setup;
543 T_reInstMode wr_call_setup;
544 SYS_UWORD8 *rd_address[2];
545 SYS_UWORD8 *wr_address[2];
546 SYS_UWORD16 rd_size_before_call[2];
547 SYS_UWORD16 rd_size_after_call[2];
548 SYS_UWORD16 wr_size_before_call[2];
549 SYS_UWORD16 wr_size_after_call[2];
550
551 void (*readOutFunc) (SYS_BOOL cldFromIrq,
552 T_reInstMode *reInstall,
553 SYS_UWORD8 nsource,
554 SYS_UWORD8 *source[],
555 SYS_UWORD16 size[],
556 SYS_UWORD32 state);
557
558 void (*writeInFunc) (SYS_BOOL cldFromIrq,
559 T_reInstMode *reInstall,
560 SYS_UWORD8 ndest,
561 SYS_UWORD8 *dest[],
562 SYS_UWORD16 size[]);
563
564 /*
565 * These fields are used to store the state defined in UAF_GetLineState.The
566 * first field is used when UAF_GetLineState and UAF_ReadData are not called.
567 * When one of these functions is called the second field is used. That
568 * avoids to lose events when UAF_GetLineState or UAF_ReadData resets the
569 * first field.
570 */
571
572 SYS_UWORD32 state_1;
573 SYS_UWORD32 state_2;
574 SYS_UWORD32 *state;
575
576 /*
577 * Errors counters.
578 */
579
580 SYS_UWORD32 framing_error;
581 SYS_UWORD32 parity_error;
582 SYS_UWORD32 overrun_error;
583 SYS_UWORD32 spurious_interrupts;
584
585 SYS_UWORD16 max_rx_fifo_level;
586
587 } t_uart;
588
589 static t_uart uart_parameters[NUMBER_OF_FD_UART];
590
591 static const SYS_UWORD32 base_address[NUMBER_OF_FD_UART] =
592 {
593 MEM_UART_IRDA,
594 MEM_UART_MODEM
595 };
596
597
598 /*
599 * DLL (LSB) and DLH (MSB) registers values using the 13 MHz clock.
600 */
601
602 static const SYS_UWORD8 dll[] =
603 {
604 0, /* Auto baud: not supported. */
605 81, /* 75 baud. */
606 40, /* 150 baud. */
607 148, /* 300 baud. */
608 74, /* 600 baud. */
609 165, /* 1200 baud. */
610 83, /* 2400 baud. */
611 169, /* 4800 baud. */
612 113, /* 7200 baud. */
613 84, /* 9600 baud. */
614 56, /* 14400 baud. */
615 42, /* 19200 baud. */
616 28, /* 28800 baud. */
617 24, /* 33900 baud: not supported. */
618 21, /* 38400 baud. */
619 14, /* 57600 baud. */
620 7, /* 115200 baud. */
621 0, /* 203125 baud: not supported. */
622 0, /* 406250 baud: not supported. */
623 0 /* 812500 baud: not supported. */
624 };
625
626 static const SYS_UWORD8 dlh[] =
627 {
628 0, /* Auto baud: not supported. */
629 42, /* 75 baud. */
630 21, /* 150 baud. */
631 10, /* 300 baud. */
632 5, /* 600 baud. */
633 2, /* 1200 baud. */
634 1, /* 2400 baud. */
635 0, /* 4800 baud. */
636 0, /* 7200 baud. */
637 0, /* 9600 baud. */
638 0, /* 14400 baud. */
639 0, /* 19200 baud. */
640 0, /* 28800 baud. */
641 0, /* 33900 baud: not supported. */
642 0, /* 38400 baud. */
643 0, /* 57600 baud. */
644 0, /* 115200 baud. */
645 0, /* 203125 baud: not supported. */
646 0, /* 406250 baud: not supported. */
647 0 /* 812500 baud: not supported. */
648 };
649
650 static const UNSIGNED baudrate_value[] =
651 {
652 0, /* Not supported. */
653 75,
654 150,
655 300,
656 600,
657 1200,
658 2400,
659 4800,
660 7200,
661 9600,
662 14400,
663 19200,
664 28800,
665 0, /* Not supported. */
666 38400,
667 57600,
668 115200,
669 0, /* Not supported. */
670 0, /* Not supported. */
671 0 /* Not supported. */
672 };
673
674 /*******************************************************************************
675 *
676 * get_bytes_in_rx_buffer
677 *
678 * Purpose : Gets the number of bytes in the RX buffer.
679 *
680 * Arguments: In : uart: Pointer on the UART structure.
681 * Out: none
682 *
683 * Returns : The number of bytes in the RX buffer.
684 *
685 ******************************************************************************/
686
687 static SYS_UWORD16
688 get_bytes_in_rx_buffer (t_uart *uart)
689 {
690 SYS_UWORD16 bytes_in_rx_buffer;
691 volatile SYS_UWORD8 *rx_in;
692
693 rx_in = uart->rx_in;
694
695 if (uart->rx_out <= rx_in)
696 bytes_in_rx_buffer = (SYS_UWORD16) (rx_in - uart->rx_out);
697 else
698 bytes_in_rx_buffer =
699 (SYS_UWORD16) (rx_in - uart->rx_out + uart->buffer_size + 1);
700
701 return (bytes_in_rx_buffer);
702 }
703
704 /*******************************************************************************
705 *
706 * get_bytes_in_tx_buffer
707 *
708 * Purpose : Gets the number of bytes in the TX buffer.
709 *
710 * Arguments: In : uart: Pointer on the UART structure.
711 * Out: none
712 *
713 * Returns : The number of bytes in the TX buffer.
714 *
715 ******************************************************************************/
716
717 static SYS_UWORD16
718 get_bytes_in_tx_buffer (t_uart *uart)
719 {
720 SYS_UWORD16 bytes_in_tx_buffer;
721 volatile SYS_UWORD8 *tx_out;
722
723 tx_out = uart->tx_out;
724
725 if (tx_out <= uart->tx_in)
726 bytes_in_tx_buffer = (SYS_UWORD16) (uart->tx_in - tx_out);
727 else
728 bytes_in_tx_buffer =
729 (SYS_UWORD16) (uart->tx_in - tx_out + uart->buffer_size + 1);
730
731 return (bytes_in_tx_buffer);
732 }
733
734 /*******************************************************************************
735 *
736 * compute_break_time
737 *
738 * Purpose : Computes a number of TDMA from 3 parameters:
739 * - baudrate,
740 * - bits per character including start bit, stop bits and parity,
741 * - number of characters.
742 * Due to the TDMA value (4.6 ms), a minimal value is sent: 2 TDMA.
743 *
744 * Arguments: In : baudrate
745 * bits_per_char
746 * number_of_chars
747 * Out: none
748 *
749 * Returns : The number of TDMA.
750 *
751 ******************************************************************************/
752
753 static UNSIGNED
754 compute_break_time (UNSIGNED baudrate,
755 UNSIGNED bits_per_char,
756 UNSIGNED number_of_chars)
757 {
758 UNSIGNED number_of_tdma;
759
760 number_of_tdma = CONVERT_TIME_IN_TDMA (
761 1000 * bits_per_char * number_of_chars / baudrate);
762
763 if (number_of_tdma == 0)
764 number_of_tdma = 1;
765
766 number_of_tdma++;
767
768 return (number_of_tdma);
769 }
770
771 /*******************************************************************************
772 *
773 * update_reading_callback
774 *
775 * Purpose : Updates the sizes array and the addresses array and get and builds
776 * the state parameter defined in UAF_GetLineState to call the
777 * readOutFunc function.
778 *
779 * Arguments: In : uart : Pointer on the UART structure.
780 * call_source: 0: LISR, 1: application.
781 * Out: none
782 *
783 * Returns : none
784 *
785 ******************************************************************************/
786
787 static void
788 update_reading_callback (t_uart *uart,
789 SYS_BOOL call_source)
790 {
791 SYS_UWORD32 state;
792 SYS_UWORD8 fragments_number;
793 SYS_UWORD16 bytes_in_rx_buffer;
794 volatile SYS_UWORD8 *rx_in;
795
796 /*
797 * Update the sizes array and the addresses array.
798 * A copy of rx_in is used because it may be updated by the interrupt
799 * handler if this function is called from the application.
800 */
801
802 rx_in = uart->rx_in;
803
804 if (uart->rx_out < rx_in) {
805
806 fragments_number = 1;
807
808 uart->rd_address[0] = uart->rx_out;
809 uart->rd_size_before_call[0] = (SYS_UWORD16) (rx_in - uart->rx_out);
810 uart->rd_size_after_call[0] = uart->rd_size_before_call[0];
811
812 uart->rd_size_before_call[1] = 0;
813 uart->rd_size_after_call[1] = 0;
814
815 bytes_in_rx_buffer = uart->rd_size_before_call[0];
816
817 } else if (rx_in == uart->rx_out) { /* RX buffer empty. */
818
819 fragments_number = 1;
820
821 uart->rd_address[0] = uart->rx_out;
822 uart->rd_size_before_call[0] = 0;
823 uart->rd_size_after_call[0] = 0;
824
825 uart->rd_size_before_call[1] = 0;
826 uart->rd_size_after_call[1] = 0;
827
828 bytes_in_rx_buffer = 0;
829
830 } else {
831
832 fragments_number = 2;
833
834 uart->rd_address[0] = uart->rx_out;
835 uart->rd_size_before_call[0] =
836 uart->buffer_size + 1 - (SYS_UWORD16) (uart->rx_out -
837 &(uart->rx_buffer[0]));
838 uart->rd_size_after_call[0] = uart->rd_size_before_call[0];
839
840 uart->rd_address[1] = &(uart->rx_buffer[0]);
841 uart->rd_size_before_call[1] = (SYS_UWORD16) (rx_in -
842 &(uart->rx_buffer[0]));
843 uart->rd_size_after_call[1] = uart->rd_size_before_call[1];
844
845 bytes_in_rx_buffer =
846 uart->rd_size_before_call[0] + uart->rd_size_before_call[1];
847
848 if (!uart->rd_size_before_call[1])
849 fragments_number = 1;
850 }
851
852 /*
853 * Build the state parameter defined in UAF_GetLineState.
854 * The field state_2 is used when state_1 is set to 0 to avoid to
855 * lose events detected in the RX interrupt handler.
856 */
857
858 state = uart->state_2;
859 uart->state_2 = 0;
860 uart->state = &(uart->state_2);
861
862 state |= uart->state_1;
863 uart->state_1 = 0;
864 uart->state = &(uart->state_1);
865
866 state |= ((((SYS_UWORD32) uart->cts_level) << RTS) |
867
868 (((SYS_UWORD32) (uart->tx_stopped_by_application |
869 uart->tx_stopped_by_driver)) << TXSTP) |
870
871 (((SYS_UWORD32) (uart->rx_stopped_by_application |
872 uart->rx_stopped_by_driver)) << RXSTP) |
873
874 (((SYS_UWORD32) (uart->buffer_size - bytes_in_rx_buffer)) << RXBLEV));
875
876 /*
877 * Fields SA, SB and X are set according to the flow control:
878 *
879 * None RTS/CTS XON/XOFF
880 * SA 0 (ns) 0 (ns) 0 (ns)
881 * SB RTS 0 RTS
882 * X 0 RTS XON:0 XOFF:1 (transmitter)
883 *
884 * ns: signal not supported.
885 * DTR/DSR flow control is not supported.
886 */
887
888 if (uart->flow_control_mode != fc_rts)
889 state |= (((SYS_UWORD32) uart->cts_level) << SB);
890
891 if (uart->flow_control_mode == fc_rts)
892 state |= (((SYS_UWORD32) uart->cts_level) << X);
893
894 else if ((uart->flow_control_mode == fc_xoff) &&
895 (uart->tx_stopped_by_application ||
896 uart->tx_stopped_by_driver))
897 state |= (1 << X);
898
899 /*
900 * Call the readOutFunc function with these parameters.
901 */
902
903 uart->rd_call_setup = rm_notDefined;
904
905 (*(uart->readOutFunc)) (call_source & 0x01, /* From HISR or application */
906 &(uart->rd_call_setup),
907 fragments_number,
908 &(uart->rd_address[0]),
909 &(uart->rd_size_after_call[0]),
910 state);
911 }
912
913 /*******************************************************************************
914 *
915 * update_writing_callback
916 *
917 * Purpose : Updates the sizes array and the addresses array to call the
918 * writeInFunc function.
919 *
920 * Arguments: In : uart : Pointer on the UART structure.
921 * call_source: 0: LISR, 1: application.
922 * Out: none
923 *
924 * Returns : none
925 *
926 ******************************************************************************/
927
928 static void
929 update_writing_callback (t_uart *uart,
930 SYS_BOOL call_source)
931 {
932 SYS_UWORD8 fragments_number;
933 volatile SYS_UWORD8 *tx_out;
934
935 /*
936 * Update the sizes array and the addresses array.
937 * A copy of tx_out is used because it may be updated by the interrupt
938 * handler if this function is called from the application.
939 */
940
941 tx_out = uart->tx_out;
942
943 if (uart->tx_in < tx_out) {
944
945 fragments_number = 1;
946
947 uart->wr_address[0] = uart->tx_in;
948 uart->wr_size_before_call[0] =
949 (SYS_UWORD16) (tx_out - uart->tx_in - 1);
950 uart->wr_size_after_call[0] = uart->wr_size_before_call[0];
951
952 uart->wr_size_before_call[1] = 0;
953 uart->wr_size_after_call[1] = 0;
954
955 } else if (tx_out == &(uart->tx_buffer[0])) {
956
957 fragments_number = 1;
958
959 uart->wr_address[0] = uart->tx_in;
960 uart->wr_size_before_call[0] =
961 uart->buffer_size -
962 (SYS_UWORD16) (uart->tx_in - &(uart->tx_buffer[0]));
963 uart->wr_size_after_call[0] = uart->wr_size_before_call[0];
964
965 uart->wr_size_before_call[1] = 0;
966 uart->wr_size_after_call[1] = 0;
967
968 } else {
969
970 fragments_number = 2;
971
972 uart->wr_address[0] = uart->tx_in;
973 uart->wr_size_before_call[0] =
974 uart->buffer_size + 1 -
975 (SYS_UWORD16) (uart->tx_in - &(uart->tx_buffer[0]));
976 uart->wr_size_after_call[0] = uart->wr_size_before_call[0];
977
978 uart->wr_address[1] = &(uart->tx_buffer[0]);
979 uart->wr_size_before_call[1] =
980 (SYS_UWORD16) (tx_out - &(uart->tx_buffer[0]) - 1);
981 uart->wr_size_after_call[1] = uart->wr_size_before_call[1];
982
983 if (!uart->wr_size_before_call[1])
984 fragments_number = 1;
985 }
986
987 /*
988 * Call the writeInFunc function with these parameters;
989 */
990
991 uart->wr_call_setup = rm_notDefined;
992
993 (*(uart->writeInFunc)) (call_source,
994 &(uart->wr_call_setup),
995 fragments_number,
996 &(uart->wr_address[0]),
997 &(uart->wr_size_after_call[0]));
998 }
999
1000 /*******************************************************************************
1001 *
1002 * stop_break
1003 *
1004 * Purpose : The timer is activated to expire when a time corresponding to the
1005 * sending time of 2 characters at least has elapsed. After a break,
1006 * no character may be sent during this period.
1007 *
1008 * Arguments: In : uartNo: Irda or Modem
1009 * Out: none
1010 *
1011 * Returns : none
1012 *
1013 ******************************************************************************/
1014
1015 static VOID
1016 stop_break (T_fd_UartId uartNo)
1017 {
1018 t_uart *uart;
1019
1020 uart = &(uart_parameters[uartNo]);
1021
1022 uart->break_to_send = 0;
1023 uart->break_in_progress = 0;
1024
1025 /*
1026 * Disable sleep mode then unmask Tx interrupt.
1027 */
1028
1029 WRITE_UART_REGISTER (
1030 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1031
1032 WRITE_UART_REGISTER (
1033 uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
1034 }
1035
1036 static VOID
1037 stop_break_entry_point_1(UNSIGNED id)
1038 {
1039 stop_break( UAF_UART_0 ); // uart Irda
1040 }
1041 static VOID
1042 stop_break_entry_point_2(UNSIGNED id)
1043 {
1044 stop_break( UAF_UART_1 ); // uart Modem
1045 }
1046
1047 /*******************************************************************************
1048 *
1049 * hisr_start_break
1050 *
1051 * Purpose : Enables the timer used to control the time without character.
1052 *
1053 * Arguments: In : none
1054 * Out: none
1055 *
1056 * Returns : none
1057 *
1058 ******************************************************************************/
1059 static VOID
1060 hisr_start_break (T_fd_UartId uartNo)
1061 {
1062 t_uart *uart;
1063
1064 uart = &(uart_parameters[uartNo]);
1065
1066 (void) NU_Control_Timer (&(uart->break_timer_ctrl_block),
1067 NU_DISABLE_TIMER);
1068
1069
1070 (void) NU_Reset_Timer (&(uart->break_timer_ctrl_block),
1071 stop_break_tab[uartNo],
1072 uart->time_without_character,
1073 0, /* The timer expires once. */
1074 NU_DISABLE_TIMER);
1075
1076 (void) NU_Control_Timer (&(uart->break_timer_ctrl_block),
1077 NU_ENABLE_TIMER);
1078 }
1079 static VOID
1080 hisr_start_break_entry_point_1( VOID )
1081 {
1082 hisr_start_break( UAF_UART_0 ); // uart Irda
1083 }
1084
1085 static VOID
1086 hisr_start_break_entry_point_2( VOID )
1087 {
1088 hisr_start_break( UAF_UART_1 ); // uart Modem
1089 }
1090
1091 /*******************************************************************************
1092 *
1093 * stop_receiver
1094 *
1095 * Purpose : Activates DTR or RTS or sends XOFF.
1096 *
1097 * Arguments: In : uart: Pointer on the UART structure.
1098 * Out: none
1099 *
1100 * Returns : none
1101 *
1102 ******************************************************************************/
1103
1104 static void
1105 stop_receiver (t_uart *uart)
1106 {
1107 /*
1108 * Disable sleep mode.
1109 */
1110
1111 WRITE_UART_REGISTER (
1112 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1113
1114 switch (uart->flow_control_mode) {
1115
1116 case fc_rts:
1117
1118 /*
1119 * CTS (RTS on UART side) is deactivated (high).
1120 */
1121
1122 WRITE_UART_REGISTER (
1123 uart, MCR, READ_UART_REGISTER (uart, MCR) & ~MRTS);
1124 break;
1125
1126 case fc_xoff:
1127
1128 uart->xon_xoff_to_send = uart->xoff_character;
1129 uart->send_xon_xoff = 1;
1130
1131 /*
1132 * Unmask Tx interrupt.
1133 */
1134
1135 WRITE_UART_REGISTER (
1136 uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
1137 break;
1138 }
1139 }
1140
1141 /*******************************************************************************
1142 *
1143 * start_receiver
1144 *
1145 * Purpose : Deactivates DTR or RTS or sends XON.
1146 *
1147 * Arguments: In : uart: Pointer on the UART structure.
1148 * Out: none
1149 *
1150 * Returns : none
1151 *
1152 ******************************************************************************/
1153
1154 static void
1155 start_receiver (t_uart *uart)
1156 {
1157 /*
1158 * Disable sleep mode.
1159 */
1160
1161 WRITE_UART_REGISTER (
1162 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1163
1164 switch (uart->flow_control_mode) {
1165
1166 case fc_rts:
1167
1168 /*
1169 * CTS (RTS on UART side) is activated (low).
1170 */
1171
1172 WRITE_UART_REGISTER (
1173 uart, MCR, READ_UART_REGISTER (uart, MCR) | MRTS);
1174 break;
1175
1176 case fc_xoff:
1177
1178 uart->xon_xoff_to_send = uart->xon_character;
1179 uart->send_xon_xoff = 1;
1180
1181 /*
1182 * Unmask Tx interrupt.
1183 */
1184
1185 WRITE_UART_REGISTER (
1186 uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
1187 break;
1188 }
1189 }
1190
1191 /*******************************************************************************
1192 *
1193 * add_esc_seq_char_in_rx_buffer
1194 *
1195 * Purpose : Writes one escape sequence character in the RX buffer.
1196 *
1197 * Arguments: In : uart: Pointer on the UART structure.
1198 * Out: none
1199 *
1200 * Returns : none
1201 *
1202 ******************************************************************************/
1203
1204 static void
1205 add_esc_seq_char_in_rx_buffer (t_uart *uart)
1206 {
1207 /*
1208 * IF the RX buffer is not full, write an escape sequence character in the
1209 * RX buffer and check wrap-around.
1210 */
1211
1212 if (!RX_BUFFER_FULL (uart)) {
1213
1214 *(uart->rx_in++) = uart->esc_seq_character;
1215
1216 if (uart->rx_in == &(uart->rx_buffer[0]) + uart->buffer_size + 1)
1217 uart->rx_in = &(uart->rx_buffer[0]);
1218 }
1219 }
1220
1221 /*******************************************************************************
1222 *
1223 * analyze_guard_period_timer_expiration
1224 *
1225 * Purpose : According to the state of the escape sequence detection, 1 or 2
1226 * escape sequence characters may be written into the TX buffer or
1227 * the escape sequence is declared as detected.
1228 * If 1 or 2 escape sequence characters have been detected the
1229 * guard period must not expire.
1230 * If 3 characters have been detected the escape sequence must
1231 * expire.
1232 *
1233 * Arguments: In : id: parameter not used.
1234 * Out: none
1235 *
1236 * Returns : none
1237 *
1238 ******************************************************************************/
1239
1240 static VOID
1241 analyze_guard_period_timer_expiration (T_fd_UartId uartNo)
1242 {
1243 t_uart *uart;
1244 SYS_UWORD16 bytes_in_rx_buffer;
1245
1246 uart = &(uart_parameters[uartNo]);
1247
1248 switch (uart->esc_seq_detection_state) {
1249
1250 case ONE_CHAR_DETECTED:
1251
1252 /*
1253 * 1 escape sequence character has been detected. The guard period has
1254 * ellapsed. This character is written into the TX buffer.
1255 */
1256
1257 add_esc_seq_char_in_rx_buffer (uart);
1258 break;
1259
1260 case TWO_CHARS_DETECTED:
1261
1262 /*
1263 * 2 escape sequence characters have been detected. The guard period has
1264 * ellapsed. These characters are written into the TX buffer.
1265 */
1266
1267 add_esc_seq_char_in_rx_buffer (uart);
1268 add_esc_seq_char_in_rx_buffer (uart);
1269
1270 break;
1271
1272 case THREE_CHARS_DETECTED:
1273
1274 /*
1275 * 3 escape sequence characters have been detected and the guard period
1276 * has ellapsed. The escape sequence is detected.
1277 */
1278
1279 uart->esc_seq_received = 1;
1280 *(uart->state) |= (1 << ESC);
1281
1282 break;
1283 }
1284
1285 uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE;
1286
1287 /*
1288 * If the high watermark is reached, RTS is activated or XOFF is sent
1289 * according to the flow control mode.
1290 */
1291
1292 bytes_in_rx_buffer = get_bytes_in_rx_buffer (uart);
1293
1294 if ((uart->flow_control_mode != fc_none) &&
1295 (bytes_in_rx_buffer >= RX_HIGH_WATERMARK (uart->buffer_size))) {
1296
1297 /*
1298 * Check if receipt must be stopped.
1299 */
1300
1301 if (!uart->rx_stopped_by_driver) {
1302
1303 uart->rx_stopped_by_driver = 1;
1304 if (!uart->rx_stopped_by_application)
1305 stop_receiver (uart);
1306 }
1307 }
1308
1309 /*
1310 * If a reading was suspended or if the callback function is installed,
1311 * it is called if one of these conditions is fulfiled:
1312 * - the RX threshold level is reached,
1313 * - a break has been detected,
1314 * - an escape sequence has been detected,
1315 */
1316
1317 if ((!uart->rd_call_from_hisr_in_progress) &&
1318 (uart->reading_suspended ||
1319 (uart->rd_call_setup == rm_reInstall))) {
1320
1321 if ((bytes_in_rx_buffer >= uart->rx_threshold_level) ||
1322 uart->break_received ||
1323 uart->esc_seq_received) {
1324
1325 uart->rd_call_from_hisr_in_progress = 1;
1326 update_reading_callback (uart, 1); /* 1: call from HISR. */
1327
1328 uart->reading_suspended = 0;
1329 uart->break_received = 0;
1330 uart->esc_seq_received = 0;
1331 }
1332 }
1333 }
1334 static VOID
1335 analyze_guard_period_timer_expiration_entry_1(UNSIGNED id)
1336 {
1337 analyze_guard_period_timer_expiration( UAF_UART_0 ); // uart Irda
1338 }
1339
1340 static VOID
1341 analyze_guard_period_timer_expiration_entry_2(UNSIGNED id)
1342 {
1343 analyze_guard_period_timer_expiration( UAF_UART_1 ); // uart Modem
1344 }
1345
1346 /*******************************************************************************
1347 *
1348 * stop_guard_period_timer
1349 *
1350 * Purpose : Stops the timer used to detect the guard period expiration.
1351 *
1352 * Arguments: In : uart: Pointer on the UART structure.
1353 * Out: none
1354 *
1355 * Returns : none
1356 *
1357 ******************************************************************************/
1358
1359 static void
1360 stop_guard_period_timer (t_uart *uart)
1361 {
1362 (void) NU_Control_Timer (&(uart->guard_period_timer_ctrl_block),
1363 NU_DISABLE_TIMER);
1364 }
1365
1366 /*******************************************************************************
1367 *
1368 * start_guard_period_timer
1369 *
1370 * Purpose : Starts a timer which expires if the guard period has ellapsed.
1371 *
1372 * Arguments: In : uart: Pointer on the UART structure.
1373 * Out: none
1374 *
1375 * Returns : none
1376 *
1377 ******************************************************************************/
1378
1379 static void
1380 start_guard_period_timer (T_fd_UartId uartNo)
1381 {
1382 t_uart *uart;
1383
1384 uart = &(uart_parameters[uartNo]);
1385
1386 (void) NU_Control_Timer (&(uart->guard_period_timer_ctrl_block),
1387 NU_DISABLE_TIMER);
1388
1389 (void) NU_Reset_Timer (&(uart->guard_period_timer_ctrl_block),
1390 analyze_guard_period_timer_expiration_tab[uartNo],
1391 uart->guard_period,
1392 0, /* The timer expires once. */
1393 NU_DISABLE_TIMER);
1394
1395 (void) NU_Control_Timer (&(uart->guard_period_timer_ctrl_block),
1396 NU_ENABLE_TIMER);
1397 }
1398
1399 /*******************************************************************************
1400 *
1401 * detect_escape_sequence
1402 *
1403 * Purpose : The state machine used to detect an escape sequence is updated
1404 * according to the array of bytes to analyse. If the state machine
1405 * goes to the initial state due to a break in the sequence
1406 * detection, the previous characters are put into the RX buffer.
1407 *
1408 * Arguments: In : uart: Pointer on the UART structure.
1409 * Out: none
1410 *
1411 * Returns : 0: Break in detection or a sequence has been detected.
1412 * 1: A sequence may be detected.
1413 *
1414 ******************************************************************************/
1415
1416 static int
1417 detect_escape_sequence (T_fd_UartId uartNo)
1418 {
1419 t_uart *uart;
1420 int detection_result;
1421 SYS_UWORD8 *rx_fifo_byte;
1422 SYS_UWORD16 bytes_in_rx_buffer;
1423 UNSIGNED elapsed_time;
1424
1425 uart = &(uart_parameters[uartNo]);
1426 detection_result = 0;
1427
1428 rx_fifo_byte = uart->rx_buffer_used_by_rx_hisr;
1429 if (rx_fifo_byte == &(uart->rx_fifo_byte_1[0]))
1430 bytes_in_rx_buffer = uart->bytes_in_rx_buffer_1;
1431 else
1432 bytes_in_rx_buffer = uart->bytes_in_rx_buffer_2;
1433
1434 if (uart->current_time > uart->previous_time)
1435 elapsed_time = uart->current_time - uart->previous_time;
1436 else
1437 elapsed_time =
1438 MAX_UNSIGNED_32 - uart->previous_time + uart->current_time;
1439
1440 switch (uart->esc_seq_detection_state) {
1441
1442 case INITIALIZATION:
1443
1444 /*
1445 * It is the first character received. It may be the first character
1446 * of an escape sequence. The elapsed_time variable is set to the
1447 * guard period value to consider this character as the first character
1448 * of an escape sequence.
1449 */
1450
1451 if (!uart->esc_seq_modified) {
1452
1453 elapsed_time = uart->guard_period;
1454 uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE;
1455 }
1456
1457 /* No break! */
1458
1459 case NO_ESCAPE_SEQUENCE:
1460
1461 /*
1462 * To go to the next state (one, two or three characters detected):
1463 * - a guard period must have elapsed since the last receipt,
1464 * - the characters must belong to the escape sequence.
1465 */
1466
1467 if ((elapsed_time >= uart->guard_period) &&
1468 (!uart->esc_seq_modified)) {
1469
1470 switch (bytes_in_rx_buffer) {
1471
1472 case 1:
1473
1474 if (*rx_fifo_byte++ == uart->esc_seq_character) {
1475
1476 uart->esc_seq_detection_state = ONE_CHAR_DETECTED;
1477 start_guard_period_timer(uartNo);
1478 detection_result = 1;
1479 }
1480
1481 break;
1482
1483 case 2:
1484
1485 if ((*rx_fifo_byte++ == uart->esc_seq_character) &&
1486 (*rx_fifo_byte++ == uart->esc_seq_character)) {
1487
1488 uart->esc_seq_detection_state = TWO_CHARS_DETECTED;
1489 start_guard_period_timer (uartNo);
1490 detection_result = 1;
1491 }
1492
1493 break;
1494
1495 case 3:
1496
1497 if ((*rx_fifo_byte++ == uart->esc_seq_character) &&
1498 (*rx_fifo_byte++ == uart->esc_seq_character) &&
1499 (*rx_fifo_byte++ == uart->esc_seq_character)) {
1500
1501 uart->esc_seq_detection_state = THREE_CHARS_DETECTED;
1502 start_guard_period_timer (uartNo);
1503 detection_result = 1;
1504 }
1505
1506 break;
1507
1508 default:
1509
1510 /*
1511 * No action.
1512 */
1513
1514 break;
1515 }
1516 }
1517
1518 uart->previous_time = uart->current_time;
1519
1520 break;
1521
1522 case ONE_CHAR_DETECTED:
1523
1524 /*
1525 * To go to the next state (two or three characters detected):
1526 * - the difference between the current time and the previous time
1527 * must be less than the guard period,
1528 * - the characters must belong to the escape sequence.
1529 * Otherwise, an escape sequence character is written in the RX buffer.
1530 */
1531
1532 if (!uart->esc_seq_modified) {
1533
1534 switch (bytes_in_rx_buffer) {
1535
1536 case 1:
1537
1538 if (*rx_fifo_byte++ == uart->esc_seq_character) {
1539
1540 uart->esc_seq_detection_state = TWO_CHARS_DETECTED;
1541 detection_result = 1;
1542 }
1543
1544 break;
1545
1546 case 2:
1547
1548 if ((*rx_fifo_byte++ == uart->esc_seq_character) &&
1549 (*rx_fifo_byte++ == uart->esc_seq_character)) {
1550
1551 start_guard_period_timer (uartNo); /* Reset the timer. */
1552
1553 uart->esc_seq_detection_state = THREE_CHARS_DETECTED;
1554 detection_result = 1;
1555 }
1556
1557 break;
1558
1559 default:
1560
1561 /*
1562 * No action.
1563 */
1564
1565 break;
1566 }
1567 }
1568
1569 if (!detection_result) {
1570
1571 add_esc_seq_char_in_rx_buffer (uart);
1572
1573 uart->previous_time = uart->current_time;
1574 uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE;
1575 }
1576
1577 break;
1578
1579 case TWO_CHARS_DETECTED:
1580
1581 /*
1582 * To go to the next state (three chars detected):
1583 * - the difference between the current time and the previous time
1584 * must be less than the guard period,
1585 * - the character must belong to the escape sequence.
1586 * Otherwise, 2 escape sequence characters are written in the RX buffer.
1587 */
1588
1589 if (!uart->esc_seq_modified) {
1590
1591 switch (bytes_in_rx_buffer) {
1592
1593 case 1:
1594
1595 if (*rx_fifo_byte++ == uart->esc_seq_character) {
1596
1597 start_guard_period_timer (uartNo); /* Reset the timer. */
1598
1599 uart->esc_seq_detection_state = THREE_CHARS_DETECTED;
1600 detection_result = 1;
1601 }
1602
1603 break;
1604
1605 default:
1606
1607 /*
1608 * No action.
1609 */
1610
1611 break;
1612 }
1613 }
1614
1615 if (!detection_result) {
1616
1617 add_esc_seq_char_in_rx_buffer (uart);
1618 add_esc_seq_char_in_rx_buffer (uart);
1619
1620 uart->previous_time = uart->current_time;
1621 uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE;
1622 }
1623
1624 break;
1625
1626 case THREE_CHARS_DETECTED:
1627
1628 /*
1629 * An escape sequence is detected if a guard period has elapsed since
1630 * the last receipt. Otherwise, 3 escape sequence characters are
1631 * written in the RX buffer.
1632 */
1633
1634 stop_guard_period_timer (uart);
1635
1636 add_esc_seq_char_in_rx_buffer (uart);
1637 add_esc_seq_char_in_rx_buffer (uart);
1638 add_esc_seq_char_in_rx_buffer (uart);
1639
1640 uart->previous_time = uart->current_time;
1641 uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE;
1642
1643 break;
1644 }
1645
1646 return (detection_result);
1647 }
1648
1649 /*******************************************************************************
1650 *
1651 * send_break
1652 *
1653 * Purpose : This function may only called if the TX FIFO is empty.
1654 * Null characters are written in the TX FIFO. The number of bytes to
1655 * write has been defined with UAF_SetLineState. Enables the break
1656 * condition.
1657 *
1658 * Arguments: In : uart: Pointer on the UART structure.
1659 * Out: none
1660 *
1661 * Returns : Number of bytes sent.
1662 *
1663 ******************************************************************************/
1664
1665 static SYS_UWORD16
1666 send_break (t_uart *uart)
1667 {
1668 SYS_UWORD16 bytes_in_tx_fifo;
1669
1670 bytes_in_tx_fifo = 0;
1671 uart->break_in_progress = 1;
1672
1673 /*
1674 * Disable sleep mode.
1675 */
1676
1677 WRITE_UART_REGISTER (
1678 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1679
1680 WRITE_UART_REGISTER (
1681 uart, LCR, READ_UART_REGISTER (uart, LCR) | BREAK_CONTROL);
1682
1683 /*
1684 * Re-enable sleep mode.
1685 */
1686
1687 WRITE_UART_REGISTER (
1688 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
1689
1690 while (uart->break_length) {
1691
1692 WRITE_UART_REGISTER (uart, THR, 0x00);
1693 uart->break_length--;
1694 bytes_in_tx_fifo++;
1695 }
1696
1697 return (bytes_in_tx_fifo);
1698 }
1699
1700 /*******************************************************************************
1701 *
1702 * build_rx_fifo_array
1703 *
1704 * Purpose : Reads the RX FIFO to build an array with bytes read.
1705 * A byte is written in this array if no error is detected.
1706 *
1707 * Arguments: In : uart: Pointer on the UART structure.
1708 * Out: none
1709 *
1710 * Returns : The number of bytes in RX FIFO.
1711 *
1712 ******************************************************************************/
1713
1714 static SYS_UWORD16
1715 build_rx_fifo_array (t_uart *uart)
1716 {
1717 SYS_UWORD8 status;
1718 SYS_UWORD8 *first_byte;
1719 SYS_UWORD8 *current_byte;
1720 SYS_UWORD16 *bytes_in_rx_buffer;
1721 SYS_UWORD16 bytes_received;
1722
1723 bytes_received = 0;
1724
1725 /*
1726 * Switch to the other buffer.
1727 */
1728
1729 first_byte = uart->rx_buffer_used_by_rx_lisr;
1730 if (first_byte == &(uart->rx_fifo_byte_1[0])) {
1731
1732 first_byte = &(uart->rx_fifo_byte_2[0]);
1733 bytes_in_rx_buffer = &(uart->bytes_in_rx_buffer_2);
1734
1735 } else {
1736
1737 first_byte = &(uart->rx_fifo_byte_1[0]);
1738 bytes_in_rx_buffer = &(uart->bytes_in_rx_buffer_1);
1739 }
1740
1741 current_byte = first_byte;
1742 uart->rx_buffer_used_by_rx_lisr = first_byte;
1743
1744 status = READ_UART_REGISTER (uart, LSR);
1745
1746 /*
1747 * Build an array with the bytes contained in the RX FIFO.
1748 */
1749
1750 while (status & DR) { /* While RX FIFO is not empty... */
1751
1752 *current_byte = READ_UART_REGISTER (uart, RHR);
1753
1754 /*
1755 * Check if a parity error or a framing error is associated with the
1756 * received data. If there is an error the byte is not copied into the
1757 * bytes array.
1758 */
1759
1760 if (status & BYTE_ERROR) {
1761
1762 if (status & OE)
1763 uart->overrun_error++;
1764
1765 if (status & PE)
1766 uart->parity_error++;
1767
1768 if (status & FE)
1769 uart->framing_error++;
1770
1771 /*
1772 * Check break detection.
1773 */
1774
1775 if (status & BI) {
1776
1777 uart->break_received = 1;
1778 *(uart->state) |=
1779 ((1 << BRK) | (MINIMAL_BREAK_LENGTH << BRKLEN));
1780 }
1781
1782 } else
1783 current_byte++;
1784
1785 status = READ_UART_REGISTER (uart, LSR);
1786 }
1787
1788 bytes_received = (SYS_UWORD16) (current_byte - first_byte);
1789 *bytes_in_rx_buffer = bytes_received;
1790
1791 /*
1792 * Re-switch to the other buffer if no valid character has been received.
1793 */
1794
1795 if (!bytes_received) {
1796
1797 if (uart->rx_buffer_used_by_rx_lisr == &(uart->rx_fifo_byte_1[0]))
1798 uart->rx_buffer_used_by_rx_lisr = &(uart->rx_fifo_byte_2[0]);
1799
1800 else
1801 uart->rx_buffer_used_by_rx_lisr = &(uart->rx_fifo_byte_1[0]);
1802 }
1803
1804 if (bytes_received > uart->max_rx_fifo_level)
1805 uart->max_rx_fifo_level = bytes_received;
1806
1807 return (bytes_received);
1808 }
1809
1810 /*******************************************************************************
1811 *
1812 * empty_rx_fifo
1813 *
1814 * Purpose : Read the RX FIFO.
1815 *
1816 * Arguments: In : uart: Pointer on the UART structure.
1817 * Out: none
1818 *
1819 * Returns : none
1820 *
1821 ******************************************************************************/
1822
1823 static void
1824 empty_rx_fifo (t_uart *uart)
1825 {
1826 SYS_UWORD16 bytes_in_rx_fifo;
1827 volatile SYS_UWORD8 dummy_byte;
1828
1829 bytes_in_rx_fifo = 0;
1830
1831 while (READ_UART_REGISTER (uart, LSR) & DR) {
1832
1833 dummy_byte = READ_UART_REGISTER (uart, RHR);
1834 bytes_in_rx_fifo++;
1835 }
1836
1837 if (bytes_in_rx_fifo > uart->max_rx_fifo_level)
1838 uart->max_rx_fifo_level = bytes_in_rx_fifo;
1839 }
1840
1841 /*******************************************************************************
1842 *
1843 * hisr_execute_rx_operations
1844 *
1845 * Purpose : If an escape sequence is detected or if a break in the detection
1846 * has occured RX FIFO bytes are written in the RX buffer.
1847 * If the software flow control is used bytes are analyzed to know
1848 * if a XON or a XOFF character is received to stop or start the
1849 * transmitter.
1850 * If a flow control is used and if the high watermark of the RX
1851 * buffer is reached the receiver is stopped.
1852 * If the RX threshold level is reached the callback mechanism is
1853 * activated.
1854 *
1855 * Arguments: In : none
1856 * Out: none
1857 *
1858 * Returns : none
1859 *
1860 ******************************************************************************/
1861 static VOID
1862 hisr_execute_rx_operations ( T_fd_UartId uartNo )
1863 {
1864 SYS_UWORD16 bytes_free_in_rx_buffer;
1865 SYS_UWORD16 wrap_around_counter;
1866 SYS_UWORD16 bytes_in_rx_buffer;
1867 SYS_UWORD16 bytes_read;
1868 SYS_UWORD8 *current_byte;
1869 SYS_UWORD8 xon_xoff_detected;
1870 t_uart *uart;
1871
1872 xon_xoff_detected = 0;
1873
1874 uart = &(uart_parameters[uartNo]);
1875
1876 /*
1877 * Switch to the other buffer.
1878 */
1879
1880 current_byte = uart->rx_buffer_used_by_rx_hisr;
1881 if (current_byte == &(uart->rx_fifo_byte_1[0])) {
1882
1883 current_byte = &(uart->rx_fifo_byte_2[0]);
1884 bytes_read = uart->bytes_in_rx_buffer_2;
1885
1886 } else {
1887
1888 current_byte = &(uart->rx_fifo_byte_1[0]);
1889 bytes_read = uart->bytes_in_rx_buffer_1;
1890 }
1891
1892 uart->rx_buffer_used_by_rx_hisr = current_byte;
1893
1894 /*
1895 * All bytes are copied into the RX buffer only if an escape sequence has
1896 * been detected or a break in the detection has occured.
1897 */
1898
1899 if (!detect_escape_sequence (uartNo)) {
1900
1901 if (uart->rx_out > uart->rx_in)
1902 bytes_free_in_rx_buffer = (SYS_UWORD16) (uart->rx_out - uart->rx_in - 1);
1903 else
1904 bytes_free_in_rx_buffer =
1905 (SYS_UWORD16) (uart->buffer_size + uart->rx_out - uart->rx_in);
1906
1907 wrap_around_counter = uart->buffer_size + 1 -
1908 (SYS_UWORD16) (uart->rx_in - &(uart->rx_buffer[0]));
1909
1910 if (uart->flow_control_mode == fc_xoff) {
1911
1912 while (bytes_read && bytes_free_in_rx_buffer) {
1913
1914 /*
1915 * If the data received is XON or XOFF, the transmitter is
1916 * enabled (XON) or disabled (XOFF).
1917 */
1918
1919 if (*current_byte == uart->xoff_character) {
1920
1921 uart->tx_stopped_by_driver = 1;
1922 xon_xoff_detected = 1;
1923
1924 } else if (*current_byte == uart->xon_character) {
1925
1926 uart->tx_stopped_by_driver = 0;
1927 xon_xoff_detected = 1;
1928
1929 /*
1930 * Disable sleep mode then unmask Tx interrupt.
1931 */
1932
1933 WRITE_UART_REGISTER (
1934 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
1935
1936 WRITE_UART_REGISTER (
1937 uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
1938
1939 } else {
1940
1941 *(uart->rx_in++) = *current_byte;
1942
1943 wrap_around_counter--;
1944 if (!wrap_around_counter) {
1945
1946 uart->rx_in = &(uart->rx_buffer[0]);
1947 wrap_around_counter = uart->buffer_size + 1;
1948 }
1949
1950 bytes_free_in_rx_buffer--;
1951 }
1952
1953 current_byte++;
1954 bytes_read--;
1955 }
1956
1957 } else {
1958
1959 while (bytes_read && bytes_free_in_rx_buffer) {
1960
1961 *(uart->rx_in++) = *current_byte++;
1962
1963 wrap_around_counter--;
1964 if (!wrap_around_counter) {
1965
1966 uart->rx_in = &(uart->rx_buffer[0]);
1967 wrap_around_counter = uart->buffer_size;
1968 }
1969
1970 bytes_free_in_rx_buffer--;
1971 bytes_read--;
1972 }
1973 }
1974
1975 /*
1976 * If the high watermark is reached, RTS is activated or XOFF is
1977 * sent according to the flow control mode.
1978 */
1979
1980 bytes_in_rx_buffer = get_bytes_in_rx_buffer (uart);
1981
1982 if ((uart->flow_control_mode != fc_none) &&
1983 (bytes_in_rx_buffer >= RX_HIGH_WATERMARK (uart->buffer_size))) {
1984
1985 /*
1986 * Check if receipt must be stopped.
1987 */
1988
1989 if (!uart->rx_stopped_by_driver) {
1990
1991 uart->rx_stopped_by_driver = 1;
1992 if (!uart->rx_stopped_by_application)
1993 stop_receiver (uart);
1994 }
1995 }
1996
1997 /*
1998 * If a reading was suspended or if the callback function is installed,
1999 * it is called if one of these conditions is fulfiled:
2000 * - the RX threshold level is reached,
2001 * - a break has been detected,
2002 */
2003
2004 if ((!uart->rd_call_from_hisr_in_progress) &&
2005 (uart->reading_suspended ||
2006 (uart->rd_call_setup == rm_reInstall))) {
2007
2008 if ((bytes_in_rx_buffer >= uart->rx_threshold_level) ||
2009 uart->break_received ||
2010 xon_xoff_detected) {
2011
2012 uart->rd_call_from_hisr_in_progress = 1;
2013 update_reading_callback (uart, 3); /* 3: call from Rx HISR. */
2014
2015 uart->reading_suspended = 0;
2016 uart->break_received = 0;
2017 uart->esc_seq_received = 0;
2018 }
2019 }
2020 }
2021 }
2022
2023 static VOID
2024 hisr_execute_rx_entry_point_1 ( VOID )
2025 {
2026 hisr_execute_rx_operations( UAF_UART_0 ); //uart Irda
2027 }
2028 static VOID
2029 hisr_execute_rx_entry_point_2 ( VOID )
2030 {
2031 hisr_execute_rx_operations( UAF_UART_1 ); //uart Modem
2032 }
2033
2034 /*******************************************************************************
2035 *
2036 * hisr_execute_v24_operations
2037 *
2038 * Purpose : The user's function is called if all conditions to call it are
2039 * fulfiled.
2040 *
2041 * Arguments: In : none
2042 * Out: none
2043 *
2044 * Returns : none
2045 *
2046 ******************************************************************************/
2047 static VOID
2048 hisr_execute_v24_operations (T_fd_UartId uartNo)
2049 {
2050 t_uart *uart;
2051
2052 uart = &(uart_parameters[uartNo]);
2053
2054 /*
2055 * If a reading was suspended or if the callback function is installed,
2056 * it is called.
2057 */
2058
2059 if ((!DRIVER_DISABLED (uart)) &&
2060 (!uart->rd_call_from_hisr_in_progress) &&
2061 (uart->reading_suspended || (uart->rd_call_setup == rm_reInstall))) {
2062
2063 uart->rd_call_from_hisr_in_progress = 1;
2064 update_reading_callback (uart, 1); /* 1: call from HISR. */
2065
2066 uart->reading_suspended = 0;
2067 uart->break_received = 0;
2068 uart->esc_seq_received = 0;
2069 }
2070 }
2071
2072 static VOID
2073 hisr_execute_v24_entry_point_1( VOID )
2074 {
2075 hisr_execute_v24_operations( UAF_UART_0 ); // uart Irda
2076 }
2077
2078 static VOID
2079 hisr_execute_v24_entry_point_2( VOID )
2080 {
2081 hisr_execute_v24_operations( UAF_UART_1 ); // uart Modem
2082 }
2083
2084
2085 /*******************************************************************************
2086 *
2087 * hisr_execute_tx_operations
2088 *
2089 * Purpose : Writes bytes from the TX buffer to the TX FIFO.
2090 * The user's function is called if all conditions to call it are
2091 * fulfiled.
2092 *
2093 * Arguments: In : none
2094 * Out: none
2095 *
2096 * Returns : none
2097 *
2098 ******************************************************************************/
2099 static VOID
2100 hisr_execute_tx_operations (T_fd_UartId uartNo)
2101 {
2102 SYS_UWORD16 bytes_in_tx_buffer;
2103 SYS_UWORD16 bytes_in_tx_fifo;
2104 SYS_UWORD16 wrap_around_counter;
2105 t_uart *uart;
2106
2107 uart = &(uart_parameters[uartNo]);
2108
2109 /*
2110 * A TX interrupt may have occured during the previous TX HISR. This case
2111 * may appear when a HISR having a higher priority has been activated when
2112 * the TX HISR was activated. When the next TX HISR is activated, the TX
2113 * FIFO may not be empty. Nothing is done until a TX interrupt will occur.
2114 * The RX HISR will be activated again and the TX FIFO will be empty.
2115 */
2116
2117 if (READ_UART_REGISTER (uart, LSR) & THRE) {
2118
2119 bytes_in_tx_fifo = 0;
2120
2121 /*
2122 * A request to send a XON/XOFF character may have been done by the
2123 * RX interrupt handler. The byte can be written because we are sure
2124 * that the TX FIFO is not full.
2125 */
2126
2127 if (uart->send_xon_xoff) {
2128
2129 WRITE_UART_REGISTER (uart, THR, uart->xon_xoff_to_send);
2130 uart->send_xon_xoff = 0;
2131 bytes_in_tx_fifo++;
2132 }
2133
2134 if ((!uart->tx_stopped_by_application) &&
2135 (!uart->tx_stopped_by_driver)) {
2136
2137 bytes_in_tx_buffer = get_bytes_in_tx_buffer (uart);
2138 wrap_around_counter =
2139 uart->buffer_size + 1 - (SYS_UWORD16) (uart->tx_out -
2140 &(uart->tx_buffer[0]));
2141
2142 /*
2143 * Loading of only (FIFO_SIZE - 1) characters in the Tx FIFO to
2144 * avoid the generation of a spurious Tx FIFO almost empty
2145 * interrupt (Ulysse bug report #35), instead of checking SSR[0].
2146 * In normal mode for THR interrupt (i.e. use of trigger level)
2147 * must only load (FIFO_SIZE - Trigger_Level - 1)
2148 */
2149
2150 while (bytes_in_tx_buffer &&
2151 //!(READ_UART_REGISTER (uart, SSR) & TX_FIFO_FULL)) {
2152 (bytes_in_tx_fifo < FIFO_SIZE)) {
2153
2154 WRITE_UART_REGISTER (uart, THR, *(uart->tx_out++));
2155 bytes_in_tx_buffer--;
2156 bytes_in_tx_fifo++;
2157
2158 wrap_around_counter--;
2159 if (!wrap_around_counter) {
2160
2161 uart->tx_out = &(uart->tx_buffer[0]);
2162 wrap_around_counter = uart->buffer_size + 1;
2163 }
2164 }
2165
2166 /*
2167 * If a writing was suspended or if the callback function is
2168 * installed, it is called if the TX threshold level is reached.
2169 */
2170
2171 if ((!DRIVER_DISABLED (uart)) &&
2172 (!uart->wr_call_from_hisr_in_progress) &&
2173 (bytes_in_tx_buffer <= uart->tx_threshold_level) &&
2174 ((uart->wr_call_setup == rm_reInstall) ||
2175 uart->writing_suspended)) {
2176
2177 uart->writing_suspended = 0;
2178
2179 uart->wr_call_from_hisr_in_progress = 1;
2180 update_writing_callback (uart, 1); /* 1: call from HISR. */
2181 }
2182 }
2183
2184 if (bytes_in_tx_fifo)
2185
2186 /*
2187 * Unmask Tx interrupt.
2188 */
2189
2190 WRITE_UART_REGISTER (
2191 uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
2192
2193 if ((!bytes_in_tx_fifo) && (uart->break_to_send))
2194 bytes_in_tx_fifo = send_break (uart);
2195
2196 /*
2197 * Re-enable the sleep mode.
2198 */
2199
2200 WRITE_UART_REGISTER (
2201 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
2202
2203 }
2204 }
2205
2206
2207 static VOID
2208 hisr_execute_tx_entry_point_1 ( VOID )
2209 {
2210 hisr_execute_tx_operations( UAF_UART_0 ); //uart Irda
2211 }
2212
2213 static VOID
2214 hisr_execute_tx_entry_point_2 ( VOID )
2215 {
2216 hisr_execute_tx_operations( UAF_UART_1 ); //uart Modem
2217 }
2218
2219 /*******************************************************************************
2220 *
2221 * read_rx_fifo
2222 *
2223 * Purpose : Reads the RX FIFO. If the driver is enabled bytes are written in
2224 * an array to be analyzed by the RX HISR.
2225 *
2226 * Arguments: In : uart: Pointer on the UART structure.
2227 * Out: none
2228 *
2229 * Returns : none
2230 *
2231 ******************************************************************************/
2232
2233 static void
2234 read_rx_fifo (t_uart *uart)
2235 {
2236
2237 /*
2238 * If the driver is disabled the RX FIFO is read to acknoledge the
2239 * interrupt else bytes received are written into an array which will be
2240 * analyzed from the RX HISR.
2241 */
2242 if (DRIVER_DISABLED (uart))
2243 empty_rx_fifo (uart);
2244 #if (BOARD == 31)
2245 else if ((*((volatile SYS_UWORD16 *) ARMIO_IN) & 0x0100) == 0x0000)
2246 empty_rx_fifo (uart);
2247 #endif
2248 else if (build_rx_fifo_array (uart))
2249 (void) NU_Activate_HISR (&(uart->rx_hisr_ctrl_block));
2250 }
2251
2252 /*******************************************************************************
2253 *
2254 * check_v24_input_lines
2255 *
2256 * Purpose : Check the V.24 input lines. According to the states of the input
2257 * lines and to the flow control mode selected, the transmitter is
2258 * enabled or disabled. The reading callback function is called if
2259 * it is installed and if all conditions are fulfiled.
2260 *
2261 * Arguments: In : uart: Pointer on the UART structure.
2262 * Out: none
2263 *
2264 * Returns : none
2265 *
2266 ******************************************************************************/
2267
2268 static void
2269 check_v24_input_lines (t_uart *uart)
2270 {
2271 SYS_BOOL v24_input_line_changed;
2272 volatile SYS_UWORD8 modem_status;
2273
2274 modem_status = READ_UART_REGISTER (uart, MSR);
2275 v24_input_line_changed = 0;
2276
2277 if (modem_status & DELTA_CTS) {
2278
2279 v24_input_line_changed = 1;
2280
2281 if (modem_status & MCTS)
2282 uart->cts_level = 0;
2283 else
2284 uart->cts_level = 1;
2285 }
2286
2287 /*
2288 * When the hardware flow control is selected, if the RS 232 input signal is
2289 * deactivated (low), the transmitter is stopped.
2290 */
2291
2292 if (uart->flow_control_mode == fc_rts) {
2293
2294 if (uart->cts_level)
2295 uart->tx_stopped_by_driver = 1;
2296
2297 else {
2298
2299 uart->tx_stopped_by_driver = 0;
2300
2301 /*
2302 * Disable sleep mode then unmask Tx interrupt.
2303 */
2304
2305 WRITE_UART_REGISTER (
2306 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
2307
2308 WRITE_UART_REGISTER (
2309 uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
2310
2311 }
2312 }
2313
2314 if (v24_input_line_changed)
2315 (void) NU_Activate_HISR (&(uart->v24_hisr_ctrl_block));
2316 }
2317
2318 /*******************************************************************************
2319 *
2320 * fill_tx_fifo
2321 *
2322 * Purpose : If the TX buffer is not empty, and if there is no break in
2323 * progress, bytes are written into the TX FIFO until the TX FIFO is
2324 * full or the TX buffer is empty. Else, if there is a break to send
2325 * an all 0s character is written into the TX FIFO and a break is
2326 * declared in progress to avoid to fill the TX FIFO on the next
2327 * interrupt.
2328 * When the TX FIFO is empty and if a break is in progress, the break
2329 * length is programmed: all 0s characters are written into the TX
2330 * FIFO. The number of bytes has been defined previously with the
2331 * UAF_SetLineState function. The break condition is enabled.
2332 * When the TX FIFO and the transmitter shift register (TSR) are both
2333 * empty and if a break is in progress, the break condition is
2334 * disabled.
2335 * When bytes are written from the TX buffer to the TX FIFO, the
2336 * writing callback function is called if it is installed and if all
2337 * conditions are fulfiled.
2338 *
2339 * Arguments: In : uart: Pointer on the UART structure.
2340 * Out: none
2341 *
2342 * Returns : none
2343 *
2344 ******************************************************************************/
2345
2346 static void
2347 fill_tx_fifo (t_uart *uart)
2348 {
2349
2350 /*
2351 * Disable sleep mode then mask Tx interrupt.
2352 */
2353
2354 WRITE_UART_REGISTER (
2355 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
2356
2357 WRITE_UART_REGISTER (
2358 uart, IER, READ_UART_REGISTER (uart, IER) & ~ETBEI);
2359
2360 /*
2361 * If a break is in progress, bytes of the TX buffer are not written into
2362 * the TX FIFO.
2363 */
2364
2365 if (!uart->break_in_progress)
2366 (void) NU_Activate_HISR (&(uart->tx_hisr_ctrl_block));
2367
2368 else {
2369
2370 /*
2371 * The break HISR is activated and the break condition is cleared.
2372 */
2373
2374 WRITE_UART_REGISTER (
2375 uart, LCR, READ_UART_REGISTER (uart, LCR) & ~BREAK_CONTROL);
2376
2377 (void) NU_Activate_HISR (&(uart->break_hisr_ctrl_block));
2378 }
2379 }
2380
2381 /*******************************************************************************
2382 *
2383 * UAF_Init
2384 *
2385 * Purpose : Initializes the UART hardware and installs interrupt handlers.
2386 * The parameters are set to the default values:
2387 * - 19200 baud,
2388 * - 8 bits / character,
2389 * - no parity,
2390 * - 1 stop bit,
2391 * - no flow control.
2392 * All functionalities of the UART driver are disabled.
2393 *
2394 * Arguments: In : uartNo: Used UART.
2395 * Out: none
2396 *
2397 * Returns : FD_OK : Successful operation.
2398 * FD_NOT_SUPPORTED: Wrong UART number.
2399 * FD_INTERNAL_ERR : Internal problem.
2400 *
2401 ******************************************************************************/
2402
2403 T_FDRET
2404 UAF_Init (T_fd_UartId uartNo)
2405 {
2406 t_uart *uart;
2407 volatile SYS_UWORD8 status;
2408 int index;
2409
2410 #if ((CHIPSET == 2) || (CHIPSET == 3) || (CHIPSET == 4))
2411 /*
2412 * Check UART number.
2413 * A return is used to simplify the code.
2414 * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware
2415 * flow control is not supported.
2416 * DCD and DTR are not supported on UART Irda on C-Sample.
2417 */
2418
2419 if ( (uartNo != UAF_UART_1) && (uartNo != UAF_UART_0) )
2420 return (FD_NOT_SUPPORTED);
2421 #endif
2422
2423 for (index = 0; index < NUMBER_OF_FD_UART; index++)
2424 uart_parameters[index].base_address = base_address[index];
2425
2426
2427 uart = &(uart_parameters[uartNo]);
2428
2429 /*
2430 * Create the 3 HISR actived in the RX/TX and V24 interrupt handlers.
2431 * A return is used to simplify the code if an error occurs.
2432 * All stacks are entirely filled with the pattern 0xFE.
2433 */
2434
2435 if (uart_initialized==0){
2436 memset (&(uart->rx_hisr_stack[0]), 0xFE, RX_HISR_STACK_SIZE);
2437 memset (&(uart->tx_hisr_stack[0]), 0xFE, TX_HISR_STACK_SIZE);
2438 memset (&(uart->v24_hisr_stack[0]), 0xFE, V24_HISR_STACK_SIZE);
2439 memset (&(uart->break_hisr_stack[0]), 0xFE, BREAK_HISR_STACK_SIZE);
2440 uart_initialized = 1;
2441 }
2442
2443
2444 if (NU_Create_HISR (&(uart->rx_hisr_ctrl_block),
2445 "Rx",
2446 hisr_execute_rx_tab[uartNo],
2447 RX_HISR_PRIORITY,
2448 &(uart->rx_hisr_stack[0]),
2449 RX_HISR_STACK_SIZE) != NU_SUCCESS)
2450
2451 return (FD_INTERNAL_ERR);
2452
2453 if (NU_Create_HISR (&(uart->tx_hisr_ctrl_block),
2454 "Tx",
2455 hisr_execute_tx_tab[uartNo],
2456 TX_HISR_PRIORITY,
2457 &(uart->tx_hisr_stack[0]),
2458 TX_HISR_STACK_SIZE) != NU_SUCCESS)
2459
2460 return (FD_INTERNAL_ERR);
2461
2462 if (NU_Create_HISR (&(uart->v24_hisr_ctrl_block),
2463 "UAF_V24",
2464 hisr_execute_v24_tab[uartNo],
2465 V24_HISR_PRIORITY,
2466 &(uart->v24_hisr_stack[0]),
2467 V24_HISR_STACK_SIZE) != NU_SUCCESS)
2468
2469 return (FD_INTERNAL_ERR);
2470
2471 /*
2472 * Create the HISR used to send a break.
2473 * A return is used to simplify the code if an error occurs.
2474 * The stack is entirely filled with the pattern 0xFE.
2475 */
2476
2477 if (NU_Create_HISR (&(uart->break_hisr_ctrl_block),
2478 "UAF_Brk",
2479 hisr_start_break_tab[uartNo],
2480 BREAK_HISR_PRIORITY,
2481 &(uart->break_hisr_stack[0]),
2482 BREAK_HISR_STACK_SIZE) != NU_SUCCESS)
2483
2484 return (FD_INTERNAL_ERR);
2485
2486 /*
2487 * Create a timer used in the break HISR.
2488 * A return is used to simplify the code if an error occurs.
2489 */
2490
2491 if (NU_Create_Timer (&(uart->break_timer_ctrl_block),
2492 "Break",
2493 stop_break_tab[uartNo],
2494 0, /* Parameter supplied to the routine: not used. */
2495 0, /* This parameter is set when the timer is reset. */
2496 0, /* The timer expires once. */
2497 NU_DISABLE_TIMER) != NU_SUCCESS)
2498
2499 return (FD_INTERNAL_ERR);
2500
2501 /*
2502 * Create a timer used in the detection of the escape sequence.
2503 * A return is used to simplify the code if an error occurs.
2504 */
2505
2506 if (NU_Create_Timer (&(uart->guard_period_timer_ctrl_block),
2507 "Esc seq",
2508 analyze_guard_period_timer_expiration_tab[uartNo],
2509 0, /* Parameter supplied to the routine: not used. */
2510 0, /* This parameter is set when the timer is reset. */
2511 0, /* The timer expires once. */
2512 NU_DISABLE_TIMER) != NU_SUCCESS)
2513
2514 return (FD_INTERNAL_ERR);
2515
2516 /*
2517 * These data are used to send a break.
2518 * A character has: 8 data bits + 1 start bit + 1 stop bit = 10 bits.
2519 */
2520
2521 uart->baudrate = baudrate_value[FD_BAUD_115200];
2522 uart->bits_per_char = 10;
2523
2524 /*
2525 * UART base address.
2526 */
2527
2528 uart->base_address = base_address[uartNo];
2529
2530 /*
2531 * Select the current array used to store received bytes.
2532 */
2533
2534 uart->rx_buffer_used_by_rx_lisr = &(uart->rx_fifo_byte_2[0]);
2535 uart->rx_buffer_used_by_rx_hisr = &(uart->rx_fifo_byte_2[0]);
2536
2537 /*
2538 * RX and TX buffers.
2539 */
2540
2541 uart->buffer_size = FD_MAX_BUFFER_SIZE;
2542 uart->rx_threshold_level = 1;
2543 uart->tx_threshold_level = 0;
2544 uart->rx_in = &(uart->rx_buffer[0]);
2545 uart->rx_out = &(uart->rx_buffer[0]);
2546 uart->tx_in = &(uart->tx_buffer[0]);
2547 uart->tx_out = &(uart->tx_buffer[0]);
2548
2549 /*
2550 * Escape sequence.
2551 */
2552
2553 uart->esc_seq_modified = 0;
2554 uart->esc_seq_detection_state = INITIALIZATION;
2555 uart->esc_seq_character = DEFAULT_ESC_SEQ_CHARACTER;
2556 uart->guard_period = CONVERT_TIME_IN_TDMA (
2557 DEFAULT_GUARD_PERIOD);
2558
2559 /*
2560 * Flow control.
2561 */
2562
2563 uart->flow_control_mode = fc_none;
2564 uart->send_xon_xoff = 0;
2565 uart->rx_stopped_by_application = 1;
2566 uart->rx_stopped_by_driver = 0;
2567 uart->tx_stopped_by_application = 1;
2568 uart->tx_stopped_by_driver = 0;
2569
2570 /*
2571 * Break.
2572 */
2573
2574 uart->break_received = 0;
2575 uart->break_to_send = 0;
2576 uart->break_in_progress = 0;
2577
2578 /*
2579 * Callback (UAF_ReadData and UAF_WriteData).
2580 */
2581
2582 uart->esc_seq_received = 0;
2583
2584 uart->reading_suspended = 0;
2585 uart->writing_suspended = 0;
2586 uart->rd_call_from_hisr_in_progress = 0;
2587 uart->wr_call_from_hisr_in_progress = 0;
2588 uart->rd_call_setup = rm_noInstall;
2589 uart->wr_call_setup = rm_noInstall;
2590
2591 /*
2592 * State defined in UAF_GetLineState.
2593 */
2594
2595 uart->state_1 = 0;
2596 uart->state_2 = 0;
2597 uart->state = &(uart->state_1);
2598
2599 /*
2600 * Errors counters.
2601 */
2602
2603 uart->framing_error = 0;
2604 uart->parity_error = 0;
2605 uart->overrun_error = 0;
2606 uart->spurious_interrupts = 0;
2607
2608 uart->max_rx_fifo_level = 0;
2609
2610 /*
2611 * Mask all interrupts causes and disable sleep mode and low power mode.
2612 */
2613
2614 WRITE_UART_REGISTER (uart, IER, 0x00);
2615
2616 /*
2617 * Reset UART mode configuration.
2618 */
2619
2620 WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE |
2621 IR_SLEEP_DISABLED |
2622 SIR_TX_WITHOUT_ACREG2 |
2623 FRAME_LENGTH_METHOD);
2624
2625 /*
2626 * FIFO configuration.
2627 * EFR[4] = 1 to allow to program FCR[5:4] and MCR[7:5].
2628 */
2629
2630 WRITE_UART_REGISTER (uart, LCR, 0xBF);
2631 SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT);
2632
2633 /*
2634 * Select the word length, the number of stop bits , the parity and set
2635 * LCR[7] (DLAB) to allow to program FCR, DLL and DLM.
2636 */
2637
2638 WRITE_UART_REGISTER (uart, LCR, WLS_8 | DLAB);
2639
2640 /*
2641 * Program the trigger levels.
2642 * MCR[6] must be set to 1.
2643 */
2644
2645 SET_BIT (uart, MCR, TCR_TLR_BIT);
2646 WRITE_UART_REGISTER (uart, TCR, 0x0F);
2647 WRITE_UART_REGISTER (uart, TLR, RX_FIFO_TRIGGER_LEVEL);
2648 RESET_BIT (uart, MCR, TCR_TLR_BIT);
2649
2650 /*
2651 * Force the generation of THR_IT on TX FIFO empty: SCR[3] = 1.
2652 */
2653
2654 WRITE_UART_REGISTER (
2655 uart, SCR, READ_UART_REGISTER (uart, SCR) | TX_EMPTY_CTL_IT);
2656
2657 /*
2658 * Program the FIFO control register. Bit 0 must be set when other FCR bits
2659 * are written to or they are not programmed.
2660 * FCR is a write-only register. It will not be modified.
2661 */
2662
2663 WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE |
2664 RX_FIFO_RESET | /* self cleared */
2665 TX_FIFO_RESET); /* self cleared */
2666
2667 /*
2668 * Program the baud generator.
2669 */
2670
2671 WRITE_UART_REGISTER (uart, DLL, dll[FD_BAUD_115200]);
2672 WRITE_UART_REGISTER (uart, DLM, dlh[FD_BAUD_115200]);
2673
2674 /*
2675 * Reset LCR[7] (DLAB) to have access to the RBR, THR and IER registers.
2676 */
2677
2678 WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB);
2679
2680 /*
2681 * Select UART mode.
2682 */
2683
2684 WRITE_UART_REGISTER (uart, MDR1, UART_MODE |
2685 IR_SLEEP_DISABLED |
2686 SIR_TX_WITHOUT_ACREG2 |
2687 FRAME_LENGTH_METHOD);
2688
2689 /*
2690 * Read the state of CTS, DSR and DCD.
2691 */
2692
2693 status = READ_UART_REGISTER (uart, MSR);
2694
2695 if (status & MCTS)
2696 uart->cts_level = 0;
2697 else
2698 uart->cts_level = 1;
2699
2700 /*
2701 * Unmask RX interrupt and the modem status interrupt.
2702 */
2703
2704 WRITE_UART_REGISTER (uart, IER, ERBI | EDSSI);
2705
2706 return (FD_OK);
2707 }
2708
2709 /*******************************************************************************
2710 *
2711 * UAF_Enable
2712 *
2713 * Purpose : The functionalities of the UART driver are disabled or enabled.
2714 * In the deactivated state, all information about the communication
2715 * parameters should be stored and recalled if the driver is again
2716 * enabled. When the driver is enabled the RX and TX buffers are
2717 * cleared.
2718 *
2719 * Arguments: In : enable: 1: enable the driver
2720 * 0: disable the driver
2721 * Out: none
2722 *
2723 * Returns : FD_OK : Successful operation.
2724 * FD_INTERNAL_ERR : Internal problem with the hardware.
2725 *
2726 ******************************************************************************/
2727
2728 T_FDRET
2729 UAF_Enable (T_fd_UartId uartNo, SYS_BOOL enable)
2730 {
2731 t_uart *uart;
2732
2733 /*
2734 * There is no case where FD_INTERNAL_ERR may be returned.
2735 */
2736
2737 uart = &(uart_parameters[uartNo]);
2738
2739 if (enable) {
2740
2741 uart->rx_stopped_by_driver = 0;
2742
2743 ENABLE_DRIVER (uart);
2744 start_receiver (uart);
2745
2746 } else {
2747
2748 DISABLE_DRIVER (uart);
2749 stop_receiver (uart);
2750
2751 uart->tx_in = &(uart->tx_buffer[0]);
2752 uart->rx_in = &(uart->rx_buffer[0]);
2753 uart->tx_out = uart->tx_in;
2754 uart->rx_out = uart->rx_in;
2755 }
2756
2757 return (FD_OK);
2758 }
2759
2760 /*******************************************************************************
2761 *
2762 * UAF_SetComPar
2763 *
2764 * Purpose : Sets up the communication parameters: baud rate, bits per
2765 * character, number of stop bits, parity.
2766 *
2767 * Arguments: In : baudrate: Used baud rate.
2768 * bpc : Used bits per character.
2769 * sb : Used stop bits.
2770 * parity : Used parity.
2771 * Out: none
2772 *
2773 * Returns : FD_OK : Successful operation.
2774 * FD_NOT_SUPPORTED: The specified parameters don't fit to the
2775 * capabilities of the UART.
2776 * FD_INTERNAL_ERR : Internal problem with the hardware.
2777 *
2778 ******************************************************************************/
2779
2780 T_FDRET
2781 UAF_SetComPar (T_fd_UartId uartNo,
2782 T_baudrate baudrate,
2783 T_bitsPerCharacter bpc,
2784 T_stopBits sb,
2785 T_parity parity)
2786 {
2787 t_uart *uart;
2788 volatile SYS_UWORD8 mcr_value;
2789 volatile SYS_UWORD8 status;
2790
2791 /*
2792 * There is no case where FD_INTERNAL_ERR may be returned.
2793 * pa_space is not supported. Some baudrates are not supported too.
2794 * A return is used to simplify the code.
2795 */
2796 baudrate = FD_BAUD_115200;
2797
2798 if ((!baudrate_value[baudrate]) ||
2799 (parity == pa_space))
2800
2801 return (FD_NOT_SUPPORTED);
2802
2803 uart = &(uart_parameters[uartNo]);
2804
2805 /*
2806 * Mask all interrupts causes and disable sleep mode and low power mode.
2807 */
2808
2809 WRITE_UART_REGISTER (uart, IER, 0x00);
2810
2811 /*
2812 * Reset UART mode configuration.
2813 */
2814
2815 WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE |
2816 IR_SLEEP_DISABLED |
2817 SIR_TX_WITHOUT_ACREG2 |
2818 FRAME_LENGTH_METHOD);
2819
2820 /*
2821 * FIFO configuration.
2822 * EFR[4] = 1 to allow to program FCR[5:4] and MCR[7:5].
2823 */
2824
2825 WRITE_UART_REGISTER (uart, LCR, 0xBF);
2826 SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT);
2827
2828 /*
2829 * Select the word length, the number of stop bits , the parity and set
2830 * LCR[7] (DLAB) to allow to program FCR, DLL and DLM.
2831 */
2832
2833 uart->baudrate = baudrate_value[baudrate];
2834 uart->bits_per_char = 1; /* Start bit. */
2835 mcr_value = DLAB;
2836
2837 if (bpc == bpc_7) {
2838
2839 mcr_value |= WLS_7;
2840 uart->bits_per_char += 7;
2841
2842 } else {
2843
2844 mcr_value |= WLS_8;
2845 uart->bits_per_char += 8;
2846 }
2847
2848 if (sb == sb_2) {
2849
2850 mcr_value |= STB;
2851 uart->bits_per_char += 2;
2852
2853 } else
2854 uart->bits_per_char += 1;
2855
2856 switch (parity) {
2857
2858 case pa_even:
2859
2860 mcr_value |= (PEN | EPS);
2861 uart->bits_per_char += 1;
2862
2863 break;
2864
2865 case pa_odd:
2866
2867 mcr_value |= PEN;
2868 uart->bits_per_char += 1;
2869
2870 break;
2871
2872 default:
2873
2874 /*
2875 * There is nothing to do.
2876 */
2877
2878 break;
2879 }
2880
2881 WRITE_UART_REGISTER (uart, LCR, mcr_value);
2882
2883 /*
2884 * Program the trigger levels.
2885 * MCR[6] must be set to 1.
2886 */
2887
2888 SET_BIT (uart, MCR, TCR_TLR_BIT);
2889 WRITE_UART_REGISTER (uart, TCR, 0x0F);
2890 WRITE_UART_REGISTER (
2891 uart, TLR, RX_FIFO_TRIGGER_LEVEL);
2892 RESET_BIT (uart, MCR, TCR_TLR_BIT);
2893
2894 /*
2895 * Force the generation of THR_IT on TX FIFO empty: SCR[3] = 1.
2896 */
2897
2898 WRITE_UART_REGISTER (
2899 uart, SCR, READ_UART_REGISTER (uart, SCR) | TX_EMPTY_CTL_IT);
2900
2901 /*
2902 * Program the FIFO control register. Bit 0 must be set when other FCR bits
2903 * are written to or they are not programmed.
2904 * FCR is a write-only register. It will not be modified.
2905 */
2906
2907 WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE |
2908 RX_FIFO_RESET | /* self cleared */
2909 TX_FIFO_RESET); /* self cleared */
2910
2911 /*
2912 * Program the baud generator.
2913 */
2914
2915 WRITE_UART_REGISTER (uart, DLL, dll[baudrate]);
2916 WRITE_UART_REGISTER (uart, DLM, dlh[baudrate]);
2917
2918 /*
2919 * Reset LCR[7] (DLAB) to have access to the RBR, THR and IER registers.
2920 */
2921
2922 WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB);
2923
2924 /*
2925 * Select UART mode.
2926 */
2927
2928 WRITE_UART_REGISTER (uart, MDR1, UART_MODE |
2929 IR_SLEEP_DISABLED |
2930 SIR_TX_WITHOUT_ACREG2 |
2931 FRAME_LENGTH_METHOD);
2932
2933 /*
2934 * Read the state of CTS, DSR and DCD.
2935 */
2936
2937 status = READ_UART_REGISTER (uart, MSR);
2938
2939 if (status & MCTS)
2940 uart->cts_level = 0;
2941 else
2942 uart->cts_level = 1;
2943
2944 /*
2945 * Unmask RX and TX interrupts and the modem status interrupt
2946 * and allow sleep mode.
2947 */
2948
2949 WRITE_UART_REGISTER (uart, IER, ERBI | ETBEI | EDSSI | IER_SLEEP);
2950 WRITE_UART_REGISTER (uart, IER, ERBI | ETBEI | EDSSI);
2951
2952 return (FD_OK);
2953 }
2954
2955 /*******************************************************************************
2956 *
2957 * UAF_SetBuffer
2958 *
2959 * Purpose : Sets up the size of the circular buffers to be used in the UART
2960 * driver. This function may be called only if the UART is disabled
2961 * with UAF_Enable.
2962 *
2963 * Arguments: In : bufSize : Specifies the size of the circular buffer.
2964 * rxThreshold: Amount of received bytes that leads to a call
2965 * to suspended read-out function which is passed
2966 * to the function UAF_ReadData.
2967 * txThreshold: Amount of bytes in the TX buffer to call the
2968 * suspended write-in function which is passed to
2969 * the function UAF_WriteData
2970 * Out: none
2971 *
2972 * Returns : FD_OK : Successful operation.
2973 * FD_NOT_SUPPORTED: bufSize exceeds the maximal possible
2974 * capabilities of the driver or the threshold
2975 * values don't correspond to the bufSize.
2976 * FD_INTERNAL_ERR : Internal problem with the hardware or the
2977 * function has been called while the UART is
2978 * enabled.
2979 *
2980 ******************************************************************************/
2981
2982 T_FDRET
2983 UAF_SetBuffer (T_fd_UartId uartNo,
2984 SYS_UWORD16 bufSize,
2985 SYS_UWORD16 rxThreshold,
2986 SYS_UWORD16 txThreshold)
2987 {
2988 T_FDRET result;
2989 t_uart *uart;
2990
2991 if ((bufSize > FD_MAX_BUFFER_SIZE) ||
2992 (rxThreshold > FD_MAX_BUFFER_SIZE) ||
2993 (txThreshold > FD_MAX_BUFFER_SIZE))
2994
2995 result = FD_NOT_SUPPORTED;
2996
2997 else {
2998
2999 uart = &(uart_parameters[uartNo]);
3000
3001 if (!DRIVER_DISABLED (uart))
3002 result = FD_INTERNAL_ERR;
3003
3004 else if (RX_HIGH_WATERMARK (bufSize) < RX_LOW_WATERMARK (bufSize))
3005 result = FD_NOT_SUPPORTED;
3006
3007 else {
3008
3009 uart->buffer_size = bufSize;
3010 uart->rx_threshold_level = rxThreshold;
3011 uart->tx_threshold_level = txThreshold;
3012
3013 result = FD_OK;
3014 }
3015 }
3016
3017 return (result);
3018 }
3019
3020 /*******************************************************************************
3021 *
3022 * UAF_SetFlowCtrl
3023 *
3024 * Purpose : Changes the flow control mode of the UART driver.
3025 * If a flow control is activated, DTR is activated or XOFF is sent
3026 * if the RX buffer is not able to store the received characters else
3027 * DTR is deactivated or XON is sent.
3028 *
3029 * Arguments: In : fcMode: flow control mode (none, DTR/DSR, RTS/CTS, XON/XOFF).
3030 * XON : ASCII code of the XON character.
3031 * XOFF : ASCII code of the XOFF character.
3032 * Out: none
3033 *
3034 * Returns : FD_OK : Successful operation.
3035 * FD_NOT_SUPPORTED: The flow control mode is not supported.
3036 * FD_INTERNAL_ERR : Internal problem with the hardware.
3037 *
3038 ******************************************************************************/
3039
3040 T_FDRET
3041 UAF_SetFlowCtrl (T_fd_UartId uartNo,
3042 T_flowCtrlMode fcMode,
3043 SYS_UWORD8 XON,
3044 SYS_UWORD8 XOFF)
3045 {
3046 T_FDRET result;
3047 t_uart *uart;
3048
3049 /*
3050 * There is no case where FD_INTERNAL_ERR may be returned.
3051 * The DTR/DSR protocol is not supported.
3052 */
3053
3054 if (fcMode == fc_dtr)
3055 result = FD_NOT_SUPPORTED;
3056
3057 else {
3058
3059 uart = &(uart_parameters[uartNo]);
3060
3061 uart->tx_stopped_by_driver = 0;
3062
3063
3064 uart->xon_character = XON;
3065 uart->xoff_character = XOFF;
3066 uart->flow_control_mode = fcMode;
3067
3068 /*
3069 * Disable sleep mode.
3070 */
3071
3072 WRITE_UART_REGISTER (
3073 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
3074
3075 WRITE_UART_REGISTER (
3076 uart, MCR, READ_UART_REGISTER (uart, MCR) | MRTS);
3077
3078 /*
3079 * Re-enable sleep mode.
3080 */
3081
3082 WRITE_UART_REGISTER (
3083 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
3084
3085 if (fcMode == fc_rts) {
3086
3087 if (uart->cts_level)
3088 uart->tx_stopped_by_driver = 1;
3089 }
3090
3091 /*
3092 * If the high watermark is reached, DTR or RTS is activated or XOFF is
3093 * sent according to the flow control mode. Else, DTR is deactivated or
3094 * XON is sent.
3095 */
3096
3097 if (fcMode != fc_none) {
3098
3099 if (get_bytes_in_rx_buffer (uart) >= RX_HIGH_WATERMARK (
3100 uart->buffer_size)) {
3101
3102 uart->rx_stopped_by_driver = 1;
3103 stop_receiver (uart);
3104
3105 } else if (!DRIVER_DISABLED (uart)) {
3106
3107 uart->rx_stopped_by_driver = 0;
3108 start_receiver (uart);
3109 }
3110
3111 } else {
3112
3113 uart->rx_stopped_by_driver = 0;
3114 uart->tx_stopped_by_driver = 0;
3115 }
3116
3117 result = FD_OK;
3118 }
3119
3120 return (result);
3121 }
3122
3123 /*******************************************************************************
3124 *
3125 * UAF_SetEscape
3126 *
3127 * Purpose : To return to the command mode at the ACI while a data connection
3128 * is established, an escape sequence has to be detected.
3129 * To distinguish between user data and the escape sequence a
3130 * defined guard period is necessary before and after this sequence.
3131 *
3132 * Arguments: In : escChar : ASCII character which could appear three times
3133 * as an escape sequence.
3134 * guardPeriod: Denotes the minimal duration of the rest before
3135 * the first and after the last character of the
3136 * escape sequence, and the maximal receiving
3137 * duration of the whole escape string. This value
3138 * is expressed in ms.
3139 * Out: none
3140 *
3141 * Returns : FD_OK : Successful operation.
3142 * FD_INTERNAL_ERR : Internal problem with the hardware.
3143 *
3144 ******************************************************************************/
3145
3146 T_FDRET
3147 UAF_SetEscape (T_fd_UartId uartNo,
3148 SYS_UWORD8 escChar,
3149 SYS_UWORD16 guardPeriod)
3150 {
3151 t_uart *uart;
3152
3153 /*
3154 * There is no case where FD_INTERNAL_ERR may be returned.
3155 */
3156
3157 uart = &(uart_parameters[uartNo]);
3158
3159 uart->esc_seq_modified = 1;
3160 uart->esc_seq_character = escChar;
3161 uart->guard_period = CONVERT_TIME_IN_TDMA ((UNSIGNED) guardPeriod);
3162 uart->esc_seq_modified = 0; /* Set to 0 by the RX interrupt handler. */
3163
3164 return (FD_OK);
3165 }
3166
3167 /*******************************************************************************
3168 *
3169 * UAF_InpAvail
3170 *
3171 * Purpose : Returns the number of characters available in the RX buffer of the
3172 * driver. If the driver is disabled the function returns 0.
3173 *
3174 * Arguments: In : none
3175 * Out: none
3176 *
3177 * Returns : >= 0 : The returned value is the amount of data in the
3178 * RX buffer.
3179 * FD_NOT_READY : The function is called while the callback of the
3180 * readOutFunc function is activated and still not
3181 * terminated.
3182 * FD_INTERNAL_ERR : Internal problem with the hardware.
3183 *
3184 ******************************************************************************/
3185
3186 T_FDRET
3187 UAF_InpAvail (T_fd_UartId uartNo)
3188 {
3189 T_FDRET result;
3190 t_uart *uart;
3191 SYS_UWORD16 bytes_read;
3192 SYS_UWORD16 bytes_in_rx_buffer;
3193
3194 /*
3195 * There is no case where FD_INTERNAL_ERR may be returned.
3196 */
3197
3198 uart = &(uart_parameters[uartNo]);
3199
3200 if (uart->rd_call_setup == rm_notDefined)
3201 result = FD_NOT_READY;
3202
3203 else if (DRIVER_DISABLED (uart))
3204 result = 0;
3205
3206 else {
3207
3208 bytes_in_rx_buffer = get_bytes_in_rx_buffer (uart);
3209
3210 /*
3211 * Update reading pointer of the RX buffer if a callback from LISR
3212 * has been done.
3213 */
3214
3215 if (uart->rd_call_from_hisr_in_progress) {
3216
3217 bytes_read = uart->rd_size_before_call[0] -
3218 uart->rd_size_after_call[0] +
3219 uart->rd_size_before_call[1] -
3220 uart->rd_size_after_call[1];
3221
3222 uart->rx_out += bytes_read;
3223
3224 if (uart->rx_out >= &(uart->rx_buffer[0]) + uart->buffer_size + 1)
3225 uart->rx_out = uart->rx_out - uart->buffer_size - 1;
3226
3227 /*
3228 * Check if the low watermark is reached to enable the receiver.
3229 */
3230
3231 bytes_in_rx_buffer = get_bytes_in_rx_buffer (uart);
3232
3233 if ((uart->flow_control_mode != fc_none) &&
3234 (bytes_in_rx_buffer <= RX_LOW_WATERMARK (uart->buffer_size))) {
3235
3236 if ((!uart->rx_stopped_by_application) &&
3237 uart->rx_stopped_by_driver)
3238 start_receiver (uart);
3239
3240 uart->rx_stopped_by_driver = 0;
3241 }
3242
3243 uart->rd_call_from_hisr_in_progress = 0;
3244 }
3245
3246 result = (T_FDRET) bytes_in_rx_buffer;
3247 }
3248
3249 return (result);
3250 }
3251
3252 /*******************************************************************************
3253 *
3254 * UAF_OutpAvail
3255 *
3256 * Purpose : Returns the number of free characters in TX buffer of the driver.
3257 * If the driver is disabled the function returns 0.
3258 *
3259 * Arguments: In : none
3260 * Out: none
3261 *
3262 * Returns : >= 0 : The returned value is the amount of data in the
3263 * TX buffer.
3264 * FD_NOT_READY : The function is called while the callback of the
3265 * writeInFunc function is activated and still not
3266 * terminated.
3267 * FD_INTERNAL_ERR : Internal problem with the hardware.
3268 *
3269 ******************************************************************************/
3270
3271 T_FDRET
3272 UAF_OutpAvail (T_fd_UartId uartNo)
3273 {
3274 T_FDRET result;
3275 t_uart *uart;
3276 SYS_UWORD16 bytes_written;
3277
3278 /*
3279 * There is no case where FD_INTERNAL_ERR may be returned.
3280 */
3281
3282 uart = &(uart_parameters[uartNo]);
3283
3284 if (uart->wr_call_setup == rm_notDefined)
3285 result = FD_NOT_READY;
3286
3287 else if (DRIVER_DISABLED (uart))
3288 result = 0;
3289
3290 else {
3291
3292 /*
3293 * Update reading pointer of the TX buffer if a callback from LISR
3294 * has been done.
3295 */
3296
3297 if (uart->wr_call_from_hisr_in_progress) {
3298
3299 bytes_written = uart->wr_size_before_call[0] -
3300 uart->wr_size_after_call[0] +
3301 uart->wr_size_before_call[1] -
3302 uart->wr_size_after_call[1];
3303
3304 uart->tx_in += bytes_written;
3305
3306 if (uart->tx_in >= &(uart->tx_buffer[0]) + uart->buffer_size + 1)
3307 uart->tx_in = uart->tx_in - uart->buffer_size - 1;
3308
3309 uart->wr_call_from_hisr_in_progress = 0;
3310
3311 /*
3312 * if the TX FIFO is empty, unmask TX empty interrupt.
3313 */
3314
3315 if (!uart->tx_stopped_by_driver &&
3316 (READ_UART_REGISTER (uart, LSR) & THRE))
3317 {
3318 /*
3319 * Disable sleep mode then unmask Tx interrupt.
3320 */
3321
3322 WRITE_UART_REGISTER (
3323 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
3324
3325 WRITE_UART_REGISTER (
3326 uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
3327 }
3328 }
3329
3330 result = (T_FDRET) (uart->buffer_size - get_bytes_in_tx_buffer (uart));
3331 }
3332
3333 return (result);
3334 }
3335
3336 /*******************************************************************************
3337 *
3338 * UAF_EnterSleep
3339 *
3340 * Purpose : Checks if UART is ready to enter Deep Sleep. If ready, enables
3341 * wake-up interrupt.
3342 *
3343 * Arguments: In : none
3344 * Out: none
3345 *
3346 * Returns: 0 : Deep Sleep is not possible.
3347 * >= 1 : Deep Sleep is possible.
3348 *
3349 * Warning: Parameters are not verified.
3350 *
3351 ******************************************************************************/
3352
3353 T_FDRET
3354 UAF_EnterSleep (T_fd_UartId uartNo)
3355 {
3356 t_uart *uart;
3357 SYS_BOOL deep_sleep;
3358 volatile SYS_UWORD8 status;
3359
3360 uart = &(uart_parameters[uartNo]);
3361 deep_sleep = 0;
3362
3363 /*
3364 * Check if RX & TX FIFOs are both empty
3365 */
3366
3367 status = READ_UART_REGISTER (uart, LSR);
3368
3369 if (!(status & DR) &&
3370 (status & TEMT)) {
3371
3372 /*
3373 * Disable sleep mode.
3374 */
3375
3376 WRITE_UART_REGISTER (
3377 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
3378
3379 /*
3380 * Mask RX, TX and the modem status interrupts.
3381 */
3382
3383 WRITE_UART_REGISTER (
3384 uart, IER, READ_UART_REGISTER (uart, IER) &
3385 ~(ERBI | ETBEI | EDSSI));
3386
3387 /*
3388 * Enable the wake-up interrupt.
3389 */
3390
3391 ENABLE_WAKEUP_INTERRUPT (uart);
3392
3393 deep_sleep = 1;
3394 }
3395
3396 return (deep_sleep);
3397 }
3398
3399 /*******************************************************************************
3400 *
3401 * UAF_WakeUp
3402 *
3403 * Purpose : Wakes up UART after Deep Sleep.
3404 *
3405 * Arguments: In : none
3406 * Out: none
3407 *
3408 * Returns: FD_OK : Successful operation.
3409 *
3410 * Warning: Parameters are not verified.
3411 *
3412 ******************************************************************************/
3413
3414 T_FDRET
3415 UAF_WakeUp (T_fd_UartId uartNo)
3416 {
3417 t_uart *uart;
3418
3419 uart = &(uart_parameters[uartNo]);
3420
3421 /*
3422 * Disable the wake-up interrupt.
3423 */
3424
3425 DISABLE_WAKEUP_INTERRUPT (uart);
3426
3427 /*
3428 * Unmask RX and modem status interrupts then allow sleep mode.
3429 */
3430
3431 WRITE_UART_REGISTER (
3432 uart, IER, READ_UART_REGISTER (uart, IER) | (ERBI | EDSSI));
3433
3434 WRITE_UART_REGISTER (
3435 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
3436
3437 return (FD_OK);
3438 }
3439
3440 /*******************************************************************************
3441 *
3442 * UAF_ReadData
3443 *
3444 * Purpose : To read the received characters out of the RX buffer the address
3445 * of a function is passed. If characters are available, the driver
3446 * calls this function and pass the address and the amount of
3447 * readable characters. Because the RX buffer is circular, the
3448 * callback function may be called with more than one address of
3449 * buffer fragment.
3450 * The readOutFunc function modifies the contents of the size array
3451 * to return the driver the number of processed characters. Each
3452 * array entry is decremented by the number of bytes read in the
3453 * fragment.
3454 * If the UAF_ReadData is called while the RX buffer is empty, it
3455 * depends on the suspend parameter to suspend the call-back or to
3456 * leave without any operation. In the case of suspension, the
3457 * return value of UAF_ReadData is UAF_SUSPENDED. A delayed call-back
3458 * will be performed if:
3459 * - the RX buffer reachs the adjusted threshold (rxThreshold of
3460 * UAF_SetBuffer),
3461 * - the state of a V.24 input line has changed,
3462 * - a break is detected,
3463 * - an escape sequence is detected.
3464 * If no suspension is necessary the function returns the number of
3465 * processed bytes.
3466 *
3467 * Arguments: In : suspend : mode of suspension in case of RX buffer empty.
3468 * readOutFunc: Callback function.
3469 * cldFromIrq: The driver sets this parameter to 1
3470 * if the callback function is called
3471 * from an interrupt service routine.
3472 * reInstall : The call-back function sets this
3473 * parameter to rm_reInstall if the
3474 * driver must call again the callback
3475 * function when the RX threshold level
3476 * is reached. Else it will be set to
3477 * rm_noInstall. Before to call the
3478 * readOutFunc function this parameter
3479 * is set to rm_notDefined.
3480 * nsource : Informed the callback function about
3481 * the number of fragments which are
3482 * ready to copy from the circular RX
3483 * buffer.
3484 * source : Array which contains the addresses
3485 * of the fragments.
3486 * size : Array which contains the sizes of
3487 * each fragments.
3488 * state : The state parameter is the status
3489 * of the V.24 lines and the break /
3490 * escape detection. The state
3491 * parameter is described in the
3492 * specification of UAF_GetLineState.
3493 * Out: none
3494 *
3495 * Returns : >= 0 : Succesful operation. Amount of processed bytes.
3496 * FD_SUSPENDED : The callback is suspended until the buffer or
3497 * state condition changed.
3498 * FD_NOT_READY : The function is called while the callback is
3499 * activated and still not terminated.
3500 * FD_INTERNAL_ERR : Internal problems with the hardware.
3501 *
3502 ******************************************************************************/
3503
3504 T_FDRET
3505 UAF_ReadData (T_fd_UartId uartNo,
3506 T_suspendMode suspend,
3507 void (readOutFunc (SYS_BOOL cldFromIrq,
3508 T_reInstMode *reInstall,
3509 SYS_UWORD8 nsource,
3510 SYS_UWORD8 *source[],
3511 SYS_UWORD16 size[],
3512 SYS_UWORD32 state)))
3513 {
3514 T_FDRET result;
3515 t_uart *uart;
3516 SYS_UWORD16 bytes_read;
3517 SYS_UWORD16 bytes_in_rx_buffer;
3518
3519 /*
3520 * There is no case where FD_INTERNAL_ERR may be returned.
3521 */
3522
3523 uart = &(uart_parameters[uartNo]);
3524
3525 if (uart->rd_call_setup == rm_notDefined)
3526 result = FD_NOT_READY;
3527
3528 else if (get_bytes_in_rx_buffer (uart) || uart->esc_seq_received) {
3529
3530 uart->readOutFunc = readOutFunc;
3531 update_reading_callback (uart, 0); /* 0: call from application. */
3532
3533 bytes_read = uart->rd_size_before_call[0] -
3534 uart->rd_size_after_call[0] +
3535 uart->rd_size_before_call[1] -
3536 uart->rd_size_after_call[1];
3537
3538 uart->rx_out += bytes_read;
3539
3540 if (uart->rx_out >= &(uart->rx_buffer[0]) + uart->buffer_size + 1)
3541 uart->rx_out = uart->rx_out - uart->buffer_size - 1;
3542
3543 /*
3544 * Check if the low watermark is reached to enable the receiver.
3545 */
3546
3547 if ((uart->flow_control_mode != fc_none) &&
3548 (get_bytes_in_rx_buffer (uart) <= RX_LOW_WATERMARK (
3549 uart->buffer_size))) {
3550
3551 if ((!uart->rx_stopped_by_application) &&
3552 uart->rx_stopped_by_driver)
3553 start_receiver (uart);
3554
3555 uart->rx_stopped_by_driver = 0;
3556 }
3557
3558 uart->esc_seq_received = 0;
3559 result = (T_FDRET) bytes_read;
3560
3561 } else if (suspend == sm_suspend) {
3562
3563 uart->readOutFunc = readOutFunc;
3564 uart->reading_suspended = 1;
3565 result = FD_SUSPENDED;
3566
3567 } else {
3568
3569 /*
3570 * The previous callback function is deinstalled.
3571 */
3572
3573 uart->rd_call_setup = rm_noInstall;
3574 uart->reading_suspended = 0;
3575 result = 0; /* 0 byte read. */
3576 }
3577
3578 return (result);
3579 }
3580
3581 /*******************************************************************************
3582 *
3583 * UAF_WriteData
3584 *
3585 * Purpose : To write characters into the TX buffer the address of a function
3586 * is passed. If free space is available in the buffer, the driver
3587 * calls this function and passes the destination address and the
3588 * amount of space. Because the RX buffer is circular, the callback
3589 * function may be called with more than one address of buffer
3590 * fragment.
3591 * The writeInFunc function modifies the contents of the size array
3592 * to return the driver the number of processed bytes. Each array
3593 * entry is decremented by the number of bytes written in this
3594 * fragment.
3595 * If the UAF_WriteData function is called while the TX buffer is
3596 * full, it depends on the suspend parameter to suspend the
3597 * call-back or to leave this function without any operation. In the
3598 * case of suspension the returned value of the UAF_WriteData is
3599 * UAF_SUSPENDED. A delayed call-back will be performed if the TX
3600 * buffer reaches the adjusted threshold (txThreshold of
3601 * UAF_SetBuffer). If no suspension is necessary the function returns
3602 * the number of processed bytes.
3603 *
3604 * Arguments: In : suspend : mode of suspension in case of TX buffer empty.
3605 * writeInFunc: Callback function.
3606 * cldFromIrq: The driver sets this parameter to 1
3607 * if the call-back function is called
3608 * from an interrupt service routine.
3609 * reInstall : The callback function sets this
3610 * parameter to rm_reInstall if the
3611 * driver must call again the callback
3612 * function when the TX threshold level
3613 * is reached. Else it will be set to
3614 * rm_noInstall. Before to call the
3615 * readOutFunc function this parameter
3616 * is set to rm_notDefined.
3617 * nsource : Informed the callback function about
3618 * the number of fragments which are
3619 * available in the TX buffer.
3620 * dest : Array which contains the addresses
3621 * of the fragments.
3622 * size : Array which contains the sizes of
3623 * each fragments.
3624 * Out: none
3625 *
3626 * Returns : >= 0 : Succesful operation. Amount of processed bytes.
3627 * FD_SUSPENDED : The callback is suspended until the buffer
3628 * condition changed.
3629 * FD_NOT_READY : The function is called while the callback is
3630 * activated and still not terminated.
3631 * FD_INTERNAL_ERR : Internal problems with the hardware.
3632 *
3633 ******************************************************************************/
3634
3635 T_FDRET
3636 UAF_WriteData (T_fd_UartId uartNo,
3637 T_suspendMode suspend,
3638 void (writeInFunc (SYS_BOOL cldFromIrq,
3639 T_reInstMode *reInstall,
3640 SYS_UWORD8 ndest,
3641 SYS_UWORD8 *dest[],
3642 SYS_UWORD16 size[])))
3643 {
3644 T_FDRET result;
3645 t_uart *uart;
3646 SYS_UWORD16 bytes_written;
3647
3648 /*
3649 * There is no case where FD_INTERNAL_ERR may be returned.
3650 */
3651
3652 uart = &(uart_parameters[uartNo]);
3653
3654 if (uart->wr_call_setup == rm_notDefined)
3655 result = FD_NOT_READY;
3656
3657 else if ((!DRIVER_DISABLED (uart)) &&
3658 (get_bytes_in_tx_buffer (uart) < uart->buffer_size)) {
3659
3660 #if (BOARD == 31)
3661 /*while ((*((volatile SYS_UWORD16 *) ARMIO_IN) & 0x0100) == 0x0000)
3662 {
3663 *((volatile SYS_UWORD16 *) ARMIO_OUT) &= ~(0x0040);
3664 }*/
3665 if ((*((volatile SYS_UWORD16 *) ARMIO_IN) & 0x0100) == 0x0000)
3666 {
3667 *((volatile SYS_UWORD16 *) ARMIO_OUT) &= ~(0x0040);
3668 NU_Sleep(4); // 1.84 ms
3669 }
3670 *((volatile SYS_UWORD16 *) ARMIO_OUT) |= 0x0040;
3671
3672 #endif
3673 uart->writeInFunc = writeInFunc;
3674 update_writing_callback (uart, 0); /* 0: call from application. */
3675
3676 bytes_written = uart->wr_size_before_call[0] -
3677 uart->wr_size_after_call[0] +
3678 uart->wr_size_before_call[1] -
3679 uart->wr_size_after_call[1];
3680
3681 uart->tx_in += bytes_written;
3682
3683 if (uart->tx_in >= &(uart->tx_buffer[0]) + uart->buffer_size + 1)
3684 uart->tx_in = uart->tx_in - uart->buffer_size - 1;
3685
3686 /*
3687 * If:
3688 * - there is no break to send,
3689 * - the flow control is not activated,
3690 * unmask the TX empty interrupt to be able to send characters.
3691 */
3692
3693 if (!uart->break_to_send &&
3694 !uart->tx_stopped_by_driver)
3695 {
3696 /*
3697 * Disable sleep mode then unmask Tx interrupt.
3698 */
3699
3700 WRITE_UART_REGISTER (
3701 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
3702
3703 WRITE_UART_REGISTER (
3704 uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
3705 }
3706
3707 result = (T_FDRET) bytes_written;
3708
3709 } else if (suspend == sm_suspend) {
3710
3711 uart->writeInFunc = writeInFunc;
3712 uart->writing_suspended = 1;
3713 result = FD_SUSPENDED;
3714
3715 } else {
3716
3717 /*
3718 * The previous callback function is deinstalled.
3719 */
3720
3721 uart->wr_call_setup = rm_noInstall;
3722 uart->writing_suspended = 0;
3723 result = 0;
3724 }
3725
3726 return (result);
3727 }
3728
3729 /*******************************************************************************
3730 *
3731 * UAF_StopRec
3732 *
3733 * Purpose : If a flow control mode is set, this function tells the terminal
3734 * equipment that no more data can be received.
3735 * XON/XOFF: XOFF is sent.
3736 * DTR/DSR : DTR is desactivated.
3737 * RTS/CTS : RTS is deactivated.
3738 *
3739 * Arguments: In : none
3740 * Out: none
3741 *
3742 * Returns : FD_OK : Successful operation.
3743 * FD_INTERNAL_ERR : Internal problem with the hardware.
3744 *
3745 ******************************************************************************/
3746
3747 T_FDRET
3748 UAF_StopRec (T_fd_UartId uartNo)
3749 {
3750 t_uart *uart;
3751
3752 /*
3753 * There is no case where FD_INTERNAL_ERR may be returned.
3754 */
3755
3756 uart = &(uart_parameters[uartNo]);
3757
3758 if (uart->flow_control_mode != fc_none)
3759 stop_receiver (uart);
3760
3761 uart->rx_stopped_by_application = 1;
3762
3763 return (FD_OK);
3764 }
3765
3766 /*******************************************************************************
3767 *
3768 * UAF_StartRec
3769 *
3770 * Purpose : If a flow control mode is set, this function tells the terminal
3771 * equipment that the receiver is again able to receive more data.
3772 * If the buffer has already reached the high water mark the driver
3773 * sends the signal only if the buffer drains to a low water mark.
3774 * XON/XOFF: XON is sent.
3775 * DTR/DSR : DTR is activated.
3776 * RTS/CTS : RTS is activated.
3777 *
3778 * Arguments: In : none
3779 * Out: none
3780 *
3781 * Returns : FD_OK : Successful operation.
3782 * FD_INTERNAL_ERR : Internal problem with the hardware.
3783 *
3784 ******************************************************************************/
3785
3786 T_FDRET
3787 UAF_StartRec (T_fd_UartId uartNo)
3788 {
3789 t_uart *uart;
3790
3791 /*
3792 * There is no case where FD_INTERNAL_ERR may be returned.
3793 */
3794
3795 uart = &(uart_parameters[uartNo]);
3796
3797 if ((uart->flow_control_mode != fc_none) && (!uart->rx_stopped_by_driver))
3798 start_receiver (uart);
3799
3800 uart->rx_stopped_by_application = 0;
3801
3802 return (FD_OK);
3803 }
3804
3805 /*******************************************************************************
3806 *
3807 * UAF_GetLineState
3808 *
3809 * Purpose : Returns the state of the V.24 lines, the flow control state and
3810 * the resukt of the break/escape detection process as a bit field.
3811 *
3812 * Arguments: In : none
3813 * Out: state : State of the V.24 lines, the flow control state and
3814 * the result of the break/escape sequence detection
3815 * process as a bit field.
3816 *
3817 * Returns : FD_OK : Successful operation.
3818 * FD_NOT_READY : The function is called while the callback of
3819 * the readOutFunc function is activated and still
3820 * not terminated.
3821 * FD_INTERNAL_ERR : Internal problem with the hardware.
3822 *
3823 ******************************************************************************/
3824
3825 T_FDRET
3826 UAF_GetLineState (T_fd_UartId uartNo, SYS_UWORD32 *state)
3827 {
3828 T_FDRET result;
3829 t_uart *uart;
3830
3831 /*
3832 * There is no case where FD_INTERNAL_ERR may be returned.
3833 * Signals not supported are reported as 0.
3834 */
3835
3836 uart = &(uart_parameters[uartNo]);
3837
3838 if (uart->rd_call_setup == rm_notDefined)
3839 result = FD_NOT_READY;
3840
3841 else {
3842
3843 /*
3844 * The field state_2 is used when state_1 is set to 0 to avoid to
3845 * lose events detected in the RX interrupt handler.
3846 * Fields BRK and BRKLEN are set when a break is detected.
3847 * The field ESC is set when an escape sequence is detected.
3848 */
3849
3850 *state = uart->state_2;
3851 uart->state_2 = 0;
3852 uart->state = &(uart->state_2);
3853
3854 *state |= uart->state_1;
3855 uart->state_1 = 0;
3856 uart->state = &(uart->state_1);
3857
3858 *state |= ((((SYS_UWORD32) uart->cts_level) << RTS) |
3859
3860 (((SYS_UWORD32) (uart->tx_stopped_by_application |
3861 uart->tx_stopped_by_driver)) << TXSTP) |
3862
3863 (((SYS_UWORD32) (uart->rx_stopped_by_application |
3864 uart->rx_stopped_by_driver)) << RXSTP) |
3865
3866 (((SYS_UWORD32) (uart->buffer_size -
3867 get_bytes_in_rx_buffer (uart))) << RXBLEV));
3868
3869 /*
3870 * Fields SA, SB and X are set according to the flow control:
3871 *
3872 * None RTS/CTS XON/XOFF
3873 * SA 0 (ns) 0 (ns) 0 (ns)
3874 * SB RTS 0 RTS
3875 * X 0 RTS XON:0 XOFF:1 (transmitter)
3876 *
3877 * ns: signal not supported.
3878 * DTR/DSR flow control is not supported.
3879 */
3880
3881 if (uart->flow_control_mode != fc_rts)
3882 *state |= (((SYS_UWORD32) uart->cts_level) << SB);
3883
3884 if (uart->flow_control_mode == fc_rts)
3885 *state |= (((SYS_UWORD32) uart->cts_level) << X);
3886
3887 else if ((uart->flow_control_mode == fc_xoff) &&
3888 (uart->tx_stopped_by_application ||
3889 uart->tx_stopped_by_driver))
3890 *state |= (1 << X);
3891
3892 result = FD_OK;
3893 }
3894
3895 return (result);
3896 }
3897
3898 /*******************************************************************************
3899 *
3900 * UAF_SetLineState
3901 *
3902 * Purpose : Sets the states of the V.24 status lines according to the bit
3903 * field of the parameter state.
3904 *
3905 * Arguments: In : state : Bit field. Only the signals which are marked with
3906 * the 'set' access can be used to change the state of
3907 * the signal.
3908 * mask : Bit field with the same structure as state. Each bit
3909 * in state corresponds to a bit in mask. Settabled
3910 * bits marked by a 1 are manipulated by the driver.
3911 * Out: none
3912 *
3913 * Returns : FD_OK : Successful operation.
3914 * FD_INTERNAL_ERR : Internal problem with the hardware.
3915 *
3916 ******************************************************************************/
3917
3918 T_FDRET
3919 UAF_SetLineState (T_fd_UartId uartNo,
3920 SYS_UWORD32 state,
3921 SYS_UWORD32 mask)
3922 {
3923 t_uart *uart;
3924 UNSIGNED break_length;
3925
3926 uart = &(uart_parameters[uartNo]);
3927
3928 /*
3929 * There is no case where FD_INTERNAL_ERR may be returned.
3930 * DTR is not supported. The SA field is ignored.
3931 */
3932
3933 if ((mask & (1 << SA)) || (mask & (1 << DCD)))
3934 return (FD_NOT_SUPPORTED); /* Return used to simplify the code */
3935
3936 /*
3937 * Check if a break has to be sent.
3938 */
3939
3940 uart->break_length = (UNSIGNED) ((state >> BRKLEN) & 0xFF);
3941
3942 if (state & (1 << BRK) && (mask & (1 << BRK))) {
3943
3944 if (uart->break_length > FIFO_SIZE)
3945 return (FD_NOT_SUPPORTED); /* Return used to simplify the code */
3946
3947 else {
3948
3949 uart->time_without_character =
3950 compute_break_time (uart->baudrate, uart->bits_per_char, 3);
3951
3952 uart->break_to_send = 1;
3953
3954 /*
3955 * If the TX FIFO is empty the break is send from this function
3956 * else the interrupt handler will send the break.
3957 */
3958
3959 if (READ_UART_REGISTER (uart, LSR) & TEMT)
3960 send_break(uart);
3961 }
3962 }
3963
3964 /*
3965 * Disable sleep mode.
3966 */
3967
3968 WRITE_UART_REGISTER (
3969 uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
3970
3971 /*
3972 * The CTS field is ignored if the RTS/CTS flow control is selected.
3973 */
3974
3975 if (mask & (1 << CTS)) {
3976
3977 if (uart->flow_control_mode != fc_rts) {
3978
3979 /*
3980 * As the RTS/CTS flow control is not selected, the X bit does not
3981 * control CTS. CTS needs only to be activated or deactivated
3982 * according to the value of the CTS field.
3983 */
3984
3985 if (state & (1 << CTS))
3986 WRITE_UART_REGISTER (
3987 uart, MCR, READ_UART_REGISTER (uart, MCR) | MRTS);
3988
3989 else
3990 WRITE_UART_REGISTER (
3991 uart, MCR, READ_UART_REGISTER (uart, MCR) & ~MRTS);
3992
3993 } else if (!(mask & (1 << X))) {
3994
3995 /*
3996 * The RTS/CTS flow control is selected but the X bit in the mask
3997 * is null. Then the CTS bit controls CTS and the receiver must be
3998 * stopped or started according to the state of the CTS bit.
3999 * The receiver is started only if it was not stopped by the driver
4000 * and if it was stopped by the application.
4001 */
4002
4003 if (state & (1 << CTS)) {
4004
4005 if (!uart->rx_stopped_by_application) {
4006
4007 if (!uart->rx_stopped_by_driver)
4008 stop_receiver (uart);
4009
4010 uart->rx_stopped_by_application = 1;
4011 }
4012
4013 } else {
4014
4015 if ((!uart->rx_stopped_by_driver) &&
4016 uart->rx_stopped_by_application)
4017 start_receiver (uart);
4018
4019 uart->rx_stopped_by_application = 0;
4020 }
4021 }
4022 }
4023
4024 /*
4025 * The DCD field is ignored if the SB bit of the mask is set.
4026 */
4027
4028 if (!(mask & (1 << SB)) && (mask & (1 << DCD))) {
4029
4030 if (state & (1 << DCD))
4031 WRITE_UART_REGISTER (
4032 uart, MCR, READ_UART_REGISTER (uart, MCR) | MDTR);
4033
4034 else
4035 WRITE_UART_REGISTER (
4036 uart, MCR, READ_UART_REGISTER (uart, MCR) & ~MDTR);
4037 }
4038
4039 /*
4040 * Signals are set according to fields SA, SB and X states and flow
4041 * control:
4042 *
4043 * None RTS/CTS XON/XOFF
4044 * SA 0 (ns) 0 (ns) 0 (ns)
4045 * SB DCD DCD DCD
4046 * X ignore CTS XON:0 XOFF:1 (receiver)
4047 *
4048 * ns: signal not supported.
4049 * DTR/DSR flow control is not supported.
4050 */
4051
4052 if (mask & (1 << SB)) {
4053
4054 if (state & (1 << SB))
4055 WRITE_UART_REGISTER (
4056 uart, MCR, READ_UART_REGISTER (uart, MCR) | MDTR);
4057
4058 else
4059 WRITE_UART_REGISTER (
4060 uart, MCR, READ_UART_REGISTER (uart, MCR) & ~MDTR);
4061 }
4062
4063
4064 if ((mask & (1 << X)) &&
4065 (uart->flow_control_mode != fc_none)) {
4066
4067 if (state & (1 << X)) {
4068
4069 if (!uart->rx_stopped_by_application) {
4070
4071 if (!uart->rx_stopped_by_driver)
4072 stop_receiver (uart);
4073
4074 uart->rx_stopped_by_application = 1;
4075 }
4076
4077 } else {
4078
4079 /*
4080 * The receiver is started only if it is not stopped by the driver
4081 * and if it is stopped by the application.
4082 */
4083
4084 if ((!uart->rx_stopped_by_driver) &&
4085 uart->rx_stopped_by_application)
4086 start_receiver (uart);
4087
4088 uart->rx_stopped_by_application = 0;
4089 }
4090 }
4091
4092 /*
4093 * Re-enable sleep mode.
4094 */
4095
4096 WRITE_UART_REGISTER (
4097 uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
4098
4099 return (FD_OK);
4100 }
4101
4102 /*******************************************************************************
4103 *
4104 * UAF_InterruptHandler
4105 *
4106 * Purpose : Interrupt handler.
4107 *
4108 * Arguments: In : uart_id : origin of interrupt
4109 * interrupt_status: source of interrupt
4110 * Out: none
4111 *
4112 * Returns : none
4113 *
4114 ******************************************************************************/
4115
4116 void
4117 UAF_InterruptHandler (T_fd_UartId uart_id,
4118 SYS_UWORD8 interrupt_status)
4119 {
4120
4121 t_uart *uart;
4122
4123 /*
4124 * uart_id is not used.
4125 */
4126
4127 uart = &(uart_parameters[uart_id]);
4128
4129 uart->current_time = NU_Retrieve_Clock ();
4130
4131 /*
4132 * Causes of interrupt:
4133 * - trigger level reached,
4134 * - character time-out indication,
4135 * - transmitter holding register empty,
4136 * - modem status.
4137 */
4138
4139 switch (interrupt_status) {
4140
4141 case RX_DATA:
4142
4143 read_rx_fifo (uart);
4144 break;
4145
4146 case TX_EMPTY:
4147
4148 fill_tx_fifo (uart);
4149 break;
4150
4151 case MODEM_STATUS:
4152
4153 check_v24_input_lines (uart);
4154 break;
4155 }
4156 }
4157
4158 /*******************************************************************************
4159 *
4160 * UAF_CheckXEmpty
4161 *
4162 * Purpose : Checks the empty condition of the Transmitter.
4163 *
4164 * Arguments: In : none
4165 * Out: none
4166 *
4167 * Returns : FD_OK : Empty condition OK.
4168 * FD_NOT_READY : Empty condition not OK.
4169 * FD_INTERNAL_ERR : Internal problem with the hardware.
4170 *
4171 ******************************************************************************/
4172
4173 T_FDRET
4174 UAF_CheckXEmpty (T_fd_UartId uartNo)
4175 {
4176 T_FDRET result;
4177 t_uart *uart;
4178 SYS_UWORD8 status;
4179
4180 /*
4181 * There is no case where FD_INTERNAL_ERR may be returned.
4182 */
4183
4184 result = FD_OK;
4185
4186 uart = &(uart_parameters[uartNo]);
4187 status = READ_UART_REGISTER (uart, LSR);
4188
4189 /*
4190 * Checks if:
4191 * - the TX SW Buffer is empty,
4192 * - the TX HW FIFO is empty (THRE),
4193 * - the Transmitter Shift Register is empty (TEMT).
4194 */
4195
4196 if (!(TX_BUFFER_EMPTY (uart)) ||
4197 !(status & THRE) ||
4198 !(status & TEMT))
4199
4200 result = FD_NOT_READY;
4201
4202 return (result);
4203 }
4204