summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/ppc403/console/console.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libcpu/powerpc/ppc403/console/console.c')
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/console/console.c602
1 files changed, 384 insertions, 218 deletions
diff --git a/c/src/lib/libcpu/powerpc/ppc403/console/console.c b/c/src/lib/libcpu/powerpc/ppc403/console/console.c
index e95642e57e..f2b53a95f3 100644
--- a/c/src/lib/libcpu/powerpc/ppc403/console/console.c
+++ b/c/src/lib/libcpu/powerpc/ppc403/console/console.c
@@ -1,6 +1,18 @@
/*
* This file contains the PowerPC 403GA console IO package.
*
+ * Author: Thomas Doerfler <td@imd.m.isar.de>
+ * IMD Ingenieurbuero fuer Microcomputertechnik
+ *
+ * COPYRIGHT (c) 1998 by IMD
+ *
+ * Changes from IMD are covered by the original distributions terms.
+ * changes include interrupt support and termios support
+ * for backward compatibility, the original polled driver has been
+ * renamed to console.c.polled
+ *
+ * This file has been initially created (polled version) by
+ *
* Author: Andrew Bray <andy@i-cubed.co.uk>
*
* COPYRIGHT (c) 1995 by i-cubed ltd.
@@ -16,32 +28,46 @@
* i-cubed limited makes no representations about the suitability
* of this software for any purpose.
*
+ * Modifications for spooling (interrupt driven) console driver
+ * by Thomas Doerfler <td@imd.m.isar.de>
+ * for these modifications:
+ * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany.
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies. IMD makes no representations about the suitability
+ * of this software for any purpose.
+ *
* Derived from c/src/lib/libbsp/no_cpu/no_bsp/console/console.c:
*
- * COPYRIGHT (c) 1989-1998.
+ * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
* On-Line Applications Research Corporation (OAR).
- * Copyright assigned to U.S. Government, 1994.
+ * All rights 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.
+ * This material may be reproduced by or for the U.S. Government pursuant
+ * to the copyright license under the clause at DFARS 252.227-7013. This
+ * notice must appear in all copies of this file and its derivatives.
*
- * $Id$
+ * console.c,v 1.4 1995/12/05 19:23:02 joel Exp
*/
#define NO_BSP_INIT
#include <bsp.h>
#include <rtems/libio.h>
-
+#include "../ictrl/ictrl.h"
+#include <stdlib.h> /* for atexit() */
extern rtems_cpu_table Cpu_table; /* owned by BSP */
struct async {
-/*-----------------------------------------------------------------------------+
+/*---------------------------------------------------------------------------+
| Line Status Register.
-+-----------------------------------------------------------------------------*/
- unsigned char SPLS;
- unsigned char SPLSset;
++---------------------------------------------------------------------------*/
+ unsigned char SPLS;
+ unsigned char SPLSset;
#define LSRDataReady 0x80
#define LSRFramingError 0x40
#define LSROverrunError 0x20
@@ -50,27 +76,27 @@ struct async {
#define LSRTxHoldEmpty 0x04
#define LSRTxShiftEmpty 0x02
-/*-----------------------------------------------------------------------------+
+/*---------------------------------------------------------------------------+
| Handshake Status Register.
-+-----------------------------------------------------------------------------*/
- unsigned char SPHS;
- unsigned char SPHSset;
++---------------------------------------------------------------------------*/
+ unsigned char SPHS;
+ unsigned char SPHSset;
#define HSRDsr 0x80
#define HSRCts 0x40
-/*-----------------------------------------------------------------------------+
+/*---------------------------------------------------------------------------+
| Baud rate divisor registers
-+-----------------------------------------------------------------------------*/
- unsigned char BRDH;
- unsigned char BRDL;
++---------------------------------------------------------------------------*/
+ unsigned char BRDH;
+ unsigned char BRDL;
-/*-----------------------------------------------------------------------------+
+/*---------------------------------------------------------------------------+
| Control Register.
-+-----------------------------------------------------------------------------*/
- unsigned char SPCTL;
-#define CRNormal 0x00
-#define CRLoopback 0x40
-#define CRAutoEcho 0x80
++---------------------------------------------------------------------------*/
+ unsigned char SPCTL;
+#define CRNormal 0x00
+#define CRLoopback 0x40
+#define CRAutoEcho 0x80
#define CRDtr 0x20
#define CRRts 0x10
#define CRWordLength7 0x00
@@ -78,212 +104,356 @@ struct async {
#define CRParityDisable 0x00
#define CRParityEnable 0x04
#define CREvenParity 0x00
-#define CROddParity 0x02
+#define CROddParity 0x02
#define CRStopBitsOne 0x00
#define CRStopBitsTwo 0x01
-#define CRDisableDtrRts 0x00
+#define CRDisableDtrRts 0x00
-/*-----------------------------------------------------------------------------+
+/*--------------------------------------------------------------------------+
| Receiver Command Register.
-+-----------------------------------------------------------------------------*/
- unsigned char SPRC;
-#define RCRDisable 0x00
-#define RCREnable 0x80
-#define RCRIntDisable 0x00
-#define RCRIntEnabled 0x20
-#define RCRDMACh2 0x40
-#define RCRDMACh3 0x60
-#define RCRErrorInt 0x10
-#define RCRPauseEnable 0x08
-
-/*-----------------------------------------------------------------------------+
++--------------------------------------------------------------------------*/
+ unsigned char SPRC;
+#define RCRDisable 0x00
+#define RCREnable 0x80
+#define RCRIntDisable 0x00
+#define RCRIntEnabled 0x20
+#define RCRDMACh2 0x40
+#define RCRDMACh3 0x60
+#define RCRErrorInt 0x10
+#define RCRPauseEnable 0x08
+
+/*--------------------------------------------------------------------------+
| Transmitter Command Register.
-+-----------------------------------------------------------------------------*/
++--------------------------------------------------------------------------*/
unsigned char SPTC;
-#define TCRDisable 0x00
-#define TCREnable 0x80
-#define TCRIntDisable 0x00
-#define TCRIntEnabled 0x20
-#define TCRDMACh2 0x40
-#define TCRDMACh3 0x60
-#define TCRTxEmpty 0x10
-#define TCRErrorInt 0x08
-#define TCRStopPause 0x04
-#define TCRBreakGen 0x02
-
-/*-----------------------------------------------------------------------------+
+#define TCRDisable 0x00
+#define TCREnable 0x80
+#define TCRIntDisable 0x00
+#define TCRIntEnabled 0x20
+#define TCRDMACh2 0x40
+#define TCRDMACh3 0x60
+#define TCRTxEmpty 0x10
+#define TCRErrorInt 0x08
+#define TCRStopPause 0x04
+#define TCRBreakGen 0x02
+
+/*--------------------------------------------------------------------------+
| Miscellanies defines.
-+-----------------------------------------------------------------------------*/
- unsigned char SPTB;
++--------------------------------------------------------------------------*/
+ unsigned char SPTB;
#define SPRB SPTB
};
-#define XOFFchar 0x13
-#define XONchar 0x11
-
typedef volatile struct async *pasync;
static const pasync port = (pasync)0x40000000;
-/* console_initialize
- *
- * This routine initializes the console IO driver.
- *
- * Input parameters: NONE
- *
- * Output parameters: NONE
- *
- * Return values:
+static void *spittyp; /* handle for termios */
+int ppc403_spi_interrupt = 1; /* do not use interrupts... */
+
+/*
+ * Rx Interrupt handler
*/
+static rtems_isr
+spiRxInterruptHandler (rtems_vector_number v)
+{
+ char ch;
+
+ /* clear any receive errors (errors are ignored now) */
+ port->SPLS = (LSRFramingError | LSROverrunError |
+ LSRParityError | LSRBreakInterrupt);
+ /*
+ * Buffer received?
+ */
+ if (port->SPLS & LSRDataReady) {
+ ch = port->SPRB; /* read receive buffer */
+ rtems_termios_enqueue_raw_characters (spittyp,&ch,1);
+ }
+}
-rtems_device_driver console_initialize(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void *arg
-)
+/*
+ * Tx Interrupt handler
+ */
+static rtems_isr
+spiTxInterruptHandler (rtems_vector_number v)
{
- rtems_status_code status;
- register unsigned tmp;
+ /*
+ * char transmitted?
+ */
+ if (0 != (port->SPLS & LSRTxHoldEmpty)) { /* must always be true!! */
+ port->SPTC &= ~TCRIntEnabled; /* stop irqs for now... */
+ /* and call termios... */
+ rtems_termios_dequeue_characters (spittyp,1);
+ }
+}
- /* Initialise the serial port */
- asm volatile ("mfdcr %0, 0xa0" : "=r" (tmp)); /* IOCR */
- tmp &= ~3;
- tmp |= (Cpu_table.serial_external_clock ? 2 : 0) |
- (Cpu_table.serial_cts_rts ? 1 : 0);
- asm volatile ("mtdcr 0xa0, %0" : "=r" (tmp) : "0" (tmp)); /* IOCR */
- port->SPLS = (LSRDataReady | LSRFramingError | LSROverrunError |
- LSRParityError | LSRBreakInterrupt);
- tmp = Cpu_table.serial_per_sec / Cpu_table.serial_rate;
- tmp = ((tmp + 8) >> 4) - 1;
- port->BRDL = tmp & 0x255;
- port->BRDH = tmp >> 8;
- port->SPCTL = (CRNormal | CRDtr | CRRts | CRWordLength8 | CRParityDisable |
- CRStopBitsOne);
- port->SPRC = (RCREnable | RCRIntDisable | RCRPauseEnable);
- port->SPTC = (TCREnable | TCRIntDisable);
- port->SPHS = (HSRDsr | HSRCts);
+/*
+ * enable/disable RTS line to start/stop remote transmitter
+ */
+static int
+spiStartRemoteTx (int minor)
+{
+ rtems_interrupt_level level;
- status = rtems_io_register_name(
- "/dev/console",
- major,
- (rtems_device_minor_number) 0
- );
-
- if (status != RTEMS_SUCCESSFUL)
- rtems_fatal_error_occurred(status);
-
- return RTEMS_SUCCESSFUL;
+ rtems_interrupt_disable (level);
+ port->SPCTL |= CRRts; /* activate RTS */
+ rtems_interrupt_enable (level);
+ return 0;
}
+static int
+spiStopRemoteTx (int minor)
+{
+ rtems_interrupt_level level;
-/* is_character_ready
- *
- * This routine returns TRUE if a character is available.
- *
- * Input parameters: NONE
- *
- * Output parameters: NONE
- *
- * Return values:
+ rtems_interrupt_disable (level);
+ port->SPCTL &= ~CRRts; /* deactivate RTS */
+ rtems_interrupt_enable (level);
+ return 0;
+}
+
+void
+spiBaudSet(unsigned32 baudrate)
+{
+ unsigned32 tmp;
+ tmp = Cpu_table.serial_per_sec / Cpu_table.serial_rate;
+ tmp = ((tmp) >> 4) - 1;
+ port->BRDL = tmp & 0xff;
+ port->BRDH = tmp >> 8;
+
+}
+/*
+ * Hardware-dependent portion of tcsetattr().
*/
+static int
+spiSetAttributes (int minor, const struct termios *t)
+{
+ int baud;
+
+ /* FIXME: check c_cflag & CRTSCTS for hardware flowcontrol */
+ /* FIXME: check and IMPLEMENT XON/XOFF */
+ switch (t->c_cflag & CBAUD) {
+ default: baud = -1; break;
+ case B50: baud = 50; break;
+ case B75: baud = 75; break;
+ case B110: baud = 110; break;
+ case B134: baud = 134; break;
+ case B150: baud = 150; break;
+ case B200: baud = 200; break;
+ case B300: baud = 300; break;
+ case B600: baud = 600; break;
+ case B1200: baud = 1200; break;
+ case B1800: baud = 1800; break;
+ case B2400: baud = 2400; break;
+ case B4800: baud = 4800; break;
+ case B9600: baud = 9600; break;
+ case B19200: baud = 19200; break;
+ case B38400: baud = 38400; break;
+ case B57600: baud = 57600; break;
+ case B115200: baud = 115200; break;
+ case B230400: baud = 230400; break;
+ case B460800: baud = 460800; break;
+ }
+ if (baud > 0) {
+ spiBaudSet(baud);
+ }
+ return 0;
+}
-rtems_boolean is_character_ready(
- char *ch
-)
+static int
+spiPollRead (int minor)
{
unsigned char status;
- if ((status = port->SPLS) & LSRDataReady)
- {
- *ch = port->SPRB;
- return(TRUE);
- }
-
- /* Clean any dodgy status */
- if ((status & (LSRFramingError | LSROverrunError | LSRParityError |
- LSRBreakInterrupt)) != 0)
- {
+ while (0 == ((status = port->SPLS) & LSRDataReady)) {
+ /* Clean any dodgy status */
+ if ((status & (LSRFramingError | LSROverrunError | LSRParityError |
+ LSRBreakInterrupt)) != 0) {
port->SPLS = (LSRFramingError | LSROverrunError | LSRParityError |
- LSRBreakInterrupt);
+ LSRBreakInterrupt);
}
+ }
+ return port->SPRB;
+}
+
+static int
+spiInterruptWrite (int minor, const char *buf, int len)
+{
+ port->SPTB = *buf; /* write char to send */
+ port->SPTC |= TCRIntEnabled; /* always enable tx interrupt */
+ return 0;
+}
+
+static int
+spiPollWrite(int minor,const char *buf,int len)
+{
+ unsigned char status;
- return FALSE;
+ while (len-- > 0) {
+ do {
+ if (port->SPHS) {
+ port->SPHS = (HSRDsr | HSRCts);
+ }
+ status = port->SPLS;
+ } while (0 == (status & LSRTxHoldEmpty));
+ port->SPTB = *buf++;
+ }
+ return 0;
}
-/* inbyte
+/*
*
- * This routine reads a character from the SOURCE.
+ * deinit SPI
*
- * Input parameters: NONE
+ */
+void
+spiDeInit(void)
+{
+ /*
+ * disable interrupts for serial port
+ * set it to state to work with polling boot monitor, if any...
+ */
+
+ /* set up baud rate to original state */
+ spiBaudSet(Cpu_table.serial_rate);
+
+ /* clear any receive (error) status */
+ port->SPLS = (LSRDataReady | LSRFramingError | LSROverrunError |
+ LSRParityError | LSRBreakInterrupt);
+
+ /* set up port control: DTR/RTS active,8 bit,1 stop,no parity */
+ port->SPCTL = (CRNormal |
+ CRDtr | CRRts |
+ CRWordLength8 | CRParityDisable | CRStopBitsOne);
+
+ /* clear handshake status bits */
+ port->SPHS = (HSRDsr | HSRCts);
+
+ /* enable receiver/transmitter, no interrupts */
+ port->SPRC = (RCREnable | RCRIntDisable);
+ port->SPTC = (TCREnable | TCRIntDisable);
+
+}
+
+/*
*
- * Output parameters: NONE
+ * init SPI
*
- * Return values:
- * character read from SOURCE
*/
-
-char inbyte( void )
+rtems_status_code
+spiInitialize(void)
{
- unsigned char status;
+ register unsigned tmp;
+ rtems_isr_entry previous_isr; /* this is a dummy */
- while (1)
- {
- if ((status = port->SPLS) & LSRDataReady)
- break;
-
- /* Clean any dodgy status */
- if ((status & (LSRFramingError | LSROverrunError | LSRParityError |
- LSRBreakInterrupt)) != 0)
- {
- port->SPLS = (LSRFramingError | LSROverrunError | LSRParityError |
- LSRBreakInterrupt);
- }
- }
+ /*
+ * Initialise the serial port
+ */
- return port->SPRB;
+ /*
+ * select RTS/CTS hardware handshake lines,
+ * select clock source
+ */
+ asm volatile ("mfdcr %0, 0xa0" : "=r" (tmp)); /* IOCR */
+
+ tmp &= ~3;
+ tmp |= (Cpu_table.serial_external_clock ? 2 : 0) | 1;
+
+ asm volatile ("mtdcr 0xa0, %0" : "=r" (tmp) : "0" (tmp)); /* IOCR */
+
+ /* clear any receive (error) status */
+ port->SPLS = (LSRDataReady | LSRFramingError | LSROverrunError |
+ LSRParityError | LSRBreakInterrupt);
+
+ /* set up baud rate */
+ spiBaudSet(Cpu_table.serial_rate);
+
+ /* set up port control: DTR/RTS active,8 bit,1 stop,no parity */
+ port->SPCTL = (CRNormal |
+ CRDtr | CRRts |
+ CRWordLength8 | CRParityDisable | CRStopBitsOne);
+
+ /* clear handshake status bits */
+ port->SPHS = (HSRDsr | HSRCts);
+
+ if (ppc403_spi_interrupt) {
+ /* add rx/tx isr to vector table */
+ ictrl_set_vector(spiRxInterruptHandler,
+ PPC_IRQ_EXT_SPIR,
+ &previous_isr);
+
+ ictrl_set_vector(spiTxInterruptHandler,
+ PPC_IRQ_EXT_SPIT,
+ &previous_isr);
+
+ port->SPRC = (RCREnable | RCRIntEnabled | RCRErrorInt);
+ port->SPTC = (TCREnable | TCRIntDisable); /* don't enable TxInt yet */
+ }
+ else {
+ /* enable receiver/transmitter, no interrupts */
+ port->SPRC = (RCREnable | RCRIntDisable);
+ port->SPTC = (TCREnable | TCRIntDisable);
+ }
+
+ atexit(spiDeInit);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ ***************
+ * BOILERPLATE *
+ ***************
+ */
+
+/*
+ * Reserve resources consumed by this driver
+ */
+void console_reserve_resources(
+ rtems_configuration_table *configuration
+)
+{
+ rtems_termios_reserve_resources (configuration, 1);
}
-/* outbyte
+/* console_initialize
*
- * This routine transmits a character out the SOURCE. It may support
- * XON/XOFF flow control.
+ * This routine initializes the console IO driver.
*
- * Input parameters:
- * ch - character to be transmitted
+ * Input parameters: NONE
*
* Output parameters: NONE
+ *
+ * Return values:
*/
-void outbyte(
- char ch
+rtems_device_driver console_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
)
{
- unsigned char status;
+ rtems_status_code status;
- while (port->SPHS)
- port->SPHS = (HSRDsr | HSRCts);
+ /*
+ * Set up TERMIOS
+ */
+ rtems_termios_initialize ();
- while (1)
- {
- status = port->SPLS;
+ /*
+ * Do device-specific initialization
+ */
+ spiInitialize ();
- if (port->SPHS)
- port->SPHS = (HSRDsr | HSRCts);
- else if (status & LSRTxHoldEmpty)
- break;
- }
-
- if (Cpu_table.serial_xon_xoff)
- while (is_character_ready(&status))
- {
- if (status == XOFFchar)
- do {
- while (!is_character_ready(&status));
- } while (status != XONchar);
- }
-
- port->SPTB = ch;
+ /*
+ * Register the device
+ */
+ status = rtems_io_register_name ("/dev/console", major, 0);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+ return RTEMS_SUCCESSFUL;
}
+
/*
* Open entry point
*/
@@ -294,7 +464,39 @@ rtems_device_driver console_open(
void * arg
)
{
- return RTEMS_SUCCESSFUL;
+ rtems_status_code sc;
+ static const rtems_termios_callbacks intrCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ NULL, /* pollRead */
+ spiInterruptWrite, /* write */
+ spiSetAttributes, /* setAttributes */
+ spiStopRemoteTx, /* stopRemoteTx */
+ spiStartRemoteTx, /* startRemoteTx */
+ 1 /* outputUsesInterrupts */
+ };
+
+ static const rtems_termios_callbacks pollCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ spiPollRead, /* pollRead */
+ spiPollWrite, /* write */
+ spiSetAttributes, /* setAttributes */
+ spiStopRemoteTx, /* stopRemoteTx */
+ spiStartRemoteTx, /* startRemoteTx */
+ 0 /* outputUsesInterrupts */
+ };
+
+ if (ppc403_spi_interrupt) {
+ rtems_libio_open_close_args_t *args = arg;
+
+ sc = rtems_termios_open (major, minor, arg, &intrCallbacks);
+ spittyp = args->iop->data1;
+ }
+ else {
+ sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
+ }
+ return sc;
}
/*
@@ -307,7 +509,7 @@ rtems_device_driver console_close(
void * arg
)
{
- return RTEMS_SUCCESSFUL;
+ return rtems_termios_close (arg);
}
/*
@@ -320,27 +522,7 @@ rtems_device_driver console_read(
void * arg
)
{
- rtems_libio_rw_args_t *rw_args;
- char *buffer;
- int maximum;
- int count = 0;
-
- rw_args = (rtems_libio_rw_args_t *) arg;
-
- buffer = rw_args->buffer;
- maximum = rw_args->count;
-
- for (count = 0; count < maximum; count++) {
- buffer[ count ] = inbyte();
- if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
- buffer[ count++ ] = '\n';
- buffer[ count ] = 0;
- break;
- }
- }
-
- rw_args->bytes_moved = count;
- return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
+ return rtems_termios_read (arg);
}
/*
@@ -353,23 +535,7 @@ rtems_device_driver console_write(
void * arg
)
{
- int count;
- int maximum;
- rtems_libio_rw_args_t *rw_args;
- char *buffer;
-
- rw_args = (rtems_libio_rw_args_t *) arg;
-
- buffer = rw_args->buffer;
- maximum = rw_args->count;
-
- for (count = 0; count < maximum; count++) {
- if ( buffer[ count ] == '\n') {
- outbyte('\r');
- }
- outbyte( buffer[ count ] );
- }
- return maximum;
+ return rtems_termios_write (arg);
}
/*
@@ -382,6 +548,6 @@ rtems_device_driver console_control(
void * arg
)
{
- return RTEMS_SUCCESSFUL;
+ return rtems_termios_ioctl (arg);
}