comparison packages/devs/serial/rs232/mn10300/current/src/serial_mn10300_2.cxx @ 0:3111d98ba7b3 ecos-v1_1-release

Initial commit of eCos version 1.1
author jlarmour
date Tue, 11 May 1999 11:16:07 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3111d98ba7b3
1 //=================================================================
2 //
3 // serial_mn10300_2.cxx
4 //
5 // Driver for the mn10300 serial port #2
6 //
7 //=================================================================
8 //####COPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 // The contents of this file are subject to the Cygnus eCos Public License
12 // Version 1.0 (the "License"); you may not use this file except in
13 // compliance with the License. You may obtain a copy of the License at
14 // http://sourceware.cygnus.com/ecos
15 //
16 // Software distributed under the License is distributed on an "AS IS"
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
18 // License for the specific language governing rights and limitations under
19 // the License.
20 //
21 // The Original Code is eCos - Embedded Cygnus Operating System, released
22 // September 30, 1998.
23 //
24 // The Initial Developer of the Original Code is Cygnus. Portions created
25 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved.
26 // -------------------------------------------
27 //
28 //####COPYRIGHTEND####
29 //=================================================================
30 //#####DESCRIPTIONBEGIN####
31 //
32 // Author(s): proven
33 // Contributors: proven
34 // Date: 1998-04-22
35 // Description: Class methods for the class Cyg_Device_Serial_mn10300
36 //####DESCRIPTIONEND####
37
38 #include <pkgconf/devs.h> // To see if we need to bother
39 #ifdef CYGPKG_DEVICES_SERIAL_RS232_MN10300_2 // Do we need to build this file
40
41 #define CYG_DEVICE_INTERNAL
42 #include <cyg/devs/serial/rs232/mn10300/serial_mn10300_2.hxx>
43 #include <cyg/kernel/sema.hxx> // Cyg_Binary_Semaphore
44
45 #ifdef CYG_DEVICE_SERIAL_RS232_MN10300_2_NAME
46 #ifdef CYG_DEVICE_SERIAL_RS232_MN10300_2_DECLARE
47 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2 CYG_DEVICE_SERIAL_RS232_MN10300_2_NAME;
48 #endif
49 #endif
50
51 static char eob_chars[] = { 4, 10, 13, 26 };
52
53 // ------------------------------------------------------------------------
54 // Constructor for serial device
55 //
56 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2()
57 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
58 : read_interrupt(CYG_DEVICE_SERIAL_RS232_RVEC, 4, (CYG_ADDRWORD)this, read_isr, read_dsr),
59 write_interrupt(CYG_DEVICE_SERIAL_RS232_TVEC, 4, (CYG_ADDRWORD)this, write_isr, write_dsr)
60 #endif
61 {
62 CYG_REPORT_FUNCTION();
63
64 // Initialize any data
65 read_buffer = NULL;
66
67 // read_buffers = NULL;
68 #ifdef CYG_DEVICE_SERIAL_RS232_READ_BUFFERS_LL
69 read_buffers_ll_last = NULL;
70 read_buffers_ll_first = NULL;
71 #endif
72
73 #ifdef CYG_DEVICE_SERIAL_RS232_READ_MODES
74 // Default to ASCII mode if READ_MODES is configured.
75 read_mode = 0xff;
76 read_mode_eob_chars = eob_chars;
77 read_mode_eob_count = sizeof(eob_chars);
78 // read_mode_translate_char = 0;
79 // read_mode_escape_next_char = 0;
80 #endif
81
82 write_buffer = NULL;
83 // write_buffers = NULL;
84 #ifdef CYG_DEVICE_SERIAL_RS232_WRITE_BUFFERS_LL
85 write_buffers_ll_last = NULL;
86 write_buffers_ll_first = NULL;
87 #endif
88
89 #ifdef CYG_DEVICE_SERIAL_RS232_WRITE_MODES
90 // Default to CR to CRLF translation
91 write_mode = 1;
92 write_char = 0;
93 #endif
94
95 // Set the timers before enabling them or the serial device
96 *CYG_DEVICE_SERIAL_RS232_TR = CYG_DEVICE_SERIAL_RS232_T1_VALUE;
97 *TIMER2_BR = CYG_DEVICE_SERIAL_RS232_T2_VALUE;
98
99 // Timer2 sourced from IOCLK
100 *TIMER2_MD = 0x80;
101
102 // Mode on PORT3, used for serial line controls.
103 *PORT3_MD = 0x01;
104
105 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
106 read_interrupt.attach();
107 write_interrupt.attach();
108 // Clear interrupts for now.
109 *CYG_DEVICE_SERIAL_RS232_ICR = 0x00;
110
111 /* Turn on interrupts by unmasking the vector */
112 kmode = CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT;
113 read_interrupt.unmask_interrupt(read_interrupt.get_vector());
114 write_interrupt.unmask_interrupt(write_interrupt.get_vector());
115 #endif
116
117 // Set the control register, finallizing the settup.
118 // Source from timer 2, 8bit chars, enable tx and rx
119 *CYG_DEVICE_SERIAL_RS232_CR = 0xc081;
120 }
121
122 // ------------------------------------------------------------------------
123 // set_kmode()
124 // Set the kernel mode to (polled, interrrupt, ...)
125 // Only applicable if we have multiple modes.
126
127 #if defined (CYG_DEVICE_SERIAL_RS232_KMODE_POLLED) && \
128 defined (CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT)
129
130 cyg_int32
131 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
132 set_kmode(cyg_uint32 new_mode)
133 {
134
135 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
136 mutex.lock();
137 #endif
138
139 /* Switching from polled mode to interrupt mode is easy */
140 if (kmode == CYG_DEVICE_SERIAL_RS232_KMODE_POLLED) {
141 if (new_mode == CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT) {
142
143 /* Turn on interrupts by unmasking the vector */
144 kmode = CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT;
145 read_interrupt.unmask_interrupt(read_interrupt.get_vector());
146 write_interrupt.unmask_interrupt(write_interrupt.get_vector());
147 }
148 }
149 /* Switching to polled mode should flush the buffers */
150 if (kmode == CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT) {
151 if (new_mode == CYG_DEVICE_SERIAL_RS232_KMODE_POLLED) {
152
153 this->io_write_flush();
154
155 /* Turn off interrupts by masking the vector */
156 kmode = CYG_DEVICE_SERIAL_RS232_KMODE_POLLED;
157 read_interrupt.mask_interrupt(read_interrupt.get_vector());
158 write_interrupt.mask_interrupt(write_interrupt.get_vector());
159 }
160 }
161
162 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
163 mutex.unlock();
164 #endif
165
166 return 0;
167 }
168
169 #else
170
171 cyg_int32
172 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
173 set_kmode(cyg_uint32 new_mode)
174 {
175 #if defined(CYG_DEVICE_SERIAL_RS232_KMODE_POLLED)
176 CYG_ASSERT (CYG_DEVICE_SERIAL_RS232_KMODE_POLLED == new_mode,
177 "Can only select polled mode" );
178 #endif
179 #if defined(CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT)
180 CYG_ASSERT (CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT == new_mode,
181 "Can only select interrupt mode" );
182 #endif
183
184 return 0;
185 }
186
187 #endif
188
189 // ------------------------------------------------------------------------
190 // Baud rate
191
192 static struct baud_rate {
193 cyg_uint8 sc_txb;
194 cyg_uint8 tm_br;
195 } baud_rate_table[] = {
196 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B0, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B0 }, // B0
197 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B0, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B0 }, // B50
198 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B0, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B0 }, // B75
199 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B0, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B0 }, // B110
200
201 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B0, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B0 }, // B134.5
202 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B0, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B0 }, // B150
203 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B0, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B0 }, // B200
204 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B0, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B0 }, // B300
205
206 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B600, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B600 }, // B600
207 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B1200, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B1200 }, // B1200
208 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B0, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B0 }, // B1800
209 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B2400, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B2400 }, // B2400
210
211 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B4800, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B4800 }, // B4800
212 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B9600, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B9600 }, // B9600
213 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B19200, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B19200 }, // B19200
214 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B38400, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B38400 }, // B38400
215
216 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B57600, CYG_DEVICE_SERIAL_RS232_T2_VALUE_B57600 }, // B57600
217 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B115200,CYG_DEVICE_SERIAL_RS232_T2_VALUE_B115200}, // B115200
218 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B230400,CYG_DEVICE_SERIAL_RS232_T2_VALUE_B230400}, // B230400
219 { CYG_DEVICE_SERIAL_RS232_T1_VALUE_B460800,CYG_DEVICE_SERIAL_RS232_T2_VALUE_B460800} // B460800
220
221 };
222
223 cyg_int32
224 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
225 get_baud_rate()
226 {
227 cyg_ucount8 i;
228 cyg_uint8 tr, tm_br;
229
230 tm_br = *TIMER2_BR;
231 tr = *CYG_DEVICE_SERIAL_RS232_TR;
232
233 for (i = 0; i < (sizeof(baud_rate_table) / sizeof(struct baud_rate)); i++) {
234 if ((tr == baud_rate_table[i].sc_txb) &&
235 (tm_br == baud_rate_table[i].tm_br)) {
236 return(i);
237 }
238 }
239
240 return(-1);
241 }
242
243 cyg_int32
244 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
245 set_baud_rate(cyg_uint32 baud_rate)
246 {
247 cyg_int32 old_baud_rate;
248 cyg_uint16 sc_icr;
249
250 if (baud_rate > (sizeof(baud_rate_table) / sizeof(struct baud_rate))) {
251 return -1;
252 }
253
254 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
255 mutex.lock();
256 #endif
257
258 /*
259 * Flush the write queue.
260 * Not necessary for the read queue
261 */
262 this->io_write_flush();
263
264 /* Get the old baud rate */
265 if ((old_baud_rate = this->get_baud_rate()) < 0)
266 old_baud_rate = 0;
267
268 /* Turn off read and write */
269 sc_icr = *CYG_DEVICE_SERIAL_RS232_CR;
270 *CYG_DEVICE_SERIAL_RS232_CR = sc_icr & 0x3fff;
271
272 /* Turn off timer 2 */
273 *TIMER2_MD = 0x00;
274
275 *CYG_DEVICE_SERIAL_RS232_TR = baud_rate_table[baud_rate].sc_txb;
276 *TIMER2_BR = baud_rate_table[baud_rate].tm_br;
277
278 /* Reenable timer and serial port for valid baud rates greater than 0 */
279 if (baud_rate_table[baud_rate].sc_txb && baud_rate_table[baud_rate].tm_br) {
280 *TIMER2_MD = 0x80;
281 *CYG_DEVICE_SERIAL_RS232_CR = sc_icr | 0xc000;
282 }
283
284 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
285 mutex.unlock();
286 #endif
287
288 return(old_baud_rate);
289
290 }
291
292 // ------------------------------------------------------------------------
293 // Line mode
294
295 cyg_int32
296 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
297 get_line_mode()
298 {
299 cyg_uint16 sc_icr;
300 cyg_int32 ret;
301
302 sc_icr = *CYG_DEVICE_SERIAL_RS232_CR;
303
304 /* bits per byte */
305 if (sc_icr & 0x0080) {
306 ret = CS8;
307 } else {
308 ret = CS7;
309 }
310 /* Stop bits */
311 if (sc_icr & 0x0008) {
312 ret |= CSTOPB;
313 }
314 /* Parity */
315 switch (sc_icr & 0x0070) {
316 case 0x0000: /* No parity */
317 break;
318 case 0x0070: /* Odd parity */
319 ret |= PARODD;
320 /* Fall through */
321 case 0x0060: /* Even parity */
322 ret |= PARENB;
323 break;
324 default:
325 ret = -1;
326 break;
327 }
328
329 return ret;
330 }
331
332 cyg_int32
333 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
334 set_line_mode(cyg_uint32 line_mode)
335 {
336 cyg_int32 old_line_mode;
337 cyg_uint16 sc_icr;
338
339 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
340 mutex.lock();
341 #endif
342 /*
343 * Flush the write queue.
344 * Not necessary for the read queue
345 */
346 this->io_write_flush();
347
348 sc_icr = *CYG_DEVICE_SERIAL_RS232_CR;
349
350 old_line_mode = this->get_line_mode();
351
352 switch(line_mode & CSIZE) {
353 case CS7:
354 sc_icr &= ~0x0080;
355 break;
356 case CS8:
357 sc_icr |= 0x0080;
358 break;
359 default:
360 return -1;
361 break;
362 }
363 if (line_mode & CSTOPB) {
364 sc_icr |= 0x0008;
365 } else {
366 sc_icr &= ~0x0008;
367 }
368 if (line_mode & PARENB) {
369 if (!(line_mode & PARODD)) {
370 sc_icr &= ~0x0010;
371 sc_icr |= 0x0060;
372 } else {
373 sc_icr |= 0x0070;
374 }
375 } else {
376 sc_icr &= ~0x0070;
377 }
378
379 /* Set the new flags all in one write. */
380 *CYG_DEVICE_SERIAL_RS232_CR = sc_icr;
381
382 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
383 mutex.unlock();
384 #endif
385
386 return old_line_mode;
387
388 }
389
390 // ------------------------------------------------------------------------
391 // set_read_mode()
392 // Set the read mode (CRNL translation, EOL detection, escape characters)
393 // Currently there are only two modes (BINARY and ASCII)
394
395 #ifdef CYG_DEVICE_SERIAL_RS232_READ_MODES
396
397 cyg_int32
398 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
399 set_read_mode(cyg_uint32 new_mode)
400 {
401 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
402 mutex.lock();
403 #endif
404 if (new_mode) {
405 read_mode = 0xff;
406 } else {
407 read_mode = 0;
408 }
409 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
410 mutex.unlock();
411 #endif
412 return 0;
413 }
414
415 cyg_int32
416 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
417 set_read_data(cyg_uint32 mode, const char * data, cyg_uint32 count)
418 {
419 cyg_int32 ret = 0;
420
421 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
422 mutex.lock();
423 #endif
424
425 // SHould turn off interrupts
426 switch(mode) {
427 case CYG_DEVICE_SERIAL_RS232_READ_MODE_EOB:
428 if (data == NULL) {
429 read_mode_eob_count = sizeof(eob_chars);
430 read_mode_eob_chars = eob_chars;
431 } else {
432 read_mode_eob_count = count;
433 read_mode_eob_chars = data;
434 }
435 break;
436 default:
437 ret = -1;
438 break;
439 }
440 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
441 mutex.unlock();
442 #endif
443 return 0;
444 }
445
446 #endif
447
448 static inline void
449 throttle(char ch)
450 {
451 #ifdef CYG_DEVICE_SERIAL_RS232_FLOW_CONTROL
452 cyg_uint8 tmp;
453
454 tmp = (data->read_throttle_free + 1) % data->read_throttle_size;
455 /* Check that there is space to put the character */
456 if (tmp != data->read_throttle_queued) {
457 data->read_throttle_buffer[tmp] = ch;
458 data->read_throttle_free = tmp;
459 }
460 data->read_throttle = 1;
461 #endif
462 }
463
464 // ------------------------------------------------------------------------
465 // read_isr()
466 //
467 cyg_uint32
468 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
469 read_isr(cyg_vector vector, CYG_ADDRWORD isr_data)
470 {
471 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2 * data =
472 (CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2 *)isr_data;
473 volatile cyg_uint8 * tty_rx, ch;
474 cyg_uint32 off, ret;
475 cyg_uint8 eob = 0;
476
477 // Default return value
478 ret = Cyg_Interrupt::HANDLED;
479
480 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
481 // Clear interrupts regardless of kmode
482 data->read_interrupt.acknowledge_interrupt(vector);
483 #endif
484
485 tty_rx = CYG_DEVICE_SERIAL_RS232_RXR;
486 ch = *tty_rx;
487
488 #ifdef CYG_DEVICE_SERIAL_RS232_READ_MODES
489 while (data->read_mode) {
490 cyg_ucount8 i;
491
492 // On escape characters, skip mode checks; break
493 // Deal with flow control characters; return
494
495 /* Deal with ignored characters first */
496 if (data->read_mode & CYG_DEVICE_SERIAL_RS232_READ_MODE_IGN) {
497 if (ch == 10)
498 return ret;
499 }
500 /* Translate characters before checking on EOB conditions. */
501 if (data->read_mode & CYG_DEVICE_SERIAL_RS232_READ_MODE_TRN) {
502 if (ch == 13)
503 ch = 10;
504 }
505 /* Return a not full IORB on an EOB condition. */
506 if (data->read_mode & CYG_DEVICE_SERIAL_RS232_READ_MODE_EOB) {
507 for (i = 0; i < data->read_mode_eob_count; i++) {
508 if (ch == data->read_mode_eob_chars[i]) {
509 eob = 1;
510 break;
511 }
512 }
513 }
514 break;
515 }
516 #endif
517
518 #ifdef CYG_DEVICE_SERIAL_RS232_FLOW_CONTROL
519 if (read_throttle == 0) {
520 #endif
521
522 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
523 if (data->read_buffer == NULL) {
524 while ((data->read_buffer = data->read_buffers.get_next_inuse(data->read_buffer))) {
525 if (data->read_buffer->xferred_length < data->read_buffer->buffer_length) {
526 ret = Cyg_Interrupt::CALL_DSR;
527 break;
528 }
529 }
530 if (data->read_buffer == NULL) {
531 ret = Cyg_Interrupt::CALL_DSR;
532 throttle(ch);
533 return ret;
534 }
535 }
536 #endif
537
538 off = data->read_buffer->xferred_length++;
539 *((char *)data->read_buffer->buffer + off) = ch;
540
541 // This is still ugly --proven 19980526
542 if ((data->read_buffer->xferred_length == data->read_buffer->buffer_length) || eob) {
543 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
544 data->read_buffer = data->read_buffers.get_next_inuse(data->read_buffer);
545 #else
546 data->read_buffer = NULL;
547 #endif
548 ret = Cyg_Interrupt::CALL_DSR;
549 }
550
551 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
552 while ((data->read_buffer != NULL) &&
553 (data->read_buffer->xferred_length == data->read_buffer->buffer_length)) {
554 data->read_buffer = data->read_buffers.get_next_inuse(data->read_buffer);
555 ret = Cyg_Interrupt::CALL_DSR; // Probably not necessary
556 }
557 #endif
558
559 #ifdef CYG_DEVICE_SERIAL_RS232_FLOW_CONTROL
560 } else {
561 throttle(ch);
562 }
563 #endif
564
565 return ret;
566
567 }
568
569 void
570 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
571 read_dsr(cyg_vector vector, cyg_ucount32 dsr_count, CYG_ADDRWORD dsr_data)
572 {
573 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
574 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2 * data =
575 (CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2 *)dsr_data;
576 cyg_ucount32 count, i;
577 Cyg_IORB * iorb;
578
579 /*
580 * Note: Interrupts are not disabled but if the isr causes another
581 * buffer to become done since the start of this call then
582 * dsr_read() will be called again to handle that buffer.
583 */
584
585 for (i = 0, count = data->read_buffers.min_done(); i < count; i++) {
586 iorb = data->read_buffers.dequeue();
587 if (iorb->callback)
588 iorb->callback(iorb);
589 }
590
591 #ifdef CYG_DEVICE_SERIAL_RS232_WRITE_BUFFERS_LL
592 // Enqueue as many iorbs as we dequeued
593 for (i = 0; i < count; i++) {
594 if ((iorb = data->read_buffers_ll_first)) {
595 data->read_buffers_ll_first = iorb->next;
596 data->read_buffers.enqueue (iorb);
597 iorb->next = NULL;
598 } else {
599 break;
600 }
601 }
602 #endif
603 #endif
604 }
605
606 cyg_int32
607 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::io_read(Cyg_IORB * iorb)
608 {
609 volatile cyg_uint8 * tty_status = CYG_DEVICE_SERIAL_RS232_SR;
610 const cyg_vector vector = CYG_DEVICE_SERIAL_RS232_RVEC;
611
612 iorb->next = NULL;
613 iorb->xferred_length = 0;
614 iorb->status = CYG_IORB_OK;
615
616 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
617 #ifdef CYG_DEVICE_SERIAL_RS232_READ_BUFFERS_LL
618 /*
619 * If more iorbs are be queued than the queuet can handle then
620 * a separate link list needs to hold the extra. Since the DSR
621 * does the dequeueing from the link list we have to enqueue
622 * with the scheduler disabled.
623 *
624 * Note: To prevent lots of scheduler locks and unlocks we check
625 * the queue while the scheduler is unlocked, and only if it is
626 * full do we lock the scheduler and verify that the queue is
627 * still full. It is possible that between the check and the lock
628 * that the DSR could run and make some space in the queue.
629 *
630 * Note: We cannot have any iorbs on the ll if the queue is not full.
631 *
632 * Note: We cannot have a full queue and also be in polled mode.
633 * This is why we return after placing the iorb on the ll if the
634 * queue is full, as there is nothing else to do.
635 */
636 if (read_buffers.min_free() == 0) {
637
638 Cyg_Scheduler::lock();
639
640 // Check again with the scheduler locked
641 if (read_buffers.min_free() == 0) {
642 if (read_buffers_ll_first) {
643 read_buffers_ll_last->next = iorb;
644 } else {
645 read_buffers_ll_first = iorb;
646 }
647 read_buffers_ll_last = iorb;
648 Cyg_Scheduler::unlock();
649 return 0;
650 }
651 Cyg_Scheduler::unlock();
652 }
653
654 #endif
655
656 read_buffers.enqueue(iorb);
657
658 if (kmode == CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT) {
659 /* We may have to enable CTR here to tell the other side to start
660 * sending characters --proven 19980513 */
661 return 0;
662 }
663 #else
664 read_buffer = iorb;
665 #endif
666
667 #ifndef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
668 /*
669 * Special nonblocking mode for polled only drivers.
670 * This is so BSPs and other non kernel things can poll for each char.
671 * individually. Use only if read modes don't otherwise solve the problem.
672 */
673 if (CYG_IORB_NOBLOCK == iorb->opcode) {
674 if ((*tty_status & 0x10) != 0) {
675 read_isr(vector, (CYG_ADDRWORD)this);
676 }
677 return 0;
678 }
679 #endif
680
681 do {
682 do {
683 while ((*tty_status & 0x10) == 0) continue;
684 } while (read_isr(vector, (CYG_ADDRWORD)this) == Cyg_Interrupt::HANDLED);
685 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
686 read_dsr(vector, 0, (CYG_ADDRWORD)this);
687 #else
688
689 // Make a callback, even in poll-mode.
690
691 // This should really be done in read_dsr, but this requires
692 // the iorb to be passed along as an argument (or in
693 // read_buffer) which a) isn't pretty, b) would require other
694 // callers of read_dsr to know that fact. The read_dsr would
695 // extract the iorb and do the below. This fix seemed cleaner
696 // given that it is a short term solution anyway. -jskov
697
698 if (iorb->callback)
699 iorb->callback(iorb);
700
701 #endif
702 } while (read_buffer);
703 return 0;
704 }
705
706 // ------------------------------------------------------------------------
707 // set_write_mode()
708 // Set the write mode (CRNL translation)
709 // Currently there are only two modes (BINARY and ASCII)
710
711 #ifdef CYG_DEVICE_SERIAL_RS232_WRITE_MODES
712
713 cyg_int32
714 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
715 set_write_mode(cyg_uint32 new_mode)
716 {
717 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
718 mutex.lock();
719 #endif
720 write_mode = new_mode;
721 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
722 mutex.unlock();
723 #endif
724 return 0;
725 }
726
727 #endif
728
729 // ------------------------------------------------------------------------
730 // write_isr()
731 // We set the mn10300 to interrupt as soon as the transmission buffer is
732 // empty. this is before the transmission is completed though. For proper
733 // flush semantics the driver should switch to getting an interrupt for
734 // transmission completed then check if it has completed and if not
735 // return HANDLED. The next interrupt should then switch back.
736 // --proven 19980523
737 //
738
739 cyg_uint32
740 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
741 write_isr(cyg_vector vector, CYG_ADDRWORD isr_data)
742 {
743 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2 * data =
744 (CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2 *)isr_data;
745 volatile cyg_uint8 * tty_tx, ch;
746 cyg_uint32 off, ret;
747
748 // Default return value
749 ret = Cyg_Interrupt::HANDLED;
750
751 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
752 // Clear interrupts regardless of kmode
753 data->write_interrupt.acknowledge_interrupt(vector);
754
755 while ((data->write_buffer == NULL) ||
756 (data->write_buffer->xferred_length == data->write_buffer->buffer_length)) {
757 data->write_buffer = data->write_buffers.get_next_inuse(data->write_buffer);
758 ret = Cyg_Interrupt::CALL_DSR;
759 if (!data->write_buffer) {
760 return ret;
761 }
762 }
763 #else
764 if (data->write_buffer->xferred_length == data->write_buffer->buffer_length) {
765 ret = Cyg_Interrupt::CALL_DSR;
766 data->write_buffer = NULL;
767 return ret;
768 }
769 #endif
770
771 off = data->write_buffer->xferred_length++;
772
773 #ifdef CYG_DEVICE_SERIAL_RS232_WRITE_MODES
774 if (data->write_mode) {
775 // This is for cr to cr/lf conversion
776 if ((ch = data->write_char)) {
777 data->write_char = '\0';
778 } else {
779 if ((*((char *)data->write_buffer->buffer + off)) != '\n') {
780 ch = *((char *)data->write_buffer->buffer + off);
781 } else {
782 // Decrement so next pass will DTRT
783 data->write_buffer->xferred_length--;
784 data->write_char = '\n';
785 ch = '\r';
786 }
787 }
788 } else
789 #endif
790 ch = *((char *)data->write_buffer->buffer + off);
791
792 tty_tx = CYG_DEVICE_SERIAL_RS232_TXR;
793 *tty_tx = ch;
794 // Do not modify any data structure after the data is written because
795 // it is possible an interrupt will call this routine before this
796 // invocation of this routine executes any code beyond this point.
797 return ret;
798 }
799
800 void
801 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::
802 write_dsr(cyg_vector vector, cyg_ucount32 dsr_count, CYG_ADDRWORD dsr_data)
803 {
804 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
805 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2 * data =
806 (CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2 *)dsr_data;
807 cyg_ucount32 count, i;
808 Cyg_IORB * iorb;
809
810 /*
811 * Note: Interrupts are not disabled but if the isr causes another
812 * buffer to become done since the start of this call then
813 * dsr_write() will be called again to handle that buffer.
814 */
815
816 for (i = 0, count = data->write_buffers.min_done(); i < count; i++) {
817 iorb = data->write_buffers.dequeue();
818 if (iorb->callback)
819 iorb->callback(iorb);
820 }
821
822 #ifdef CYG_DEVICE_SERIAL_RS232_WRITE_BUFFERS_LL
823 // Enqueue as many iorbs as we dequeued
824 for (i = 0; i < count; i++) {
825 if ((iorb = data->write_buffers_ll_first)) {
826 data->write_buffers_ll_first = iorb->next;
827 data->write_buffers.enqueue (iorb);
828 iorb->next = NULL;
829 } else {
830 break;
831 }
832 }
833 #endif
834 #endif
835 }
836
837 cyg_int32
838 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::io_write(Cyg_IORB * iorb)
839 {
840 volatile CYG_DEVICE_SERIAL_RS232_SR_SIZE * tty_status = CYG_DEVICE_SERIAL_RS232_SR;
841 const cyg_vector vector = CYG_DEVICE_SERIAL_RS232_TVEC;
842
843 iorb->next = NULL;
844 iorb->xferred_length = 0;
845 iorb->status = CYG_IORB_OK;
846
847 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
848 #ifdef CYG_DEVICE_SERIAL_RS232_WRITE_BUFFERS_LL
849 /*
850 * If more iorbs are be queued than the queuet can handle then
851 * a separate link list needs to hold the extra. Since the DSR
852 * does the dequeueing from the link list we have to enqueue
853 * with the scheduler disabled.
854 *
855 * Note: To prevent lots of scheduler locks and unlocks we check
856 * the queue while the scheduler is unlocked, and only if it is
857 * full do we lock the scheduler and verify that the queue is
858 * still full. It is possible that between the check and the lock
859 * that the DSR could run and make some space in the queue.
860 *
861 * Note: We cannot have any iorbs on the ll if the queue is not full.
862 *
863 * Note: We cannot have a full queue and also be in polled mode.
864 * This is why we return after placing the iorb on the ll if the
865 * queue is full, as there is nothing else to do.
866 */
867 if (write_buffers.min_free() == 0) {
868
869 Cyg_Scheduler::lock();
870
871 // Check again with the scheduler locked
872 if (write_buffers.min_free() == 0) {
873 if (write_buffers_ll_first) {
874 write_buffers_ll_last->next = iorb;
875 } else {
876 write_buffers_ll_first = iorb;
877 }
878 write_buffers_ll_last = iorb;
879 Cyg_Scheduler::unlock();
880 return 0;
881 }
882 Cyg_Scheduler::unlock();
883 }
884
885 #endif
886
887 write_buffers.enqueue (iorb);
888 if (kmode == CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT) {
889 if (write_buffer == NULL) {
890 // Must check that iorb isn't already done --proven 19980516
891 if (iorb->buffer_length == 0) {
892 write_isr (vector, (CYG_ADDRWORD)this);
893 write_dsr (vector, 0, (CYG_ADDRWORD)this);
894 } else {
895 /* Prime serial write interrupts with first byte */
896 while ((*tty_status & 0x20) != 0) continue;
897 write_isr (vector, (CYG_ADDRWORD)this);
898 }
899 }
900 return 0;
901 }
902 #else
903 write_buffer = iorb;
904 #endif
905
906 do {
907 do {
908 while ((*tty_status & 0x20) != 0) continue;
909 } while (write_isr(vector, (CYG_ADDRWORD)this) == Cyg_Interrupt::HANDLED);
910 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
911 write_dsr (vector, 0, (CYG_ADDRWORD)this);
912 #else
913
914 // Make a callback, even in poll-mode.
915
916 // This should really be done in write_dsr, but this requires
917 // the iorb to be passed along as an argument (or in
918 // read_buffer) which a) isn't pretty, b) would require other
919 // callers of write_dsr to know that fact. The write_dsr would
920 // extract the iorb and do the below. This fix seemed cleaner
921 // given that it is a short term solution anyway. -jskov
922
923 if (iorb->callback)
924 iorb->callback(iorb);
925
926 #endif
927 } while (write_buffer);
928 return 0;
929 }
930
931 // ------------------------------------------------------------------------
932 // Asynchronous versions are only configured with the
933 // interrupt version is configured
934 //
935 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
936
937 cyg_int32
938 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::io_read_asynchronous(Cyg_IORB * iorb)
939 {
940 // Do we want to configure an error condition for this? --proven 19980506
941 CYG_ASSERT (kmode == CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT,
942 "Cannot do an io_read_asynchronous while in polled mode" );
943
944 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
945 mutex.lock();
946 #endif
947 this->io_read (iorb);
948 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
949 mutex.unlock();
950 #endif
951 return 0;
952
953 }
954
955 cyg_int32
956 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::io_write_asynchronous(Cyg_IORB * iorb)
957 {
958 // Do we want to configure an error condition for this? --proven 19980506
959 CYG_ASSERT (kmode == CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT,
960 "Cannot do an io_write_asynchronous while in polled mode" );
961
962 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
963 mutex.lock();
964 #endif
965 this->io_write (iorb);
966 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
967 mutex.unlock();
968 #endif
969 return 0;
970 }
971 #endif
972
973 // ------------------------------------------------------------------------
974 // Blocking versions just call the internal version with a callback.
975 //
976
977 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
978 static void
979 callback(Cyg_IORB *iorb)
980 {
981 Cyg_Binary_Semaphore * data = (Cyg_Binary_Semaphore *)iorb->callback_data;
982 data->post();
983 }
984 #endif
985
986 cyg_int32
987 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::io_read_blocking(Cyg_IORB * iorb)
988 {
989 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
990 mutex.lock();
991 #endif
992 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
993 if (kmode == CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT) {
994 Cyg_Binary_Semaphore read(0);
995
996 // We need a callback routine to wake us up
997 iorb->callback_data = (CYG_ADDRESS)&read;
998 iorb->callback = callback;
999 this->io_read(iorb);
1000 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
1001 mutex.unlock();
1002 #endif
1003 read.wait();
1004 return 0;
1005 } else
1006 #endif
1007 {
1008 iorb->callback = NULL;
1009 this->io_read(iorb);
1010 }
1011 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
1012 mutex.unlock();
1013 #endif
1014 return 0;
1015 }
1016
1017 cyg_int32
1018 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::io_write_blocking(Cyg_IORB * iorb)
1019 {
1020 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
1021 mutex.lock();
1022 #endif
1023 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
1024 if (kmode == CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT) {
1025 Cyg_Binary_Semaphore write(0);
1026
1027 // We need a callback routine to wake us up
1028 iorb->callback_data = (CYG_ADDRESS)&write;
1029 iorb->callback = callback;
1030 this->io_write(iorb);
1031 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
1032 mutex.unlock();
1033 #endif
1034 write.wait();
1035 return 0;
1036 } else
1037 #endif
1038 {
1039 iorb->callback = NULL;
1040 this->io_write(iorb);
1041 }
1042 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
1043 mutex.unlock();
1044 #endif
1045 return 0;
1046 }
1047
1048 // Internal routine needed to flush writes in a blocking manner.
1049 void
1050 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::io_write_flush(void)
1051 {
1052 Cyg_IORB iorb;
1053
1054 iorb.buffer_length = 0;
1055 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
1056 if (kmode == CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT) {
1057 Cyg_Binary_Semaphore write(0);
1058
1059 // We need a callback routine to wake us up
1060 iorb.callback_data = (CYG_ADDRESS)&write;
1061 iorb.callback = callback;
1062 this->io_write(&iorb);
1063 write.wait();
1064 } else
1065 #endif
1066 {
1067 iorb.callback = NULL;
1068 this->io_write(&iorb);
1069 }
1070 }
1071
1072 // ------------------------------------------------------------------------
1073 // Cancel routines to stop an existing IO operation
1074 //
1075
1076 cyg_int32
1077 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::io_read_cancel(Cyg_IORB * iorb)
1078 {
1079 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
1080 mutex.lock();
1081 #endif
1082 Cyg_Scheduler::lock();
1083 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
1084 read_interrupt.disable_interrupts();
1085 #endif
1086
1087 // For now only allow the current iorb to be cancelable
1088 // --proven 19980714
1089
1090 if (read_buffer == NULL) {
1091 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
1092 if ((read_buffer = read_buffers.get_next_inuse(read_buffer)) == NULL)
1093 #endif
1094 {
1095 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
1096 read_interrupt.enable_interrupts();
1097 #endif
1098 Cyg_Scheduler::unlock();
1099 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
1100 mutex.unlock();
1101 #endif
1102 return 0;
1103 }
1104 }
1105 if (((iorb == NULL) && read_buffer) ||
1106 (iorb && (read_buffer == iorb))) {
1107 read_buffer->status = CYG_IORB_CANCELED;
1108 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
1109 read_buffer = read_buffers.get_next_inuse(read_buffer);
1110 #endif
1111 // Need to clear out any flush iorbs -- proven 19980714
1112 } else {
1113 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
1114 read_interrupt.enable_interrupts();
1115 #endif
1116 Cyg_Scheduler::unlock();
1117 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
1118 mutex.unlock();
1119 #endif
1120 return 0;
1121 }
1122
1123 #ifdef CYG_DEVICE_SERIAL_RS232_KMODE_INTERRUPT
1124 read_interrupt.enable_interrupts();
1125 #endif
1126 read_dsr(CYG_DEVICE_SERIAL_RS232_RVEC, 0, (CYG_ADDRWORD)this);
1127 Cyg_Scheduler::unlock();
1128 #ifdef CYG_DEVICE_SERIAL_RS232_MUTEX
1129 mutex.unlock();
1130 #endif
1131 return 0;
1132 }
1133
1134 // ------------------------------------------------------------------------
1135 // Assert versions. These versions bypass most of the driver code.
1136 // These are to be used by the BSP or asserts. Only use them once
1137 // start_sync() is called and when done normal operations is
1138 // restarted with the end_sync() mode.
1139 //
1140 // Note DO NOT DO LOCKING IN THIS ROUTINE!!!
1141 //
1142
1143 #ifdef CYG_DEVICE_SERIAL_RS232_MN10300_2_KMODE_ASSERT
1144 cyg_int32
1145 CYG_CLASS_DEVICE_SERIAL_RS232_MN10300_2::io_write_assert(Cyg_IORB * iorb)
1146 {
1147 volatile cyg_uint8 * tty_status = CYG_DEVICE_SERIAL_RS232_SR;
1148 volatile cyg_uint8 * tty_tx = CYG_DEVICE_SERIAL_RS232_TXR;
1149 cyg_uint8 ch;
1150
1151 iorb->xferred_length = 0;
1152 while (iorb->xferred_length < iorb->buffer_length) {
1153 if ((ch = (*((char *)iorb->buffer + iorb->xferred_length++))) == '\n') {
1154 while ((*tty_status & 0x20) != 0) continue;
1155 *tty_tx = '\r';
1156 }
1157 while ((*tty_status & 0x20) != 0) continue;
1158 *tty_tx = ch;
1159 }
1160 return 0;
1161 }
1162
1163 #endif // #ifdef CYG_DEVICE_SERIAL_RS232_MN10300_2_KMODE_ASSERT
1164
1165 #endif // #ifdef CYGPKG_DEVICES_SERIAL_RS232_MN10300_2
1166 // EOF serial_mn10300_2.cxx