diff options
author | Jennifer Averett <Jennifer.Averett@OARcorp.com> | 2011-10-18 18:23:51 +0000 |
---|---|---|
committer | Jennifer Averett <Jennifer.Averett@OARcorp.com> | 2011-10-18 18:23:51 +0000 |
commit | ba692232fa53278801b9f17318b8f6692bd3d92c (patch) | |
tree | 33ddd615cd8e42bda34b77db13ae19b2d2066610 /c/src/lib/libbsp/shared/console.c | |
parent | 2011-10-18 Jennifer Averett <Jennifer.Averett@OARcorp.com (diff) | |
download | rtems-ba692232fa53278801b9f17318b8f6692bd3d92c.tar.bz2 |
2011-10-18 Jennifer Averett <Jennifer.Averett@OARcorp.com>
PR 1917/bsps
* console.c: Modifications to add dynamic tables for libchip serial
drivers.
* console_control.c, console_private.h, console_read.c,
console_select.c, console_write.c: New files.
Diffstat (limited to 'c/src/lib/libbsp/shared/console.c')
-rw-r--r-- | c/src/lib/libbsp/shared/console.c | 293 |
1 files changed, 175 insertions, 118 deletions
diff --git a/c/src/lib/libbsp/shared/console.c b/c/src/lib/libbsp/shared/console.c index b103dbdf94..05d59cbe93 100644 --- a/c/src/lib/libbsp/shared/console.c +++ b/c/src/lib/libbsp/shared/console.c @@ -1,10 +1,13 @@ -/* - * This file contains the generic console driver shell used - * by all console drivers using libchip. +/** + * @file * - * This driver uses the termios pseudo driver. + * @ingroup Console * - * COPYRIGHT (c) 1989-1997. + * @brief Extension of the generic libchip console driver shell + */ + +/* + * COPYRIGHT (c) 1989-2011. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be @@ -16,30 +19,101 @@ #include <bsp.h> #include <rtems/libio.h> -#include <rtems/console.h> #include <stdlib.h> #include <assert.h> #include <termios.h> #include <rtems/termiostypes.h> #include <libchip/serial.h> +#include "console_private.h" + +unsigned long Console_Port_Count = 0; +console_tbl **Console_Port_Tbl = NULL; +console_data *Console_Port_Data = NULL; +rtems_device_minor_number Console_Port_Minor = 0; +bool console_initialized = false; /* - * Configuration Information + * console_initialize_pointers + * + * This method is used to initialize the table of pointers to the + * serial port configuration structure entries. */ +static void console_initialize_pointers(void) +{ + int i; + + if ( Console_Port_Tbl ) + return; + + Console_Port_Count = Console_Configuration_Count; + Console_Port_Tbl = malloc( Console_Port_Count * sizeof( console_tbl * ) ); + if (Console_Port_Tbl == NULL) + rtems_panic("No memory for console pointers"); + + for (i=0 ; i < Console_Port_Count ; i++) + Console_Port_Tbl[i] = &Console_Configuration_Ports[i]; +} -extern console_data Console_Port_Data[]; -extern unsigned long Console_Port_Count; -extern rtems_device_minor_number Console_Port_Minor; - -/*PAGE +/* + * console_register_devices * + * This method is used to add dynamically discovered devices to the + * set of serial ports supported. + */ +void console_register_devices( + console_tbl *new_ports, + size_t number_of_ports +) +{ + int old_number_of_ports; + int i; + + console_initialize_pointers(); + + /* + * console_initialize has been invoked so it is now too late to + * register devices. + */ + if ( console_initialized == true ) { + printk( "Attempt to register console devices after driver initialized\n" ); + rtems_fatal_error_occurred( 0xdead0001 ); + } + + /* + * Allocate memory for the console port extension + */ + old_number_of_ports = Console_Port_Count; + Console_Port_Count += number_of_ports; + Console_Port_Tbl = realloc( + Console_Port_Tbl, + Console_Port_Count * sizeof( console_tbl * ) + ); + if ( Console_Port_Tbl == NULL ) { + printk( "Unable to allocate pointer table for registering console devices\n" ); + rtems_fatal_error_occurred( 0xdead0002 ); + } + + Console_Port_Data = calloc( Console_Port_Count, sizeof( console_data ) ); + if ( Console_Port_Data == NULL ) { + printk( "Unable to allocate data table for console devices\n" ); + rtems_fatal_error_occurred( 0xdead0003 ); + } + + /* + * Now add the new devices at the end. + */ + + for (i=0 ; i < number_of_ports ; i++) { + Console_Port_Tbl[old_number_of_ports + i] = &new_ports[i]; + } +} + +/* * console_open * * open a port as a termios console. - * */ - rtems_device_driver console_open( rtems_device_major_number major, rtems_device_minor_number minor, @@ -65,17 +139,17 @@ rtems_device_driver console_open( * Open the port as a termios console driver. */ - cptr = &Console_Port_Tbl[minor]; + cptr = Console_Port_Tbl[minor]; Callbacks.firstOpen = cptr->pDeviceFns->deviceFirstOpen; Callbacks.lastClose = cptr->pDeviceFns->deviceLastClose; Callbacks.pollRead = cptr->pDeviceFns->deviceRead; Callbacks.write = cptr->pDeviceFns->deviceWrite; Callbacks.setAttributes = cptr->pDeviceFns->deviceSetAttributes; if (cptr->pDeviceFlow != NULL) { - Callbacks.stopRemoteTx = cptr->pDeviceFlow->deviceStopRemoteTx; + Callbacks.stopRemoteTx = cptr->pDeviceFlow->deviceStopRemoteTx; Callbacks.startRemoteTx = cptr->pDeviceFlow->deviceStartRemoteTx; } else { - Callbacks.stopRemoteTx = NULL; + Callbacks.stopRemoteTx = NULL; Callbacks.startRemoteTx = NULL; } Callbacks.outputUsesInterrupts = cptr->pDeviceFns->deviceOutputUsesInterrupts; @@ -85,7 +159,7 @@ rtems_device_driver console_open( * Console_Port_Tbl[minor].ulHysteresis); */ - status = rtems_termios_open ( major, minor, arg, &Callbacks ); + status = rtems_termios_open( major, minor, arg, &Callbacks ); Console_Port_Data[minor].termios_data = args->iop->data1; /* Get tty pointur from the Console_Port_Data */ @@ -103,37 +177,35 @@ rtems_device_driver console_open( /* * If it's the first open, modified, if need, the port parameters */ - if (minor!=Console_Port_Minor) { + if ( minor != Console_Port_Minor ) { /* - * If this is not the console we do not want ECHO and - * so forth + * If this is not the console we do not want ECHO and so forth */ - IoctlArgs.iop=args->iop; - IoctlArgs.command=RTEMS_IO_GET_ATTRIBUTES; - IoctlArgs.buffer=&Termios; - rtems_termios_ioctl(&IoctlArgs); - Termios.c_lflag=ICANON; - IoctlArgs.command=RTEMS_IO_SET_ATTRIBUTES; - rtems_termios_ioctl(&IoctlArgs); + IoctlArgs.iop = args->iop; + IoctlArgs.command = RTEMS_IO_GET_ATTRIBUTES; + IoctlArgs.buffer = &Termios; + rtems_termios_ioctl( &IoctlArgs ); + + Termios.c_lflag = ICANON; + IoctlArgs.command = RTEMS_IO_SET_ATTRIBUTES; + rtems_termios_ioctl( &IoctlArgs ); } } if ( (args->iop->flags&LIBIO_FLAGS_READ) && - Console_Port_Tbl[minor].pDeviceFlow && - Console_Port_Tbl[minor].pDeviceFlow->deviceStartRemoteTx) { - Console_Port_Tbl[minor].pDeviceFlow->deviceStartRemoteTx(minor); + cptr->pDeviceFlow && + cptr->pDeviceFlow->deviceStartRemoteTx) { + cptr->pDeviceFlow->deviceStartRemoteTx(minor); } return status; } -/*PAGE - * +/* * console_close * * This routine closes a port that has been opened as console. */ - rtems_device_driver console_close( rtems_device_major_number major, rtems_device_minor_number minor, @@ -142,8 +214,11 @@ rtems_device_driver console_close( { rtems_libio_open_close_args_t *args = arg; struct rtems_termios_tty *current_tty; + console_tbl *cptr; + + cptr = Console_Port_Tbl[minor]; - /* Get tty pointeur from the Console_Port_Data */ + /* Get tty pointer from the Console_Port_Data */ current_tty = Console_Port_Data[minor].termios_data; /* Get the tty refcount to determine if we need to do deviceStopRemoteTx. @@ -151,111 +226,93 @@ rtems_device_driver console_close( */ if ( (current_tty->refcount == 1) ) { if ( (args->iop->flags&LIBIO_FLAGS_READ) && - Console_Port_Tbl[minor].pDeviceFlow && - Console_Port_Tbl[minor].pDeviceFlow->deviceStopRemoteTx) { - Console_Port_Tbl[minor].pDeviceFlow->deviceStopRemoteTx(minor); + cptr->pDeviceFlow && + cptr->pDeviceFlow->deviceStopRemoteTx) { + cptr->pDeviceFlow->deviceStopRemoteTx(minor); } } return rtems_termios_close (arg); } -/*PAGE - * - * console_read - * - * This routine uses the termios driver to read a character. - */ - -rtems_device_driver console_read( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg -) -{ - return rtems_termios_read (arg); -} - -/*PAGE - * - * console_write - * - * this routine uses the termios driver to write a character. - */ - -rtems_device_driver console_write( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg -) -{ - return rtems_termios_write (arg); -} - -/*PAGE - * - * console_control - * - * this routine uses the termios driver to process io - */ - -rtems_device_driver console_control( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg -) -{ - return rtems_termios_ioctl (arg); -} - -/*PAGE - * +/* * console_initialize * * Routine called to initialize the console device driver. */ - rtems_device_driver console_initialize( rtems_device_major_number major, - rtems_device_minor_number minor, + rtems_device_minor_number minor_arg, void *arg ) { - rtems_status_code sc = RTEMS_SUCCESSFUL; - bool first = true; + rtems_status_code status; + rtems_device_minor_number minor; + console_tbl *port; + + /* + * If we have no devices which were registered earlier then we + * must still initialize pointers and set Console_Port_Data. + */ + if ( ! Console_Port_Tbl ) { + console_initialize_pointers(); + Console_Port_Data = calloc( Console_Port_Count, sizeof( console_data ) ); + if ( Console_Port_Data == NULL ) { + printk( "Unable to allocate data table for console devices\n" ); + rtems_fatal_error_occurred( 0xdead0003 ); + } + } + + /* + * console_initialize has been invoked so it is now too late to + * register devices. + */ + console_initialized = true; + /* + * Initialize the termio interface, our table of pointers to device + * information structures, and determine if the user has explicitly + * specified which device is to be used for the console. + */ rtems_termios_initialize(); + bsp_console_select(); - for (minor = 0; minor < Console_Port_Count; ++minor) { - const console_tbl *device = &Console_Port_Tbl [minor]; - - if ( - (device->deviceProbe == NULL || device->deviceProbe(minor)) - && device->pDeviceFns->deviceProbe(minor) - ) { - device->pDeviceFns->deviceInitialize(minor); - if (first) { - first = false; - Console_Port_Minor = minor; - sc = rtems_io_register_name(CONSOLE_DEVICE_NAME, major, minor); - if (sc != RTEMS_SUCCESSFUL) { - rtems_fatal_error_occurred(sc); - } + /* + * Iterate over all of the console devices we know about + * and initialize them. + */ + for (minor=0 ; minor < Console_Port_Count ; minor++) { + /* + * First perform the configuration dependent probe, then the + * device dependent probe + */ + port = Console_Port_Tbl[minor]; + + if ( (!port->deviceProbe || port->deviceProbe(minor)) && + port->pDeviceFns->deviceProbe(minor)) { + + status = rtems_io_register_name( port->sDeviceName, major, minor ); + if (status != RTEMS_SUCCESSFUL) { + printk( "Unable to register /dev/console\n" ); + rtems_fatal_error_occurred(status); } - if (device->sDeviceName != NULL) { - sc = rtems_io_register_name(device->sDeviceName, major, minor); - if (sc != RTEMS_SUCCESSFUL) { - rtems_fatal_error_occurred(sc); + + if (minor == Console_Port_Minor) { + if (RTEMS_DEBUG) + printk( "Register %s as the CONSOLE\n", port->sDeviceName ); + status = rtems_io_register_name( "dev/console", major, minor ); + if (status != RTEMS_SUCCESSFUL) { + printk( "Unable to register /dev/console\n" ); + rtems_fatal_error_occurred(status); } } - } - } - if (first) { - /* - * Failed to find a working device - */ - rtems_fatal_error_occurred(RTEMS_IO_ERROR); + /* + * Initialize the hardware device. + */ + port->pDeviceFns->deviceInitialize(minor); + + } } return RTEMS_SUCCESSFUL; |