diff options
Diffstat (limited to 'c/src/libchip/serial/ns16550.c')
-rw-r--r-- | c/src/libchip/serial/ns16550.c | 875 |
1 files changed, 0 insertions, 875 deletions
diff --git a/c/src/libchip/serial/ns16550.c b/c/src/libchip/serial/ns16550.c deleted file mode 100644 index b1e5892c15..0000000000 --- a/c/src/libchip/serial/ns16550.c +++ /dev/null @@ -1,875 +0,0 @@ -/** - * @file - * - * This file contains the TTY driver for the National Semiconductor NS16550. - * - * This part is widely cloned and second sourced. It is found in a number - * of "Super IO" controllers. - * - * 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-2012. - * 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.rtems.org/license/LICENSE. - */ - -#include <stdlib.h> - -#include <rtems.h> -#include <rtems/libio.h> -#include <rtems/ringbuf.h> -#include <rtems/bspIo.h> -#include <rtems/termiostypes.h> - -#include <libchip/serial.h> -#include <libchip/sersupp.h> - -#include <bsp.h> - -#include <libchip/ns16550_p.h> -#include <libchip/ns16550.h> - -#if defined(BSP_FEATURE_IRQ_EXTENSION) - #include <bsp/irq.h> -#elif defined(BSP_FEATURE_IRQ_LEGACY) - #include <bsp/irq.h> -#elif defined(__PPC__) || defined(__i386__) - #include <bsp/irq.h> - #define BSP_FEATURE_IRQ_LEGACY - #ifdef BSP_SHARED_HANDLER_SUPPORT - #define BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT - #endif -#endif - -typedef struct { - uint8_t ucModemCtrl; - int transmitFifoChars; -} NS16550Context; - -/* - * Driver functions - */ - -NS16550_STATIC void ns16550_init(int minor); - -NS16550_STATIC int ns16550_open( - int major, - int minor, - void * arg -); - -NS16550_STATIC int ns16550_close( - int major, - int minor, - void * arg -); - -NS16550_STATIC void ns16550_write_polled( - int minor, - char cChar -); - -NS16550_STATIC int ns16550_assert_RTS( - int minor -); - -NS16550_STATIC int ns16550_negate_RTS( - int minor -); - -NS16550_STATIC int ns16550_assert_DTR( - int minor -); - -NS16550_STATIC int ns16550_negate_DTR( - int minor -); - -NS16550_STATIC void ns16550_initialize_interrupts(int minor); - -NS16550_STATIC void ns16550_cleanup_interrupts(int minor); - -NS16550_STATIC ssize_t ns16550_write_support_int( - int minor, - const char *buf, - size_t len -); - -NS16550_STATIC ssize_t ns16550_write_support_polled( - int minor, - const char *buf, - size_t len - ); - -int ns16550_inbyte_nonblocking_polled( - int minor -); - -NS16550_STATIC void ns16550_enable_interrupts( - console_tbl *c, - int mask -); - -NS16550_STATIC int ns16550_set_attributes( - int minor, - const struct termios *t -); - -#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY) - NS16550_STATIC void ns16550_isr(void *arg); -#endif - -RTEMS_INTERRUPT_LOCK_DEFINE(static, ns16550_lock, "NS16550") - -/* - * Flow control is only supported when using interrupts - */ - -const console_flow ns16550_flow_RTSCTS = { - ns16550_negate_RTS, /* deviceStopRemoteTx */ - ns16550_assert_RTS /* deviceStartRemoteTx */ -}; - -const console_flow ns16550_flow_DTRCTS = { - ns16550_negate_DTR, /* deviceStopRemoteTx */ - ns16550_assert_DTR /* deviceStartRemoteTx */ -}; - -const console_fns ns16550_fns = { - libchip_serial_default_probe, /* deviceProbe */ - ns16550_open, /* deviceFirstOpen */ - ns16550_close, /* deviceLastClose */ - NULL, /* deviceRead */ - ns16550_write_support_int, /* deviceWrite */ - ns16550_init, /* deviceInitialize */ - ns16550_write_polled, /* deviceWritePolled */ - ns16550_set_attributes, /* deviceSetAttributes */ - true /* deviceOutputUsesInterrupts */ -}; - -const console_fns ns16550_fns_polled = { - libchip_serial_default_probe, /* deviceProbe */ - ns16550_open, /* deviceFirstOpen */ - ns16550_close, /* deviceLastClose */ - ns16550_inbyte_nonblocking_polled, /* deviceRead */ - ns16550_write_support_polled, /* deviceWrite */ - ns16550_init, /* deviceInitialize */ - ns16550_write_polled, /* deviceWritePolled */ - ns16550_set_attributes, /* deviceSetAttributes */ - false /* deviceOutputUsesInterrupts */ -}; - -static uint32_t NS16550_GetBaudDivisor(const console_tbl *c, uint32_t baud) -{ - uint32_t clock = c->ulClock; - uint32_t baudDivisor = (clock != 0 ? clock : 115200) / (baud * 16); - - if (c->deviceType == SERIAL_NS16550_WITH_FDR) { - uint32_t fractionalDivider = 0x10; - uint32_t err = baud; - uint32_t mulVal; - uint32_t divAddVal; - - clock /= 16 * baudDivisor; - for (mulVal = 1; mulVal < 16; ++mulVal) { - for (divAddVal = 0; divAddVal < mulVal; ++divAddVal) { - uint32_t actual = (mulVal * clock) / (mulVal + divAddVal); - uint32_t newErr = actual > baud ? actual - baud : baud - actual; - - if (newErr < err) { - err = newErr; - fractionalDivider = (mulVal << 4) | divAddVal; - } - } - } - - (*c->setRegister)( - c->ulCtrlPort1, - NS16550_FRACTIONAL_DIVIDER, - fractionalDivider - ); - } - - return baudDivisor; -} - -/* - * ns16550_init - */ - -void ns16550_init(int minor) -{ - uintptr_t pNS16550; - uint8_t ucDataByte; - uint32_t ulBaudDivisor; - NS16550Context *pns16550Context; - setRegister_f setReg; - getRegister_f getReg; - console_tbl *c = Console_Port_Tbl [minor]; - - pns16550Context=(NS16550Context *)malloc(sizeof(NS16550Context)); - - if (pns16550Context == NULL) { - printk( "%s: Error: Not enough memory\n", __func__); - rtems_fatal_error_occurred( 0xdeadbeef); - } - - Console_Port_Data[minor].pDeviceContext=(void *)pns16550Context; - pns16550Context->ucModemCtrl=SP_MODEM_IRQ; - - pNS16550 = c->ulCtrlPort1; - setReg = c->setRegister; - getReg = c->getRegister; - - /* Clear the divisor latch, clear all interrupt enables, - * and reset and - * disable the FIFO's. - */ - - (*setReg)(pNS16550, NS16550_LINE_CONTROL, 0x0); - ns16550_enable_interrupts( c, NS16550_DISABLE_ALL_INTR ); - - /* Set the divisor latch and set the baud rate. */ - - ulBaudDivisor = NS16550_GetBaudDivisor(c, (uintptr_t) c->pDeviceParams); - ucDataByte = SP_LINE_DLAB; - (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte); - - /* XXX */ - (*setReg)(pNS16550,NS16550_TRANSMIT_BUFFER,(uint8_t)(ulBaudDivisor & 0xffU)); - (*setReg)( - pNS16550,NS16550_INTERRUPT_ENABLE, - (uint8_t)(( ulBaudDivisor >> 8 ) & 0xffU ) - ); - - /* Clear the divisor latch and set the character size to eight bits */ - /* with one stop bit and no parity checking. */ - ucDataByte = EIGHT_BITS; - (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte); - - /* Enable and reset transmit and receive FIFOs. TJA */ - ucDataByte = SP_FIFO_ENABLE; - (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte); - - ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST; - (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte); - - ns16550_enable_interrupts(c, NS16550_DISABLE_ALL_INTR); - - /* Set data terminal ready. */ - /* And open interrupt tristate line */ - (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl); - - (*getReg)(pNS16550, NS16550_LINE_STATUS ); - (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER ); -} - -/* - * ns16550_open - */ - -int ns16550_open( - int major, - int minor, - void *arg -) -{ - 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]; - console_data *d = &Console_Port_Data [minor]; - - d->termios_data = tty; - - /* Assert DTR */ - if (c->pDeviceFlow != &ns16550_flow_DTRCTS) { - ns16550_assert_DTR( minor); - } - - /* Set initial baud */ - rtems_termios_set_initial_baud( tty, (intptr_t) c->pDeviceParams); - - if (c->pDeviceFns->deviceOutputUsesInterrupts) { - ns16550_initialize_interrupts( minor); - ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); - } - - return RTEMS_SUCCESSFUL; -} - -/* - * ns16550_close - */ - -int ns16550_close( - int major, - int minor, - void * arg -) -{ - console_tbl *c = Console_Port_Tbl [minor]; - - /* - * Negate DTR - */ - if (c->pDeviceFlow != &ns16550_flow_DTRCTS) { - ns16550_negate_DTR(minor); - } - - ns16550_enable_interrupts(c, NS16550_DISABLE_ALL_INTR); - - if (c->pDeviceFns->deviceOutputUsesInterrupts) { - ns16550_cleanup_interrupts(minor); - } - - return(RTEMS_SUCCESSFUL); -} - -/** - * @brief Polled write for NS16550. - */ -void ns16550_outch_polled(console_tbl *c, char out) -{ - uintptr_t port = c->ulCtrlPort1; - getRegister_f get = c->getRegister; - setRegister_f set = c->setRegister; - uint32_t status = 0; - rtems_interrupt_lock_context lock_context; - - /* Save port interrupt mask */ - uint32_t interrupt_mask = get( port, NS16550_INTERRUPT_ENABLE); - - /* Disable port interrupts */ - ns16550_enable_interrupts( c, NS16550_DISABLE_ALL_INTR); - - while (true) { - /* Try to transmit the character in a critical section */ - rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); - - /* Read the transmitter holding register and check it */ - status = get( port, NS16550_LINE_STATUS); - if ((status & SP_LSR_THOLD) != 0) { - /* Transmit character */ - set( port, NS16550_TRANSMIT_BUFFER, out); - - /* Finished */ - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - break; - } else { - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - } - - /* Wait for transmitter holding register to be empty */ - do { - status = get( port, NS16550_LINE_STATUS); - } while ((status & SP_LSR_THOLD) == 0); - } - - /* Restore port interrupt mask */ - set( port, NS16550_INTERRUPT_ENABLE, interrupt_mask); -} - -void ns16550_write_polled(int minor, char out) -{ - console_tbl *c = Console_Port_Tbl [minor]; - - ns16550_outch_polled( c, out ); -} - -/* - * These routines provide control of the RTS and DTR lines - */ - -/* - * ns16550_assert_RTS - */ - -NS16550_STATIC int ns16550_assert_RTS(int minor) -{ - uint32_t pNS16550; - rtems_interrupt_lock_context lock_context; - NS16550Context *pns16550Context; - setRegister_f setReg; - - pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext; - - pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Assert RTS - */ - rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); - pns16550Context->ucModemCtrl|=SP_MODEM_RTS; - (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl); - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - return 0; -} - -/* - * ns16550_negate_RTS - */ - -NS16550_STATIC int ns16550_negate_RTS(int minor) -{ - uint32_t pNS16550; - rtems_interrupt_lock_context lock_context; - NS16550Context *pns16550Context; - setRegister_f setReg; - - pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext; - - pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Negate RTS - */ - rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); - pns16550Context->ucModemCtrl&=~SP_MODEM_RTS; - (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl); - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - return 0; -} - -/* - * These flow control routines utilise a connection from the local DTR - * line to the remote CTS line - */ - -/* - * ns16550_assert_DTR - */ - -NS16550_STATIC int ns16550_assert_DTR(int minor) -{ - uint32_t pNS16550; - rtems_interrupt_lock_context lock_context; - NS16550Context *pns16550Context; - setRegister_f setReg; - - pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext; - - pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Assert DTR - */ - rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); - pns16550Context->ucModemCtrl|=SP_MODEM_DTR; - (*setReg)(pNS16550, NS16550_MODEM_CONTROL, pns16550Context->ucModemCtrl); - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - return 0; -} - -/* - * ns16550_negate_DTR - */ - -NS16550_STATIC int ns16550_negate_DTR(int minor) -{ - uint32_t pNS16550; - rtems_interrupt_lock_context lock_context; - NS16550Context *pns16550Context; - setRegister_f setReg; - - pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext; - - pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1; - setReg = Console_Port_Tbl[minor]->setRegister; - - /* - * Negate DTR - */ - rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); - pns16550Context->ucModemCtrl&=~SP_MODEM_DTR; - (*setReg)(pNS16550, NS16550_MODEM_CONTROL,pns16550Context->ucModemCtrl); - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - return 0; -} - -/* - * ns16550_set_attributes - * - * This function sets the channel to reflect the requested termios - * port settings. - */ - -int ns16550_set_attributes( - int minor, - const struct termios *t -) -{ - uint32_t pNS16550; - uint32_t ulBaudDivisor; - uint8_t ucLineControl; - uint32_t baud_requested; - setRegister_f setReg; - rtems_interrupt_lock_context lock_context; - const console_tbl *c = Console_Port_Tbl [minor]; - - pNS16550 = c->ulCtrlPort1; - setReg = c->setRegister; - - /* - * Calculate the baud rate divisor - * - * Assert ensures there is no division by 0. - */ - - baud_requested = rtems_termios_baud_to_number(t->c_ospeed); - _Assert( baud_requested != 0 ); - ulBaudDivisor = NS16550_GetBaudDivisor(c, baud_requested); - - ucLineControl = 0; - - /* - * Parity - */ - - if (t->c_cflag & PARENB) { - ucLineControl |= SP_LINE_PAR; - if (!(t->c_cflag & PARODD)) - ucLineControl |= SP_LINE_ODD; - } - - /* - * Character Size - */ - - if (t->c_cflag & CSIZE) { - switch (t->c_cflag & CSIZE) { - case CS5: ucLineControl |= FIVE_BITS; break; - case CS6: ucLineControl |= SIX_BITS; break; - case CS7: ucLineControl |= SEVEN_BITS; break; - case CS8: ucLineControl |= EIGHT_BITS; break; - } - } else { - ucLineControl |= EIGHT_BITS; /* default to 9600,8,N,1 */ - } - - /* - * Stop Bits - */ - - if (t->c_cflag & CSTOPB) { - ucLineControl |= SP_LINE_STOP; /* 2 stop bits */ - } else { - ; /* 1 stop bit */ - } - - /* - * Now actually set the chip - */ - - rtems_interrupt_lock_acquire(&ns16550_lock, &lock_context); - - /* - * Set the baud rate - * - * NOTE: When the Divisor Latch Access Bit (DLAB) is set to 1, - * the transmit buffer and interrupt enable registers - * turn into the LSB and MSB divisor latch registers. - */ - - (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB); - (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff); - (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff); - - /* - * Now write the line control - */ - (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl ); - - rtems_interrupt_lock_release(&ns16550_lock, &lock_context); - - return 0; -} - -#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY) - -/** - * @brief Process interrupt. - */ -NS16550_STATIC void ns16550_process( int minor) -{ - console_tbl *c = Console_Port_Tbl [minor]; - console_data *d = &Console_Port_Data [minor]; - NS16550Context *ctx = d->pDeviceContext; - uint32_t port = c->ulCtrlPort1; - getRegister_f get = c->getRegister; - int i; - char buf [SP_FIFO_SIZE]; - - /* Iterate until no more interrupts are pending */ - do { - /* Fetch received characters */ - i = 0; - while ((get(port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) { - buf[i++] = (char) get(port, NS16550_RECEIVE_BUFFER); - if (i == SP_FIFO_SIZE) { - /* Enqueue fetched characters */ - rtems_termios_enqueue_raw_characters( d->termios_data, buf, i); - i = 0; - } - } - - if (i > 0) - rtems_termios_enqueue_raw_characters( d->termios_data, buf, i); - - /* Check if we can dequeue transmitted characters */ - if (ctx->transmitFifoChars > 0 - && (get( port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) { - /* Dequeue transmitted characters */ - rtems_termios_dequeue_characters( - d->termios_data, - ctx->transmitFifoChars - ); - } - } 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. - */ -ssize_t ns16550_write_support_int( - int minor, - const char *buf, - size_t len -) -{ - console_tbl *c = Console_Port_Tbl [minor]; - console_data *d = &Console_Port_Data [minor]; - NS16550Context *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]); - } - - ctx->transmitFifoChars = out; - - if (out > 0) { - ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR); - } else { - ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR_EXCEPT_TX); - } - - return 0; -} - -/* - * ns16550_enable_interrupts - * - * This routine initializes the port to have the specified interrupts masked. - */ -NS16550_STATIC void ns16550_enable_interrupts( - console_tbl *c, - int mask -) -{ - uint32_t pNS16550; - setRegister_f setReg; - - pNS16550 = c->ulCtrlPort1; - setReg = c->setRegister; - - (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, mask); -} - -#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY) - void ns16550_isr(void *arg) - { - int minor = (intptr_t) arg; - - ns16550_process( minor); - } -#endif - -/* - * ns16550_initialize_interrupts - * - * This routine initializes the port to operate in interrupt driver mode. - */ -NS16550_STATIC void ns16550_initialize_interrupts( int minor) -{ -#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY) - console_tbl *c = Console_Port_Tbl [minor]; -#endif - - #ifdef BSP_FEATURE_IRQ_EXTENSION - { - rtems_status_code sc = RTEMS_SUCCESSFUL; - sc = rtems_interrupt_handler_install( - c->ulIntVector, - "NS16550", - RTEMS_INTERRUPT_SHARED, - ns16550_isr, - (void *) (intptr_t) minor - ); - if (sc != RTEMS_SUCCESSFUL) { - /* FIXME */ - printk( "%s: Error: Install interrupt handler\n", __func__); - rtems_fatal_error_occurred( 0xdeadbeef); - } - } - #elif defined(BSP_FEATURE_IRQ_LEGACY) - { - int rv = 0; - #ifdef BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT - rtems_irq_connect_data cd = { - c->ulIntVector, - ns16550_isr, - (void *) minor, - NULL, - NULL, - NULL, - NULL - }; - rv = BSP_install_rtems_shared_irq_handler( &cd); - #else - rtems_irq_connect_data cd = { - c->ulIntVector, - ns16550_isr, - (void *) minor, - NULL, - NULL, - NULL - }; - rv = BSP_install_rtems_irq_handler( &cd); - #endif - if (rv == 0) { - /* FIXME */ - printk( "%s: Error: Install interrupt handler\n", __func__); - rtems_fatal_error_occurred( 0xdeadbeef); - } - } - #endif -} - -NS16550_STATIC void ns16550_cleanup_interrupts(int minor) -{ - #if defined(BSP_FEATURE_IRQ_EXTENSION) - rtems_status_code sc = RTEMS_SUCCESSFUL; - console_tbl *c = Console_Port_Tbl [minor]; - sc = rtems_interrupt_handler_remove( - c->ulIntVector, - ns16550_isr, - (void *) (intptr_t) minor - ); - if (sc != RTEMS_SUCCESSFUL) { - /* FIXME */ - printk("%s: Error: Remove interrupt handler\n", __func__); - rtems_fatal_error_occurred(0xdeadbeef); - } - #elif defined(BSP_FEATURE_IRQ_LEGACY) - int rv = 0; - console_tbl *c = Console_Port_Tbl [minor]; - rtems_irq_connect_data cd = { - .name = c->ulIntVector, - .hdl = ns16550_isr, - .handle = (void *) minor - }; - rv = BSP_remove_rtems_irq_handler(&cd); - if (rv == 0) { - /* FIXME */ - printk("%s: Error: Remove interrupt handler\n", __func__); - rtems_fatal_error_occurred(0xdeadbeef); - } - #endif -} - -/* - * ns16550_write_support_polled - * - * Console Termios output entry point. - * - */ - -ssize_t ns16550_write_support_polled( - int minor, - const char *buf, - size_t len -) -{ - int nwrite = 0; - - /* - * poll each byte in the string out of the port. - */ - while (nwrite < len) { - /* - * transmit character - */ - ns16550_write_polled(minor, *buf++); - nwrite++; - } - - /* - * return the number of bytes written. - */ - return nwrite; -} - -/* - * Debug gets() support - */ -int ns16550_inch_polled( - console_tbl *c -) -{ - uint32_t pNS16550; - unsigned char ucLineStatus; - uint8_t cChar; - getRegister_f getReg; - - pNS16550 = c->ulCtrlPort1; - getReg = c->getRegister; - - ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS); - if (ucLineStatus & SP_LSR_RDY) { - cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER); - return (int)cChar; - } - return -1; -} - -/* - * ns16550_inbyte_nonblocking_polled - * - * Console Termios polling input entry point. - */ -int ns16550_inbyte_nonblocking_polled(int minor) -{ - console_tbl *c = Console_Port_Tbl [minor]; - - return ns16550_inch_polled( c ); -} |