diff options
Diffstat (limited to '')
-rw-r--r-- | c/src/lib/libbsp/powerpc/score603e/console/console.c | 497 |
1 files changed, 497 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/score603e/console/console.c b/c/src/lib/libbsp/powerpc/score603e/console/console.c new file mode 100644 index 0000000000..a3836bd6a8 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/score603e/console/console.c @@ -0,0 +1,497 @@ +/* + * This file contains the TTY driver for the serial ports on the SCORE603e. + * + * This driver uses the termios pseudo driver. + * + * Currently only polled mode is supported. + * + * 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 <bsp.h> +#include <rtems/libio.h> +#include <stdlib.h> +#include <assert.h> + +#include "consolebsp.h" + +#if (1) +/* + * The Port Used for the Console interface is based upon which + * debugger is being used. The SDS debugger uses a binary + * interface on port 0 as part of the debugger. Thus port 0 can + * not be used as the console port for the SDS debugger. + */ + +#if (SCORE603E_USE_SDS) +#define USE_FOR_CONSOLE_DEF 1 + +#elif (SCORE603E_USE_OPEN_FIRMWARE) +#define USE_FOR_CONSOLE_DEF 0 + +#elif (SCORE603E_USE_NONE) +#define USE_FOR_CONSOLE_DEF 0 + +#elif (SCORE603E_USE_DINK) +#define USE_FOR_CONSOLE_DEF 0 + +#else +#error "SCORE603E CONSOLE.C -- what ROM monitor are you using" +#endif + +#endif + +#if (0) +extern int USE_FOR_CONSOLE; +#endif + +int USE_FOR_CONSOLE = USE_FOR_CONSOLE_DEF; + +/* + * + * Console Device Driver Entry Points + */ + +/* PAGE + * + * DEBUG_puts + * + * This should be safe in the event of an error. It attempts to insure + * 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; + int console; + volatile rtems_unsigned8 *csr; + + console = USE_FOR_CONSOLE; + + csr = Ports_85C30[ console ].ctrl; + + /* should disable interrupts here */ + + for ( s = string ; *s ; s++ ) + outbyte_polled_85c30( csr, *s ); + + outbyte_polled_85c30( csr, '\r' ); + outbyte_polled_85c30( csr, '\n' ); + + /* should enable interrupts here */ +} + +/* PAGE + * + * console_inbyte_nonblocking + * + * Console Termios polling input entry point. + */ + +int console_inbyte_nonblocking( + int minor +) +{ + int port = minor; + + /* + * verify port Number + */ + assert ( port < NUM_Z85C30_PORTS ); + + /* + * return a character from the 85c30 port. + */ + return inbyte_nonblocking_85c30( &Ports_85C30[ port ] ); +} + + +void console_reserve_resources( + rtems_configuration_table *configuration +) +{ + rtems_termios_reserve_resources( configuration, NUM_Z85C30_PORTS ); +} + + +rtems_device_driver console_close( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + 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); +} + + + +/* + * Interrupt driven console IO + */ + +#if CONSOLE_USE_INTERRUPTS + +rtems_isr console_isr( + rtems_vector_number vector +) +{ + int i; + + for (i=0; i < NUM_Z85C30_PORTS; i++){ + ISR_85c30_Async( &Ports_85C30[i] ); + +#if (0) /* XXX - TO TEST LOOP BACKS comment this out. */ + if ( Ports_85C30[i].Chip->vector == vector ) { + ISR_85c30_Async( &Ports_85C30[i] ); + } +#endif + } +} + +void console_exit() +{ + int i; + volatile Ring_buffer_t *buffer; + rtems_unsigned32 ch; + + for ( i=0 ; i < NUM_Z85C30_PORTS ; i++ ) { + + buffer = &( Ports_85C30[i].Protocol->TX_Buffer); + + while ( !Ring_buffer_Is_empty( buffer ) ) { + Ring_buffer_Remove_character( buffer, ch ); + outbyte_polled_85c30( Ports_85C30[i].ctrl, ch ); + } + } +} + +void console_initialize_interrupts( void ) +{ + volatile Ring_buffer_t *buffer; + Console_Protocol *protocol; + int i; + + for ( i=0 ; i < NUM_Z85C30_PORTS ; i++ ) { + protocol = Ports_85C30[i].Protocol; + + /* + * Initialize the ring buffer and set to not transmitting. + */ + buffer = &protocol->TX_Buffer; + Ring_buffer_Initialize( buffer ); + protocol->Is_TX_active = FALSE; + } + + /* + * Connect each vector to the interupt service routine. + */ + for (i=0; i < NUM_Z85C30_CHIPS; i++) + set_vector( console_isr, Chips_85C30[i].vector, 1 ); + + + atexit( console_exit ); + +} +void console_outbyte_interrupts( + const Port_85C30_info *Port, + char ch +); + +/* XXXXXX */ +#endif + + +/* 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; + rtems_device_minor_number console; + int port, chip, p0,p1; + + /* + * initialize the termio interface. + */ + rtems_termios_initialize(); + + /* + * Register Device Names + */ + console = USE_FOR_CONSOLE; + status = rtems_io_register_name( "/dev/console", major, console ); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred(status); + + /* + * Initialize Hardware + */ + + +/* + * INITIALIZE_COM_PORTS is defined in the linker script. If it is + * true all serial chips on the board are to be reset at startup + * otherwise the reset is assumed to occur elsewhere (ie. in the + * debugger...) + */ +#if ( INITIALIZE_COM_PORTS ) + + /* + * Force to perform a hardware reset w/o + * Master interrupt enable via register 9 + */ + + for (port=0; port<NUM_Z85C30_PORTS; port++){ + p0 = port; + port++; + p1 = port; + Reset_85c30_chip( Ports_85C30[p0].ctrl, Ports_85C30[p1].ctrl ); + } +#else + /* TEMP - To see if this makes a diff with the new ports. + * Never reset chip 1 when using the chip as a monitor + */ + for (port=2; port<NUM_Z85C30_PORTS; port++){ + p0 = port; + port++; + p1 = port; + Reset_85c30_chip( Ports_85C30[p0].ctrl, Ports_85C30[p1].ctrl ); + } +#endif + + /* + * Initialize each port. + * Note: the ports are numbered such that 0,1 are on the first chip + * 2,3 are on the second .... + */ + + for (port=0; port<NUM_Z85C30_PORTS; port++) { + chip = port >> 1; + initialize_85c30_port( &Ports_85C30[port] ); + } + +#if CONSOLE_USE_INTERRUPTS + console_initialize_interrupts(); +#endif + + return RTEMS_SUCCESSFUL; +} + +/* PAGE + * + * console_write_support + * + * Console Termios output entry point. + * + */ +int console_write_support( + int minor, + const char *buf, + int len) +{ + int nwrite = 0; + volatile rtems_unsigned8 *csr; + int port = minor; + + /* + * verify port Number + */ + assert ( port < NUM_Z85C30_PORTS ); + + /* + * Set the csr based upon the port number. + */ + csr = Ports_85C30[ port ].ctrl; + + /* + * poll each byte in the string out of the port. + */ + while (nwrite < len) { +#if (CONSOLE_USE_INTERRUPTS) + console_outbyte_interrupts( &Ports_85C30[ port ], *buf++ ); +#else + outbyte_polled_85c30( csr, *buf++ ); +#endif + nwrite++; + } + + /* + * return the number of bytes written. + */ + return nwrite; +} + +/* 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 sc; + int port = minor; +#if (CONSOLE_USE_INTERRUPTS) + rtems_libio_open_close_args_t *args = arg; + static const rtems_termios_callbacks intrCallbacks = { + NULL, /* firstOpen */ + NULL, /* lastClose */ + NULL, /* pollRead */ + console_write_support, /* write */ + NULL, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + 1 /* outputUsesInterrupts */ + }; +#else + static const rtems_termios_callbacks pollCallbacks = { + NULL, /* firstOpen */ + NULL, /* lastClose */ + console_inbyte_nonblocking, /* pollRead */ + console_write_support, /* write */ + NULL, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + 0 /* outputUsesInterrupts */ + }; +#endif + + + /* + * Verify the minor number is valid. + */ + if (minor < 0) + return RTEMS_INVALID_NUMBER; + + if ( port > NUM_Z85C30_PORTS ) + return RTEMS_INVALID_NUMBER; + + /* + * open the port as a termios console driver. + */ + +#if (CONSOLE_USE_INTERRUPTS) + sc = rtems_termios_open( major, minor, arg, &intrCallbacks ); + + Ports_85C30[ minor ].Protocol->console_termios_data = args->iop->data1; +#else + sc = rtems_termios_open( major, minor, arg, &pollCallbacks ); +#endif + + return sc; +} + + +#if (CONSOLE_USE_INTERRUPTS) + +/* + * console_outbyte_interrupts + * + * This routine transmits a character out. + * + * Input parameters: + * port - port to transmit character to + * ch - character to be transmitted + * + * Output parameters: NONE + * + * Return values: NONE + */ +void console_outbyte_interrupts( + const Port_85C30_info *Port, + char ch +) +{ + Console_Protocol *protocol; + rtems_unsigned32 isrlevel; + + protocol = Port->Protocol; + + /* + * If this is the first character then we need to prime the pump + */ + + if ( protocol->Is_TX_active == FALSE ) { + + rtems_interrupt_disable( isrlevel ); + protocol->Is_TX_active = TRUE; + outbyte_polled_85c30( Port->ctrl, ch ); + rtems_interrupt_enable( isrlevel ); + + return; + } + + while ( Ring_buffer_Is_full( &protocol->TX_Buffer ) ); + + Ring_buffer_Add_character( &protocol->TX_Buffer, ch ); +} + +#endif + + + + + + + + + + + |