Back to home page

LXR

 
 

    


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

0001  /*
0002   *  Multi UART console serial I/O.
0003   *
0004   * TO DO: Add DMA input/output
0005   */
0006 
0007 #include <stdio.h>
0008 #include <fcntl.h>
0009 #include <termios.h>
0010 #include <malloc.h>
0011 
0012 #include <rtems/libio.h>
0013 #include <rtems/console.h>
0014 #include <rtems/termiostypes.h>
0015 #include <bsp.h>
0016 
0017 #include <rtems/bspIo.h>
0018 
0019 #define UART_INTC0_IRQ_VECTOR(x) (64+13+(x))
0020 
0021 #define MCF_UART_USR_ERROR ( MCF_UART_USR_RB | \
0022                              MCF_UART_USR_FE | \
0023                              MCF_UART_USR_PE | \
0024                              MCF_UART_USR_OE )
0025 
0026 static ssize_t IntUartPollWrite(int minor, const char *buf, size_t len);
0027 static ssize_t IntUartInterruptWrite(int minor, const char *buf, size_t len);
0028 
0029 #define MAX_UART_INFO     3
0030 #define RX_BUFFER_SIZE    512
0031 
0032 struct IntUartInfoStruct
0033 {
0034   int iomode;
0035   volatile int uimr;
0036   int baud;
0037   int databits;
0038   int parity;
0039   int stopbits;
0040   int hwflow;
0041   int rx_in;
0042   int rx_out;
0043   char rx_buffer[RX_BUFFER_SIZE];
0044   void *ttyp;
0045 };
0046 
0047 struct IntUartInfoStruct IntUartInfo[MAX_UART_INFO];
0048 
0049 /***************************************************************************
0050    Function : IntUartSet
0051 
0052    Description : This updates the hardware UART settings.
0053  ***************************************************************************/
0054 static void
0055 IntUartSet(int minor, int baud, int databits, int parity, int stopbits,
0056            int hwflow)
0057 {
0058   int divisor;
0059   uint32_t clock_speed;
0060   uint8_t umr1 = 0;
0061   uint8_t umr2 = 0;
0062   struct IntUartInfoStruct *info = &IntUartInfo[minor];
0063   int level;
0064 
0065   rtems_interrupt_disable(level);
0066 
0067   /* disable interrupts, clear RTS line, and disable the UARTS */
0068   MCF_UART_UIMR(minor) = 0;
0069   MCF_UART_UOP0(minor) = 1;
0070   MCF_UART_UCR(minor) = (MCF_UART_UCR_TX_DISABLED | MCF_UART_UCR_RX_DISABLED);
0071 
0072   /* save the current values */
0073   info->uimr = 0;
0074   info->baud = baud;
0075   info->databits = databits;
0076   info->parity = parity;
0077   info->stopbits = stopbits;
0078   info->hwflow = hwflow;
0079 
0080   clock_speed = bsp_get_CPU_clock_speed();
0081   /* determine the baud divisor value */
0082   divisor = ((clock_speed) / (32 * baud));
0083   if (divisor < 2)
0084     divisor = 2;
0085 
0086   /* check to see if doing hardware flow control */
0087   if (hwflow) {
0088     /* set hardware flow options */
0089     umr1 |= MCF_UART_UMR_RXRTS;
0090     umr2 |= MCF_UART_UMR_TXCTS;
0091   }
0092 
0093   /* determine the new umr values */
0094   umr1 |= (parity | databits);
0095   umr2 |= (stopbits);
0096 
0097   /* reset the uart */
0098   MCF_UART_UCR(minor) = MCF_UART_UCR_RESET_ERROR;
0099   MCF_UART_UCR(minor) = MCF_UART_UCR_RESET_RX;
0100   MCF_UART_UCR(minor) = MCF_UART_UCR_RESET_TX;
0101 
0102   /* reset the uart mode register and update values */
0103   MCF_UART_UCR(minor) = MCF_UART_UCR_RESET_MR;
0104   MCF_UART_UMR(minor) = umr1;
0105   MCF_UART_UMR(minor) = umr2;
0106 
0107   /* set the baud rate values */
0108   MCF_UART_UCSR(minor) =
0109     (MCF_UART_UCSR_RCS_SYS_CLK | MCF_UART_UCSR_TCS_SYS_CLK);
0110   MCF_UART_UBG1(minor) = (divisor & 0xff00) >> 8;
0111   MCF_UART_UBG2(minor) = (divisor & 0x00ff);
0112 
0113   /* enable the uart */
0114   MCF_UART_UCR(minor) = (MCF_UART_UCR_TX_ENABLED | MCF_UART_UCR_RX_ENABLED);
0115 
0116   /* check to see if interrupts need to be enabled */
0117   if (info->iomode != TERMIOS_POLLED) {
0118     /* enable rx interrupts */
0119     info->uimr |= MCF_UART_UIMR_RXRDY_FU;
0120     MCF_UART_UIMR(minor) = info->uimr;
0121   }
0122 
0123   /* check to see if doing hardware flow control */
0124   if (hwflow) {
0125     /* assert the RTS line */
0126     MCF_UART_UOP1(minor) = 1;
0127   }
0128 
0129   rtems_interrupt_enable(level);
0130 
0131 }
0132 
0133 /***************************************************************************
0134    Function : IntUartSetAttributes
0135 
0136    Description : This provides the hardware-dependent portion of tcsetattr().
0137    value and sets it. At the moment this just sets the baud rate.
0138 
0139    Note: The highest baudrate is 115200 as this stays within
0140    an error of +/- 5% at 25MHz processor clock
0141  ***************************************************************************/
0142 static int IntUartSetAttributes(int minor, const struct termios *t)
0143 {
0144   /* set default index values */
0145   int baud = (int) 19200;
0146   int databits = (int) MCF_UART_UMR_BC_8;
0147   int parity = (int) MCF_UART_UMR_PM_NONE;
0148   int stopbits = (int) MCF_UART_UMR_SB_STOP_BITS_1;
0149   int hwflow = (int) 0;
0150   struct IntUartInfoStruct *info = &IntUartInfo[minor];
0151 
0152   /* check to see if input is valid */
0153   if (t != (const struct termios *) 0) {
0154     /* determine baud rate index */
0155     baud = rtems_termios_baud_to_number(t->c_ospeed);
0156 
0157     /* determine data bits */
0158     switch (t->c_cflag & CSIZE) {
0159       case CS5:
0160         databits = (int) MCF_UART_UMR_BC_5;
0161         break;
0162       case CS6:
0163         databits = (int) MCF_UART_UMR_BC_6;
0164         break;
0165       case CS7:
0166         databits = (int) MCF_UART_UMR_BC_7;
0167         break;
0168       case CS8:
0169         databits = (int) MCF_UART_UMR_BC_8;
0170         break;
0171     }
0172 
0173     /* determine if parity is enabled */
0174     if (t->c_cflag & PARENB) {
0175       if (t->c_cflag & PARODD) {
0176         /* odd parity */
0177         parity = (int) MCF_UART_UMR_PM_ODD;
0178       } else {
0179         /* even parity */
0180         parity = (int) MCF_UART_UMR_PM_EVEN;
0181       }
0182     }
0183 
0184     /* determine stop bits */
0185     if (t->c_cflag & CSTOPB) {
0186       /* two stop bits */
0187       stopbits = (int) MCF_UART_UMR_SB_STOP_BITS_2;
0188     }
0189 
0190     /* check to see if hardware flow control */
0191     if (t->c_cflag & CRTSCTS) {
0192       hwflow = 1;
0193     }
0194   }
0195 
0196   /* check to see if values have changed */
0197   if ((baud != info->baud) ||
0198       (databits != info->databits) ||
0199       (parity != info->parity) ||
0200       (stopbits != info->stopbits) || (hwflow != info->hwflow)) {
0201 
0202     /* call function to set values */
0203     IntUartSet(minor, baud, databits, parity, stopbits, hwflow);
0204   }
0205 
0206   return (RTEMS_SUCCESSFUL);
0207 
0208 }
0209 
0210 /***************************************************************************
0211    Function : IntUartInterruptHandler
0212 
0213    Description : This is the interrupt handler for the internal uart. It
0214    determines which channel caused the interrupt before queueing any received
0215    chars and dequeueing chars waiting for transmission.
0216  ***************************************************************************/
0217 static rtems_isr IntUartInterruptHandler(rtems_vector_number v)
0218 {
0219   unsigned int chan = v - UART_INTC0_IRQ_VECTOR(0);
0220   struct IntUartInfoStruct *info = &IntUartInfo[chan];
0221 
0222   /* check to see if received data */
0223   if (MCF_UART_UISR(chan) & MCF_UART_UISR_RXRDY_FU) {
0224     /* read data and put into the receive buffer */
0225     while (MCF_UART_USR(chan) & MCF_UART_USR_RXRDY) {
0226 
0227       if (MCF_UART_USR(chan) & MCF_UART_USR_ERROR) {
0228         /* clear the error */
0229         MCF_UART_UCR(chan) = MCF_UART_UCR_RESET_ERROR;
0230       }
0231       /* put data in rx buffer and check for errors */
0232       info->rx_buffer[info->rx_in] = MCF_UART_URB(chan);
0233 
0234       /* update buffer values */
0235       info->rx_in++;
0236 
0237       if (info->rx_in >= RX_BUFFER_SIZE) {
0238         info->rx_in = 0;
0239       }
0240     }
0241     /* Make sure the port has been opened */
0242     if (info->ttyp) {
0243 
0244       /* check to see if task driven */
0245       if (info->iomode == TERMIOS_TASK_DRIVEN) {
0246         /* notify rx task that rx buffer has data */
0247         rtems_termios_rxirq_occured(info->ttyp);
0248       } else {
0249         /* Push up the received data */
0250         rtems_termios_enqueue_raw_characters(info->ttyp, info->rx_buffer,
0251                                              info->rx_in);
0252         info->rx_in = 0;
0253       }
0254     }
0255   }
0256 
0257   /* check to see if data needs to be transmitted */
0258   if ((info->uimr & MCF_UART_UIMR_TXRDY) &&
0259       (MCF_UART_UISR(chan) & MCF_UART_UISR_TXRDY)) {
0260 
0261     /* disable tx interrupts */
0262     info->uimr &= ~MCF_UART_UIMR_TXRDY;
0263     MCF_UART_UIMR(chan) = info->uimr;
0264 
0265     /* tell upper level that character has been sent */
0266     if (info->ttyp)
0267       rtems_termios_dequeue_characters(info->ttyp, 1);
0268   }
0269 }
0270 
0271 /***************************************************************************
0272    Function : IntUartInitialize
0273 
0274    Description : This initialises the internal uart hardware for all
0275    internal uarts. If the internal uart is to be interrupt driven then the
0276    interrupt vectors are hooked.
0277  ***************************************************************************/
0278 static void IntUartInitialize(void)
0279 {
0280   unsigned int chan;
0281   struct IntUartInfoStruct *info;
0282   rtems_isr_entry old_handler;
0283   int level;
0284 
0285   for (chan = 0; chan < MAX_UART_INFO; chan++) {
0286     info = &IntUartInfo[chan];
0287 
0288     info->ttyp = NULL;
0289     info->rx_in = 0;
0290     info->rx_out = 0;
0291     info->baud = -1;
0292     info->databits = -1;
0293     info->parity = -1;
0294     info->stopbits = -1;
0295     info->hwflow = -1;
0296     info->iomode = TERMIOS_POLLED;                /*polled console io */
0297 
0298     MCF_UART_UACR(chan) = 0;
0299     MCF_UART_UIMR(chan) = 0;
0300     if (info->iomode != TERMIOS_POLLED) {
0301       rtems_interrupt_catch(IntUartInterruptHandler,
0302                             UART_INTC0_IRQ_VECTOR(chan), &old_handler);
0303     }
0304 
0305     /* set uart default values */
0306     IntUartSetAttributes(chan, NULL);
0307 
0308     /* unmask interrupt */
0309     rtems_interrupt_disable(level);
0310     switch (chan) {
0311       case 0:
0312         MCF_INTC0_ICR13 = MCF_INTC_ICR_IL(UART0_IRQ_LEVEL) |
0313           MCF_INTC_ICR_IP(UART0_IRQ_PRIORITY);
0314         MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_MASK13 | MCF_INTC_IMRL_MASKALL);
0315         break;
0316 
0317       case 1:
0318         MCF_INTC0_ICR14 = MCF_INTC_ICR_IL(UART1_IRQ_LEVEL) |
0319           MCF_INTC_ICR_IP(UART1_IRQ_PRIORITY);
0320         MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_MASK14 | MCF_INTC_IMRL_MASKALL);
0321         break;
0322 
0323       case 2:
0324         MCF_INTC0_ICR15 = MCF_INTC_ICR_IL(UART2_IRQ_LEVEL) |
0325           MCF_INTC_ICR_IP(UART2_IRQ_PRIORITY);
0326         MCF_INTC0_IMRL &= ~(MCF_INTC_IMRL_MASK15 | MCF_INTC_IMRL_MASKALL);
0327         break;
0328     }
0329     rtems_interrupt_enable(level);
0330 
0331   }                                               /* of chan loop */
0332 
0333 }                                                 /* IntUartInitialise */
0334 
0335 /***************************************************************************
0336    Function : IntUartInterruptWrite
0337 
0338    Description : This writes a single character to the appropriate uart
0339    channel. This is either called during an interrupt or in the user's task
0340    to initiate a transmit sequence. Calling this routine enables Tx
0341    interrupts.
0342  ***************************************************************************/
0343 static ssize_t IntUartInterruptWrite(int minor, const char *buf, size_t len)
0344 {
0345   if (len > 0) {
0346     /* write out character */
0347     MCF_UART_UTB(minor) = *buf;
0348 
0349     /* enable tx interrupt */
0350     IntUartInfo[minor].uimr |= MCF_UART_UIMR_TXRDY;
0351     MCF_UART_UIMR(minor) = IntUartInfo[minor].uimr;
0352   }
0353 
0354   return (0);
0355 }
0356 
0357 /***************************************************************************
0358    Function : IntUartInterruptOpen
0359 
0360    Description : This enables interrupts when the tty is opened.
0361  ***************************************************************************/
0362 static int IntUartInterruptOpen(int major, int minor, void *arg)
0363 {
0364   struct IntUartInfoStruct *info = &IntUartInfo[minor];
0365 
0366   /* enable the uart */
0367   MCF_UART_UCR(minor) = (MCF_UART_UCR_TX_ENABLED | MCF_UART_UCR_RX_ENABLED);
0368 
0369   /* check to see if interrupts need to be enabled */
0370   if (info->iomode != TERMIOS_POLLED) {
0371     /* enable rx interrupts */
0372     info->uimr |= MCF_UART_UIMR_RXRDY_FU;
0373     MCF_UART_UIMR(minor) = info->uimr;
0374   }
0375 
0376   /* check to see if doing hardware flow control */
0377   if (info->hwflow) {
0378     /* assert the RTS line */
0379     MCF_UART_UOP1(minor) = 1;
0380   }
0381 
0382   return (0);
0383 }
0384 
0385 /***************************************************************************
0386    Function : IntUartInterruptClose
0387 
0388    Description : This disables interrupts when the tty is closed.
0389  ***************************************************************************/
0390 static int IntUartInterruptClose(int major, int minor, void *arg)
0391 {
0392   struct IntUartInfoStruct *info = &IntUartInfo[minor];
0393 
0394   /* disable the interrupts and the uart */
0395   MCF_UART_UIMR(minor) = 0;
0396   MCF_UART_UCR(minor) = (MCF_UART_UCR_TX_DISABLED | MCF_UART_UCR_RX_DISABLED);
0397 
0398   /* reset values */
0399   info->ttyp = NULL;
0400   info->uimr = 0;
0401   info->rx_in = 0;
0402   info->rx_out = 0;
0403 
0404   return (0);
0405 }
0406 
0407 /***************************************************************************
0408    Function : IntUartTaskRead
0409 
0410    Description : This reads all available characters from the internal uart
0411    and places them into the termios buffer.  The rx interrupts will be
0412    re-enabled after all data has been read.
0413  ***************************************************************************/
0414 static int IntUartTaskRead(int minor)
0415 {
0416   char buffer[RX_BUFFER_SIZE];
0417   int count;
0418   int rx_in;
0419   int index = 0;
0420   struct IntUartInfoStruct *info = &IntUartInfo[minor];
0421 
0422   /* determine number of values to copy out */
0423   rx_in = info->rx_in;
0424   if (info->rx_out <= rx_in) {
0425     count = rx_in - info->rx_out;
0426   } else {
0427     count = (RX_BUFFER_SIZE - info->rx_out) + rx_in;
0428   }
0429 
0430   /* copy data into local buffer from rx buffer */
0431   while ((index < count) && (index < RX_BUFFER_SIZE)) {
0432     /* copy data byte */
0433     buffer[index] = info->rx_buffer[info->rx_out];
0434     index++;
0435 
0436     /* increment rx buffer values */
0437     info->rx_out++;
0438     if (info->rx_out >= RX_BUFFER_SIZE) {
0439       info->rx_out = 0;
0440     }
0441   }
0442 
0443   /* check to see if buffer is not empty */
0444   if (count > 0) {
0445     /* set characters into termios buffer  */
0446     rtems_termios_enqueue_raw_characters(info->ttyp, buffer, count);
0447   }
0448 
0449   return (EOF);
0450 }
0451 
0452 /***************************************************************************
0453    Function : IntUartPollRead
0454 
0455    Description : This reads a character from the internal uart. It returns
0456    to the caller without blocking if not character is waiting.
0457  ***************************************************************************/
0458 static int IntUartPollRead(int minor)
0459 {
0460   if ((MCF_UART_USR(minor) & MCF_UART_USR_RXRDY) == 0)
0461     return (-1);
0462 
0463   return (MCF_UART_URB(minor));
0464 }
0465 
0466 /***************************************************************************
0467    Function : IntUartPollWrite
0468 
0469    Description : This writes out each character in the buffer to the
0470    appropriate internal uart channel waiting till each one is sucessfully
0471    transmitted.
0472  ***************************************************************************/
0473 static ssize_t IntUartPollWrite(int minor, const char *buf, size_t len)
0474 {
0475   size_t retval = len;
0476   /* loop over buffer */
0477   while (len--) {
0478     /* block until we can transmit */
0479     while ((MCF_UART_USR(minor) & MCF_UART_USR_TXRDY) == 0)
0480       continue;
0481     /* transmit data byte */
0482     MCF_UART_UTB(minor) = *buf++;
0483   }
0484   return retval;
0485 }
0486 
0487 /***************************************************************************
0488    Function : console_initialize
0489 
0490    Description : This initialises termios, both sets of uart hardware before
0491    registering /dev/tty devices for each channel and the system /dev/console.
0492  ***************************************************************************/
0493 rtems_device_driver console_initialize(rtems_device_major_number major,
0494                                        rtems_device_minor_number minor,
0495                                        void *arg)
0496 {
0497   rtems_status_code status;
0498 
0499   /* Set up TERMIOS */
0500   rtems_termios_initialize();
0501 
0502   /* set io modes for the different channels and initialize device */
0503   IntUartInfo[minor].iomode = TERMIOS_IRQ_DRIVEN;
0504   IntUartInitialize();
0505 
0506   /* Register the console port */
0507   status = rtems_io_register_name("/dev/console", major, CONSOLE_PORT);
0508   if (status != RTEMS_SUCCESSFUL) {
0509     rtems_fatal_error_occurred(status);
0510   }
0511 
0512   /* Register the other port */
0513   if (CONSOLE_PORT != 0) {
0514     status = rtems_io_register_name("/dev/tty00", major, 0);
0515     if (status != RTEMS_SUCCESSFUL) {
0516       rtems_fatal_error_occurred(status);
0517     }
0518   }
0519   if (CONSOLE_PORT != 1) {
0520     status = rtems_io_register_name("/dev/tty01", major, 1);
0521     if (status != RTEMS_SUCCESSFUL) {
0522       rtems_fatal_error_occurred(status);
0523     }
0524   }
0525 
0526   return (RTEMS_SUCCESSFUL);
0527 }
0528 
0529 /***************************************************************************
0530    Function : console_open
0531 
0532    Description : This actually opens the device depending on the minor
0533    number set during initialisation. The device specific access routines are
0534    passed to termios when the devices is opened depending on whether it is
0535    polled or not.
0536  ***************************************************************************/
0537 rtems_device_driver console_open(rtems_device_major_number major,
0538                                  rtems_device_minor_number minor, void *arg)
0539 {
0540   rtems_status_code status = RTEMS_INVALID_NUMBER;
0541   rtems_libio_open_close_args_t *args = (rtems_libio_open_close_args_t *) arg;
0542   struct IntUartInfoStruct *info;
0543 
0544   static const rtems_termios_callbacks IntUartPollCallbacks = {
0545     NULL,                                         /* firstOpen */
0546     NULL,                                         /* lastClose */
0547     IntUartPollRead,                              /* pollRead */
0548     IntUartPollWrite,                             /* write */
0549     IntUartSetAttributes,                         /* setAttributes */
0550     NULL,                                         /* stopRemoteTx */
0551     NULL,                                         /* startRemoteTx */
0552     TERMIOS_POLLED                                /* mode */
0553   };
0554   static const rtems_termios_callbacks IntUartIntrCallbacks = {
0555     IntUartInterruptOpen,                         /* firstOpen */
0556     IntUartInterruptClose,                        /* lastClose */
0557     NULL,                                         /* pollRead */
0558     IntUartInterruptWrite,                        /* write */
0559     IntUartSetAttributes,                         /* setAttributes */
0560     NULL,                                         /* stopRemoteTx */
0561     NULL,                                         /* startRemoteTx */
0562     TERMIOS_IRQ_DRIVEN                            /* mode */
0563   };
0564 
0565   static const rtems_termios_callbacks IntUartTaskCallbacks = {
0566     IntUartInterruptOpen,                         /* firstOpen */
0567     IntUartInterruptClose,                        /* lastClose */
0568     IntUartTaskRead,                              /* pollRead */
0569     IntUartInterruptWrite,                        /* write */
0570     IntUartSetAttributes,                         /* setAttributes */
0571     NULL,                                         /* stopRemoteTx */
0572     NULL,                                         /* startRemoteTx */
0573     TERMIOS_TASK_DRIVEN                           /* mode */
0574   };
0575 
0576   /* open the port depending on the minor device number */
0577   if ((minor >= 0) && (minor < MAX_UART_INFO)) {
0578     info = &IntUartInfo[minor];
0579     switch (info->iomode) {
0580       case TERMIOS_POLLED:
0581         status = rtems_termios_open(major, minor, arg, &IntUartPollCallbacks);
0582         break;
0583       case TERMIOS_IRQ_DRIVEN:
0584         status = rtems_termios_open(major, minor, arg, &IntUartIntrCallbacks);
0585         info->ttyp = args->iop->data1;
0586         break;
0587       case TERMIOS_TASK_DRIVEN:
0588         status = rtems_termios_open(major, minor, arg, &IntUartTaskCallbacks);
0589         info->ttyp = args->iop->data1;
0590         break;
0591     }
0592   }
0593 
0594   if (status == RTEMS_SUCCESSFUL) {
0595     /*
0596      * Reset the default baudrate.
0597      */
0598     struct termios term;
0599 
0600     if (tcgetattr(STDIN_FILENO, &term) >= 0) {
0601       term.c_cflag &= ~(CSIZE);
0602       term.c_cflag |= CS8;
0603       term.c_ispeed = B19200;
0604       term.c_ospeed = B19200;
0605       tcsetattr(STDIN_FILENO, TCSANOW, &term);
0606     }
0607   }
0608 
0609   return (status);
0610 }
0611 
0612 /***************************************************************************
0613    Function : console_close
0614 
0615    Description : This closes the device via termios
0616  ***************************************************************************/
0617 rtems_device_driver console_close(rtems_device_major_number major,
0618                                   rtems_device_minor_number minor, void *arg)
0619 {
0620   return (rtems_termios_close(arg));
0621 }
0622 
0623 /******************
0624 *********************************************************
0625    Function : console_read
0626 
0627    Description : Read from the device via termios
0628  ***************************************************************************/
0629 rtems_device_driver console_read(rtems_device_major_number major,
0630                                  rtems_device_minor_number minor, void *arg)
0631 {
0632   return (rtems_termios_read(arg));
0633 }
0634 
0635 /***************************************************************************
0636    Function : console_write
0637 
0638    Description : Write to the device via termios
0639  ***************************************************************************/
0640 rtems_device_driver console_write(rtems_device_major_number major,
0641                                   rtems_device_minor_number minor, void *arg)
0642 {
0643   return (rtems_termios_write(arg));
0644 }
0645 
0646 /***************************************************************************
0647    Function : console_ioctl
0648 
0649    Description : Pass the IOCtl call to termios
0650  ***************************************************************************/
0651 rtems_device_driver console_control(rtems_device_major_number major,
0652                                     rtems_device_minor_number minor,
0653                                     void *arg)
0654 {
0655   return (rtems_termios_ioctl(arg));
0656 }