source: rtems/c/src/lib/libbsp/m68k/gen68340/console/console.c @ 9b4422a2

4.115
Last change on this file since 9b4422a2 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 15:09:24

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

  • Property mode set to 100644
File size: 19.3 KB
Line 
1/*
2 *  68340/68349 console serial I/O.
3 *
4 *  Author:
5 *  Geoffroy Montel
6 *  France Telecom - CNET/DSM/TAM/CAT
7 *  4, rue du Clos Courtel
8 *  35512 CESSON-SEVIGNE
9 *  FRANCE
10 *
11 *  e-mail: g_montel@yahoo.com
12 *
13 *  COPYRIGHT (c) 1989-1999.
14 *  On-Line Applications Research Corporation (OAR).
15 *
16 *  The license and distribution terms for this file may be
17 *  found in the file LICENSE in this distribution or at
18 *  http://www.rtems.com/license/LICENSE.
19 */
20
21#include <termios.h>
22#include <bsp.h>
23#include <rtems/libio.h>
24#include <m68340.h>
25#include <m340uart.h>
26#include <m340timer.h>
27
28#include <stdarg.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <rtems/termiostypes.h>
32
33#define CONSOLE_VECTOR 121
34#define CONSOLE_IRQ_LEVEL 3
35#define CONSOLE_INTERRUPT_ARBITRATION 2
36
37static void *ttypA;             /* to remember which tty has been opened on channel A
38                                   used when interrupts are enabled */
39
40static void *ttypB;             /* to remember which tty has been opened on channel B
41                                   used when interrupts are enabled */
42
43unsigned char DUIER_mirror = 0 ;  /* reflects the state of IER register, which is Write Only */
44unsigned char Error_Status_A = 0; /* error status on Channel A */
45unsigned char Error_Status_B = 0; /* error status on Channel A */
46
47/*
48 * Device-specific routines
49 */
50
51#define USE_INTERRUPTS_A (m340_uart_config[UART_CHANNEL_A].mode==UART_INTERRUPTS)
52#define USE_INTERRUPTS_B (m340_uart_config[UART_CHANNEL_B].mode==UART_INTERRUPTS)
53#define CHANNEL_ENABLED_A m340_uart_config[UART_CHANNEL_A].enable
54#define CHANNEL_ENABLED_B m340_uart_config[UART_CHANNEL_B].enable
55
56#define set_DUIER(a) DUIER_mirror |= (a); DUIER = DUIER_mirror
57#define unset_DUIER(a) DUIER_mirror &= ~(a); DUIER = DUIER_mirror
58
59#define Enable_Interrupts_Tx_A if (USE_INTERRUPTS_A) set_DUIER(m340_TxRDYA)
60#define Disable_Interrupts_Tx_A if (USE_INTERRUPTS_A) unset_DUIER(m340_TxRDYA)
61
62#define Enable_Interrupts_Tx_B if (USE_INTERRUPTS_B) set_DUIER(m340_TxRDYB)
63#define Disable_Interrupts_Tx_B if (USE_INTERRUPTS_B) unset_DUIER(m340_TxRDYB)
64
65/******************************************************
66  Name: InterruptHandler
67  Input parameters: vector number
68  Output parameters: -
69  Description: UART ISR Routine, called by _RTEMS_ISR
70 *****************************************************/
71rtems_isr
72InterruptHandler (rtems_vector_number v)
73{
74 char ch;
75
76 /*****************************************************************************
77 **                             CHANNEL A                                    **
78 *****************************************************************************/
79
80    /* check Received Break*/
81    if (DUSRA & m340_RB) {
82       Error_Status_A |= m340_RB;
83       /* reset error status */
84       DUCRA = m340_Reset_Error_Status;
85    }
86
87    /* buffer received ? */
88    if (DUSRA & m340_Rx_RDY) {
89       do {
90           /* error encountered? */
91           if (DUSRA & (m340_OE | m340_PE | m340_FE | m340_RB)) {
92              Error_Status_A |= DUSRA;
93              /* reset error status */
94              DUCRA = m340_Reset_Error_Status;
95              /* all the characters in the queue may not be good */
96              while (DUSRA & m340_Rx_RDY)
97                    /* push them in a trash */
98                    ch = DURBA;
99           }
100           else {
101                 /* this is necessary, otherwise it blocks when FIFO is full */
102                 ch = DURBA;
103                 rtems_termios_enqueue_raw_characters(ttypA,&ch,1);
104           }
105       } while (DUSRA & m340_Rx_RDY);
106       Restart_Fifo_Full_A_Timer();     /* only if necessary (pointer to a fake function if
107                                           not in FIFO full mode) */
108    }
109
110    else /* if no character has been received */
111       Restart_Check_A_Timer();         /* same remark */
112
113    /* ready to accept a character ? */
114    if (DUISR & DUIER_mirror & m340_TxRDYA) {
115        Disable_Interrupts_Tx_A;
116        /* one character has been transmitted */
117        rtems_termios_dequeue_characters(ttypA,1);
118    }
119
120 /*****************************************************************************
121 **                             CHANNEL B                                    **
122 *****************************************************************************/
123
124    /* check Received Break*/
125    if (DUSRB & m340_RB) {
126       Error_Status_B |= m340_RB;
127       /* reset error status */
128       DUCRB = m340_Reset_Error_Status;
129    }
130
131    /* buffer received ? */
132    if (DUSRB & m340_Rx_RDY) {
133       do {
134           if (DUSRB & (m340_OE | m340_PE | m340_FE | m340_RB)) {
135              Error_Status_B |= DUSRB;
136              /* reset error status */
137              DUCRB = m340_Reset_Error_Status;
138              /* all the characters in the queue may not be good */
139              while (DUSRB & m340_Rx_RDY)
140                    /* push them in a trash */
141                    ch = DURBB;
142           }
143           else {
144                 ch = DURBB;
145                 rtems_termios_enqueue_raw_characters(ttypB,&ch,1);
146           }
147
148       } while (DUSRB & m340_Rx_RDY);
149       Restart_Fifo_Full_B_Timer();
150    }
151    else /* if no character has been received */
152       Restart_Check_B_Timer();
153
154    /* ready to accept a character ? */
155    if (DUISR & DUIER_mirror & m340_TxRDYB) {
156        Disable_Interrupts_Tx_B;
157        /* one character has been transmitted */
158        rtems_termios_dequeue_characters(ttypB,1);
159    }
160}
161
162/******************************************************
163  Name: InterruptWrite
164  Input parameters: minor = channel, pointer to buffer,
165                    and length of buffer to transmit
166  Output parameters: -
167  Description: write the first character of buf only
168               may be called by either console_write
169               or rtems_termios_enqueue_raw_characters
170 *****************************************************/
171static ssize_t
172InterruptWrite (int minor, const char *buf, size_t len)
173{
174 if (minor==UART_CHANNEL_A) {
175    if (len>0) DUTBA=*buf;
176    Enable_Interrupts_Tx_A;
177 }
178 else if (minor==UART_CHANNEL_B) {
179    if (len>0) DUTBB=*buf;
180    Enable_Interrupts_Tx_B;
181 }
182 return 0;
183}
184
185/******************************************************
186  Name: dbug_out_char
187  Input parameters: channel, character to emit
188  Output parameters: -
189  Description: wait for the UART to be ready to emit
190               a character and send it
191 *****************************************************/
192void dbug_out_char( int minor, int ch )
193{
194 if (minor==UART_CHANNEL_A) {
195    while (!(DUSRA & m340_Tx_RDY)) continue;
196    DUTBA=ch;
197 }
198 else if (minor==UART_CHANNEL_B) {
199    while (!(DUSRB & m340_Tx_RDY)) continue;
200    DUTBB=ch;
201 }
202}
203
204/******************************************************
205  Name: dbug_in_char
206  Input parameters: -
207  Output parameters: received character
208  Description: return the character in the UART
209 *****************************************************/
210int dbug_in_char( int minor )
211{
212 if (minor==UART_CHANNEL_A) {
213    return DURBA;
214 }
215 else if (minor==UART_CHANNEL_B) {
216    return DURBB;
217 }
218 return 0;
219}
220
221/******************************************************
222  Name: dbug_char_present
223  Input parameters: channel #
224  Output parameters: TRUE or FALSE
225  Description: return whether there's a character
226               in the receive buffer
227 *****************************************************/
228int dbug_char_present( int minor )
229{
230 if (minor==UART_CHANNEL_A) {
231    return (DUSRA & m340_Rx_RDY);
232 }
233 else if (minor==UART_CHANNEL_B) {
234    return (DUSRB & m340_Rx_RDY);
235 }
236 return 0;
237}
238
239/******************************************************
240  Name: dbugInitialise
241  Input parameters: -
242  Output parameters: -
243  Description: Init the UART
244 *****************************************************/
245static void
246dbugInitialise (void)
247{
248     t_baud_speed_table uart_config;            /* configuration of UARTS */
249
250     /*
251      * Reset Receiver
252      */
253     DUCRA = m340_Reset_Receiver;
254     DUCRB = m340_Reset_Receiver;
255
256     /*
257      * Reset Transmitter
258      */
259     DUCRA = m340_Reset_Transmitter;
260     DUCRB = m340_Reset_Transmitter;
261
262     /*
263      * Enable serial module for normal operation, ignore FREEZE, select the crystal clock,
264      * supervisor/user serial registers unrestricted
265      * interrupt arbitration at priority CONSOLE_INTERRUPT_ARBITRATION
266      * WARNING : 8 bits access only on this UART!
267      */
268     DUMCRH = 0x00;
269     DUMCRL = CONSOLE_INTERRUPT_ARBITRATION;
270
271     /*
272      * Interrupt level register
273      */
274     DUILR = CONSOLE_IRQ_LEVEL;
275
276     /* sets the IVR */
277     DUIVR = CONSOLE_VECTOR;
278
279     /* search for a correct m340 uart configuration */
280     uart_config = Find_Right_m340_UART_Config(m340_uart_config[UART_CHANNEL_A].rx_baudrate,
281                                               m340_uart_config[UART_CHANNEL_A].tx_baudrate,
282                                               CHANNEL_ENABLED_A,
283                                               m340_uart_config[UART_CHANNEL_B].rx_baudrate,
284                                               m340_uart_config[UART_CHANNEL_B].tx_baudrate,
285                                               CHANNEL_ENABLED_B);
286
287     /*****************************************************************************
288     **                         CHANNEL A                                        **
289     *****************************************************************************/
290     if (CHANNEL_ENABLED_A) {
291
292        if (USE_INTERRUPTS_A) {
293           rtems_isr_entry old_handler;
294           rtems_status_code sc;
295
296           sc = rtems_interrupt_catch (InterruptHandler,
297                                       CONSOLE_VECTOR,
298                                       &old_handler);
299
300           /* uncomment this if you want to pass control to your own ISR handler
301              it may be usefull to do so to check for performances with an oscilloscope */
302           /*
303           {
304            proc_ptr ignored;
305            _CPU_ISR_install_raw_handler( CONSOLE_VECTOR, _Debug_ISR_Handler_Console, &ignored );
306           }
307           */
308
309           /*
310            * Interrupt Enable Register
311            * Enable Interrupts on Channel A Receiver Ready
312            */
313           set_DUIER(m340_RxRDYA);
314        }
315        else {
316                /*
317                 * Disable Interrupts on channel A
318                 */
319                unset_DUIER(m340_RxRDYA&m340_TxRDYA);
320        }
321
322        /*
323         * Change set of baud speeds
324         * disable input control
325         */
326        /* no good uart configuration ? */
327        if (uart_config.nb<1) rtems_fatal_error_occurred (-1);
328
329        if (uart_config.baud_speed_table[UART_CHANNEL_A].set==1)
330           DUACR = m340_BRG_Set1;
331        else
332           DUACR = m340_BRG_Set2;
333
334        /*
335         * make OPCR an auxiliary function serving the communication channels
336         */
337        DUOPCR = m340_OPCR_Aux;
338
339        /* poll the XTAL_RDY bit until it is cleared to ensure that an unstable crystal
340           input is not applied to the baud rate generator */
341        while (DUISR & m340_XTAL_RDY) continue;
342
343        /*
344         * Serial Channel Baud Speed
345         */
346        DUCSRA = (uart_config.baud_speed_table[UART_CHANNEL_A].rcs << 4)
347               | (uart_config.baud_speed_table[UART_CHANNEL_A].tcs);
348
349        /*
350         * Serial Channel Configuration
351         */
352        DUMR1A = m340_uart_config[UART_CHANNEL_A].parity_mode
353               | m340_uart_config[UART_CHANNEL_A].bits_per_char
354               | m340_RxRTS;
355
356        if (m340_uart_config[UART_CHANNEL_A].rx_mode==UART_FIFO_FULL) DUMR1A |= m340_R_F | m340_ERR;
357
358        /*
359         * Serial Channel Configuration 2
360         */
361        DUMR2A |= m340_normal;
362
363        /*
364         * Enable Channel A: transmitter and receiver
365         */
366        DUCRA = m340_Transmitter_Enable | m340_Receiver_Enable;
367     } /* channel A enabled */
368
369     /*****************************************************************************
370     **                         CHANNEL B                                        **
371     *****************************************************************************/
372     if (CHANNEL_ENABLED_B) {
373
374        /* we mustn't set the console vector twice! */
375        if ((USE_INTERRUPTS_B && !(CHANNEL_ENABLED_A))
376           || (USE_INTERRUPTS_B && CHANNEL_ENABLED_A && !USE_INTERRUPTS_A)) {
377           rtems_isr_entry old_handler;
378           rtems_status_code sc;
379
380           sc = rtems_interrupt_catch (InterruptHandler,
381                                       CONSOLE_VECTOR,
382                                       &old_handler);
383
384           /* uncomment this if you want to pass control to your own ISR handler
385              it may be usefull to do so to check for performances with an oscilloscope */
386           /*
387           {
388            proc_ptr ignored;
389            _CPU_ISR_install_raw_handler( CONSOLE_VECTOR, _Debug_ISR_Handler_Console, &ignored );
390           }
391           */
392
393           /*
394            * Interrupt Enable Register
395            * Enable Interrupts on Channel A Receiver Ready
396            */
397           set_DUIER(m340_RxRDYB);
398        }
399        else {
400                /*
401                 * Disable Interrupts on channel B
402                 */
403                unset_DUIER(m340_RxRDYB&m340_TxRDYB);
404        }
405
406        /*
407         * Change set of baud speeds
408         * disable input control
409         */
410
411        /* no good uart configuration ? */
412        if (uart_config.nb<2) rtems_fatal_error_occurred (-1);
413
414        /* don't set DUACR twice! */
415        if (!CHANNEL_ENABLED_A) {
416           if (uart_config.baud_speed_table[UART_CHANNEL_B].set==1)
417              DUACR = m340_BRG_Set1;
418           else
419              DUACR = m340_BRG_Set2;
420        }
421
422        /*
423         * make OPCR an auxiliary function serving the communication channels
424         */
425        if (!CHANNEL_ENABLED_A) DUOPCR = m340_OPCR_Aux;
426
427        /* poll the XTAL_RDY bit until it is cleared to ensure that an unstable crystal
428           input is not applied to the baud rate generator */
429        while (DUISR & m340_XTAL_RDY) continue;
430
431        /*
432         * Serial Channel Baud Speed
433         */
434        DUCSRB = (uart_config.baud_speed_table[UART_CHANNEL_B].rcs << 4)
435               | (uart_config.baud_speed_table[UART_CHANNEL_B].tcs);
436
437        /*
438         * Serial Channel Configuration
439         */
440        DUMR1B = m340_uart_config[UART_CHANNEL_B].parity_mode
441               | m340_uart_config[UART_CHANNEL_B].bits_per_char
442               | m340_RxRTS;
443
444        if (m340_uart_config[UART_CHANNEL_B].rx_mode==UART_FIFO_FULL) DUMR1B |= m340_R_F | m340_ERR;
445
446        /*
447         * Serial Channel Configuration 2
448         */
449        DUMR2B |= m340_normal;
450
451        /*
452         * Enable Channel A: transmitter and receiver
453         */
454        DUCRB = m340_Transmitter_Enable | m340_Receiver_Enable;
455     } /* channel B enabled */
456}
457
458/******************************************************
459  Name: SetAttributes
460  Input parameters: termios structure, channel
461  Output parameters: -
462  Description: return whether there's a character
463               in the receive buffer
464  TO DO: add the channel # to check for!!
465 *****************************************************/
466static int
467SetAttributes (int minor, const struct termios *t)
468{
469 rtems_interrupt_level level;
470 float ispeed, ospeed;
471 int isp, osp;
472
473 /* output speed */
474 if (t->c_cflag & CBAUDEX)
475    osp = (t->c_cflag & CBAUD) + CBAUD + 1;
476 else
477    osp = t->c_cflag & CBAUD;
478
479 /* input speed */
480 isp = (t->c_cflag / (CIBAUD / CBAUD)) &  CBAUD;
481
482 /* convert it */
483 ispeed = rtems_termios_baud_to_number(isp);
484 ospeed = rtems_termios_baud_to_number(osp);
485
486 if (ispeed || ospeed) {
487       /* update config table */
488       m340_uart_config[UART_CHANNEL_A].rx_baudrate = ((minor==UART_CHANNEL_A)&&(ispeed!=0)) ? ispeed  : m340_uart_config[UART_CHANNEL_A].rx_baudrate;
489       m340_uart_config[UART_CHANNEL_A].tx_baudrate = ((minor==UART_CHANNEL_A)&&(ospeed!=0)) ? ospeed  : m340_uart_config[UART_CHANNEL_A].tx_baudrate;
490       m340_uart_config[UART_CHANNEL_B].rx_baudrate = ((minor==UART_CHANNEL_B)&&(ispeed!=0)) ? ispeed  : m340_uart_config[UART_CHANNEL_B].rx_baudrate;
491       m340_uart_config[UART_CHANNEL_B].tx_baudrate = ((minor==UART_CHANNEL_B)&&(ospeed!=0)) ? ospeed  : m340_uart_config[UART_CHANNEL_B].tx_baudrate;
492 }
493
494 /* change parity */
495 if (t->c_cflag & PARENB) {
496    if (t->c_cflag & PARODD) m340_uart_config[minor].parity_mode = m340_Odd_Parity;
497    else m340_uart_config[minor].parity_mode = m340_Even_Parity;
498 }
499
500 /* change bits per character */
501 if (t->c_cflag & CSIZE) {
502    switch (t->c_cflag & CSIZE) {
503        default:        break;
504        case CS5:       m340_uart_config[minor].bits_per_char = m340_5bpc;      break;
505        case CS6:       m340_uart_config[minor].bits_per_char = m340_6bpc;      break;
506        case CS7:       m340_uart_config[minor].bits_per_char = m340_7bpc;      break;
507        case CS8:       m340_uart_config[minor].bits_per_char = m340_8bpc;      break;
508    }
509 }
510
511 /* if serial module configuration has been changed */
512 if (t->c_cflag & (CBAUD | CIBAUD | CSIZE | PARENB)) {
513    rtems_interrupt_disable(level);
514    /* reinit the UART */
515    dbugInitialise();
516    rtems_interrupt_enable (level);
517 }
518
519 return 0;
520}
521
522/******************************************************
523  Name: console_initialize
524  Input parameters: MAJOR # of console_driver,
525                    minor is always 0,
526                    args are always NULL
527  Output parameters: -
528  Description: Reserve resources consumed by this driver
529  TODO: We should pass m340_uart_config table in arg
530 *****************************************************/
531rtems_device_driver console_initialize(
532  rtems_device_major_number  major,
533  rtems_device_minor_number  minor,
534  void                      *arg
535)
536{
537        rtems_status_code status;
538        int i;
539
540        /*
541         * Set up TERMIOS
542         */
543        rtems_termios_initialize ();
544
545        /*
546         * Do device-specific initialization
547         */
548        Init_UART_Table();
549        dbugInitialise ();
550        Fifo_Full_benchmark_timer_initialize();
551
552        /*
553         * Register the devices
554         */
555        for (i=0; i<UART_NUMBER_OF_CHANNELS; i++) {
556            if (m340_uart_config[i].enable) {
557                status = rtems_io_register_name (m340_uart_config[i].name, major, i);
558                if (status != RTEMS_SUCCESSFUL)
559                        rtems_fatal_error_occurred (status);
560            }
561        }
562
563        return RTEMS_SUCCESSFUL;
564}
565
566/******************************************************
567  Name: console_open
568  Input parameters: channel #, arg
569  Output parameters: -
570  Description: open the device
571 *****************************************************/
572rtems_device_driver console_open(
573  rtems_device_major_number major,
574  rtems_device_minor_number minor,
575  void                    * arg
576)
577{
578 rtems_status_code sc = 0;
579
580 static const rtems_termios_callbacks intrCallbacks = {
581                NULL,                   /* firstOpen */
582                NULL,                   /* lastClose */
583                NULL,                   /* pollRead */
584                InterruptWrite,         /* write */
585                SetAttributes,          /* setAttributes */
586                NULL,                   /* stopRemoteTx */
587                NULL,                   /* startRemoteTx */
588                1                       /* outputUsesInterrupts */
589 };
590
591 static const rtems_termios_callbacks pollCallbacks = {
592                NULL,                   /* firstOpen */
593                NULL,                   /* lastClose */
594                dbugRead,               /* pollRead */
595                dbugWrite,              /* write */
596                SetAttributes,          /* setAttributes */
597                NULL,                   /* stopRemoteTx */
598                NULL,                   /* startRemoteTx */
599                0                       /* outputUsesInterrupts */
600 };
601
602 if (minor==UART_CHANNEL_A) {
603        if (USE_INTERRUPTS_A) {
604                rtems_libio_open_close_args_t *args = arg;
605
606                sc |= rtems_termios_open (major, minor, arg, &intrCallbacks);
607                ttypA = args->iop->data1;
608        }
609        else {
610                sc |= rtems_termios_open (major, minor, arg, &pollCallbacks);
611        }
612 }
613
614 else if (minor==UART_CHANNEL_B) {
615        if (USE_INTERRUPTS_B) {
616                rtems_libio_open_close_args_t *args = arg;
617
618                sc |= rtems_termios_open (major, minor, arg, &intrCallbacks);
619                ttypB = args->iop->data1;
620        }
621        else {
622                sc |= rtems_termios_open (major, minor, arg, &pollCallbacks);
623        }
624 }
625
626 else return RTEMS_INVALID_NUMBER;
627
628 return sc;
629}
630
631/******************************************************
632  Name: console_close
633  Input parameters: channel #, termios args
634  Output parameters: -
635  Description: close the device
636 *****************************************************/
637rtems_device_driver console_close(
638  rtems_device_major_number major,
639  rtems_device_minor_number minor,
640  void                    * arg
641)
642{
643        return rtems_termios_close (arg);
644}
645
646/******************************************************
647  Name: console_read
648  Input parameters: channel #, termios args
649  Output parameters: -
650  Description: read the device
651 *****************************************************/
652rtems_device_driver console_read(
653  rtems_device_major_number major,
654  rtems_device_minor_number minor,
655  void                    * arg
656)
657{
658        return rtems_termios_read (arg);
659}
660
661/******************************************************
662  Name: console_write
663  Input parameters: channel #, termios args
664  Output parameters: -
665  Description: write to the device
666 *****************************************************/
667rtems_device_driver console_write(
668  rtems_device_major_number major,
669  rtems_device_minor_number minor,
670  void                    * arg
671)
672{
673        return rtems_termios_write (arg);
674}
675
676/******************************************************
677  Name: console_control
678  Input parameters: channel #, termios args
679  Output parameters: -
680  Description: Handle ioctl request
681 *****************************************************/
682rtems_device_driver console_control(
683  rtems_device_major_number major,
684  rtems_device_minor_number minor,
685  void                    * arg
686)
687{
688        rtems_libio_ioctl_args_t *args = arg;
689
690        if (args->command == RTEMS_IO_SET_ATTRIBUTES)
691                SetAttributes (minor, (struct termios *)args->buffer);
692
693        return rtems_termios_ioctl (arg);
694}
Note: See TracBrowser for help on using the repository browser.