Back to home page

LXR

 
 

    


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

0001 /*
0002  *  Multi UART console serial I/O.
0003  *
0004  * TO DO: Add DMA input/output
0005  */
0006 
0007 /*
0008  * Copyright (c) 2005 Eric Norum <eric@norum.ca>
0009  *
0010  * COPYRIGHT (c) 2005.
0011  * On-Line Applications Research Corporation (OAR).
0012  *
0013  * The license and distribution terms for this file may be
0014  * found in the file LICENSE in this distribution or at
0015  * http://www.rtems.org/license/LICENSE.
0016  */
0017 
0018 #include <stdio.h>
0019 #include <fcntl.h>
0020 #include <termios.h>
0021 #include <malloc.h>
0022 
0023 #include <rtems/console.h>
0024 #include <rtems/libio.h>
0025 #include <rtems/termiostypes.h>
0026 #include <bsp.h>
0027 
0028 #include <rtems/bspIo.h>
0029 
0030 #define UART_INTC0_IRQ_VECTOR(x) (64+13+(x))
0031 
0032 #define MCF5282_UART_USR_ERROR ( MCF5282_UART_USR_RB | \
0033                                  MCF5282_UART_USR_FE | \
0034                                  MCF5282_UART_USR_PE | \
0035                                  MCF5282_UART_USR_OE )
0036 
0037 static ssize_t IntUartPollWrite(int minor, const char *buf, size_t len);
0038 static ssize_t IntUartInterruptWrite (int minor, const char *buf, size_t len);
0039 
0040 static void
0041 _BSP_null_char( char c )
0042 {
0043     int level;
0044 
0045     rtems_interrupt_disable(level);
0046     while ( (MCF5282_UART_USR(CONSOLE_PORT) & MCF5282_UART_USR_TXRDY) == 0 )
0047         continue;
0048     MCF5282_UART_UTB(CONSOLE_PORT) = c;
0049     while ( (MCF5282_UART_USR(CONSOLE_PORT) & MCF5282_UART_USR_TXRDY) == 0 )
0050         continue;
0051     rtems_interrupt_enable(level);
0052 }
0053 
0054 BSP_polling_getchar_function_type       BSP_poll_char = NULL;
0055 BSP_output_char_function_type           BSP_output_char = _BSP_null_char;
0056 
0057 /*
0058  * The MCF5282 has three UARTs.  Enable all them here.  I/O pin selection
0059  * is assumed to have been done elsewher.
0060  */
0061 #define MAX_UART_INFO     3
0062 #define RX_BUFFER_SIZE    512
0063 
0064 struct IntUartInfoStruct
0065 {
0066     int                    iomode;
0067     volatile int           uimr;
0068     int                    baud;
0069     int                    databits;
0070     int                    parity;
0071     int                    stopbits;
0072     int                    hwflow;
0073     int                    rx_in;
0074     int                    rx_out;
0075     char                   rx_buffer[RX_BUFFER_SIZE];
0076     void                  *ttyp;
0077 };
0078 
0079 struct IntUartInfoStruct IntUartInfo[MAX_UART_INFO];
0080 
0081 /***************************************************************************
0082    Function : IntUartSet
0083 
0084    Description : This updates the hardware UART settings.
0085  ***************************************************************************/
0086 static void
0087 IntUartSet(int minor, int baud, int databits, int parity, int stopbits, int hwflow)
0088 {
0089     int                         divisor;
0090     uint32_t                    clock_speed;
0091     uint8_t                   umr1 = 0;
0092     uint8_t                   umr2 = 0;
0093     struct IntUartInfoStruct   *info = &IntUartInfo[minor];
0094     int                         level;
0095 
0096     rtems_interrupt_disable(level);
0097 
0098 
0099     /* disable interrupts, clear RTS line, and disable the UARTS */
0100     MCF5282_UART_UIMR(minor) = 0;
0101     MCF5282_UART_UOP0(minor) = 1;
0102     MCF5282_UART_UCR(minor) = (MCF5282_UART_UCR_TX_DISABLED | MCF5282_UART_UCR_RX_DISABLED);
0103 
0104     /* save the current values */
0105     info->uimr     = 0;
0106     info->baud     = baud;
0107     info->databits = databits;
0108     info->parity   = parity;
0109     info->stopbits = stopbits;
0110     info->hwflow   = hwflow;
0111 
0112     clock_speed = bsp_get_CPU_clock_speed();
0113     /* determine the baud divisor value */
0114     divisor = (clock_speed / ( 32 * baud ));
0115     if ( divisor < 2 ) {
0116         divisor = 2;
0117     }
0118 
0119     /* check to see if doing hardware flow control */
0120     if ( hwflow )
0121     {
0122         /* set hardware flow options */
0123         umr1 |= MCF5282_UART_UMR1_RXRTS;
0124         umr2 |= MCF5282_UART_UMR2_TXCTS;
0125     }
0126 
0127     /* determine the new umr values */
0128     umr1 |= (parity | databits);
0129     umr2 |= (stopbits);
0130 
0131     /* reset the uart */
0132     MCF5282_UART_UCR(minor) = MCF5282_UART_UCR_RESET_ERROR;
0133     MCF5282_UART_UCR(minor) = MCF5282_UART_UCR_RESET_RX;
0134     MCF5282_UART_UCR(minor) = MCF5282_UART_UCR_RESET_TX;
0135 
0136     /* reset the uart mode register and update values */
0137     MCF5282_UART_UCR(minor) = MCF5282_UART_UCR_RESET_MR;
0138     MCF5282_UART_UMR(minor) = umr1;
0139     MCF5282_UART_UMR(minor) = umr2;
0140 
0141     /* set the baud rate values */
0142     MCF5282_UART_UCSR(minor) = (MCF5282_UART_UCSR_RCS_SYS_CLK | MCF5282_UART_UCSR_TCS_SYS_CLK);
0143     MCF5282_UART_UBG1(minor) = (divisor & 0xff00) >> 8;
0144     MCF5282_UART_UBG2(minor) = (divisor & 0x00ff);
0145 
0146     /* enable the uart */
0147     MCF5282_UART_UCR(minor) = (MCF5282_UART_UCR_TX_ENABLED | MCF5282_UART_UCR_RX_ENABLED);
0148 
0149     /* check to see if interrupts need to be enabled */
0150     if ( info->iomode != TERMIOS_POLLED )
0151     {
0152         /* enable rx interrupts */
0153         info->uimr |= MCF5282_UART_UIMR_FFULL;
0154         MCF5282_UART_UIMR(minor) = info->uimr;
0155     }
0156 
0157     /* check to see if doing hardware flow control */
0158     if ( hwflow )
0159     {
0160         /* assert the RTS line */
0161         MCF5282_UART_UOP1(minor) = 1;
0162     }
0163 
0164     rtems_interrupt_enable(level);
0165 
0166 }
0167 
0168 
0169 /***************************************************************************
0170    Function : IntUartSetAttributes
0171 
0172    Description : This provides the hardware-dependent portion of tcsetattr().
0173    value and sets it. At the moment this just sets the baud rate.
0174 
0175    Note: The highest baudrate is 115200 as this stays within
0176    an error of +/- 5% at 25MHz processor clock
0177  ***************************************************************************/
0178 static int
0179 IntUartSetAttributes(int minor, const struct termios *t)
0180 {
0181     /* set default index values */
0182     int                         baud     = (int)9600;
0183     int                         databits = (int)MCF5282_UART_UMR1_BC_8;
0184     int                         parity   = (int)MCF5282_UART_UMR1_PM_NONE;
0185     int                         stopbits = (int)MCF5282_UART_UMR2_STOP_BITS_1;
0186     int                         hwflow   = (int)0;
0187     struct IntUartInfoStruct   *info     = &IntUartInfo[minor];
0188 
0189     /* check to see if input is valid */
0190     if ( t != (const struct termios *)0 )
0191     {
0192         /* determine baud rate index */
0193     baud = rtems_termios_baud_to_number(t->c_ospeed);
0194 
0195         /* determine data bits */
0196         switch ( t->c_cflag & CSIZE )
0197         {
0198             case CS5:
0199                 databits = (int)MCF5282_UART_UMR1_BC_5;
0200                 break;
0201             case CS6:
0202                 databits = (int)MCF5282_UART_UMR1_BC_6;
0203                 break;
0204             case CS7:
0205                 databits = (int)MCF5282_UART_UMR1_BC_7;
0206                 break;
0207             case CS8:
0208                 databits = (int)MCF5282_UART_UMR1_BC_8;
0209                 break;
0210         }
0211 
0212         /* determine if parity is enabled */
0213         if ( t->c_cflag & PARENB )
0214         {
0215             if ( t->c_cflag & PARODD )
0216             {
0217                 /* odd parity */
0218                 parity = (int)MCF5282_UART_UMR1_PM_ODD;
0219             }
0220             else
0221             {
0222                 /* even parity */
0223                 parity = (int)MCF5282_UART_UMR1_PM_EVEN;
0224             }
0225         }
0226 
0227         /* determine stop bits */
0228         if ( t->c_cflag & CSTOPB )
0229         {
0230             /* two stop bits */
0231             stopbits = (int)MCF5282_UART_UMR2_STOP_BITS_2;
0232         }
0233 
0234         /* check to see if hardware flow control */
0235         if ( t->c_cflag & CRTSCTS )
0236         {
0237             hwflow = 1;
0238         }
0239     }
0240 
0241     /* check to see if values have changed */
0242     if ( ( baud     != info->baud     ) ||
0243          ( databits != info->databits ) ||
0244          ( parity   != info->parity   ) ||
0245          ( stopbits != info->stopbits ) ||
0246          ( hwflow   != info->hwflow   ) )
0247     {
0248 
0249         /* call function to set values */
0250         IntUartSet(minor, baud, databits, parity, stopbits, hwflow);
0251     }
0252 
0253     return( RTEMS_SUCCESSFUL );
0254 
0255 }
0256 
0257 /***************************************************************************
0258    Function : IntUartInterruptHandler
0259 
0260    Description : This is the interrupt handler for the internal uart. It
0261    determines which channel caused the interrupt before queueing any received
0262    chars and dequeueing chars waiting for transmission.
0263  ***************************************************************************/
0264 static rtems_isr
0265 IntUartInterruptHandler(rtems_vector_number v)
0266 {
0267     unsigned int                chan = v - UART_INTC0_IRQ_VECTOR(0);
0268     struct IntUartInfoStruct   *info = &IntUartInfo[chan];
0269 
0270     /* check to see if received data */
0271     if ( MCF5282_UART_UISR(chan) & MCF5282_UART_UISR_RXRDY )
0272     {
0273         /* read data and put into the receive buffer */
0274         while ( MCF5282_UART_USR(chan) & MCF5282_UART_USR_RXRDY )
0275         {
0276 
0277             if ( MCF5282_UART_USR(chan) & MCF5282_UART_USR_ERROR )
0278             {
0279                 /* clear the error */
0280                 MCF5282_UART_UCR(chan) = MCF5282_UART_UCR_RESET_ERROR;
0281             }
0282             /* put data in rx buffer and check for errors */
0283             info->rx_buffer[info->rx_in] = MCF5282_UART_URB(chan);
0284 
0285             /* update buffer values */
0286             info->rx_in++;
0287 
0288             if ( info->rx_in >= RX_BUFFER_SIZE )
0289             {
0290                 info->rx_in = 0;
0291             }
0292         }
0293         /* Make sure the port has been opened */
0294         if ( info->ttyp )
0295         {
0296 
0297             /* check to see if task driven */
0298             if ( info->iomode == TERMIOS_TASK_DRIVEN )
0299             {
0300                 /* notify rx task that rx buffer has data */
0301                 rtems_termios_rxirq_occured(info->ttyp);
0302             }
0303             else
0304             {
0305                 /* Push up the received data */
0306                 rtems_termios_enqueue_raw_characters(info->ttyp, info->rx_buffer, info->rx_in);
0307                 info->rx_in    = 0;
0308             }
0309         }
0310     }
0311 
0312     /* check to see if data needs to be transmitted */
0313     if ( ( info->uimr & MCF5282_UART_UIMR_TXRDY ) &&
0314          ( MCF5282_UART_UISR(chan) & MCF5282_UART_UISR_TXRDY ) )
0315     {
0316 
0317         /* disable tx interrupts */
0318         info->uimr &= ~MCF5282_UART_UIMR_TXRDY;
0319         MCF5282_UART_UIMR(chan) = info->uimr;
0320 
0321         /* tell upper level that character has been sent */
0322         if ( info->ttyp )
0323             rtems_termios_dequeue_characters(info->ttyp, 1);
0324     }
0325 }
0326 
0327 
0328 
0329 /***************************************************************************
0330    Function : IntUartInitialize
0331 
0332    Description : This initialises the internal uart hardware for all
0333    internal uarts. If the internal uart is to be interrupt driven then the
0334    interrupt vectors are hooked.
0335  ***************************************************************************/
0336 static void
0337 IntUartInitialize(void)
0338 {
0339     unsigned int        chan;
0340     struct IntUartInfoStruct   *info;
0341     rtems_isr_entry old_handler;
0342     int level;
0343 
0344     for ( chan = 0; chan < MAX_UART_INFO; chan++ )
0345     {
0346         info = &IntUartInfo[chan];
0347 
0348         info->ttyp     = NULL;
0349         info->rx_in    = 0;
0350         info->rx_out   = 0;
0351         info->baud     = -1;
0352         info->databits = -1;
0353         info->parity   = -1;
0354         info->stopbits = -1;
0355         info->hwflow   = -1;
0356 
0357         MCF5282_UART_UACR(chan) = 0;
0358         MCF5282_UART_UIMR(chan) = 0;
0359         if ( info->iomode != TERMIOS_POLLED )
0360         {
0361             rtems_interrupt_catch (IntUartInterruptHandler,
0362                                    UART_INTC0_IRQ_VECTOR(chan),
0363                                    &old_handler);
0364         }
0365 
0366         /* set uart default values */
0367         IntUartSetAttributes(chan, NULL);
0368 
0369         /* unmask interrupt */
0370         rtems_interrupt_disable(level);
0371         switch(chan) {
0372         case 0:
0373             bsp_allocate_interrupt(UART0_IRQ_LEVEL, UART0_IRQ_PRIORITY);
0374             MCF5282_INTC0_ICR13 = MCF5282_INTC_ICR_IL(UART0_IRQ_LEVEL) |
0375                                   MCF5282_INTC_ICR_IP(UART0_IRQ_PRIORITY);
0376             MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_INT13 |
0377                                     MCF5282_INTC_IMRL_MASKALL);
0378             break;
0379 
0380         case 1:
0381             bsp_allocate_interrupt(UART1_IRQ_LEVEL, UART1_IRQ_PRIORITY);
0382             MCF5282_INTC0_ICR14 = MCF5282_INTC_ICR_IL(UART1_IRQ_LEVEL) |
0383                                   MCF5282_INTC_ICR_IP(UART1_IRQ_PRIORITY);
0384             MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_INT14 |
0385                                     MCF5282_INTC_IMRL_MASKALL);
0386             break;
0387 
0388         case 2:
0389             bsp_allocate_interrupt(UART2_IRQ_LEVEL, UART2_IRQ_PRIORITY);
0390             MCF5282_INTC0_ICR15 = MCF5282_INTC_ICR_IL(UART2_IRQ_LEVEL) |
0391                                   MCF5282_INTC_ICR_IP(UART2_IRQ_PRIORITY);
0392             MCF5282_INTC0_IMRL &= ~(MCF5282_INTC_IMRL_INT15 |
0393                                     MCF5282_INTC_IMRL_MASKALL);
0394             break;
0395         }
0396         rtems_interrupt_enable(level);
0397 
0398     } /* of chan loop */
0399 
0400 
0401 } /* IntUartInitialise */
0402 
0403 
0404 /***************************************************************************
0405    Function : IntUartInterruptWrite
0406 
0407    Description : This writes a single character to the appropriate uart
0408    channel. This is either called during an interrupt or in the user's task
0409    to initiate a transmit sequence. Calling this routine enables Tx
0410    interrupts.
0411  ***************************************************************************/
0412 static ssize_t
0413 IntUartInterruptWrite (int minor, const char *buf, size_t len)
0414 {
0415     if (len > 0) {
0416         /* write out character */
0417         MCF5282_UART_UTB(minor) = *buf;
0418 
0419         /* enable tx interrupt */
0420         IntUartInfo[minor].uimr |= MCF5282_UART_UIMR_TXRDY;
0421         MCF5282_UART_UIMR(minor) = IntUartInfo[minor].uimr;
0422     }
0423 
0424     return 0;
0425 }
0426 
0427 /***************************************************************************
0428    Function : IntUartInterruptOpen
0429 
0430    Description : This enables interrupts when the tty is opened.
0431  ***************************************************************************/
0432 static int
0433 IntUartInterruptOpen(int major, int minor, void *arg)
0434 {
0435     struct IntUartInfoStruct   *info = &IntUartInfo[minor];
0436     int level;
0437 
0438     /*
0439      * Enable serial I/O pin assignments
0440      */
0441     rtems_interrupt_disable(level);
0442     switch(minor) {
0443     case 0:
0444         MCF5282_GPIO_PUAPAR |= MCF5282_GPIO_PUAPAR_PUAPA1|MCF5282_GPIO_PUAPAR_PUAPA0;
0445         break;
0446     case 1:
0447         MCF5282_GPIO_PUAPAR |= MCF5282_GPIO_PUAPAR_PUAPA3|MCF5282_GPIO_PUAPAR_PUAPA2;
0448         break;
0449     case 2:
0450         MCF5282_GPIO_PASPAR =
0451           (MCF5282_GPIO_PASPAR
0452            & ~(MCF5282_GPIO_PASPAR_PASPA3(3)|MCF5282_GPIO_PASPAR_PASPA2(3)))
0453           |  (MCF5282_GPIO_PASPAR_PASPA3(2)|MCF5282_GPIO_PASPAR_PASPA2(2));
0454         break;
0455     }
0456     rtems_interrupt_enable(level);
0457     /* enable the uart */
0458     MCF5282_UART_UCR(minor) = (MCF5282_UART_UCR_TX_ENABLED | MCF5282_UART_UCR_RX_ENABLED);
0459 
0460     /* check to see if interrupts need to be enabled */
0461     if ( info->iomode != TERMIOS_POLLED )
0462     {
0463         /* enable rx interrupts */
0464         info->uimr |= MCF5282_UART_UIMR_FFULL;
0465         MCF5282_UART_UIMR(minor) = info->uimr;
0466     }
0467 
0468     /* check to see if doing hardware flow control */
0469     if ( info->hwflow )
0470     {
0471         /* assert the RTS line */
0472         MCF5282_UART_UOP1(minor) = 1;
0473     }
0474 
0475     return( 0 );
0476 }
0477 
0478 
0479 
0480 /***************************************************************************
0481    Function : IntUartInterruptClose
0482 
0483    Description : This disables interrupts when the tty is closed.
0484  ***************************************************************************/
0485 static int
0486 IntUartInterruptClose(int major, int minor, void *arg)
0487 {
0488     struct IntUartInfoStruct   *info = &IntUartInfo[minor];
0489 
0490     /* disable the interrupts and the uart */
0491     MCF5282_UART_UIMR(minor) = 0;
0492     MCF5282_UART_UCR(minor) = (MCF5282_UART_UCR_TX_DISABLED | MCF5282_UART_UCR_RX_DISABLED);
0493 
0494     /* reset values */
0495     info->ttyp     = NULL;
0496     info->uimr       = 0;
0497     info->rx_in    = 0;
0498     info->rx_out   = 0;
0499 
0500     return( 0 );
0501 }
0502 
0503 /***************************************************************************
0504    Function : IntUartTaskRead
0505 
0506    Description : This reads all available characters from the internal uart
0507    and places them into the termios buffer.  The rx interrupts will be
0508    re-enabled after all data has been read.
0509  ***************************************************************************/
0510 static int
0511 IntUartTaskRead(int minor)
0512 {
0513     char                        buffer[RX_BUFFER_SIZE];
0514     int                         count;
0515     int                         rx_in;
0516     int                         index = 0;
0517     struct IntUartInfoStruct   *info  = &IntUartInfo[minor];
0518 
0519     /* determine number of values to copy out */
0520     rx_in = info->rx_in;
0521     if ( info->rx_out <= rx_in )
0522     {
0523         count = rx_in - info->rx_out;
0524     }
0525     else
0526     {
0527         count = (RX_BUFFER_SIZE - info->rx_out) + rx_in;
0528     }
0529 
0530     /* copy data into local buffer from rx buffer */
0531     while ( ( index < count ) && ( index < RX_BUFFER_SIZE ) )
0532     {
0533         /* copy data byte */
0534         buffer[index] = info->rx_buffer[info->rx_out];
0535         index++;
0536 
0537         /* increment rx buffer values */
0538         info->rx_out++;
0539         if ( info->rx_out >= RX_BUFFER_SIZE )
0540         {
0541             info->rx_out = 0;
0542         }
0543     }
0544 
0545     /* check to see if buffer is not empty */
0546     if ( count > 0 )
0547     {
0548         /* set characters into termios buffer  */
0549         rtems_termios_enqueue_raw_characters(info->ttyp, buffer, count);
0550     }
0551 
0552     return( EOF );
0553 }
0554 
0555 
0556 
0557 /***************************************************************************
0558    Function : IntUartPollRead
0559 
0560    Description : This reads a character from the internal uart. It returns
0561    to the caller without blocking if not character is waiting.
0562  ***************************************************************************/
0563 static int
0564 IntUartPollRead (int minor)
0565 {
0566     if ( (MCF5282_UART_USR(minor) & MCF5282_UART_USR_RXRDY) == 0 )
0567         return(-1);
0568 
0569     return(MCF5282_UART_URB(minor));
0570 }
0571 
0572 
0573 /***************************************************************************
0574    Function : IntUartPollWrite
0575 
0576    Description : This writes out each character in the buffer to the
0577    appropriate internal uart channel waiting till each one is sucessfully
0578    transmitted.
0579  ***************************************************************************/
0580 static ssize_t
0581 IntUartPollWrite (int minor, const char *buf, size_t len)
0582 {
0583     size_t retval = len;
0584     /* loop over buffer */
0585     while ( len-- )
0586     {
0587         /* block until we can transmit */
0588         while ( (MCF5282_UART_USR(minor) & MCF5282_UART_USR_TXRDY) == 0 )
0589             continue;
0590         /* transmit data byte */
0591         MCF5282_UART_UTB(minor) = *buf++;
0592     }
0593     return retval;
0594 }
0595 
0596 /***************************************************************************
0597    Function : console_initialize
0598 
0599    Description : This initialises termios, all uart hardware before
0600    registering /dev/tty devices for each channel and the system /dev/console.
0601  ***************************************************************************/
0602 rtems_device_driver console_initialize(
0603     rtems_device_major_number  major,
0604     rtems_device_minor_number  minor,
0605     void  *arg )
0606 {
0607     rtems_status_code status;
0608     int chan;
0609 
0610     /* Set up TERMIOS */
0611     rtems_termios_initialize ();
0612 
0613     /* set io modes for the different channels and initialize device */
0614     for ( chan = 0; chan < MAX_UART_INFO; chan++ )
0615         IntUartInfo[chan].iomode = TERMIOS_IRQ_DRIVEN;
0616     IntUartInitialize();
0617 
0618     /* Register the console port */
0619     status = rtems_io_register_name ("/dev/console", major, CONSOLE_PORT);
0620     if ( status != RTEMS_SUCCESSFUL )
0621     {
0622         rtems_fatal_error_occurred (status);
0623     }
0624 
0625     /* Register the other ports */
0626     if ( CONSOLE_PORT != 0 )
0627     {
0628         status = rtems_io_register_name ("/dev/tty00", major, 0);
0629         if ( status != RTEMS_SUCCESSFUL )
0630         {
0631             rtems_fatal_error_occurred (status);
0632         }
0633     }
0634     if ( CONSOLE_PORT != 1 )
0635     {
0636         status = rtems_io_register_name ("/dev/tty01", major, 1);
0637         if ( status != RTEMS_SUCCESSFUL )
0638         {
0639             rtems_fatal_error_occurred (status);
0640         }
0641     }
0642     status = rtems_io_register_name ("/dev/tty02", major, 2);
0643     if ( status != RTEMS_SUCCESSFUL )
0644     {
0645         rtems_fatal_error_occurred (status);
0646     }
0647 
0648     return(RTEMS_SUCCESSFUL);
0649 }
0650 
0651 /***************************************************************************
0652    Function : console_open
0653 
0654    Description : This actually opens the device depending on the minor
0655    number set during initialisation. The device specific access routines are
0656    passed to termios when the devices is opened depending on whether it is
0657    polled or not.
0658  ***************************************************************************/
0659 rtems_device_driver console_open(
0660     rtems_device_major_number major,
0661     rtems_device_minor_number minor,
0662     void  * arg)
0663 {
0664     rtems_status_code                status = RTEMS_INVALID_NUMBER;
0665     rtems_libio_open_close_args_t   *args   = (rtems_libio_open_close_args_t *)arg;
0666     struct IntUartInfoStruct        *info;
0667 
0668     static const rtems_termios_callbacks IntUartPollCallbacks = {
0669         NULL,                 /* firstOpen */
0670         NULL,                 /* lastClose */
0671         IntUartPollRead,      /* pollRead */
0672         IntUartPollWrite,     /* write */
0673         IntUartSetAttributes, /* setAttributes */
0674         NULL,                 /* stopRemoteTx */
0675         NULL,                 /* startRemoteTx */
0676         TERMIOS_POLLED        /* mode */
0677     };
0678     static const rtems_termios_callbacks IntUartIntrCallbacks = {
0679         IntUartInterruptOpen,  /* firstOpen */
0680         IntUartInterruptClose, /* lastClose */
0681         NULL,                  /* pollRead */
0682         IntUartInterruptWrite, /* write */
0683         IntUartSetAttributes,  /* setAttributes */
0684         NULL,                  /* stopRemoteTx */
0685         NULL,                  /* startRemoteTx */
0686         TERMIOS_IRQ_DRIVEN     /* mode */
0687     };
0688 
0689     static const rtems_termios_callbacks IntUartTaskCallbacks = {
0690         IntUartInterruptOpen,  /* firstOpen */
0691         IntUartInterruptClose, /* lastClose */
0692         IntUartTaskRead,       /* pollRead */
0693         IntUartInterruptWrite, /* write */
0694         IntUartSetAttributes,  /* setAttributes */
0695         NULL,                  /* stopRemoteTx */
0696         NULL,                  /* startRemoteTx */
0697         TERMIOS_TASK_DRIVEN    /* mode */
0698     };
0699 
0700     /* open the port depending on the minor device number */
0701     if ( ( minor >= 0 ) && ( minor < MAX_UART_INFO ) )
0702     {
0703         info = &IntUartInfo[minor];
0704         switch ( info->iomode )
0705         {
0706             case TERMIOS_POLLED:
0707                 status = rtems_termios_open(major, minor, arg, &IntUartPollCallbacks);
0708                 break;
0709             case TERMIOS_IRQ_DRIVEN:
0710                 status = rtems_termios_open(major, minor, arg, &IntUartIntrCallbacks);
0711                 info->ttyp = args->iop->data1;
0712                 break;
0713             case TERMIOS_TASK_DRIVEN:
0714                 status = rtems_termios_open(major, minor, arg, &IntUartTaskCallbacks);
0715                 info->ttyp = args->iop->data1;
0716                 break;
0717         }
0718     }
0719 
0720     return( status );
0721 }
0722 
0723 /***************************************************************************
0724    Function : console_close
0725 
0726    Description : This closes the device via termios
0727  ***************************************************************************/
0728 rtems_device_driver console_close(
0729     rtems_device_major_number major,
0730     rtems_device_minor_number minor,
0731     void   * arg)
0732 {
0733     return(rtems_termios_close (arg));
0734 }
0735 
0736 /******************
0737 *********************************************************
0738    Function : console_read
0739 
0740    Description : Read from the device via termios
0741  ***************************************************************************/
0742 rtems_device_driver console_read(
0743     rtems_device_major_number major,
0744     rtems_device_minor_number minor,
0745     void  * arg)
0746 {
0747     return(rtems_termios_read (arg));
0748 }
0749 
0750 /***************************************************************************
0751    Function : console_write
0752 
0753    Description : Write to the device via termios
0754  ***************************************************************************/
0755 rtems_device_driver console_write(
0756     rtems_device_major_number major,
0757     rtems_device_minor_number minor,
0758     void  * arg)
0759 {
0760     return(rtems_termios_write (arg));
0761 }
0762 
0763 /***************************************************************************
0764    Function : console_ioctl
0765 
0766    Description : Pass the IOCtl call to termios
0767  ***************************************************************************/
0768 rtems_device_driver console_control(
0769     rtems_device_major_number major,
0770     rtems_device_minor_number minor,
0771     void  * arg)
0772 {
0773     return( rtems_termios_ioctl (arg) );
0774 }
0775