diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-19 06:28:01 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-20 13:08:32 +0200 |
commit | d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc (patch) | |
tree | caa54b4229e86a68c84ab5961af34e087dce5302 /bsps/powerpc/shared | |
parent | bsps/powerpc: Move shared btimer support (diff) | |
download | rtems-d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc.tar.bz2 |
bsps: Move console drivers to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'bsps/powerpc/shared')
-rw-r--r-- | bsps/powerpc/shared/console/console.c | 314 | ||||
-rw-r--r-- | bsps/powerpc/shared/console/uart.c | 781 |
2 files changed, 1095 insertions, 0 deletions
diff --git a/bsps/powerpc/shared/console/console.c b/bsps/powerpc/shared/console/console.c new file mode 100644 index 0000000000..f275683cc2 --- /dev/null +++ b/bsps/powerpc/shared/console/console.c @@ -0,0 +1,314 @@ +/* + * console.c -- console I/O package + * + * Copyright (C) 1999 Eric Valette. valette@crf.canon.fr + * + * This code is based on the pc386 BSP console.c so the following + * copyright also applies : + * + * (C) Copyright 1997 - + * - NavIST Group - Real-Time Distributed Systems and Industrial Automation + * + * Till Straumann, <strauman@slac.stanford.edu>, 12/20/2001 + * separate BSP specific stuff from generics... + * + * http://pandora.ist.utl.pt + * + * Instituto Superior Tecnico * Lisboa * PORTUGAL + * 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 <assert.h> +#include <inttypes.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <rtems/bspIo.h> +#include <rtems/libio.h> +#include <rtems/console.h> +#include <rtems/termiostypes.h> +#include <termios.h> +#include <bsp/uart.h> +#include <rtems/bspIo.h> /* printk */ + +/* Definitions for BSPConsolePort */ +/* + * Possible value for console input/output : + * BSP_CONSOLE_PORT_CONSOLE + * BSP_UART_COM1 + * BSP_UART_COM2 + */ +int BSPConsolePort = BSP_CONSOLE_PORT; + +int BSPBaseBaud = BSP_UART_BAUD_BASE; + +/* + * TERMIOS_OUTPUT_MODE should be a 'bspopts.h/configure'-able option; + * we could even make it a link-time option (but that would require + * small changes)... + */ +#if defined(USE_POLLED_IO) + #define TERMIOS_OUTPUT_MODE TERMIOS_POLLED +#elif defined(USE_TASK_DRIVEN_IO) + #define TERMIOS_OUTPUT_MODE TERMIOS_TASK_DRIVEN +#else + #define TERMIOS_OUTPUT_MODE TERMIOS_IRQ_DRIVEN +#endif + +/*-------------------------------------------------------------------------+ +| External Prototypes ++--------------------------------------------------------------------------*/ + +static int conSetAttr(int minor, const struct termios *); + +typedef struct TtySTblRec_ { + char *name; + rtems_irq_hdl isr; +} TtySTblRec, *TtySTbl; + +static TtySTblRec ttyS[]={ + { "/dev/ttyS0", +#ifdef BSP_UART_IOBASE_COM1 + BSP_uart_termios_isr_com1 +#else + 0 +#endif + }, + { "/dev/ttyS1", +#ifdef BSP_UART_IOBASE_COM2 + BSP_uart_termios_isr_com2 +#else + 0 +#endif + }, +}; + +/*-------------------------------------------------------------------------+ +| Console device driver INITIALIZE entry point. ++--------------------------------------------------------------------------+ +| Initilizes the I/O console (keyboard + VGA display) driver. ++--------------------------------------------------------------------------*/ +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code status; + + /* + * The video was initialized in the start.s code and does not need + * to be reinitialized. + */ + + /* + * Set up TERMIOS + */ + rtems_termios_initialize(); + + /* + * Do device-specific initialization + */ + + /* RTEMS calls this routine once with 'minor'==0; loop through + * all known instances... + */ + + for (minor=0; minor < sizeof(ttyS)/sizeof(ttyS[0]); minor++) { + char *nm; + /* + * Skip ports (possibly not supported by BSP...) we have no ISR for + */ + if ( ! ttyS[minor].isr ) + continue; + /* + * Register the device + */ + status = rtems_io_register_name ((nm=ttyS[minor].name), major, minor); + if ( RTEMS_SUCCESSFUL==status && BSPConsolePort == minor) { + printk("Registering /dev/console as minor %" PRIu32 " (==%s)\n", + minor, + ttyS[minor].name); + /* also register an alias */ + status = rtems_io_register_name ( (nm="/dev/console"), major, minor); + } + + if (status != RTEMS_SUCCESSFUL) { + printk("Error registering %s!\n",nm); + rtems_fatal_error_occurred (status); + } + } + + return RTEMS_SUCCESSFUL; +} /* console_initialize */ + +#if !defined(USE_POLLED_IO) +static int console_first_open(int major, int minor, void *arg) +{ + rtems_status_code status; + + /* must not open a minor device we have no ISR for */ + assert( minor>=0 && minor < sizeof(ttyS)/sizeof(ttyS[0]) && ttyS[minor].isr ); + + /* 9600-8-N-1 */ + BSP_uart_init(minor, 9600, 0); + status = BSP_uart_install_isr(minor, ttyS[minor].isr); + if (!status) { + printk("Error installing serial console interrupt handler for '%s'!\n", + ttyS[minor].name); + rtems_fatal_error_occurred(status); + } + + /* + * Pass data area info down to driver + */ + BSP_uart_termios_set(minor, ((rtems_libio_open_close_args_t *)arg)->iop->data1); + + /* Enable interrupts on channel */ + BSP_uart_intr_ctrl(minor, BSP_UART_INTR_CTRL_TERMIOS); + + return 0; +} +#endif + +#if !defined(USE_POLLED_IO) +static int console_last_close(int major, int minor, void *arg) +{ + BSP_uart_remove_isr(minor, ttyS[minor].isr); + return 0; +} +#endif + +/*-------------------------------------------------------------------------+ +| Console device driver OPEN entry point ++--------------------------------------------------------------------------*/ +rtems_device_driver console_open( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code status; + static rtems_termios_callbacks cb = +#if defined(USE_POLLED_IO) + { + NULL, /* firstOpen */ + NULL, /* lastClose */ + NULL, /* pollRead */ + BSP_uart_termios_write_polled, /* write */ + conSetAttr, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + TERMIOS_POLLED /* outputUsesInterrupts */ + }; +#else + { + console_first_open, /* firstOpen */ + console_last_close, /* lastClose */ +#ifdef USE_TASK_DRIVEN_IO + BSP_uart_termios_read_com, /* pollRead */ +#else + NULL, /* pollRead */ +#endif + BSP_uart_termios_write_com, /* write */ + conSetAttr, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + TERMIOS_OUTPUT_MODE /* outputUsesInterrupts */ + }; +#endif + + status = rtems_termios_open (major, minor, arg, &cb); + + if (status != RTEMS_SUCCESSFUL) { + printk("Error opening console device\n"); + return status; + } + + return RTEMS_SUCCESSFUL; +} + +/*-------------------------------------------------------------------------+ +| Console device driver CLOSE entry point ++--------------------------------------------------------------------------*/ +rtems_device_driver +console_close( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_device_driver res = RTEMS_SUCCESSFUL; + + res = rtems_termios_close (arg); + + return res; +} /* console_close */ + +/*-------------------------------------------------------------------------+ +| Console device driver READ entry point. ++--------------------------------------------------------------------------+ +| Read characters from the I/O console. We only have stdin. ++--------------------------------------------------------------------------*/ +rtems_device_driver console_read( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + return rtems_termios_read (arg); +} /* console_read */ + +/*-------------------------------------------------------------------------+ +| Console device driver WRITE entry point. ++--------------------------------------------------------------------------+ +| Write characters to the I/O console. Stderr and stdout are the same. ++--------------------------------------------------------------------------*/ +rtems_device_driver console_write( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + return rtems_termios_write (arg); +} /* console_write */ + +/* + * Handle ioctl request. + */ +rtems_device_driver console_control( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ +/* does the BSP support break callbacks ? */ +#if defined(BIOCSETBREAKCB) && defined(BIOCGETBREAKCB) + rtems_libio_ioctl_args_t *ioa=arg; + switch (ioa->command) { + case BIOCSETBREAKCB: return BSP_uart_set_break_cb(minor, ioa); + case BIOCGETBREAKCB: return BSP_uart_get_break_cb(minor, ioa); + default: break; + } +#endif + return rtems_termios_ioctl (arg); +} + +static int conSetAttr( + int minor, + const struct termios *t +) +{ + rtems_termios_baud_t baud; + + baud = rtems_termios_baud_to_number(t->c_ospeed); + if ( baud > 115200 ) + rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR); + + BSP_uart_set_baud(minor, baud); + + return 0; +} diff --git a/bsps/powerpc/shared/console/uart.c b/bsps/powerpc/shared/console/uart.c new file mode 100644 index 0000000000..62212b98db --- /dev/null +++ b/bsps/powerpc/shared/console/uart.c @@ -0,0 +1,781 @@ +/* + * This software is Copyright (C) 1998 by T.sqware - all rights limited + * It is provided in to the public domain "as is", can be freely modified + * as far as this copyight notice is kept unchanged, but does not imply + * an endorsement by T.sqware of the product in which it is included. + */ + +#include <stdint.h> +#include <stdio.h> +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/uart.h> +#include <rtems/libio.h> +#include <rtems/bspIo.h> +#include <rtems/termiostypes.h> +#include <termios.h> +#include <assert.h> + +/* + * Basic 16552 driver + */ + +struct uart_data +{ + unsigned long ioBase; + int irq; + int hwFlow; + int baud; + BSP_UartBreakCbRec breakCallback; + int ioMode; +}; + +/* + * Initialization of BSP specific data. + * The constants are pulled in from a BSP + * specific file, whereas all of the code + * in this file is generic and makes no + * assumptions about addresses, irq vectors + * etc... + */ + +#define UART_UNSUPP ((unsigned long)(-1)) + +static struct uart_data uart_data[2] = { + { +#ifdef BSP_UART_IOBASE_COM1 + BSP_UART_IOBASE_COM1, + BSP_UART_COM1_IRQ, +#else + UART_UNSUPP, + -1, +#endif + }, + { +#ifdef BSP_UART_IOBASE_COM2 + BSP_UART_IOBASE_COM2, + BSP_UART_COM2_IRQ, +#else + UART_UNSUPP, + -1, +#endif + }, +}; + +#define MAX_UARTS (sizeof(uart_data)/sizeof(uart_data[0])) +#define SANITY_CHECK(uart) \ + assert( MAX_UARTS > (unsigned)(uart) && uart_data[(uart)].ioBase != UART_UNSUPP ) +/* + * Macros to read/write register of uart, if configuration is + * different just rewrite these macros + */ + +static inline unsigned char +uread(int uart, unsigned int reg) +{ + return in_8((uint8_t*)(uart_data[uart].ioBase + reg)); +} + +static inline void +uwrite(int uart, int reg, unsigned int val) +{ + out_8((uint8_t*)(uart_data[uart].ioBase + reg), val); +} + + +static void +uartError(int uart, void *termiosPrivate) +{ + unsigned char uartStatus, dummy; + BSP_UartBreakCbProc h; + + uartStatus = uread(uart, LSR); + dummy = uread(uart, RBR); + +#ifdef UARTDEBUG + if (uartStatus & OE) + printk("********* Over run Error **********\n"); + if (uartStatus & PE) + printk("********* Parity Error **********\n"); + if (uartStatus & FE) + printk("********* Framing Error **********\n"); + if (uartStatus & BI) { + printk("********* BREAK INTERRUPT *********\n"); +#endif + if ((h=uart_data[uart].breakCallback.handler)) { + h(uart, + (dummy<<8)|uartStatus, + termiosPrivate, + uart_data[uart].breakCallback.private); + } +#ifdef UARTDEBUG + if (uartStatus & ERFIFO) + printk("********* Error receive Fifo **********\n"); +#endif +} + +/* + * Uart initialization, it is hardcoded to 8 bit, no parity, + * one stop bit, FIFO, things to be changed + * are baud rate and nad hw flow control, + * and longest rx fifo setting + */ +void +BSP_uart_init(int uart, int baud, int hwFlow) +{ + unsigned char tmp; + + /* Sanity check */ + SANITY_CHECK(uart); + + /* Make sure any printk activity drains before + * re-initializing. + */ + while ( ! (uread(uart, LSR) & TEMT) ) + ; + + switch(baud) + { + case 50: + case 75: + case 110: + case 134: + case 300: + case 600: + case 1200: + case 2400: + case 9600: + case 19200: + case 38400: + case 57600: + case 115200: + break; + default: + assert(0); + return; + } + + /* Set DLAB bit to 1 */ + uwrite(uart, LCR, DLAB); + + if ( (int)BSPBaseBaud <= 0 ) { + /* Use current divisor assuming BSPBaseBaud gives us the current speed */ + BSPBaseBaud = BSPBaseBaud ? -BSPBaseBaud : 9600; + BSPBaseBaud *= ((uread(uart, DLM) << 8) | uread(uart, DLL)); + } + + /* Set baud rate */ + uwrite(uart, DLL, (BSPBaseBaud/baud) & 0xff); + uwrite(uart, DLM, ((BSPBaseBaud/baud) >> 8) & 0xff); + + /* 8-bit, no parity , 1 stop */ + uwrite(uart, LCR, CHR_8_BITS); + + /* Set DTR, RTS and OUT2 high */ + uwrite(uart, MCR, DTR | RTS | OUT_2); + + /* Enable FIFO */ + uwrite(uart, FCR, FIFO_EN | XMIT_RESET | RCV_RESET | RECEIVE_FIFO_TRIGGER12); + + /* Disable Interrupts */ + uwrite(uart, IER, 0); + + /* Read status to clear them */ + tmp = uread(uart, LSR); + tmp = uread(uart, RBR); + tmp = uread(uart, MSR); + (void) tmp; /* avoid set but not used warning */ + + /* Remember state */ + uart_data[uart].hwFlow = hwFlow; + uart_data[uart].baud = baud; + return; +} + +/* + * Set baud + */ +void +BSP_uart_set_baud(int uart, int baud) +{ + unsigned char mcr, ier; + + /* Sanity check */ + SANITY_CHECK(uart); + + /* + * This function may be called whenever TERMIOS parameters + * are changed, so we have to make sure that baud change is + * indeed required. + */ + + if(baud == uart_data[uart].baud) + { + return; + } + + mcr = uread(uart, MCR); + ier = uread(uart, IER); + + BSP_uart_init(uart, baud, uart_data[uart].hwFlow); + + uwrite(uart, MCR, mcr); + uwrite(uart, IER, ier); + + return; +} + +/* + * Enable/disable interrupts + */ +void +BSP_uart_intr_ctrl(int uart, int cmd) +{ + + SANITY_CHECK(uart); + + switch(cmd) + { + case BSP_UART_INTR_CTRL_DISABLE: + uwrite(uart, IER, INTERRUPT_DISABLE); + break; + case BSP_UART_INTR_CTRL_ENABLE: + if(uart_data[uart].hwFlow) + { + uwrite(uart, IER, + (RECEIVE_ENABLE | + TRANSMIT_ENABLE | + RECEIVER_LINE_ST_ENABLE | + MODEM_ENABLE + ) + ); + } + else + { + uwrite(uart, IER, + (RECEIVE_ENABLE | + TRANSMIT_ENABLE | + RECEIVER_LINE_ST_ENABLE + ) + ); + } + break; + case BSP_UART_INTR_CTRL_TERMIOS: + if(uart_data[uart].hwFlow) + { + uwrite(uart, IER, + (RECEIVE_ENABLE | + RECEIVER_LINE_ST_ENABLE | + MODEM_ENABLE + ) + ); + } + else + { + uwrite(uart, IER, + (RECEIVE_ENABLE | + RECEIVER_LINE_ST_ENABLE + ) + ); + } + break; + case BSP_UART_INTR_CTRL_GDB: + uwrite(uart, IER, RECEIVE_ENABLE); + break; + default: + assert(0); + break; + } + + return; +} + +void +BSP_uart_throttle(int uart) +{ + unsigned int mcr; + + SANITY_CHECK(uart); + + if(!uart_data[uart].hwFlow) + { + /* Should not happen */ + assert(0); + return; + } + mcr = uread (uart, MCR); + /* RTS down */ + mcr &= ~RTS; + uwrite(uart, MCR, mcr); + + return; +} + +void +BSP_uart_unthrottle(int uart) +{ + unsigned int mcr; + + SANITY_CHECK(uart); + + if(!uart_data[uart].hwFlow) + { + /* Should not happen */ + assert(0); + return; + } + mcr = uread (uart, MCR); + /* RTS up */ + mcr |= RTS; + uwrite(uart, MCR, mcr); + + return; +} + +/* + * Status function, -1 if error + * detected, 0 if no received chars available, + * 1 if received char available, 2 if break + * is detected, it will eat break and error + * chars. It ignores overruns - we cannot do + * anything about - it execpt count statistics + * and we are not counting it. + */ +int +BSP_uart_polled_status(int uart) +{ + unsigned char val; + + SANITY_CHECK(uart); + + val = uread(uart, LSR); + + if(val & BI) + { + /* BREAK found, eat character */ + uread(uart, RBR); + return BSP_UART_STATUS_BREAK; + } + + if((val & (DR | OE | FE)) == 1) + { + /* No error, character present */ + return BSP_UART_STATUS_CHAR; + } + + if((val & (DR | OE | FE)) == 0) + { + /* Nothing */ + return BSP_UART_STATUS_NOCHAR; + } + + /* + * Framing or parity error + * eat character + */ + uread(uart, RBR); + + return BSP_UART_STATUS_ERROR; +} + +/* + * Polled mode write function + */ +void +BSP_uart_polled_write(int uart, int val) +{ + unsigned char val1; + + /* Sanity check */ + SANITY_CHECK(uart); + + for(;;) + { + if((val1=uread(uart, LSR)) & THRE) + { + break; + } + } + + if(uart_data[uart].hwFlow) + { + for(;;) + { + if(uread(uart, MSR) & CTS) + { + break; + } + } + } + + uwrite(uart, THR, val & 0xff); + + return; +} + +void +BSP_output_char_via_serial(const char val) +{ + BSP_uart_polled_write(BSPConsolePort, val); +} + +/* + * Polled mode read function + */ +int +BSP_uart_polled_read(int uart) +{ + unsigned char val; + + SANITY_CHECK(uart); + + for(;;) + { + if(uread(uart, LSR) & DR) + { + break; + } + } + + val = uread(uart, RBR); + + return (int)(val & 0xff); +} + +unsigned +BSP_poll_char_via_serial() +{ + return BSP_uart_polled_read(BSPConsolePort); +} + +static void +uart_noop(const rtems_irq_connect_data *unused) +{ + return; +} + +/* note that the IRQ names contain _ISA_ for legacy + * reasons. They can be any interrupt, depending + * on the particular BSP... + */ + +static int +uart_isr_is_on(const rtems_irq_connect_data *irq) +{ + int uart; + + uart = (irq->name == BSP_UART_COM1_IRQ) ? + BSP_UART_COM1 : BSP_UART_COM2; + + return uread(uart,IER); +} + +static int +doit(int uart, rtems_irq_hdl handler, int (*p)(const rtems_irq_connect_data*)) +{ + rtems_irq_connect_data d={0}; + d.name = uart_data[uart].irq; + d.off = d.on = uart_noop; + d.isOn = uart_isr_is_on; + d.hdl = handler; + return p(&d); +} + +int +BSP_uart_install_isr(int uart, rtems_irq_hdl handler) +{ +/* Using shared interrupts by default might break things.. the + * shared IRQ installer uses malloc() and if a BSP had called this + * during early init it might not work... + */ +#ifdef BSP_UART_USE_SHARED_IRQS + return doit(uart, handler, BSP_install_rtems_shared_irq_handler); +#else + return doit(uart, handler, BSP_install_rtems_irq_handler); +#endif +} + +int +BSP_uart_remove_isr(int uart, rtems_irq_hdl handler) +{ + return doit(uart, handler, BSP_remove_rtems_irq_handler); +} + +/* ================ Termios support =================*/ + +static volatile int termios_stopped_com[2] = {0,0}; +static volatile int termios_tx_active_com[2] = {0,0}; +static void* termios_ttyp_com[2] = {NULL,NULL}; +static char termios_tx_hold_com[2] = {0,0}; +static volatile char termios_tx_hold_valid_com[2] = {0,0}; + +/* + * Set channel parameters + */ +void +BSP_uart_termios_set(int uart, void *p) +{ + struct rtems_termios_tty *ttyp = p; + unsigned char val; + SANITY_CHECK(uart); + + if(uart_data[uart].hwFlow) + { + val = uread(uart, MSR); + + termios_stopped_com[uart] = (val & CTS) ? 0 : 1; + } + else + { + termios_stopped_com[uart] = 0; + } + termios_tx_active_com[uart] = 0; + termios_ttyp_com[uart] = ttyp; + termios_tx_hold_com[uart] = 0; + termios_tx_hold_valid_com[uart] = 0; + + uart_data[uart].ioMode = ttyp->device.outputUsesInterrupts; + + return; +} + +ssize_t +BSP_uart_termios_write_polled(int minor, const char *buf, size_t len) +{ + int uart=minor; /* could differ, theoretically */ + int nwrite; + const char *b = buf; + + for (nwrite=0 ; nwrite < len ; nwrite++) { + BSP_uart_polled_write(uart, *b++); + } + return nwrite; +} + +ssize_t +BSP_uart_termios_write_com(int minor, const char *buf, size_t len) +{ + int uart=minor; /* could differ, theoretically */ + + if(len <= 0) + { + return 0; + } + + /* If the TX buffer is busy - something is royally screwed up */ + /* assert((uread(BSP_UART_COM1, LSR) & THRE) != 0); */ + + if(termios_stopped_com[uart]) + { + /* CTS low */ + termios_tx_hold_com[uart] = *buf; + termios_tx_hold_valid_com[uart] = 1; + return 0; + } + + /* Write character */ + uwrite(uart, THR, *buf & 0xff); + + /* Enable interrupts if necessary */ + if(!termios_tx_active_com[uart] && uart_data[uart].hwFlow) + { + termios_tx_active_com[uart] = 1; + uwrite(uart, IER, + (RECEIVE_ENABLE | + TRANSMIT_ENABLE | + RECEIVER_LINE_ST_ENABLE | + MODEM_ENABLE + ) + ); + } + else if(!termios_tx_active_com[uart]) + { + termios_tx_active_com[uart] = 1; + uwrite(uart, IER, + (RECEIVE_ENABLE | + TRANSMIT_ENABLE | + RECEIVER_LINE_ST_ENABLE + ) + ); + } + + return 0; +} + +int +BSP_uart_termios_read_com(int uart) +{ + int off = (int)0; + char buf[40]; + rtems_interrupt_level l; + + /* read bytes */ + while (( off < sizeof(buf) ) && ( uread(uart, LSR) & DR )) { + buf[off++] = uread(uart, RBR); + } + + /* write out data */ + if ( off > 0 ) { + rtems_termios_enqueue_raw_characters(termios_ttyp_com[uart], buf, off); + } + + /* enable receive interrupts */ + rtems_interrupt_disable(l); + uwrite(uart, IER, uread(uart, IER) | (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE)); + rtems_interrupt_enable(l); + + return ( EOF ); +} + +static void +BSP_uart_termios_isr_com(int uart) +{ + unsigned char buf[40]; + unsigned char val, ier; + int off, ret, vect; + + off = 0; + + for(;;) + { + vect = uread(uart, IIR) & 0xf; + + switch(vect) + { + case MODEM_STATUS : + val = uread(uart, MSR); + if(uart_data[uart].hwFlow) + { + if(val & CTS) + { + /* CTS high */ + termios_stopped_com[uart] = 0; + if(termios_tx_hold_valid_com[uart]) + { + termios_tx_hold_valid_com[uart] = 0; + BSP_uart_termios_write_com(uart, &termios_tx_hold_com[uart], + 1); + } + } + else + { + /* CTS low */ + termios_stopped_com[uart] = 1; + } + } + break; + case NO_MORE_INTR : + /* No more interrupts */ + if(off != 0) + { + /* Update rx buffer */ + rtems_termios_enqueue_raw_characters(termios_ttyp_com[uart], + (char *)buf, + off); + } + return; + case TRANSMITTER_HODING_REGISTER_EMPTY : + /* + * TX holding empty: we have to disable these interrupts + * if there is nothing more to send. + */ + + ret = rtems_termios_dequeue_characters(termios_ttyp_com[uart], 1); + + /* If nothing else to send disable interrupts */ + if(ret == 0 && uart_data[uart].hwFlow) + { + uwrite(uart, IER, + (RECEIVE_ENABLE | + RECEIVER_LINE_ST_ENABLE | + MODEM_ENABLE + ) + ); + termios_tx_active_com[uart] = 0; + } + else if(ret == 0) + { + uwrite(uart, IER, + (RECEIVE_ENABLE | + RECEIVER_LINE_ST_ENABLE + ) + ); + termios_tx_active_com[uart] = 0; + } + break; + case RECEIVER_DATA_AVAIL : + case CHARACTER_TIMEOUT_INDICATION: + if ( uart_data[uart].ioMode == TERMIOS_TASK_DRIVEN ) + { + /* ensure interrupts are enabled */ + if ( (ier = uread(uart,IER)) & RECEIVE_ENABLE ) + { + /* disable interrupts and notify termios */ + ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE); + uwrite(uart, IER, ier); + rtems_termios_rxirq_occured(termios_ttyp_com[uart]); + } + } + else + { + /* RX data ready */ + assert(off < sizeof(buf)); + while ( off < sizeof(buf) && ( DR & uread(uart, LSR) ) ) + buf[off++] = uread(uart, RBR); + } + break; + case RECEIVER_ERROR: + /* RX error: eat character */ + uartError(uart, termios_ttyp_com[uart]); + break; + default: + /* Should not happen */ + assert(0); + return; + } + } +} + +/* + * XXX - Note that this can now be one isr with the uart + * passed as the parameter. + */ +void +BSP_uart_termios_isr_com1(void *unused) +{ + BSP_uart_termios_isr_com(BSP_UART_COM1); +} + +void +BSP_uart_termios_isr_com2(void *unused) +{ + BSP_uart_termios_isr_com(BSP_UART_COM2); +} + +/* retrieve 'break' handler info */ +int +BSP_uart_get_break_cb(int uart, rtems_libio_ioctl_args_t *arg) +{ +BSP_UartBreakCb cb=arg->buffer; +unsigned long flags; + SANITY_CHECK(uart); + rtems_interrupt_disable(flags); + *cb = uart_data[uart].breakCallback; + rtems_interrupt_enable(flags); + arg->ioctl_return=0; + return RTEMS_SUCCESSFUL; +} + +/* install 'break' handler */ +int +BSP_uart_set_break_cb(int uart, rtems_libio_ioctl_args_t *arg) +{ +BSP_UartBreakCb cb=arg->buffer; +unsigned long flags; + SANITY_CHECK(uart); + rtems_interrupt_disable(flags); + uart_data[uart].breakCallback = *cb; + rtems_interrupt_enable(flags); + arg->ioctl_return=0; + return RTEMS_SUCCESSFUL; +} |