Back to home page

LXR

 
 

    


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

0001 /*
0002  *  This file contains the MBX8xx termios serial I/O package.
0003  *  Only asynchronous I/O is supported.
0004  *
0005  *  The SCCs and SMCs are assigned as follows
0006  *
0007  *   Channel     Device      Minor   Note
0008  *    SMC1      /dev/tty0      0
0009  *    SMC2      /dev/tty1      1
0010  *    SCC1                     2     N/A. Hardwired as ethernet port
0011  *    SCC2      /dev/tty2      3
0012  *    SCC3      /dev/tty3      4
0013  *    SCC4      /dev/tty4      5
0014  *
0015  * The SCCs and SMCs on the eval board are assigned as follows
0016  *
0017  *   Channel     Device      Minor   Termios
0018  *    SMC1      /dev/tty3      4       no
0019  *    SMC2      /dev/tty4      5       no
0020  *    SCC1      /dev/tty0      0       no
0021  *    SCC2      /dev/console   1       yes
0022  *    SCC3      /dev/tty1      2       no   * USED FOR NETWORK I/F
0023  *    SCC4      /dev/tty2      3       no   * USED FOR NETWORK I/F
0024  *
0025  *  All ports support termios. The use of termios is recommended for real-time
0026  *  applications. Termios provides buffering and input processing. When not
0027  *  using termios, processing is limited to the substitution of LF for CR on
0028  *  input, and the output of a CR following the output of a LF character.
0029  *  Note that the terminal should not send CR/LF pairs when the return key
0030  *  is pressed, and that output lines are terminated with LF/CR, not CR/LF
0031  *  (although that would be easy to change).
0032  *
0033  *  I/O may be interrupt-driven (recommended for real-time applications) or
0034  *  polled. Polled I/O may be performed by this device driver entirely, or
0035  *  in part by EPPCBug. With EPPCBug 1.1, polled I/O is limited to the
0036  *  EPPCBug debug console. This is a limitation of the firmware. Later
0037  *  firmware may be able to do I/O through any port. This code assumes
0038  *  that the EPPCBug console is the default: SMC1. If the console and
0039  *  printk ports are set to anything else with EPPCBug polled I/O, the
0040  *  system will hang. Only port SMC1 is usable with EPPCBug polled I/O.
0041  *
0042  *  LIMITATIONS:
0043  *
0044  *  It is not possible to use different I/O modes on the different ports. The
0045  *  exception is with printk. The printk port can use a different mode from
0046  *  the other ports. If this is done, it is important not to open the printk
0047  *  port from an RTEMS application.
0048  *
0049  *  Currently, the I/O modes are determined at build time. It would be much
0050  *  better to have the mode selected at boot time based on parameters in
0051  *  NVRAM.
0052  *
0053  *  Interrupt-driven I/O requires termios.
0054  *
0055  *  TESTS:
0056  *
0057  *  TO RUN THE TESTS, USE POLLED I/O WITHOUT TERMIOS SUPPORT. Some tests
0058  *  play with the interrupt masks and turn off I/O. Those tests will hang
0059  *  when interrupt-driven I/O is used. Other tests, such as cdtest, do I/O
0060  *  from the static constructors before the console is open. This test
0061  *  will not work with interrupt-driven I/O. Because of the buffering
0062  *  performed in termios, test output may not be in sequence.The tests
0063  *  should all be fixed to work with interrupt-driven I/O and to
0064  *  produce output in the expected sequence. Obviously, the termios test
0065  *  requires termios support in the driver.
0066  *
0067  *  Set CONSOLE_MINOR to the appropriate device minor number in the
0068  *  config file. This allows the RTEMS application console to be different
0069  *  from the EPPBug debug console or the GDB port.
0070  *
0071  *  This driver handles all five available serial ports: it distinguishes
0072  *  the sub-devices using minor device numbers. It is not possible to have
0073  *  other protocols running on the other ports when this driver is used as
0074  *  currently written.
0075  */
0076 
0077 /*
0078  *  Based on code (alloc860.c in eth_comm port) by
0079  *  Jay Monkman (jmonkman@frasca.com),
0080  *  Copyright (C) 1998 by Frasca International, Inc.
0081  *
0082  *  Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
0083  *  and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>.
0084  *  Copyright (c) 2000, National Research Council of Canada
0085  *
0086  *  Modifications by Andy Dachs <iwe@fsmal.net> for MPC8260
0087  *  support.
0088  */
0089 #include <stdarg.h>
0090 #include <stdio.h>
0091 #include <termios.h>
0092 
0093 #include <rtems/console.h>
0094 #include <rtems/bspIo.h>
0095 #include <rtems/libio.h>
0096 #include <bsp.h>
0097 
0098 static void _BSP_output_char( char c );
0099 static rtems_status_code do_poll_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);
0100 static rtems_status_code do_poll_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);
0101 
0102 BSP_output_char_function_type     BSP_output_char = _BSP_output_char;
0103 BSP_polling_getchar_function_type BSP_poll_char = NULL;
0104 
0105 /*
0106  *  do_poll_read
0107  *
0108  *  Input characters through polled I/O. Returns has soon as a character has
0109  *  been received. Otherwise, if we wait for the number of requested characters,
0110  *  we could be here forever!
0111  *
0112  *  CR is converted to LF on input. The terminal should not send a CR/LF pair
0113  *  when the return or enter key is pressed.
0114  *
0115  *  Input parameters:
0116  *    major - ignored. Should be the major number for this driver.
0117  *    minor - selected channel.
0118  *    arg->buffer - where to put the received characters.
0119  *    arg->count  - number of characters to receive before returning--Ignored.
0120  *
0121  *  Output parameters:
0122  *    arg->bytes_moved - the number of characters read. Always 1.
0123  *
0124  *  Return value: RTEMS_SUCCESSFUL
0125  *
0126  *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
0127  */
0128 static rtems_status_code do_poll_read(
0129   rtems_device_major_number major,
0130   rtems_device_minor_number minor,
0131   void                    * arg
0132 )
0133 {
0134   rtems_libio_rw_args_t *rw_args = arg;
0135   int c;
0136 
0137 #define BSP_READ  m8xx_uart_pollRead
0138 
0139   while( (c = BSP_READ(minor)) == -1 );
0140   rw_args->buffer[0] = (uint8_t)c;
0141   if( rw_args->buffer[0] == '\r' )
0142       rw_args->buffer[0] = '\n';
0143   rw_args->bytes_moved = 1;
0144   return RTEMS_SUCCESSFUL;
0145 }
0146 
0147 /*
0148  *  do_poll_write
0149  *
0150  *  Output characters through polled I/O. Returns only once every character has
0151  *  been sent.
0152  *
0153  *  CR is transmitted AFTER a LF on output.
0154  *
0155  *  Input parameters:
0156  *    major - ignored. Should be the major number for this driver.
0157  *    minor - selected channel
0158  *    arg->buffer - where to get the characters to transmit.
0159  *    arg->count  - the number of characters to transmit before returning.
0160  *
0161  *  Output parameters:
0162  *    arg->bytes_moved - the number of characters read
0163  *
0164  *  Return value: RTEMS_SUCCESSFUL
0165  *
0166  *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
0167  */
0168 static rtems_status_code do_poll_write(
0169   rtems_device_major_number major,
0170   rtems_device_minor_number minor,
0171   void                    * arg
0172 )
0173 {
0174   rtems_libio_rw_args_t *rw_args = arg;
0175   uint32_t   i;
0176   char cr ='\r';
0177 
0178 #define BSP_WRITE m8xx_uart_pollWrite
0179 
0180   for( i = 0; i < rw_args->count; i++ ) {
0181     BSP_WRITE(minor, &(rw_args->buffer[i]), 1);
0182     if ( rw_args->buffer[i] == '\n' )
0183       BSP_WRITE(minor, &cr, 1);
0184   }
0185   rw_args->bytes_moved = i;
0186   return RTEMS_SUCCESSFUL;
0187 
0188 }
0189 
0190 /*
0191  *  Print functions prototyped in bspIo.h
0192  */
0193 
0194 static void _BSP_output_char( char c )
0195 {
0196   /*
0197    *  Can't rely on console_initialize having been called before this function
0198    *  is used, so it may fail unless output is done through EPPC-Bug.
0199    */
0200 #define PRINTK_WRITE m8xx_uart_pollWrite
0201 
0202   PRINTK_WRITE( PRINTK_MINOR, &c, 1 );
0203 }
0204 
0205 /*
0206  ***************
0207  * BOILERPLATE *
0208  ***************
0209  *
0210  *  All these functions are prototyped in rtems/c/src/lib/include/console.h.
0211  */
0212 
0213 /*
0214  * Initialize and register the device
0215  */
0216 rtems_device_driver console_initialize(
0217   rtems_device_major_number major,
0218   rtems_device_minor_number minor,
0219   void *arg
0220 )
0221 {
0222   rtems_status_code status;
0223   rtems_device_minor_number console_minor;
0224 
0225   /*
0226    * Set up TERMIOS if needed
0227    */
0228 
0229     console_minor = CONSOLE_MINOR;
0230 
0231 #if UARTS_USE_TERMIOS == 1
0232 
0233     rtems_termios_initialize ();
0234 #else
0235     rtems_termios_initialize ();
0236 #endif /* UARTS_USE_TERMIOS */
0237 
0238   /*
0239    *  Do common initialization.
0240    */
0241   m8xx_uart_initialize();
0242 
0243   /*
0244    * Do device-specific initialization
0245    */
0246 #if 0
0247   m8xx_uart_smc_initialize(SMC1_MINOR); /* /dev/tty4 */
0248   m8xx_uart_smc_initialize(SMC2_MINOR); /* /dev/tty5 */
0249 #endif
0250 
0251   m8xx_uart_scc_initialize(SCC1_MINOR); /* /dev/tty0    */
0252   m8xx_uart_scc_initialize(SCC2_MINOR); /* /dev/tty1    */
0253 
0254 #if 0  /* used as network connections */
0255   m8xx_uart_scc_initialize(SCC3_MINOR); /* /dev/tty2    */
0256   m8xx_uart_scc_initialize(SCC4_MINOR); /* /dev/tty3    */
0257 #endif
0258 
0259   /*
0260    * Set up interrupts
0261    */
0262   m8xx_uart_interrupts_initialize();
0263 
0264   status = rtems_io_register_name ("/dev/tty0", major, SCC1_MINOR);
0265   if (status != RTEMS_SUCCESSFUL)
0266     rtems_fatal_error_occurred (status);
0267   chmod("/dev/tty0",0660);
0268   chown("/dev/tty0",2,0);
0269 
0270   status = rtems_io_register_name ("/dev/tty1", major, SCC2_MINOR);
0271   if (status != RTEMS_SUCCESSFUL)
0272     rtems_fatal_error_occurred (status);
0273   chmod("/dev/tty1",0660);
0274   chown("/dev/tty1",2,0);
0275 
0276 #if 0
0277   status = rtems_io_register_name ("/dev/tty2", major, SCC3_MINOR);
0278   if (status != RTEMS_SUCCESSFUL)
0279     rtems_fatal_error_occurred (status);
0280 
0281   status = rtems_io_register_name ("/dev/tty3", major, SCC4_MINOR);
0282   if (status != RTEMS_SUCCESSFUL)
0283     rtems_fatal_error_occurred (status);
0284 
0285   status = rtems_io_register_name ("/dev/tty4", major, SMC1_MINOR);
0286   if (status != RTEMS_SUCCESSFUL)
0287     rtems_fatal_error_occurred (status);
0288 
0289   status = rtems_io_register_name ("/dev/tty5", major, SMC2_MINOR);
0290   if (status != RTEMS_SUCCESSFUL)
0291     rtems_fatal_error_occurred (status);
0292 #endif
0293   /* Now register the RTEMS console */
0294   status = rtems_io_register_name ("/dev/console", major, console_minor);
0295   if (status != RTEMS_SUCCESSFUL)
0296     rtems_fatal_error_occurred (status);
0297   chmod("/dev/console",0666);
0298   chown("/dev/console",2,0);
0299 
0300   return RTEMS_SUCCESSFUL;
0301 }
0302 
0303 /*
0304  * Open the device
0305  */
0306 rtems_device_driver console_open(
0307   rtems_device_major_number major,
0308   rtems_device_minor_number minor,
0309   void *arg
0310 )
0311 {
0312 #if UARTS_IO_MODE == 1  /* RTEMS interrupt-driven I/O with termios */
0313   /* Used to track termios private data for callbacks */
0314   extern struct rtems_termios_tty *ttyp[];
0315   rtems_libio_open_close_args_t *args = arg;
0316 
0317   static const rtems_termios_callbacks intrCallbacks = {
0318     NULL,                           /* firstOpen */
0319     NULL,                           /* lastClose */
0320     NULL,                         /* pollRead */
0321     m8xx_uart_write,              /* write */
0322     m8xx_uart_setAttributes,        /* setAttributes */
0323     NULL,                           /* stopRemoteTx */
0324     NULL,                           /* startRemoteTx */
0325     TERMIOS_IRQ_DRIVEN                  /* outputUsesInterrupts */
0326   };
0327 #else
0328 #if (UARTS_USE_TERMIOS == 1) && (UARTS_IO_MODE != 1)
0329   static const rtems_termios_callbacks pollCallbacks = {
0330     NULL,                           /* firstOpen */
0331     NULL,                           /* lastClose */
0332     m8xx_uart_pollRead,           /* pollRead */
0333     m8xx_uart_pollWrite,          /* write */
0334     m8xx_uart_setAttributes,      /* setAttributes */
0335     NULL,                           /* stopRemoteTx */
0336     NULL,                           /* startRemoteTx */
0337     TERMIOS_POLLED                /* outputUsesInterrupts */
0338   };
0339 #endif
0340 
0341 #endif
0342 
0343   rtems_status_code sc;
0344 
0345   if ( minor > NUM_PORTS-1 )
0346     return RTEMS_INVALID_NUMBER;
0347 
0348 #if UARTS_USE_TERMIOS == 1
0349 
0350 #if UARTS_IO_MODE == 1  /* RTEMS interrupt-driven I/O with termios */
0351   sc = rtems_termios_open( major, minor, arg, &intrCallbacks );
0352   ttyp[minor] = args->iop->data1;        /* Keep cookie returned by termios_open */
0353 #else                     /* RTEMS polled I/O with termios */
0354   sc = rtems_termios_open( major, minor, arg, &pollCallbacks );
0355 #endif
0356 
0357 #else /* UARTS_USE_TERMIOS != 1 */
0358   /* no termios -- default to polled I/O */
0359   sc = RTEMS_SUCCESSFUL;
0360 #endif /* UARTS_USE_TERMIOS != 1 */
0361 
0362   return sc;
0363 
0364 }
0365 
0366 /*
0367  * Close the device
0368  */
0369 rtems_device_driver console_close(
0370   rtems_device_major_number major,
0371   rtems_device_minor_number minor,
0372   void *arg
0373 )
0374 {
0375   if ( minor > NUM_PORTS-1 )
0376     return RTEMS_INVALID_NUMBER;
0377 
0378 #if UARTS_USE_TERMIOS == 1
0379   return rtems_termios_close( arg );
0380 #else
0381   return RTEMS_SUCCESSFUL;
0382 #endif
0383 
0384 }
0385 
0386 /*
0387  * Read from the device
0388  */
0389 rtems_device_driver console_read(
0390   rtems_device_major_number major,
0391   rtems_device_minor_number minor,
0392   void *arg
0393 )
0394 {
0395   if ( minor > NUM_PORTS-1 )
0396     return RTEMS_INVALID_NUMBER;
0397 
0398 #if UARTS_USE_TERMIOS == 1
0399   return rtems_termios_read( arg );
0400 #else
0401   return do_poll_read( major, minor, arg );
0402 #endif
0403 
0404 }
0405 
0406 /*
0407  * Write to the device
0408  */
0409 rtems_device_driver console_write(
0410   rtems_device_major_number major,
0411   rtems_device_minor_number minor,
0412   void *arg
0413 )
0414 {
0415   if ( minor > NUM_PORTS-1 )
0416     return RTEMS_INVALID_NUMBER;
0417 
0418 #if UARTS_USE_TERMIOS == 1
0419   return rtems_termios_write( arg );
0420 #else
0421     /* no termios -- default to polled */
0422   return do_poll_write( major, minor, arg );
0423 #endif
0424 
0425 }
0426 
0427 /*
0428  * Handle ioctl request.
0429  */
0430 rtems_device_driver console_control(
0431   rtems_device_major_number major,
0432   rtems_device_minor_number minor,
0433   void *arg
0434 )
0435 {
0436   if ( minor > NUM_PORTS-1 )
0437     return RTEMS_INVALID_NUMBER;
0438 
0439 #if UARTS_USE_TERMIOS == 1
0440   return rtems_termios_ioctl( arg );
0441 #else
0442   return RTEMS_SUCCESSFUL;
0443 #endif
0444 
0445 }
0446 
0447 /*
0448  *  Support routine for console-generic
0449  */
0450 int mbx8xx_console_get_configuration(void)
0451 {
0452 #if UARTS_IO_MODE == 1
0453   return 0x02;
0454 #else
0455   return 0;
0456 #endif
0457 
0458 }