summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/mvme2307/console/console.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1999-10-04 20:41:28 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1999-10-04 20:41:28 +0000
commit19ca7978a660fd325d9a6b25f3dd964f81fe8b19 (patch)
treea06262aa2dafe8d981dcb9d7287bd1643526664f /c/src/lib/libbsp/powerpc/mvme2307/console/console.c
parentThe fiels isatty.c and creat.c were copied from newlib/libc/posix to (diff)
downloadrtems-19ca7978a660fd325d9a6b25f3dd964f81fe8b19.tar.bz2
Motorola MVME2307 BSP submitted by Jay Kulpinski <jskulpin@eng01.gdds.com>.
No modifications made.
Diffstat (limited to 'c/src/lib/libbsp/powerpc/mvme2307/console/console.c')
-rw-r--r--c/src/lib/libbsp/powerpc/mvme2307/console/console.c442
1 files changed, 442 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/mvme2307/console/console.c b/c/src/lib/libbsp/powerpc/mvme2307/console/console.c
new file mode 100644
index 0000000000..4d15691cb5
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mvme2307/console/console.c
@@ -0,0 +1,442 @@
+/*
+ * This file contains the hardware specific portions of the TTY driver
+ * for the serial port on the MVME230x.
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * 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 <termios.h>
+#include <bsp.h>
+#include <rtems/libio.h>
+#include <stdlib.h>
+
+/* PC16550D register definitions */
+#define UART_BASE_ADDR ((char *) IO_TO_LOCAL(0x03f8))
+
+#define RBR 0
+#define THR 0
+#define DLL 0
+#define DLM 1
+
+#define LCR 3
+# define FIVE_BITS 0x2
+# define SIX_BITS 0x2
+# define SEVEN_BITS 0x2
+# define EIGHT_BITS 0x3
+# define ONE_STOP_BIT 0x0
+# define TWO_STOP_BITS 0x4
+# define NO_PARITY 0x00
+# define ODD_PARITY 0x08
+# define EVEN_PARITY 0x18
+# define DLAB 0x80
+
+#define LSR 5
+# define DR 0x01
+# define OE 0x02
+# define PE 0x04
+# define FE 0x08
+# define BI 0x10
+# define THRE 0x20
+# define TEMT 0x40
+# define ERR_IN_FIFO 0x40
+
+#define FCR 2
+# define ENABLE_FIFOS 0x01
+# define RESET_RC_FIFO 0x02
+# define RESET_TX_FIFO 0x04
+# define FIFO_MODE_1 0x08
+# define RX_TRIGGER_1 0x00
+# define RX_TRIGGER_4 0x40
+# define RX_TRIGGER_8 0x80
+# define RX_TRIGGER_14 0xC0
+
+#define IIR 2
+# define NO_INTS_PENDING 0x01
+# define RX_ERROR 0x06
+# define RX_DATA_READY 0x04
+# define TX_NOT_FULL 0x02
+# define MODEM_STATUS 0x00
+# define INT_ID_MASK 0x06
+
+#define IER 1
+# define ENA_RX_READY_INT 0x1
+# define ENA_TX_EMPTY_INT 0x2
+# define ENA_RX_ERROR_INT 0x4
+# define ENA_MODEM_STATUS_INT 0x8
+
+#define MSR 6
+# define DELTA_CTS 0x01
+# define DELTA_DSR 0x02
+# define END_OF_RING 0x04
+# define DELTA_DCD 0x08
+# define CTS 0x10
+# define DSR 0x20
+# define RING 0x40
+# define DCD 0x80
+
+#define MCR 4
+# define DTR 0x01
+# define RTS 0x02
+# define OUT1 0x04
+# define OUT2 0x08
+# define LOOPBACK 0x10
+
+#define SCR 7
+
+int use_polled_io = CONSOLE_USE_POLLED;
+void *tty_ptr_for_irq;
+
+/*
+ * Hardware-dependent portion of tcsetattr().
+ */
+static int
+setAttributes (int minor, const struct termios *t)
+{
+ int divisor;
+ volatile char *uart = UART_BASE_ADDR;
+ char lcr_image = 0;
+
+ /* set character size */
+ switch (t->c_cflag & CSIZE) {
+ case CS5: lcr_image = FIVE_BITS; break;
+ case CS6: lcr_image = SIX_BITS; break;
+ case CS7: lcr_image = SEVEN_BITS; break;
+ case CS8: lcr_image = EIGHT_BITS; break;
+ }
+
+ /* set number of stop bits */
+ if (t->c_cflag & CSTOPB) {
+ lcr_image |= TWO_STOP_BITS;
+ } else {
+ lcr_image |= ONE_STOP_BIT;
+ }
+
+ /* set parity */
+ if ((t->c_cflag & PARENB) == 0) {
+ lcr_image |= NO_PARITY;
+ } else if (t->c_cflag & PARODD) {
+ lcr_image |= ODD_PARITY;
+ } else {
+ lcr_image |= EVEN_PARITY;
+ }
+
+ /* set the baud rate */
+ switch (t->c_cflag & CBAUD) {
+ default: divisor = -1; break;
+ case B50: divisor = 2304; break;
+ case B75: divisor = 1536; break;
+ case B110: divisor = 1047; break;
+ case B134: divisor = 857; break;
+ case B150: divisor = 768; break;
+ case B200: divisor = 576; break;
+ case B300: divisor = 384; break;
+ case B600: divisor = 192; break;
+ case B1200: divisor = 96; break;
+ case B1800: divisor = 64; break;
+ case B2400: divisor = 48; break;
+ case B4800: divisor = 24; break;
+ case B9600: divisor = 12; break;
+ case B19200: divisor = 6; break;
+ case B38400: divisor = 3; break;
+ case B57600: divisor = 2; break;
+ case B115200: divisor = -1; break;
+ case B230400: divisor = -1; break;
+ case B460800: divisor = -1; break;
+ }
+ if (divisor > 0) {
+ uart[LCR] = (lcr_image |= DLAB);
+ uart[DLM] = divisor >> 8;
+ uart[DLL] = divisor;
+ lcr_image &= ~DLAB;
+ }
+
+ /* activate the new configuration */
+ uart[LCR] = lcr_image;
+ return 0;
+}
+
+/*
+ * Interrupt handler
+ */
+static rtems_isr consoleInterruptHandler (rtems_vector_number v)
+{
+ volatile char *uart = UART_BASE_ADDR;
+ volatile char ignore;
+ char buffer[16], iir_image;
+ int len;
+
+ while (((iir_image = uart[IIR]) & NO_INTS_PENDING) == 0) {
+ switch (iir_image & INT_ID_MASK) {
+ case RX_ERROR:
+ /*
+ * read the line status register to clear condition.
+ * nothing done with the information at this point.
+ */
+ ignore = uart[LSR];
+ break;
+ case RX_DATA_READY:
+ /*
+ * empty the receive fifo and transfer bytes to termios layer
+ */
+ len = 0;
+ do {
+ buffer[len++] = uart[RBR];
+ } while (len < sizeof(buffer) && (uart[LSR] & DR));
+ rtems_termios_enqueue_raw_characters(tty_ptr_for_irq,
+ buffer, len);
+ break;
+ case TX_NOT_FULL:
+ /*
+ * notify termios layer that characters have been sent
+ */
+ len = uart[SCR];
+ /* we'll get one interrupt when we start - ignore it */
+ if (len) {
+ rtems_termios_dequeue_characters(tty_ptr_for_irq, len);
+ }
+ break;
+ case MODEM_STATUS:
+ /*
+ * read the modem status register to clear condition.
+ * nothing done with the information at this point.
+ */
+ ignore = uart[MSR];
+ break;
+ }
+ }
+}
+
+/*
+ * console_inbyte_nonblocking
+ *
+ * This routine polls for a character.
+ */
+
+int console_inbyte_nonblocking(
+ int port
+)
+{
+ volatile char *uart = UART_BASE_ADDR;
+
+ if (uart[LSR] & DR) {
+ return uart[RBR];
+ } else {
+ return -1;
+ }
+}
+
+
+/*
+ * Console Termios Support Entry Points
+ *
+ */
+
+int console_write_polled (
+ int minor,
+ const char *buf,
+ int len
+)
+{
+ int nwrite = 0;
+ volatile char *uart = UART_BASE_ADDR;
+
+ while (nwrite < len) {
+ /* wait as long as needed for transmit buffer to empty */
+ while ((uart[LSR] & THRE) == 0) ;
+ uart[THR] = *buf++;
+ nwrite++;
+ }
+
+ /* return value seems to be ignored by termios layer, we'll return count */
+ return nwrite;
+}
+
+int console_write_interrupts (
+ int minor,
+ const char *buf,
+ int len
+)
+{
+ const int FIFO_depth = 16;
+ int nwrite;
+ volatile char *uart = UART_BASE_ADDR;
+
+ /* write up to len characters, stopping if FIFO fills */
+ for (nwrite = 0; nwrite < len && nwrite < FIFO_depth; nwrite++) {
+ uart[THR] = *buf++;
+ }
+
+ /* save count of bytes sent so interrupt can report it to termios layer */
+ uart[SCR] = nwrite;
+
+ /* return value seems to be ignored by termios layer, we'll return count */
+ return nwrite;
+}
+
+/*
+ * Console Device Driver Entry Points
+ *
+ */
+
+/*
+ * Initialize and register the device
+ */
+rtems_device_driver console_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_status_code status;
+ volatile char *uart = UART_BASE_ADDR;
+
+ rtems_termios_initialize();
+
+ /*
+ * Register Device Names
+ */
+
+ status = rtems_io_register_name( "/dev/console", major, 0 );
+ if (status != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred(status);
+ }
+ /* default mode: 9600 bps, 8 bits, 1 stop, no parity */
+# define DEFAULT_MODE (EIGHT_BITS | ONE_STOP_BIT | NO_PARITY)
+ uart[LCR] = DEFAULT_MODE | DLAB;
+ uart[DLM] = 0;
+ uart[DLL] = 12;
+ uart[LCR] = DEFAULT_MODE;
+
+ /* enable the receive and transmit FIFOs */
+ uart[FCR] = ENABLE_FIFOS | RESET_RC_FIFO | RESET_TX_FIFO | RX_TRIGGER_1;
+
+ /* set modem control lines */
+ uart[MCR] = DTR | RTS;
+
+ /* zero the scratch register - this will hold a count of tx characters */
+ uart[SCR] = 0;
+
+ /* initialize interrupts */
+ if (!use_polled_io) {
+ rtems_isr_entry old_handler;
+ rtems_status_code sc;
+
+ sc = bsp_interrupt_catch(consoleInterruptHandler, IRQ_UART,
+ &old_handler);
+ sc = bsp_interrupt_enable(IRQ_UART, PRIORITY_ISA_INT);
+ uart[IER] = ENA_RX_READY_INT | ENA_TX_EMPTY_INT;
+ } else {
+ uart[IER] = 0;
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Open the device
+ */
+rtems_device_driver console_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ rtems_status_code sc;
+ static const rtems_termios_callbacks pollCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ console_inbyte_nonblocking, /* pollRead */
+ console_write_polled, /* write */
+ setAttributes, /* setAttributes */
+ NULL, /* stopRemoteTx */
+ NULL, /* startRemoteTx */
+ 0 /* outputUsesInterrupts */
+ };
+ static const rtems_termios_callbacks intrCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ NULL, /* pollRead */
+ console_write_interrupts, /* write */
+ setAttributes, /* setAttributes */
+ NULL, /* stopRemoteTx */
+ NULL, /* startRemoteTx */
+ 1 /* outputUsesInterrupts */
+ };
+
+
+ if ( minor > 1 )
+ return RTEMS_INVALID_NUMBER;
+
+ if (use_polled_io) {
+ sc = rtems_termios_open (major, minor, arg, &pollCallbacks );
+ } else {
+ sc = rtems_termios_open (major, minor, arg, &intrCallbacks );
+ tty_ptr_for_irq = ((rtems_libio_open_close_args_t *)arg)->iop->data1;
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Close the device
+ */
+rtems_device_driver console_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_close (arg);
+}
+
+/*
+ * Read from the device
+ */
+rtems_device_driver console_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_read (arg);
+}
+
+/*
+ * Write to the device
+ */
+rtems_device_driver console_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_write (arg);
+}
+
+/*
+ * Handle ioctl request.
+ */
+rtems_device_driver console_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_ioctl (arg);
+}
+
+/*
+ * Reserve resources consumed by this driver
+ */
+void console_reserve_resources(
+ rtems_configuration_table *configuration
+)
+{
+ rtems_termios_reserve_resources( configuration, 1 );
+}