Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:45

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  68340/68349 console serial I/O.
0005  */
0006 
0007 /*
0008  *  Author:
0009  *  Geoffroy Montel
0010  *  France Telecom - CNET/DSM/TAM/CAT
0011  *  4, rue du Clos Courtel
0012  *  35512 CESSON-SEVIGNE
0013  *  FRANCE
0014  *
0015  *  e-mail: g_montel@yahoo.com
0016  *
0017  *  COPYRIGHT (c) 1989-1999.
0018  *  On-Line Applications Research Corporation (OAR).
0019  *
0020  * Redistribution and use in source and binary forms, with or without
0021  * modification, are permitted provided that the following conditions
0022  * are met:
0023  * 1. Redistributions of source code must retain the above copyright
0024  *    notice, this list of conditions and the following disclaimer.
0025  * 2. Redistributions in binary form must reproduce the above copyright
0026  *    notice, this list of conditions and the following disclaimer in the
0027  *    documentation and/or other materials provided with the distribution.
0028  *
0029  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0030  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0031  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0032  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0033  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0034  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0035  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0036  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0037  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0038  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0039  * POSSIBILITY OF SUCH DAMAGE.
0040  */
0041 
0042 #include <termios.h>
0043 
0044 #include <stdarg.h>
0045 #include <stdio.h>
0046 #include <stdlib.h>
0047 
0048 #include <bsp.h>
0049 #include <rtems/libio.h>
0050 #include <rtems/termiostypes.h>
0051 #include <rtems/console.h>
0052 #include <m68340.h>
0053 #include <m340uart.h>
0054 #include <m340timer.h>
0055 
0056 #define CONSOLE_VECTOR 121
0057 #define CONSOLE_IRQ_LEVEL 3
0058 #define CONSOLE_INTERRUPT_ARBITRATION 2
0059 
0060 static void *ttypA;     /* to remember which tty has been opened on channel A
0061                    used when interrupts are enabled */
0062 
0063 static void *ttypB;     /* to remember which tty has been opened on channel B
0064                    used when interrupts are enabled */
0065 
0066 unsigned char DUIER_mirror = 0 ;  /* reflects the state of IER register, which is Write Only */
0067 unsigned char Error_Status_A = 0; /* error status on Channel A */
0068 unsigned char Error_Status_B = 0; /* error status on Channel A */
0069 
0070 /*
0071  * Device-specific routines
0072  */
0073 
0074 #define USE_INTERRUPTS_A (m340_uart_config[UART_CHANNEL_A].mode==UART_INTERRUPTS)
0075 #define USE_INTERRUPTS_B (m340_uart_config[UART_CHANNEL_B].mode==UART_INTERRUPTS)
0076 #define CHANNEL_ENABLED_A m340_uart_config[UART_CHANNEL_A].enable
0077 #define CHANNEL_ENABLED_B m340_uart_config[UART_CHANNEL_B].enable
0078 
0079 #define set_DUIER(a) DUIER_mirror |= (a); DUIER = DUIER_mirror
0080 #define unset_DUIER(a) DUIER_mirror &= ~(a); DUIER = DUIER_mirror
0081 
0082 #define Enable_Interrupts_Tx_A if (USE_INTERRUPTS_A) set_DUIER(m340_TxRDYA)
0083 #define Disable_Interrupts_Tx_A if (USE_INTERRUPTS_A) unset_DUIER(m340_TxRDYA)
0084 
0085 #define Enable_Interrupts_Tx_B if (USE_INTERRUPTS_B) set_DUIER(m340_TxRDYB)
0086 #define Disable_Interrupts_Tx_B if (USE_INTERRUPTS_B) unset_DUIER(m340_TxRDYB)
0087 
0088 /******************************************************
0089   Name: InterruptHandler
0090   Input parameters: vector number
0091   Output parameters: -
0092   Description: UART ISR Routine, called by _RTEMS_ISR
0093  *****************************************************/
0094 rtems_isr
0095 InterruptHandler (rtems_vector_number v)
0096 {
0097  char ch;
0098 
0099  /*****************************************************************************
0100  **             CHANNEL A                    **
0101  *****************************************************************************/
0102 
0103     /* check Received Break*/
0104     if (DUSRA & m340_RB) {
0105        Error_Status_A |= m340_RB;
0106        /* reset error status */
0107        DUCRA = m340_Reset_Error_Status;
0108     }
0109 
0110     /* buffer received ? */
0111     if (DUSRA & m340_Rx_RDY) {
0112        do {
0113        /* error encountered? */
0114        if (DUSRA & (m340_OE | m340_PE | m340_FE | m340_RB)) {
0115           Error_Status_A |= DUSRA;
0116           /* reset error status */
0117               DUCRA = m340_Reset_Error_Status;
0118           /* all the characters in the queue may not be good */
0119           while (DUSRA & m340_Rx_RDY)
0120             /* push them in a trash */
0121             ch = DURBA;
0122        }
0123        else {
0124          /* this is necessary, otherwise it blocks when FIFO is full */
0125          ch = DURBA;
0126          rtems_termios_enqueue_raw_characters(ttypA,&ch,1);
0127        }
0128        } while (DUSRA & m340_Rx_RDY);
0129        Restart_Fifo_Full_A_Timer(); /* only if necessary (pointer to a fake function if
0130                        not in FIFO full mode) */
0131     }
0132 
0133     else /* if no character has been received */
0134        Restart_Check_A_Timer();     /* same remark */
0135 
0136     /* ready to accept a character ? */
0137     if (DUISR & DUIER_mirror & m340_TxRDYA) {
0138     Disable_Interrupts_Tx_A;
0139     /* one character has been transmitted */
0140     rtems_termios_dequeue_characters(ttypA,1);
0141     }
0142 
0143  /*****************************************************************************
0144  **             CHANNEL B                    **
0145  *****************************************************************************/
0146 
0147     /* check Received Break*/
0148     if (DUSRB & m340_RB) {
0149        Error_Status_B |= m340_RB;
0150        /* reset error status */
0151        DUCRB = m340_Reset_Error_Status;
0152     }
0153 
0154     /* buffer received ? */
0155     if (DUSRB & m340_Rx_RDY) {
0156        do {
0157        if (DUSRB & (m340_OE | m340_PE | m340_FE | m340_RB)) {
0158           Error_Status_B |= DUSRB;
0159           /* reset error status */
0160               DUCRB = m340_Reset_Error_Status;
0161           /* all the characters in the queue may not be good */
0162           while (DUSRB & m340_Rx_RDY)
0163             /* push them in a trash */
0164             ch = DURBB;
0165        }
0166        else {
0167          ch = DURBB;
0168          rtems_termios_enqueue_raw_characters(ttypB,&ch,1);
0169        }
0170 
0171        } while (DUSRB & m340_Rx_RDY);
0172        Restart_Fifo_Full_B_Timer();
0173     }
0174     else /* if no character has been received */
0175        Restart_Check_B_Timer();
0176 
0177     /* ready to accept a character ? */
0178     if (DUISR & DUIER_mirror & m340_TxRDYB) {
0179     Disable_Interrupts_Tx_B;
0180     /* one character has been transmitted */
0181     rtems_termios_dequeue_characters(ttypB,1);
0182     }
0183 }
0184 
0185 /******************************************************
0186   Name: InterruptWrite
0187   Input parameters: minor = channel, pointer to buffer,
0188             and length of buffer to transmit
0189   Output parameters: -
0190   Description: write the first character of buf only
0191            may be called by either console_write
0192            or rtems_termios_enqueue_raw_characters
0193  *****************************************************/
0194 static ssize_t
0195 InterruptWrite (int minor, const char *buf, size_t len)
0196 {
0197  if (minor==UART_CHANNEL_A) {
0198     if (len>0) {
0199       DUTBA=*buf;
0200       Enable_Interrupts_Tx_A;
0201     }
0202  }
0203  else if (minor==UART_CHANNEL_B) {
0204     if (len>0) {
0205       DUTBB=*buf;
0206       Enable_Interrupts_Tx_B;
0207     }
0208  }
0209  return 0;
0210 }
0211 
0212 /******************************************************
0213   Name: dbug_out_char
0214   Input parameters: channel, character to emit
0215   Output parameters: -
0216   Description: wait for the UART to be ready to emit
0217            a character and send it
0218  *****************************************************/
0219 void dbug_out_char( int minor, int ch )
0220 {
0221  if (minor==UART_CHANNEL_A) {
0222     while (!(DUSRA & m340_Tx_RDY)) continue;
0223     DUTBA=ch;
0224  }
0225  else if (minor==UART_CHANNEL_B) {
0226     while (!(DUSRB & m340_Tx_RDY)) continue;
0227     DUTBB=ch;
0228  }
0229 }
0230 
0231 /******************************************************
0232   Name: dbug_in_char
0233   Input parameters: -
0234   Output parameters: received character
0235   Description: return the character in the UART
0236  *****************************************************/
0237 int dbug_in_char( int minor )
0238 {
0239  if (minor==UART_CHANNEL_A) {
0240     return DURBA;
0241  }
0242  else if (minor==UART_CHANNEL_B) {
0243     return DURBB;
0244  }
0245  return 0;
0246 }
0247 
0248 /******************************************************
0249   Name: dbug_char_present
0250   Input parameters: channel #
0251   Output parameters: TRUE or FALSE
0252   Description: return whether there's a character
0253            in the receive buffer
0254  *****************************************************/
0255 int dbug_char_present( int minor )
0256 {
0257  if (minor==UART_CHANNEL_A) {
0258     return (DUSRA & m340_Rx_RDY);
0259  }
0260  else if (minor==UART_CHANNEL_B) {
0261     return (DUSRB & m340_Rx_RDY);
0262  }
0263  return 0;
0264 }
0265 
0266 /******************************************************
0267   Name: dbugInitialise
0268   Input parameters: -
0269   Output parameters: -
0270   Description: Init the UART
0271  *****************************************************/
0272 static void
0273 dbugInitialise (void)
0274 {
0275      t_baud_speed_table uart_config;        /* configuration of UARTS */
0276 
0277      /*
0278       * Reset Receiver
0279       */
0280      DUCRA = m340_Reset_Receiver;
0281      DUCRB = m340_Reset_Receiver;
0282 
0283      /*
0284       * Reset Transmitter
0285       */
0286      DUCRA = m340_Reset_Transmitter;
0287      DUCRB = m340_Reset_Transmitter;
0288 
0289      /*
0290       * Enable serial module for normal operation, ignore FREEZE, select the crystal clock,
0291       * supervisor/user serial registers unrestricted
0292       * interrupt arbitration at priority CONSOLE_INTERRUPT_ARBITRATION
0293       * WARNING : 8 bits access only on this UART!
0294       */
0295      DUMCRH = 0x00;
0296      DUMCRL = CONSOLE_INTERRUPT_ARBITRATION;
0297 
0298      /*
0299       * Interrupt level register
0300       */
0301      DUILR = CONSOLE_IRQ_LEVEL;
0302 
0303      /* sets the IVR */
0304      DUIVR = CONSOLE_VECTOR;
0305 
0306      /* search for a correct m340 uart configuration */
0307      uart_config = Find_Right_m340_UART_Config(m340_uart_config[UART_CHANNEL_A].rx_baudrate,
0308                            m340_uart_config[UART_CHANNEL_A].tx_baudrate,
0309                            CHANNEL_ENABLED_A,
0310                            m340_uart_config[UART_CHANNEL_B].rx_baudrate,
0311                            m340_uart_config[UART_CHANNEL_B].tx_baudrate,
0312                            CHANNEL_ENABLED_B);
0313 
0314      /*****************************************************************************
0315      **             CHANNEL A                        **
0316      *****************************************************************************/
0317      if (CHANNEL_ENABLED_A) {
0318 
0319     if (USE_INTERRUPTS_A) {
0320        rtems_isr_entry old_handler;
0321 
0322        (void) rtems_interrupt_catch (InterruptHandler,
0323                        CONSOLE_VECTOR,
0324                        &old_handler);
0325 
0326        /* uncomment this if you want to pass control to your own ISR handler
0327           it may be usefull to do so to check for performances with an oscilloscope */
0328        /*
0329        {
0330         CPU_ISR_raw_handler ignored;
0331         _CPU_ISR_install_raw_handler( CONSOLE_VECTOR, _Debug_ISR_Handler_Console, &ignored );
0332        }
0333        */
0334 
0335        /*
0336         * Interrupt Enable Register
0337         * Enable Interrupts on Channel A Receiver Ready
0338         */
0339        set_DUIER(m340_RxRDYA);
0340     }
0341     else {
0342         /*
0343          * Disable Interrupts on channel A
0344          */
0345         unset_DUIER(m340_RxRDYA&m340_TxRDYA);
0346     }
0347 
0348     /*
0349      * Change set of baud speeds
0350      * disable input control
0351      */
0352     /* no good uart configuration ? */
0353     if (uart_config.nb<1) rtems_fatal_error_occurred (-1);
0354 
0355     if (uart_config.baud_speed_table[UART_CHANNEL_A].set==1)
0356        DUACR = m340_BRG_Set1;
0357     else
0358        DUACR = m340_BRG_Set2;
0359 
0360     /*
0361      * make OPCR an auxiliary function serving the communication channels
0362      */
0363     DUOPCR = m340_OPCR_Aux;
0364 
0365     /* poll the XTAL_RDY bit until it is cleared to ensure that an unstable crystal
0366        input is not applied to the baud rate generator */
0367     while (DUISR & m340_XTAL_RDY) continue;
0368 
0369     /*
0370      * Serial Channel Baud Speed
0371      */
0372     DUCSRA = (uart_config.baud_speed_table[UART_CHANNEL_A].rcs << 4)
0373            | (uart_config.baud_speed_table[UART_CHANNEL_A].tcs);
0374 
0375     /*
0376      * Serial Channel Configuration
0377      */
0378     DUMR1A = m340_uart_config[UART_CHANNEL_A].parity_mode
0379            | m340_uart_config[UART_CHANNEL_A].bits_per_char
0380            | m340_RxRTS;
0381 
0382     if (m340_uart_config[UART_CHANNEL_A].rx_mode==UART_FIFO_FULL) DUMR1A |= m340_R_F | m340_ERR;
0383 
0384     /*
0385      * Serial Channel Configuration 2
0386      */
0387     DUMR2A |= m340_normal;
0388 
0389     /*
0390      * Enable Channel A: transmitter and receiver
0391      */
0392     DUCRA = m340_Transmitter_Enable | m340_Receiver_Enable;
0393      } /* channel A enabled */
0394 
0395      /*****************************************************************************
0396      **             CHANNEL B                        **
0397      *****************************************************************************/
0398      if (CHANNEL_ENABLED_B) {
0399 
0400     /* we mustn't set the console vector twice! */
0401     if ((USE_INTERRUPTS_B && !(CHANNEL_ENABLED_A))
0402        || (USE_INTERRUPTS_B && CHANNEL_ENABLED_A && !USE_INTERRUPTS_A)) {
0403        rtems_isr_entry old_handler;
0404 
0405        (void) rtems_interrupt_catch (InterruptHandler,
0406                        CONSOLE_VECTOR,
0407                        &old_handler);
0408 
0409        /* uncomment this if you want to pass control to your own ISR handler
0410           it may be usefull to do so to check for performances with an oscilloscope */
0411        /*
0412        {
0413         CPU_ISR_raw_handler ignored;
0414         _CPU_ISR_install_raw_handler( CONSOLE_VECTOR, _Debug_ISR_Handler_Console, &ignored );
0415        }
0416        */
0417 
0418        /*
0419         * Interrupt Enable Register
0420         * Enable Interrupts on Channel A Receiver Ready
0421         */
0422        set_DUIER(m340_RxRDYB);
0423     }
0424     else {
0425         /*
0426          * Disable Interrupts on channel B
0427          */
0428         unset_DUIER(m340_RxRDYB&m340_TxRDYB);
0429     }
0430 
0431     /*
0432      * Change set of baud speeds
0433      * disable input control
0434      */
0435 
0436     /* no good uart configuration ? */
0437     if (uart_config.nb<2) rtems_fatal_error_occurred (-1);
0438 
0439     /* don't set DUACR twice! */
0440     if (!CHANNEL_ENABLED_A) {
0441        if (uart_config.baud_speed_table[UART_CHANNEL_B].set==1)
0442               DUACR = m340_BRG_Set1;
0443        else
0444               DUACR = m340_BRG_Set2;
0445         }
0446 
0447     /*
0448      * make OPCR an auxiliary function serving the communication channels
0449      */
0450     if (!CHANNEL_ENABLED_A) DUOPCR = m340_OPCR_Aux;
0451 
0452     /* poll the XTAL_RDY bit until it is cleared to ensure that an unstable crystal
0453        input is not applied to the baud rate generator */
0454     while (DUISR & m340_XTAL_RDY) continue;
0455 
0456     /*
0457      * Serial Channel Baud Speed
0458      */
0459     DUCSRB = (uart_config.baud_speed_table[UART_CHANNEL_B].rcs << 4)
0460            | (uart_config.baud_speed_table[UART_CHANNEL_B].tcs);
0461 
0462     /*
0463      * Serial Channel Configuration
0464      */
0465     DUMR1B = m340_uart_config[UART_CHANNEL_B].parity_mode
0466            | m340_uart_config[UART_CHANNEL_B].bits_per_char
0467            | m340_RxRTS;
0468 
0469     if (m340_uart_config[UART_CHANNEL_B].rx_mode==UART_FIFO_FULL) DUMR1B |= m340_R_F | m340_ERR;
0470 
0471     /*
0472      * Serial Channel Configuration 2
0473      */
0474     DUMR2B |= m340_normal;
0475 
0476     /*
0477      * Enable Channel A: transmitter and receiver
0478      */
0479     DUCRB = m340_Transmitter_Enable | m340_Receiver_Enable;
0480      } /* channel B enabled */
0481 }
0482 
0483 /******************************************************
0484   Name: SetAttributes
0485   Input parameters: termios structure, channel
0486   Output parameters: -
0487   Description: return whether there's a character
0488            in the receive buffer
0489   TO DO: add the channel # to check for!!
0490  *****************************************************/
0491 static int
0492 SetAttributes (int minor, const struct termios *t)
0493 {
0494  rtems_interrupt_level level;
0495  float ispeed, ospeed;
0496 
0497  /* convert it */
0498  ispeed = rtems_termios_baud_to_number(t->c_ispeed);
0499  ospeed = rtems_termios_baud_to_number(t->c_ospeed);
0500 
0501  if (ispeed || ospeed) {
0502        /* update config table */
0503        m340_uart_config[UART_CHANNEL_A].rx_baudrate = ((minor==UART_CHANNEL_A)&&(ispeed!=0)) ? ispeed  : m340_uart_config[UART_CHANNEL_A].rx_baudrate;
0504        m340_uart_config[UART_CHANNEL_A].tx_baudrate = ((minor==UART_CHANNEL_A)&&(ospeed!=0)) ? ospeed  : m340_uart_config[UART_CHANNEL_A].tx_baudrate;
0505        m340_uart_config[UART_CHANNEL_B].rx_baudrate = ((minor==UART_CHANNEL_B)&&(ispeed!=0)) ? ispeed  : m340_uart_config[UART_CHANNEL_B].rx_baudrate;
0506        m340_uart_config[UART_CHANNEL_B].tx_baudrate = ((minor==UART_CHANNEL_B)&&(ospeed!=0)) ? ospeed  : m340_uart_config[UART_CHANNEL_B].tx_baudrate;
0507  }
0508 
0509  /* change parity */
0510  if (t->c_cflag & PARENB) {
0511     if (t->c_cflag & PARODD) m340_uart_config[minor].parity_mode = m340_Odd_Parity;
0512     else m340_uart_config[minor].parity_mode = m340_Even_Parity;
0513  }
0514 
0515  /* change bits per character */
0516  if (t->c_cflag & CSIZE) {
0517     switch (t->c_cflag & CSIZE) {
0518     default:    break;
0519     case CS5:   m340_uart_config[minor].bits_per_char = m340_5bpc;  break;
0520     case CS6:   m340_uart_config[minor].bits_per_char = m340_6bpc;  break;
0521     case CS7:   m340_uart_config[minor].bits_per_char = m340_7bpc;  break;
0522     case CS8:   m340_uart_config[minor].bits_per_char = m340_8bpc;  break;
0523     }
0524  }
0525 
0526  /* if serial module configuration has been changed */
0527  if (t->c_cflag & (CSIZE | PARENB)) {
0528     rtems_interrupt_disable(level);
0529     /* reinit the UART */
0530     dbugInitialise();
0531     rtems_interrupt_enable (level);
0532  }
0533 
0534  return 0;
0535 }
0536 
0537 /******************************************************
0538   Name: console_initialize
0539   Input parameters: MAJOR # of console_driver,
0540             minor is always 0,
0541             args are always NULL
0542   Output parameters: -
0543   Description: Reserve resources consumed by this driver
0544   TODO: We should pass m340_uart_config table in arg
0545  *****************************************************/
0546 rtems_device_driver console_initialize(
0547   rtems_device_major_number  major,
0548   rtems_device_minor_number  minor,
0549   void                      *arg
0550 )
0551 {
0552     rtems_status_code status;
0553     int i;
0554 
0555     /*
0556      * Set up TERMIOS
0557      */
0558     rtems_termios_initialize ();
0559 
0560     /*
0561      * Do device-specific initialization
0562      */
0563         Init_UART_Table();
0564     dbugInitialise ();
0565     Fifo_Full_benchmark_timer_initialize();
0566 
0567     /*
0568      * Register the devices
0569      */
0570     for (i=0; i<UART_NUMBER_OF_CHANNELS; i++) {
0571         if (m340_uart_config[i].enable) {
0572         status = rtems_io_register_name (m340_uart_config[i].name, major, i);
0573         if (status != RTEMS_SUCCESSFUL)
0574             rtems_fatal_error_occurred (status);
0575         }
0576     }
0577 
0578     return RTEMS_SUCCESSFUL;
0579 }
0580 
0581 /******************************************************
0582   Name: console_open
0583   Input parameters: channel #, arg
0584   Output parameters: -
0585   Description: open the device
0586  *****************************************************/
0587 rtems_device_driver console_open(
0588   rtems_device_major_number major,
0589   rtems_device_minor_number minor,
0590   void                    * arg
0591 )
0592 {
0593  rtems_status_code sc = 0;
0594 
0595  static const rtems_termios_callbacks intrCallbacks = {
0596         NULL,           /* firstOpen */
0597         NULL,           /* lastClose */
0598         NULL,           /* pollRead */
0599         InterruptWrite,     /* write */
0600         SetAttributes,      /* setAttributes */
0601         NULL,           /* stopRemoteTx */
0602         NULL,           /* startRemoteTx */
0603         TERMIOS_IRQ_DRIVEN  /* outputUsesInterrupts */
0604  };
0605 
0606  static const rtems_termios_callbacks pollCallbacks = {
0607         NULL,           /* firstOpen */
0608         NULL,           /* lastClose */
0609         dbugRead,       /* pollRead */
0610         dbugWrite,      /* write */
0611         SetAttributes,      /* setAttributes */
0612         NULL,           /* stopRemoteTx */
0613         NULL,           /* startRemoteTx */
0614         TERMIOS_POLLED      /* outputUsesInterrupts */
0615  };
0616 
0617  if (minor==UART_CHANNEL_A) {
0618     if (USE_INTERRUPTS_A) {
0619         rtems_libio_open_close_args_t *args = arg;
0620 
0621         sc |= rtems_termios_open (major, minor, arg, &intrCallbacks);
0622         ttypA = args->iop->data1;
0623     }
0624     else {
0625         sc |= rtems_termios_open (major, minor, arg, &pollCallbacks);
0626     }
0627  }
0628 
0629  else if (minor==UART_CHANNEL_B) {
0630     if (USE_INTERRUPTS_B) {
0631         rtems_libio_open_close_args_t *args = arg;
0632 
0633         sc |= rtems_termios_open (major, minor, arg, &intrCallbacks);
0634         ttypB = args->iop->data1;
0635     }
0636     else {
0637         sc |= rtems_termios_open (major, minor, arg, &pollCallbacks);
0638     }
0639  }
0640 
0641  else return RTEMS_INVALID_NUMBER;
0642 
0643  return sc;
0644 }
0645 
0646 /******************************************************
0647   Name: console_close
0648   Input parameters: channel #, termios args
0649   Output parameters: -
0650   Description: close the device
0651  *****************************************************/
0652 rtems_device_driver console_close(
0653   rtems_device_major_number major,
0654   rtems_device_minor_number minor,
0655   void                    * arg
0656 )
0657 {
0658     return rtems_termios_close (arg);
0659 }
0660 
0661 /******************************************************
0662   Name: console_read
0663   Input parameters: channel #, termios args
0664   Output parameters: -
0665   Description: read the device
0666  *****************************************************/
0667 rtems_device_driver console_read(
0668   rtems_device_major_number major,
0669   rtems_device_minor_number minor,
0670   void                    * arg
0671 )
0672 {
0673     return rtems_termios_read (arg);
0674 }
0675 
0676 /******************************************************
0677   Name: console_write
0678   Input parameters: channel #, termios args
0679   Output parameters: -
0680   Description: write to the device
0681  *****************************************************/
0682 rtems_device_driver console_write(
0683   rtems_device_major_number major,
0684   rtems_device_minor_number minor,
0685   void                    * arg
0686 )
0687 {
0688     return rtems_termios_write (arg);
0689 }
0690 
0691 /******************************************************
0692   Name: console_control
0693   Input parameters: channel #, termios args
0694   Output parameters: -
0695   Description: Handle ioctl request
0696  *****************************************************/
0697 rtems_device_driver console_control(
0698   rtems_device_major_number major,
0699   rtems_device_minor_number minor,
0700   void                    * arg
0701 )
0702 {
0703     rtems_libio_ioctl_args_t *args = arg;
0704 
0705   if (args->command == TIOCSETA)
0706         SetAttributes (minor, (struct termios *)args->buffer);
0707 
0708     return rtems_termios_ioctl (arg);
0709 }