Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:01

0001 /*
0002  * Console driver for SH-4 UART modules
0003  *
0004  * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia
0005  * Author: Alexandra Kossovsky <sasha@oktet.ru>
0006  *
0007  *  COPYRIGHT (c) 1989-1998.
0008  *  On-Line Applications Research Corporation (OAR).
0009  *
0010  *  The license and distribution terms for this file may be
0011  *  found in the file LICENSE in this distribution or at
0012  *  http://www.rtems.org/license/LICENSE.
0013  */
0014 
0015 #include <termios.h>
0016 
0017 #include <rtems/console.h>
0018 #include <rtems/libio.h>
0019 #include <bsp.h>
0020 
0021 #include "sh/sh4uart.h"
0022 
0023 /* Descriptor structures for two on-chip UART channels */
0024 sh4uart sh4_uarts[2];
0025 
0026 /* Console operations mode:
0027  *     0 - raw (non-termios) polled input/output
0028  *     1 - termios-based polled input/output
0029  *     2 - termios-based interrupt-driven input/output
0030  *     3 - non-termios over gdb stub
0031  */
0032 int console_mode = 3;
0033 #define CONSOLE_MODE_RAW  (0)
0034 #define CONSOLE_MODE_POLL (1)
0035 #define CONSOLE_MODE_INT  (2)
0036 #define CONSOLE_MODE_IPL  (3)
0037 
0038 /* Wrapper functions for SH-4 UART generic driver */
0039 
0040 /* console_poll_read --
0041  *     wrapper for poll read function
0042  *
0043  * PARAMETERS:
0044  *     minor - minor device number
0045  *
0046  * RETURNS:
0047  *     character code readed from UART, or -1 if there is no characters
0048  *     available
0049  */
0050 static int
0051 console_poll_read(int minor)
0052 {
0053         return sh4uart_poll_read(&sh4_uarts[minor]);
0054 }
0055 
0056 /* console_interrupt_write --
0057  *     wrapper for interrupt write function
0058  *
0059  * PARAMETERS:
0060  *     minor - minor device number
0061  *     buf - output buffer
0062  *     len - output buffer length
0063  *
0064  * RETURNS:
0065  *     result code
0066  */
0067 static ssize_t
0068 console_interrupt_write(int minor, const char *buf, size_t len)
0069 {
0070         return sh4uart_interrupt_write(&sh4_uarts[minor], buf, len);
0071 }
0072 
0073 /* console_poll_write --
0074  *     wrapper for polling mode write function
0075  *
0076  * PARAMETERS:
0077  *     minor - minor device number
0078  *     buf - output buffer
0079  *     len - output buffer length
0080  *
0081  * RETURNS:
0082  *     result code
0083  */
0084 static ssize_t
0085 console_poll_write(int minor, const char *buf, size_t len)
0086 {
0087         return sh4uart_poll_write(&sh4_uarts[minor], buf, len);
0088 }
0089 
0090 /* console_set_attributes --
0091  *     wrapper for hardware-dependent termios attributes setting
0092  *
0093  * PARAMETERS:
0094  *     minor - minor device number
0095  *     t - pointer to the termios structure
0096  *
0097  * RETURNS:
0098  *     result code
0099  */
0100 static int
0101 console_set_attributes(int minor, const struct termios *t)
0102 {
0103         return sh4uart_set_attributes(&sh4_uarts[minor], t);
0104 }
0105 
0106 /* console_stop_remote_tx --
0107  *     wrapper for stopping data flow from remote party.
0108  *
0109  * PARAMETERS:
0110  *     minor - minor device number
0111  *
0112  * RETURNS:
0113  *     result code
0114  */
0115 static int
0116 console_stop_remote_tx(int minor)
0117 {
0118     if (minor < sizeof(sh4_uarts)/sizeof(sh4_uarts[0]))
0119         return sh4uart_stop_remote_tx(&sh4_uarts[minor]);
0120     else
0121         return RTEMS_INVALID_NUMBER;
0122 }
0123 
0124 /* console_start_remote_tx --
0125  *     wrapper for resuming data flow from remote party.
0126  *
0127  * PARAMETERS:
0128  *     minor - minor device number
0129  *
0130  */
0131 static int
0132 console_start_remote_tx(int minor)
0133 {
0134     if (minor < sizeof(sh4_uarts)/sizeof(sh4_uarts[0]))
0135         return sh4uart_start_remote_tx(&sh4_uarts[minor]);
0136     else
0137         return RTEMS_INVALID_NUMBER;
0138 }
0139 
0140 /* console_first_open --
0141  *     wrapper for UART controller initialization functions
0142  *
0143  * PARAMETERS:
0144  *     major - major device number
0145  *     minor - minor device number
0146  *     arg - libio device open argument
0147  *
0148  * RETURNS:
0149  *     error code
0150  */
0151 static int
0152 console_first_open(int major, int minor, void *arg)
0153 {
0154     rtems_libio_open_close_args_t *args = arg;
0155     rtems_status_code sc;
0156 
0157     sc = sh4uart_init(&sh4_uarts[minor], /* uart */
0158             args->iop->data1,       /* tty */
0159             minor+1,                /* channel */
0160             (console_mode == CONSOLE_MODE_INT));
0161 
0162     if (sc == RTEMS_SUCCESSFUL)
0163         sc = sh4uart_reset(&sh4_uarts[minor]);
0164 
0165     return sc;
0166 }
0167 
0168 /* console_last_close --
0169  *     wrapper for UART controller close function
0170  *
0171  * PARAMETERS:
0172  *     major - major device number
0173  *     minor - minor device number
0174  *     arg - libio device close argument
0175  *
0176  * RETURNS:
0177  *     error code
0178  */
0179 static int
0180 console_last_close(int major, int minor, void *arg)
0181 {
0182     if (console_mode != CONSOLE_MODE_IPL)
0183     /* working from gdb we should not disable port operations */
0184         return sh4uart_disable(&sh4_uarts[minor],
0185             !(boot_mode == SH4_BOOT_MODE_IPL));
0186     else
0187     return RTEMS_SUCCESSFUL;
0188 }
0189 
0190 /* console_initialize --
0191  *     This routine initializes the console IO drivers and register devices
0192  *     in RTEMS I/O system.
0193  *
0194  * PARAMETERS:
0195  *     major - major console device number
0196  *     minor - minor console device number (not used)
0197  *     arg - device initialize argument
0198  *
0199  * RETURNS:
0200  *     RTEMS error code (RTEMS_SUCCESSFUL if device initialized successfuly)
0201  */
0202 rtems_device_driver
0203 console_initialize(rtems_device_major_number major,
0204         rtems_device_minor_number minor,
0205         void *arg)
0206 {
0207     rtems_status_code status;
0208 
0209 #ifdef SH4_WITH_IPL
0210     /* booting from flash we cannot have IPL console */
0211     if (boot_mode != SH4_BOOT_MODE_IPL && console_mode == CONSOLE_MODE_IPL)
0212         console_mode = CONSOLE_MODE_INT;
0213 
0214     /* break out from gdb if neccessary */
0215     if (boot_mode == SH4_BOOT_MODE_IPL && console_mode != CONSOLE_MODE_IPL)
0216         ipl_finish();
0217 #endif
0218 
0219     /*
0220      * Set up TERMIOS
0221      */
0222     if ((console_mode != CONSOLE_MODE_RAW) &&
0223                     (console_mode != CONSOLE_MODE_IPL))
0224         rtems_termios_initialize ();
0225 
0226     /*
0227      * Register the devices
0228      */
0229     status = rtems_io_register_name ("/dev/console", major, 0);
0230     if (status != RTEMS_SUCCESSFUL)
0231         rtems_fatal_error_occurred (status);
0232 
0233     status = rtems_io_register_name ("/dev/aux", major, 1);
0234     if (status != RTEMS_SUCCESSFUL)
0235         rtems_fatal_error_occurred (status);
0236 
0237     if (console_mode == CONSOLE_MODE_RAW)
0238     {
0239         rtems_status_code sc;
0240         sc = sh4uart_init(&sh4_uarts[0],              /* uart */
0241                 NULL,                  /* tty */
0242                 1,                     /* UART channel number */
0243                 0);                    /* Poll-mode */
0244 
0245         if (sc == RTEMS_SUCCESSFUL)
0246             sc = sh4uart_reset(&sh4_uarts[0]);
0247 
0248         sc = sh4uart_init(&sh4_uarts[1],              /* uart */
0249                 NULL,                  /* tty */
0250                 2,                     /* UART channel number */
0251                 0);                    /* Poll-mode */
0252 
0253         if (sc == RTEMS_SUCCESSFUL)
0254             sc = sh4uart_reset(&sh4_uarts[1]);
0255 
0256         return sc;
0257     }
0258 
0259     return RTEMS_SUCCESSFUL;
0260 }
0261 
0262 /* console_open --
0263  *     Open console device driver. Pass appropriate termios callback
0264  *     functions to termios library.
0265  *
0266  * PARAMETERS:
0267  *     major - major device number for console devices
0268  *     minor - minor device number for console
0269  *     arg - device opening argument
0270  *
0271  * RETURNS:
0272  *     RTEMS error code
0273  */
0274 rtems_device_driver
0275 console_open(rtems_device_major_number major,
0276         rtems_device_minor_number minor,
0277         void *arg)
0278 {
0279     static const rtems_termios_callbacks intr_callbacks = {
0280         console_first_open,        /* firstOpen */
0281         console_last_close,        /* lastClose */
0282         NULL,                      /* pollRead */
0283         console_interrupt_write,   /* write */
0284         console_set_attributes,    /* setAttributes */
0285         console_stop_remote_tx,    /* stopRemoteTx */
0286         console_start_remote_tx,   /* startRemoteTx */
0287         TERMIOS_IRQ_DRIVEN         /* outputUsesInterrupts */
0288     };
0289     static const rtems_termios_callbacks poll_callbacks = {
0290         console_first_open,        /* firstOpen */
0291         console_last_close,        /* lastClose */
0292         console_poll_read,         /* pollRead */
0293         console_poll_write,        /* write */
0294         console_set_attributes,    /* setAttributes */
0295         console_stop_remote_tx,    /* stopRemoteTx */
0296         console_start_remote_tx,   /* startRemoteTx */
0297         TERMIOS_POLLED             /* outputUsesInterrupts */
0298     };
0299 
0300     switch (console_mode)
0301     {
0302         case CONSOLE_MODE_RAW:
0303         case CONSOLE_MODE_IPL:
0304             return RTEMS_SUCCESSFUL;
0305 
0306         case CONSOLE_MODE_INT:
0307             return rtems_termios_open(major, minor, arg, &intr_callbacks);
0308 
0309         case CONSOLE_MODE_POLL:
0310             return rtems_termios_open(major, minor, arg, &poll_callbacks);
0311 
0312         default:
0313             rtems_fatal_error_occurred(0xC07A1310);
0314     }
0315 
0316     return RTEMS_INTERNAL_ERROR;
0317 }
0318 
0319 /* console_close --
0320  *     Close console device.
0321  *
0322  * PARAMETERS:
0323  *     major - major device number for console devices
0324  *     minor - minor device number for console
0325  *     arg - device close argument
0326  *
0327  * RETURNS:
0328  *     RTEMS error code
0329  */
0330 rtems_device_driver
0331 console_close(rtems_device_major_number major,
0332         rtems_device_minor_number minor,
0333         void *arg)
0334 {
0335     if ((console_mode != CONSOLE_MODE_RAW) &&
0336             (console_mode != CONSOLE_MODE_IPL))
0337         return rtems_termios_close (arg);
0338     else
0339         return RTEMS_SUCCESSFUL;
0340 }
0341 
0342 /* console_read --
0343  *     Read from the console device
0344  *
0345  * PARAMETERS:
0346  *     major - major device number for console devices
0347  *     minor - minor device number for console
0348  *     arg - device read argument
0349  *
0350  * RETURNS:
0351  *     RTEMS error code
0352  */
0353 rtems_device_driver
0354 console_read(rtems_device_major_number major,
0355         rtems_device_minor_number minor,
0356         void *arg)
0357 {
0358     if ((console_mode != CONSOLE_MODE_RAW) &&
0359             (console_mode != CONSOLE_MODE_IPL))
0360     {
0361         return rtems_termios_read (arg);
0362     }
0363     else
0364     {
0365         rtems_libio_rw_args_t *argp = arg;
0366         char *buf = argp->buffer;
0367         int count = argp->count;
0368         int n = 0;
0369         int c;
0370         while (n < count)
0371         {
0372             do {
0373                 c = (console_mode == CONSOLE_MODE_RAW) ?
0374                         sh4uart_poll_read(&sh4_uarts[minor]) :
0375                         ipl_console_poll_read(minor);
0376             } while (c == -1);
0377             if (c == '\r')
0378                 c = '\n';
0379             *(buf++) = c;
0380             n++;
0381             if (c == '\n')
0382                 break;
0383         }
0384         argp->bytes_moved = n;
0385         return RTEMS_SUCCESSFUL;
0386     }
0387 }
0388 
0389 /* console_write --
0390  *     Write to the console device
0391  *
0392  * PARAMETERS:
0393  *     major - major device number for console devices
0394  *     minor - minor device number for console
0395  *     arg - device write argument
0396  *
0397  * RETURNS:
0398  *     RTEMS error code
0399  */
0400 rtems_device_driver
0401 console_write(rtems_device_major_number major,
0402         rtems_device_minor_number minor,
0403         void *arg)
0404 {
0405     switch (console_mode)
0406     {
0407         case CONSOLE_MODE_POLL:
0408         case CONSOLE_MODE_INT:
0409                 return rtems_termios_write (arg);
0410         case CONSOLE_MODE_RAW:
0411         {
0412             rtems_libio_rw_args_t *argp = arg;
0413             char cr = '\r';
0414             char *buf = argp->buffer;
0415             int count = argp->count;
0416             int i;
0417 
0418             for (i = 0; i < count; i++)
0419             {
0420                 if (*buf == '\n')
0421                     sh4uart_poll_write(&sh4_uarts[minor], &cr, 1);
0422                 sh4uart_poll_write(&sh4_uarts[minor], buf, 1);
0423                 buf++;
0424             }
0425             argp->bytes_moved = count;
0426             return RTEMS_SUCCESSFUL;
0427         }
0428 #ifdef SH4_WITH_IPL
0429         case CONSOLE_MODE_IPL:
0430         {
0431             rtems_libio_rw_args_t *argp = arg;
0432             char *buf = argp->buffer;
0433             int count = argp->count;
0434             ipl_console_poll_write(minor, buf, count);
0435             argp->bytes_moved = count;
0436             return RTEMS_SUCCESSFUL;
0437         }
0438 #endif
0439         default: /* Unreachable */
0440             return RTEMS_NOT_DEFINED;
0441     }
0442 }
0443 
0444 /* console_control --
0445  *     Handle console device I/O control (IOCTL)
0446  *
0447  * PARAMETERS:
0448  *     major - major device number for console devices
0449  *     minor - minor device number for console
0450  *     arg - device ioctl argument
0451  *
0452  * RETURNS:
0453  *     RTEMS error code
0454  */
0455 rtems_device_driver
0456 console_control(rtems_device_major_number major,
0457         rtems_device_minor_number minor,
0458         void *arg)
0459 {
0460     if ((console_mode != CONSOLE_MODE_RAW) &&
0461             (console_mode != CONSOLE_MODE_IPL))
0462     {
0463         return rtems_termios_ioctl (arg);
0464     }
0465     else
0466     {
0467         return RTEMS_SUCCESSFUL;
0468     }
0469 }