From a800d09cc79100fb8e10e10fa344c5218ce91d69 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Mon, 12 Apr 2004 21:52:13 +0000 Subject: 2004-04-12 David Querbach * .cvsignore, ChangeLog, Makefile.am, README, bsp_specs, configure.ac, times, clock/p_clock.c, console/console.c, include/.cvsignore, include/bsp.h, include/coverhd.h, irq/irq.h, startup/bspstart.c, startup/iss555.c, startup/linkcmds, startup/start.S, wrapup/.cvsignore, wrapup/Makefile.am: New files. --- c/src/lib/libbsp/powerpc/ss555/console/console.c | 377 +++++++++++++++++++++++ 1 file changed, 377 insertions(+) create mode 100644 c/src/lib/libbsp/powerpc/ss555/console/console.c (limited to 'c/src/lib/libbsp/powerpc/ss555/console') diff --git a/c/src/lib/libbsp/powerpc/ss555/console/console.c b/c/src/lib/libbsp/powerpc/ss555/console/console.c new file mode 100644 index 0000000000..810cf69bda --- /dev/null +++ b/c/src/lib/libbsp/powerpc/ss555/console/console.c @@ -0,0 +1,377 @@ +/* + * console.c + * + * This file contains the Intec SS555 termios serial I/O package. + * + * The SCI channels are assigned as follows + * + * Channel Device Minor + * SCI1 /dev/tty0 0 + * SCI2 /dev/tty1 1 + * + * All ports support termios. The use of termios is recommended for real-time + * applications. Termios provides buffering and input processing. When not + * using termios, processing is limited to the substitution of LF for CR on + * input, and the output of a CR following the output of a LF character. + * Note that the terminal should not send CR/LF pairs when the return key + * is pressed, and that output lines are terminated with LF/CR, not CR/LF + * (although that would be easy to change). + * + * I/O may be interrupt-driven (recommended for real-time applications) or + * polled. + * + * LIMITATIONS: + * + * It is not possible to use different I/O modes on the different ports. The + * exception is with printk. The printk port can use a different mode from + * the other ports. If this is done, it is important not to open the printk + * port from an RTEMS application. + * + * Currently, the I/O modes are determined at build time. It would be much + * better to have the mode selected at boot time based on parameters in + * NVRAM. + * + * Interrupt-driven I/O requires termios. + * + * TESTS: + * + * TO RUN THE TESTS, USE POLLED I/O WITHOUT TERMIOS SUPPORT. Some tests + * play with the interrupt masks and turn off I/O. Those tests will hang + * when interrupt-driven I/O is used. Other tests, such as cdtest, do I/O + * from the static constructors before the console is open. This test + * will not work with interrupt-driven I/O. Because of the buffering + * performed in termios, test output may not be in sequence.The tests + * should all be fixed to work with interrupt-driven I/O and to + * produce output in the expected sequence. Obviously, the termios test + * requires termios support in the driver. + * + * Set CONSOLE_MINOR to the appropriate device minor number in the + * config file. This allows the RTEMS application console to be different + * from the GDB port. + * + * This driver handles both available serial ports: it distinguishes + * the sub-devices using minor device numbers. It is not possible to have + * other protocols running on the other ports when this driver is used as + * currently written. + * + * + * SS555 port sponsored by Defence Research and Development Canada - Suffield + * Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca) + * + * Derived from c/src/lib/libbsp/powerpc/mbx8xx/console/console.c: + * + * Based on code (alloc860.c in eth_comm port) by + * Jay Monkman (jmonkman@frasca.com), + * Copyright (C) 1998 by Frasca International, Inc. + * + * Modifications by Darlene Stewart + * and Charles-Antoine Gauthier . + * Copyright (c) 2000, National Research Council of Canada + * + */ +#include +#include +#include /* Must be before libio.h */ +#include +#include +#include + +static void _BSP_output_char( char c ); +static rtems_status_code do_poll_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg); +static rtems_status_code do_poll_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg); + +static void _BSP_null_char( char c ) {return;} + +BSP_output_char_function_type BSP_output_char = _BSP_null_char; + + +/* + * do_poll_read + * + * Input characters through polled I/O. Returns as soon as a character has + * been received. Otherwise, if we wait for the number of requested + * characters, we could be here forever! + * + * CR is converted to LF on input. The terminal should not send a CR/LF pair + * when the return or enter key is pressed. + * + * Input parameters: + * major - ignored. Should be the major number for this driver. + * minor - selected channel. + * arg->buffer - where to put the received characters. + * arg->count - number of characters to receive before returning--Ignored. + * + * Output parameters: + * arg->bytes_moved - the number of characters read. Always 1. + * + * Return value: RTEMS_SUCCESSFUL + * + * CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O! + */ +static rtems_status_code do_poll_read( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + rtems_libio_rw_args_t *rw_args = arg; + int c; + + while( (c = m5xx_uart_pollRead(minor)) == -1 ); + rw_args->buffer[0] = (unsigned8)c; + if( rw_args->buffer[0] == '\r' ) + rw_args->buffer[0] = '\n'; + rw_args->bytes_moved = 1; + + return RTEMS_SUCCESSFUL; +} + + +/* + * do_poll_write + * + * Output characters through polled I/O. Returns only once every character has + * been sent. + * + * CR is transmitted AFTER a LF on output. + * + * Input parameters: + * major - ignored. Should be the major number for this driver. + * minor - selected channel + * arg->buffer - where to get the characters to transmit. + * arg->count - the number of characters to transmit before returning. + * + * Output parameters: + * arg->bytes_moved - the number of characters read + * + * Return value: RTEMS_SUCCESSFUL + * + * CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O! + */ +static rtems_status_code do_poll_write( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + rtems_libio_rw_args_t *rw_args = arg; + unsigned32 i; + char cr ='\r'; + + for( i = 0; i < rw_args->count; i++ ) { + m5xx_uart_pollWrite(minor, &(rw_args->buffer[i]), 1); + if ( rw_args->buffer[i] == '\n' ) + m5xx_uart_pollWrite(minor, &cr, 1); + } + rw_args->bytes_moved = i; + + return RTEMS_SUCCESSFUL; +} + + +/* + * Print functions prototyped in bspIo.h + */ + +static void _BSP_output_char( char c ) +{ + char cr = '\r'; + + /* + * Can't rely on console_initialize having been called before this + * function is used, so it may fail. + */ + + m5xx_uart_pollWrite( PRINTK_MINOR, &c, 1 ); + if( c == '\n' ) + m5xx_uart_pollWrite( PRINTK_MINOR, &cr, 1 ); +} + + +/* + *************** + * BOILERPLATE * + *************** + * + * All these functions are prototyped in rtems/c/src/lib/include/console.h. + */ + +/* + * Initialize and register the device + */ +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code status; + + /* + * Set up TERMIOS if needed + */ + #if UARTS_USE_TERMIOS == 1 + rtems_termios_initialize (); + #endif /* UARTS_USE_TERMIOS */ + + /* + * Do device-specific initialization + */ + BSP_output_char = _BSP_output_char; + + m5xx_uart_initialize(SCI1_MINOR); + status = rtems_io_register_name ("/dev/tty0", major, SCI1_MINOR); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (status); + + m5xx_uart_initialize(SCI2_MINOR); + status = rtems_io_register_name ("/dev/tty1", major, SCI2_MINOR); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (status); + + /* Now register the RTEMS console */ + status = rtems_io_register_name ("/dev/console", major, CONSOLE_MINOR); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (status); + + return RTEMS_SUCCESSFUL; +} + + +/* + * Open the device + */ +rtems_device_driver console_open( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code sc; + + if ( minor > NUM_PORTS - 1 ) + return RTEMS_INVALID_NUMBER; + + #if (UARTS_USE_TERMIOS == 1) + { + #if (UARTS_IO_MODE == 1) /* RTEMS interrupt-driven I/O with termios */ + + static const rtems_termios_callbacks callbacks = { + m5xx_uart_firstOpen, /* firstOpen */ + m5xx_uart_lastClose, /* lastClose */ + NULL, /* pollRead */ + m5xx_uart_write, /* write */ + m5xx_uart_setAttributes, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + TERMIOS_IRQ_DRIVEN /* outputUsesInterrupts */ + }; + sc = rtems_termios_open( major, minor, arg, &callbacks ); + + #else /* UARTS_IO_MODE != 1 */ /* RTEMS polled I/O with termios */ + + static const rtems_termios_callbacks callbacks = { + m5xx_uart_firstOpen, /* firstOpen */ + m5xx_uart_lastClose, /* lastClose */ + m5xx_uart_pollRead, /* pollRead */ + m5xx_uart_pollWrite, /* write */ + m5xx_uart_setAttributes, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + TERMIOS_POLLED /* outputUsesInterrupts */ + }; + sc = rtems_termios_open( major, minor, arg, &callbacks ); + + #endif + + return sc; + } + + #else /* no termios -- default to polled I/O */ + { + sc = RTEMS_SUCCESSFUL; + } + #endif + + return sc; +} + + +/* + * Close the device + */ +rtems_device_driver console_close( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + if ( minor > NUM_PORTS-1 ) + return RTEMS_INVALID_NUMBER; + + #if UARTS_USE_TERMIOS == 1 + return rtems_termios_close( arg ); + #else + return RTEMS_SUCCESSFUL; + #endif +} + + +/* + * Read from the device + */ +rtems_device_driver console_read( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + if ( minor > NUM_PORTS-1 ) + return RTEMS_INVALID_NUMBER; + + #if UARTS_USE_TERMIOS == 1 + return rtems_termios_read( arg ); + #else + return do_poll_read( major, minor, arg ); + #endif +} + + +/* + * Write to the device + */ +rtems_device_driver console_write( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + if ( minor > NUM_PORTS-1 ) + return RTEMS_INVALID_NUMBER; + + #if UARTS_USE_TERMIOS == 1 + return rtems_termios_write( arg ); + #else + return do_poll_write( major, minor, arg ); + #endif +} + + +/* + * Handle ioctl request. + */ +rtems_device_driver console_control( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + if ( minor > NUM_PORTS-1 ) + return RTEMS_INVALID_NUMBER; + + #if UARTS_USE_TERMIOS == 1 + return rtems_termios_ioctl( arg ); + #else + return RTEMS_SUCCESSFUL; + #endif +} -- cgit v1.2.3