From b21b0ab3e77d91fc32e4324d3dfaf57ce24096ab Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Mon, 13 Nov 2000 22:40:29 +0000 Subject: 2000-11-13 Jiri Gaisler * .cvsignore, ChangeLog, Makefile.am, README, bsp_specs, configure.in, times, clock/.cvsignore, clock/Makefile.am, clock/ckinit.c, console/.cvsignore, console/Makefile.am, console/console.c, console/consolereserveresources.c, console/debugputs.c, gnatsupp/.cvsignore, gnatsupp/Makefile.am, gnatsupp/gnatsupp.c, include/.cvsignore, include/Makefile.am, include/bsp.h, include/coverhd.h, include/leon.h, start/.cvsignore, start/Makefile.am, startup/.cvsignore, startup/Makefile.am, startup/boardinit.S, startup/linkcmds, startup/setvec.c, startup/spurious.c, timer/.cvsignore, timer/Makefile.am, timer/timer.c, tools/.cvsignore, tools/Makefile.am, tools/configure.in, tools/runtest.in, wrapup/.cvsignore, wrapup/Makefile.am: New file. --- c/src/lib/libbsp/sparc/leon/console/.cvsignore | 2 + c/src/lib/libbsp/sparc/leon/console/Makefile.am | 33 ++ c/src/lib/libbsp/sparc/leon/console/console.c | 439 +++++++++++++++++++++ .../sparc/leon/console/consolereserveresources.c | 21 + c/src/lib/libbsp/sparc/leon/console/debugputs.c | 109 +++++ 5 files changed, 604 insertions(+) create mode 100644 c/src/lib/libbsp/sparc/leon/console/.cvsignore create mode 100644 c/src/lib/libbsp/sparc/leon/console/Makefile.am create mode 100644 c/src/lib/libbsp/sparc/leon/console/console.c create mode 100644 c/src/lib/libbsp/sparc/leon/console/consolereserveresources.c create mode 100644 c/src/lib/libbsp/sparc/leon/console/debugputs.c (limited to 'c/src/lib/libbsp/sparc/leon/console') diff --git a/c/src/lib/libbsp/sparc/leon/console/.cvsignore b/c/src/lib/libbsp/sparc/leon/console/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/lib/libbsp/sparc/leon/console/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/lib/libbsp/sparc/leon/console/Makefile.am b/c/src/lib/libbsp/sparc/leon/console/Makefile.am new file mode 100644 index 0000000000..dfce241bab --- /dev/null +++ b/c/src/lib/libbsp/sparc/leon/console/Makefile.am @@ -0,0 +1,33 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +PGM = $(ARCH)/console.rel + +C_FILES = console.c consolereserveresources.c debugputs.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +OBJS = $(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +$(PGM): $(OBJS) + $(make-rel) + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile + +all-local: $(ARCH) $(OBJS) $(PGM) + +.PRECIOUS: $(PGM) + +EXTRA_DIST = console.c consolereserveresources.c debugputs.c + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/sparc/leon/console/console.c b/c/src/lib/libbsp/sparc/leon/console/console.c new file mode 100644 index 0000000000..00730f5718 --- /dev/null +++ b/c/src/lib/libbsp/sparc/leon/console/console.c @@ -0,0 +1,439 @@ +/* + * This file contains the TTY driver for the serial ports on the LEON. + * + * This driver uses the termios pseudo driver. + * + * COPYRIGHT (c) 1989-1998. + * 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 + +/* + * Should we use a polled or interrupt drived console? + * + * NOTE: This is defined in the custom/leon.cfg file. + * + * WARNING: In sis 1.6, it did not appear that the UART interrupts + * worked in a desirable fashion. Immediately upon writing + * a character into the TX buffer, an interrupt was generated. + * This did not allow enough time for the program to put more + * characters in the buffer. So every character resulted in + * "priming" the transmitter. This effectively results in + * in a polled console with a useless interrupt per character + * on output. It is reasonable to assume that input does not + * share this problem although it was not investigated. + * + */ + +/* + * console_outbyte_polled + * + * This routine transmits a character using polling. + */ + +void console_outbyte_polled( + int port, + char ch +); + +/* body is in debugputs.c */ + +/* + * console_inbyte_nonblocking + * + * This routine polls for a character. + */ + +int console_inbyte_nonblocking( int port ); + +/* body is in debugputs.c */ + +/* + * Interrupt driven console IO + */ + +#if (CONSOLE_USE_INTERRUPTS) + +/* + * Buffers between task and ISRs + */ + +#include + +Ring_buffer_t TX_Buffer[ 2 ]; +boolean Is_TX_active[ 2 ]; + +void *console_termios_data[ 2 ]; + +/* + * console_isr_a + * + * This routine is the console interrupt handler for Channel 1. + * + * Input parameters: + * vector - vector number + * + * Output parameters: NONE + * + * Return values: NONE + */ + +rtems_isr console_isr_a( + rtems_vector_number vector +) +{ + char ch; + int UStat; + + if ( (UStat = LEON_REG.UART_Status_1) & LEON_REG_UART_STATUS_DR ) { + if (UStat & LEON_REG_UART_STATUS_ERR) { + LEON_REG.UART_Status_1 = LEON_REG_UART_STATUS_CLR; + } + ch = LEON_REG.UART_Channel_1; + + rtems_termios_enqueue_raw_characters( console_termios_data[ 0 ], &ch, 1 ); + } + + if ( LEON_REG.UART_Status_1 & LEON_REG_UART_STATUS_THE ) { + if ( !Ring_buffer_Is_empty( &TX_Buffer[ 0 ] ) ) { + Ring_buffer_Remove_character( &TX_Buffer[ 0 ], ch ); + LEON_REG.UART_Channel_1 = (unsigned32) ch; + } else + Is_TX_active[ 0 ] = FALSE; + } + + LEON_Clear_interrupt( LEON_INTERRUPT_UART_1_RX_TX ); +} + +/* + * console_isr_b + * + * This routine is the console interrupt handler for Channel 2. + * + * Input parameters: + * vector - vector number + * + * Output parameters: NONE + * + * Return values: NONE + */ + +rtems_isr console_isr_b( + rtems_vector_number vector +) +{ + char ch; + int UStat; + + if ( (UStat = LEON_REG.UART_Status_2) & LEON_REG_UART_STATUS_DR ) { + if (UStat & LEON_REG_UART_STATUS_ERR) { + LEON_REG.UART_Status_2 = LEON_REG_UART_STATUS_CLR; + } + ch = LEON_REG.UART_Channel_2; + rtems_termios_enqueue_raw_characters( console_termios_data[ 1 ], &ch, 1 ); + + } + + if ( LEON_REG.UART_Status_2 & LEON_REG_UART_STATUS_THE ) { + if ( !Ring_buffer_Is_empty( &TX_Buffer[ 1 ] ) ) { + Ring_buffer_Remove_character( &TX_Buffer[ 1 ], ch ); + LEON_REG.UART_Channel_2 = (unsigned32) ch; + } else + Is_TX_active[ 1 ] = FALSE; + } + + LEON_Clear_interrupt( LEON_INTERRUPT_UART_2_RX_TX ); +} + +/* + * console_exit + * + * This routine allows the console to exit by masking its associated interrupt + * vectors. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ + +void console_exit() +{ + rtems_unsigned32 port; + rtems_unsigned32 ch; + + /* + * Although the interrupts for the UART are unmasked, the PIL is set to + * disable all external interrupts. So we might as well do this first. + */ + + LEON_Mask_interrupt( LEON_INTERRUPT_UART_1_RX_TX ); + LEON_Mask_interrupt( LEON_INTERRUPT_UART_2_RX_TX ); + + for ( port=0 ; port <= 1 ; port++ ) { + while ( !Ring_buffer_Is_empty( &TX_Buffer[ port ] ) ) { + Ring_buffer_Remove_character( &TX_Buffer[ port ], ch ); + console_outbyte_polled( port, ch ); + } + } + + /* + * Now wait for all the data to actually get out ... the send register + * should be empty. + */ + + while ( (LEON_REG.UART_Status_1 & LEON_REG_UART_STATUS_THE) != + LEON_REG_UART_STATUS_THE ); + + while ( (LEON_REG.UART_Status_2 & LEON_REG_UART_STATUS_THE) != + LEON_REG_UART_STATUS_THE ); + + LEON_REG.UART_Control_1 = 0; + LEON_REG.UART_Control_2 = 0; + LEON_REG.UART_Status_1 = 0; + LEON_REG.UART_Status_2 = 0; + + +} + +#define CONSOLE_UART_1_TRAP LEON_TRAP_TYPE( LEON_INTERRUPT_UART_1_RX_TX ) +#define CONSOLE_UART_2_TRAP LEON_TRAP_TYPE( LEON_INTERRUPT_UART_2_RX_TX ) + +/* + * console_initialize_interrupts + * + * This routine initializes the console's receive and transmit + * ring buffers and loads the appropriate vectors to handle the interrupts. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ + +#ifdef RDB_BREAK_IN + extern unsigned32 trap_table[]; +#endif + +void console_initialize_interrupts( void ) +{ + Ring_buffer_Initialize( &TX_Buffer[ 0 ] ); + Ring_buffer_Initialize( &TX_Buffer[ 1 ] ); + + Is_TX_active[ 0 ] = FALSE; + Is_TX_active[ 1 ] = FALSE; + + atexit( console_exit ); + + LEON_REG.UART_Control_1 |= LEON_REG_UART_CTRL_RI | LEON_REG_UART_CTRL_TI; + LEON_REG.UART_Control_2 |= LEON_REG_UART_CTRL_RI | LEON_REG_UART_CTRL_TI; + + set_vector( console_isr_a, CONSOLE_UART_1_TRAP, 1 ); +#ifdef RDB_BREAK_IN + if (trap_table[0x150/4] == 0x91d02000) +#endif + set_vector( console_isr_b, CONSOLE_UART_2_TRAP, 1 ); +} + +/* + * console_outbyte_interrupt + * + * 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_interrupt( + int port, + char ch +) +{ + /* + * If this is the first character then we need to prime the pump + */ + + if ( Is_TX_active[ port ] == FALSE ) { + Is_TX_active[ port ] = TRUE; + console_outbyte_polled( port, ch ); + return; + } + + while ( Ring_buffer_Is_full( &TX_Buffer[ port ] ) ); + + Ring_buffer_Add_character( &TX_Buffer[ port ], ch ); +} + +#endif /* CONSOLE_USE_INTERRUPTS */ + +/* + * Console Termios Support Entry Points + * + */ + +int console_write_support (int minor, const char *buf, int len) +{ + int nwrite = 0; + + while (nwrite < len) { +#if (CONSOLE_USE_INTERRUPTS) + console_outbyte_interrupt( minor, *buf++ ); +#else + console_outbyte_polled( minor, *buf++ ); +#endif + nwrite++; + } + return nwrite; +} + +void console_reserve_resources( + rtems_configuration_table *configuration +) +{ + rtems_termios_reserve_resources( configuration, 2 ); +} + +/* + * Console Device Driver Entry Points + * + */ + +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code status; + + rtems_termios_initialize(); + + /* + * Register Device Names + */ + + status = rtems_io_register_name( "/dev/console", major, 0 ); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred(status); + + status = rtems_io_register_name( "/dev/console_b", major, 1 ); + if (status != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred(status); + + /* + * Initialize Hardware + */ + + LEON_REG.UART_Control_1 = LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE; + LEON_REG.UART_Control_2 = LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE | + LEON_REG_UART_CTRL_RI; /* rx irq default enable for remote debugger */ + LEON_REG.UART_Status_1 = 0; + LEON_REG.UART_Status_2 = 0; +#if (CONSOLE_USE_INTERRUPTS) + console_initialize_interrupts(); +#endif + + return RTEMS_SUCCESSFUL; +} + +rtems_device_driver console_open( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + rtems_status_code sc; +#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 */ + 0 /* 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 + + assert( minor <= 1 ); + if ( minor > 2 ) + return RTEMS_INVALID_NUMBER; + +#if (CONSOLE_USE_INTERRUPTS) + sc = rtems_termios_open (major, minor, arg, &intrCallbacks); + + console_termios_data[ minor ] = args->iop->data1; +#else + sc = rtems_termios_open (major, minor, arg, &pollCallbacks); +#endif + + return RTEMS_SUCCESSFUL; +} + +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); +} + diff --git a/c/src/lib/libbsp/sparc/leon/console/consolereserveresources.c b/c/src/lib/libbsp/sparc/leon/console/consolereserveresources.c new file mode 100644 index 0000000000..b5df942a8e --- /dev/null +++ b/c/src/lib/libbsp/sparc/leon/console/consolereserveresources.c @@ -0,0 +1,21 @@ +/* + * This file contains the TTY driver for the serial ports on the LEON. + * + * This driver uses the termios pseudo driver. + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * 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 + +int console_reserve_resources_removed; diff --git a/c/src/lib/libbsp/sparc/leon/console/debugputs.c b/c/src/lib/libbsp/sparc/leon/console/debugputs.c new file mode 100644 index 0000000000..71b5c8debf --- /dev/null +++ b/c/src/lib/libbsp/sparc/leon/console/debugputs.c @@ -0,0 +1,109 @@ +/* + * This file contains the TTY driver for the serial ports on the LEON. + * + * This driver uses the termios pseudo driver. + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * 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 + +/* + * console_outbyte_polled + * + * This routine transmits a character using polling. + */ + +void console_outbyte_polled( + int port, + char ch +) +{ + if ( port == 0 ) { + while ( (LEON_REG.UART_Status_1 & LEON_REG_UART_STATUS_THE) == 0 ); + LEON_REG.UART_Channel_1 = (int) ch; + return; + } + + while ( (LEON_REG.UART_Status_2 & LEON_REG_UART_STATUS_THE) == 0 ); + LEON_REG.UART_Channel_2 = (int) ch; +} + +/* + * console_inbyte_nonblocking + * + * This routine polls for a character. + */ + +int console_inbyte_nonblocking( int port ) +{ + + switch (port) { + + case 0: + if (LEON_REG.UART_Status_1 & LEON_REG_UART_STATUS_ERR) { + LEON_REG.UART_Status_1 = ~LEON_REG_UART_STATUS_ERR; + } + + if ((LEON_REG.UART_Status_1 & LEON_REG_UART_STATUS_DR) == 0) + return -1; + return (int) LEON_REG.UART_Channel_1; + return 1; + + case 1: + if (LEON_REG.UART_Status_2 & LEON_REG_UART_STATUS_ERR) { + LEON_REG.UART_Status_2 = ~LEON_REG_UART_STATUS_ERR; + } + + if ((LEON_REG.UART_Status_2 & LEON_REG_UART_STATUS_DR) == 0) + return -1; + return (int) LEON_REG.UART_Channel_2; + + default: + assert( 0 ); + } + + return -1; +} + +/* + * 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; + unsigned32 old_level; + + LEON_Disable_interrupt( LEON_INTERRUPT_UART_1_RX_TX, old_level ); + LEON_REG.UART_Control_1 = LEON_REG_UART_CTRL_TE; + for ( s = string ; *s ; s++ ) + console_outbyte_polled( 0, *s ); + + console_outbyte_polled( 0, '\r' ); + console_outbyte_polled( 0, '\n' ); + LEON_Restore_interrupt( LEON_INTERRUPT_UART_1_RX_TX, old_level ); +} -- cgit v1.2.3