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