summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2007-07-04 12:37:36 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2007-07-04 12:37:36 +0000
commit862c231785024acbd6c830fb30e0a6a64e6c3318 (patch)
treefc09530e45e5436192c6286e70b912fbff8bcf16 /c/src/lib/libcpu
parentmerged individual exception handler code to a common one. (diff)
downloadrtems-862c231785024acbd6c830fb30e0a6a64e6c3318.tar.bz2
added virtex BSP support and some missing files for common PPC
exception handling
Diffstat (limited to '')
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/asm_utils.S63
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.c501
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.h324
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.c292
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.h95
5 files changed, 1275 insertions, 0 deletions
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/asm_utils.S b/c/src/lib/libcpu/powerpc/new-exceptions/asm_utils.S
new file mode 100644
index 0000000000..45a0f3ea73
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/new-exceptions/asm_utils.S
@@ -0,0 +1,63 @@
+/*
+ * asm_utils.s
+ *
+ * $Id$
+ *
+ * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
+ *
+ * This file contains the low-level support for moving exception
+ * exception code to appropriate location.
+ *
+ */
+
+#include <rtems/asm.h>
+#include <rtems/score/cpu.h>
+
+ .globl codemove
+codemove:
+ .type codemove,@function
+/* r3 dest, r4 src, r5 length in bytes, r6 cachelinesize */
+ cmplw cr1,r3,r4
+ addi r0,r5,3
+ srwi. r0,r0,2
+ beq cr1,4f /* In place copy is not necessary */
+ beq 7f /* Protect against 0 count */
+ mtctr r0
+ bge cr1,2f
+
+ la r8,-4(r4)
+ la r7,-4(r3)
+1: lwzu r0,4(r8)
+ stwu r0,4(r7)
+ bdnz 1b
+ b 4f
+
+2: slwi r0,r0,2
+ add r8,r4,r0
+ add r7,r3,r0
+3: lwzu r0,-4(r8)
+ stwu r0,-4(r7)
+ bdnz 3b
+
+/* Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4: cmpwi r6,0
+ add r5,r3,r5
+ beq 7f /* Always flush prefetch queue in any case */
+ subi r0,r6,1
+ andc r3,r3,r0
+ mr r4,r3
+5: cmplw r4,r5
+ dcbst 0,r4
+ add r4,r4,r6
+ blt 5b
+ sync /* Wait for all dcbst to complete on bus */
+ mr r4,r3
+6: cmplw r4,r5
+ icbi 0,r4
+ add r4,r4,r6
+ blt 6b
+7: sync /* Wait for all icbi to complete on bus */
+ isync
+ blr
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.c b/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.c
new file mode 100644
index 0000000000..d412f38008
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.c
@@ -0,0 +1,501 @@
+/*
+ * raw_exception.c - This file contains implementation of C function to
+ * Instantiate 60x ppc primary exception entries.
+ * More detailed information can be found on motorola
+ * site and more precisely in the following book :
+ *
+ * MPC750
+ * Risc Microporcessor User's Manual
+ * Motorola REF : MPC750UM/AD 8/97
+ *
+ * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
+ * Canon Centre Recherche France.
+ *
+ * Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
+ * to support 603, 603e, 604, 604e exceptions
+ *
+ * moved to "libcpu/powerpc/new-exceptions and consolidated
+ * by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
+ * to be common for all PPCs with new excpetions
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+#include <rtems/system.h>
+#include <rtems/score/powerpc.h>
+#include <rtems/bspIo.h>
+#include <libcpu/raw_exception.h>
+#include <libcpu/cpuIdent.h>
+
+#include <string.h>
+
+static rtems_raw_except_connect_data* raw_except_table;
+static rtems_raw_except_connect_data default_raw_except_entry;
+static rtems_raw_except_global_settings* local_settings;
+
+void * codemove(void *, const void *, unsigned int, unsigned long);
+
+
+static void* ppc_get_vector_addr(rtems_vector vector)
+{
+ unsigned vaddr;
+ extern rtems_cpu_table Cpu_table;
+
+ switch(vector) {
+ /*
+ * some vectors are located at odd addresses and only available
+ * on some CPU derivates. this construct will handle them
+ * if available
+ */
+#if defined(PPC_HAS_60X_VECTORS)
+ /* Special case; altivec unavailable doesn't fit :-( */
+ case ASM_VEC_VECTOR:
+ vaddr = ASM_VEC_VECTOR_OFFSET;
+ break;
+#endif
+#if defined(ASM_PIT_VECTOR)
+ case ASM_PIT_VECTOR:
+ vaddr = ASM_PIT_VECTOR_OFFSET;
+ break;
+#endif
+#if defined(ASM_FIT_VECTOR)
+ case ASM_FIT_VECTOR:
+ vaddr = ASM_FIT_VECTOR_OFFSET;
+ break;
+#endif
+#if defined(ASM_WDOG_VECTOR)
+ case ASM_WDOG_VECTOR:
+ vaddr = ASM_WDOG_VECTOR_OFFSET;
+ break;
+#endif
+ default:
+ vaddr = ((unsigned)vector) << 8;
+ break;
+ }
+ if ( Cpu_table.exceptions_in_RAM )
+ return ((void*) vaddr);
+
+ return ((void*) (vaddr + 0xfff00000));
+}
+
+
+#if ( defined(mpc860) || defined(mpc821) )
+
+int mpc860_vector_is_valid(rtems_vector vector)
+{
+ switch(vector) {
+ case ASM_RESET_VECTOR: /* fall through */
+ case ASM_MACH_VECTOR:
+ case ASM_PROT_VECTOR:
+ case ASM_ISI_VECTOR:
+ case ASM_EXT_VECTOR:
+ case ASM_ALIGN_VECTOR:
+ case ASM_PROG_VECTOR:
+ case ASM_FLOAT_VECTOR:
+ case ASM_DEC_VECTOR:
+
+ case ASM_SYS_VECTOR:
+ case ASM_TRACE_VECTOR:
+ case ASM_FLOATASSIST_VECTOR:
+
+ case ASM_SOFTEMUL_VECTOR:
+ case ASM_ITLBMISS_VECTOR:
+ case ASM_DTLBMISS_VECTOR:
+ case ASM_ITLBERROR_VECTOR:
+ case ASM_DTLBERROR_VECTOR:
+
+ case ASM_DBREAK_VECTOR:
+ case ASM_IBREAK_VECTOR:
+ case ASM_PERIFBREAK_VECTOR:
+ case ASM_DEVPORT_VECTOR:
+ return 1;
+ default: return 0;
+ }
+}
+#endif
+
+#if (defined(mpc555) || defined(mpc505))
+
+int ppc_vector_is_valid(rtems_vector vector)
+{
+ switch (current_ppc_cpu) {
+ case PPC_5XX:
+ switch(vector) {
+ case ASM_RESET_VECTOR:
+ case ASM_MACH_VECTOR:
+
+ case ASM_EXT_VECTOR:
+ case ASM_ALIGN_VECTOR:
+ case ASM_PROG_VECTOR:
+ case ASM_FLOAT_VECTOR:
+ case ASM_DEC_VECTOR:
+
+ case ASM_SYS_VECTOR:
+ case ASM_TRACE_VECTOR:
+ case ASM_FLOATASSIST_VECTOR:
+
+ case ASM_SOFTEMUL_VECTOR:
+
+ case ASM_IPROT_VECTOR:
+ case ASM_DPROT_VECTOR:
+
+ case ASM_DBREAK_VECTOR:
+ case ASM_IBREAK_VECTOR:
+ case ASM_MEBREAK_VECTOR:
+ case ASM_NMEBREAK_VECTOR:
+ return 1;
+ default:
+ return 0;
+ }
+ default:
+ printk("Please complete libcpu/powerpc/shared/new-exceptions/raw_exception.c\n");
+ printk("current_ppc_cpu = %x\n", current_ppc_cpu);
+ return 0;
+ }
+}
+#endif
+
+#if defined(ppc405)
+int ppc405_vector_is_valid(rtems_vector vector)
+
+{
+ switch(vector) {
+ case ASM_RESET_VECTOR: /* fall through */
+ case ASM_MACH_VECTOR:
+ case ASM_PROT_VECTOR:
+ case ASM_ISI_VECTOR:
+ case ASM_EXT_VECTOR:
+ case ASM_ALIGN_VECTOR:
+ case ASM_PROG_VECTOR:
+ case ASM_SYS_VECTOR:
+ case ASM_PIT_VECTOR:
+ case ASM_ITLBMISS_VECTOR:
+ case ASM_DTLBMISS_VECTOR:
+ return 1;
+ default: return 0;
+ }
+}
+#endif /* defined(ppc405) */
+
+#if defined(PPC_HAS_60X_VECTORS) /* 60x style cpu types */
+
+int altivec_vector_is_valid(rtems_vector vector)
+{
+ switch(vector) {
+ case ASM_VEC_VECTOR:
+ case ASM_VEC_ASSIST_VECTOR:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+int mpc750_vector_is_valid(rtems_vector vector)
+
+{
+ switch(vector) {
+ case ASM_RESET_VECTOR: /* fall through */
+ case ASM_MACH_VECTOR:
+ case ASM_PROT_VECTOR:
+ case ASM_ISI_VECTOR:
+ case ASM_EXT_VECTOR:
+ case ASM_ALIGN_VECTOR:
+ case ASM_PROG_VECTOR:
+ case ASM_FLOAT_VECTOR:
+ case ASM_DEC_VECTOR:
+ case ASM_SYS_VECTOR:
+ case ASM_TRACE_VECTOR:
+ case ASM_ADDR_VECTOR:
+ case ASM_SYSMGMT_VECTOR:
+ case ASM_ITM_VECTOR:
+ return 1;
+ default: return 0;
+ }
+}
+
+int PSIM_vector_is_valid(rtems_vector vector)
+{
+ switch(vector) {
+ case ASM_RESET_VECTOR: /* fall through */
+ case ASM_MACH_VECTOR:
+ case ASM_PROT_VECTOR:
+ case ASM_ISI_VECTOR:
+ case ASM_EXT_VECTOR:
+ case ASM_ALIGN_VECTOR:
+ case ASM_PROG_VECTOR:
+ case ASM_FLOAT_VECTOR:
+ case ASM_DEC_VECTOR:
+ return 1;
+ case ASM_SYS_VECTOR:
+ return 0;
+ case ASM_TRACE_VECTOR:
+ return 1;
+ case ASM_PERFMON_VECTOR:
+ return 0;
+ case ASM_IMISS_VECTOR: /* fall through */
+ case ASM_DLMISS_VECTOR:
+ case ASM_DSMISS_VECTOR:
+ case ASM_ADDR_VECTOR:
+ case ASM_SYSMGMT_VECTOR:
+ return 1;
+ case ASM_ITM_VECTOR:
+ return 0;
+ }
+ return 0;
+}
+
+int mpc603_vector_is_valid(rtems_vector vector)
+{
+ switch(vector) {
+ case ASM_RESET_VECTOR: /* fall through */
+ case ASM_MACH_VECTOR:
+ case ASM_PROT_VECTOR:
+ case ASM_ISI_VECTOR:
+ case ASM_EXT_VECTOR:
+ case ASM_ALIGN_VECTOR:
+ case ASM_PROG_VECTOR:
+ case ASM_FLOAT_VECTOR:
+ case ASM_DEC_VECTOR:
+ case ASM_SYS_VECTOR:
+ case ASM_TRACE_VECTOR:
+ return 1;
+ case ASM_PERFMON_VECTOR:
+ return 0;
+ case ASM_IMISS_VECTOR: /* fall through */
+ case ASM_DLMISS_VECTOR:
+ case ASM_DSMISS_VECTOR:
+ case ASM_ADDR_VECTOR:
+ case ASM_SYSMGMT_VECTOR:
+ return 1;
+ case ASM_ITM_VECTOR:
+ return 0;
+ }
+ return 0;
+}
+
+int mpc604_vector_is_valid(rtems_vector vector)
+{
+ switch(vector) {
+ case ASM_RESET_VECTOR: /* fall through */
+ case ASM_MACH_VECTOR:
+ case ASM_PROT_VECTOR:
+ case ASM_ISI_VECTOR:
+ case ASM_EXT_VECTOR:
+ case ASM_ALIGN_VECTOR:
+ case ASM_PROG_VECTOR:
+ case ASM_FLOAT_VECTOR:
+ case ASM_DEC_VECTOR:
+ case ASM_SYS_VECTOR:
+ case ASM_TRACE_VECTOR:
+ case ASM_PERFMON_VECTOR:
+ return 1;
+ case ASM_IMISS_VECTOR: /* fall through */
+ case ASM_DLMISS_VECTOR:
+ case ASM_DSMISS_VECTOR:
+ return 0;
+ case ASM_ADDR_VECTOR: /* fall through */
+ case ASM_SYSMGMT_VECTOR:
+ return 1;
+ case ASM_ITM_VECTOR:
+ return 0;
+ }
+ return 0;
+}
+
+#endif /* 60x style cpu types */
+
+int ppc_vector_is_valid(rtems_vector vector)
+{
+ switch (current_ppc_cpu) {
+#if defined(PPC_HAS_60X_VECTORS)
+ case PPC_7400:
+ if ( altivec_vector_is_valid(vector) )
+ return 1;
+ /* else fall thru */
+ case PPC_750:
+ if (!mpc750_vector_is_valid(vector)) {
+ return 0;
+ }
+ break;
+ case PPC_7455: /* Kate Feng */
+ case PPC_7457:
+ if ( altivec_vector_is_valid(vector) )
+ return 1;
+ /* else fall thru */
+ case PPC_604:
+ case PPC_604e:
+ case PPC_604r:
+ if (!mpc604_vector_is_valid(vector)) {
+ return 0;
+ }
+ break;
+ case PPC_603:
+ case PPC_603e:
+ case PPC_603le:
+ case PPC_603ev:
+ case PPC_8260:
+ /* case PPC_8240: -- same value as 8260 */
+ case PPC_8245:
+ if (!mpc603_vector_is_valid(vector)) {
+ return 0;
+ }
+ break;
+ case PPC_PSIM:
+ if (!PSIM_vector_is_valid(vector)) {
+ return 0;
+ }
+ break;
+#endif
+#if ( defined(mpc860) || defined(mpc821) )
+ case PPC_860:
+ if (!mpc860_vector_is_valid(vector)) {
+ return 0;
+ }
+ break;
+#endif
+#if defined(ppc405)
+ case PPC_405:
+ if (!ppc405_vector_is_valid(vector)) {
+ return 0;
+ }
+ break;
+#endif
+ default:
+ printk("Please complete "
+ "libcpu/powerpc/new-exceptions/raw_exception.c\n"
+ "current_ppc_cpu = %x\n", current_ppc_cpu);
+ return 0;
+ }
+ return 1;
+}
+
+int ppc_set_exception (const rtems_raw_except_connect_data* except)
+{
+ unsigned int level;
+
+ if (!ppc_vector_is_valid(except->exceptIndex)) {
+ printk("ppc_set_exception: vector %d is not valid\n",
+ except->exceptIndex);
+ return 0;
+ }
+ /*
+ * Check if default handler is actually connected. If not issue an error.
+ * You must first get the current handler via mpc60x_get_current_exception
+ * and then disconnect it using mpc60x_delete_exception.
+ * RATIONALE : to always have the same transition by forcing the user
+ * to get the previous handler before accepting to disconnect.
+ */
+
+ if (memcmp(ppc_get_vector_addr(except->exceptIndex),
+ (void*)default_raw_except_entry.hdl.raw_hdl,
+ default_raw_except_entry.hdl.raw_hdl_size)) {
+ printk("ppc_set_exception: raw vector not installed\n");
+ return 0;
+ }
+
+ _CPU_ISR_Disable(level);
+
+ raw_except_table [except->exceptIndex] = *except;
+ codemove((void*)ppc_get_vector_addr(except->exceptIndex),
+ except->hdl.raw_hdl,
+ except->hdl.raw_hdl_size,
+ PPC_CACHE_ALIGNMENT);
+ except->on(except);
+
+ _CPU_ISR_Enable(level);
+ return 1;
+}
+
+int ppc_get_current_exception (rtems_raw_except_connect_data* except)
+{
+ if (!ppc_vector_is_valid(except->exceptIndex)){
+ return 0;
+ }
+
+ *except = raw_except_table [except->exceptIndex];
+
+ return 1;
+}
+
+int ppc_delete_exception (const rtems_raw_except_connect_data* except)
+{
+ unsigned int level;
+
+ if (!ppc_vector_is_valid(except->exceptIndex)){
+ return 0;
+ }
+ /*
+ * Check if handler passed is actually connected. If not issue an error.
+ * You must first get the current handler via ppc_get_current_exception
+ * and then disconnect it using ppc_delete_exception.
+ * RATIONALE : to always have the same transition by forcing the user
+ * to get the previous handler before accepting to disconnect.
+ */
+ if (memcmp(ppc_get_vector_addr(except->exceptIndex),
+ (void*)except->hdl.raw_hdl,
+ except->hdl.raw_hdl_size)) {
+ return 0;
+ }
+ _CPU_ISR_Disable(level);
+
+ except->off(except);
+ codemove((void*)ppc_get_vector_addr(except->exceptIndex),
+ default_raw_except_entry.hdl.raw_hdl,
+ default_raw_except_entry.hdl.raw_hdl_size,
+ PPC_CACHE_ALIGNMENT);
+
+
+ raw_except_table[except->exceptIndex] = default_raw_except_entry;
+ raw_except_table[except->exceptIndex].exceptIndex = except->exceptIndex;
+
+ _CPU_ISR_Enable(level);
+
+ return 1;
+}
+
+/*
+ * Exception global init.
+ */
+int ppc_init_exceptions (rtems_raw_except_global_settings* config)
+{
+ unsigned i;
+ unsigned int level;
+
+ /*
+ * store various accelerators
+ */
+ raw_except_table = config->rawExceptHdlTbl;
+ local_settings = config;
+ default_raw_except_entry = config->defaultRawEntry;
+
+ _CPU_ISR_Disable(level);
+
+ for (i=0; i <= LAST_VALID_EXC; i++) {
+ if (!ppc_vector_is_valid(i)){
+ continue;
+ }
+ codemove((void*)ppc_get_vector_addr(i),
+ raw_except_table[i].hdl.raw_hdl,
+ raw_except_table[i].hdl.raw_hdl_size,
+ PPC_CACHE_ALIGNMENT);
+ if (raw_except_table[i].hdl.raw_hdl != default_raw_except_entry.hdl.raw_hdl) {
+ raw_except_table[i].on(&raw_except_table[i]);
+ }
+ else {
+ raw_except_table[i].off(&raw_except_table[i]);
+ }
+ }
+ _CPU_ISR_Enable(level);
+
+ return 1;
+}
+
+int ppc_get_exception_config (rtems_raw_except_global_settings** config)
+{
+ *config = local_settings;
+ return 1;
+}
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.h b/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.h
new file mode 100644
index 0000000000..1805484f8e
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/new-exceptions/raw_exception.h
@@ -0,0 +1,324 @@
+/*
+ * raw_execption.h
+ *
+ * This file contains implementation of C function to
+ * Instantiate 60x ppc primary exception entries.
+ * More detailed information can be found on motorola
+ * site and more precisely in the following book :
+ *
+ * MPC750
+ * Risc Microporcessor User's Manual
+ * Mtorola REF : MPC750UM/AD 8/97
+ *
+ * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
+ * Canon Centre Recherche France.
+ *
+ * Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
+ * to support 603, 603e, 604, 604e exceptions
+ *
+ * moved to "libcpu/powerpc/new-exceptions and consolidated
+ * by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>
+ * to be common for all PPCs with new excpetions
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _LIBCPU_RAW_EXCEPTION_H
+#define _LIBCPU_RAW_EXCEPTION_H
+
+#include <rtems/powerpc/powerpc.h>
+/*
+ * find out, whether we want to (re)enable the MMU in the assembly code
+ * FIXME: move this to a better location
+ */
+#if (defined(ppc403) || defined(ppc405))
+#define PPC_USE_MMU 0
+#else
+#define PPC_USE_MMU 1
+#endif
+
+/*
+ * Exception Vectors and offsets as defined in the MCP750 manual
+ * used by most PPCs
+ */
+
+#define ASM_RESET_VECTOR 0x01
+#define ASM_RESET_VECTOR_OFFSET (ASM_RESET_VECTOR << 8)
+
+#define ASM_MACH_VECTOR 0x02
+#define ASM_MACH_VECTOR_OFFSET (ASM_MACH_VECTOR << 8)
+
+#define ASM_PROT_VECTOR 0x03
+#define ASM_PROT_VECTOR_OFFSET (ASM_PROT_VECTOR << 8)
+
+#define ASM_ISI_VECTOR 0x04
+#define ASM_ISI_VECTOR_OFFSET (ASM_ISI_VECTOR << 8)
+
+#define ASM_EXT_VECTOR 0x05
+#define ASM_EXT_VECTOR_OFFSET (ASM_EXT_VECTOR << 8)
+
+#define ASM_ALIGN_VECTOR 0x06
+#define ASM_ALIGN_VECTOR_OFFSET (ASM_ALIGN_VECTOR << 8)
+
+#define ASM_PROG_VECTOR 0x07
+#define ASM_PROG_VECTOR_OFFSET (ASM_PROG_VECTOR << 8)
+
+#define ASM_FLOAT_VECTOR 0x08
+#define ASM_FLOAT_VECTOR_OFFSET (ASM_FLOAT_VECTOR << 8)
+
+#define ASM_DEC_VECTOR 0x09
+#define ASM_DEC_VECTOR_OFFSET (ASM_DEC_VECTOR << 8)
+
+/* Bummer: Altivec unavailable doesn't fit into this scheme... (0xf20).
+ * We'd like to avoid reserved vectors but OTOH we don't want to use
+ * just an available high number because tables (and copies) are of
+ * size LAST_VALID_EXC.
+ * So until there is a CPU that uses 0xA we'll just use that :-(
+ */
+#define ASM_VEC_VECTOR 0x0A
+#define ASM_VEC_VECTOR_OFFSET (0xf20)
+
+#define ASM_SYS_VECTOR 0x0C
+#define ASM_SYS_VECTOR_OFFSET (ASM_SYS_VECTOR << 8)
+
+#define ASM_TRACE_VECTOR 0x0D
+#define ASM_TRACE_VECTOR_OFFSET (ASM_TRACE_VECTOR << 8)
+
+#if defined(ppc405)
+ /*
+ * vectors for PPC405
+ */
+#define ASM_CRIT_VECTOR ASM_RESET_VECTOR
+#define ASM_CRIT_VECTOR_OFFSET (ASM_CRIT_VECTOR << 8)
+
+#define ASM_PIT_VECTOR 0x10
+#define ASM_PIT_VECTOR_OFFSET (ASM_PIT_VECTOR << 8)
+
+#define ASM_ITLBMISS_VECTOR 0x11
+#define ASM_ITLBMISS_VECTOR_OFFSET (ASM_ITLBMISS_VECTOR << 8)
+
+#define ASM_DTLBMISS_VECTOR 0x12
+#define ASM_DTLBMISS_VECTOR_OFFSET (ASM_DTLBMISS_VECTOR << 8)
+
+#define ASM_FIT_VECTOR 0x13
+#define ASM_FIT_VECTOR_OFFSET (0x1010)
+
+#define ASM_WDOG_VECTOR 0x14
+#define ASM_WDOG_VECTOR_OFFSET (0x1020)
+
+#define LAST_VALID_EXC ASM_WDOG_VECTOR
+
+/*
+ * bit mask of all exception vectors, that are handled
+ * as "critical" exsceptions (using SRR2/SRR3/rfci)
+ * this value will be evaluated in the default exception entry/exit
+ * code to determine, whether to use SRR0/SRR1/rfi or SRR2/SRR3/rfci
+ */
+#define ASM_VECTORS_CRITICAL \
+ (( 1 << (31-ASM_CRIT_VECTOR)) \
+ |(1 << (31-ASM_MACH_VECTOR)) \
+ |(1 << (31-ASM_WDOG_VECTOR)))
+
+#elif ( defined(mpc860) || defined(mpc821) )
+ /*
+ * vectors for MPC8xx
+ */
+
+/*
+ * FIXME: even more vector names might get used in common,
+ * but the names have diverged between different PPC families
+ */
+#define ASM_FLOATASSIST_VECTOR 0x0E
+#define ASM_FLOATASSIST_VECTOR_OFFSET (ASM_FLOATASSIST_VECTOR << 8)
+
+#define ASM_SOFTEMUL_VECTOR 0x10
+#define ASM_SOFTEMUL_VECTOR_OFFSET (ASM_SOFTEMUL_VECTOR << 8)
+
+#define ASM_ITLBMISS_VECTOR 0x11
+#define ASM_ITLBMISS_VECTOR_OFFSET (ASM_ITLBMISS_VECTOR << 8)
+
+#define ASM_DTLBMISS_VECTOR 0x12
+#define ASM_DTLBMISS_VECTOR_OFFSET (ASM_DTLBMISS_VECTOR << 8)
+
+#define ASM_ITLBERROR_VECTOR 0x13
+#define ASM_ITLBERROR_VECTOR_OFFSET (ASM_ITLBERROR_VECTOR << 8)
+
+#define ASM_DTLBERROR_VECTOR 0x14
+#define ASM_DTLBERROR_VECTOR_OFFSET (ASM_DTLBERROR_VECTOR << 8)
+
+#define ASM_DBREAK_VECTOR 0x1C
+#define ASM_DBREAK_VECTOR_OFFSET (ASM_DBREAK_VECTOR << 8)
+
+#define ASM_IBREAK_VECTOR 0x1D
+#define ASM_IBREAK_VECTOR_OFFSET (ASM_IBREAK_VECTOR << 8)
+
+#define ASM_PERIFBREAK_VECTOR 0x1E
+#define ASM_PERIFBREAK_VECTOR_OFFSET (ASM_PERIFBREAK_VECTOR << 8)
+
+#define ASM_DEVPORT_VECTOR 0x1F
+#define ASM_DEVPORT_VECTOR_OFFSET (ASM_DEVPORT_VECTOR_OFFSET << 8)
+
+#define LAST_VALID_EXC ASM_DEVPORT_VECTOR
+
+#elif (defined(mpc555) || defined(mpc505))
+ /*
+ * vectorx for MPC5xx
+ */
+#define ASM_FLOATASSIST_VECTOR 0x0E
+
+#define ASM_SOFTEMUL_VECTOR 0x10
+
+#define ASM_IPROT_VECTOR 0x13
+#define ASM_DPROT_VECTOR 0x14
+
+#define ASM_DBREAK_VECTOR 0x1C
+#define ASM_IBREAK_VECTOR 0x1D
+#define ASM_MEBREAK_VECTOR 0x1E
+#define ASM_NMEBREAK_VECTOR 0x1F
+
+#define LAST_VALID_EXC ASM_NMEBREAK_VECTOR
+
+#else /* 60x style cpu types */
+#define PPC_HAS_60X_VECTORS
+
+#define ASM_PERFMON_VECTOR 0x0F
+#define ASM_PERFMON_VECTOR_OFFSET (ASM_PERFMON_VECTOR << 8)
+
+#define ASM_IMISS_VECTOR 0x10
+
+#define ASM_DLMISS_VECTOR 0x11
+
+#define ASM_DSMISS_VECTOR 0x12
+
+#define ASM_ADDR_VECTOR 0x13
+#define ASM_ADDR_VECTOR_OFFSET (ASM_ADDR_VECTOR << 8)
+
+#define ASM_SYSMGMT_VECTOR 0x14
+#define ASM_SYSMGMT_VECTOR_OFFSET (ASM_SYSMGMT_VECTOR << 8)
+
+#define ASM_VEC_ASSIST_VECTOR 0x16
+#define ASM_VEC_ASSIST_VECTOR_OFFSET (ASM_VEC_ASSIST_VECTOR << 8)
+
+#define ASM_ITM_VECTOR 0x17
+#define ASM_ITM_VECTOR_OFFSET (ASM_ITM_VECTOR << 8)
+
+#define LAST_VALID_EXC ASM_ITM_VECTOR
+
+#endif
+
+ /*
+ * bits to be set in MSR in exception entry code
+ */
+#if ( PPC_HAS_RI) && ( PPC_USE_MMU)
+#define PPC_MSR_EXC_BITS (PPC_MSR_RI | PPC_MSR_DR | PPC_MSR_IR)
+#elif ( PPC_HAS_RI) && (!PPC_USE_MMU)
+#define PPC_MSR_EXC_BITS (PPC_MSR_RI)
+#elif (!PPC_HAS_RI) && ( PPC_USE_MMU)
+#define PPC_MSR_EXC_BITS ( PPC_MSR_DR | PPC_MSR_IR)
+#else
+#endif
+
+
+
+#ifndef ASM
+
+/*
+ * Type definition for raw exceptions.
+ */
+
+typedef unsigned char rtems_vector;
+struct __rtems_raw_except_connect_data__;
+typedef void (*rtems_raw_except_func) (void);
+typedef unsigned long rtems_raw_except_hdl_size;
+
+typedef struct {
+ rtems_vector vector;
+ rtems_raw_except_func raw_hdl;
+ rtems_raw_except_hdl_size raw_hdl_size;
+}rtems_raw_except_hdl;
+
+typedef void (*rtems_raw_except_enable) (const struct __rtems_raw_except_connect_data__*);
+typedef void (*rtems_raw_except_disable) (const struct __rtems_raw_except_connect_data__*);
+typedef int (*rtems_raw_except_is_enabled) (const struct __rtems_raw_except_connect_data__*);
+
+typedef struct __rtems_raw_except_connect_data__{
+ /*
+ * Exception vector (As defined in the manual)
+ */
+ rtems_vector exceptIndex;
+ /*
+ * Exception raw handler. See comment on handler properties below in function prototype.
+ */
+ rtems_raw_except_hdl hdl;
+ /*
+ * function for enabling raw exceptions. In order to be consistent
+ * with the fact that the raw connexion can defined in the
+ * libcpu library, this library should have no knowledge of
+ * board specific hardware to manage exceptions and thus the
+ * "on" routine must enable the except at processor level only.
+ *
+ */
+ rtems_raw_except_enable on;
+ /*
+ * function for disabling raw exceptions. In order to be consistent
+ * with the fact that the raw connexion can defined in the
+ * libcpu library, this library should have no knowledge of
+ * board specific hardware to manage exceptions and thus the
+ * "on" routine must disable the except both at device and PIC level.
+ *
+ */
+ rtems_raw_except_disable off;
+ /*
+ * function enabling to know what exception may currently occur
+ */
+ rtems_raw_except_is_enabled isOn;
+}rtems_raw_except_connect_data;
+
+typedef struct {
+ /*
+ * size of all the table fields (*Tbl) described below.
+ */
+ unsigned int exceptSize;
+ /*
+ * Default handler used when disconnecting exceptions.
+ */
+ rtems_raw_except_connect_data defaultRawEntry;
+ /*
+ * Table containing initials/current value.
+ */
+ rtems_raw_except_connect_data* rawExceptHdlTbl;
+}rtems_raw_except_global_settings;
+
+/*
+ * C callable function enabling to set up one raw idt entry
+ */
+extern int ppc_set_exception (const rtems_raw_except_connect_data*);
+
+/*
+ * C callable function enabling to get one current raw idt entry
+ */
+extern int ppc_get_current_exception (rtems_raw_except_connect_data*);
+
+/*
+ * C callable function enabling to remove one current raw idt entry
+ */
+extern int ppc_delete_exception (const rtems_raw_except_connect_data*);
+
+/*
+ * C callable function enabling to check if vector is valid
+ */
+extern int ppc_vector_is_valid(rtems_vector vector);
+
+/*
+ * Exception global init.
+ */
+extern int ppc_init_exceptions (rtems_raw_except_global_settings* config);
+extern int ppc_get_exception_config (rtems_raw_except_global_settings** config);
+
+# endif /* ASM */
+
+#endif
diff --git a/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.c b/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.c
new file mode 100644
index 0000000000..6a1f810cd0
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.c
@@ -0,0 +1,292 @@
+/* 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.
+ *
+ * Modifications for PPC405GP by Dennis Ehlin
+ *
+ */
+
+#include "ictrl.h"
+#include <rtems.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
+ */
+#if defined(ppc405)
+RTEMS_INLINE_ROUTINE void
+clr_exisr(uint32_t mask)
+{
+ asm volatile ("mtdcr 0xC0,%0"::"r" (mask));/*EXISR*/
+}
+
+/*
+ * get value of EXISR
+ */
+RTEMS_INLINE_ROUTINE uint32_t
+get_exisr(void)
+{
+ uint32_t val;
+
+ asm volatile ("mfdcr %0,0xC0":"=r" (val));/*EXISR*/
+ return val;
+}
+
+/*
+ * get value of EXIER
+ */
+RTEMS_INLINE_ROUTINE uint32_t
+get_exier(void)
+{
+ uint32_t val;
+ asm volatile ("mfdcr %0,0xC2":"=r" (val));/*EXIER*/
+ return val;
+}
+
+/*
+ * set value of EXIER
+ */
+RTEMS_INLINE_ROUTINE void
+set_exier(uint32_t val)
+{
+ asm volatile ("mtdcr 0xC2,%0"::"r" (val));/*EXIER*/
+}
+
+#else /* not ppc405 */
+
+RTEMS_INLINE_ROUTINE void
+clr_exisr(uint32_t mask)
+{
+ asm volatile ("mtdcr 0x40,%0"::"r" (mask));/*EXISR*/
+}
+
+/*
+ * get value of EXISR
+ */
+RTEMS_INLINE_ROUTINE uint32_t
+get_exisr(void)
+{
+ uint32_t val;
+
+ asm volatile ("mfdcr %0,0x40":"=r" (val));/*EXISR*/
+ return val;
+}
+
+/*
+ * get value of EXIER
+ */
+RTEMS_INLINE_ROUTINE uint32_t
+get_exier(void)
+{
+ uint32_t val;
+ asm volatile ("mfdcr %0,0x42":"=r" (val));/*EXIER*/
+ return val;
+}
+
+/*
+ * set value of EXIER
+ */
+RTEMS_INLINE_ROUTINE void
+set_exier(uint32_t val)
+{
+ asm volatile ("mtdcr 0x42,%0"::"r" (val));/*EXIER*/
+}
+#endif /* ppc405 */
+/*
+ * enable an external interrupt, make this interrupt consistent
+ */
+RTEMS_INLINE_ROUTINE void
+enable_ext_irq( uint32_t mask)
+{
+ uint32_t 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( uint32_t mask)
+{
+ uint32_t 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 Configuration Table, if any.
+ *
+ */
+void
+ictrl_spurious_handler(uint32_t 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 (rtems_cpu_configuration_get_spurious_handler()) {
+ rtems_cpu_configuration_get_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)
+{
+ uint32_t 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); too early to ack*/
+ handler = ictrl_vector_table[exvec];
+ if (handler) {
+ istat &= ~mask;
+ global_vec = exvec + PPC_IRQ_EXT_BASE;
+ (handler)(global_vec);
+ }
+ clr_exisr(mask);/* now we can ack*/
+ }
+ }
+ 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,
+ uint32_t 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/irq/ictrl.h b/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.h
new file mode 100644
index 0000000000..4370788108
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/irq/ictrl.h
@@ -0,0 +1,95 @@
+/* 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.
+ *
+ * Modifications for PPC405GP by Dennis Ehlin
+ *
+ */
+
+
+#ifndef _ICTRL_H
+#define _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 */
+#ifndef ppc405
+#define PPC_EXI_MASK 0x0FFFFFFF
+#else /* ppc405 */
+#define PPC_EXI_MASK 0xFFFFFFFF
+#endif /* ppc405 */
+
+#ifndef ppc405
+#define PPC_IRQ_EXT_SPIR (PPC_IRQ_EXT_BASE+4)
+#define PPC_IRQ_EXT_SPIT (PPC_IRQ_EXT_BASE+5)
+#else /* ppc405 */
+#define PPC_IRQ_EXT_UART0 (PPC_IRQ_EXT_BASE+0)
+#define PPC_IRQ_EXT_UART1 (PPC_IRQ_EXT_BASE+1)
+#endif /* ppc405 */
+#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,
+ uint32_t vector,
+ rtems_isr_entry *old_handler
+);
+/*
+ * activate the interrupt controller
+ */
+rtems_status_code
+ictrl_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ICTRL_H */
+/* end of include file */