diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2011-03-03 14:03:48 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2011-03-03 14:03:48 +0000 |
commit | 5180f7cb36c1f5483772d39847bd29f6369d978c (patch) | |
tree | bd4a4c3f83f2ce00064bf989413a9a14a695af05 /c | |
parent | 280f82d71dd5c0beef5da32a6d639ec5ac782007 (diff) |
2011-03-03 Joel Sherrill <joel.sherrilL@OARcorp.com>
PR 1750/bsps
* console/erc32_console.c: The new console driver did not support
polled mode. It also had a bug in which it could lose a transmitter
interrupt.
Diffstat (limited to 'c')
-rw-r--r-- | c/src/lib/libbsp/sparc/erc32/ChangeLog | 7 | ||||
-rw-r--r-- | c/src/lib/libbsp/sparc/erc32/console/erc32_console.c | 368 |
2 files changed, 217 insertions, 158 deletions
diff --git a/c/src/lib/libbsp/sparc/erc32/ChangeLog b/c/src/lib/libbsp/sparc/erc32/ChangeLog index afeb44822a..80665d1088 100644 --- a/c/src/lib/libbsp/sparc/erc32/ChangeLog +++ b/c/src/lib/libbsp/sparc/erc32/ChangeLog @@ -1,3 +1,10 @@ +2011-03-03 Joel Sherrill <joel.sherrilL@OARcorp.com> + + PR 1750/bsps + * console/erc32_console.c: The new console driver did not support + polled mode. It also had a bug in which it could lose a transmitter + interrupt. + 2011-02-02 Ralf Corsépius <ralf.corsepius@rtems.org> * configure.ac: Require autoconf-2.68, automake-1.11.1. diff --git a/c/src/lib/libbsp/sparc/erc32/console/erc32_console.c b/c/src/lib/libbsp/sparc/erc32/console/erc32_console.c index e91c4c0f0a..1478afb57d 100644 --- a/c/src/lib/libbsp/sparc/erc32/console/erc32_console.c +++ b/c/src/lib/libbsp/sparc/erc32/console/erc32_console.c @@ -27,6 +27,7 @@ #include <libchip/sersupp.h> #include <bsp.h> +#include <bspopts.h> #define CONSOLE_BUF_SIZE (16) @@ -35,23 +36,32 @@ static uint8_t erc32_console_get_register(uint32_t addr, uint8_t i) { - volatile uint32_t *reg = (volatile uint32_t *)addr; - return (uint8_t) reg [i]; + volatile uint32_t *reg = (volatile uint32_t *)addr; + return (uint8_t) reg [i]; } static void erc32_console_set_register(uint32_t addr, uint8_t i, uint8_t val) { - volatile uint32_t *reg = (volatile uint32_t *)addr; - reg [i] = val; + volatile uint32_t *reg = (volatile uint32_t *)addr; + reg [i] = val; } static int erc32_console_first_open(int major, int minor, void *arg); -static ssize_t erc32_console_write_support_int(int minor, const char *buf, size_t len); + +#if (CONSOLE_USE_INTERRUPTS) + static ssize_t erc32_console_write_support_int( + int minor, const char *buf, size_t len); +#else + int console_inbyte_nonblocking( int port ); + static ssize_t erc32_console_write_support_polled( + int minor, const char *buf, size_t len); +#endif static void erc32_console_initialize(int minor); rtems_device_minor_number Console_Port_Minor = 0; -console_fns erc32_fns = { +#if (CONSOLE_USE_INTERRUPTS) + console_fns erc32_fns = { libchip_serial_default_probe, /* deviceProbe */ erc32_console_first_open, /* deviceFirstOpen */ NULL, /* deviceLastClose */ @@ -60,48 +70,61 @@ console_fns erc32_fns = { erc32_console_initialize, /* deviceInitialize */ NULL, /* deviceWritePolled */ NULL, /* deviceSetAttributes */ - true /* deviceOutputUsesInterrupts */ -}; + TERMIOS_IRQ_DRIVEN /* deviceOutputUsesInterrupts */ + }; +#else + console_fns erc32_fns = { + libchip_serial_default_probe, /* deviceProbe */ + erc32_console_first_open, /* deviceFirstOpen */ + NULL, /* deviceLastClose */ + console_inbyte_nonblocking, /* deviceRead */ + erc32_console_write_support_polled, /* deviceWrite */ + erc32_console_initialize, /* deviceInitialize */ + NULL, /* deviceWritePolled */ + NULL, /* deviceSetAttributes */ + TERMIOS_POLLED /* deviceOutputUsesInterrupts */ + }; +#endif console_tbl Console_Port_Tbl [] = { - { - .sDeviceName = "/dev/console", - .deviceType = SERIAL_CUSTOM, - .pDeviceFns = &erc32_fns, - .deviceProbe = NULL, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) 1, - .ulCtrlPort1 = 0, - .ulCtrlPort2 = 0, - .ulDataPort = 0, - .getRegister = erc32_console_get_register, - .setRegister = erc32_console_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = 16, - .ulIntVector = ERC32_INTERRUPT_UART_A_RX_TX - }, - { - .sDeviceName = "/dev/console_b", - .deviceType = SERIAL_CUSTOM, - .pDeviceFns = &erc32_fns, - .deviceProbe = NULL, - .pDeviceFlow = NULL, - .ulMargin = 16, - .ulHysteresis = 8, - .pDeviceParams = (void *) 1, - .ulCtrlPort1 = 0, - .ulCtrlPort2 = 0, - .ulDataPort = 0, - .getRegister = erc32_console_get_register, - .setRegister = erc32_console_set_register, - .getData = NULL, - .setData = NULL, - .ulClock = 16, - .ulIntVector = ERC32_INTERRUPT_UART_B_RX_TX - }, + { + .sDeviceName = "/dev/console_a", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &erc32_fns, + .deviceProbe = NULL, + .pDeviceFlow = NULL, + .ulMargin = 16, + .ulHysteresis = 8, + .pDeviceParams = (void *) -1, /* could be baud rate */ + .ulCtrlPort1 = 0, + .ulCtrlPort2 = 0, + .ulDataPort = 0, + .getRegister = erc32_console_get_register, + .setRegister = erc32_console_set_register, + .getData = NULL, + .setData = NULL, + .ulClock = 16, + .ulIntVector = ERC32_INTERRUPT_UART_A_RX_TX + }, + { + .sDeviceName = "/dev/console_b", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &erc32_fns, + .deviceProbe = NULL, + .pDeviceFlow = NULL, + .ulMargin = 16, + .ulHysteresis = 8, + .pDeviceParams = (void *) -1, /* could be baud rate */ + .ulCtrlPort1 = 0, + .ulCtrlPort2 = 0, + .ulDataPort = 0, + .getRegister = erc32_console_get_register, + .setRegister = erc32_console_set_register, + .getData = NULL, + .setData = NULL, + .ulClock = 16, + .ulIntVector = ERC32_INTERRUPT_UART_B_RX_TX + }, }; /* always exactly two uarts for erc32 */ @@ -113,124 +136,151 @@ console_data Console_Port_Data [ERC32_UART_COUNT]; static int erc32_console_first_open(int major, int minor, void *arg) { - /* Check minor number */ - if (minor < 0 || minor > 1) { - return -1; - } - - rtems_libio_open_close_args_t *oca = arg; - struct rtems_termios_tty *tty = oca->iop->data1; - console_tbl *ct = &Console_Port_Tbl [minor]; - console_data *cd = &Console_Port_Data [minor]; - - cd->termios_data = tty; - rtems_termios_set_initial_baud(tty, (int32_t)ct->pDeviceParams); - - return 0; + /* Check minor number */ + if (minor < 0 || minor > 1) { + return -1; + } + + rtems_libio_open_close_args_t *oca = arg; + struct rtems_termios_tty *tty = oca->iop->data1; + console_tbl *ct = &Console_Port_Tbl [minor]; + console_data *cd = &Console_Port_Data [minor]; + + cd->termios_data = tty; + rtems_termios_set_initial_baud(tty, (int32_t)ct->pDeviceParams); + + return 0; } +#if (CONSOLE_USE_INTERRUPTS) static ssize_t erc32_console_write_support_int(int minor, const char *buf, size_t len) { - console_data *cd = &Console_Port_Data[minor]; - int k = 0; - - if (minor == 0) { /* uart a */ - for (k = 0; k < len && (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA); k ++) { - ERC32_MEC.UART_Channel_A = (unsigned char)buf[k]; - } - ERC32_Force_interrupt(ERC32_INTERRUPT_UART_A_RX_TX); - } else { /* uart b */ - for (k = 0; k < len && (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB); k ++) { - ERC32_MEC.UART_Channel_B = (unsigned char)buf[k]; - } - ERC32_Force_interrupt(ERC32_INTERRUPT_UART_B_RX_TX); + console_data *cd = &Console_Port_Data[minor]; + int k = 0; + + if (minor == 0) { /* uart a */ + for (k = 0; + k < len && (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA); k ++) { + ERC32_MEC.UART_Channel_A = (unsigned char)buf[k]; } - - if (len > 0) { - cd->pDeviceContext = (void *)k; - cd->bActive = true; + ERC32_Force_interrupt(ERC32_INTERRUPT_UART_A_RX_TX); + } else { /* uart b */ + for (k = 0; + k < len && (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB); k ++) { + ERC32_MEC.UART_Channel_B = (unsigned char)buf[k]; } - - return 0; + ERC32_Force_interrupt(ERC32_INTERRUPT_UART_B_RX_TX); + } + + if (len > 0) { + cd->pDeviceContext = (void *)k; + cd->bActive = true; + } + + return 0; } static void erc32_console_isr_a( - rtems_vector_number vector + rtems_vector_number vector ) { - console_data *cd = &Console_Port_Data[0]; - - /* check for error */ - if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRA) { - ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA; - ERC32_MEC.Control = ERC32_MEC.Control; - } - - do { - int chars_to_dequeue = (int)cd->pDeviceContext; - int rv = 0; - int i = 0; - char buf[CONSOLE_BUF_SIZE]; + console_data *cd = &Console_Port_Data[0]; + + /* check for error */ + if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRA) { + ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA; + ERC32_MEC.Control = ERC32_MEC.Control; + } + + do { + int chars_to_dequeue = (int)cd->pDeviceContext; + int rv = 0; + int i = 0; + char buf[CONSOLE_BUF_SIZE]; - /* enqueue received chars */ - while (i < CONSOLE_BUF_SIZE) { - if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRA) { - buf[i] = ERC32_MEC.UART_Channel_A; - ++i; - } else { - break; - } - } - rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i); - - /* dequeue transmitted chars */ + /* enqueue received chars */ + while (i < CONSOLE_BUF_SIZE) { + if (!(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRA)) + break; + buf[i] = ERC32_MEC.UART_Channel_A; + ++i; + } + if ( i ) + rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i); + + /* dequeue transmitted chars */ + if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA) { + rv = rtems_termios_dequeue_characters( + cd->termios_data, chars_to_dequeue); + if ( !rv ) { cd->pDeviceContext = 0; - rv = rtems_termios_dequeue_characters(cd->termios_data, chars_to_dequeue); - if (rv == 0 && !(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRA)) { - cd->bActive = false; - ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_A_RX_TX); - } - } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_A_RX_TX)); + cd->bActive = false; + } + ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_A_RX_TX); + } + } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_A_RX_TX)); } static void erc32_console_isr_b( - rtems_vector_number vector + rtems_vector_number vector ) { - console_data *cd = &Console_Port_Data[1]; - - /* check for error */ - if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRB) { - ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB; - ERC32_MEC.Control = ERC32_MEC.Control; - } - - do { - int chars_to_dequeue = (int)cd->pDeviceContext; - int rv = 0; - int i = 0; - char buf[CONSOLE_BUF_SIZE]; + console_data *cd = &Console_Port_Data[1]; + + /* check for error */ + if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRB) { + ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB; + ERC32_MEC.Control = ERC32_MEC.Control; + } + + do { + int chars_to_dequeue = (int)cd->pDeviceContext; + int rv = 0; + int i = 0; + char buf[CONSOLE_BUF_SIZE]; - /* enqueue received chars */ - while (i < CONSOLE_BUF_SIZE) { - if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRB) { - buf[i] = ERC32_MEC.UART_Channel_B; - ++i; - } else { - break; - } - } - rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i); - - /* dequeue transmitted chars */ + /* enqueue received chars */ + while (i < CONSOLE_BUF_SIZE) { + if (!(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRB)) + break; + buf[i] = ERC32_MEC.UART_Channel_B; + ++i; + } + if ( i ) + rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i); + + /* dequeue transmitted chars */ + if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB) { + rv = rtems_termios_dequeue_characters( + cd->termios_data, chars_to_dequeue); + if ( !rv ) { cd->pDeviceContext = 0; - rv = rtems_termios_dequeue_characters(cd->termios_data, chars_to_dequeue); - if (rv == 0 && !(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRB)) { - cd->bActive = false; - ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_B_RX_TX); - } - } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_B_RX_TX)); + cd->bActive = false; + } + ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_B_RX_TX); + } + } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_B_RX_TX)); } +#else + +extern void console_outbyte_polled( int port, unsigned char ch ); + +static ssize_t erc32_console_write_support_polled( + int minor, + const char *buf, + size_t len +) +{ + int nwrite = 0; + + while (nwrite < len) { + console_outbyte_polled( minor, *buf++ ); + nwrite++; + } + return nwrite; +} + +#endif /* @@ -242,21 +292,23 @@ static void erc32_console_initialize( int minor ) { - console_data *cd = &Console_Port_Data [minor]; - - cd->bActive = false; - cd->pDeviceContext = 0; - - /* - * Initialize the Termios infrastructure. If Termios has already - * been initialized by another device driver, then this call will - * have no effect. - */ - rtems_termios_initialize(); - - /* - * Initialize Hardware - */ + console_data *cd = &Console_Port_Data [minor]; + + cd->bActive = false; + cd->pDeviceContext = 0; + + /* + * Initialize the Termios infrastructure. If Termios has already + * been initialized by another device driver, then this call will + * have no effect. + */ + rtems_termios_initialize(); + + /* + * Initialize Hardware + */ + #if (CONSOLE_USE_INTERRUPTS) set_vector(erc32_console_isr_a, CONSOLE_UART_A_TRAP, 1); set_vector(erc32_console_isr_b, CONSOLE_UART_B_TRAP, 1); + #endif } |