diff options
author | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2009-07-17 13:53:24 +0000 |
---|---|---|
committer | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2009-07-17 13:53:24 +0000 |
commit | ec5d45053b71f052d978e423f08ad4e28e1b800d (patch) | |
tree | e816f35f7d24a8a6c99bcdd60a18ca5227ff8bee /c | |
parent | ARM bsp maintenance (diff) | |
download | rtems-ec5d45053b71f052d978e423f08ad4e28e1b800d.tar.bz2 |
code cleanup
Diffstat (limited to 'c')
-rw-r--r-- | c/src/ChangeLog | 6 | ||||
-rw-r--r-- | c/src/libchip/serial/ns16550.c | 212 | ||||
-rw-r--r-- | c/src/libchip/serial/ns16550_p.h | 55 |
3 files changed, 119 insertions, 154 deletions
diff --git a/c/src/ChangeLog b/c/src/ChangeLog index 79cdd52b4b..9c780033d0 100644 --- a/c/src/ChangeLog +++ b/c/src/ChangeLog @@ -5,6 +5,12 @@ now use the same macros. * aclocal/bsp-bspcleanup-options.m4: New file. +2009-07-15 Sebastian Huber <sebastian.huber@embedded-brains.de> + + * libchip/serial/ns16550.c, libchip/serial/ns16550_p.h: Removed + obsolete defines and declarations. Set initial baud during device + open. Fixed interrupt mode. + 2009-06-12 Joel Sherrill <joel.sherrill@oarcorp.com> * libchip/i2c/spi-sd-card.c, libchip/ide/ata.c: Eliminate using the diff --git a/c/src/libchip/serial/ns16550.c b/c/src/libchip/serial/ns16550.c index f31ddf7a04..631625e6a9 100644 --- a/c/src/libchip/serial/ns16550.c +++ b/c/src/libchip/serial/ns16550.c @@ -30,6 +30,7 @@ #include <rtems/libio.h> #include <rtems/ringbuf.h> #include <rtems/bspIo.h> +#include <rtems/termiostypes.h> #include <libchip/serial.h> #include <libchip/sersupp.h> @@ -164,20 +165,24 @@ NS16550_STATIC void ns16550_init(int minor) */ NS16550_STATIC int ns16550_open( - int major, - int minor, - void * arg + int major, + int minor, + void *arg ) { - /* - * Assert DTR - */ + rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg; + struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1; + console_tbl *c = &Console_Port_Tbl [minor]; - if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_DTRCTS) { - ns16550_assert_DTR(minor); + /* Assert DTR */ + if (c->pDeviceFlow != &ns16550_flow_DTRCTS) { + ns16550_assert_DTR( minor); } - return(RTEMS_SUCCESSFUL); + /* Set initial baud */ + rtems_termios_set_initial_baud( tty, (int) c->pDeviceParams); + + return RTEMS_SUCCESSFUL; } /* @@ -203,15 +208,22 @@ NS16550_STATIC int ns16550_close( /** * @brief Polled write for NS16550. */ -NS16550_STATIC void ns16550_write_polled( int minor, char c) +NS16550_STATIC void ns16550_write_polled( int minor, char out) { - uint32_t port = Console_Port_Tbl [minor].ulCtrlPort1; - getRegister_f get = Console_Port_Tbl [minor].getRegister; - setRegister_f set = Console_Port_Tbl [minor].setRegister; - uint32_t status; + console_tbl *c = &Console_Port_Tbl [minor]; + uint32_t port = c->ulCtrlPort1; + getRegister_f get = c->getRegister; + setRegister_f set = c->setRegister; + uint32_t status = 0; rtems_interrupt_level level; - while (1) { + /* Save port interrupt mask */ + uint32_t interrupt_mask = get( port, NS16550_INTERRUPT_ENABLE); + + /* Disable port interrupts */ + ns16550_enable_interrupts( minor, NS16550_DISABLE_ALL_INTR); + + while (true) { /* Try to transmit the character in a critical section */ rtems_interrupt_disable( level); @@ -219,7 +231,7 @@ NS16550_STATIC void ns16550_write_polled( int minor, char c) status = get( port, NS16550_LINE_STATUS); if ((status & SP_LSR_THOLD) != 0) { /* Transmit character */ - set( port, NS16550_TRANSMIT_BUFFER, c); + set( port, NS16550_TRANSMIT_BUFFER, out); /* Finished */ rtems_interrupt_enable( level); @@ -233,6 +245,9 @@ NS16550_STATIC void ns16550_write_polled( int minor, char c) status = get( port, NS16550_LINE_STATUS); } while ((status & SP_LSR_THOLD) == 0); } + + /* Restore port interrupt mask */ + set( port, NS16550_INTERRUPT_ENABLE, interrupt_mask); } /* @@ -448,72 +463,91 @@ NS16550_STATIC int ns16550_set_attributes( } #if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY) -/* - * ns16550_process - * - * This routine is the console interrupt handler for A port. - */ -NS16550_STATIC void ns16550_process(int minor) +/** + * @brief Process interrupt. + */ +NS16550_STATIC void ns16550_process( int minor) { console_tbl *c = &Console_Port_Tbl [minor]; console_data *d = &Console_Port_Data [minor]; - - uint32_t pNS16550; - volatile uint8_t ucLineStatus; - volatile uint8_t ucInterruptId; - char cChar; - getRegister_f getReg; - setRegister_f setReg; - - pNS16550 = c->ulCtrlPort1; - getReg = c->getRegister; - setReg = c->setRegister; - + ns16550_context *ctx = d->pDeviceContext; + uint32_t port = c->ulCtrlPort1; + getRegister_f get = c->getRegister; + setRegister_f set = c->setRegister; + int i = 0; + char buf [SP_FIFO_SIZE]; + + /* Iterate until no more interrupts are pending */ do { - /* - * Deal with any received characters - */ - while (true) { - ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS); - if (~ucLineStatus & SP_LSR_RDY) { + /* Fetch received characters */ + for (i = 0; i < SP_FIFO_SIZE; ++i) { + if ((get( port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) { + buf [i] = (char) get(port, NS16550_RECEIVE_BUFFER); + } else { break; } - cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER); - rtems_termios_enqueue_raw_characters( - d->termios_data, - &cChar, - 1 - ); } - /* - * TX all the characters we can - */ + /* Enqueue fetched characters */ + rtems_termios_enqueue_raw_characters( d->termios_data, buf, i); - while (true) { - ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS); - if (~ucLineStatus & SP_LSR_THOLD) { - /* - * We'll get another interrupt when - * the transmitter holding reg. becomes - * free again - */ - break; - } + /* Check if we can dequeue transmitted characters */ + if (ctx->transmitFifoChars > 0 + && (get( port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) { + unsigned chars = ctx->transmitFifoChars; + + /* + * We finished the transmission, so clear the number of characters in the + * transmit FIFO. + */ + ctx->transmitFifoChars = 0; - if (rtems_termios_dequeue_characters( d->termios_data, 1) == 0) { - if (c->pDeviceFlow != &ns16550_flow_RTSCTS) { - ns16550_negate_RTS(minor); - } + /* Dequeue transmitted characters */ + if (rtems_termios_dequeue_characters( d->termios_data, chars) == 0) { + /* Nothing to do */ d->bActive = false; - ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); - break; + ns16550_enable_interrupts( minor, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); } } + } while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0); +} +#endif + +/** + * @brief Transmits up to @a len characters from @a buf. + * + * This routine is invoked either from task context with disabled interrupts to + * start a new transmission process with exactly one character in case of an + * idle output state or from the interrupt handler to refill the transmitter. + * + * Returns always zero. + */ +NS16550_STATIC int ns16550_write_support_int( + int minor, + const char *buf, + int len +) +{ + console_tbl *c = &Console_Port_Tbl [minor]; + console_data *d = &Console_Port_Data [minor]; + ns16550_context *ctx = d->pDeviceContext; + uint32_t port = c->ulCtrlPort1; + setRegister_f set = c->setRegister; + int i = 0; + int out = len > SP_FIFO_SIZE ? SP_FIFO_SIZE : len; + + for (i = 0; i < out; ++i) { + set( port, NS16550_TRANSMIT_BUFFER, buf [i]); + } + + if (len > 0) { + ctx->transmitFifoChars = out; + d->bActive = true; + ns16550_enable_interrupts( minor, NS16550_ENABLE_ALL_INTR); + } - ucInterruptId = (*getReg)(pNS16550, NS16550_INTERRUPT_ID); - } while((ucInterruptId&0xf)!=0x1); + return 0; } /* @@ -521,8 +555,6 @@ NS16550_STATIC void ns16550_process(int minor) * * This routine initializes the port to have the specified interrupts masked. */ -#endif - NS16550_STATIC void ns16550_enable_interrupts( int minor, int mask @@ -622,48 +654,6 @@ NS16550_STATIC void ns16550_initialize_interrupts( int minor) } /* - * ns16550_write_support_int - * - * Console Termios output entry point. - */ - -NS16550_STATIC int ns16550_write_support_int( - int minor, - const char *buf, - int len -) -{ - uint32_t Irql; - uint32_t pNS16550; - setRegister_f setReg; - - setReg = Console_Port_Tbl[minor].setRegister; - pNS16550 = Console_Port_Tbl[minor].ulCtrlPort1; - - /* - * We are using interrupt driven output and termios only sends us - * one character at a time. - */ - - if ( !len ) - return 0; - - if(Console_Port_Tbl[minor].pDeviceFlow != &ns16550_flow_RTSCTS) { - ns16550_assert_RTS(minor); - } - - rtems_interrupt_disable(Irql); - if ( Console_Port_Data[minor].bActive == false) { - Console_Port_Data[minor].bActive = true; - ns16550_enable_interrupts(minor, NS16550_ENABLE_ALL_INTR); - } - (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, *buf); - rtems_interrupt_enable(Irql); - - return 1; -} - -/* * ns16550_write_support_polled * * Console Termios output entry point. diff --git a/c/src/libchip/serial/ns16550_p.h b/c/src/libchip/serial/ns16550_p.h index 480d3ea5e1..a32b46f969 100644 --- a/c/src/libchip/serial/ns16550_p.h +++ b/c/src/libchip/serial/ns16550_p.h @@ -29,24 +29,11 @@ extern "C" { #define NS16550_STATIC static -/* - * Define serial port read registers structure. - */ - -typedef volatile struct _SP_READ_REGISTERS { - unsigned char ReceiveBuffer; - unsigned char InterruptEnable; - unsigned char InterruptId; - unsigned char LineControl; - unsigned char ModemControl; - unsigned char LineStatus; - unsigned char ModemStatus; - unsigned char ScratchPad; -} SP_READ_REGISTERS, *PSP_READ_REGISTERS; - #define NS16550_RECEIVE_BUFFER 0 +#define NS16550_TRANSMIT_BUFFER 0 #define NS16550_INTERRUPT_ENABLE 1 #define NS16550_INTERRUPT_ID 2 +#define NS16550_FIFO_CONTROL 2 #define NS16550_LINE_CONTROL 3 #define NS16550_MODEM_CONTROL 4 #define NS16550_LINE_STATUS 5 @@ -54,24 +41,6 @@ typedef volatile struct _SP_READ_REGISTERS { #define NS16550_SCRATCH_PAD 7 /* - * Define serial port write registers structure. - */ - -typedef volatile struct _SP_WRITE_REGISTERS { - unsigned char TransmitBuffer; - unsigned char InterruptEnable; - unsigned char FifoControl; - unsigned char LineControl; - unsigned char ModemControl; - unsigned char Reserved1; - unsigned char ModemStatus; - unsigned char ScratchPad; -} SP_WRITE_REGISTERS, *PSP_WRITE_REGISTERS; - -#define NS16550_TRANSMIT_BUFFER 0 -#define NS16550_FIFO_CONTROL 2 - -/* * Define serial port interrupt enable register structure. */ @@ -85,15 +54,13 @@ typedef volatile struct _SP_WRITE_REGISTERS { #define NS16550_ENABLE_ALL_INTR_EXCEPT_TX (SP_INT_RX_ENABLE) /* - * Define serial port interrupt id register structure. + * Define serial port interrupt ID register structure. */ -typedef struct _SP_INTERRUPT_ID { - unsigned char InterruptPending : 1; - unsigned char Identification : 3; - unsigned char Reserved1 : 2; - unsigned char FifoEnabled : 2; -} SP_INTERRUPT_ID, *PSP_INTERRUPT_ID; +#define SP_IID_0 0x01 +#define SP_IID_1 0x02 +#define SP_IID_2 0x04 +#define SP_IID_3 0x08 /* * Define serial port fifo control register structure. @@ -105,6 +72,8 @@ typedef struct _SP_INTERRUPT_ID { #define SP_FIFO_DMA 0x08 #define SP_FIFO_RXLEVEL 0xc0 +#define SP_FIFO_SIZE 16 + /* * Define serial port line control register structure. */ @@ -156,9 +125,9 @@ typedef struct _SP_INTERRUPT_ID { #define SP_LSR_TX 0x40 #define SP_LSR_EFIFO 0x80 -typedef struct _ns16550_context -{ - uint8_t ucModemCtrl; +typedef struct { + uint8_t ucModemCtrl; + int transmitFifoChars; } ns16550_context; /* |