/* * This file contains the TTY driver for the PPCn_60x * * This driver uses the termios pseudo driver. * * COPYRIGHT (c) 1998 by Radstone Technology * * * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. * * You are hereby granted permission to use, copy, modify, and distribute * this file, provided that this notice, plus the above copyright notice * and disclaimer, appears in all copies. Radstone Technology will provide * no support for this code. * * COPYRIGHT (c) 1989-1997. * On-Line Applications Research Corporation (OAR). * Copyright assigned to U.S. Government, 1994. * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.OARcorp.com/rtems/license.html. * * $Id$ */ #include #include #include #include #include #include "console.h" /* * Load configuration table */ #include "config.c" #define NUM_CONSOLE_PORTS (sizeof(Console_Port_Tbl)/sizeof(console_tbl)) console_data Console_Port_Data[NUM_CONSOLE_PORTS]; unsigned long Console_Port_Count; rtems_device_minor_number Console_Port_Minor; /* PAGE * * console_open * * open a port as a termios console. * */ rtems_device_driver console_open( rtems_device_major_number major, rtems_device_minor_number minor, void * arg ) { rtems_status_code status; rtems_libio_open_close_args_t *args = arg; rtems_libio_ioctl_args_t IoctlArgs; struct termios Termios; rtems_termios_callbacks Callbacks; console_fns *c; /* * Verify the port number is valid. */ if(minor>Console_Port_Count) { return RTEMS_INVALID_NUMBER; } /* * open the port as a termios console driver. */ c = Console_Port_Tbl[minor].pDeviceFns; Callbacks.firstOpen = c->deviceFirstOpen; Callbacks.lastClose = c->deviceLastClose; Callbacks.pollRead = c->deviceRead; Callbacks.write = c->deviceWrite; Callbacks.setAttributes = c->deviceSetAttributes; Callbacks.stopRemoteTx = Console_Port_Tbl[minor].pDeviceFlow->deviceStopRemoteTx; Callbacks.startRemoteTx = Console_Port_Tbl[minor].pDeviceFlow->deviceStartRemoteTx; Callbacks.outputUsesInterrupts = c->deviceOutputUsesInterrupts; status = rtems_termios_open ( major, minor, arg, &Callbacks); Console_Port_Data[minor].termios_data = args->iop->data1; /* * Patch in flow control routines */ /* XXX */ #if 0 if((status==RTEMS_SUCCESSFUL) && (Console_Port_Tbl[minor].pDeviceFlow)) { status=rtems_termios_flow_control( major, minor, arg, Console_Port_Tbl[minor].pDeviceFlow-> deviceStartRemoteTx, Console_Port_Tbl[minor].pDeviceFlow->deviceStopRemoteTx, Console_Port_Tbl[minor].ulMargin, Console_Port_Tbl[minor].ulHysteresis); } #endif if(minor!=Console_Port_Minor) { /* * 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); } 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); } return status; } rtems_device_driver console_close( rtems_device_major_number major, rtems_device_minor_number minor, void * arg ) { rtems_libio_open_close_args_t *args = arg; 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); } return rtems_termios_close (arg); } rtems_device_driver console_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg ) { return rtems_termios_read (arg); } rtems_device_driver console_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg ) { return rtems_termios_write (arg); } 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, void *arg ) { rtems_status_code status; /* * initialize the termio interface. */ rtems_termios_initialize(); Console_Port_Count=NUM_CONSOLE_PORTS; for(minor=0; minordeviceProbe(minor)) { /* * Use this device for the console */ break; } } if(minor==Console_Port_Count) { /* * Failed to find a working device */ rtems_fatal_error_occurred(RTEMS_IO_ERROR); } Console_Port_Minor=minor; /* * Register Device Names */ status = rtems_io_register_name("/dev/console", major, Console_Port_Minor ); if (status != RTEMS_SUCCESSFUL) { rtems_fatal_error_occurred(status); } Console_Port_Tbl[minor].pDeviceFns->deviceInitialize( Console_Port_Minor); for(minor++;minordeviceProbe(minor)) { status = rtems_io_register_name( Console_Port_Tbl[minor].sDeviceName, major, minor ); if (status != RTEMS_SUCCESSFUL) { rtems_fatal_error_occurred(status); } /* * Initialize the hardware device. */ Console_Port_Tbl[minor].pDeviceFns->deviceInitialize( minor); } } return RTEMS_SUCCESSFUL; } /* PAGE * * DEBUG_puts * * This should be safe in the event of an error. It attempts to ensure * that no TX empty interrupts occur while it is doing polled IO. Then * it restores the state of that external interrupt. * * Input parameters: * string - pointer to debug output string * * Output parameters: NONE * * Return values: NONE */ void DEBUG_puts( char *string ) { char *s; unsigned32 Irql; rtems_interrupt_disable(Irql); for ( s = string ; *s ; s++ ) { Console_Port_Tbl[Console_Port_Minor].pDeviceFns-> deviceWritePolled(Console_Port_Minor, *s); } rtems_interrupt_enable(Irql); } /* PAGE * * DEBUG_puth * * This should be safe in the event of an error. It attempts to ensure * that no TX empty interrupts occur while it is doing polled IO. Then * it restores the state of that external interrupt. * * Input parameters: * ulHexNum - value to display * * Output parameters: NONE * * Return values: NONE */ void DEBUG_puth( unsigned32 ulHexNum ) { unsigned long i,d; unsigned32 Irql; rtems_interrupt_disable(Irql); Console_Port_Tbl[Console_Port_Minor].pDeviceFns-> deviceWritePolled(Console_Port_Minor, '0'); Console_Port_Tbl[Console_Port_Minor].pDeviceFns-> deviceWritePolled(Console_Port_Minor, 'x'); for(i=32;i;) { i-=4; d=(ulHexNum>>i)&0xf; Console_Port_Tbl[Console_Port_Minor].pDeviceFns-> deviceWritePolled(Console_Port_Minor, (d<=9) ? d+'0' : d+'a'-0xa); } rtems_interrupt_enable(Irql); }