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