Back to home page

LXR

 
 

    


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

0001 /***************************************************************************
0002  *
0003  * MODULE DESCRIPTION:
0004  * This module implements the RTEMS drivers for the PC serial ports
0005  * as /dev/ttyS1 for COM1 and /dev/ttyS2 as COM2. If one of the ports
0006  * is used as the console, this driver would fail to initialize.
0007  *
0008  * This code was based on the console driver. It is based on the
0009  * current termios framework. This is just a shell around the
0010  * termios support.
0011  *
0012  * by: Rosimildo da Silva:
0013  *     rdasilva@connecttel.com
0014  *     http://www.connecttel.com
0015  *
0016  ****************************************************************************/
0017 
0018 
0019 #include <inttypes.h>
0020 #include <stdio.h>
0021 #include <stdlib.h>
0022 #include <assert.h>
0023 
0024 #include <bsp.h>
0025 #include <bsp/irq.h>
0026 #include <rtems/bspIo.h>
0027 #include <rtems/libio.h>
0028 #include <rtems/termiostypes.h>
0029 #include <termios.h>
0030 #include <uart.h>
0031 #include <libcpu/cpuModel.h>
0032 #include <bsp/tty_drv.h>
0033 
0034 int BSP_poll_read(int);
0035 
0036 /* Internal routines */
0037 static int tty1_conSetAttr( int minor, const struct termios *t);
0038 static int tty2_conSetAttr( int minor, const struct termios *t);
0039 
0040 extern BSP_polling_getchar_function_type BSP_poll_char;
0041 extern int BSPConsolePort;
0042 extern void rtems_set_waiting_id_comx( int port,  rtems_id id, rtems_event_set event );
0043 
0044 /*
0045  *  TTYS1 - device driver INITIALIZE entry point.
0046  */
0047 rtems_device_driver
0048 tty1_initialize(rtems_device_major_number major,
0049                    rtems_device_minor_number minor,
0050                    void                      *arg)
0051 {
0052   rtems_status_code status;
0053 
0054   /* Check if this port is not been used as console */
0055   if( BSPConsolePort == BSP_UART_COM1 )
0056   {
0057     status = -1;
0058     printk("TTYS1: port selected as console.\n");
0059     rtems_fatal_error_occurred( status );
0060   }
0061 
0062   /*
0063    * Set up TERMIOS
0064    */
0065   rtems_termios_initialize();
0066 
0067   /*
0068    * Do device-specific initialization
0069    */
0070   /* 9600-8-N-1, without hardware flow control */
0071   BSP_uart_init( BSP_UART_COM1, 9600, CHR_8_BITS, 0, 0, 0 );
0072   status = rtems_interrupt_handler_install(
0073     BSP_UART_COM1_IRQ,
0074     "tty_drv",
0075     RTEMS_INTERRUPT_UNIQUE,
0076     BSP_uart_termios_isr_com1,
0077     NULL
0078   );
0079   assert(status == RTEMS_SUCCESSFUL);
0080   /*
0081    * Register the device
0082    */
0083   status = rtems_io_register_name ("/dev/ttyS1", major, 0);
0084   if (status != RTEMS_SUCCESSFUL)
0085   {
0086       printk("Error registering ttyS1 device!\n");
0087       rtems_fatal_error_occurred (status);
0088   }
0089   printk("Device: /dev/ttyS1 initialized.\n");
0090   return RTEMS_SUCCESSFUL;
0091 } /* tty_initialize */
0092 
0093 static int tty1_last_close(int major, int minor, void *arg)
0094 {
0095   rtems_status_code status;
0096 
0097   status = rtems_interrupt_handler_remove(
0098     BSP_UART_COM1_IRQ,
0099     BSP_uart_termios_isr_com1,
0100     NULL
0101   );
0102   assert(status == RTEMS_SUCCESSFUL);
0103   return 0;
0104 }
0105 
0106 /*
0107  * TTY1 - device driver OPEN entry point
0108  */
0109 rtems_device_driver
0110 tty1_open(rtems_device_major_number major,
0111                 rtems_device_minor_number minor,
0112                 void                      *arg)
0113 {
0114   rtems_status_code  status;
0115 #ifndef USE_TASK_DRIVEN
0116   static rtems_termios_callbacks cb =
0117   {
0118     NULL,                        /* firstOpen */
0119     tty1_last_close,             /* lastClose */
0120     NULL,                        /* poll read */
0121     BSP_uart_termios_write_com1, /* write */
0122     tty1_conSetAttr,             /* setAttributes */
0123     NULL,                        /* stopRemoteTx */
0124     NULL,                        /* startRemoteTx */
0125     TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
0126   };
0127 #else
0128   static rtems_termios_callbacks cb =
0129   {
0130     NULL,                        /* firstOpen */
0131     NULL,                        /* lastClose */
0132     BSP_uart_termios_read_com1,  /* poll read */
0133     BSP_uart_termios_write_com1, /* write */
0134     tty1_conSetAttr,             /* setAttributes */
0135     NULL,                        /* stopRemoteTx */
0136     NULL,                        /* startRemoteTx */
0137     TERMIOS_TASK_DRIVEN          /* outputUsesInterrupts */
0138   };
0139 #endif
0140 
0141   status = rtems_termios_open( major, minor, arg, &cb );
0142   if(status != RTEMS_SUCCESSFUL)
0143   {
0144      printk("Error openning tty1 device\n");
0145      return status;
0146   }
0147 
0148   /*
0149    * Pass data area info down to driver
0150    */
0151   BSP_uart_termios_set( BSP_UART_COM1,
0152                        ((rtems_libio_open_close_args_t *)arg)->iop->data1 );
0153   /* Enable interrupts  on channel */
0154   BSP_uart_intr_ctrl( BSP_UART_COM1, BSP_UART_INTR_CTRL_TERMIOS);
0155   return RTEMS_SUCCESSFUL;
0156 }
0157 
0158 /*
0159  * TTY - device driver CLOSE entry point
0160  */
0161 rtems_device_driver
0162 tty_close(rtems_device_major_number major,
0163               rtems_device_minor_number minor,
0164               void                      *arg)
0165 {
0166 
0167   return (rtems_termios_close (arg));
0168 
0169 } /* tty_close */
0170 
0171 /*
0172  * TTY device driver READ entry point.
0173  * Read characters from the tty device.
0174  */
0175 rtems_device_driver
0176 tty_read(rtems_device_major_number major,
0177              rtems_device_minor_number minor,
0178              void                      *arg)
0179 {
0180   return rtems_termios_read (arg);
0181 } /* tty_read */
0182 
0183 /*
0184  * TTY device driver WRITE entry point.
0185  * Write characters to the tty device.
0186  */
0187 rtems_device_driver
0188 tty_write(rtems_device_major_number major,
0189               rtems_device_minor_number minor,
0190               void                    * arg)
0191 {
0192     return rtems_termios_write (arg);
0193 
0194 } /* tty_write */
0195 
0196 /*
0197  * Handle ioctl request. This is a generic internal
0198  * routine to handle both devices.
0199  */
0200 static rtems_device_driver tty_control( int port, void  *arg )
0201 {
0202     rtems_libio_ioctl_args_t *args = arg;
0203     switch( args->command )
0204     {
0205        default:
0206       return rtems_termios_ioctl (arg);
0207         break;
0208    }
0209     args->ioctl_return = 0;
0210    return RTEMS_SUCCESSFUL;
0211 }
0212 
0213 /*
0214  * Handle ioctl request for ttyS1.
0215  */
0216 rtems_device_driver
0217 tty1_control(rtems_device_major_number major,
0218         rtems_device_minor_number minor,
0219         void                      * arg
0220 )
0221 {
0222   return tty_control( BSP_UART_COM1, arg );
0223 }
0224 
0225 static int
0226 conSetAttr(int port, int minor, const struct termios *t)
0227 {
0228   unsigned long baud, databits, parity, stopbits;
0229 
0230   baud = rtems_termios_baud_to_number(t->c_ospeed);
0231   if ( baud > 115200 )
0232     rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
0233 
0234   if (t->c_cflag & PARENB) {
0235     /* Parity is enabled */
0236     if (t->c_cflag & PARODD) {
0237       /* Parity is odd */
0238       parity = PEN;
0239     }
0240     else {
0241       /* Parity is even */
0242       parity = PEN | EPS;
0243     }
0244   }
0245   else {
0246     /* No parity */
0247     parity = 0;
0248   }
0249 
0250   switch (t->c_cflag & CSIZE) {
0251     case CS5: databits = CHR_5_BITS; break;
0252     case CS6: databits = CHR_6_BITS; break;
0253     case CS7: databits = CHR_7_BITS; break;
0254     default:  /* just to avoid warnings -- all cases are covered */
0255     case CS8: databits = CHR_8_BITS; break;
0256   }
0257 
0258   if (t->c_cflag & CSTOPB) {
0259     /* 2 stop bits */
0260     stopbits = STB;
0261   }
0262   else {
0263     /* 1 stop bit */
0264     stopbits = 0;
0265   }
0266 
0267   printk("Setting attributes, port=%X, baud=%d, linemode = 0x%02x\n",
0268          port, (int) baud, (int) (databits | parity | stopbits) );
0269   BSP_uart_set_attributes(port, baud, databits, parity, stopbits);
0270   return 0;
0271 }
0272 
0273 /*
0274  * Handle ioctl request for ttyS2.
0275  */
0276 static int
0277 tty1_conSetAttr( int minor, const struct termios *t)
0278 {
0279   return conSetAttr( BSP_UART_COM1, minor, t );
0280 }
0281 
0282 /*
0283  * TTY2 device driver INITIALIZE entry point.
0284  */
0285 rtems_device_driver
0286 tty2_initialize(rtems_device_major_number major,
0287                    rtems_device_minor_number minor,
0288                    void                      *arg)
0289 {
0290   rtems_status_code status;
0291 
0292   /* Check if this port is not been used as console */
0293   if( BSPConsolePort == BSP_UART_COM2 )
0294   {
0295     status = -1;
0296     printk("TTY2: port selected as console.\n");
0297     rtems_fatal_error_occurred( status );
0298   }
0299 
0300   /*
0301    * Set up TERMIOS
0302    */
0303   rtems_termios_initialize();
0304 
0305   /*
0306    * Do device-specific initialization
0307    */
0308   /* 9600-8-N-1, without hardware flow control */
0309   BSP_uart_init( BSP_UART_COM2, 9600, CHR_8_BITS, 0, 0, 0);
0310   status = rtems_interrupt_handler_install(
0311     BSP_UART_COM2_IRQ,
0312     "tty_drv",
0313     RTEMS_INTERRUPT_UNIQUE,
0314     BSP_uart_termios_isr_com2,
0315     NULL
0316   );
0317   assert(status == RTEMS_SUCCESSFUL);
0318 
0319   /*
0320    * Register the device
0321    */
0322   status = rtems_io_register_name ("/dev/ttyS2", major, 0);
0323   if (status != RTEMS_SUCCESSFUL)
0324   {
0325       printk("Error registering tty2 device!\n");
0326       rtems_fatal_error_occurred (status);
0327   }
0328   printk("Device: /dev/ttyS2 initialized.\n");
0329   return RTEMS_SUCCESSFUL;
0330 } /* tty_initialize */
0331 
0332 static int tty2_last_close(int major, int minor, void *arg)
0333 {
0334   rtems_status_code status;
0335 
0336   status = rtems_interrupt_handler_remove(
0337     BSP_UART_COM2_IRQ,
0338     BSP_uart_termios_isr_com2,
0339     NULL
0340   );
0341   assert(status == RTEMS_SUCCESSFUL);
0342   return 0;
0343 }
0344 
0345 /*
0346  * TTY2 device driver OPEN entry point
0347  */
0348 rtems_device_driver
0349 tty2_open(rtems_device_major_number major,
0350                 rtems_device_minor_number minor,
0351                 void                      *arg)
0352 {
0353   rtems_status_code              status;
0354 #ifndef USE_TASK_DRIVEN
0355   static rtems_termios_callbacks cb =
0356   {
0357     NULL,                        /* firstOpen */
0358     tty2_last_close,             /* lastClose */
0359     NULL,                        /* poll read */
0360     BSP_uart_termios_write_com2, /* write */
0361     tty2_conSetAttr,             /* setAttributes */
0362     NULL,                        /* stopRemoteTx */
0363     NULL,                        /* startRemoteTx */
0364     TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
0365   };
0366 #else
0367   static rtems_termios_callbacks cb =
0368   {
0369     NULL,                        /* firstOpen */
0370     NULL,                        /* lastClose */
0371     BSP_uart_termios_read_com2,  /* poll read */
0372     BSP_uart_termios_write_com2, /* write */
0373     tty2_conSetAttr,             /* setAttributes */
0374     NULL,                        /* stopRemoteTx */
0375     NULL,                        /* startRemoteTx */
0376     TERMIOS_TASK_DRIVEN          /* outputUsesInterrupts */
0377   };
0378 #endif
0379 
0380   status = rtems_termios_open (major, minor, arg, &cb);
0381   if(status != RTEMS_SUCCESSFUL)
0382   {
0383      printk("Error openning tty1 device\n");
0384      return status;
0385   }
0386 
0387   /*
0388    * Pass data area info down to driver
0389    */
0390   BSP_uart_termios_set( BSP_UART_COM2,
0391              ((rtems_libio_open_close_args_t *)arg)->iop->data1 );
0392    /* Enable interrupts  on channel */
0393   BSP_uart_intr_ctrl( BSP_UART_COM2, BSP_UART_INTR_CTRL_TERMIOS);
0394   return RTEMS_SUCCESSFUL;
0395 }
0396 
0397 /*
0398  * Handle ioctl request for TTY2
0399  */
0400 rtems_device_driver
0401 tty2_control(rtems_device_major_number major,
0402         rtems_device_minor_number minor,
0403         void                      * arg
0404 )
0405 {
0406    return tty_control( BSP_UART_COM2, arg );
0407 }
0408 
0409 static int
0410 tty2_conSetAttr( int minor, const struct termios *t)
0411 {
0412   return conSetAttr( BSP_UART_COM2, minor, t );
0413 }