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