summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1998-09-30 21:55:53 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1998-09-30 21:55:53 +0000
commitaecfa2bf09e26bfef4cb07bfe31d94ab0c92ae1a (patch)
tree364d49eba07d2be2cc1455ab7f2dafcc261f706f
parentBSP submitted by Thomas Doerfler <td@imd.m.isar.de>: (diff)
downloadrtems-aecfa2bf09e26bfef4cb07bfe31d94ab0c92ae1a.tar.bz2
BSP submitted by Thomas Doerfler <td@imd.m.isar.de>:
Finally I am through: I have found the last bugs that made RTEMS- 4.0-beta3 start on my ppc403 board from ROM. So now the '403 support is up to date again. Roughly I have added the following features: - support for the on-chip interrupt controller (in a separate module) - interrupt support for the console device - termios support for the console device ============================================== Since the BSP behaivour changed in some details (console no longer is polling, other memory layout etc) I have created a new BSP "helas403" rather than changing the "papyrus" BSP. The old "polled" console driver still sticks around in "console.c.polled" To get the BSP up and running, I had to create the new BSP files (derived from papyrus). Besides that, the following source areas have been changed: - c/src/lib/libcpu/powerpc/ppc403: changes to console driver, small changes to clock driver, new "ictrl" interrupt controller driver - c/src/exec/score/cpu/powerpc/ppc.h: some small changes (added ppc403 characteristics like a exception vector prefix register, some special register definitions). I am quite sure, they are compatible with the existing sources, although I did not check - c/src/exec/score/cpu/powerpc/cpu.c: There is one severe limitation in the exception entries: Due to the current code arrangement, the "branch absolute" to the ISR handler may only jump to the first 128MByte or the last 128MByte of the 4GByte address range. When the ppc403 is running out of ROM, the ROM functions are located in the last 128MByte (0xFFF00000 and up). These addresses were not handled correctly (sign reduced) in "install_raw_handler". The change I added should work on existing ppc BSPs aswell... - c/src/lib/libc/termios.c: During my tests, I added one change you sent me, so this patch will already be incorporated in the current source tree. There are some smaller changes, see the attached diff file. ========================================= Concerning the GNU toolchain: I tried several tool chains. Finally I almost succeeded with egcs-1.0.3a with patch egcs-1.0.3-rtems-diff-19980527 I had to add the following lines to the egcs files. Without them configure complaint that the cross compiler could not generate executable output. - additional lines needed in egcs distribution in file gcc/config/rs6000/rtems.h: +++ lines start #undef STARTFILE_DEFAULT_SPEC #define STARTFILE_DEFAULT_SPEC "ecrti.o%s" #undef ENDFILE_DEFAULT_SPEC #define ENDFILE_DEFAULT_SPEC "ecrtn.o%s" ++++ lines end As far as I have seen in the Changelog of egcs, you have recently sent two patches affecting the powerpc support, but they were added in the wrong order.... :-( egcs-19980628 with patch egcs-19980628-rtems-diff-19980707 does not work! I used binutils 2.9.1 with patch binutils-2.9.1-rtems-diff-19980515 (binutils 2.8.1 does not work, internal error in gas) and newlib-1.8.0 with patch newlib-1.8.0-rtems-diff-19980707 Finally I had to poke a line in the "bit" script, since, on my LINUX machine, the GNU make is only available as "make", not as "gmake"... For all the tools and newlib I selected configuration "powerpc- rtems". -------------------------------------------- IMD Ingenieurbuero fuer Microcomputertechnik Thomas Doerfler Herbststrasse 8 D-82178 Puchheim Germany email: td@imd.m.isar.de
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/Makefile.in2
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/clock/clock.c21
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/console/console.c602
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/console/console.c.polled393
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/ictrl/Makefile.in61
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.c250
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.h84
7 files changed, 1192 insertions, 221 deletions
diff --git a/c/src/lib/libcpu/powerpc/ppc403/Makefile.in b/c/src/lib/libcpu/powerpc/ppc403/Makefile.in
index f4490904c1..a58384c787 100644
--- a/c/src/lib/libcpu/powerpc/ppc403/Makefile.in
+++ b/c/src/lib/libcpu/powerpc/ppc403/Makefile.in
@@ -11,4 +11,4 @@ PROJECT_ROOT = @PROJECT_ROOT@
include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
include $(RTEMS_ROOT)/make/directory.cfg
-SUB_DIRS=include console clock timer vectors
+SUB_DIRS=include console clock timer vectors ictrl
diff --git a/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c b/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c
index 4a8f66d643..99b538dcd3 100644
--- a/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c
+++ b/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c
@@ -20,6 +20,12 @@
*
* Derived from c/src/lib/libcpu/hppa1.1/clock/clock.c:
*
+ * Modifications for deriving timer clock from cpu system clock by
+ * Thomas Doerfler <td@imd.m.isar.de>
+ * for these modifications:
+ * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany.
+ *
+ *
* COPYRIGHT (c) 1989-1998.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
@@ -133,8 +139,14 @@ void Install_clock(rtems_isr_entry clock_isr)
Clock_driver_ticks = 0;
asm volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); /* IOCR */
- iocr &= ~4;
- iocr |= 4; /* Select external timer clock */
+
+ if (Cpu_table.timer_internal_clock) {
+ iocr &= ~4; /* timer clocked from system clock */
+ }
+ else {
+ iocr |= 4; /* select external timer clock */
+ }
+
asm volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr)); /* IOCR */
asm volatile ("mfspr %0, 0x11f" : "=r" ((pvr))); /* PVR */
@@ -143,7 +155,12 @@ void Install_clock(rtems_isr_entry clock_isr)
return; /* Not a ppc403 */
if ((pvr & 0xff00) == 0x0000) /* 403GA */
+#if 0 /* FIXME: in which processor versions will "autoload" work properly? */
auto_restart = (pvr & 0x00f0) > 0x0000 ? 1 : 0;
+#else
+ /* no known chip version supports auto restart of timer... */
+ auto_restart = 0;
+#endif
else if ((pvr & 0xff00) == 0x0100) /* 403GB */
auto_restart = 1;
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);
}
diff --git a/c/src/lib/libcpu/powerpc/ppc403/console/console.c.polled b/c/src/lib/libcpu/powerpc/ppc403/console/console.c.polled
new file mode 100644
index 0000000000..a623dde95a
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/console/console.c.polled
@@ -0,0 +1,393 @@
+/*
+ * This file contains the PowerPC 403GA console IO package.
+ *
+ * Author: Andrew Bray <andy@i-cubed.co.uk>
+ *
+ * COPYRIGHT (c) 1995 by i-cubed ltd.
+ *
+ * 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, and that the name of i-cubed limited not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * i-cubed limited 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.
+ * 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$
+ */
+
+#define NO_BSP_INIT
+
+#include <bsp.h>
+#include <rtems/libio.h>
+
+extern rtems_cpu_table Cpu_table; /* owned by BSP */
+
+struct async {
+/*-----------------------------------------------------------------------------+
+| Line Status Register.
++-----------------------------------------------------------------------------*/
+ unsigned char SPLS;
+ unsigned char SPLSset;
+#define LSRDataReady 0x80
+#define LSRFramingError 0x40
+#define LSROverrunError 0x20
+#define LSRParityError 0x10
+#define LSRBreakInterrupt 0x08
+#define LSRTxHoldEmpty 0x04
+#define LSRTxShiftEmpty 0x02
+
+/*-----------------------------------------------------------------------------+
+| Handshake Status Register.
++-----------------------------------------------------------------------------*/
+ unsigned char SPHS;
+ unsigned char SPHSset;
+#define HSRDsr 0x80
+#define HSRCts 0x40
+
+/*-----------------------------------------------------------------------------+
+| Baud rate divisor registers
++-----------------------------------------------------------------------------*/
+ unsigned char BRDH;
+ unsigned char BRDL;
+
+/*-----------------------------------------------------------------------------+
+| Control Register.
++-----------------------------------------------------------------------------*/
+ unsigned char SPCTL;
+#define CRNormal 0x00
+#define CRLoopback 0x40
+#define CRAutoEcho 0x80
+#define CRDtr 0x20
+#define CRRts 0x10
+#define CRWordLength7 0x00
+#define CRWordLength8 0x08
+#define CRParityDisable 0x00
+#define CRParityEnable 0x04
+#define CREvenParity 0x00
+#define CROddParity 0x02
+#define CRStopBitsOne 0x00
+#define CRStopBitsTwo 0x01
+#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
+
+/*-----------------------------------------------------------------------------+
+| 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
+
+/*-----------------------------------------------------------------------------+
+| Miscellanies defines.
++-----------------------------------------------------------------------------*/
+ 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:
+ */
+
+rtems_device_driver console_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_status_code status;
+ register unsigned tmp;
+
+ /* 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;
+#if 0 /* replaced by IMD... */
+ tmp = ((tmp + 8) >> 4) - 1;
+ port->BRDL = tmp & 0x255;
+ port->BRDH = tmp >> 8;
+#else
+ tmp = ((tmp) >> 4) - 1;
+ port->BRDL = tmp & 0xff;
+ port->BRDH = tmp >> 8;
+#endif
+ port->SPCTL = (CRNormal | CRDtr | CRRts | CRWordLength8 | CRParityDisable |
+ CRStopBitsOne);
+ port->SPRC = (RCREnable | RCRIntDisable | RCRPauseEnable);
+ port->SPTC = (TCREnable | TCRIntDisable);
+ port->SPHS = (HSRDsr | HSRCts);
+
+ 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;
+}
+
+
+/* is_character_ready
+ *
+ * This routine returns TRUE if a character is available.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values:
+ */
+
+rtems_boolean is_character_ready(
+ char *ch
+)
+{
+ unsigned char status;
+
+ if ((status = port->SPLS) & LSRDataReady)
+ {
+ *ch = port->SPRB;
+ return(TRUE);
+ }
+
+ /* Clean any dodgy status */
+ if ((status & (LSRFramingError | LSROverrunError | LSRParityError |
+ LSRBreakInterrupt)) != 0)
+ {
+ port->SPLS = (LSRFramingError | LSROverrunError | LSRParityError |
+ LSRBreakInterrupt);
+ }
+
+ return FALSE;
+}
+
+/* inbyte
+ *
+ * This routine reads a character from the SOURCE.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values:
+ * character read from SOURCE
+ */
+
+char inbyte( void )
+{
+ unsigned char status;
+
+ 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);
+ }
+ }
+
+ return port->SPRB;
+}
+
+/* outbyte
+ *
+ * This routine transmits a character out the SOURCE. It may support
+ * XON/XOFF flow control.
+ *
+ * Input parameters:
+ * ch - character to be transmitted
+ *
+ * Output parameters: NONE
+ */
+
+void outbyte(
+ char ch
+)
+{
+ unsigned char status;
+
+ while (port->SPHS)
+ port->SPHS = (HSRDsr | HSRCts);
+
+ while (1)
+ {
+ status = port->SPLS;
+
+ 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;
+}
+
+/*
+ * Open entry point
+ */
+
+rtems_device_driver console_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Close entry point
+ */
+
+rtems_device_driver console_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * read bytes from the serial port. We only have stdin.
+ */
+
+rtems_device_driver console_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ 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;
+}
+
+/*
+ * write bytes to the serial port. Stdout and stderr are the same.
+ */
+
+rtems_device_driver console_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ 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;
+}
+
+/*
+ * IO Control entry point
+ */
+
+rtems_device_driver console_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return RTEMS_SUCCESSFUL;
+}
+
diff --git a/c/src/lib/libcpu/powerpc/ppc403/ictrl/Makefile.in b/c/src/lib/libcpu/powerpc/ppc403/ictrl/Makefile.in
new file mode 100644
index 0000000000..551b527ead
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/ictrl/Makefile.in
@@ -0,0 +1,61 @@
+#
+# $Id$
+#
+
+@SET_MAKE@
+srcdir = @srcdir@
+VPATH = @srcdir@
+RTEMS_ROOT = @top_srcdir@
+PROJECT_ROOT = @PROJECT_ROOT@
+
+PGM=${ARCH}/ictrl.rel
+
+# C source names, if any, go here -- minus the .c
+C_PIECES=ictrl
+C_FILES=$(C_PIECES:%=%.c)
+C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
+
+H_FILES=$(srcdir)/ictrl.h
+
+# Assembly source names, if any, go here -- minus the .s
+S_PIECES=
+S_FILES=$(S_PIECES:%=%.s)
+S_O_FILES=$(S_FILES:%.s=${ARCH}/%.o)
+
+SRCS=$(C_FILES) $(CC_FILES) $(H_FILES) $(S_FILES)
+OBJS=$(C_O_FILES) $(CC_O_FILES) $(S_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg
+include $(RTEMS_ROOT)/make/leaf.cfg
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+DEFINES +=
+CPPFLAGS +=
+CFLAGS += $(CFLAGS_OS_V)
+
+LD_PATHS +=
+LD_LIBS +=
+LDFLAGS +=
+
+#
+# Add your list of files to delete here. The config files
+# already know how to delete some stuff, so you may want
+# to just run 'make clean' first to see what gets missed.
+# 'make clobber' already includes 'make clean'
+#
+
+CLEAN_ADDITIONS +=
+CLOBBER_ADDITIONS +=
+
+${PGM}: ${SRCS} ${OBJS}
+ $(make-rel)
+
+all: ${ARCH} $(SRCS) $(PGM)
+ $(INSTALL) -m 444 $(H_FILES) $(PROJECT_INCLUDE)
+
+# the .rel file built here will be put into libbsp.a by
+# libbsp/hppa/BSP/wrapup/Makefile
+install: all
diff --git a/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.c b/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.c
new file mode 100644
index 0000000000..11d09f748a
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.c
@@ -0,0 +1,250 @@
+/* ictrl.c
+ *
+ * This routine installs and handles external interrupt vectors for
+ * PowerPC 403 CPU built-in external interrupt controller
+ *
+ * Author: Thomas Doerfler <td@imd.m.isar.de>
+ *
+ * COPYRIGHT (c) 1998 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, and that the name of IMD not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * IMD makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ */
+
+#include "ictrl.h"
+#include <bsp.h>
+#include <rtems/libio.h>
+
+#include <stdlib.h> /* for atexit() */
+
+/*
+ * ISR vector table to dispatch external interrupts
+ */
+
+rtems_isr_entry ictrl_vector_table[PPC_IRQ_EXT_MAX];
+
+/*
+ *
+ * some utilities to access the EXI* registers
+ *
+ */
+
+/*
+ * clear bits in EXISR that have a bit set in mask
+ */
+RTEMS_INLINE_ROUTINE void
+clr_exisr(unsigned32 mask)
+{
+ asm volatile ("mtdcr 0x40,%0"::"r" (mask));/*EXISR*/
+}
+
+/*
+ * get value of EXISR
+ */
+RTEMS_INLINE_ROUTINE unsigned32
+get_exisr(void)
+{
+ unsigned32 val;
+
+ asm volatile ("mfdcr %0,0x40":"=r" (val));/*EXISR*/
+ return val;
+}
+
+/*
+ * get value of EXIER
+ */
+RTEMS_INLINE_ROUTINE unsigned32
+get_exier(void)
+{
+ unsigned32 val;
+ asm volatile ("mfdcr %0,0x42":"=r" (val));/*EXIER*/
+ return val;
+}
+
+/*
+ * set value of EXIER
+ */
+RTEMS_INLINE_ROUTINE void
+set_exier(unsigned32 val)
+{
+ asm volatile ("mtdcr 0x42,%0"::"r" (val));/*EXIER*/
+}
+
+/*
+ * enable an external interrupt, make this interrupt consistent
+ */
+RTEMS_INLINE_ROUTINE void
+enable_ext_irq( unsigned32 mask)
+{
+ unsigned32 isrlvl;
+ _CPU_ISR_Disable(isrlvl);
+ set_exier(get_exier() | ((mask)&PPC_EXI_MASK));
+ _CPU_ISR_Enable(isrlvl);
+}
+
+/*
+ * disable an external interrupt, make this interrupt consistent
+ */
+RTEMS_INLINE_ROUTINE void
+disable_ext_irq( unsigned32 mask)
+{
+ unsigned32 isrlvl;
+ _CPU_ISR_Disable(isrlvl);
+ set_exier(get_exier() & ~(mask) & PPC_EXI_MASK);
+ _CPU_ISR_Enable(isrlvl);
+}
+
+/*
+ *
+ * this function is called, when a external interrupt is present and
+ * enabled but there is no handler installed. It will clear
+ * the corresponding enable bits and call the spurious handler
+ * present in the _CPU_Table, if any.
+ *
+ */
+void
+ictrl_spurious_handler(unsigned32 spurious_mask,
+ CPU_Interrupt_frame *cpu_frame)
+{
+ int v;
+
+ for (v=0; v < PPC_IRQ_EXT_MAX; v++) {
+ if (VEC_TO_EXMSK(v) & spurious_mask) {
+ clr_exisr(VEC_TO_EXMSK(v));
+ disable_ext_irq(VEC_TO_EXMSK(v));
+#if 0
+ printf("spurious external interrupt: %d at pc 0x%x; disabling\n",
+ vector, cpu_frame->Interrupt.pcoqfront);
+#endif
+ if (_CPU_Table.spurious_handler) {
+ _CPU_Table.spurious_handler(v + PPC_IRQ_EXT_BASE,cpu_frame);
+ }
+ }
+ }
+}
+
+
+/*
+ * ISR Handler: this is called from the primary exception dispatcher
+ */
+
+void
+ictrl_isr(rtems_vector_number vector,CPU_Interrupt_frame *cpu_frame)
+{
+ unsigned32 istat,
+ mask,
+ global_vec;
+ int exvec;
+ rtems_isr_entry handler;
+
+ istat = get_exisr() & get_exier() & PPC_EXI_MASK;
+
+ /* FIXME: this may be speeded up using cntlzw instruction */
+ for (exvec = 0;exvec < PPC_IRQ_EXT_MAX;exvec++) {
+ mask = VEC_TO_EXMSK(exvec);
+ if (0 != (istat & mask)) {
+ clr_exisr(mask);
+ handler = ictrl_vector_table[exvec];
+ if (handler) {
+ istat &= ~mask;
+ global_vec = exvec + PPC_IRQ_EXT_BASE;
+ (handler)(global_vec);
+ }
+ }
+ }
+ if (istat != 0) { /* anything left? then we have a spurious interrupt */
+ ictrl_spurious_handler(istat,cpu_frame);
+ }
+}
+
+/*
+ *
+ * the following functions form the user interface
+ *
+ */
+
+/*
+ *
+ * install a user vector for one of the external interrupt sources
+ *
+ */
+rtems_status_code
+ictrl_set_vector(rtems_isr_entry new_handler,
+ unsigned32 vector,
+ rtems_isr_entry *old_handler
+)
+{
+ /*
+ * We put the actual user ISR address in 'ictrl_vector_table'. This will
+ * be used by the _ictrl_isr so the user gets control.
+ */
+
+ /* check for valid vector range */
+ if ((vector >= PPC_IRQ_EXT_BASE) &&
+ (vector < PPC_IRQ_EXT_BASE + PPC_IRQ_EXT_MAX)) {
+
+ /* return old handler entry */
+ *old_handler = ictrl_vector_table[vector - PPC_IRQ_EXT_BASE];
+
+ if (new_handler != NULL) {
+ /* store handler function... */
+ ictrl_vector_table[vector - PPC_IRQ_EXT_BASE] = new_handler;
+ /* then enable it in EXIER register */
+ enable_ext_irq(VEC_TO_EXMSK(vector - PPC_IRQ_EXT_BASE));
+ }
+ else { /* new_handler == NULL */
+ /* then disable it in EXIER register */
+ disable_ext_irq(VEC_TO_EXMSK(vector - PPC_IRQ_EXT_BASE));
+ ictrl_vector_table[vector - PPC_IRQ_EXT_BASE] = NULL;
+ }
+ return RTEMS_SUCCESSFUL;
+ }
+ else {
+ return RTEMS_INVALID_NUMBER;
+ }
+}
+
+/*
+ * Called via atexit()
+ * deactivate the interrupt controller
+ */
+
+void
+ictrl_exit(void)
+{
+ /* mark them all unused */
+ disable_ext_irq(~0);
+ clr_exisr(~0);
+
+}
+
+/*
+ * activate the interrupt controller
+ */
+
+rtems_status_code
+ictrl_init(void)
+{
+ proc_ptr dummy;
+
+ /* mark them all unused */
+ disable_ext_irq(~0);
+ clr_exisr(~0);
+
+ /* install the external interrupt handler */
+ _CPU_ISR_install_vector(PPC_IRQ_EXTERNAL,
+ ictrl_isr,
+ &dummy);
+ atexit(ictrl_exit);
+ return RTEMS_SUCCESSFUL;
+}
+
diff --git a/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.h b/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.h
new file mode 100644
index 0000000000..5891d8aa2e
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.h
@@ -0,0 +1,84 @@
+/* ictrl.h
+ *
+ * This file contains definitions and declarations for the
+ * PowerPC 403 CPU built-in external interrupt controller
+ *
+ *
+ * Author: Thomas Doerfler <td@imd.m.isar.de>
+ *
+ * COPYRIGHT (c) 1998 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, and that the name of IMD not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * IMD makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ */
+
+
+#ifndef _INCLUDE_ICTRL_h
+#define _INCLUDE_ICTRL_h
+
+#include <rtems.h>
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * definitions for second level IRQ handler support
+ * External Interrupts via EXTERNAL/EISR
+ */
+#define PPC_IRQ_EXT_BASE (PPC_IRQ_LAST+1)
+
+/* mask for external interrupt status in EXIER/EXISR register */
+/* note: critical interrupt is in these registers aswell */
+#define PPC_EXI_MASK 0x0FFFFFFF
+
+#define PPC_IRQ_EXT_SPIR (PPC_IRQ_EXT_BASE+4)
+#define PPC_IRQ_EXT_SPIT (PPC_IRQ_EXT_BASE+5)
+#define PPC_IRQ_EXT_JTAGR (PPC_IRQ_EXT_BASE+6)
+#define PPC_IRQ_EXT_JTAGT (PPC_IRQ_EXT_BASE+7)
+#define PPC_IRQ_EXT_DMA0 (PPC_IRQ_EXT_BASE+8)
+#define PPC_IRQ_EXT_DMA1 (PPC_IRQ_EXT_BASE+9)
+#define PPC_IRQ_EXT_DMA2 (PPC_IRQ_EXT_BASE+10)
+#define PPC_IRQ_EXT_DMA3 (PPC_IRQ_EXT_BASE+11)
+#define PPC_IRQ_EXT_0 (PPC_IRQ_EXT_BASE+27)
+#define PPC_IRQ_EXT_1 (PPC_IRQ_EXT_BASE+28)
+#define PPC_IRQ_EXT_2 (PPC_IRQ_EXT_BASE+29)
+#define PPC_IRQ_EXT_3 (PPC_IRQ_EXT_BASE+30)
+#define PPC_IRQ_EXT_4 (PPC_IRQ_EXT_BASE+31)
+
+#define PPC_IRQ_EXT_MAX (32)
+
+#define VEC_TO_EXMSK(v) (0x80000000 >> (v))
+
+/*
+ *
+ * install a user vector for one of the external interrupt sources
+ *
+ */
+rtems_status_code
+ictrl_set_vector(rtems_isr_entry new_handler,
+ unsigned32 vector,
+ rtems_isr_entry *old_handler
+);
+/*
+ * activate the interrupt controller
+ */
+rtems_status_code
+ictrl_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _INCLUDE_ICTRL_h */
+/* end of include file */