summaryrefslogtreecommitdiffstats
path: root/bsps
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-23 09:50:39 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-23 15:18:44 +0200
commit8f8ccee0d9e1c3adfb1de484f26f6d9f6ff08708 (patch)
tree5dc76f7a4527b0a500fbf5ee91486b2780e47a1a /bsps
parentbsps: Move SPI drivers to bsps (diff)
downloadrtems-8f8ccee0d9e1c3adfb1de484f26f6d9f6ff08708.tar.bz2
bsps: Move interrupt controller support to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'bsps')
-rw-r--r--bsps/arm/beagle/irq/irq.c144
-rw-r--r--bsps/arm/csb336/irq/irq.c51
-rw-r--r--bsps/arm/csb337/irq/irq.c56
-rw-r--r--bsps/arm/edb7312/irq/bsp_irq_asm.S323
-rw-r--r--bsps/arm/edb7312/irq/irq.c180
-rw-r--r--bsps/arm/gdbarmsim/irq/irq-dispatch.c50
-rw-r--r--bsps/arm/gdbarmsim/irq/irq.c71
-rw-r--r--bsps/arm/gumstix/irq/irq.c51
-rw-r--r--bsps/arm/lpc176x/irq/irq.c75
-rw-r--r--bsps/arm/lpc24xx/irq/irq-dispatch.c50
-rw-r--r--bsps/arm/lpc24xx/irq/irq.c120
-rwxr-xr-xbsps/arm/lpc32xx/irq/irq.c344
-rw-r--r--bsps/arm/raspberrypi/irq/irq.c168
-rw-r--r--bsps/arm/rtl22xx/irq/irq.c70
-rw-r--r--bsps/arm/shared/irq/irq-armv7m.c67
-rw-r--r--bsps/arm/shared/irq/irq-dispatch-armv7m.c32
-rw-r--r--bsps/arm/shared/irq/irq-gic.c180
-rw-r--r--bsps/arm/smdk2410/irq/irq.c45
-rw-r--r--bsps/arm/tms570/irq/irq.c202
-rw-r--r--bsps/epiphany/epiphany_sim/irq/irq.c64
-rw-r--r--bsps/i386/shared/irq/elcr.c170
-rw-r--r--bsps/i386/shared/irq/elcr.h37
-rw-r--r--bsps/i386/shared/irq/idt.c381
-rw-r--r--bsps/i386/shared/irq/irq.c405
-rw-r--r--bsps/i386/shared/irq/irq_asm.S268
-rw-r--r--bsps/i386/shared/irq/irq_init.c191
-rw-r--r--bsps/lm32/shared/irq/irq.c30
-rw-r--r--bsps/m68k/genmcf548x/irq/intc-icr-init-values.c29
-rw-r--r--bsps/m68k/genmcf548x/irq/irq.c229
-rw-r--r--bsps/mips/csb350/irq/vectorisrs.c168
-rw-r--r--bsps/mips/hurricane/irq/vectorisrs.c58
-rw-r--r--bsps/mips/jmr3904/irq/vectorisrs.c47
-rw-r--r--bsps/mips/malta/irq/interruptmask.c36
-rw-r--r--bsps/mips/malta/irq/vectorisrs.c90
-rw-r--r--bsps/mips/rbtx4925/irq/vectorisrs.c64
-rw-r--r--bsps/mips/rbtx4938/irq/vectorisrs.c64
-rw-r--r--bsps/mips/shared/irq/exception.S661
-rw-r--r--bsps/mips/shared/irq/i8259.c332
-rw-r--r--bsps/mips/shared/irq/interruptmask.c29
-rw-r--r--bsps/mips/shared/irq/interruptmask_TX49.c29
-rw-r--r--bsps/mips/shared/irq/irq.c101
-rw-r--r--bsps/mips/shared/irq/vectorexceptions.c81
-rw-r--r--bsps/or1k/generic_or1k/irq/irq.c43
-rw-r--r--bsps/powerpc/beatnik/irq/discovery_pic.c993
-rw-r--r--bsps/powerpc/beatnik/irq/irq_init.c110
-rw-r--r--bsps/powerpc/beatnik/irq/irq_test_app.c164
-rw-r--r--bsps/powerpc/gen5200/irq/irq.c722
-rw-r--r--bsps/powerpc/gen83xx/irq/irq.c596
-rw-r--r--bsps/powerpc/haleakala/irq/irq.c237
-rw-r--r--bsps/powerpc/haleakala/irq/irq_init.c96
-rw-r--r--bsps/powerpc/mpc8260ads/irq/irq.c372
-rw-r--r--bsps/powerpc/mvme3100/irq/irq_init.c138
-rw-r--r--bsps/powerpc/mvme5500/README.irq20
-rw-r--r--bsps/powerpc/mvme5500/irq/BSP_irq.c483
-rw-r--r--bsps/powerpc/mvme5500/irq/irq_init.c148
-rw-r--r--bsps/powerpc/psim/irq/irq_init.c125
-rw-r--r--bsps/powerpc/qemuppc/irq/irq_init.c61
-rw-r--r--bsps/powerpc/qoriq/irq/irq.c387
-rw-r--r--bsps/powerpc/shared/irq/i8259.c149
-rw-r--r--bsps/powerpc/shared/irq/irq_init.c364
-rw-r--r--bsps/powerpc/shared/irq/openpic.c622
-rw-r--r--bsps/powerpc/shared/irq/openpic_i8259_irq.c331
-rw-r--r--bsps/powerpc/t32mppc/irq/irq.c41
-rw-r--r--bsps/powerpc/tqm8xx/irq/irq.c231
-rw-r--r--bsps/powerpc/virtex/irq/irq_init.c167
-rw-r--r--bsps/powerpc/virtex4/irq/irq_init.c326
-rw-r--r--bsps/powerpc/virtex5/irq/irq_init.c343
-rw-r--r--bsps/riscv/riscv_generic/irq/irq.c60
68 files changed, 13172 insertions, 0 deletions
diff --git a/bsps/arm/beagle/irq/irq.c b/bsps/arm/beagle/irq/irq.c
new file mode 100644
index 0000000000..2fa1a5b0f0
--- /dev/null
+++ b/bsps/arm/beagle/irq/irq.c
@@ -0,0 +1,144 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ * @ingroup arm_beagle
+ *
+ * @brief Interrupt support.
+ */
+
+/*
+ * Copyright (c) 2014 Ben Gras <beng@shrike-systems.com>. All rights reserved.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/irq-generic.h>
+#include <bsp/linker-symbols.h>
+#include <bsp/fatal.h>
+
+#include <rtems/score/armv4.h>
+
+#include <libcpu/arm-cp15.h>
+
+struct omap_intr
+{
+ uint32_t base;
+ int size;
+};
+
+#if IS_DM3730
+static struct omap_intr omap_intr = {
+ .base = OMAP3_DM37XX_INTR_BASE,
+ .size = 0x1000,
+};
+#endif
+
+#if IS_AM335X
+static struct omap_intr omap_intr = {
+ .base = OMAP3_AM335X_INTR_BASE,
+ .size = 0x1000,
+};
+#endif
+
+/* Enables interrupts at the Interrupt Controller side. */
+static inline void omap_irq_ack(void)
+{
+ mmio_write(omap_intr.base + OMAP3_INTCPS_CONTROL, OMAP3_INTR_NEWIRQAGR);
+
+ /* Flush data cache to make sure all the previous writes are done
+ before re-enabling interrupts. */
+ flush_data_cache();
+}
+
+void bsp_interrupt_dispatch(void)
+{
+ const uint32_t reg = mmio_read(omap_intr.base + OMAP3_INTCPS_SIR_IRQ);
+
+ if ((reg & OMAP3_INTR_SPURIOUSIRQ_MASK) != OMAP3_INTR_SPURIOUSIRQ_MASK) {
+ const rtems_vector_number irq = reg & OMAP3_INTR_ACTIVEIRQ_MASK;
+
+ bsp_interrupt_handler_dispatch(irq);
+ } else {
+ /* Ignore spurious interrupts. We'll still ACK it so new interrupts
+ can be generated. */
+ }
+
+ omap_irq_ack();
+}
+
+/* There are 4 32-bit interrupt mask registers for a total of 128 interrupts.
+ The IRQ number tells us which register to use. */
+static uint32_t omap_get_mir_reg(rtems_vector_number vector, uint32_t *const mask)
+{
+ uint32_t mir_reg;
+
+ /* Select which bit to set/clear in the MIR register. */
+ *mask = 1ul << (vector % 32u);
+
+ if (vector < 32u) {
+ mir_reg = OMAP3_INTCPS_MIR0;
+ } else if (vector < 64u) {
+ mir_reg = OMAP3_INTCPS_MIR1;
+ } else if (vector < 96u) {
+ mir_reg = OMAP3_INTCPS_MIR2;
+ } else if (vector < 128u) {
+ mir_reg = OMAP3_INTCPS_MIR3;
+ } else {
+ /* Invalid IRQ number. This should never happen. */
+ bsp_fatal(0);
+ }
+
+ return mir_reg;
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ uint32_t mask, cur;
+ uint32_t mir_reg = omap_get_mir_reg(vector, &mask);
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ cur = mmio_read(omap_intr.base + mir_reg);
+ mmio_write(omap_intr.base + mir_reg, cur & ~mask);
+ flush_data_cache();
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ uint32_t mask, cur;
+ uint32_t mir_reg = omap_get_mir_reg(vector, &mask);
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ cur = mmio_read(omap_intr.base + mir_reg);
+ mmio_write(omap_intr.base + mir_reg, cur | mask);
+ flush_data_cache();
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ int i;
+ uint32_t intc_ilrx;
+
+ /* AM335X TRM 6.2.1 Initialization Sequence */
+ mmio_write(omap_intr.base + OMAP3_INTCPS_SYSCONFIG, OMAP3_SYSCONFIG_AUTOIDLE);
+ mmio_write(omap_intr.base + OMAP3_INTCPS_IDLE, 0);
+ /* priority 0 to all IRQs */
+ for(intc_ilrx = 0x100; intc_ilrx <= 0x2fc; intc_ilrx += 4) {
+ mmio_write(omap_intr.base + intc_ilrx, 0);
+ }
+
+ /* Mask all interrupts */
+ for(i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; i++)
+ bsp_interrupt_vector_disable(i);
+
+ /* Install generic interrupt handler */
+ arm_cp15_set_exception_handler(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt);
+ arm_cp15_set_vector_base_address(bsp_vector_table_begin);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/arm/csb336/irq/irq.c b/bsps/arm/csb336/irq/irq.c
new file mode 100644
index 0000000000..e5887b9717
--- /dev/null
+++ b/bsps/arm/csb336/irq/irq.c
@@ -0,0 +1,51 @@
+/*
+ * Motorola MC9328MXL Interrupt handler
+ *
+ * Copyright (c) 2010 embedded brains GmbH.
+ *
+ * Copyright (c) 2004 by Jay Monkman <jtm@lopingdog.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+#include <mc9328mxl.h>
+
+void bsp_interrupt_dispatch(void)
+{
+
+ rtems_vector_number vector = MC9328MXL_AITC_NIVECSR >> 16;
+
+ bsp_interrupt_handler_dispatch(vector);
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if (vector < MC9328MXL_NUM_INTS)
+ MC9328MXL_AITC_INTENNUM = vector;
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if (vector < MC9328MXL_NUM_INTS)
+ MC9328MXL_AITC_INTDISNUM = vector;
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+
+ _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/arm/csb337/irq/irq.c b/bsps/arm/csb337/irq/irq.c
new file mode 100644
index 0000000000..95e93845b9
--- /dev/null
+++ b/bsps/arm/csb337/irq/irq.c
@@ -0,0 +1,56 @@
+/*
+ * Atmel AT91RM9200 Interrupt handler
+ *
+ * Copyright (c) 2010 embedded brains GmbH.
+ *
+ * Copyright (c) 2004 by Jay Monkman <jtm@lopingdog.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+#include <at91rm9200.h>
+
+void bsp_interrupt_dispatch(void)
+{
+ rtems_vector_number vector = AIC_CTL_REG(AIC_IVR);
+
+ bsp_interrupt_handler_dispatch(vector);
+
+ AIC_CTL_REG(AIC_EOICR) = 0;
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ AIC_CTL_REG(AIC_IECR) = 1 << vector;
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ AIC_CTL_REG(AIC_IDCR) = 1 << vector;
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ unsigned long i = 0;
+
+ for (i = 0; i < 32; ++i) {
+ AIC_SVR_REG(i<<2) = i;
+ }
+
+ /* disable all interrupts */
+ AIC_CTL_REG(AIC_IDCR) = 0xffffffff;
+
+ _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/arm/edb7312/irq/bsp_irq_asm.S b/bsps/arm/edb7312/irq/bsp_irq_asm.S
new file mode 100644
index 0000000000..c48466967b
--- /dev/null
+++ b/bsps/arm/edb7312/irq/bsp_irq_asm.S
@@ -0,0 +1,323 @@
+/*
+ * Cirrus EP7312 Intererrupt handler
+ */
+
+/*
+ * Copyright (c) 2002 by Jay Monkman <jtm@smoothsmoothie.com>
+ *
+ * Copyright (c) 2002 by Charlie Steader <charlies@poliac.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+*/
+
+#define __asm__
+#include <bsp.h>
+#include <bsp/irq.h>
+
+ .extern edb7312_interrupt_dispatch
+
+/*
+ * Function to obtain, execute an IT handler and acknowledge the IT
+ */
+
+ .globl bsp_interrupt_dispatch
+bsp_interrupt_dispatch :
+/*
+ * Look at interrupt status register to determine source.
+ * From source, determine offset into expanded vector table
+ * and load handler address into r0.
+ */
+
+ ldr r1, =0x80000000 /* close to interrupt status/mask registers 1 */
+ ldr r2, =0x80001000 /* close to interrupt status/mask registers 2 */
+ ldr r3, =0x80002000 /* close to interrupt status/mask registers 3 */
+
+ stmdb sp!,{r4, r5, r6}
+
+/*
+ * INTSR3
+ */
+check_dai:
+ ldr r4, [r3, #0x240]
+ ldr r5, [r3, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+ tst r6, #0x0001
+ beq check_extfiq
+ mov r0, #BSP_DAIINT
+ b get_handler
+
+/*
+ * INTSR1
+ */
+check_extfiq:
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+ tst r6, #0x0001
+ beq check_bl
+ mov r0, #BSP_EXTFIQ
+ b get_handler
+
+check_bl:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0002
+ beq check_we
+ mov r0, #BSP_BLINT
+ b get_handler
+
+check_we:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0004
+ beq check_mc
+ mov r0, #BSP_WEINT
+ b get_handler
+
+check_mc:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0008
+ beq check_cs
+ mov r0, #BSP_MCINT
+ b get_handler
+
+check_cs:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0010
+ beq check_e1
+ mov r0, #BSP_CSINT
+ b get_handler
+
+check_e1:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0020
+ beq check_e2
+ mov r0, #BSP_EINT1
+ b get_handler
+
+check_e2:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0040
+ beq check_e3
+ mov r0, #BSP_EINT2
+ b get_handler
+
+check_e3:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0080
+ beq check_tc1
+ mov r0, #BSP_EINT3
+ b get_handler
+
+check_tc1:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0100
+ beq check_tc2
+ mov r0, #BSP_TC1OI
+ b get_handler
+
+check_tc2:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0200
+ beq check_rtc
+ mov r0, #BSP_TC2OI
+ b get_handler
+
+check_rtc:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0400
+ beq check_tick
+ mov r0, #BSP_RTCMI
+ b get_handler
+
+check_tick:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0800
+ beq check_utx1
+ mov r0, #BSP_TINT
+ b get_handler
+
+check_utx1:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x1000
+ beq check_urx1
+ mov r0, #BSP_UTXINT1
+ b get_handler
+
+check_urx1:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x2000
+ beq check_ums
+ mov r0, #BSP_URXINT1
+ b get_handler
+
+check_ums:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x4000
+ beq check_sse
+ mov r0, #BSP_UMSINT
+ b get_handler
+
+check_sse:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r1, #0x240]
+ ldr r5, [r1, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x8000
+ beq check_kbd
+ mov r0, #BSP_SSEOTI
+ b get_handler
+
+/*
+ * INTSR2
+ */
+check_kbd:
+ ldr r4, [r2, #0x240]
+ ldr r5, [r2, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+ tst r6, #0x0001
+ beq check_ss2rx
+ mov r0, #BSP_KBDINT
+ b get_handler
+
+check_ss2rx:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r2, #0x240]
+ ldr r5, [r2, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0002
+ beq check_ss2tx
+ mov r0, #BSP_SS2RX
+ b get_handler
+
+check_ss2tx:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r2, #0x240]
+ ldr r5, [r2, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x0004
+ beq check_utx2
+ mov r0, #BSP_SS2TX
+ b get_handler
+
+check_utx2:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r2, #0x240]
+ ldr r5, [r2, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x1000
+ beq check_urx2
+ mov r0, #BSP_UTXINT2
+ b get_handler
+
+check_urx2:
+#if 0
+MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES
+ ldr r4, [r2, #0x240]
+ ldr r5, [r2, #0x280]
+ and r6, r4, r5 /* only look at interrupts which are enabled */
+#endif
+ tst r6, #0x2000
+ beq IRQ_NoInterrupt
+ mov r0, #BSP_URXINT2
+ b get_handler
+
+get_handler:
+
+ ldmia sp!,{r4, r5, r6}
+
+ /*
+ * re-enable interrupts at processor level as the current
+ * interrupt source is now masked via VEGA logic
+ */
+/*
+ mrs r1, cpsr
+ and r1, r1, #0xFFFFFF3F
+ msr cpsr, r1
+*/
+
+ stmdb sp!,{lr}
+ bl edb7312_interrupt_dispatch
+ ldmia sp!,{lr}
+
+IRQ_NoInterrupt:
+ /* return to the "main" interrupt handler */
+ mov pc, lr
diff --git a/bsps/arm/edb7312/irq/irq.c b/bsps/arm/edb7312/irq/irq.c
new file mode 100644
index 0000000000..1d9151a1bd
--- /dev/null
+++ b/bsps/arm/edb7312/irq/irq.c
@@ -0,0 +1,180 @@
+/*
+ * Cirrus EP7312 Intererrupt handler
+ */
+
+/*
+ * Copyright (c) 2010 embedded brains GmbH.
+ *
+ * Copyright (c) 2002 by Jay Monkman <jtm@smoothsmoothie.com>
+ *
+ * Copyright (c) 2002 by Charlie Steader <charlies@poliac.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+*/
+
+#include <rtems/score/armv4.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+#include <ep7312.h>
+
+void edb7312_interrupt_dispatch(rtems_vector_number vector)
+{
+ bsp_interrupt_handler_dispatch(vector);
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if(vector >= BSP_EXTFIQ && vector <= BSP_SSEOTI)
+ {
+ /* interrupt managed by INTMR1 and INTSR1 */
+ *EP7312_INTMR1 |= (1 << vector);
+ }
+ else if(vector >= BSP_KBDINT && vector <= BSP_SS2TX)
+ {
+ /* interrupt managed by INTMR2 and INTSR2 */
+ *EP7312_INTMR2 |= (1 << (vector - 16));
+ }
+ else if(vector >= BSP_UTXINT2 && vector <= BSP_URXINT2)
+ {
+ /* interrupt managed by INTMR2 and INTSR2 */
+ *EP7312_INTMR2 |= (1 << (vector - 7));
+ }
+ else if(vector == BSP_DAIINT)
+ {
+ /* interrupt managed by INTMR3 and INTSR3 */
+ *EP7312_INTMR3 |= (1 << (vector - 21));
+ }
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if(vector >= BSP_EXTFIQ && vector <= BSP_SSEOTI)
+ {
+ /* interrupt managed by INTMR1 and INTSR1 */
+ *EP7312_INTMR1 &= ~(1 << vector);
+ }
+ else if(vector >= BSP_KBDINT && vector <= BSP_SS2TX)
+ {
+ /* interrupt managed by INTMR2 and INTSR2 */
+ *EP7312_INTMR2 &= ~(1 << (vector - 16));
+ }
+ else if(vector >= BSP_UTXINT2 && vector <= BSP_URXINT2)
+ {
+ /* interrupt managed by INTMR2 and INTSR2 */
+ *EP7312_INTMR2 &= ~(1 << (vector - 7));
+ }
+ else if(vector == BSP_DAIINT)
+ {
+ /* interrupt managed by INTMR3 and INTSR3 */
+ *EP7312_INTMR3 &= ~(1 << (vector - 21));
+ }
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ uint32_t int_stat = 0;
+
+ /* mask all interrupts */
+ *EP7312_INTMR1 = 0x0;
+ *EP7312_INTMR2 = 0x0;
+ *EP7312_INTMR3 = 0x0;
+
+ /* clear all pending interrupt status' */
+ int_stat = *EP7312_INTSR1;
+ if(int_stat & EP7312_INTR1_EXTFIQ)
+ {
+ }
+ if(int_stat & EP7312_INTR1_BLINT)
+ {
+ *EP7312_BLEOI = 0xFFFFFFFF;
+ }
+ if(int_stat & EP7312_INTR1_WEINT)
+ {
+ *EP7312_TEOI = 0xFFFFFFFF;
+ }
+ if(int_stat & EP7312_INTR1_MCINT)
+ {
+ }
+ if(int_stat & EP7312_INTR1_CSINT)
+ {
+ *EP7312_COEOI = 0xFFFFFFFF;
+ }
+ if(int_stat & EP7312_INTR1_EINT1)
+ {
+ }
+ if(int_stat & EP7312_INTR1_EINT2)
+ {
+ }
+ if(int_stat & EP7312_INTR1_EINT3)
+ {
+ }
+ if(int_stat & EP7312_INTR1_TC1OI)
+ {
+ *EP7312_TC1EOI = 0xFFFFFFFF;
+ }
+ if(int_stat & EP7312_INTR1_TC2OI)
+ {
+ *EP7312_TC2EOI = 0xFFFFFFFF;
+ }
+ if(int_stat & EP7312_INTR1_RTCMI)
+ {
+ *EP7312_RTCEOI = 0xFFFFFFFF;
+ }
+ if(int_stat & EP7312_INTR1_TINT)
+ {
+ *EP7312_TEOI = 0xFFFFFFFF;
+ }
+ if(int_stat & EP7312_INTR1_URXINT1)
+ {
+ }
+ if(int_stat & EP7312_INTR1_UTXINT1)
+ {
+ }
+ if(int_stat & EP7312_INTR1_UMSINT)
+ {
+ *EP7312_UMSEOI = 0xFFFFFFFF;
+ }
+ if(int_stat & EP7312_INTR1_SSEOTI)
+ {
+ *EP7312_SYNCIO;
+ }
+ int_stat = *EP7312_INTSR1;
+
+ int_stat = *EP7312_INTSR2;
+ if(int_stat & EP7312_INTR2_KBDINT)
+ {
+ *EP7312_KBDEOI = 0xFFFFFFFF;
+ }
+ if(int_stat & EP7312_INTR2_SS2RX)
+ {
+ }
+ if(int_stat & EP7312_INTR2_SS2TX)
+ {
+ }
+ if(int_stat & EP7312_INTR2_URXINT2)
+ {
+ }
+ if(int_stat & EP7312_INTR2_UTXINT2)
+ {
+ }
+ int_stat = *EP7312_INTSR2;
+
+ int_stat = *EP7312_INTSR3;
+ if(int_stat & EP7312_INTR2_DAIINT)
+ {
+ }
+ int_stat = *EP7312_INTSR3;
+
+ _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/arm/gdbarmsim/irq/irq-dispatch.c b/bsps/arm/gdbarmsim/irq/irq-dispatch.c
new file mode 100644
index 0000000000..f045fb8149
--- /dev/null
+++ b/bsps/arm/gdbarmsim/irq/irq-dispatch.c
@@ -0,0 +1,50 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief GDB ARM Simulator interrupt support.
+ */
+
+/*
+ * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+#ifdef ARM_MULTILIB_ARCH_V4
+
+void bsp_interrupt_dispatch(void)
+{
+ /* Read current vector number */
+ /* rtems_vector_number vector = VICVectAddr; */
+ rtems_vector_number vector = 0;
+
+ /* Enable interrupts in program status register */
+ uint32_t psr = _ARMV4_Status_irq_enable();
+
+ /* Dispatch interrupt handlers */
+ bsp_interrupt_handler_dispatch(vector);
+
+ /* Restore program status register */
+ _ARMV4_Status_restore(psr);
+
+ /* Acknowledge interrupt */
+ //VICVectAddr = 0;
+}
+
+#endif /* ARM_MULTILIB_ARCH_V4 */
diff --git a/bsps/arm/gdbarmsim/irq/irq.c b/bsps/arm/gdbarmsim/irq/irq.c
new file mode 100644
index 0000000000..886f928d2d
--- /dev/null
+++ b/bsps/arm/gdbarmsim/irq/irq.c
@@ -0,0 +1,71 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief GDB ARM Simulator interrupt support.
+ */
+
+/*
+ * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+#include <rtems/score/armv7m.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/linker-symbols.h>
+
+/*
+ * Prototypes
+ */
+void lpc24xx_irq_set_priority(rtems_vector_number, unsigned);
+unsigned lpc24xx_irq_get_priority(rtems_vector_number);
+
+static inline bool lpc24xx_irq_is_valid(rtems_vector_number vector)
+{
+ return vector <= BSP_INTERRUPT_VECTOR_MAX;
+}
+
+void lpc24xx_irq_set_priority(rtems_vector_number vector, unsigned priority)
+{
+}
+
+unsigned lpc24xx_irq_get_priority(rtems_vector_number vector)
+{
+ return 0; /* bogus value to avoid warning */
+}
+
+#ifdef ARM_MULTILIB_ARCH_V4
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ /* Install the IRQ exception handler */
+ _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+#endif /* ARM_MULTILIB_ARCH_V4 */
diff --git a/bsps/arm/gumstix/irq/irq.c b/bsps/arm/gumstix/irq/irq.c
new file mode 100644
index 0000000000..425795b165
--- /dev/null
+++ b/bsps/arm/gumstix/irq/irq.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010 embedded brains GmbH.
+ *
+ * PXA255 Interrupt handler by Yang Xi <hiyangxi@gmail.com>
+ * Copyright (c) 2004 by Jay Monkman <jtm@lopingdog.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+#include <pxa255.h>
+
+void bsp_interrupt_dispatch(void)
+{
+ rtems_vector_number vector = 31 - __builtin_clz(XSCALE_INT_ICIP);
+
+ bsp_interrupt_handler_dispatch(vector);
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ XSCALE_INT_ICMR |= 1 << vector;
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ XSCALE_INT_ICMR &= ~(1 << vector);
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ /* disable all interrupts */
+ XSCALE_INT_ICMR = 0x0;
+
+ /* Direct the interrupt to IRQ*/
+ XSCALE_INT_ICLR = 0x0;
+
+ /* Install the IRQ exception handler */
+ _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/arm/lpc176x/irq/irq.c b/bsps/arm/lpc176x/irq/irq.c
new file mode 100644
index 0000000000..e05fd59e6c
--- /dev/null
+++ b/bsps/arm/lpc176x/irq/irq.c
@@ -0,0 +1,75 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief LPC176X interrupt support.
+ */
+
+/*
+ * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+#include <rtems/score/armv7m.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/lpc176x.h>
+#include <bsp/linker-symbols.h>
+
+/**
+ * @brief Checks if the current interrupt vector length is valid or not.
+ *
+ * @param vector The current interrupt vector length.
+ * @return TRUE if valid.
+ * FALSE otherwise.
+ */
+static inline bool lpc176x_irq_is_valid( const rtems_vector_number vector )
+{
+ return vector <= BSP_INTERRUPT_VECTOR_MAX;
+}
+
+void lpc176x_irq_set_priority(
+ const rtems_vector_number vector,
+ unsigned priority
+)
+{
+ if ( lpc176x_irq_is_valid( vector ) ) {
+ if ( priority > LPC176X_IRQ_PRIORITY_VALUE_MAX ) {
+ priority = LPC176X_IRQ_PRIORITY_VALUE_MAX;
+ }
+
+ /* else implies that the priority is unlocked. Also,
+ there is nothing to do. */
+
+ _ARMV7M_NVIC_Set_priority( (int) vector, (int) ( priority << 3u ) );
+ }
+
+ /* else implies that the rtems vector number is invalid. Also,
+ there is nothing to do. */
+}
+
+unsigned lpc176x_irq_get_priority( const rtems_vector_number vector )
+{
+ unsigned priority;
+
+ if ( lpc176x_irq_is_valid( vector ) ) {
+ priority = (unsigned) ( _ARMV7M_NVIC_Get_priority( (int) vector ) >> 3u );
+ } else {
+ priority = LPC176X_IRQ_PRIORITY_VALUE_MIN - 1u;
+ }
+
+ return priority;
+}
diff --git a/bsps/arm/lpc24xx/irq/irq-dispatch.c b/bsps/arm/lpc24xx/irq/irq-dispatch.c
new file mode 100644
index 0000000000..66d05fdf9d
--- /dev/null
+++ b/bsps/arm/lpc24xx/irq/irq-dispatch.c
@@ -0,0 +1,50 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief LPC24XX interrupt support.
+ */
+
+/*
+ * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/lpc24xx.h>
+
+#ifdef ARM_MULTILIB_ARCH_V4
+
+void bsp_interrupt_dispatch(void)
+{
+ /* Read current vector number */
+ rtems_vector_number vector = VICVectAddr;
+
+ /* Enable interrupts in program status register */
+ uint32_t psr = _ARMV4_Status_irq_enable();
+
+ /* Dispatch interrupt handlers */
+ bsp_interrupt_handler_dispatch(vector);
+
+ /* Restore program status register */
+ _ARMV4_Status_restore(psr);
+
+ /* Acknowledge interrupt */
+ VICVectAddr = 0;
+}
+
+#endif /* ARM_MULTILIB_ARCH_V4 */
diff --git a/bsps/arm/lpc24xx/irq/irq.c b/bsps/arm/lpc24xx/irq/irq.c
new file mode 100644
index 0000000000..7801c37843
--- /dev/null
+++ b/bsps/arm/lpc24xx/irq/irq.c
@@ -0,0 +1,120 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief LPC24XX interrupt support.
+ */
+
+/*
+ * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+#include <rtems/score/armv7m.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/lpc24xx.h>
+#include <bsp/linker-symbols.h>
+
+static inline bool lpc24xx_irq_is_valid(rtems_vector_number vector)
+{
+ return vector <= BSP_INTERRUPT_VECTOR_MAX;
+}
+
+void lpc24xx_irq_set_priority(rtems_vector_number vector, unsigned priority)
+{
+ if (lpc24xx_irq_is_valid(vector)) {
+ if (priority > LPC24XX_IRQ_PRIORITY_VALUE_MAX) {
+ priority = LPC24XX_IRQ_PRIORITY_VALUE_MAX;
+ }
+
+ #ifdef ARM_MULTILIB_ARCH_V4
+ VICVectPriorityBase [vector] = priority;
+ #else
+ _ARMV7M_NVIC_Set_priority((int) vector, (int) (priority << 3));
+ #endif
+ }
+}
+
+unsigned lpc24xx_irq_get_priority(rtems_vector_number vector)
+{
+ if (lpc24xx_irq_is_valid(vector)) {
+ #ifdef ARM_MULTILIB_ARCH_V4
+ return VICVectPriorityBase [vector];
+ #else
+ return (unsigned) (_ARMV7M_NVIC_Get_priority((int) vector) >> 3);
+ #endif
+ } else {
+ return LPC24XX_IRQ_PRIORITY_VALUE_MIN - 1U;
+ }
+}
+
+#ifdef ARM_MULTILIB_ARCH_V4
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ VICIntEnable = 1U << vector;
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ VICIntEnClear = 1U << vector;
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ volatile uint32_t *addr = VICVectAddrBase;
+ volatile uint32_t *prio = VICVectPriorityBase;
+ rtems_vector_number i = 0;
+
+ /* Disable all interrupts */
+ VICIntEnClear = 0xffffffff;
+
+ /* Clear all software interrupts */
+ VICSoftIntClear = 0xffffffff;
+
+ /* Use IRQ category */
+ VICIntSelect = 0;
+
+ for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) {
+ /* Use the vector address register to store the vector number */
+ addr [i] = i;
+
+ /* Give vector lowest priority */
+ prio [i] = 15;
+ }
+
+ /* Reset priority mask register */
+ VICSWPrioMask = 0xffff;
+
+ /* Acknowledge interrupts for all priorities */
+ for (
+ i = LPC24XX_IRQ_PRIORITY_VALUE_MIN;
+ i <= LPC24XX_IRQ_PRIORITY_VALUE_MAX;
+ ++i
+ ) {
+ VICVectAddr = 0;
+ }
+
+ /* Install the IRQ exception handler */
+ _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+#endif /* ARM_MULTILIB_ARCH_V4 */
diff --git a/bsps/arm/lpc32xx/irq/irq.c b/bsps/arm/lpc32xx/irq/irq.c
new file mode 100755
index 0000000000..eac320000b
--- /dev/null
+++ b/bsps/arm/lpc32xx/irq/irq.c
@@ -0,0 +1,344 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_interrupt
+ *
+ * @brief Interrupt support.
+ */
+
+/*
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/lpc32xx.h>
+#include <bsp/linker-symbols.h>
+#include <bsp/mmu.h>
+
+/*
+ * Mask out SIC 1 and 2 IRQ request. There is no need to mask out the FIQ,
+ * since a pending FIQ would be a fatal error. The default handler will be
+ * invoked in this case.
+ */
+#define LPC32XX_MIC_STATUS_MASK (~0x3U)
+
+typedef union {
+ struct {
+ uint32_t mic;
+ uint32_t sic_1;
+ uint32_t sic_2;
+ } field;
+ uint32_t fields_table [LPC32XX_IRQ_MODULE_COUNT];
+} lpc32xx_irq_fields;
+
+static uint8_t lpc32xx_irq_priority_table [LPC32XX_IRQ_COUNT];
+
+static lpc32xx_irq_fields lpc32xx_irq_priority_masks [LPC32XX_IRQ_PRIORITY_COUNT];
+
+static lpc32xx_irq_fields lpc32xx_irq_enable;
+
+static inline bool lpc32xx_irq_priority_is_valid(unsigned priority)
+{
+ return priority <= LPC32XX_IRQ_PRIORITY_LOWEST;
+}
+
+#define LPC32XX_IRQ_BIT_OPS_DEFINE \
+ unsigned bit = index & 0x1fU; \
+ unsigned module = index >> 5
+
+#define LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE \
+ LPC32XX_IRQ_BIT_OPS_DEFINE; \
+ unsigned module_offset = module << 14; \
+ volatile uint32_t *reg = (volatile uint32_t *) \
+ ((volatile char *) &lpc32xx.mic + module_offset + register_offset)
+
+#define LPC32XX_IRQ_OFFSET_ER 0U
+#define LPC32XX_IRQ_OFFSET_RSR 4U
+#define LPC32XX_IRQ_OFFSET_SR 8U
+#define LPC32XX_IRQ_OFFSET_APR 12U
+#define LPC32XX_IRQ_OFFSET_ATR 16U
+#define LPC32XX_IRQ_OFFSET_ITR 20U
+
+static inline bool lpc32xx_irq_is_bit_set_in_register(unsigned index, unsigned register_offset)
+{
+ LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE;
+
+ return *reg & (1U << bit);
+}
+
+static inline void lpc32xx_irq_set_bit_in_register(unsigned index, unsigned register_offset)
+{
+ LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE;
+
+ *reg |= 1U << bit;
+}
+
+static inline void lpc32xx_irq_clear_bit_in_register(unsigned index, unsigned register_offset)
+{
+ LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE;
+
+ *reg &= ~(1U << bit);
+}
+
+static inline void lpc32xx_irq_set_bit_in_field(unsigned index, lpc32xx_irq_fields *fields)
+{
+ LPC32XX_IRQ_BIT_OPS_DEFINE;
+
+ fields->fields_table [module] |= 1U << bit;
+}
+
+static inline void lpc32xx_irq_clear_bit_in_field(unsigned index, lpc32xx_irq_fields *fields)
+{
+ LPC32XX_IRQ_BIT_OPS_DEFINE;
+
+ fields->fields_table [module] &= ~(1U << bit);
+}
+
+static inline unsigned lpc32xx_irq_get_index(uint32_t val)
+{
+ ARM_SWITCH_REGISTERS;
+
+ __asm__ volatile (
+ ARM_SWITCH_TO_ARM
+ "clz %[val], %[val]\n"
+ "rsb %[val], %[val], #31\n"
+ ARM_SWITCH_BACK
+ : [val] "=r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT
+ : "[val]" (val)
+ );
+
+ return val;
+}
+
+void lpc32xx_irq_set_priority(rtems_vector_number vector, unsigned priority)
+{
+ if (bsp_interrupt_is_valid_vector(vector)) {
+ rtems_interrupt_level level;
+ unsigned i = 0;
+
+ if (priority > LPC32XX_IRQ_PRIORITY_LOWEST) {
+ priority = LPC32XX_IRQ_PRIORITY_LOWEST;
+ }
+
+ lpc32xx_irq_priority_table [vector] = (uint8_t) priority;
+
+ for (i = LPC32XX_IRQ_PRIORITY_HIGHEST; i <= priority; ++i) {
+ rtems_interrupt_disable(level);
+ lpc32xx_irq_clear_bit_in_field(vector, &lpc32xx_irq_priority_masks [i]);
+ rtems_interrupt_enable(level);
+ }
+
+ for (i = priority + 1; i <= LPC32XX_IRQ_PRIORITY_LOWEST; ++i) {
+ rtems_interrupt_disable(level);
+ lpc32xx_irq_set_bit_in_field(vector, &lpc32xx_irq_priority_masks [i]);
+ rtems_interrupt_enable(level);
+ }
+ }
+}
+
+unsigned lpc32xx_irq_get_priority(rtems_vector_number vector)
+{
+ if (bsp_interrupt_is_valid_vector(vector)) {
+ return lpc32xx_irq_priority_table [vector];
+ } else {
+ return LPC32XX_IRQ_PRIORITY_LOWEST;
+ }
+}
+
+void lpc32xx_irq_set_activation_polarity(rtems_vector_number vector, lpc32xx_irq_activation_polarity activation_polarity)
+{
+ if (bsp_interrupt_is_valid_vector(vector)) {
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ if (activation_polarity == LPC32XX_IRQ_ACTIVE_HIGH_OR_RISING_EDGE) {
+ lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_APR);
+ } else {
+ lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_APR);
+ }
+ rtems_interrupt_enable(level);
+ }
+}
+
+lpc32xx_irq_activation_polarity lpc32xx_irq_get_activation_polarity(rtems_vector_number vector)
+{
+ if (bsp_interrupt_is_valid_vector(vector)) {
+ if (lpc32xx_irq_is_bit_set_in_register(vector, LPC32XX_IRQ_OFFSET_APR)) {
+ return LPC32XX_IRQ_ACTIVE_HIGH_OR_RISING_EDGE;
+ } else {
+ return LPC32XX_IRQ_ACTIVE_LOW_OR_FALLING_EDGE;
+ }
+ } else {
+ return LPC32XX_IRQ_ACTIVE_LOW_OR_FALLING_EDGE;
+ }
+}
+
+void lpc32xx_irq_set_activation_type(rtems_vector_number vector, lpc32xx_irq_activation_type activation_type)
+{
+ if (bsp_interrupt_is_valid_vector(vector)) {
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ if (activation_type == LPC32XX_IRQ_EDGE_SENSITIVE) {
+ lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ATR);
+ } else {
+ lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ATR);
+ }
+ rtems_interrupt_enable(level);
+ }
+}
+
+lpc32xx_irq_activation_type lpc32xx_irq_get_activation_type(rtems_vector_number vector)
+{
+ if (bsp_interrupt_is_valid_vector(vector)) {
+ if (lpc32xx_irq_is_bit_set_in_register(vector, LPC32XX_IRQ_OFFSET_ATR)) {
+ return LPC32XX_IRQ_EDGE_SENSITIVE;
+ } else {
+ return LPC32XX_IRQ_LEVEL_SENSITIVE;
+ }
+ } else {
+ return LPC32XX_IRQ_LEVEL_SENSITIVE;
+ }
+}
+
+void bsp_interrupt_dispatch(void)
+{
+ uint32_t status = lpc32xx.mic.sr & LPC32XX_MIC_STATUS_MASK;
+ uint32_t er_mic = lpc32xx.mic.er;
+ uint32_t er_sic_1 = lpc32xx.sic_1.er;
+ uint32_t er_sic_2 = lpc32xx.sic_2.er;
+ uint32_t psr = 0;
+ lpc32xx_irq_fields *masks = NULL;
+ rtems_vector_number vector = 0;
+ unsigned priority = 0;
+
+ if (status != 0) {
+ vector = lpc32xx_irq_get_index(status);
+ } else {
+ status = lpc32xx.sic_1.sr;
+ if (status != 0) {
+ vector = lpc32xx_irq_get_index(status) + LPC32XX_IRQ_MODULE_SIC_1;
+ } else {
+ status = lpc32xx.sic_2.sr;
+ if (status != 0) {
+ vector = lpc32xx_irq_get_index(status) + LPC32XX_IRQ_MODULE_SIC_2;
+ } else {
+ return;
+ }
+ }
+ }
+
+ priority = lpc32xx_irq_priority_table [vector];
+
+ masks = &lpc32xx_irq_priority_masks [priority];
+
+ lpc32xx.mic.er = er_mic & masks->field.mic;
+ lpc32xx.sic_1.er = er_sic_1 & masks->field.sic_1;
+ lpc32xx.sic_2.er = er_sic_2 & masks->field.sic_2;
+
+ psr = _ARMV4_Status_irq_enable();
+
+ bsp_interrupt_handler_dispatch(vector);
+
+ _ARMV4_Status_restore(psr);
+
+ lpc32xx.mic.er = er_mic & lpc32xx_irq_enable.field.mic;
+ lpc32xx.sic_1.er = er_sic_1 & lpc32xx_irq_enable.field.sic_1;
+ lpc32xx.sic_2.er = er_sic_2 & lpc32xx_irq_enable.field.sic_2;
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ rtems_interrupt_level level;
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ rtems_interrupt_disable(level);
+ lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ER);
+ lpc32xx_irq_set_bit_in_field(vector, &lpc32xx_irq_enable);
+ rtems_interrupt_enable(level);
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ rtems_interrupt_level level;
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ rtems_interrupt_disable(level);
+ lpc32xx_irq_clear_bit_in_field(vector, &lpc32xx_irq_enable);
+ lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ER);
+ rtems_interrupt_enable(level);
+}
+
+void lpc32xx_set_exception_handler(
+ Arm_symbolic_exception_name exception,
+ void (*handler)(void)
+)
+{
+ if ((unsigned) exception < MAX_EXCEPTIONS) {
+ uint32_t *table = (uint32_t *) bsp_vector_table_begin + MAX_EXCEPTIONS;
+
+ table [exception] = (uint32_t) handler;
+
+ #ifndef LPC32XX_DISABLE_MMU
+ rtems_cache_flush_multiple_data_lines(table, 64);
+ rtems_cache_invalidate_multiple_instruction_lines(NULL, 64);
+ #endif
+ }
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ size_t i = 0;
+
+ /* Set default priority */
+ for (i = 0; i < LPC32XX_IRQ_COUNT; ++i) {
+ lpc32xx_irq_priority_table [i] = LPC32XX_IRQ_PRIORITY_LOWEST;
+ }
+
+ /* Enable SIC 1 and 2 at all priorities */
+ for (i = 0; i < LPC32XX_IRQ_PRIORITY_COUNT; ++i) {
+ lpc32xx_irq_priority_masks [i].field.mic = 0xc0000003;
+ }
+
+ /* Disable all interrupts except SIC 1 and 2 */
+ lpc32xx_irq_enable.field.sic_2 = 0x0;
+ lpc32xx_irq_enable.field.sic_1 = 0x0;
+ lpc32xx_irq_enable.field.mic = 0xc0000003;
+ lpc32xx.sic_1.er = 0x0;
+ lpc32xx.sic_2.er = 0x0;
+ lpc32xx.mic.er = 0xc0000003;
+
+ /* Set interrupt types to IRQ */
+ lpc32xx.mic.itr = 0x0;
+ lpc32xx.sic_1.itr = 0x0;
+ lpc32xx.sic_2.itr = 0x0;
+
+ /* Set interrupt activation polarities */
+ lpc32xx.mic.apr = 0x3ff0efe0;
+ lpc32xx.sic_1.apr = 0xfbd27184;
+ lpc32xx.sic_2.apr = 0x801810c0;
+
+ /* Set interrupt activation types */
+ lpc32xx.mic.atr = 0x0;
+ lpc32xx.sic_1.atr = 0x26000;
+ lpc32xx.sic_2.atr = 0x0;
+
+ lpc32xx_set_exception_handler(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/arm/raspberrypi/irq/irq.c b/bsps/arm/raspberrypi/irq/irq.c
new file mode 100644
index 0000000000..5b10385bfe
--- /dev/null
+++ b/bsps/arm/raspberrypi/irq/irq.c
@@ -0,0 +1,168 @@
+/**
+ * @file irq.c
+ *
+ * @ingroup raspberrypi_interrupt
+ *
+ * @brief Interrupt support.
+ */
+
+/*
+ * Copyright (c) 2014 Andre Marques <andre.lousa.marques at gmail.com>
+ *
+ * Copyright (c) 2009
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * D-82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/raspberrypi.h>
+#include <bsp/linker-symbols.h>
+#include <bsp/mmu.h>
+#include <rtems/bspIo.h>
+#include <strings.h>
+
+#ifdef RTEMS_SMP
+#include <rtems/score/smp.h>
+#include <rtems/score/smpimpl.h>
+#endif
+
+typedef struct {
+ unsigned long enable_reg_addr;
+ unsigned long disable_reg_addr;
+} bcm2835_irq_ctrl_reg_t;
+
+static const bcm2835_irq_ctrl_reg_t bcm2835_irq_ctrl_reg_table[] = {
+ { BCM2835_IRQ_ENABLE1, BCM2835_IRQ_DISABLE1 },
+ { BCM2835_IRQ_ENABLE2, BCM2835_IRQ_DISABLE2 },
+ { BCM2835_IRQ_ENABLE_BASIC, BCM2835_IRQ_DISABLE_BASIC }
+};
+
+static inline const bcm2835_irq_ctrl_reg_t *
+bsp_vector_to_reg(rtems_vector_number vector)
+{
+ return bcm2835_irq_ctrl_reg_table + (vector >> 5);
+}
+
+static inline uint32_t
+bsp_vector_to_mask(rtems_vector_number vector)
+{
+ return 1 << (vector & 0x1f);
+}
+
+static const int bcm2835_irq_speedup_table[] =
+{
+ /* 0 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 0,
+ /* 1 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 1,
+ /* 2 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 2,
+ /* 3 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 3,
+ /* 4 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 4,
+ /* 5 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 5,
+ /* 6 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 6,
+ /* 7 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 7,
+ /* 8 */ -1, /* One or more bits set in pending register 1 */
+ /* 9 */ -2, /* One or more bits set in pending register 2 */
+ /* 10 */ 7, /* GPU IRQ 7 */
+ /* 11 */ 9, /* GPU IRQ 9 */
+ /* 12 */ 10, /* GPU IRQ 10 */
+ /* 13 */ 18, /* GPU IRQ 18 */
+ /* 14 */ 19, /* GPU IRQ 19 */
+ /* 15 */ 53, /* GPU IRQ 53 */
+ /* 16 */ 54, /* GPU IRQ 54 */
+ /* 17 */ 55, /* GPU IRQ 55 */
+ /* 18 */ 56, /* GPU IRQ 56 */
+ /* 19 */ 57, /* GPU IRQ 57 */
+ /* 20 */ 62, /* GPU IRQ 62 */
+};
+
+/*
+ * Define which basic peding register (BCM2835_IRQ_BASIC) bits
+ * should be processed through bcm2835_irq_speedup_table
+ */
+
+#define BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS 0x1ffcff
+
+/*
+ * Determine the source of the interrupt and dispatch the correct handler.
+ */
+void bsp_interrupt_dispatch(void)
+{
+ unsigned int pend;
+ unsigned int pend_bit;
+
+ rtems_vector_number vector = 255;
+
+#ifdef RTEMS_SMP
+ uint32_t cpu_index_self = _SMP_Get_current_processor();
+ uint32_t local_source = BCM2835_REG(BCM2836_IRQ_SOURCE_REG(cpu_index_self));
+
+ if ( local_source & BCM2836_IRQ_SOURCE_MBOX3 ) {
+ /* reset mailbox 3 contents to zero */
+ BCM2835_REG(BCM2836_MAILBOX_3_READ_CLEAR_BASE + 0x10 * cpu_index_self) = 0xffffffff;
+ _SMP_Inter_processor_interrupt_handler();
+ }
+ if ( cpu_index_self != 0 )
+ return;
+#endif /* RTEMS_SMP */
+
+ pend = BCM2835_REG(BCM2835_IRQ_BASIC);
+ if ( pend & BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS ) {
+ pend_bit = ffs(pend) - 1;
+ vector = bcm2835_irq_speedup_table[pend_bit];
+ } else {
+ pend = BCM2835_REG(BCM2835_IRQ_PENDING1);
+ if ( pend != 0 ) {
+ pend_bit = ffs(pend) - 1;
+ vector = pend_bit;
+ } else {
+ pend = BCM2835_REG(BCM2835_IRQ_PENDING2);
+ if ( pend != 0 ) {
+ pend_bit = ffs(pend) - 1;
+ vector = pend_bit + 32;
+ }
+ }
+ }
+
+ if ( vector < 255 )
+ {
+ bsp_interrupt_handler_dispatch(vector);
+ }
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ BCM2835_REG(bsp_vector_to_reg(vector)->enable_reg_addr) =
+ bsp_vector_to_mask(vector);
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ BCM2835_REG(bsp_vector_to_reg(vector)->disable_reg_addr) =
+ bsp_vector_to_mask(vector);
+}
+
+void bsp_interrupt_handler_default(rtems_vector_number vector)
+{
+ printk("spurious interrupt: %lu\n", vector);
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ BCM2835_REG(BCM2835_IRQ_DISABLE1) = 0xffffffff;
+ BCM2835_REG(BCM2835_IRQ_DISABLE2) = 0xffffffff;
+ BCM2835_REG(BCM2835_IRQ_DISABLE_BASIC) = 0xffffffff;
+ BCM2835_REG(BCM2835_IRQ_FIQ_CTRL) = 0;
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/arm/rtl22xx/irq/irq.c b/bsps/arm/rtl22xx/irq/irq.c
new file mode 100644
index 0000000000..83e140bd7b
--- /dev/null
+++ b/bsps/arm/rtl22xx/irq/irq.c
@@ -0,0 +1,70 @@
+/*
+ * Philps LPC22XX Interrupt handler
+ *
+ * Copyright (c) 2010 embedded brains GmbH.
+ *
+ * Copyright (c) 2006 by Ray<rayx.cn@gmail.com> to support LPC ARM
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+#include <lpc22xx.h>
+
+void bsp_interrupt_dispatch(void)
+{
+ rtems_vector_number vector = 31 - __builtin_clz(VICIRQStatus);
+
+ bsp_interrupt_handler_dispatch(vector);
+
+ VICVectAddr = 0;
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ VICIntEnable |= 1 << vector;
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ VICIntEnClr = 1 << vector;
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ volatile uint32_t *ctrl = (volatile uint32_t *) VICVectCntlBase;
+ size_t i = 0;
+
+ /* Disable all interrupts */
+ VICIntEnClr = 0xffffffff;
+
+ /* Use IRQ category */
+ VICIntSelect = 0;
+
+ /* Enable access in USER mode */
+ VICProtection = 0;
+
+ for (i = 0; i < 16; ++i) {
+ /* Disable vector mode */
+ ctrl [i] = 0;
+
+ /* Acknowledge interrupts for all priorities */
+ VICVectAddr = 0;
+ }
+
+ /* Acknowledge interrupts for all priorities */
+ VICVectAddr = 0;
+
+ /* Install the IRQ exception handler */
+ _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/arm/shared/irq/irq-armv7m.c b/bsps/arm/shared/irq/irq-armv7m.c
new file mode 100644
index 0000000000..99c0e373bf
--- /dev/null
+++ b/bsps/arm/shared/irq/irq-armv7m.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011-2012 Sebastian Huber. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <string.h>
+
+#include <rtems/score/armv7m.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/linker-symbols.h>
+#include <bsp/armv7m-irq.h>
+
+#ifdef ARM_MULTILIB_ARCH_V7M
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ _ARMV7M_NVIC_Set_enable((int) vector);
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ _ARMV7M_NVIC_Clear_enable((int) vector);
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ int i;
+ ARMV7M_Exception_handler *vector_table =
+ (ARMV7M_Exception_handler *) bsp_vector_table_begin;
+
+ if (bsp_vector_table_begin != bsp_start_vector_table_begin) {
+ memcpy(
+ vector_table,
+ bsp_start_vector_table_begin,
+ (size_t) bsp_vector_table_size
+ );
+ }
+
+ _ARMV7M_SCB->icsr = ARMV7M_SCB_ICSR_PENDSVCLR | ARMV7M_SCB_ICSR_PENDSTCLR;
+
+ for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) {
+ vector_table [ARMV7M_VECTOR_IRQ(i)] = _ARMV7M_NVIC_Interrupt_dispatch;
+ _ARMV7M_NVIC_Clear_enable(i);
+ _ARMV7M_NVIC_Clear_pending(i);
+ _ARMV7M_NVIC_Set_priority(i, BSP_ARMV7M_IRQ_PRIORITY_DEFAULT);
+ }
+
+ _ARMV7M_SCB->vtor = vector_table;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+#endif /* ARM_MULTILIB_ARCH_V7M */
diff --git a/bsps/arm/shared/irq/irq-dispatch-armv7m.c b/bsps/arm/shared/irq/irq-dispatch-armv7m.c
new file mode 100644
index 0000000000..c810a9784a
--- /dev/null
+++ b/bsps/arm/shared/irq/irq-dispatch-armv7m.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011-2012 Sebastian Huber. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv7m.h>
+
+#include <bsp/irq-generic.h>
+#include <bsp/armv7m-irq.h>
+
+#ifdef ARM_MULTILIB_ARCH_V7M
+
+void _ARMV7M_NVIC_Interrupt_dispatch(void)
+{
+ rtems_vector_number vector =
+ ARMV7M_SCB_ICSR_VECTACTIVE_GET(_ARMV7M_SCB->icsr);
+
+ _ARMV7M_Interrupt_service_enter();
+ bsp_interrupt_handler_dispatch(ARMV7M_IRQ_OF_VECTOR(vector));
+ _ARMV7M_Interrupt_service_leave();
+}
+
+#endif /* ARM_MULTILIB_ARCH_V7M */
diff --git a/bsps/arm/shared/irq/irq-gic.c b/bsps/arm/shared/irq/irq-gic.c
new file mode 100644
index 0000000000..ea4b6ef06a
--- /dev/null
+++ b/bsps/arm/shared/irq/irq-gic.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2013 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <info@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp/arm-gic.h>
+
+#include <rtems/score/armv4.h>
+
+#include <libcpu/arm-cp15.h>
+
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/start.h>
+
+#define GIC_CPUIF ((volatile gic_cpuif *) BSP_ARM_GIC_CPUIF_BASE)
+
+#define PRIORITY_DEFAULT 127
+
+void bsp_interrupt_dispatch(void)
+{
+ volatile gic_cpuif *cpuif = GIC_CPUIF;
+ uint32_t icciar = cpuif->icciar;
+ rtems_vector_number vector = GIC_CPUIF_ICCIAR_ACKINTID_GET(icciar);
+ rtems_vector_number spurious = 1023;
+
+ if (vector != spurious) {
+ uint32_t psr = _ARMV4_Status_irq_enable();
+
+ bsp_interrupt_handler_dispatch(vector);
+
+ _ARMV4_Status_restore(psr);
+
+ cpuif->icceoir = icciar;
+ }
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ volatile gic_dist *dist = ARM_GIC_DIST;
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ gic_id_enable(dist, vector);
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ volatile gic_dist *dist = ARM_GIC_DIST;
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ gic_id_disable(dist, vector);
+}
+
+static inline uint32_t get_id_count(volatile gic_dist *dist)
+{
+ uint32_t id_count = GIC_DIST_ICDICTR_IT_LINES_NUMBER_GET(dist->icdictr);
+
+ id_count = 32 * (id_count + 1);
+ id_count = id_count <= 1020 ? id_count : 1020;
+
+ return id_count;
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ volatile gic_cpuif *cpuif = GIC_CPUIF;
+ volatile gic_dist *dist = ARM_GIC_DIST;
+ uint32_t id_count = get_id_count(dist);
+ uint32_t id;
+
+ arm_cp15_set_exception_handler(
+ ARM_EXCEPTION_IRQ,
+ _ARMV4_Exception_interrupt
+ );
+
+ for (id = 0; id < id_count; id += 32) {
+ dist->icdicer[id / 32] = 0xffffffff;
+ }
+
+ for (id = 0; id < id_count; ++id) {
+ gic_id_set_priority(dist, id, PRIORITY_DEFAULT);
+ }
+
+ for (id = 32; id < id_count; ++id) {
+ gic_id_set_targets(dist, id, 0x01);
+ }
+
+ cpuif->iccpmr = GIC_CPUIF_ICCPMR_PRIORITY(0xff);
+ cpuif->iccbpr = GIC_CPUIF_ICCBPR_BINARY_POINT(0x0);
+ cpuif->iccicr = GIC_CPUIF_ICCICR_ENABLE;
+
+ dist->icddcr = GIC_DIST_ICDDCR_ENABLE;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+#ifdef RTEMS_SMP
+BSP_START_TEXT_SECTION void arm_gic_irq_initialize_secondary_cpu(void)
+{
+ volatile gic_cpuif *cpuif = GIC_CPUIF;
+ volatile gic_dist *dist = ARM_GIC_DIST;
+
+ while ((dist->icddcr & GIC_DIST_ICDDCR_ENABLE) == 0) {
+ /* Wait */
+ }
+
+ cpuif->iccpmr = GIC_CPUIF_ICCPMR_PRIORITY(0xff);
+ cpuif->iccbpr = GIC_CPUIF_ICCBPR_BINARY_POINT(0x0);
+ cpuif->iccicr = GIC_CPUIF_ICCICR_ENABLE;
+}
+#endif
+
+rtems_status_code arm_gic_irq_set_priority(
+ rtems_vector_number vector,
+ uint8_t priority
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+ if (bsp_interrupt_is_valid_vector(vector)) {
+ volatile gic_dist *dist = ARM_GIC_DIST;
+
+ gic_id_set_priority(dist, vector, priority);
+ } else {
+ sc = RTEMS_INVALID_ID;
+ }
+
+ return sc;
+}
+
+rtems_status_code arm_gic_irq_get_priority(
+ rtems_vector_number vector,
+ uint8_t *priority
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+ if (bsp_interrupt_is_valid_vector(vector)) {
+ volatile gic_dist *dist = ARM_GIC_DIST;
+
+ *priority = gic_id_get_priority(dist, vector);
+ } else {
+ sc = RTEMS_INVALID_ID;
+ }
+
+ return sc;
+}
+
+void bsp_interrupt_set_affinity(
+ rtems_vector_number vector,
+ const Processor_mask *affinity
+)
+{
+ volatile gic_dist *dist = ARM_GIC_DIST;
+ uint8_t targets = (uint8_t) _Processor_mask_To_uint32_t(affinity, 0);
+
+ gic_id_set_targets(dist, vector, targets);
+}
+
+void bsp_interrupt_get_affinity(
+ rtems_vector_number vector,
+ Processor_mask *affinity
+)
+{
+ volatile gic_dist *dist = ARM_GIC_DIST;
+ uint8_t targets = gic_id_get_targets(dist, vector);
+
+ _Processor_mask_From_uint32_t(affinity, targets, 0);
+}
diff --git a/bsps/arm/smdk2410/irq/irq.c b/bsps/arm/smdk2410/irq/irq.c
new file mode 100644
index 0000000000..ea8f610353
--- /dev/null
+++ b/bsps/arm/smdk2410/irq/irq.c
@@ -0,0 +1,45 @@
+/* irq.c
+ *
+ * This file contains the implementation of the function described in irq.h
+ *
+ * Copyright (c) 2010 embedded brains GmbH.
+ *
+ * CopyRight (C) 2000 Canon Research France SA.
+ * Emmanuel Raguet, mailto:raguet@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/armv4.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+#include <s3c24xx.h>
+
+void bsp_interrupt_dispatch(void)
+{
+ rtems_vector_number vector = *((uint32_t *) rINTOFFSET_ADDR);
+
+ bsp_interrupt_handler_dispatch(vector);
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/arm/tms570/irq/irq.c b/bsps/arm/tms570/irq/irq.c
new file mode 100644
index 0000000000..579c11ed2a
--- /dev/null
+++ b/bsps/arm/tms570/irq/irq.c
@@ -0,0 +1,202 @@
+/**
+ * @file irq.c
+ *
+ * @ingroup tms570
+ *
+ * @brief TMS570 interrupt support functions definitions.
+ */
+
+/*
+ * Copyright (c) 2014 Premysl Houdek <kom541000@gmail.com>
+ *
+ * Google Summer of Code 2014 at
+ * Czech Technical University in Prague
+ * Zikova 1903/4
+ * 166 36 Praha 6
+ * Czech Republic
+ *
+ * Based on LPC24xx and LPC1768 BSP
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/irq-generic.h>
+#include <bsp/tms570-vim.h>
+#include <bsp/irq.h>
+#include <rtems/score/armv4.h>
+
+unsigned int priorityTable[BSP_INTERRUPT_VECTOR_MAX+1];
+
+/**
+ * @brief Set priority of the interrupt vector.
+ *
+ * This function is here because of compability. It should set
+ * priority of the interrupt vector.
+ * @warning It does not set any priority at HW layer. It is nearly imposible to
+ * @warning set priority of the interrupt on TMS570 in a nice way.
+ * @param[in] vector vector of isr
+ * @param[in] priority new priority assigned to the vector
+ * @return Void
+ */
+void tms570_irq_set_priority(
+ rtems_vector_number vector,
+ unsigned priority
+)
+{
+ if ( bsp_interrupt_is_valid_vector(vector) ) {
+ priorityTable[vector] = priority;
+ }
+}
+
+/**
+ * @brief Gets priority of the interrupt vector.
+ *
+ * This function is here because of compability. It returns priority
+ * of the isr vector last set by tms570_irq_set_priority function.
+ *
+ * @warning It does not return any real priority of the HW layer.
+ * @param[in] vector vector of isr
+ * @retval 0 vector is invalid.
+ * @retval priority priority of the interrupt
+ */
+unsigned tms570_irq_get_priority(
+ rtems_vector_number vector
+)
+{
+ if ( bsp_interrupt_is_valid_vector(vector) ) {
+ return priorityTable[vector];
+ }
+ return 0;
+}
+
+/**
+ * @brief Interrupt dispatch
+ *
+ * Called by OS to determine which interrupt occured.
+ * Function passes control to interrupt handler.
+ *
+ * @return Void
+ */
+void bsp_interrupt_dispatch(void)
+{
+ rtems_vector_number vector = TMS570_VIM.IRQINDEX-1;
+
+ bsp_interrupt_handler_dispatch(vector);
+}
+
+/**
+ * @brief enables interrupt vector in the HW
+ *
+ * Enables HW interrupt for specified vector
+ *
+ * @param[in] vector vector of the isr which needs to be enabled.
+ * @retval RTEMS_INVALID_ID vector is invalid.
+ * @retval RTEMS_SUCCESSFUL interrupt source enabled.
+ */
+void bsp_interrupt_vector_enable(
+ rtems_vector_number vector
+)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ TMS570_VIM.REQENASET[vector >> 5] = 1 << (vector & 0x1f);
+}
+
+/**
+ * @brief disables interrupt vector in the HW
+ *
+ * Disables HW interrupt for specified vector
+ *
+ * @param[in] vector vector of the isr which needs to be disabled.
+ * @retval RTEMS_INVALID_ID vector is invalid.
+ * @retval RTEMS_SUCCESSFUL interrupt source disabled.
+ */
+void bsp_interrupt_vector_disable(
+ rtems_vector_number vector
+)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ TMS570_VIM.REQENACLR[vector >> 5] = 1 << (vector & 0x1f);
+}
+
+/**
+ * @brief Init function of interrupt module
+ *
+ * Resets vectored interrupt interface to default state.
+ * Disables all interrupts.
+ * Set all sources as IRQ (not FIR).
+ *
+ * @retval RTEMS_SUCCESSFUL All is set
+ */
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ void (**vim_vec)(void) = (void (**)(void)) 0xFFF82000;
+ unsigned int value = 0x00010203;
+ unsigned int i = 0;
+ uint32_t sctlr;
+
+ /* Disable interrupts */
+ for ( i = 0; i < 3; i++ ) {
+ TMS570_VIM.REQENACLR[i] = 0xffffffff;
+ }
+ /* Map default events on interrupt vectors */
+ for ( i = 0; i < 24; i += 1, value += 0x04040404) {
+ TMS570_VIM.CHANCTRL[i] = value;
+ }
+ /* Set all vectors as IRQ (not FIR) */
+ TMS570_VIM.FIRQPR[0] = 3;
+ TMS570_VIM.FIRQPR[1] = 0;
+ TMS570_VIM.FIRQPR[2] = 0;
+
+ /*
+ _CPU_ISR_install_vector(
+ ARM_EXCEPTION_IRQ,
+ _ARMV4_Exception_interrupt,
+ NULL
+ );
+
+ Call to setup of interrupt entry in CPU level exception vectors table
+ is not used (necessary/possible) because the table is provided
+ by c/src/lib/libbsp/arm/shared/start/start.S and POM overlay
+ solution remaps that to address zero.
+ */
+
+ for ( i = 0; i <= 94; ++i ) {
+ vim_vec[i] = _ARMV4_Exception_interrupt;
+ }
+ /* Clear bit VE in SCTLR register to not use VIM IRQ exception bypass*/
+ asm volatile ("mrc p15, 0, %0, c1, c0, 0\n": "=r" (sctlr));
+ /*
+ * Disable bypass of CPU level exception table for interrupt entry which
+ * can be provided by VIM hardware
+ */
+ sctlr &= ~(1 << 24);
+ #if 0
+ /*
+ * Option to enable exception table bypass for interrupts
+ *
+ * Because RTEMS requires all interrupts to be serviced through
+ * common _ARMV4_Exception_interrupt handler to allow task switching
+ * on exit from interrupt working correctly, vim_vec cannot point
+ * directly to individual vector handlers and need to point
+ * to single entry path. But if TMS570_VIM.IRQINDEX is then used
+ * to target execution to corresponding service then for some
+ * peripherals (i.e. EMAC) interrupt is already acknowledged
+ * by VIM and IRQINDEX is read as zero which leads to spurious
+ * interrupt and peripheral not serviced/blocked.
+ *
+ * To analyze this behavior we used trampolines which setup
+ * bsp_interrupt_vector_inject and pass execution to
+ * _ARMV4_Exception_interrupt. It works but is more ugly than
+ * use of POM remap for these cases where application does not
+ * start at address 0x00000000. If RTEMS image is placed at
+ * memory space beginning then no of these constructs is necessary.
+ */
+ sctlr |= 1 << 24;
+ #endif
+ asm volatile ("mcr p15, 0, %0, c1, c0, 0\n": : "r" (sctlr));
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/epiphany/epiphany_sim/irq/irq.c b/bsps/epiphany/epiphany_sim/irq/irq.c
new file mode 100644
index 0000000000..994e25bf0e
--- /dev/null
+++ b/bsps/epiphany/epiphany_sim/irq/irq.c
@@ -0,0 +1,64 @@
+/**
+ * @file
+ *
+ * @ingroup epiphany_interrupt
+ *
+ * @brief Interrupt support.
+ */
+
+/*
+ * Epiphany CPU Dependent Source
+ *
+ * Copyright (c) 2015 University of York.
+ * Hesham ALMatary <hmka501@york.ac.uk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+#include <rtems/inttypes.h>
+
+/* Almost all of the jobs that the following functions should
+ * do are implemented in cpukit
+ */
+
+void bsp_interrupt_handler_default(rtems_vector_number vector)
+{
+ printk("spurious interrupt: %" PRIdrtems_vector_number "\n", vector);
+}
+
+rtems_status_code bsp_interrupt_facility_initialize()
+{
+ return 0;
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+}
diff --git a/bsps/i386/shared/irq/elcr.c b/bsps/i386/shared/irq/elcr.c
new file mode 100644
index 0000000000..f72e36c33f
--- /dev/null
+++ b/bsps/i386/shared/irq/elcr.c
@@ -0,0 +1,170 @@
+/*-
+ * Copyright (c) 2004 John Baldwin <jhb@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef __rtems__
+__FBSDID("$FreeBSD$");
+#endif /* __rtems__ */
+
+/*
+ * The ELCR is a register that controls the trigger mode and polarity of
+ * EISA and ISA interrupts. In FreeBSD 3.x and 4.x, the ELCR was only
+ * consulted for determining the appropriate trigger mode of EISA
+ * interrupts when using an APIC. However, it seems that almost all
+ * systems that include PCI also include an ELCR that manages the ISA
+ * IRQs 0 through 15. Thus, we check for the presence of an ELCR on
+ * every machine by checking to see if the values found at bootup are
+ * sane. Note that the polarity of ISA and EISA IRQs are linked to the
+ * trigger mode. All edge triggered IRQs use active-hi polarity, and
+ * all level triggered interrupts use active-lo polarity.
+ *
+ * The format of the ELCR is simple: it is a 16-bit bitmap where bit 0
+ * controls IRQ 0, bit 1 controls IRQ 1, etc. If the bit is zero, the
+ * associated IRQ is edge triggered. If the bit is one, the IRQ is
+ * level triggered.
+ */
+
+#ifndef __rtems__
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <machine/intr_machdep.h>
+#endif /* __rtems__ */
+
+#ifdef __rtems__
+#include <bsp.h>
+#include "i386_io.h"
+#include <errno.h>
+#include "elcr.h"
+#endif /* __rtems__ */
+
+#define ELCR_PORT 0x4d0
+#define ELCR_MASK(irq) (1 << (irq))
+
+static int elcr_status;
+#ifdef __rtems__
+static
+#endif /* __rtems__ */
+int elcr_found;
+
+#ifdef __rtems__
+#undef printf
+#define printf printk
+#define bootverbose 1
+#define KASSERT(...)
+#endif /* __rtems__ */
+
+/*
+ * Check to see if we have what looks like a valid ELCR. We do this by
+ * verifying that IRQs 0, 1, 2, and 13 are all edge triggered.
+ */
+int
+elcr_probe(void)
+{
+ int i;
+
+ elcr_status = inb(ELCR_PORT) | inb(ELCR_PORT + 1) << 8;
+ if ((elcr_status & (ELCR_MASK(0) | ELCR_MASK(1) | ELCR_MASK(2) |
+ ELCR_MASK(8) | ELCR_MASK(13))) != 0)
+ return (ENXIO);
+ if (bootverbose) {
+ printf("ELCR Found. ISA IRQs programmed as:\n");
+ for (i = 0; i < 16; i++)
+ printf(" %2d", i);
+ printf("\n");
+ for (i = 0; i < 16; i++)
+ if (elcr_status & ELCR_MASK(i))
+ printf(" L");
+ else
+ printf(" E");
+ printf("\n");
+ }
+#ifndef __rtems__
+ if (resource_disabled("elcr", 0))
+ return (ENXIO);
+#endif /* __rtems__ */
+ elcr_found = 1;
+ return (0);
+}
+
+/*
+ * Returns 1 for level trigger, 0 for edge.
+ */
+enum intr_trigger
+elcr_read_trigger(u_int irq)
+{
+#ifdef __rtems__
+ if (!elcr_found)
+ return INTR_TRIGGER_EDGE;
+#endif /* __rtems__ */
+ KASSERT(elcr_found, ("%s: no ELCR was found!", __func__));
+ KASSERT(irq <= 15, ("%s: invalid IRQ %u", __func__, irq));
+ if (elcr_status & ELCR_MASK(irq))
+ return (INTR_TRIGGER_LEVEL);
+ else
+ return (INTR_TRIGGER_EDGE);
+}
+
+/*
+ * Set the trigger mode for a specified IRQ. Mode of 0 means edge triggered,
+ * and a mode of 1 means level triggered.
+ */
+void
+elcr_write_trigger(u_int irq, enum intr_trigger trigger)
+{
+ int new_status;
+
+#ifdef __rtems__
+ if (!elcr_found)
+ return;
+#endif /* __rtems__ */
+ KASSERT(elcr_found, ("%s: no ELCR was found!", __func__));
+ KASSERT(irq <= 15, ("%s: invalid IRQ %u", __func__, irq));
+ if (trigger == INTR_TRIGGER_LEVEL)
+ new_status = elcr_status | ELCR_MASK(irq);
+ else
+ new_status = elcr_status & ~ELCR_MASK(irq);
+ if (new_status == elcr_status)
+ return;
+ elcr_status = new_status;
+ if (irq >= 8)
+ outb(ELCR_PORT + 1, elcr_status >> 8);
+ else
+ outb(ELCR_PORT, elcr_status & 0xff);
+}
+
+void
+elcr_resume(void)
+{
+#ifdef __rtems__
+ if (!elcr_found)
+ return;
+#endif /* __rtems__ */
+
+ KASSERT(elcr_found, ("%s: no ELCR was found!", __func__));
+ outb(ELCR_PORT, elcr_status & 0xff);
+ outb(ELCR_PORT + 1, elcr_status >> 8);
+}
diff --git a/bsps/i386/shared/irq/elcr.h b/bsps/i386/shared/irq/elcr.h
new file mode 100644
index 0000000000..a006d4f149
--- /dev/null
+++ b/bsps/i386/shared/irq/elcr.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 Chris Johns <chrisj@rtems.org>
+ *
+ * Header for the FreeBSD ported elcr.c
+ */
+
+#ifndef _IRQ_ELCR_H_
+#define _IRQ_ELCR_H_
+
+#include <sys/cdefs.h>
+
+enum intr_trigger {
+ INTR_TRIGGER_EDGE,
+ INTR_TRIGGER_LEVEL
+};
+
+/*
+ * Check to see if we have what looks like a valid ELCR. We do this by
+ * verifying that IRQs 0, 1, 2, and 13 are all edge triggered.
+ */
+int elcr_probe(void);
+
+/*
+ * Returns 1 for level trigger, 0 for edge.
+ */
+enum intr_trigger elcr_read_trigger(u_int irq);
+
+/*
+ * Set the trigger mode for a specified IRQ. Mode of 0 means edge triggered,
+ * and a mode of 1 means level triggered.
+ */
+void elcr_write_trigger(u_int irq, enum intr_trigger trigger);
+
+void elcr_resume(void);
+
+
+#endif
diff --git a/bsps/i386/shared/irq/idt.c b/bsps/i386/shared/irq/idt.c
new file mode 100644
index 0000000000..d3adbc4f05
--- /dev/null
+++ b/bsps/i386/shared/irq/idt.c
@@ -0,0 +1,381 @@
+/*
+ * cpu.c - This file contains implementation of C function to
+ * instantiate IDT entries. More detailled information can be found
+ * on Intel site and more precisely in the following book :
+ *
+ * Pentium Processor family
+ * Developper's Manual
+ *
+ * Volume 3 : Architecture and Programming Manual
+ *
+ * Copyright (C) 1998 Eric Valette (valette@crf.canon.fr)
+ * Canon Centre Recherche France.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/score/cpu.h>
+#include <bsp/irq.h>
+#include <bsp/tblsizes.h>
+
+/*
+ * This locking is not enough if IDT is changed at runtime
+ * and entry can be changed for vector which is enabled
+ * at change time. But such use is broken anyway.
+ * Protect code only against concurrent changes.
+ * Even that is probably unnecessary if different
+ * entries are changed concurrently.
+ */
+RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_idt_access_lock, "rtems_idt_access_lock" );
+
+static rtems_raw_irq_connect_data* raw_irq_table;
+static rtems_raw_irq_connect_data default_raw_irq_entry;
+static interrupt_gate_descriptor default_idt_entry;
+static rtems_raw_irq_global_settings* local_settings;
+
+void create_interrupt_gate_descriptor (interrupt_gate_descriptor* idtEntry,
+ rtems_raw_irq_hdl hdl)
+{
+ idtEntry->low_offsets_bits = (((unsigned) hdl) & 0xffff);
+ idtEntry->segment_selector = i386_get_cs();
+ idtEntry->fixed_value_bits = 0;
+ idtEntry->gate_type = 0xe;
+ idtEntry->privilege = 0;
+ idtEntry->present = 1;
+ idtEntry->high_offsets_bits = ((((unsigned) hdl) >> 16) & 0xffff);
+}
+
+rtems_raw_irq_hdl get_hdl_from_vector(rtems_vector_offset index)
+{
+ uint32_t hdl;
+ interrupt_gate_descriptor* idt_entry_tbl;
+ unsigned limit;
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+ /* Convert limit into number of entries */
+ limit = (limit + 1) / sizeof(interrupt_gate_descriptor);
+
+ if(index >= limit) {
+ return 0;
+ }
+
+ hdl = (idt_entry_tbl[index].low_offsets_bits |
+ (idt_entry_tbl[index].high_offsets_bits << 16));
+ return (rtems_raw_irq_hdl) hdl;
+}
+
+int i386_set_idt_entry (const rtems_raw_irq_connect_data* irq)
+{
+ interrupt_gate_descriptor* idt_entry_tbl;
+ unsigned limit;
+ rtems_interrupt_lock_context lock_context;
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+ /* Convert limit into number of entries */
+ limit = (limit + 1) / sizeof(interrupt_gate_descriptor);
+
+ if (irq->idtIndex >= limit) {
+ return 0;
+ }
+ /*
+ * Check if default handler is actually connected. If not issue an error.
+ * You must first get the current handler via i386_get_current_idt_entry
+ * and then disconnect it using i386_delete_idt_entry.
+ * RATIONALE : to always have the same transition by forcing the user
+ * to get the previous handler before accepting to disconnect.
+ */
+ if (get_hdl_from_vector(irq->idtIndex) != default_raw_irq_entry.hdl) {
+ return 0;
+ }
+
+ rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context);
+
+ raw_irq_table [irq->idtIndex] = *irq;
+ create_interrupt_gate_descriptor (&idt_entry_tbl[irq->idtIndex], irq->hdl);
+ if (irq->on)
+ irq->on(irq);
+
+ rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context);
+ return 1;
+}
+
+void _CPU_ISR_install_vector (uint32_t vector,
+ proc_ptr hdl,
+ proc_ptr * oldHdl)
+{
+ interrupt_gate_descriptor* idt_entry_tbl;
+ unsigned limit;
+ interrupt_gate_descriptor new;
+ rtems_interrupt_lock_context lock_context;
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+ /* Convert limit into number of entries */
+ limit = (limit + 1) / sizeof(interrupt_gate_descriptor);
+
+ if (vector >= limit) {
+ return;
+ }
+ rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context);
+ * ((unsigned int *) oldHdl) = idt_entry_tbl[vector].low_offsets_bits |
+ (idt_entry_tbl[vector].high_offsets_bits << 16);
+
+ create_interrupt_gate_descriptor(&new, hdl);
+ idt_entry_tbl[vector] = new;
+
+ rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context);
+}
+
+int i386_get_current_idt_entry (rtems_raw_irq_connect_data* irq)
+{
+ interrupt_gate_descriptor* idt_entry_tbl;
+ unsigned limit;
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+ /* Convert limit into number of entries */
+ limit = (limit + 1) / sizeof(interrupt_gate_descriptor);
+
+ if (irq->idtIndex >= limit) {
+ return 0;
+ }
+ raw_irq_table [irq->idtIndex].hdl = get_hdl_from_vector(irq->idtIndex);
+
+ *irq = raw_irq_table [irq->idtIndex];
+
+ return 1;
+}
+
+int i386_delete_idt_entry (const rtems_raw_irq_connect_data* irq)
+{
+ interrupt_gate_descriptor* idt_entry_tbl;
+ unsigned limit;
+ rtems_interrupt_lock_context lock_context;
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+ /* Convert limit into number of entries */
+ limit = (limit + 1) / sizeof(interrupt_gate_descriptor);
+
+ if (irq->idtIndex >= limit) {
+ return 0;
+ }
+ /*
+ * Check if handler passed is actually connected. If not issue an error.
+ * You must first get the current handler via i386_get_current_idt_entry
+ * and then disconnect it using i386_delete_idt_entry.
+ * RATIONALE : to always have the same transition by forcing the user
+ * to get the previous handler before accepting to disconnect.
+ */
+ if (get_hdl_from_vector(irq->idtIndex) != irq->hdl){
+ return 0;
+ }
+ rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context);
+
+ idt_entry_tbl[irq->idtIndex] = default_idt_entry;
+
+ if (irq->off)
+ irq->off(irq);
+
+ raw_irq_table[irq->idtIndex] = default_raw_irq_entry;
+ raw_irq_table[irq->idtIndex].idtIndex = irq->idtIndex;
+
+ rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context);
+
+ return 1;
+}
+
+/*
+ * Caution this function assumes the IDTR has been already set.
+ */
+int i386_init_idt (rtems_raw_irq_global_settings* config)
+{
+ unsigned limit;
+ unsigned i;
+ rtems_interrupt_lock_context lock_context;
+ interrupt_gate_descriptor* idt_entry_tbl;
+
+ i386_get_info_from_IDTR (&idt_entry_tbl, &limit);
+
+ /* Convert limit into number of entries */
+ limit = (limit + 1) / sizeof(interrupt_gate_descriptor);
+
+ if (config->idtSize != limit) {
+ return 0;
+ }
+ /*
+ * store various accelarators
+ */
+ raw_irq_table = config->rawIrqHdlTbl;
+ local_settings = config;
+ default_raw_irq_entry = config->defaultRawEntry;
+
+ rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context);
+
+ create_interrupt_gate_descriptor (&default_idt_entry, default_raw_irq_entry.hdl);
+
+ for (i=0; i < limit; i++) {
+ interrupt_gate_descriptor new;
+ create_interrupt_gate_descriptor (&new, raw_irq_table[i].hdl);
+ idt_entry_tbl[i] = new;
+ if (raw_irq_table[i].hdl != default_raw_irq_entry.hdl) {
+ raw_irq_table[i].on(&raw_irq_table[i]);
+ }
+ else {
+ raw_irq_table[i].off(&raw_irq_table[i]);
+ }
+ }
+ rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context);
+
+ return 1;
+}
+
+int i386_get_idt_config (rtems_raw_irq_global_settings** config)
+{
+ *config = local_settings;
+ return 1;
+}
+
+uint32_t i386_raw_gdt_entry (uint16_t segment_selector_index,
+ segment_descriptors* sd)
+{
+ uint16_t gdt_limit;
+ uint16_t tmp_segment = 0;
+ segment_descriptors* gdt_entry_tbl;
+ uint8_t present;
+
+ i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit);
+
+ if (segment_selector_index >= (gdt_limit+1)/8) {
+ /* index to GDT table out of bounds */
+ return 0;
+ }
+ if (segment_selector_index == 0) {
+ /* index 0 is not usable */
+ return 0;
+ }
+
+ /* put prepared descriptor into the GDT */
+ present = sd->present;
+ sd->present = 0;
+ gdt_entry_tbl[segment_selector_index].present = 0;
+ RTEMS_COMPILER_MEMORY_BARRIER();
+ gdt_entry_tbl[segment_selector_index] = *sd;
+ RTEMS_COMPILER_MEMORY_BARRIER();
+ gdt_entry_tbl[segment_selector_index].present = present;
+ sd->present = present;
+ /*
+ * Now, reload all segment registers so that the possible changes takes effect.
+ */
+ __asm__ volatile( "movw %%ds,%0 ; movw %0,%%ds\n\t"
+ "movw %%es,%0 ; movw %0,%%es\n\t"
+ "movw %%fs,%0 ; movw %0,%%fs\n\t"
+ "movw %%gs,%0 ; movw %0,%%gs\n\t"
+ "movw %%ss,%0 ; movw %0,%%ss"
+ : "=r" (tmp_segment)
+ : "0" (tmp_segment)
+ );
+ return 1;
+}
+
+void i386_fill_segment_desc_base(uint32_t base,
+ segment_descriptors* sd)
+{
+ sd->base_address_15_0 = base & 0xffff;
+ sd->base_address_23_16 = (base >> 16) & 0xff;
+ sd->base_address_31_24 = (base >> 24) & 0xff;
+}
+
+void i386_fill_segment_desc_limit(uint32_t limit,
+ segment_descriptors* sd)
+{
+ sd->granularity = 0;
+ if (limit > 65535) {
+ sd->granularity = 1;
+ limit /= 4096;
+ }
+ sd->limit_15_0 = limit & 0xffff;
+ sd->limit_19_16 = (limit >> 16) & 0xf;
+}
+
+/*
+ * Caution this function assumes the GDTR has been already set.
+ */
+uint32_t i386_set_gdt_entry (uint16_t segment_selector_index, uint32_t base,
+ uint32_t limit)
+{
+ segment_descriptors gdt_entry;
+ memset(&gdt_entry, 0, sizeof(gdt_entry));
+
+ i386_fill_segment_desc_limit(limit, &gdt_entry);
+ i386_fill_segment_desc_base(base, &gdt_entry);
+ /*
+ * set up descriptor type (this may well becomes a parameter if needed)
+ */
+ gdt_entry.type = 2; /* Data R/W */
+ gdt_entry.descriptor_type = 1; /* Code or Data */
+ gdt_entry.privilege = 0; /* ring 0 */
+ gdt_entry.present = 1; /* not present */
+
+ /*
+ * Now, reload all segment registers so the limit takes effect.
+ */
+ return i386_raw_gdt_entry(segment_selector_index, &gdt_entry);
+}
+
+uint16_t i386_next_empty_gdt_entry ()
+{
+ uint16_t gdt_limit;
+ segment_descriptors* gdt_entry_tbl;
+ /* initial amount of filled descriptors */
+ static uint16_t segment_selector_index = NUM_SYSTEM_GDT_DESCRIPTORS - 1;
+
+ segment_selector_index += 1;
+ i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit);
+ if (segment_selector_index >= (gdt_limit+1)/8) {
+ return 0;
+ }
+ return segment_selector_index;
+}
+
+uint16_t i386_cpy_gdt_entry(uint16_t segment_selector_index,
+ segment_descriptors* struct_to_fill)
+{
+ uint16_t gdt_limit;
+ segment_descriptors* gdt_entry_tbl;
+
+ i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit);
+
+ if (segment_selector_index >= (gdt_limit+1)/8) {
+ return 0;
+ }
+
+ *struct_to_fill = gdt_entry_tbl[segment_selector_index];
+ return segment_selector_index;
+}
+
+segment_descriptors* i386_get_gdt_entry(uint16_t segment_selector_index)
+{
+ uint16_t gdt_limit;
+ segment_descriptors* gdt_entry_tbl;
+
+ i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit);
+
+ if (segment_selector_index >= (gdt_limit+1)/8) {
+ return 0;
+ }
+ return &gdt_entry_tbl[segment_selector_index];
+}
+
+uint32_t i386_limit_gdt_entry(segment_descriptors* gdt_entry)
+{
+ uint32_t lim = (gdt_entry->limit_15_0 + (gdt_entry->limit_19_16<<16));
+ if (gdt_entry->granularity) {
+ return lim*4096+4095;
+ }
+ return lim;
+}
diff --git a/bsps/i386/shared/irq/irq.c b/bsps/i386/shared/irq/irq.c
new file mode 100644
index 0000000000..ac08f1f7be
--- /dev/null
+++ b/bsps/i386/shared/irq/irq.c
@@ -0,0 +1,405 @@
+/*
+ * This file contains the implementation of the function described in irq.h
+ */
+
+/*
+ * Copyright (c) 2009 embedded brains GmbH
+ * Copyright (C) 1998 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <rtems/score/cpu.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+
+#include "elcr.h"
+
+RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_i8259_access_lock, "rtems_i8259_access_lock" );
+
+/*
+ * pointer to the mask representing the additionnal irq vectors
+ * that must be disabled when a particular entry is activated.
+ * They will be dynamically computed from teh prioruty table given
+ * in BSP_rtems_irq_mngt_set();
+ * CAUTION : this table is accessed directly by interrupt routine
+ * prologue.
+ */
+static rtems_i8259_masks irq_mask_or_tbl[BSP_IRQ_LINES_NUMBER];
+
+/*
+ * Stats of interrupts dispatched.
+ */
+static uint32_t irq_count[BSP_IRQ_VECTOR_NUMBER] = {0};
+static uint32_t spurious_count;
+
+/*
+ * Edge or level trigger interrupts.
+ */
+static enum intr_trigger irq_trigger[BSP_IRQ_LINES_NUMBER];
+
+/*-------------------------------------------------------------------------+
+| Cache for 1st and 2nd PIC IRQ line's mssk (enabled or disabled) register.
++--------------------------------------------------------------------------*/
+/*
+ * lower byte is interrupt mask on the master PIC.
+ * while upper bits are interrupt on the slave PIC.
+ * This cache is initialized in ldseg.s
+ */
+static rtems_i8259_masks i8259a_imr_cache = 0xFFFB;
+static rtems_i8259_masks i8259a_in_progress = 0;
+
+static inline
+void BSP_i8259a_irq_update_master_imr( void )
+{
+ rtems_i8259_masks mask = i8259a_in_progress | i8259a_imr_cache;
+ outport_byte( PIC_MASTER_IMR_IO_PORT, mask & 0xff );
+}
+
+static inline
+void BSP_i8259a_irq_update_slave_imr( void )
+{
+ rtems_i8259_masks mask = i8259a_in_progress | i8259a_imr_cache;
+ outport_byte( PIC_SLAVE_IMR_IO_PORT, ( mask >> 8 ) & 0xff );
+}
+
+/*
+ * Print the stats.
+ */
+uint32_t BSP_irq_count_dump(FILE *f)
+{
+ uint32_t tot = 0;
+ int i;
+ if ( !f )
+ f = stdout;
+ fprintf(f,"SPURIOUS: %9"PRIu32"\n", spurious_count);
+ for ( i = 0; i < BSP_IRQ_VECTOR_NUMBER; i++ ) {
+ char type = '-';
+ if (i < BSP_IRQ_LINES_NUMBER)
+ type = irq_trigger[i] == INTR_TRIGGER_EDGE ? 'E' : 'L';
+ tot += irq_count[i];
+ fprintf(f,"IRQ %2u: %c %9"PRIu32"\n", i, type, irq_count[i]);
+ }
+ return tot;
+}
+
+/*
+ * Is the IRQ valid?
+ */
+static inline bool BSP_i8259a_irq_valid(const rtems_irq_number irqLine)
+{
+ return ((int)irqLine >= BSP_IRQ_VECTOR_LOWEST_OFFSET) &&
+ ((int)irqLine <= BSP_IRQ_MAX_ON_i8259A);
+}
+
+/*
+ * Read the IRR register. The default.
+ */
+static inline uint8_t BSP_i8259a_irq_int_request_reg(uint32_t ioport)
+{
+ uint8_t isr;
+ inport_byte(ioport, isr);
+ return isr;
+}
+
+/*
+ * Read the ISR register. Keep the default of the IRR.
+ */
+static inline uint8_t BSP_i8259a_irq_in_service_reg(uint32_t ioport)
+{
+ uint8_t isr;
+ outport_byte(ioport, PIC_OCW3_SEL | PIC_OCW3_RR | PIC_OCW3_RIS);
+ inport_byte(ioport, isr);
+ outport_byte(ioport, PIC_OCW3_SEL | PIC_OCW3_RR);
+ return isr;
+}
+
+/*-------------------------------------------------------------------------+
+| Function: BSP_irq_disable_at_i8259a
+| Description: Mask IRQ line in appropriate PIC chip.
+| Global Variables: i8259a_imr_cache, i8259a_in_progress
+| Arguments: vector_offset - number of IRQ line to mask.
+| Returns: 0 is OK.
++--------------------------------------------------------------------------*/
+static int BSP_irq_disable_at_i8259a(const rtems_irq_number irqLine)
+{
+ unsigned short mask;
+ rtems_interrupt_lock_context lock_context;
+
+ rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context);
+
+ mask = 1 << irqLine;
+ i8259a_imr_cache |= mask;
+
+ if (irqLine < 8)
+ {
+ BSP_i8259a_irq_update_master_imr();
+ }
+ else
+ {
+ BSP_i8259a_irq_update_slave_imr();
+ }
+
+ rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------+
+| Function: BSP_irq_enable_at_i8259a
+| Description: Unmask IRQ line in appropriate PIC chip.
+| Global Variables: i8259a_imr_cache, i8259a_in_progress
+| Arguments: irqLine - number of IRQ line to mask.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+static int BSP_irq_enable_at_i8259a(const rtems_irq_number irqLine)
+{
+ unsigned short mask;
+ rtems_interrupt_lock_context lock_context;
+ uint8_t isr;
+ uint8_t irr;
+
+ rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context);
+
+ mask = 1 << irqLine;
+ i8259a_imr_cache &= ~mask;
+
+ if (irqLine < 8)
+ {
+ isr = BSP_i8259a_irq_in_service_reg(PIC_MASTER_COMMAND_IO_PORT);
+ irr = BSP_i8259a_irq_int_request_reg(PIC_MASTER_COMMAND_IO_PORT);
+ BSP_i8259a_irq_update_master_imr();
+ }
+ else
+ {
+ isr = BSP_i8259a_irq_in_service_reg(PIC_SLAVE_COMMAND_IO_PORT);
+ irr = BSP_i8259a_irq_int_request_reg(PIC_SLAVE_COMMAND_IO_PORT);
+ BSP_i8259a_irq_update_slave_imr();
+ }
+
+ if (((isr ^ irr) & mask) != 0)
+ printk("i386: isr=%x irr=%x\n", isr, irr);
+
+ rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context);
+
+ return 0;
+} /* mask_irq */
+
+/*-------------------------------------------------------------------------+
+| Function: BSP_irq_ack_at_i8259a
+| Description: Signal generic End Of Interrupt (EOI) to appropriate PIC.
+| Global Variables: None.
+| Arguments: irqLine - number of IRQ line to acknowledge.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+static int BSP_irq_ack_at_i8259a(const rtems_irq_number irqLine)
+{
+ uint8_t slave_isr = 0;
+
+ if (irqLine >= 8) {
+ outport_byte(PIC_SLAVE_COMMAND_IO_PORT, PIC_EOI);
+ slave_isr = BSP_i8259a_irq_in_service_reg(PIC_SLAVE_COMMAND_IO_PORT);
+ }
+
+ /*
+ * Only issue the EOI to the master if there are no more interrupts in
+ * service for the slave. i8259a data sheet page 18, The Special Fully Nested
+ * Mode, b.
+ */
+ if (slave_isr == 0)
+ outport_byte(PIC_MASTER_COMMAND_IO_PORT, PIC_EOI);
+
+ return 0;
+
+} /* ackIRQ */
+
+/*
+ * ------------------------ RTEMS Irq helper functions ----------------
+ */
+
+static rtems_irq_prio irqPrioTable[BSP_IRQ_LINES_NUMBER]={
+ /*
+ * actual priorities for each interrupt source:
+ * 0 means that only current interrupt is masked
+ * 255 means all other interrupts are masked
+ * The second entry has a priority of 255 because
+ * it is the slave pic entry and is should always remain
+ * unmasked.
+ */
+ 0,0,
+ 255,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static void compute_i8259_masks_from_prio (void)
+{
+ rtems_interrupt_lock_context lock_context;
+ unsigned int i;
+ unsigned int j;
+
+ rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context);
+
+ /*
+ * Always mask at least current interrupt to prevent re-entrance
+ */
+ for (i=0; i < BSP_IRQ_LINES_NUMBER; i++) {
+ * ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i);
+ for (j = 0; j < BSP_IRQ_LINES_NUMBER; j++) {
+ /*
+ * Mask interrupts at i8259 level that have a lower priority
+ */
+ if (irqPrioTable [i] > irqPrioTable [j]) {
+ * ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j);
+ }
+ }
+ }
+
+ rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context);
+}
+
+static inline bool bsp_interrupt_vector_is_valid(rtems_vector_number vector)
+{
+ return BSP_i8259a_irq_valid((const rtems_irq_number) vector);
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ BSP_irq_enable_at_i8259a(vector);
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ BSP_irq_disable_at_i8259a(vector);
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ int i;
+
+ /*
+ * set up internal tables used by rtems interrupt prologue
+ */
+ compute_i8259_masks_from_prio();
+
+ /*
+ * must enable slave pic anyway
+ */
+ BSP_irq_enable_at_i8259a(2);
+
+ /*
+ * Probe the ELCR.
+ */
+ elcr_probe();
+
+ for (i = 0; i < BSP_IRQ_LINES_NUMBER; i++)
+ irq_trigger[i] = elcr_read_trigger(i);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Global so the asm handler can call it.
+ */
+void BSP_dispatch_isr(int vector);
+
+void BSP_dispatch_isr(int vector)
+{
+ rtems_interrupt_lock_context lock_context;
+ rtems_i8259_masks in_progress_save = 0;
+
+ if (vector < BSP_IRQ_VECTOR_NUMBER) {
+ /*
+ * Hardware?
+ */
+ if (vector <= BSP_IRQ_MAX_ON_i8259A) {
+
+ rtems_interrupt_lock_acquire_isr(&rtems_i8259_access_lock, &lock_context);
+
+ /*
+ * See if this is a spurious interrupt.
+ */
+ if ((vector == 7 || vector == 15)) {
+ /*
+ * Only check it there no handler for 7 or 15.
+ */
+ if (bsp_interrupt_handler_is_empty(vector)) {
+ /*
+ * Read the ISR register to see if IRQ 7/15 is really pending.
+ */
+ uint8_t isr = BSP_i8259a_irq_in_service_reg(PIC_MASTER_COMMAND_IO_PORT);
+ if ((isr & (1 << 7)) == 0) {
+ ++spurious_count;
+ rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context);
+ return;
+ }
+ }
+ }
+
+ /*
+ * Save the current cached value for the IMR. It will have the bit for this
+ * vector clear.
+ */
+ if (vector <= BSP_IRQ_MAX_ON_i8259A) {
+ in_progress_save = i8259a_in_progress;
+ i8259a_in_progress |= irq_mask_or_tbl[vector];
+ BSP_i8259a_irq_update_master_imr();
+ BSP_i8259a_irq_update_slave_imr();
+ }
+
+ /*
+ * Do not use auto-EOI as some slave PIC do not work correctly.
+ */
+ BSP_irq_ack_at_i8259a(vector);
+
+ rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context);
+ }
+
+ /*
+ * Count the interrupt.
+ */
+ irq_count[vector]++;
+
+ RTEMS_COMPILER_MEMORY_BARRIER();
+ /*
+ * Allow nesting.
+ */
+ __asm__ __volatile__("sti");
+
+ bsp_interrupt_handler_dispatch(vector);
+
+ /*
+ * Disallow nesting.
+ */
+ __asm__ __volatile__("cli");
+
+ RTEMS_COMPILER_MEMORY_BARRIER();
+
+ if (vector <= BSP_IRQ_MAX_ON_i8259A) {
+
+ rtems_interrupt_lock_acquire_isr(&rtems_i8259_access_lock, &lock_context);
+
+ /*
+ * Put the mask back but keep this vector masked if the trigger type is
+ * level. The driver or a thread level interrupt server needs to enable it
+ * again.
+ */
+ if (vector <= BSP_IRQ_MAX_ON_i8259A) {
+ i8259a_in_progress = in_progress_save;
+ BSP_i8259a_irq_update_master_imr();
+ BSP_i8259a_irq_update_slave_imr();
+ }
+
+ rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context);
+ }
+ }
+}
diff --git a/bsps/i386/shared/irq/irq_asm.S b/bsps/i386/shared/irq/irq_asm.S
new file mode 100644
index 0000000000..181293351e
--- /dev/null
+++ b/bsps/i386/shared/irq/irq_asm.S
@@ -0,0 +1,268 @@
+/*
+ * This file contains the implementation of the function described in irq.h
+ */
+
+/*
+ * Copyright (C) 1998 valette@crf.canon.fr
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * 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.org/license/LICENSE.
+ */
+
+#include <rtems/asm.h>
+#include <rtems/system.h>
+#include <bspopts.h>
+#include <rtems/score/cpu.h>
+#include <rtems/score/percpu.h>
+
+#include <bsp.h> /* to establish dependency on prototype */
+
+#ifndef CPU_STACK_ALIGNMENT
+#error "Missing header? CPU_STACK_ALIGNMENT is not defined here"
+#endif
+
+/* Stack frame we use for intermediate storage */
+#define ARG_OFF 0
+#define MSK_OFF 4 /* not used any more */
+#define EBX_OFF 8 /* ebx */
+#define EBP_OFF 12 /* code restoring ebp/esp relies on */
+#define ESP_OFF 16 /* esp being on top of ebp! */
+#ifdef __SSE__
+/* need to be on 16 byte boundary for SSE, add 12 to do that */
+#define FRM_SIZ (20+12+512)
+#define SSE_OFF 32
+#else
+#define FRM_SIZ 20
+#endif
+
+ BEGIN_CODE
+
+SYM (_ISR_Handler):
+ /*
+ * Before this was point is reached the vectors unique
+ * entry point did the following:
+ *
+ * 1. saved scratch registers registers eax edx ecx"
+ * 2. put the vector number in ecx.
+ *
+ * BEGINNING OF ESTABLISH SEGMENTS
+ *
+ * WARNING: If an interrupt can occur when the segments are
+ * not correct, then this is where we should establish
+ * the segments. In addition to establishing the
+ * segments, it may be necessary to establish a stack
+ * in the current data area on the outermost interrupt.
+ *
+ * NOTE: If the previous values of the segment registers are
+ * pushed, do not forget to adjust SAVED_REGS.
+ *
+ * NOTE: Make sure the exit code which restores these
+ * when this type of code is needed.
+ */
+
+ /***** ESTABLISH SEGMENTS CODE GOES HERE ******/
+
+ /*
+ * END OF ESTABLISH SEGMENTS
+ */
+
+ /*
+ * Establish an aligned stack frame
+ * original sp
+ * saved ebx
+ * saved ebp
+ * saved irq mask
+ * vector arg to BSP_dispatch_isr <- aligned SP
+ */
+ movl esp, eax
+ subl $FRM_SIZ, esp
+ andl $ - CPU_STACK_ALIGNMENT, esp
+ movl ebx, EBX_OFF(esp)
+ movl eax, ESP_OFF(esp)
+ movl ebp, EBP_OFF(esp)
+
+ /*
+ * GCC versions starting with 4.3 no longer place the cld
+ * instruction before string operations. We need to ensure
+ * it is set correctly for ISR handlers.
+ */
+ cld
+
+#ifdef __SSE__
+ /* NOTE: SSE only is supported if the BSP enables fxsave/fxrstor
+ * to save/restore SSE context! This is so far only implemented
+ * for pc386!.
+ */
+
+ /* We save SSE here (on the task stack) because we possibly
+ * call other C-code (besides the ISR, namely _Thread_Dispatch())
+ */
+ /* don't wait here; a possible exception condition will eventually be
+ * detected when the task resumes control and executes a FP instruction
+ fwait
+ */
+ fxsave SSE_OFF(esp)
+ fninit /* clean-slate FPU */
+ movl $0x1f80, ARG_OFF(esp) /* use ARG_OFF as scratch space */
+ ldmxcsr ARG_OFF(esp) /* clean-slate MXCSR */
+#endif
+
+ /*
+ * Now switch stacks if necessary
+ */
+
+PUBLIC (ISR_STOP)
+ISR_STOP:
+.check_stack_switch:
+ movl esp, ebp /* ebp = previous stack pointer */
+
+#ifdef RTEMS_SMP
+ call SYM(_CPU_SMP_Get_current_processor)
+ sall $PER_CPU_CONTROL_SIZE_LOG2, eax
+ addl $SYM(_Per_CPU_Information), eax
+ movl eax, ebx
+#else
+ movl $SYM(_Per_CPU_Information), ebx
+#endif
+
+ /* is this the outermost interrupt? */
+ cmpl $0, PER_CPU_ISR_NEST_LEVEL(ebx)
+ jne nested /* No, then continue */
+ movl PER_CPU_INTERRUPT_STACK_HIGH(ebx), esp
+
+ /*
+ * We want to insure that the old stack pointer is in ebp
+ * By saving it on every interrupt, all we have to do is
+ * movl ebp->esp near the end of every interrupt.
+ */
+
+nested:
+ incl PER_CPU_ISR_NEST_LEVEL(ebx) /* one nest level deeper */
+ incl PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(ebx) /* disable
+ multitasking */
+ /*
+ * ECX is preloaded with the vector number; store as arg
+ * on top of stack. Note that _CPU_Interrupt_stack_high
+ * was adjusted in _CPU_Interrupt_stack_setup() (score/rtems/cpu.h)
+ * to make sure there is space.
+ */
+
+ movl ecx, ARG_OFF(esp) /* store vector arg in stack */
+ call BSP_dispatch_isr
+
+ movl ARG_OFF(esp), ecx /* grab vector arg from stack */
+
+ /*
+ * Restore stack. This moves back to the task stack
+ * when all interrupts are unnested.
+ */
+ movl ebp, esp
+
+ decl PER_CPU_ISR_NEST_LEVEL(ebx) /* one less ISR nest level */
+ /* If interrupts are nested, */
+ /* then dispatching is disabled */
+
+ decl PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(ebx)
+ /* unnest multitasking */
+ /* Is dispatch disabled */
+ jne .exit /* Yes, then exit */
+
+ cmpb $0, PER_CPU_DISPATCH_NEEDED(ebx)
+ /* Is task switch necessary? */
+ jne .schedule /* Yes, then call the scheduler */
+ jmp .exit /* No, exit */
+
+.schedule:
+ /*
+ * the scratch registers have already been saved and we are already
+ * back on the thread system stack. So we can call _Thread_Dispatch
+ * directly
+ */
+ call _Thread_Dispatch
+ /*
+ * fall through exit to restore complete contex (scratch registers
+ * eip, CS, Flags).
+ */
+.exit:
+
+#ifdef __SSE__
+ fwait
+ fxrstor SSE_OFF(esp)
+#endif
+
+ /* restore ebx, ebp and original esp */
+ addl $EBX_OFF, esp
+ popl ebx
+ popl ebp
+ popl esp
+
+ /*
+ * BEGINNING OF DE-ESTABLISH SEGMENTS
+ *
+ * NOTE: Make sure there is code here if code is added to
+ * load the segment registers.
+ *
+ */
+
+ /******* DE-ESTABLISH SEGMENTS CODE GOES HERE ********/
+
+ /*
+ * END OF DE-ESTABLISH SEGMENTS
+ */
+ popl edx
+ popl ecx
+ popl eax
+ iret
+
+#define DISTINCT_INTERRUPT_ENTRY(_vector) \
+ .p2align 4 ; \
+ PUBLIC (rtems_irq_prologue_ ## _vector ) ; \
+SYM (rtems_irq_prologue_ ## _vector ): \
+ pushl eax ; \
+ pushl ecx ; \
+ pushl edx ; \
+ movl $ _vector, ecx ; \
+ jmp SYM (_ISR_Handler) ;
+
+DISTINCT_INTERRUPT_ENTRY(0)
+DISTINCT_INTERRUPT_ENTRY(1)
+DISTINCT_INTERRUPT_ENTRY(2)
+DISTINCT_INTERRUPT_ENTRY(3)
+DISTINCT_INTERRUPT_ENTRY(4)
+DISTINCT_INTERRUPT_ENTRY(5)
+DISTINCT_INTERRUPT_ENTRY(6)
+DISTINCT_INTERRUPT_ENTRY(7)
+DISTINCT_INTERRUPT_ENTRY(8)
+DISTINCT_INTERRUPT_ENTRY(9)
+DISTINCT_INTERRUPT_ENTRY(10)
+DISTINCT_INTERRUPT_ENTRY(11)
+DISTINCT_INTERRUPT_ENTRY(12)
+DISTINCT_INTERRUPT_ENTRY(13)
+DISTINCT_INTERRUPT_ENTRY(14)
+DISTINCT_INTERRUPT_ENTRY(15)
+DISTINCT_INTERRUPT_ENTRY(16)
+
+ /*
+ * routine used to initialize the IDT by default
+ */
+
+PUBLIC (default_raw_idt_handler)
+PUBLIC (raw_idt_notify)
+
+SYM (default_raw_idt_handler):
+ pusha
+ cld
+ mov esp, ebp
+ andl $ - CPU_STACK_ALIGNMENT, esp
+ call raw_idt_notify
+ mov ebp, esp
+ popa
+ iret
+
+END_CODE
+
+END
diff --git a/bsps/i386/shared/irq/irq_init.c b/bsps/i386/shared/irq/irq_init.c
new file mode 100644
index 0000000000..fdf4801a5a
--- /dev/null
+++ b/bsps/i386/shared/irq/irq_init.c
@@ -0,0 +1,191 @@
+/* irq_init.c
+ *
+ * This file contains the implementation of rtems initialization
+ * related to interrupt handling.
+ *
+ * Copyright (c) 2009 embedded brains GmbH
+ * CopyRight (C) 1998 valette@crf.canon.fr
+ *
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems/bspIo.h>
+
+#include <rtems/score/cpu.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+/*
+ * rtems prologue generated in irq_asm.S
+ */
+extern void rtems_irq_prologue_0(void);
+extern void rtems_irq_prologue_1(void);
+extern void rtems_irq_prologue_2(void);
+extern void rtems_irq_prologue_3(void);
+extern void rtems_irq_prologue_4(void);
+extern void rtems_irq_prologue_5(void);
+extern void rtems_irq_prologue_6(void);
+extern void rtems_irq_prologue_7(void);
+extern void rtems_irq_prologue_8(void);
+extern void rtems_irq_prologue_9(void);
+extern void rtems_irq_prologue_10(void);
+extern void rtems_irq_prologue_11(void);
+extern void rtems_irq_prologue_12(void);
+extern void rtems_irq_prologue_13(void);
+extern void rtems_irq_prologue_14(void);
+extern void rtems_irq_prologue_15(void);
+extern void rtems_irq_prologue_16(void);
+/*
+ * default vectors
+ */
+extern void default_raw_idt_handler(void);
+
+/*
+ * default raw on/off function
+ */
+static void raw_nop_func(const struct __rtems_raw_irq_connect_data__ *unused)
+{
+}
+
+/*
+ * default raw isOn function
+ */
+static int raw_not_connected(
+ const struct __rtems_raw_irq_connect_data__ *unused
+)
+{
+ return 0;
+}
+
+static rtems_raw_irq_connect_data idtHdl[IDT_SIZE];
+
+static rtems_raw_irq_hdl rtemsIrq[BSP_IRQ_VECTOR_NUMBER] = {
+ rtems_irq_prologue_0,
+ rtems_irq_prologue_1,
+ rtems_irq_prologue_2,
+ rtems_irq_prologue_3,
+ rtems_irq_prologue_4,
+ rtems_irq_prologue_5,
+ rtems_irq_prologue_6,
+ rtems_irq_prologue_7,
+ rtems_irq_prologue_8,
+ rtems_irq_prologue_9,
+ rtems_irq_prologue_10,
+ rtems_irq_prologue_11,
+ rtems_irq_prologue_12,
+ rtems_irq_prologue_13,
+ rtems_irq_prologue_14,
+ rtems_irq_prologue_15,
+ rtems_irq_prologue_16,
+};
+
+static rtems_raw_irq_connect_data defaultRawIrq = {
+ 0, /* vectorIdex */
+ default_raw_idt_handler, /* hdl */
+ raw_nop_func, /* on */
+ raw_nop_func, /* off */
+ raw_not_connected /* isOn */
+};
+
+static interrupt_gate_descriptor idtEntry;
+
+static rtems_raw_irq_global_settings raw_initial_config;
+
+
+/*
+ * This method is called from irq_asm.S and cannot be static.
+ */
+void raw_idt_notify(void)
+{
+ printk("raw_idt_notify has been called \n");
+}
+
+void rtems_irq_mngt_init(void)
+{
+ int i;
+ interrupt_gate_descriptor* idt_entry_tbl;
+ unsigned int limit;
+ rtems_interrupt_level level;
+
+ i386_get_info_from_IDTR(&idt_entry_tbl, &limit);
+
+ /* Convert into number of entries */
+ limit = (limit + 1)/sizeof(interrupt_gate_descriptor);
+
+ if(limit != IDT_SIZE) {
+ printk("IDT table size mismatch !!! System locked\n");
+ while(1);
+ }
+
+ /*
+ * The interrupt management can be initialized only once
+ * during system bootup and that should happen on boot
+ * CPU so there is no need to synchronize with others CPUs.
+ */
+ rtems_interrupt_local_disable(level);
+
+ /*
+ * Init the complete IDT vector table with defaultRawIrq value
+ */
+ for (i = 0; i < IDT_SIZE ; i++) {
+ idtHdl[i] = defaultRawIrq;
+ idtHdl[i].idtIndex = i;
+ }
+
+ raw_initial_config.idtSize = IDT_SIZE;
+ raw_initial_config.defaultRawEntry = defaultRawIrq;
+ raw_initial_config.rawIrqHdlTbl = idtHdl;
+
+ if (!i386_init_idt (&raw_initial_config)) {
+ /*
+ * put something here that will show the failure...
+ */
+ printk("Unable to initialize IDT!!! System locked\n");
+ while (1);
+ }
+ /*
+ * Patch the entry that will be used by RTEMS for interrupt management
+ * with RTEMS prologue.
+ */
+ for (i = 0; i < BSP_IRQ_VECTOR_NUMBER; i++) {
+ create_interrupt_gate_descriptor(&idtEntry, rtemsIrq[i]);
+ idt_entry_tbl[i + BSP_ASM_IRQ_VECTOR_BASE] = idtEntry;
+ }
+ /*
+ * At this point we have completed the initialization of IDT
+ * with raw handlers. We must now initialize the higher level
+ * interrupt management.
+ */
+
+ /*
+ * Init initial Interrupt management config
+ */
+ bsp_interrupt_initialize();
+
+ /*
+ * #define DEBUG
+ */
+#ifdef DEBUG
+ {
+ /*
+ * following adresses should be the same
+ */
+ unsigned tmp;
+
+ printk("idt_entry_tbl = %x Interrupt_descriptor_table addr = %x\n",
+ idt_entry_tbl, &Interrupt_descriptor_table);
+ tmp = (unsigned) get_hdl_from_vector (BSP_ASM_IRQ_VECTOR_BASE + BSP_PERIODIC_TIMER);
+ printk("clock isr address from idt = %x should be %x\n",
+ tmp, (unsigned) rtems_irq_prologue_0);
+ }
+ printk("i8259s_cache = %x\n", * (unsigned short*) &i8259s_cache);
+ BSP_wait_polled_input();
+#endif
+}
diff --git a/bsps/lm32/shared/irq/irq.c b/bsps/lm32/shared/irq/irq.c
new file mode 100644
index 0000000000..79626ee449
--- /dev/null
+++ b/bsps/lm32/shared/irq/irq.c
@@ -0,0 +1,30 @@
+/* irq.c
+ *
+ * Copyright (c) 2010 Sebastien Bourdeauducq
+ *
+ * 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.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <rtems/score/cpu.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ return RTEMS_SUCCESSFUL;
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ lm32_interrupt_unmask(1 << vector);
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ lm32_interrupt_mask(1 << vector);
+}
diff --git a/bsps/m68k/genmcf548x/irq/intc-icr-init-values.c b/bsps/m68k/genmcf548x/irq/intc-icr-init-values.c
new file mode 100644
index 0000000000..afc58224ea
--- /dev/null
+++ b/bsps/m68k/genmcf548x/irq/intc-icr-init-values.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/irq.h>
+
+#define ICR(lvl, prio) (MCF548X_INTC_ICRn_IL(lvl) | MCF548X_INTC_ICRn_IP(prio))
+
+const uint8_t mcf548x_intc_icr_init_values[64] = {
+ [MCF548X_IRQ_SLT0] = ICR(4, 7),
+ [MCF548X_IRQ_SLT1] = ICR(4, 6),
+ [MCF548X_IRQ_PSC0] = ICR(3, 7),
+ [MCF548X_IRQ_PSC1] = ICR(3, 6),
+ [MCF548X_IRQ_PSC2] = ICR(3, 5),
+ [MCF548X_IRQ_PSC3] = ICR(3, 4),
+ [MCF548X_IRQ_FEC0] = ICR(2, 7),
+ [MCF548X_IRQ_FEC1] = ICR(2, 6)
+};
diff --git a/bsps/m68k/genmcf548x/irq/irq.c b/bsps/m68k/genmcf548x/irq/irq.c
new file mode 100644
index 0000000000..f02231b67c
--- /dev/null
+++ b/bsps/m68k/genmcf548x/irq/irq.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2013 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp/irq-generic.h>
+
+#include <mcf548x/mcf548x.h>
+
+void asm_default_interrupt(void);
+
+typedef void (*void_func)(void);
+
+typedef struct {
+ rtems_interrupt_handler handler;
+ void *arg;
+ const char *info;
+} interrupt_control;
+
+static interrupt_control interrupt_controls[BSP_INTERRUPT_VECTOR_MAX + 1];
+
+static uint32_t vector_to_reg(rtems_vector_number vector)
+{
+ return ((vector + 32U) >> 5) & 0x1;
+}
+
+static uint32_t vector_to_bit(rtems_vector_number vector)
+{
+ return 1U << (vector & 0x1fU);
+}
+
+static volatile uint32_t *vector_to_imr(rtems_vector_number vector)
+{
+ volatile uint32_t *imr = &MCF548X_INTC_IMRH;
+
+ return &imr[vector_to_reg(vector)];
+}
+
+static rtems_vector_number exception_vector_to_vector(
+ rtems_vector_number exception_vector
+)
+{
+ return exception_vector - 64U;
+}
+
+static rtems_vector_number vector_to_exception_vector(
+ rtems_vector_number vector
+)
+{
+ return vector + 64U;
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ volatile uint32_t *imr = vector_to_imr(vector);
+ uint32_t bit = vector_to_bit(vector);
+ rtems_interrupt_level level;
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ rtems_interrupt_disable(level);
+ *imr &= ~bit;
+ rtems_interrupt_enable(level);
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ volatile uint32_t *imr = vector_to_imr(vector);
+ uint32_t bit = vector_to_bit(vector);
+ rtems_interrupt_level level;
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ rtems_interrupt_disable(level);
+ *imr |= bit;
+ rtems_interrupt_enable(level);
+}
+
+static void_func get_exception_handler(rtems_vector_number vector)
+{
+ void **vbr;
+ void_func *exception_table;
+
+ m68k_get_vbr(vbr);
+
+ exception_table = (void_func *)vbr;
+
+ return exception_table[vector_to_exception_vector(vector)];
+}
+
+static void set_exception_handler(rtems_vector_number vector, void_func handler)
+{
+ void **vbr;
+ void_func *exception_table;
+
+ m68k_get_vbr(vbr);
+
+ exception_table = (void_func *)vbr;
+
+ exception_table[vector_to_exception_vector(vector)] = handler;
+}
+
+static void dispatch_handler(rtems_vector_number exception_vector)
+{
+ const interrupt_control *ic =
+ &interrupt_controls[exception_vector_to_vector(exception_vector)];
+
+ (*ic->handler)(ic->arg);
+}
+
+static uint8_t get_intc_icr(rtems_vector_number vector)
+{
+ volatile uint8_t *icr = &MCF548X_INTC_ICR0;
+
+ return icr[vector];
+}
+
+rtems_status_code rtems_interrupt_handler_install(
+ rtems_vector_number vector,
+ const char *info,
+ rtems_option options,
+ rtems_interrupt_handler handler,
+ void *arg
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+ if (bsp_interrupt_is_valid_vector(vector)) {
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+
+ if (
+ get_exception_handler(vector) == asm_default_interrupt
+ && get_intc_icr(vector) != 0
+ ) {
+ interrupt_control *ic = &interrupt_controls[vector];
+
+ ic->handler = handler;
+ ic->arg = arg;
+ ic->info = info;
+
+ _ISR_Vector_table[vector_to_exception_vector(vector)]
+ = dispatch_handler;
+ set_exception_handler(vector, _ISR_Handler);
+ bsp_interrupt_vector_enable(vector);
+ } else {
+ sc = RTEMS_RESOURCE_IN_USE;
+ }
+
+ rtems_interrupt_enable(level);
+ } else {
+ sc = RTEMS_INVALID_ID;
+ }
+
+ return sc;
+}
+
+static bool is_occupied_by_us(rtems_vector_number vector)
+{
+ return get_exception_handler(vector) == _ISR_Handler
+ && _ISR_Vector_table[vector_to_exception_vector(vector)]
+ == dispatch_handler;
+}
+
+rtems_status_code rtems_interrupt_handler_remove(
+ rtems_vector_number vector,
+ rtems_interrupt_handler handler,
+ void *arg
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+ if (bsp_interrupt_is_valid_vector(vector)) {
+ rtems_interrupt_level level;
+ interrupt_control *ic = &interrupt_controls[vector];
+
+ rtems_interrupt_disable(level);
+
+ if (
+ is_occupied_by_us(vector)
+ && ic->handler == handler
+ && ic->arg == arg
+ ) {
+ bsp_interrupt_vector_disable(vector);
+ set_exception_handler(vector, asm_default_interrupt);
+
+ memset(ic, 0, sizeof(*ic));
+ } else {
+ sc = RTEMS_UNSATISFIED;
+ }
+
+ rtems_interrupt_enable(level);
+ } else {
+ sc = RTEMS_INVALID_ID;
+ }
+
+ return sc;
+}
+
+rtems_status_code rtems_interrupt_handler_iterate(
+ rtems_vector_number vector,
+ rtems_interrupt_per_handler_routine routine,
+ void *arg
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+ if (bsp_interrupt_is_valid_vector(vector)) {
+ if (is_occupied_by_us(vector)) {
+ const interrupt_control *ic = &interrupt_controls[vector];
+
+ (*routine)(arg, ic->info, RTEMS_INTERRUPT_UNIQUE, ic->handler, ic->arg);
+ }
+ } else {
+ sc = RTEMS_INVALID_ID;
+ }
+
+ return sc;
+}
diff --git a/bsps/mips/csb350/irq/vectorisrs.c b/bsps/mips/csb350/irq/vectorisrs.c
new file mode 100644
index 0000000000..d8e071281e
--- /dev/null
+++ b/bsps/mips/csb350/irq/vectorisrs.c
@@ -0,0 +1,168 @@
+/**
+ * @file
+ *
+ * Au1x00 Interrupt Vectoring
+ */
+
+/*
+ * Copyright (c) 2005 by Cogent Computer Systems
+ * Written by Jay Monkman <jtm@lopingdog.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <stdlib.h>
+#include <libcpu/au1x00.h>
+#include <libcpu/isr_entries.h>
+#include <rtems/irq.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+static void call_vectored_isr(CPU_Interrupt_frame *, uint32_t , void *);
+
+#include <rtems/bspIo.h> /* for printk */
+
+void mips_vector_isr_handlers( CPU_Interrupt_frame *frame )
+{
+ unsigned int sr;
+ unsigned int cause;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+
+ cause &= (sr & SR_IMASK);
+ cause >>= CAUSE_IPSHIFT;
+
+ /* count/compare interrupt */
+ if ( cause & 0x80 ) {
+ unsigned long zero = 0;
+ /*
+ * I don't see a good way to disable the compare
+ * interrupt, so let's just ignore it.
+ */
+ __asm__ volatile ("mtc0 %0, $11\n" :: "r" (zero));
+ }
+
+ /* Performance counter */
+ if ( cause & 0x40 ) {
+ bsp_interrupt_handler_dispatch(AU1X00_IRQ_PERF);
+ }
+
+ /* Interrupt controller 0 */
+ if ( cause & 0x0c ) {
+ call_vectored_isr(frame, cause, (void *)AU1X00_IC0_ADDR);
+ }
+
+ /* Interrupt controller 1 */
+ if ( cause & 0x30 ) {
+ call_vectored_isr(frame, cause, (void *)AU1X00_IC1_ADDR);
+ }
+
+ /* SW[0] */
+ if ( cause & 0x01 )
+ bsp_interrupt_handler_dispatch( AU1X00_IRQ_SW0 );
+
+ /* SW[1] */
+ if ( cause & 0x02 )
+ bsp_interrupt_handler_dispatch( AU1X00_IRQ_SW1 );
+}
+
+void mips_default_isr( int vector )
+{
+ unsigned int sr;
+ unsigned int cause;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+
+ printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n",
+ vector, cause, sr );
+ rtems_fatal_error_occurred(1);
+}
+
+static void call_vectored_isr(
+ CPU_Interrupt_frame *frame,
+ uint32_t cause,
+ void *ctrlr
+ )
+{
+ uint32_t src;
+ uint32_t mask;
+ int index;
+
+ /* get mask register */
+ mask = AU1X00_IC_MASKRD(ctrlr);
+
+ /* check request 0 */
+ src = AU1X00_IC_REQ0INT(ctrlr);
+ src = src & mask;
+ index = 0;
+ while (src) {
+ /* check LSB */
+ if (src & 1) {
+ /* clear rising/falling edge detects */
+ AU1X00_IC_RISINGCLR(ctrlr) = (1 << index);
+ AU1X00_IC_FALLINGCLR(ctrlr) = (1 << index);
+ au_sync();
+ bsp_interrupt_handler_dispatch(AU1X00_IRQ_IC0_BASE + index);
+ }
+ index ++;
+
+ /* shift, and make sure MSB is clear */
+ src = (src >> 1) & 0x7fffffff;
+ }
+
+ /* check request 1 */
+ src = AU1X00_IC_REQ1INT(ctrlr);
+ src = src & mask;
+ index = 0;
+ while (src) {
+ /* check LSB */
+ if (src & 1) {
+ /* clear rising/falling edge detects */
+ AU1X00_IC_RISINGCLR(ctrlr) = (1 << index);
+ AU1X00_IC_FALLINGCLR(ctrlr) = (1 << index);
+ au_sync();
+ bsp_interrupt_handler_dispatch(AU1X00_IRQ_IC0_BASE + index);
+ }
+ index ++;
+
+ /* shift, and make sure MSB is clear */
+ src = (src >> 1) & 0x7fffffff;
+ }
+}
+
+/* Generate a software interrupt */
+int assert_sw_irq(uint32_t irqnum)
+{
+ uint32_t cause;
+
+ if (irqnum <= 1) {
+ mips_get_cause(cause);
+ cause = cause | ((irqnum + 1) << CAUSE_IPSHIFT);
+ mips_set_cause(cause);
+
+ return irqnum;
+ } else {
+ return -1;
+ }
+}
+
+/* Clear a software interrupt */
+int negate_sw_irq(uint32_t irqnum)
+{
+ uint32_t cause;
+
+ if (irqnum <= 1) {
+ mips_get_cause(cause);
+ cause = cause & ~((irqnum + 1) << CAUSE_IPSHIFT);
+ mips_set_cause(cause);
+
+ return irqnum;
+ } else {
+ return -1;
+ }
+}
diff --git a/bsps/mips/hurricane/irq/vectorisrs.c b/bsps/mips/hurricane/irq/vectorisrs.c
new file mode 100644
index 0000000000..e55566697d
--- /dev/null
+++ b/bsps/mips/hurricane/irq/vectorisrs.c
@@ -0,0 +1,58 @@
+/**
+ * @file
+ *
+ * RM5231 Interrupt Vectoring
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <stdlib.h>
+#include <libcpu/isr_entries.h>
+#include <libcpu/rm5231.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+#include <rtems/bspIo.h> /* for printk */
+
+void mips_default_isr( int vector );
+
+void mips_vector_isr_handlers( CPU_Interrupt_frame *frame )
+{
+ unsigned int sr;
+ unsigned int cause;
+ unsigned int i;
+ unsigned int mask;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+
+ cause &= (sr & SR_IMASK);
+ cause >>= CAUSE_IPSHIFT;
+
+ for ( i=1, mask=0x80 ; i<=8 ; i++, mask >>= 1 ) {
+ if ( cause & mask )
+ bsp_interrupt_handler_dispatch( MIPS_INTERRUPT_BASE + 8 - i );
+ }
+}
+
+void mips_default_isr( int vector )
+{
+ unsigned int sr;
+ unsigned int cause;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+
+ printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n",
+ vector, cause, sr );
+ rtems_fatal_error_occurred(1);
+}
+
diff --git a/bsps/mips/jmr3904/irq/vectorisrs.c b/bsps/mips/jmr3904/irq/vectorisrs.c
new file mode 100644
index 0000000000..629c4c45f8
--- /dev/null
+++ b/bsps/mips/jmr3904/irq/vectorisrs.c
@@ -0,0 +1,47 @@
+/**
+ * @file
+ *
+ * TX3904 Interrupt Vectoring
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <stdlib.h>
+#include <bsp/irq.h>
+#include <rtems/bspIo.h> /* for printk */
+#include <bsp/irq-generic.h>
+#include <libcpu/isr_entries.h>
+
+void mips_vector_isr_handlers( CPU_Interrupt_frame *frame )
+{
+ unsigned int sr;
+ unsigned int cause;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+
+ cause &= (sr & SR_IMASK);
+ cause >>= CAUSE_IPSHIFT;
+
+ if ( cause & 0x80 ) /* IP[5] ==> INT0 */
+ bsp_interrupt_handler_dispatch( TX3904_IRQ_INT0 );
+
+ if ( cause & 0x40 ) { /* (IP[4] == 1) ==> IP[0-3] are valid */
+ unsigned int v = (cause >> 2) & 0x0f;
+ bsp_interrupt_handler_dispatch( MIPS_INTERRUPT_BASE + v );
+ }
+
+ if ( cause & 0x02 ) /* SW[0] */
+ bsp_interrupt_handler_dispatch( TX3904_IRQ_SOFTWARE_1 );
+
+ if ( cause & 0x01 ) /* IP[1] */
+ bsp_interrupt_handler_dispatch( TX3904_IRQ_SOFTWARE_2 );
+}
diff --git a/bsps/mips/malta/irq/interruptmask.c b/bsps/mips/malta/irq/interruptmask.c
new file mode 100644
index 0000000000..d639ab17a9
--- /dev/null
+++ b/bsps/mips/malta/irq/interruptmask.c
@@ -0,0 +1,36 @@
+/**
+ * @file
+ *
+ * This file contains the implementation of the MIPS port
+ * support routine which provides the BSP specific default
+ * interrupt mask.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+
+/*
+ * This function returns a mask value which is used to select the bits
+ * in the processor status register that can be set to enable interrupts.
+ * The mask value should not include the 2 software interrupt enable bits.
+ */
+
+uint32_t mips_interrupt_mask( void )
+{
+ uint32_t interrupt_mask;
+
+ /*
+ * This has only been tested with qemu for the mips malta and
+ * may not be correct for the 24k on real hardware.
+ */
+ interrupt_mask = 0x0000ff00;
+ return(interrupt_mask);
+}
diff --git a/bsps/mips/malta/irq/vectorisrs.c b/bsps/mips/malta/irq/vectorisrs.c
new file mode 100644
index 0000000000..a2b9288646
--- /dev/null
+++ b/bsps/mips/malta/irq/vectorisrs.c
@@ -0,0 +1,90 @@
+/**
+ * @file
+ *
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <stdlib.h>
+#include <bsp/irq-generic.h>
+#include <bsp/pci.h>
+#include <bsp/i8259.h>
+#include <bsp.h>
+#include <libcpu/isr_entries.h>
+
+void mips_default_isr( int vector );
+
+#include <rtems/bspIo.h> /* for printk */
+
+void mips_vector_isr_handlers( CPU_Interrupt_frame *frame )
+{
+ unsigned int sr;
+ unsigned int cause;
+ unsigned int pending;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+
+ pending = (cause & sr & 0xff00) >> CAUSE_IPSHIFT;
+
+ /* SW Bits */
+ if ( pending & 0x01) {
+ printk("Pending IRQ Q 0x%x\n", pending );
+ }
+
+ if ( pending & 0x02) {
+ printk("Pending IRQ Q 0x%x\n", pending );
+ }
+
+ /* South Bridge Interrupt */
+ if ( pending & 0x04) {
+ BSP_i8259s_int_process();
+ }
+
+ /* South Bridge SMI */
+ if (pending & 0x08){
+ printk( "Pending IRQ 0x%x\n", pending );
+ }
+
+ /* TTY 2 */
+ if (pending & 0x10) {
+ printk( "Pending IRQ 0x%x\n", pending );
+ }
+ /* Core HI */
+ if (pending & 0x20) {
+ printk( "Pending IRQ 0x%x\n", pending );
+ }
+ /* Core LO */
+ if (pending & 0x40) {
+ printk( "Pending IRQ 0x%x\n", pending );
+ }
+
+ if ( pending & 0x80 ) {
+ bsp_interrupt_handler_dispatch( MALTA_INT_TICKER );
+ }
+}
+
+void mips_default_isr( int vector )
+{
+ unsigned int sr;
+ unsigned int cause;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+
+ printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n",
+ vector, cause, sr );
+
+ while(1); /* Lock it up */
+
+ rtems_fatal_error_occurred(1);
+}
+
diff --git a/bsps/mips/rbtx4925/irq/vectorisrs.c b/bsps/mips/rbtx4925/irq/vectorisrs.c
new file mode 100644
index 0000000000..09020c5020
--- /dev/null
+++ b/bsps/mips/rbtx4925/irq/vectorisrs.c
@@ -0,0 +1,64 @@
+/**
+ * @file
+ *
+ * TX4925 Interrupt Vectoring
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <stdlib.h>
+#include <libcpu/isr_entries.h>
+#include <libcpu/tx4925.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <rtems/bspIo.h> /* for printk */
+
+void mips_default_isr( int vector );
+
+void mips_vector_isr_handlers( CPU_Interrupt_frame *frame )
+{
+ unsigned int sr;
+ unsigned int cause;
+ unsigned int pending;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+
+ pending = (cause & sr & 0x700) >> CAUSE_IPSHIFT;
+
+ if ( pending & 0x4 ) { /* (IP[2] == 1) ==> IP[3-7] are valid */
+ unsigned int v = (cause >> (CAUSE_IPSHIFT + 3)) & 0x1f;
+ bsp_interrupt_handler_dispatch( MIPS_INTERRUPT_BASE + v );
+ }
+
+ if ( pending & 0x01 ) /* IP[0] */
+ bsp_interrupt_handler_dispatch( TX4925_IRQ_SOFTWARE_1 );
+
+ if ( pending & 0x02 ) /* IP[1] */
+ bsp_interrupt_handler_dispatch( TX4925_IRQ_SOFTWARE_2 );
+}
+
+void mips_default_isr( int vector )
+{
+ unsigned int sr;
+ unsigned int cause;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+
+ printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n",
+ vector, cause, sr );
+
+ while(1); /* Lock it up */
+
+ rtems_fatal_error_occurred(1);
+}
+
diff --git a/bsps/mips/rbtx4938/irq/vectorisrs.c b/bsps/mips/rbtx4938/irq/vectorisrs.c
new file mode 100644
index 0000000000..d38e4f81c2
--- /dev/null
+++ b/bsps/mips/rbtx4938/irq/vectorisrs.c
@@ -0,0 +1,64 @@
+/**
+ * @file
+ *
+ * TX4925 Interrupt Vectoring
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <stdlib.h>
+#include <libcpu/isr_entries.h>
+#include <libcpu/tx4938.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <rtems/bspIo.h> /* for printk */
+
+void mips_default_isr( int vector );
+
+void mips_vector_isr_handlers( CPU_Interrupt_frame *frame )
+{
+ unsigned int sr;
+ unsigned int cause;
+ unsigned int pending;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+
+ pending = (cause & sr & 0x700) >> CAUSE_IPSHIFT;
+
+ if ( pending & 0x4 ) { /* (IP[2] == 1) ==> IP[3-7] are valid */
+ unsigned int v = (cause >> (CAUSE_IPSHIFT + 3)) & 0x1f;
+ bsp_interrupt_handler_dispatch( MIPS_INTERRUPT_BASE + v );
+ }
+
+ if ( pending & 0x01 ) /* IP[0] */
+ bsp_interrupt_handler_dispatch( TX4938_IRQ_SOFTWARE_1 );
+
+ if ( pending & 0x02 ) /* IP[1] */
+ bsp_interrupt_handler_dispatch( TX4938_IRQ_SOFTWARE_2 );
+}
+
+void mips_default_isr( int vector )
+{
+ unsigned int sr;
+ unsigned int cause;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+
+ printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n",
+ vector, cause, sr );
+
+ while(1); /* Lock it up */
+
+ rtems_fatal_error_occurred(1);
+}
+
diff --git a/bsps/mips/shared/irq/exception.S b/bsps/mips/shared/irq/exception.S
new file mode 100644
index 0000000000..e916ae55fe
--- /dev/null
+++ b/bsps/mips/shared/irq/exception.S
@@ -0,0 +1,661 @@
+/*
+ * This file contains a customized MIPS exception handler.
+ * It hooks into the exception handler present in the resident
+ * PMON debug monitor.
+ */
+
+/*
+ * Author: Bruce Robinson
+ *
+ * This code was derived from cpu_asm.S with the following copyright:
+ *
+ * COPYRIGHT (c) 1996 by Transition Networks Inc.
+ *
+ * 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 Transition Networks not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * Transition Networks makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ * Derived from c/src/exec/score/cpu/no_cpu/cpu_asm.s:
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bspopts.h>
+#include <rtems/asm.h>
+#include <rtems/score/percpu.h>
+#include <rtems/mips/iregdef.h>
+#include <rtems/mips/idtcpu.h>
+#if BSP_HAS_USC320
+ #include <usc.h>
+#endif
+
+#if __mips == 3
+/* 64 bit register operations */
+#define NOP nop
+#define ADD dadd
+#define STREG sd
+#define LDREG ld
+#define ADDU addu
+#define ADDIU addiu
+#define STREGC1 sdc1
+#define LDREGC1 ldc1
+#define R_SZ 8
+#define F_SZ 8
+#define SZ_INT 8
+#define SZ_INT_POW2 3
+
+/* XXX if we don't always want 64 bit register ops, then another ifdef */
+
+#elif __mips == 1
+/* 32 bit register operations*/
+#define NOP nop
+#define ADD add
+#define STREG sw
+#define LDREG lw
+#define ADDU add
+#define ADDIU addi
+#define STREGC1 swc1
+#define LDREGC1 lwc1
+#define R_SZ 4
+#define F_SZ 4
+#define SZ_INT 4
+#define SZ_INT_POW2 2
+#else
+#error "mips assembly: what size registers do I deal with?"
+#endif
+
+
+#define ISR_VEC_SIZE 4
+#define EXCP_STACK_SIZE (NREGS*R_SZ)
+
+.extern _Thread_Dispatch
+
+/* void __ISR_Handler()
+ *
+ * This routine provides the RTEMS interrupt management.
+ *
+ */
+
+#if 0
+void _ISR_Handler()
+{
+ /*
+ * This discussion ignores a lot of the ugly details in a real
+ * implementation such as saving enough registers/state to be
+ * able to do something real. Keep in mind that the goal is
+ * to invoke a user's ISR handler which is written in C and
+ * uses a certain set of registers.
+ *
+ * Also note that the exact order is to a large extent flexible.
+ * Hardware will dictate a sequence for a certain subset of
+ * _ISR_Handler while requirements for setting
+ */
+
+ /*
+ * At entry to "common" _ISR_Handler, the vector number must be
+ * available. On some CPUs the hardware puts either the vector
+ * number or the offset into the vector table for this ISR in a
+ * known place. If the hardware does not give us this information,
+ * then the assembly portion of RTEMS for this port will contain
+ * a set of distinct interrupt entry points which somehow place
+ * the vector number in a known place (which is safe if another
+ * interrupt nests this one) and branches to _ISR_Handler.
+ *
+ */
+#endif
+FRAME(bsp_ISR_Handler,sp,0,ra)
+ .set noreorder
+
+#if 0
+/* Activate TX49xx PIO19 signal for diagnostics */
+ lui k0,0xff1f
+ ori k0,k0,0xf500
+ lw k0,(k0)
+ lui k1,0x8
+ or k1,k1,k0
+ lui k0,0xff1f
+ ori k0,k0,0xf500
+ sw k1,(k0)
+#endif
+ mfc0 k0,C0_CAUSE /* Determine if an interrupt generated this exception */
+ nop
+ and k1,k0,CAUSE_EXCMASK
+ beq k1,zero,_chk_int /* If so, branch to service here */
+ nop
+ la k0,_int_esr_link /* Otherwise, jump to next exception handler in PMON exception chain */
+ lw k0,(k0)
+ lw k0,4(k0)
+ j k0
+ nop
+_chk_int:
+ mfc0 k1,C0_SR
+ nop
+ and k0,k1
+#if HAS_RM52xx
+ and k0,CAUSE_IPMASK
+#elif HAS_TX49xx
+ and k0,(SR_IBIT1 | SR_IBIT2 | SR_IBIT3)
+#endif
+ /* external interrupt not enabled, ignore */
+ beq k0,zero,_ISR_Handler_quick_exit
+ nop
+
+/* For debugging interrupts, clear EXL to allow breakpoints */
+#if 0
+ MFC0 k0, C0_SR
+#if __mips == 3
+ li k1,SR_EXL /* Clear EXL and Set IE to enable interrupts */
+ not k1
+ and k0,k1
+ li k1,SR_IE
+#elif __mips == 1
+ li k1,SR_IEC
+#endif
+ or k0, k1
+ mtc0 k0, C0_SR
+ NOP
+#endif
+
+
+ /*
+ * save some or all context on stack
+ * may need to save some special interrupt information for exit
+ */
+
+ /* Q: _ISR_Handler, not using IDT/SIM ...save extra regs? */
+
+ /* wastes a lot of stack space for context?? */
+ ADDIU sp,sp,-EXCP_STACK_SIZE
+
+ STREG ra, R_RA*R_SZ(sp) /* store ra on the stack */
+ STREG v0, R_V0*R_SZ(sp)
+ STREG v1, R_V1*R_SZ(sp)
+ STREG a0, R_A0*R_SZ(sp)
+ STREG a1, R_A1*R_SZ(sp)
+ STREG a2, R_A2*R_SZ(sp)
+ STREG a3, R_A3*R_SZ(sp)
+ STREG t0, R_T0*R_SZ(sp)
+ STREG t1, R_T1*R_SZ(sp)
+ STREG t2, R_T2*R_SZ(sp)
+ STREG t3, R_T3*R_SZ(sp)
+ STREG t4, R_T4*R_SZ(sp)
+ STREG t5, R_T5*R_SZ(sp)
+ STREG t6, R_T6*R_SZ(sp)
+ STREG t7, R_T7*R_SZ(sp)
+ mflo t0
+ STREG t8, R_T8*R_SZ(sp)
+ STREG t0, R_MDLO*R_SZ(sp)
+ STREG t9, R_T9*R_SZ(sp)
+ mfhi t0
+ STREG gp, R_GP*R_SZ(sp)
+ STREG t0, R_MDHI*R_SZ(sp)
+ STREG fp, R_FP*R_SZ(sp)
+
+ .set noat
+ STREG AT, R_AT*R_SZ(sp)
+ .set at
+
+ mfc0 t0,C0_SR
+ dmfc0 t1,C0_EPC
+ STREG t0,R_SR*R_SZ(sp)
+ STREG t1,R_EPC*R_SZ(sp)
+
+ /*
+ *
+ * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+ * if ( _ISR_Nest_level == 0 )
+ * switch to software interrupt stack
+ * #endif
+ */
+
+ /*
+ * _ISR_Nest_level++;
+ */
+ lw t0,ISR_NEST_LEVEL
+ NOP
+ add t0,t0,1
+ sw t0,ISR_NEST_LEVEL
+ /*
+ * _Thread_Dispatch_disable_level++;
+ */
+ lw t1,THREAD_DISPATCH_DISABLE_LEVEL
+ NOP
+ add t1,t1,1
+ sw t1,THREAD_DISPATCH_DISABLE_LEVEL
+
+ /* DEBUG - Add the following code to disable interrupts and clear
+ * EXL in status register, this will allow memory
+ * exceptions to occur while servicing the current interrupt
+ */
+#if 0
+ /* Disable interrupts from internal interrupt controller */
+ li t0,~CAUSE_IP2_MASK
+ mfc0 t1,C0_SR
+ nop
+ and t1,t0
+ mtc0 t1,C0_SR
+ nop
+ /* Clear EXL in status register to allow memory exceptions to occur */
+ li t0,~SR_EXL
+ mfc0 t1,C0_SR
+ nop
+ and t1,t0
+ mtc0 t1,C0_SR
+ nop
+#endif
+
+ /*
+ * Call the CPU model or BSP specific routine to decode the
+ * interrupt source and actually vector to device ISR handlers.
+ */
+ move a0,sp
+ jal mips_vector_isr_handlers
+ NOP
+
+ /* Add the following code to disable interrupts (see DEBUG above) */
+#if 0
+ li t0,SR_EXL /* Set EXL to hold off interrupts */
+ mfc0 t1,C0_SR
+ nop
+ or t1,t0
+ mtc0 t1,C0_SR
+ nop
+ /* Enable interrupts from internal interrupt controller */
+ li t0,CAUSE_IP2_MASK
+ mfc0 t1,C0_SR
+ nop
+ or t1,t0
+ mtc0 t1,C0_SR
+ nop
+#endif
+
+_ISR_Handler_cleanup:
+
+ /*
+ * --_ISR_Nest_level;
+ */
+ lw t2,ISR_NEST_LEVEL
+ NOP
+ add t2,t2,-1
+ sw t2,ISR_NEST_LEVEL
+ /*
+ * --_Thread_Dispatch_disable_level;
+ */
+ lw t1,THREAD_DISPATCH_DISABLE_LEVEL
+ NOP
+ add t1,t1,-1
+ sw t1,THREAD_DISPATCH_DISABLE_LEVEL
+ /*
+ * if ( _Thread_Dispatch_disable_level || _ISR_Nest_level )
+ * goto the label "exit interrupt (simple case)"
+ */
+ or t0,t2,t1
+ bne t0,zero,_ISR_Handler_exit
+ NOP
+
+
+ /*
+ * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+ * restore stack
+ * #endif
+ *
+ * if ( !_Thread_Dispatch_necessary )
+ * goto the label "exit interrupt (simple case)"
+ */
+ lb t0,DISPATCH_NEEDED
+ NOP
+ or t0,t0,t0
+ beq t0,zero,_ISR_Handler_exit
+ NOP
+
+/*
+** Turn on interrupts before entering Thread_Dispatch which
+** will run for a while, thus allowing new interrupts to
+** be serviced. Observe the Thread_Dispatch_disable_level interlock
+** that prevents recursive entry into Thread_Dispatch.
+*/
+
+ mfc0 t0, C0_SR
+#if __mips == 3
+ li t1,SR_EXL /* Clear EXL and Set IE to enable interrupts */
+ not t1
+ and t0,t1
+ li t1,SR_IE
+#elif __mips == 1
+ li t1,SR_IEC
+#endif
+ or t0, t1
+ mtc0 t0, C0_SR
+ NOP
+
+ /* save off our stack frame so the context switcher can get to it */
+ la t0,__exceptionStackFrame
+ STREG sp,(t0)
+
+ jal _Thread_Dispatch
+ NOP
+
+ /* and make sure its clear in case we didn't dispatch. if we did, its
+ ** already cleared */
+ la t0,__exceptionStackFrame
+ STREG zero,(t0)
+ NOP
+
+/*
+** turn interrupts back off while we restore context so
+** a badly timed interrupt won't accidentally mess things up
+*/
+ mfc0 t0, C0_SR
+#if __mips == 3
+ li t1,SR_IE /* Clear IE first (recommended) */
+ not t1
+ and t0,t1
+ mtc0 t0, C0_SR
+ li t1,SR_EXL | SR_IE /* Set EXL and IE, this puts status register bits back to interrupted state */
+ or t0,t1
+#elif __mips == 1
+ /* ints off, current & prev kernel mode on (kernel mode enabled is bit clear..argh!) */
+ li t1,SR_IEC | SR_KUP | SR_KUC
+ not t1
+ and t0, t1
+#endif
+ mtc0 t0, C0_SR
+ NOP
+
+ /*
+ * prepare to get out of interrupt
+ * return from interrupt (maybe to _ISR_Dispatch)
+ *
+ * LABEL "exit interrupt (simple case):"
+ * prepare to get out of interrupt
+ * return from interrupt
+ */
+
+_ISR_Handler_exit:
+
+/* restore interrupt context from stack */
+ LDREG t8, R_MDLO*R_SZ(sp)
+ LDREG t0, R_T0*R_SZ(sp)
+ mtlo t8
+ LDREG t8, R_MDHI*R_SZ(sp)
+ LDREG t1, R_T1*R_SZ(sp)
+ mthi t8
+ LDREG t2, R_T2*R_SZ(sp)
+ LDREG t3, R_T3*R_SZ(sp)
+ LDREG t4, R_T4*R_SZ(sp)
+ LDREG t5, R_T5*R_SZ(sp)
+ LDREG t6, R_T6*R_SZ(sp)
+ LDREG t7, R_T7*R_SZ(sp)
+ LDREG t8, R_T8*R_SZ(sp)
+ LDREG t9, R_T9*R_SZ(sp)
+ LDREG gp, R_GP*R_SZ(sp)
+ LDREG fp, R_FP*R_SZ(sp)
+ LDREG ra, R_RA*R_SZ(sp)
+ LDREG a0, R_A0*R_SZ(sp)
+ LDREG a1, R_A1*R_SZ(sp)
+ LDREG a2, R_A2*R_SZ(sp)
+ LDREG a3, R_A3*R_SZ(sp)
+ LDREG v1, R_V1*R_SZ(sp)
+ LDREG v0, R_V0*R_SZ(sp)
+
+ LDREG k1, R_EPC*R_SZ(sp)
+ mtc0 k1,C0_EPC
+
+ .set noat
+ LDREG AT, R_AT*R_SZ(sp)
+ .set at
+
+ ADDIU sp,sp,EXCP_STACK_SIZE
+
+_ISR_Handler_quick_exit:
+ eret
+ nop
+
+
+#if BSP_HAS_USC320
+ /* Interrupts from USC320 are serviced here */
+ .global USC_isr
+ .extern Clock_isr
+USC_isr:
+ /* check if it's a USC320 heartbeat interrupt */
+ la k0,INT_STAT /* read INT_STAT register */
+ lw k0,(k0)
+ nop /* reading from external device */
+ sll k0,(31-21) /* test bit 21 (HBI) */
+
+ bgez k0,USC_isr2 /* branch if not a heartbeat interrupt */
+ NOP
+
+ /* clear the heartbeat interrupt */
+ la k0,INT_STAT
+ li t0,HBI_MASK
+ sw t0,(k0)
+ /* wait for interrupt to clear */
+USC_isr1:
+ la k0,INT_STAT /* read INT_STAT register */
+ lw k0,(k0)
+ nop /* reading from external device */
+ sll k0,(31-21) /* test bit 21 (HBI) */
+ bltz k0,USC_isr1 /* branch if bit set */
+ nop
+ j Clock_isr /* Jump to clock isr */
+ nop
+USC_isr2:
+ j ra /* no serviceable interrupt, return without doing anything */
+ nop
+#endif
+
+#if 0
+ .global int7_isr
+ .extern Interrupt_7_isr
+int7_isr:
+ /* Verify interrupt is from Timer */
+ la k0,IRCS /* read Interrupt Current Status register */
+ lw k0,(k0)
+ nop /* reading from external device */
+ li k1,IRCS_CAUSE_MASK
+ and k0,k0,k1 /* isolate interrupt cause */
+
+ li k1,INT7INT /* test for interrupt 7 */
+ subu k1,k0,k1
+ beq k1,zero,int7_isr1
+ nop
+ j ra /* interrupt 7 no longer valid, return without doing anything */
+ nop
+int7_isr1:
+ j Interrupt_7_isr /* Jump to Interrupt 7 isr */
+ nop
+#endif
+
+ .set reorder
+
+ENDFRAME(bsp_ISR_Handler)
+
+
+FRAME(_BRK_Handler,sp,0,ra)
+ .set noreorder
+
+#if BSP_HAS_USC320
+ la k0,INT_CFG3 /* Disable heartbeat interrupt in USC320, it interferes with PMON exception handler */
+ lw k1,(k0)
+ li k0,~HBI_MASK
+ and k1,k1,k0
+ la k0,INT_CFG3
+ sw k1,(k0)
+#endif
+
+ la k0,_brk_esr_link /* Jump to next exception handler in PMON exception chain */
+ lw k0,(k0)
+ lw k0,4(k0)
+ j k0
+ nop
+
+ .set reorder
+ENDFRAME(_BRK_Handler)
+
+
+/**************************************************************************
+**
+** init_exc_vecs() - moves the exception code into the addresses
+** reserved for exception vectors
+**
+** UTLB Miss exception vector at address 0x80000000
+**
+** General exception vector at address 0x80000080
+**
+** RESET exception vector is at address 0xbfc00000
+**
+***************************************************************************/
+
+FRAME(init_exc_vecs,sp,0,ra)
+ .set noreorder
+
+ .extern mon_onintr
+
+/* Install interrupt handler in PMON exception handling chain */
+
+ addiu sp,sp,-8
+ sw ra,(sp) /* Save ra contents on stack */
+ move a0,zero
+ la a1,_int_esr_link
+ jal mon_onintr /* Make PMON system call to install interrupt exception handler */
+ nop
+ li a0,9
+ la a1,_brk_esr_link
+ jal mon_onintr /* Make PMON system call to install break exception handler */
+ nop
+ lw ra,(sp)
+ addiu sp,sp,8 /* Restore ra contents from stack */
+ j ra
+ nop
+
+ .set reorder
+ENDFRAME(init_exc_vecs)
+
+
+#if 0 /* Unused code below */
+
+/*************************************************************
+* enable_int7(ints)
+* Enable interrupt 7
+*/
+FRAME(enable_int7,sp,0,ra)
+ .set noreorder
+
+ la t0,IRDM1 # Set interrupt controller detection mode (bits 2-3 = 0 for int 7 active low)
+ li t1,0x0
+ sw t1,(t0)
+
+ la t0,IRLVL4 # Set interrupt controller level (bit 8-10 = 2 for int 7 at level 2)
+ li t1,0x200
+ sw t1,(t0)
+
+ la t0,IRMSK # Set interrupt controller mask
+ li t1,0x0
+ sw t1,(t0)
+
+ la t0,IRDEN # Enable interrupts from controller
+ li t1,0x1
+ sw t1,(t0)
+
+ j ra
+ nop
+ .set reorder
+ENDFRAME(enable_int7)
+
+/*************************************************************
+* disable_int7(ints)
+* Disable interrupt 7
+*/
+FRAME(disable_int7,sp,0,ra)
+ .set noreorder
+
+ la t0,IRLVL4 # Set interrupt controller level (bit 8-10 = 0 to diasble int 7)
+ li t1,0x200
+ sw t1,(t0)
+
+ j ra
+ nop
+ .set reorder
+ENDFRAME(disable_int7)
+#endif
+
+/*************************************************************
+* exception:
+* Diagnostic code that can be hooked to PMON interrupt handler.
+* Generates pulse on PIO22 pin.
+* Called from _exception code in PMON (see mips.s of PMON).
+* Return address is located in k1.
+*/
+FRAME(tx49xxexception,sp,0,ra)
+ .set noreorder
+ la k0,k1tmp
+ sw k1,(k0)
+
+/* Activate TX49xx PIO22 signal for diagnostics */
+ lui k0,0xff1f
+ ori k0,k0,0xf500
+ lw k0,(k0)
+ lui k1,0x40
+ or k1,k1,k0
+ lui k0,0xff1f
+ ori k0,k0,0xf500
+ sw k1,(k0)
+ nop
+
+/* De-activate TX49xx PIO22 signal for diagnostics */
+ lui k0,0xff1f
+ ori k0,k0,0xf500
+ lw k0,(k0)
+ lui k1,0x40
+ not k1
+ and k1,k1,k0
+ lui k0,0xff1f
+ ori k0,k0,0xf500
+ sw k1,(k0)
+ nop
+
+ la k0,k1tmp
+ lw k1,(k0)
+ j k1
+ .set reorder
+ENDFRAME(tx49xxexception)
+
+
+
+
+ .data
+
+k1tmp: .word 0 /* Temporary strage for K1 during interrupt service */
+
+/*************************************************************
+*
+* Exception handler links, used in PMON exception handler chains
+*/
+ /* Interrupt exception service routine link */
+ .global _int_esr_link
+_int_esr_link:
+ .word 0
+ .word bsp_ISR_Handler
+
+ /* Break exception service routine link */
+ .global _brk_esr_link
+_brk_esr_link:
+ .word 0
+ .word _BRK_Handler
+
+
+
+
diff --git a/bsps/mips/shared/irq/i8259.c b/bsps/mips/shared/irq/i8259.c
new file mode 100644
index 0000000000..d92b5400a9
--- /dev/null
+++ b/bsps/mips/shared/irq/i8259.c
@@ -0,0 +1,332 @@
+/**
+ * @file
+ *
+ * This file was based upon the powerpc and the i386.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+/*
+ * Copyright (C) 1998, 1999 valette@crf.canon.fr
+ */
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/i8259.h>
+#include <bsp/pci.h>
+#include <bsp/irq-generic.h>
+#include <rtems/bspIo.h>
+
+
+#define DEBUG_8259 1
+
+#define ValidateIrqLine( _irq ) \
+ if ( ((int)_irq < 0) ||((int)_irq > 16)) return 1;
+
+/*-------------------------------------------------------------------------+
+| Cache for 1st and 2nd PIC IRQ line's status (enabled or disabled) register.
++--------------------------------------------------------------------------*/
+/*
+ * lower byte is interrupt mask on the master PIC.
+ * while upper bits are interrupt on the slave PIC.
+ */
+volatile rtems_i8259_masks i8259s_cache = 0xfffb;
+
+/*-------------------------------------------------------------------------+
+| Function: BSP_irq_disable_at_i8259s
+| Description: Mask IRQ line in appropriate PIC chip.
+| Global Variables: i8259s_cache
+| Arguments: vector_offset - number of IRQ line to mask.
+| Returns: original state or -1 on error.
++--------------------------------------------------------------------------*/
+int BSP_irq_disable_at_i8259s (const rtems_irq_number irqLine)
+{
+ unsigned short mask;
+ rtems_interrupt_level level;
+ int rval;
+
+ ValidateIrqLine(irqLine);
+
+ rtems_interrupt_disable(level);
+
+ /* Recalculate the value */
+ mask = 1 << irqLine;
+ rval = i8259s_cache & mask ? 0 : 1;
+ i8259s_cache |= mask;
+
+ /* Determine which chip and write the value. */
+ if (irqLine < 8) {
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_MASTER_IMR_IO_PORT,
+ i8259s_cache & 0xff
+ );
+ } else {
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_SLAVE_IMR_IO_PORT,
+ ((i8259s_cache & 0xff00) >> 8)
+ );
+ }
+
+ rtems_interrupt_enable(level);
+
+ return rval;
+}
+
+/*-------------------------------------------------------------------------+
+| Function: BSP_irq_enable_at_i8259s
+| Description: Unmask IRQ line in appropriate PIC chip.
+| Global Variables: i8259s_cache
+| Arguments: irqLine - number of IRQ line to mask.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+int BSP_irq_enable_at_i8259s (const rtems_irq_number irqLine)
+{
+ unsigned short mask;
+ rtems_interrupt_level level;
+
+ ValidateIrqLine( irqLine );
+
+ rtems_interrupt_disable(level);
+
+ /* Calculate the value */
+ mask = ~(1 << irqLine);
+ i8259s_cache &= mask;
+
+ /* Determine which chip and write the value */
+ if (irqLine < 8) {
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_MASTER_IMR_IO_PORT,
+ i8259s_cache & 0xff
+ );
+ } else {
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_SLAVE_IMR_IO_PORT,
+ ((i8259s_cache & 0xff00) >> 8)
+ );
+ }
+
+ rtems_interrupt_enable(level);
+
+ return 0;
+} /* mask_irq */
+
+
+int BSP_irq_enabled_at_i8259s(const rtems_irq_number irqLine)
+{
+ unsigned short mask;
+
+ ValidateIrqLine( irqLine );
+
+ mask = (1 << irqLine);
+
+ return (~(i8259s_cache & mask));
+}
+
+/*-------------------------------------------------------------------------+
+| Function: BSP_irq_ack_at_i8259s
+| Description: Signal generic End Of Interrupt (EOI) to appropriate PIC.
+| Global Variables: None.
+| Arguments: irqLine - number of IRQ line to acknowledge.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+int BSP_irq_ack_at_i8259s (const rtems_irq_number irqLine)
+{
+ if (irqLine >= 8) {
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_MASTER_COMMAND_IO_PORT,
+ SLAVE_PIC_EOSI
+ );
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_SLAVE_COMMAND_IO_PORT,
+ (PIC_EOSI | (irqLine - 8))
+ );
+ }else {
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_MASTER_COMMAND_IO_PORT,
+ (PIC_EOSI | irqLine)
+ );
+ }
+
+ return 0;
+
+} /* ackIRQ */
+
+void BSP_i8259s_init(void)
+{
+ volatile uint32_t i;
+
+ simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xff );
+ simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xff );
+
+
+ /*
+ * init master 8259 interrupt controller
+ */
+
+ /* Start init sequence */
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_MASTER_COMMAND_IO_PORT,
+ 0x11
+ );
+ /* Vector base = 0 */
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_MASTER_IMR_IO_PORT,
+ 0x00
+ );
+
+ /* edge tiggered, Cascade (slave) on IRQ2 */
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_MASTER_IMR_IO_PORT,
+ 0x04
+ );
+
+ /* Select 8086 mode */
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_MASTER_IMR_IO_PORT,
+ 0x01
+ );
+
+ /*
+ * init slave interrupt controller
+ */
+
+ /* Start init sequence */
+ simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_COMMAND_IO_PORT, 0x11);
+
+ /* Vector base = 8 */
+ simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0x08);
+
+ /* edge triggered, Cascade (slave) on IRQ2 */
+ simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0x02);
+
+ /* Select 8086 mode */
+ simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0x01);
+
+ /* Mask all except cascade */
+ simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xFB);
+
+ /* Mask all */
+ simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xFF);
+
+ /*
+ * Enable all interrupts in debug mode.
+ */
+
+ if ( DEBUG_8259 ) {
+ i8259s_cache = 0x0101;
+ }
+
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_MASTER_IMR_IO_PORT,
+ i8259s_cache & 0xff
+ );
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_SLAVE_IMR_IO_PORT,
+ ((i8259s_cache & 0xff00) >> 8)
+ );
+
+ for (i=0; i<10000; i++);
+}
+
+#define PCI__GEN(bus, off, num) (((off)^((bus) << 7))+((num) << 4))
+#define PCI_INTR_ACK(bus) PCI__GEN(bus, 0x0c34, 0)
+
+volatile uint8_t master;
+volatile uint8_t slave;
+volatile uint8_t temp;
+
+void bsp_show_interrupt_regs(void);
+void bsp_show_interrupt_regs() {
+ unsigned int sr;
+ unsigned int cause;
+ unsigned int pending;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+ pending = (cause & sr & 0xff00) >> CAUSE_IPSHIFT;
+
+ master = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_COMMAND_IO_PORT);
+ slave = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_COMMAND_IO_PORT);
+
+ printk("sr: 0x%x cause: 0x%x pending: 0x%x master: 0x%x slave: 0x%x\n",
+ sr, cause, pending, master, slave
+ );
+}
+
+int BSP_i8259s_int_process()
+{
+ uint8_t irq;
+ volatile uint32_t temp;
+
+ /* Get the Interrupt */
+ irq = simple_in_le32(BSP_PCI_BASE_ADDRESS, PCI_INTR_ACK(0) );
+
+ /*
+ * Mask interrupts
+ * + Mask all except cascade on master
+ * + Mask all on slave
+ */
+ simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xFB);
+ simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xFF);
+
+ /* Call the Handler */
+ temp = irq + MALTA_SB_IRQ_0;
+ bsp_interrupt_handler_dispatch( temp );
+
+ /* Reset the interrupt on the 8259 either the master or the slave chip */
+ if (irq & 8) {
+ temp = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT);
+
+ /* Mask all */
+ simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xFF);
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_SLAVE_COMMAND_IO_PORT,
+ (PIC_EOSI + (irq&7))
+ );
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_MASTER_COMMAND_IO_PORT,
+ SLAVE_PIC_EOSI
+ );
+ } else {
+ temp = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT);
+ /* Mask all except cascade */
+ simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xFB);
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_MASTER_COMMAND_IO_PORT,
+ (PIC_EOSI+irq)
+ );
+ }
+
+ /* Restore the interrupts */
+ simple_out_8(BSP_8259_BASE_ADDRESS,PIC_MASTER_IMR_IO_PORT,i8259s_cache&0xff);
+ simple_out_8(
+ BSP_8259_BASE_ADDRESS,
+ PIC_SLAVE_IMR_IO_PORT,
+ ((i8259s_cache & 0xff00) >> 8)
+ );
+
+ return 0;
+}
diff --git a/bsps/mips/shared/irq/interruptmask.c b/bsps/mips/shared/irq/interruptmask.c
new file mode 100644
index 0000000000..c63421e569
--- /dev/null
+++ b/bsps/mips/shared/irq/interruptmask.c
@@ -0,0 +1,29 @@
+/**
+ * @file
+ *
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+
+/*
+ * This function returns a mask value which is used to select the bits
+ * in the processor status register that can be set to enable interrupts.
+ * The mask value should not include the 2 software interrupt enable bits.
+ */
+
+uint32_t mips_interrupt_mask( void )
+{
+ uint32_t interrupt_mask;
+
+ interrupt_mask = 0x0000fc00;
+ return(interrupt_mask);
+}
diff --git a/bsps/mips/shared/irq/interruptmask_TX49.c b/bsps/mips/shared/irq/interruptmask_TX49.c
new file mode 100644
index 0000000000..5b1daa57c3
--- /dev/null
+++ b/bsps/mips/shared/irq/interruptmask_TX49.c
@@ -0,0 +1,29 @@
+/**
+ * @file
+ *
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+
+/*
+ * This function returns a mask value which is used to select the bits
+ * in the processor status register that can be set to enable interrupts.
+ * The mask value should not include the 2 software interrupt enable bits.
+ */
+
+uint32_t mips_interrupt_mask( void )
+{
+ uint32_t interrupt_mask;
+
+ interrupt_mask = 0x00000400; /* Toshiba TX49 processors have a non-standard interrupt mask */
+ return(interrupt_mask);
+}
diff --git a/bsps/mips/shared/irq/irq.c b/bsps/mips/shared/irq/irq.c
new file mode 100644
index 0000000000..1c2d3b8c5b
--- /dev/null
+++ b/bsps/mips/shared/irq/irq.c
@@ -0,0 +1,101 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_interrupt
+ *
+ * @brief Interrupt support.
+ */
+
+/*
+ * Copyright (c) 2005 by Cogent Computer Systems
+ * Written by Jay Monkman <jtm@lopingdog.com>
+ *
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+
+#include <inttypes.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <libcpu/isr_entries.h>
+#include <rtems/bspIo.h>
+
+static const char *const cause_strings[32] = {
+ /* 0 */ "Int",
+ /* 1 */ "TLB Mods",
+ /* 2 */ "TLB Load",
+ /* 3 */ "TLB Store",
+ /* 4 */ "Address Load",
+ /* 5 */ "Address Store",
+ /* 6 */ "Instruction Bus Error",
+ /* 7 */ "Data Bus Error",
+ /* 8 */ "Syscall",
+ /* 9 */ "Breakpoint",
+ /* 10 */ "Reserved Instruction",
+ /* 11 */ "Coprocessor Unuseable",
+ /* 12 */ "Overflow",
+ /* 13 */ "Trap",
+ /* 14 */ "Instruction Virtual Coherency Error",
+ /* 15 */ "FP Exception",
+ /* 16 */ "Reserved 16",
+ /* 17 */ "Reserved 17",
+ /* 18 */ "Reserved 18",
+ /* 19 */ "Reserved 19",
+ /* 20 */ "Reserved 20",
+ /* 21 */ "Reserved 21",
+ /* 22 */ "Reserved 22",
+ /* 23 */ "Watch",
+ /* 24 */ "Reserved 24",
+ /* 25 */ "Reserved 25",
+ /* 26 */ "Reserved 26",
+ /* 27 */ "Reserved 27",
+ /* 28 */ "Reserved 28",
+ /* 29 */ "Reserved 29",
+ /* 30 */ "Reserved 30",
+ /* 31 */ "Data Virtual Coherency Error"
+};
+
+static inline bool bsp_irq_is_valid(rtems_vector_number vector)
+{
+ return vector <= BSP_INTERRUPT_VECTOR_MAX;
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ mips_install_isr_entries();
+ return RTEMS_SUCCESSFUL;
+}
+
+void bsp_interrupt_handler_default(rtems_vector_number vector)
+{
+ uint32_t sr;
+ uint32_t cause;
+
+ mips_get_sr( sr );
+ mips_get_cause( cause );
+
+ printk( "Unhandled exception %" PRId32 "\n", vector );
+ printk( "sr: 0x%08" PRIu32 " cause: 0x%08" PRIu32 " --> %s\n", sr, cause,
+ cause_strings[(cause >> 2) &0x1f] );
+ #if 0
+ mips_dump_exception_frame( frame );
+ #endif
+ rtems_fatal_error_occurred(1);
+}
diff --git a/bsps/mips/shared/irq/vectorexceptions.c b/bsps/mips/shared/irq/vectorexceptions.c
new file mode 100644
index 0000000000..cdfd94c136
--- /dev/null
+++ b/bsps/mips/shared/irq/vectorexceptions.c
@@ -0,0 +1,81 @@
+/**
+ * @file
+ *
+ * Common Code for Vectoring MIPS Exceptions
+ *
+ * The actual decoding of the cause register and vector number assignment
+ * is CPU model specific.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rtems/mips/iregdef.h>
+#include <rtems/mips/idtcpu.h>
+#include <rtems/bspIo.h>
+#include <bsp/irq-generic.h>
+
+struct regdef
+{
+ int offset;
+ char *name;
+};
+
+static const struct regdef dumpregs[]= {
+ { R_RA, "R_RA" }, { R_V0, "R_V0" }, { R_V1, "R_V1" },
+ { R_A0, "R_A0" }, { R_A1, "R_A1" }, { R_A2, "R_A2" },
+ { R_A3, "R_A3" }, { R_T0, "R_T0" }, { R_T1, "R_T1" },
+ { R_T2, "R_T2" }, { R_T3, "R_T3" }, { R_T4, "R_T4" },
+ { R_T5, "R_T5" }, { R_T6, "R_T6" }, { R_T7, "R_T7" },
+ { R_T8, "R_T8" }, { R_MDLO, "R_MDLO" }, { R_MDHI, "R_MDHI" },
+ { R_GP, "R_GP" }, { R_FP, "R_FP" }, { R_AT, "R_AT" },
+ { R_EPC,"R_EPC"}, { -1, NULL }
+};
+
+void _CPU_Exception_frame_print( const CPU_Exception_frame *frame )
+{
+ uint32_t *frame_u32;
+ int i, j;
+
+ frame_u32 = (uint32_t *)frame;
+ for(i=0; dumpregs[i].offset > -1; i++)
+ {
+ printk(" %s", dumpregs[i].name);
+ for(j=0; j< 7-strlen(dumpregs[i].name); j++) printk(" ");
+#if (__mips == 1 ) || (__mips == 32)
+ printk(" %08" PRIu32 "%c",
+ frame_u32[dumpregs[i].offset], (i%3) ? '\t' : '\n' );
+#elif __mips == 3
+ printk(" %08" PRIu32 "", frame_u32[2 * dumpregs[i].offset + 1] );
+ printk("%08" PRIu32 "%c",
+ frame_u32[2 * dumpregs[i].offset], (i%2) ? '\t' : '\n' );
+#endif
+ }
+ printk( "\n" );
+}
+
+/*
+ * There are constants defined for these but they should basically
+ * all be close to the same set.
+ */
+
+void mips_vector_exceptions( CPU_Interrupt_frame *frame )
+{
+ uint32_t cause;
+ uint32_t exc;
+
+ mips_get_cause( cause );
+ exc = (cause >> 2) & 0x1f;
+
+ bsp_interrupt_handler_dispatch( exc );
+}
diff --git a/bsps/or1k/generic_or1k/irq/irq.c b/bsps/or1k/generic_or1k/irq/irq.c
new file mode 100644
index 0000000000..f9a7b6426d
--- /dev/null
+++ b/bsps/or1k/generic_or1k/irq/irq.c
@@ -0,0 +1,43 @@
+/**
+ * @file
+ *
+ * @ingroup or1k_interrupt
+ *
+ * @brief Interrupt support.
+ */
+
+/*
+ * Copyright (c) 2014 Hesham ALMatary
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <rtems/inttypes.h>
+
+/* Almost all of the jobs that the following functions should
+ * do are implemented in cpukit
+ */
+
+void bsp_interrupt_handler_default(rtems_vector_number vector)
+{
+ printk("spurious interrupt: %" PRIdrtems_vector_number "\n", vector);
+}
+
+rtems_status_code bsp_interrupt_facility_initialize()
+{
+ return 0;
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+}
diff --git a/bsps/powerpc/beatnik/irq/discovery_pic.c b/bsps/powerpc/beatnik/irq/discovery_pic.c
new file mode 100644
index 0000000000..f77125c4a7
--- /dev/null
+++ b/bsps/powerpc/beatnik/irq/discovery_pic.c
@@ -0,0 +1,993 @@
+/* Interrupt driver + dispatcher for the discovery host controller */
+
+/* Author: T. Straumann, 2005-2007
+ *
+ * Acknowledgements:
+ * Valuable information was obtained from the following drivers
+ * netbsd: (C) Allegro Networks Inc; Wasabi Systems Inc.
+ * linux: (C) MontaVista, Software, Inc; Chris Zankel, Mark A. Greer.
+ * rtems: (C) Brookhaven National Laboratory; K. Feng
+ * but this implementation is original work by the author.
+ */
+
+/*
+ * Authorship
+ * ----------
+ * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was
+ * created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * The 'beatnik' BSP was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/gtreg.h>
+#include <bsp/gtintrreg.h>
+#include <rtems/bspIo.h>
+#include <bsp/vectors.h>
+#include <libcpu/byteorder.h>
+#include <libcpu/spr.h>
+
+/* dont change the order (main_lo, main_hi, gpp) which
+ * matches the interrupt numbers!
+ */
+#define MAIN_LO_IDX 0
+#define MAIN_HI_IDX 1
+#define GPP_IDX 2
+#define NUM_INTR_REGS 3
+
+
+#define SYNC() __asm__ volatile("sync")
+
+/* How many times should the ISR dispatcher check for
+ * pending interrupts until it decides that something's
+ * fishy (i.e., a user ISR fails to clear the interrupt
+ * source)
+ */
+#define MAX_SPIN_LOOPS 100
+
+/* If FASTER is defined, a few obscure I/O statements found in the linux
+ * driver are removed
+ */
+#define FASTER
+
+/* Array helper */
+#define NumberOf(arr) (sizeof(arr)/sizeof((arr)[0]))
+
+
+/* MVME6100 specific; re-define watchdog NMI pin to be a normal output
+ * so we have a way to raise an interrupt in software (GPP[26] is wired to
+ * GPP[6] on the MVME6100).
+ */
+#define MVME6100_IRQ_DEBUG 4
+
+#define GPP_WIRED_OUT_BIT_6100 26 /* CAVEAT: this is bit 26 on the 6100 */
+#define GPP_WIRED_OUT_BIT_5500 24 /* CAVEAT: this is bit 24 on the 5500 */
+#define GPP_WIRED_IN_BIT 6
+
+/* Ored mask of debugging features to enable */
+#define IRQ_DEBUG_BASIC 1
+/* This is _very_ lowlevel */
+#define IRQ_DEBUG_DISPATCHER 2
+/* Record maximal dispatching latency */
+#define IRQ_DEBUG_MAXLAT 8 /* PPC only */
+
+#define IRQ_DEBUG (0 /*|(IRQ_DEBUG_BASIC)*/|(MVME6100_IRQ_DEBUG)|(IRQ_DEBUG_MAXLAT))
+
+/**********
+ * Typedefs
+ **********/
+
+/* Set of the three relevant cause registers */
+typedef volatile unsigned IrqMask[NUM_INTR_REGS];
+
+#define REGP(x) ((volatile uint32_t *)(x))
+
+/* Information we keep about the PIC */
+typedef struct _Mv64x60PicRec {
+ /* base address as seen from CPU */
+ uintptr_t reg_base;
+
+ /* addresses of 'cause' registers */
+ volatile uint32_t *causes[NUM_INTR_REGS];
+
+ /* addresses of 'mask' registers */
+ volatile uint32_t *masks[NUM_INTR_REGS];
+
+ /* masks for all priorities. If an
+ * interrupt source has priority X,
+ * its corresponding bit is set
+ * (enabled) in mcache[i] for all
+ * i < X and cleared for i >= X
+ */
+ volatile IrqMask mcache[BSP_IRQ_MAX_PRIO+1];
+
+ /* Priority we're executing at.
+ * Thread-level is priority 0,
+ * ISRs range from 1..MAX_PRIO
+ */
+ volatile rtems_irq_prio current_priority;
+} Mv64x60PicRec, *Mv64x60Pic;
+
+/**********
+ * Globals
+ **********/
+
+
+/* Copy of the configuration */
+static rtems_irq_global_settings theConfig;
+/* PIC description */
+static Mv64x60PicRec thePic;
+
+#if (IRQ_DEBUG) & MVME6100_IRQ_DEBUG
+static unsigned long gpp_out_bit = 0;
+#endif
+
+#if (IRQ_DEBUG) & IRQ_DEBUG_MAXLAT
+unsigned long discovery_pic_max_dispatching_latency = 0;
+#ifdef __PPC__
+static inline unsigned long mftb(void)
+{
+unsigned long rval;
+ asm volatile("mftb %0":"=r"(rval));
+ return rval;
+}
+#else
+#define mftb() 0
+#endif
+#endif
+
+/**********
+ * Functions
+ **********/
+
+/* Debugging helper routines */
+static void pregs(volatile uint32_t **p)
+{
+int i;
+ for (i=NUM_INTR_REGS-1; i>=0; i--) {
+ printk(" 0x%08x", ld_le32(p[i]));
+ printk( i ? " --":"\n");
+ }
+}
+
+static void pmsks(volatile IrqMask p)
+{
+int i;
+ for (i=NUM_INTR_REGS-1; i>=0; i--) {
+ printk(" 0x%08x", p[i]);
+ printk( i ? " --":"\n");
+ }
+}
+
+static void discovery_dump_picregs(void)
+{
+ printk(" ..GPP_IRQ. -- ..MAIN_HI. -- ..MAIN_LO.\n");
+ printk("Cause:"); pregs(thePic.causes);
+ printk("Mask: "); pregs(thePic.masks);
+}
+
+/* Small inline helpers */
+
+/* return 0 if this PIC is not 'responsible' for a given irq number
+ * we also 'ignore' the GPP summary bits - these must always remain
+ * enabled.
+ */
+static inline int
+validIrqNo(rtems_irq_number irq)
+{
+ return
+ irq >= BSP_PCI_IRQ_LOWEST_OFFSET
+ && irq <= BSP_PCI_IRQ_MAX_OFFSET
+ && ! (IMH_GPP_SUM & (1<<(irq-32)));
+}
+
+/* return 0 if a given priority is outside the valid range */
+static inline int
+validPri(rtems_irq_prio pri)
+{
+ /* silence compiler warning about limited range of type;
+ * hope it never changes...
+ */
+ return /* pri>=0 && */ pri <=BSP_IRQ_MAX_PRIO;
+}
+
+/* Return position of the most significant bit that is set in 'x' */
+static inline int
+__ilog2(unsigned x)
+{
+ asm volatile("cntlzw %0, %0":"=&r"(x):"0"(x));
+ return 31-x;
+}
+
+/* Convert irq number to cause register index
+ * (array of handles in the PicRec).
+ * ASSUMES: 'irq' within valid range.
+ */
+static inline unsigned
+irqDiv32(unsigned irq)
+{
+ return (irq-BSP_PCI_IRQ_LOWEST_OFFSET)>>5;
+}
+
+/* Convert irq number to cause/mask bit number.
+ * ASSUMES: 'irq' within valid range.
+ */
+
+static inline unsigned
+irqMod32(unsigned irq)
+{
+ return (irq-BSP_PCI_IRQ_LOWEST_OFFSET)&31;
+}
+
+/* NON-ATOMICALLY set/clear bits in a MV64x60 register
+ *
+ * register contents at offset 'off' are ANDed with
+ * complement of the 'clr' mask and ORed with 'set' mask:
+ *
+ * *off = (*off & ~clr) | set
+ *
+ * ASSUMES: executed from IRQ-disabled section
+ */
+static inline void
+gt_bitmod(unsigned off, unsigned set, unsigned clr)
+{
+ st_le32(REGP(thePic.reg_base + off),
+ (ld_le32(REGP(thePic.reg_base+off)) & ~clr) | set);
+}
+
+static inline unsigned
+gt_read(unsigned off)
+{
+ return ld_le32(REGP(thePic.reg_base + off));
+}
+
+static inline void
+gt_write(unsigned off, unsigned val)
+{
+ st_le32(REGP(thePic.reg_base + off), val);
+}
+
+/* Enable interrupt number 'irq' at the PIC.
+ *
+ * Checks for valid arguments but has no way of
+ * communicating violation; prints to console
+ * if illegal arguments are given.
+ *
+ * This routine may be called from ISR level.
+ *
+ * Algorithm: set corresponding bit in masks
+ * for all priorities lower than the
+ * target irq's priority and push
+ * mask for the currently executing
+ * priority out to the PIC.
+ */
+
+void
+BSP_enable_irq_at_pic(rtems_irq_number irq)
+{
+unsigned i,j;
+unsigned long flags;
+volatile uint32_t *p;
+uint32_t v,m;
+
+ if ( !validIrqNo(irq) ) {
+/* API change - must silently ignore...
+ printk("BSP_enable_irq_at_pic: Invalid argument (irq #%i)\n",irq);
+ */
+ return;
+ }
+
+#if (IRQ_DEBUG) & IRQ_DEBUG_BASIC
+ printk("IRQ: Enable #%i;",irq);
+#endif
+
+ if ( (i=irqDiv32(irq)) > NUM_INTR_REGS ) {
+ /* This is probably a more serious error; don't ignore silently */
+ printk("BSP_enable_irq_at_pic: illegal argument\n");
+ return;
+ }
+ /* compute register pointer and bit mask */
+ p = thePic.masks[i];
+ m = 1<<irqMod32(irq);
+
+ rtems_interrupt_disable(flags);
+ {
+ /* access table from protected section to be thread-safe */
+ rtems_irq_prio pri = theConfig.irqPrioTbl[irq];
+ for ( j=0; j<pri; j++ ) {
+ thePic.mcache[j][i] |= m;
+ }
+ st_le32(p, (v=thePic.mcache[thePic.current_priority][i]));
+ /* linux driver reads back GPP mask; maybe it's wise to do the same */
+ (void)ld_le32(thePic.masks[GPP_IDX]);
+ }
+ SYNC();
+ rtems_interrupt_enable(flags);
+
+#if (IRQ_DEBUG) & IRQ_DEBUG_BASIC
+ printk(" Mask[%i]: 0x%08x -> 0x%08x\n",i,v,ld_le32(p));
+
+#endif
+}
+
+/* Disable interrupt number 'irq' at the PIC.
+ *
+ * Checks for valid arguments but has no way of
+ * communicating violation; prints to console
+ * if illegal arguments are given.
+ *
+ * This routine may be called from ISR level.
+ *
+ * Algorithm: clear corresponding bit in masks
+ * for all priorities and push the
+ * mask for the currently executing
+ * priority out to the PIC.
+ */
+
+int
+BSP_disable_irq_at_pic(rtems_irq_number irq)
+{
+unsigned i,j;
+unsigned long flags;
+volatile uint32_t *p;
+uint32_t v,m;
+int rval;
+
+ if ( !validIrqNo(irq) ) {
+/* API change - must silently ignore...
+ printk("BSP_disable_irq_at_pic: Invalid argument (irq #%i)\n",irq);
+ */
+ return -1;
+ }
+
+#if (IRQ_DEBUG) & IRQ_DEBUG_BASIC
+ printk("IRQ: Disable #%i;",irq);
+#endif
+
+ if ( (i=irqDiv32(irq)) > NUM_INTR_REGS ) {
+ /* This is probably a more serious error; don't ignore silently */
+ printk("BSP_enable_irq_at_pic: illegal argument\n");
+ return -1;
+ }
+
+ /* compute register pointer and bit mask */
+ p = thePic.masks[i];
+ m = (1<<irqMod32(irq));
+
+ rtems_interrupt_disable(flags);
+ {
+ rval = thePic.mcache[thePic.current_priority][i] & m;
+ for (j=0; j<=BSP_IRQ_MAX_PRIO; j++)
+ thePic.mcache[j][i] &= ~m;
+ st_le32(p, (v=thePic.mcache[thePic.current_priority][i]));
+ /* linux driver reads back GPP mask; maybe it's wise to do the same */
+ (void)ld_le32(thePic.masks[GPP_IDX]);
+ }
+ SYNC();
+ rtems_interrupt_enable(flags);
+
+#if (IRQ_DEBUG) & IRQ_DEBUG_BASIC
+ printk(" Mask[%i]: 0x%08x -> 0x%08x\n",i,v,ld_le32(p));
+#endif
+
+ return rval ? 1 : 0;
+}
+
+int
+BSP_irq_is_enabled_at_pic(rtems_irq_number irq)
+{
+unsigned i;
+ if ( !validIrqNo(irq) ) {
+ printk("BSP_irq_is_enabled_at_pic: Invalid argument (irq #%i)\n",irq);
+ return -1;
+ }
+
+ if ( (i=irqDiv32(irq)) > NUM_INTR_REGS ) {
+ printk("BSP_enable_irq_at_pic: illegal argument\n");
+ return -1;
+ }
+ return ld_le32(thePic.masks[i]) & (1<<irqMod32(irq)) ? 1 : 0;
+}
+
+
+/* Change priority of interrupt number 'irq' to 'pri'
+ *
+ * RETURNS: 0 on success, nonzero on failure (illegal args)
+ *
+ * NOTE: This routine must not be called from ISR level.
+ *
+ * Algorithm: Set bit corresponding to 'irq' in the masks for
+ * all priorities < pri and clear in all masks
+ * for priorities >=pri
+ */
+int
+BSP_irq_set_priority(rtems_irq_number irq, rtems_irq_prio pri)
+{
+unsigned long flags;
+volatile uint32_t *p;
+uint32_t v,m;
+unsigned i,j;
+
+ if ( thePic.current_priority > 0 ) {
+ printk("BSP_irq_set_priority: must not be called from ISR level\n");
+ return -1;
+ }
+
+ if ( !validPri(pri) ) {
+ printk("BSP_irq_set_priority: invalid argument (pri #%i)\n",pri);
+ return -1;
+ }
+
+ if ( BSP_DECREMENTER != irq ) {
+ if ( !validIrqNo(irq) ) {
+ printk("BSP_irq_set_priority: invalid argument (irq #%i)\n",irq);
+ return -1;
+ }
+
+ if ( (i=irqDiv32(irq)) > NUM_INTR_REGS ) {
+ printk("BSP_irq_set_priority: illegal argument (irq #%i not PCI?)\n", irq);
+ return -1;
+ }
+ }
+
+#if (IRQ_DEBUG) & IRQ_DEBUG_BASIC
+ printk("IRQ: Set Priority #%i -> %i;",irq,pri);
+#endif
+
+ if ( BSP_DECREMENTER == irq ) {
+ theConfig.irqPrioTbl[irq] = pri;
+ return 0;
+ }
+
+ /* compute register pointer and bit mask */
+ p = thePic.masks[i];
+ m = 1<<irqMod32(irq);
+
+ rtems_interrupt_disable(flags);
+ {
+ for (j=0; j<=BSP_IRQ_MAX_PRIO; j++) {
+ if ( j<pri )
+ thePic.mcache[j][i] |= m;
+ else
+ thePic.mcache[j][i] &= ~m;
+ }
+ theConfig.irqPrioTbl[irq] = pri;
+ st_le32(p, (v=thePic.mcache[thePic.current_priority][i]));
+ /* linux driver reads back GPP mask; maybe it's wise to do the same */
+ (void)ld_le32(thePic.masks[GPP_IDX]);
+ }
+ SYNC();
+ rtems_interrupt_enable(flags);
+
+#if (IRQ_DEBUG) & IRQ_DEBUG_BASIC
+ printk(" Mask[%i]: 0x%08x -> 0x%08x\n",i,v,ld_le32(p));
+#endif
+
+ return 0;
+}
+
+/* Initialize the PIC; routine needed by BSP framework
+ *
+ * RETURNS: NONZERO on SUCCESS, 0 on error!
+ */
+int
+BSP_setup_the_pic(rtems_irq_global_settings* config)
+{
+int i;
+ /*
+ * Store copy of configuration
+ */
+ theConfig = *config;
+
+ /* check config */
+ if ( theConfig.irqNb <= BSP_PCI_IRQ_MAX_OFFSET ) {
+ printk("BSP_setup_the_pic: FATAL ERROR: configured IRQ table too small???\n");
+ return 0;
+ }
+
+ for ( i=0; i<theConfig.irqNb; i++ ) {
+ if ( !validPri(theConfig.irqPrioTbl[i]) ) {
+ printk("BSP_setup_the_pic: invalid priority (%i) for irg #%i; setting to 1\n", theConfig.irqPrioTbl[i], i);
+ theConfig.irqPrioTbl[i]=1;
+ }
+ }
+
+ /* TODO: Detect; Switch wired-out bit; */
+ thePic.reg_base = BSP_MV64x60_BASE;
+
+ thePic.current_priority = 0;
+
+#if (IRQ_DEBUG) & MVME6100_IRQ_DEBUG
+#endif
+
+ switch ( BSP_getDiscoveryVersion(/* assert */ 1) ) {
+ case MV_64360:
+ thePic.causes[MAIN_LO_IDX] = REGP(thePic.reg_base + ICR_360_MIC_LO);
+ thePic.causes[MAIN_HI_IDX] = REGP(thePic.reg_base + ICR_360_MIC_HI);
+ thePic.masks[MAIN_LO_IDX] = REGP(thePic.reg_base + ICR_360_C0IM_LO);
+ thePic.masks[MAIN_HI_IDX] = REGP(thePic.reg_base + ICR_360_C0IM_HI);
+ break;
+
+ case GT_64260_A:
+ case GT_64260_B:
+ thePic.causes[MAIN_LO_IDX] = REGP(thePic.reg_base + ICR_260_MIC_LO);
+ thePic.causes[MAIN_HI_IDX] = REGP(thePic.reg_base + ICR_260_MIC_HI);
+ thePic.masks[MAIN_LO_IDX] = REGP(thePic.reg_base + ICR_260_CIM_LO);
+ thePic.masks[MAIN_HI_IDX] = REGP(thePic.reg_base + ICR_260_CIM_HI);
+ break;
+
+ default:
+ rtems_panic("Unable to initialize interrupt controller; unknown chip");
+ break;
+ }
+
+ thePic.causes[GPP_IDX] = REGP(thePic.reg_base + GT_GPP_Interrupt_Cause);
+ thePic.masks[GPP_IDX] = REGP(thePic.reg_base + GT_GPP_Interrupt_Mask);
+
+ /* Initialize mask cache */
+ for ( i=0; i<=BSP_IRQ_MAX_PRIO; i++ ) {
+ thePic.mcache[i][MAIN_LO_IDX] = 0;
+ /* Always enable the summary bits. Otherwise, GPP interrupts dont
+ * make it 'through' to the GPP cause
+ */
+ thePic.mcache[i][MAIN_HI_IDX] = IMH_GPP_SUM;
+ thePic.mcache[i][GPP_IDX] = 0;
+ }
+
+ /* mask and clear everything */
+ for ( i=0; i<NUM_INTR_REGS; i++ ) {
+ st_le32(thePic.causes[i], 0);
+ st_le32(thePic.masks[i], 0);
+ }
+
+ /* make sure GPP Irqs are level sensitive */
+ gt_bitmod(
+ GT_CommUnitArb_Ctrl, /* reg */
+ GT_CommUnitArb_Ctrl_GPP_Ints_Level_Sensitive, /* set */
+ 0); /* clr */
+
+ /* enable summaries */
+ st_le32(thePic.masks[MAIN_LO_IDX], thePic.mcache[thePic.current_priority][MAIN_LO_IDX]);
+ st_le32(thePic.masks[MAIN_HI_IDX], thePic.mcache[thePic.current_priority][MAIN_HI_IDX]);
+ st_le32(thePic.masks[GPP_IDX ], thePic.mcache[thePic.current_priority][GPP_IDX ]);
+
+ /* believe the interrupts are all level sensitive (which is good); we leave all the
+ * inputs configured they way the are by MotLoad...
+ */
+
+ /* Finally, enable all interrupts for which the configuration table has already
+ * a handler installed.
+ */
+ for ( i=BSP_PCI_IRQ_LOWEST_OFFSET; i<=BSP_PCI_IRQ_MAX_OFFSET; i++ ) {
+ if ( theConfig.irqHdlTbl[i].hdl != theConfig.defaultEntry.hdl ) {
+ BSP_enable_irq_at_pic(i);
+ }
+ }
+
+ return 1;
+}
+
+int discovery_pic_max_loops = 0;
+
+
+/* Change the priority level we're executing at and mask all interrupts of
+ * the same and lower priorities
+ *
+ * RETURNS old priority;
+ */
+
+static inline rtems_irq_prio
+change_executing_prio_level(rtems_irq_prio pri)
+{
+register rtems_irq_prio rval = thePic.current_priority;
+ thePic.current_priority = pri;
+ st_le32(thePic.masks[MAIN_LO_IDX], thePic.mcache[pri][MAIN_LO_IDX]);
+ st_le32(thePic.masks[MAIN_HI_IDX], thePic.mcache[pri][MAIN_HI_IDX]);
+ st_le32(thePic.masks[GPP_IDX ], thePic.mcache[pri][GPP_IDX ]);
+ /* this DOES seem to be necessary */
+ (void)ld_le32(thePic.masks[GPP_IDX]);
+ return rval;
+}
+
+/* Scan the three cause register and find the pending interrupt with
+ * the highest priority.
+ *
+ * Two facts make this quite efficient
+ * a) the PPC has an opcode for finding the number of leading zero-bits
+ * in a register (__ilog2()).
+ * b) as we proceed we mask all sources of equal or lower priorites; they won't be
+ * seen while scanning:
+ *
+ * maxpri = 0;
+ * bits = in_le32(cause);
+ * while ( bits &= mask[maxpri] ) {
+ * irq_no = __ilog2(bits);
+ * maxpri = priority[irq_no];
+ * }
+ *
+ * a) __ilog() is 1-2 machine instructions
+ * b) while loop is only executed as many times as interrupts of different
+ * priorities are pending at the same time (and only if lower-priority
+ * ones are found first; otherwise, the iteration terminates quicker).
+ *
+ * ==> highest priority source is found quickly. It takes at most
+ *
+ * BSP_IRQ_MAX_PRIO * ( ~3 reg-only instructions + 2 memory access )
+ * + 2 reg-only instructions + 1 I/O + 1 memory access.
+ *
+ *
+ */
+
+static unsigned mlc, mhc, gpc;
+
+static int decrementerPending = 0;
+#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+int decrementerIrqs = 0;
+#endif
+
+static inline unsigned
+find_highest_priority_pending_irq(rtems_irq_prio *ppri)
+{
+register int rval = -1;
+register rtems_irq_prio *pt = theConfig.irqPrioTbl + BSP_PCI_IRQ_LOWEST_OFFSET;
+register rtems_irq_prio pmax = *ppri;
+register unsigned cse,ocse;
+
+#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ discovery_dump_picregs();
+#endif
+
+ if ( decrementerPending ) {
+/* Don't flood
+#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("Decrementer IRQ pending\n");
+#endif
+*/
+ if ( theConfig.irqPrioTbl[BSP_DECREMENTER] > pmax ) {
+ pmax = theConfig.irqPrioTbl[BSP_DECREMENTER];
+ rval = BSP_DECREMENTER;
+ }
+ }
+
+ mlc = cse = ld_le32(thePic.causes[MAIN_LO_IDX]);
+#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("MAIN_LO; cse: 0x%08x, msk 0x%08x\n", cse ,thePic.mcache[pmax][MAIN_LO_IDX]);
+#endif
+ while ( cse &= thePic.mcache[pmax][MAIN_LO_IDX] ) {
+ rval = __ilog2(cse);
+ pmax = pt[rval];
+#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("Max pri IRQ now %i\n",rval);
+#endif
+ }
+ mhc = cse = ocse = ld_le32(thePic.causes[MAIN_HI_IDX]);
+#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("MAIN_HI; cse: 0x%08x, msk 0x%08x\n", cse, thePic.mcache[pmax][MAIN_HI_IDX]);
+#endif
+ /* don't look at the GPP summary; only check for 'real' MAIN_HI sources */
+ cse &= ~IMH_GPP_SUM;
+ while ( cse &= thePic.mcache[pmax][MAIN_HI_IDX] ) {
+ rval = __ilog2(cse) + 32;
+ pmax = pt[rval];
+#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("Max pri IRQ now %i\n",rval);
+#endif
+ }
+ gpc = cse = ld_le32(thePic.causes[GPP_IDX ]);
+ /* if there were GPP ints, scan the GPP cause now */
+ if ( ocse & IMH_GPP_SUM ) {
+#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("GPP; cse: 0x%08x, msk 0x%08x\n", cse, thePic.mcache[pmax][GPP_IDX ]);
+#endif
+ cse &= thePic.mcache[pmax][GPP_IDX ];
+ ocse = cse;
+ while ( cse ) {
+ rval = __ilog2(cse) + 64;
+ pmax = pt[rval];
+ cse &= thePic.mcache[pmax][GPP_IDX ];
+#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("Max pri IRQ now %i\n",rval);
+#endif
+ }
+#ifndef FASTER
+ /* this doesn't seem to be necessary -- however, the linux people do it... */
+ out_le32(thePic.causes[GPP_IDX], ~ocse);
+#endif
+ }
+#ifndef FASTER
+ /* this doesn't seem to be necessary -- however, the linux people do it... */
+ (void)in_le32(thePic.causes[GPP_IDX]);
+#endif
+
+ *ppri = pmax;
+
+ if ( BSP_DECREMENTER == rval ) {
+#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ decrementerIrqs++;
+#endif
+ decrementerPending = 0;
+ }
+
+ return rval;
+}
+
+#if 0 /* TODO: should this be cleaned up ? */
+#define _IRQ_DEBUG IRQ_DEBUG_DISPATCHER
+static inline unsigned
+ffind_highest_priority_pending_irq(rtems_irq_prio *ppri)
+{
+register int rval = -1;
+register rtems_irq_prio *pt = theConfig.irqPrioTbl + BSP_PCI_IRQ_LOWEST_OFFSET;
+register rtems_irq_prio pmax = *ppri;
+register unsigned cse,ocse;
+
+#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ discovery_dump_picregs();
+#endif
+
+ cse = in_le32(thePic.causes[MAIN_LO_IDX]);
+#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("MAIN_LO; cse: 0x%08x, msk 0x%08x\n", cse ,thePic.mcache[pmax][MAIN_LO_IDX]);
+#endif
+ while ( cse &= thePic.mcache[pmax][MAIN_LO_IDX] ) {
+ rval = __ilog2(cse);
+ pmax = pt[rval];
+#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("Max pri IRQ now %i\n",rval);
+#endif
+ }
+ cse = ocse = in_le32(thePic.causes[MAIN_HI_IDX]);
+#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("MAIN_HI; cse: 0x%08x, msk 0x%08x\n", cse, thePic.mcache[pmax][MAIN_HI_IDX]);
+#endif
+ /* don't look at the GPP summary; only check for 'real' MAIN_HI sources */
+ cse &= ~IMH_GPP_SUM;
+ while ( cse &= thePic.mcache[pmax][MAIN_HI_IDX] ) {
+ rval = __ilog2(cse) + 32;
+ pmax = pt[rval];
+#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("Max pri IRQ now %i\n",rval);
+#endif
+ }
+ /* if there were GPP ints, scan the GPP cause now */
+ if ( ocse & IMH_GPP_SUM ) {
+ cse = in_le32(thePic.causes[GPP_IDX ]);
+#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("GPP; cse: 0x%08x, msk 0x%08x\n", cse, thePic.mcache[pmax][GPP_IDX ]);
+#endif
+ cse &= thePic.mcache[pmax][GPP_IDX ];
+ ocse = cse;
+ while ( cse ) {
+ rval = __ilog2(cse) + 64;
+ pmax = pt[rval];
+ cse &= thePic.mcache[pmax][GPP_IDX ];
+#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ printk("Max pri IRQ now %i\n",rval);
+#endif
+ }
+ /* this doesn't seem to be necessary -- however, the linux people do it... */
+ out_le32(thePic.causes[GPP_IDX], ~ocse);
+ }
+ /* this doesn't seem to be necessary -- however, the linux people do it... */
+ (void)in_le32(thePic.causes[GPP_IDX]);
+
+ *ppri = pmax;
+ return rval;
+}
+#endif
+
+
+/* Here's our dispatcher; the BSP framework uses the same one for EE and decrementer
+ * exceptions...
+ */
+int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum)
+{
+register int irq;
+int loop, last_irq;
+rtems_irq_prio pri;
+#if (IRQ_DEBUG) & IRQ_DEBUG_MAXLAT
+unsigned long diff;
+#endif
+
+#if (IRQ_DEBUG) & IRQ_DEBUG_MAXLAT
+ diff = mftb();
+#endif
+
+ if (excNum == ASM_DEC_VECTOR) {
+ decrementerPending = 1;
+ }
+
+ /* Tradeoff: EITHER we loop as long as interrupts are pending
+ * incurring the overhead of one extra run of the 'find_pending_irq' routine.
+ * OR we do rely on the handler just being invoked again if multiple
+ * interrupts are pending.
+ *
+ * The first solution gives better worst-case behavior
+ * the second slightly better average performance.
+ * --> we go for the first solution. This also enables us to catch
+ * runaway interrupts, i.e., bad drivers that don't clear interrupts
+ * at the device. Can be very handy during driver development...
+ */
+ for ( loop=0, last_irq=-1, pri = thePic.current_priority;
+ (irq=find_highest_priority_pending_irq(&pri)) >=0;
+ loop++, last_irq = irq ) {
+
+ /* raise priority level and remember current one */
+ pri = change_executing_prio_level(pri);
+
+ SYNC();
+
+#if (IRQ_DEBUG) & IRQ_DEBUG_MAXLAT
+ if ( 0 == loop ) {
+ diff = mftb()-diff;
+ if ( diff > discovery_pic_max_dispatching_latency )
+ discovery_pic_max_dispatching_latency = diff;
+ }
+#endif
+
+#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER
+ if ( BSP_DECREMENTER == irq ) {
+ printk("IRQ: dispatching DECREMENTER\n");
+ } else {
+ int idx = irqDiv32(irq);
+ printk("IRQ: dispatching #%i; causes[%i]=0x%08x\n", irq, idx, ld_le32(thePic.causes[idx]));
+ }
+#endif
+
+ bsp_irq_dispatch_list( theConfig.irqHdlTbl, irq, theConfig.defaultEntry.hdl );
+
+ /* restore executing priority level */
+ (void)change_executing_prio_level(pri);
+
+ if ( (loop > MAX_SPIN_LOOPS) && (last_irq == irq) ) {
+ /* try to catch run-away interrupts without disabling a 'legal' one;
+ * this should never happen with the decrementer (and
+ * BSP_disable_irq_at_pic(BSP_DECREMENTER) would fail)
+ */
+ printk("Runaway IRQ #%i; disabling\n", irq);
+ BSP_disable_irq_at_pic(irq);
+ loop = 0;
+ }
+ }
+
+ if (!loop) {
+ if ( decrementerPending && pri >= theConfig.irqPrioTbl[BSP_DECREMENTER] ) {
+ /* we cannot mask the decrementer interrupt so it is possible that it
+ * gets delivered even though it has a lower priority than what we're
+ * currently executing at.
+ * In this case, we ignore the zero loop count and return;
+ * the interrupted instance of C_dispatch_irq_handler() will eventually
+ * lower the executing priority and catch the 'decrementerPending' flag
+ * we just set.
+ */
+ } else {
+ printk("Discovery: Spurious interrupt; causes were gpp: 0x%x, mhc: 0x%x, mlc: 0x%x\n", gpc, mhc, mlc);
+ printk("Current priority level %i, decrementerPending %i\n", pri, decrementerPending);
+ {
+ rtems_irq_prio p=pri;
+ printk("PIC register dump:\n");
+ discovery_dump_picregs();
+ printk("Current Priority: %i, found %i\n",pri,find_highest_priority_pending_irq(&p));
+ discovery_dump_picregs();
+ for (p=0; p<=BSP_IRQ_MAX_PRIO; p++) {
+ printk("M[%i] :",p);pmsks(thePic.mcache[p]);
+ }
+ }
+ }
+ }
+ else if (loop>discovery_pic_max_loops)
+ discovery_pic_max_loops = loop;
+
+ return 0;
+}
+
+
+#if (IRQ_DEBUG) & MVME6100_IRQ_DEBUG
+void
+discovery_pic_install_debug_irq(void)
+{
+ switch ( BSP_getBoardType() ) {
+ case MVME6100: gpp_out_bit = GPP_WIRED_OUT_BIT_6100; break;
+ case MVME5500: gpp_out_bit = GPP_WIRED_OUT_BIT_5500; break;
+ default:
+ gpp_out_bit = 0; break;
+ break;
+ }
+ if ( gpp_out_bit ) {
+ unsigned mppoff;
+ switch (gpp_out_bit / 8) {
+ default: /* silence warning; this is never reached */
+ case 0: mppoff = GT_MPP_Control0; break;
+ case 1: mppoff = GT_MPP_Control1; break;
+ case 2: mppoff = GT_MPP_Control2; break;
+ case 3: mppoff = GT_MPP_Control3; break;
+ }
+
+ /* switch GPP pin allocated to watchdog (value 4) to
+ * GPP I/O (value 0 ??; have no doc, found out by experimenting)
+ */
+ gt_bitmod(mppoff, 0, (0xf<<(4*(gpp_out_bit % 8))));
+
+ /* make it an output */
+ gt_bitmod(GT_GPP_IO_Control, (1<<gpp_out_bit), 0);
+
+ /* don't invert levels */
+ gt_bitmod(GT_GPP_Level_Control, 0, (1<<GPP_WIRED_IN_BIT) | (1<<gpp_out_bit));
+
+ /* clear output */
+ gt_bitmod(GT_GPP_Value, 0, 1<<gpp_out_bit);
+
+ printk("GPP levelctl now 0x%08x\n", gt_read(GT_GPP_Level_Control));
+ printk("GPP value now 0x%08x\n", gt_read(GT_GPP_Value));
+ printk("MPP ctl 0 now 0x%08x\n", gt_read(GT_MPP_Control0));
+ printk("MPP ctl 1 now 0x%08x\n", gt_read(GT_MPP_Control1));
+ printk("MPP ctl 2 now 0x%08x\n", gt_read(GT_MPP_Control2));
+ printk("MPP ctl 3 now 0x%08x\n", gt_read(GT_MPP_Control3));
+
+ }
+}
+
+/* Control the state of the external 'wire' that connects the
+ * GPP_WIRED_OUT --> GPP_WIRED_IN pins
+ */
+void
+discovery_pic_set_debug_irq(int on)
+{
+unsigned long flags, clr;
+ if ( !gpp_out_bit ) {
+ printk("discovery_pic_set_debug_irq(): unknown wire output\n");
+ return;
+ }
+ if (on) {
+ on = 1<<gpp_out_bit;
+ clr = 0;
+ } else {
+ clr = 1<<gpp_out_bit;
+ on = 0;
+ }
+ rtems_interrupt_disable(flags);
+ gt_bitmod(GT_GPP_Value, on, clr);
+ rtems_interrupt_enable(flags);
+}
+#endif
+
+#if 0
+/* Here's some code for testing */
+#endif
diff --git a/bsps/powerpc/beatnik/irq/irq_init.c b/bsps/powerpc/beatnik/irq/irq_init.c
new file mode 100644
index 0000000000..2c0554c988
--- /dev/null
+++ b/bsps/powerpc/beatnik/irq/irq_init.c
@@ -0,0 +1,110 @@
+/* irq_init.c
+ *
+ * This file contains the implementation of rtems initialization
+ * related to interrupt handling.
+ *
+ * CopyRight (C) 1999 valette@crf.canon.fr
+ *
+ * Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
+ * to make it valid for MVME2300 Motorola boards.
+ *
+ * Modified by T. Straumann for the 'beatnik' BSP.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/vectors.h>
+#include <rtems/bspIo.h>
+
+#if 0
+#include <libcpu/io.h>
+#include <libcpu/spr.h>
+#include <bsp/pci.h>
+#include <bsp/residual.h>
+#include <bsp/openpic.h>
+#include <bsp/irq.h>
+#include <bsp.h>
+#include <bsp/motorola.h>
+#endif
+
+/*
+#define SHOW_ISA_PCI_BRIDGE_SETTINGS
+*/
+
+extern unsigned int external_exception_vector_prolog_code_size[];
+extern void external_exception_vector_prolog_code(void);
+extern unsigned int decrementer_exception_vector_prolog_code_size[];
+extern void decrementer_exception_vector_prolog_code(void);
+
+/*
+ * default handler
+ */
+static void nop_func(void *arg){}
+
+static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
+static rtems_irq_global_settings initial_config;
+static rtems_irq_prio rtemsPrioTbl[BSP_IRQ_NUMBER];
+static rtems_irq_connect_data defaultIrq = {
+ name: 0,
+ hdl: nop_func,
+ handle: 0,
+ on: 0,
+ off: 0,
+ isOn: 0
+};
+
+
+ /*
+ * This code assumes the exceptions management setup has already
+ * been done. We just need to replace the exceptions that will
+ * be handled like interrupt. On mcp750/mpc750 and many PPC processors
+ * this means the decrementer exception and the external exception.
+ */
+
+void BSP_rtems_irq_mng_init(unsigned cpuId)
+{
+int i;
+
+ /*
+ * First initialize the Interrupt management hardware
+ */
+
+ /*
+ * Initialize Rtems management interrupt table
+ */
+
+ /*
+ * re-init the rtemsIrq table
+ */
+ for (i = BSP_LOWEST_OFFSET; i <= BSP_MAX_OFFSET; i++) {
+ rtemsIrq[i] = defaultIrq;
+ rtemsIrq[i].name = i;
+ rtemsPrioTbl[i] = BSP_IRQ_DEFAULT_PRIORITY;
+ }
+
+ /*
+ * Init initial Interrupt management config
+ */
+ initial_config.irqNb = BSP_IRQ_NUMBER;
+ initial_config.defaultEntry = defaultIrq;
+ initial_config.irqHdlTbl = rtemsIrq;
+ initial_config.irqBase = BSP_LOWEST_OFFSET;
+ initial_config.irqPrioTbl = rtemsPrioTbl;
+
+ if (!BSP_rtems_irq_mngt_set(&initial_config)) {
+ /*
+ * put something here that will show the failure...
+ */
+ rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
+ }
+
+#ifdef TRACE_IRQ_INIT
+ printk("RTEMS IRQ management is now operationnal\n");
+#endif
+}
+
diff --git a/bsps/powerpc/beatnik/irq/irq_test_app.c b/bsps/powerpc/beatnik/irq/irq_test_app.c
new file mode 100644
index 0000000000..cb9ff146ad
--- /dev/null
+++ b/bsps/powerpc/beatnik/irq/irq_test_app.c
@@ -0,0 +1,164 @@
+/* Init
+ *
+ * This routine is the initialization task for this test program.
+ * It is called from init_exec and has the responsibility for creating
+ * and starting the tasks that make up the test. If the time of day
+ * clock is required for the test, it should also be set to a known
+ * value by this function.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ *
+ * OAR init.c Template modified by T. Straumann who provided
+ * the implementation of this application.
+ */
+
+#define CONFIGURE_INIT
+
+#include <rtems.h>
+
+/* functions */
+rtems_task Init(
+ rtems_task_argument argument
+);
+
+/* configuration information */
+#include <bsp.h> /* for device driver prototypes */
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_MAXIMUM_TASKS 1
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#include <confdefs.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <bsp/irq.h>
+#include <rtems/bspIo.h>
+
+
+void noop(){}
+int connected() {return 1;}
+
+rtems_irq_connect_data blah = { 0, 0, noop, noop, connected };
+extern void discovery_pic_set_debug_irq();
+
+#define WIRE_IRQ (BSP_IRQ_GPP_0 + 6)
+#define ABRT_IRQ (BSP_IRQ_GPP_0 + 2)
+
+static volatile int testno=0;
+static volatile int wloops =0;
+static volatile int aloops =0;
+
+void wire_hdl()
+{
+ if ( 1 == testno ) {
+ BSP_disable_irq_at_pic(WIRE_IRQ);
+ }
+
+ if ( 2 == testno || 3 == testno ) {
+ discovery_pic_set_debug_irq(0);
+ printk("WIRE -- this message should be printed %s\n", 3==testno ? "FIRST":"SECOND");
+ } else {
+ }
+
+ /* assume the driver checks for less than 1000 loops */
+ if ( ++wloops > 1000) {
+ printk("wire IRQ. FAILURE -- driver couldn't catch runaway ISR. Disabling IRQ source.\n");
+ discovery_pic_set_debug_irq(0);
+ BSP_disable_irq_at_pic(WIRE_IRQ);
+ }
+ /*
+ */
+}
+
+void abrt_hdl()
+{
+ aloops++;
+ if ( 2 == testno || 3 == testno ) {
+ discovery_pic_set_debug_irq(1);
+ printk("ABRT -- this message should be printed %s\n", 2==testno ? "FIRST":"SECOND");
+ } else
+ printk("ABRT IRQ\n");
+
+ if ( 1== testno ) {
+ BSP_enable_irq_at_pic(WIRE_IRQ);
+ }
+ BSP_disable_irq_at_pic(ABRT_IRQ);
+}
+
+
+rtems_task Init(
+ rtems_task_argument ignored
+)
+{
+ blah.name = WIRE_IRQ;
+ blah.hdl = wire_hdl;
+ if (!BSP_install_rtems_irq_handler(&blah)) {
+ fprintf(stderr,"installing handler 1 failed\n");
+ }
+ blah.name = ABRT_IRQ;
+ blah.hdl = abrt_hdl;
+ if (!BSP_install_rtems_irq_handler(&blah)) {
+ fprintf(stderr,"installing handler 2 failed\n");
+ }
+ printf("Hello, testing the ISR dispatcher...\n");
+ printf(" 1. Trying to catch runaway interrupt\n");
+ printf(" If the system freezes, the test failed!\n");
+ fflush(stdout); sleep(1);
+ aloops = wloops = 0;
+ discovery_pic_set_debug_irq(1);
+ printf(" >>> %s\n", wloops<1000 ? "SUCCESS" : "FAILED");
+ discovery_pic_set_debug_irq(0);
+
+ testno++;
+ printf(" 2. Testing enabling / disabling interrupt from ISR\n");
+ printf(" Hit the ABORT key for this test\n");
+ fflush(stdout); sleep(1);
+ aloops = wloops = 0;
+ BSP_disable_irq_at_pic(WIRE_IRQ);
+ BSP_irq_set_priority(ABRT_IRQ,1);
+ BSP_enable_irq_at_pic(ABRT_IRQ);
+ discovery_pic_set_debug_irq(1);
+ while (!aloops)
+ ;
+ discovery_pic_set_debug_irq(0);
+ sleep(2);
+ printf(" >>> disabling ABRT IRQ from isr %s\n", 1==aloops ? "SUCCESS":"FAILURE");
+ printf(" flashing WIRE IRQ from isr %s\n", 1==wloops ? "SUCCESS":"FAILURE");
+
+
+ testno++;
+ printf(" 3. Testing interrupt priorities\n");
+ BSP_irq_set_priority(ABRT_IRQ,2);
+ BSP_irq_set_priority(WIRE_IRQ,2);
+ BSP_enable_irq_at_pic(ABRT_IRQ);
+ BSP_enable_irq_at_pic(WIRE_IRQ);
+ printf(" Hit the ABORT key for this test\n");
+ fflush(stdout); sleep(1);
+ aloops = wloops = 0;
+ while (!aloops)
+ ;
+ sleep(2);
+ testno++;
+ printf(" Now we are raising the priority of the wire interrupt\n");
+ BSP_irq_set_priority(WIRE_IRQ,3);
+ BSP_enable_irq_at_pic(ABRT_IRQ);
+ printf(" Hit the ABORT key for this test\n");
+ fflush(stdout); sleep(1);
+ aloops = wloops = 0;
+ while (!aloops)
+ ;
+
+ sleep(2);
+ printf( "That's it; we're done...\n" );
+ exit( 0 );
+}
diff --git a/bsps/powerpc/gen5200/irq/irq.c b/bsps/powerpc/gen5200/irq/irq.c
new file mode 100644
index 0000000000..11d9e3992e
--- /dev/null
+++ b/bsps/powerpc/gen5200/irq/irq.c
@@ -0,0 +1,722 @@
+/*===============================================================*\
+| Project: RTEMS generic MPC5200 BSP |
++-----------------------------------------------------------------+
+| Partially based on the code references which are named below. |
+| Adaptions, modifications, enhancements and any recent parts of |
+| the code are: |
+| Copyright (c) 2005 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.org/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the irq controller handler |
+\*===============================================================*/
+/***********************************************************************/
+/* */
+/* Module: irq.c */
+/* Date: 07/17/2003 */
+/* Purpose: RTEMS MPC5x00 CPU main interrupt handler & routines */
+/* */
+/*---------------------------------------------------------------------*/
+/* */
+/* Description: This file contains the implementation of the */
+/* functions described in irq.h */
+/* */
+/*---------------------------------------------------------------------*/
+/* */
+/* Code */
+/* References: MPC8260ads main interrupt handler & routines */
+/* Module: irc.c */
+/* Project: RTEMS 4.6.0pre1 / MCF8260ads BSP */
+/* Version 1.2 */
+/* Date: 04/18/2002 */
+/* */
+/* Author(s) / Copyright(s): */
+/* */
+/* Copyright (C) 1998, 1999 valette@crf.canon.fr */
+/* */
+/* Modified for mpc8260 Andy Dachs <a.dachs@sstl.co.uk> */
+/* Surrey Satellite Technology Limited, 2000 */
+/* Nested exception handlers not working yet. */
+/* */
+/* The license and distribution terms for this file may be */
+/* found in the file LICENSE in this distribution or at */
+/* http://www.rtems.org/license/LICENSE. */
+/* */
+/*---------------------------------------------------------------------*/
+/* */
+/* Partially based on the code references which are named above. */
+/* Adaptions, modifications, enhancements and any recent parts of */
+/* the code are under the right of */
+/* */
+/* IPR Engineering, Dachauer Straße 38, D-80335 München */
+/* Copyright(C) 2003 */
+/* */
+/*---------------------------------------------------------------------*/
+/* */
+/* IPR Engineering makes no representation or warranties with */
+/* respect to the performance of this computer program, and */
+/* specifically disclaims any responsibility for any damages, */
+/* special or consequential, connected with the use of this program. */
+/* */
+/*---------------------------------------------------------------------*/
+/* */
+/* Version history: 1.0 */
+/* */
+/***********************************************************************/
+
+#include <inttypes.h>
+
+#include <rtems.h>
+
+#include <libcpu/powerpc-utility.h>
+#include <bsp/vectors.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/mpc5200.h>
+
+/*
+ * bit in the SIU mask registers (PPC bit numbering) that should
+ * be set to enable the relevant interrupt, mask of 32 is for unused entries
+ *
+ */
+const static unsigned int SIU_MaskBit [BSP_SIU_IRQ_NUMBER] = {
+ 0, 1, 2, 3, /* smart_comm, psc1, psc2, psc3 */
+ 4, 5, 6, 7, /* irda/psc6, eth, usb, ata */
+ 8, 9, 10, 11, /* pci_ctrl, pci_sc_rx, pci_sc_tx, psc4 */
+ 12, 13, 14, 15, /* psc5,spi_modf, spi_spif, i2c1 */
+ 16, 17, 18, 19, /* i2c, can1, can2, ir_rx */
+ 20, 21, 15, 16, /* ir_rx, xlb_arb, slice_tim2, irq1, */
+ 17, 18, 19, 20, /* irq2, irq3, lo_int, rtc_pint */
+ 21, 22, 23, 24, /* rtc_sint, gpio_std, gpio_wkup, tmr0 */
+ 25, 26, 27, 28, /* tmr1, tmr2, tmr3, tmr4 */
+ 29, 30, 31, 32, /* tmr5, tmr6, tmr7, res */
+ 32, 32, 32 /* res, res, res */
+};
+
+static unsigned char irqPrioTable [BSP_SIU_IRQ_NUMBER] = {
+/* per. int. priorities (0-7) / 4bit coding / msb is HI/LO selection */
+/* msb = 0 -> non-critical per. int. is routed to main int. (LO_int) */
+/* msb = 1 -> critical per. int. is routed to critical int. (HI_int) */
+ 0xF, 0, 0, 0, /* smart_comm (do not change!), psc1, psc2, psc3 */
+ 0, 0, 0, 0, /* irda, eth, usb, ata */
+ 0, 0, 0, 0, /* pci_ctrl, pci_sc_rx, pci_sc_tx, res */
+ 0, 0, 0, 0, /* res, spi_modf, spi_spif, i2c1 */
+ 0, 0, 0, 0, /* i2c, can1, can2, ir_rx */
+ 0, 0, /* ir_rx, xlb_arb */
+/* main interrupt priorities (0-7) / 4bit coding / msb is INT/SMI selection */
+/* msb = 0 -> main int. is routed to processor INT (low vector base 0x500 ) */
+/* msb = 1 -> main int. is routed to processor SMI (low vector base 0x1400 ) */
+ 0, 0, /* slice_tim2, irq1 */
+ 0, 0, 0, 0, /* irq2, irq3, lo_int, rtc_pint */
+ 0, 0, 0, 0, /* rtc_sint, gpio_std, gpio_wkup, tmr0 */
+ 0, 0, 0, 0, /* tmr1, tmr2, tmr3, tmr4 */
+ 0, 0, 0, /* tmr5, tmr6, tmr7 */
+ /* critical interrupt priorities (0-3) / 2bit coding / no special purpose of msb */
+ 0, /* irq0 */
+ 0, 0, 0 /* slice_tim1, hi_int, ccs_wkup */
+};
+
+static uint32_t irqMaskTable [BSP_PER_IRQ_NUMBER + BSP_MAIN_IRQ_NUMBER];
+
+/*
+ * Check if symbolic IRQ name is a Processor IRQ
+ */
+static inline bool is_processor_irq( rtems_vector_number irqLine)
+{
+
+ return ((irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET)
+ && (irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET));
+}
+
+/*
+ * Check for SIU IRQ and return base index
+ */
+static inline bool is_siu_irq( rtems_vector_number irqLine)
+{
+
+ return ((irqLine <= BSP_SIU_IRQ_MAX_OFFSET)
+ && (irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET));
+}
+
+/*
+ * Check for SIU IRQ and return base index
+ */
+static inline int get_siu_irq_base_index( rtems_vector_number irqLine)
+{
+ if (irqLine <= BSP_PER_IRQ_MAX_OFFSET)
+ return BSP_PER_IRQ_LOWEST_OFFSET;
+
+ if (irqLine <= BSP_MAIN_IRQ_MAX_OFFSET)
+ return BSP_MAIN_IRQ_LOWEST_OFFSET;
+
+ if (irqLine <= BSP_CRIT_IRQ_MAX_OFFSET)
+ return BSP_CRIT_IRQ_LOWEST_OFFSET;
+
+ return -1;
+}
+
+static inline void BSP_enable_per_irq_at_siu(
+ rtems_vector_number irqLine
+)
+{
+ uint8_t lo_hi_ind = 0,
+ prio_index_offset;
+ uint32_t *reg;
+
+ /* calculate the index offset of priority value bit field */
+ prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
+
+ /* set interrupt priorities */
+ if (irqPrioTable [irqLine] <= 15) {
+
+ /* set peripheral int priority */
+ reg = (uint32_t *) (&(mpc5200.per_pri_1));
+
+ /* choose proper register */
+ reg += (irqLine >> 3);
+
+ /* set priority as given in priority table */
+ *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2)));
+
+ /* test msb (hash-bit) and set LO_/HI_int indicator */
+ if ((lo_hi_ind = (irqPrioTable [irqLine] >> 3))) {
+
+ /* set critical HI_int priority */
+ reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
+ *reg |= (irqPrioTable [BSP_SIU_IRQ_HI_INT] << 26);
+
+ /*
+ * critical interrupt handling for the 603le core is not
+ * yet supported, routing of critical interrupts is forced
+ * to core_int (bit 31 / CEb)
+ */
+ mpc5200.ext_en_type |= 1;
+
+ } else {
+ if (irqPrioTable [irqLine] <= 15) {
+ /* set main LO_int priority */
+ reg = (uint32_t *) (&(mpc5200.main_pri_1));
+ *reg |= (irqPrioTable [BSP_SIU_IRQ_LO_INT] << 16);
+ }
+ }
+ }
+
+ /* if LO_int ind., enable (unmask) main interrupt */
+ if (!lo_hi_ind) {
+ mpc5200.crit_pri_main_mask &=
+ ~(0x80000000 >> SIU_MaskBit [BSP_SIU_IRQ_LO_INT]);
+ }
+
+ /* enable (unmask) peripheral interrupt */
+ mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]);
+
+ /* FIXME: Why? */
+ mpc5200.main_pri_1;
+ mpc5200.crit_pri_main_mask;
+ mpc5200.per_pri_1;
+ mpc5200.per_mask;
+}
+
+static inline void BSP_enable_main_irq_at_siu(
+ rtems_vector_number irqLine
+)
+{
+
+ uint8_t prio_index_offset;
+ uint32_t *reg;
+
+ /* calculate the index offset of priority value bit field */
+ prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
+
+ /* set main interrupt priority */
+ if (irqPrioTable [irqLine] <= 15) {
+
+ /* set main int priority */
+ reg = (uint32_t *) (&(mpc5200.main_pri_1));
+
+ /* choose proper register */
+ reg += (irqLine >> 3);
+
+ /* set priority as given in priority table */
+ *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2)));
+
+ if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
+ /* enable external irq-pin */
+ mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
+ }
+ }
+
+ /* enable (unmask) main interrupt */
+ mpc5200.crit_pri_main_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]);
+
+}
+
+static inline void BSP_enable_crit_irq_at_siu(
+ rtems_vector_number irqLine
+)
+{
+ uint8_t prio_index_offset;
+ uint32_t *reg;
+
+ prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
+
+ /*
+ * critical interrupt handling for the 603Le core is not
+ * yet supported, routing of critical interrupts is forced
+ * to core_int (bit 31 / CEb)
+ */
+ mpc5200.ext_en_type |= 1;
+
+ /* set critical interrupt priorities */
+ if (irqPrioTable [irqLine] <= 3) {
+
+ /* choose proper register */
+ reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
+
+ /* set priority as given in priority table */
+ *reg |= (irqPrioTable [irqLine] << (30 - (prio_index_offset << 1)));
+
+ /* external irq0-pin */
+ if (irqLine == BSP_SIU_IRQ_IRQ1) {
+ /* enable external irq-pin */
+ mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset));
+ }
+ }
+}
+
+static inline void BSP_disable_per_irq_at_siu(
+ rtems_vector_number irqLine
+)
+{
+ uint8_t prio_index_offset;
+ uint32_t *reg;
+
+ /* calculate the index offset of priority value bit field */
+ prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8;
+
+ /* disable (mask) peripheral interrupt */
+ mpc5200.per_mask |= (0x80000000 >> SIU_MaskBit [irqLine]);
+
+ /* reset priority to lowest level (reset value) */
+ reg = (uint32_t *) (&(mpc5200.per_pri_1));
+ reg += (irqLine >> 3);
+ *reg &= ~(15 << (28 - (prio_index_offset << 2)));
+}
+
+static inline void BSP_disable_main_irq_at_siu(
+ rtems_vector_number irqLine
+)
+{
+ uint8_t prio_index_offset;
+ uint32_t *reg;
+
+ /* calculate the index offset of priority value bit field */
+ prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8;
+
+ /* disable (mask) main interrupt */
+ mpc5200.crit_pri_main_mask |= (0x80000000 >> SIU_MaskBit [irqLine]);
+
+ if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) {
+ /* disable external irq-pin */
+ mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
+ }
+
+ /* reset priority to lowest level (reset value) */
+ reg = (uint32_t *) (&(mpc5200.main_pri_1));
+ reg += (irqLine >> 3);
+ *reg &= ~(15 << (28 - (prio_index_offset << 2)));
+}
+
+static inline void BSP_disable_crit_irq_at_siu( rtems_vector_number
+ irqLine)
+{
+ uint8_t prio_index_offset;
+ uint32_t *reg;
+
+ prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET;
+
+ /* reset critical int priority to lowest level (reset value) */
+ reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask));
+ *reg &= ~(3 << (30 - (prio_index_offset << 1)));
+
+ if (irqLine == BSP_SIU_IRQ_IRQ1) {
+ /* disable external irq0-pin */
+ mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset));
+ }
+}
+
+/*
+ * This function enables a given siu interrupt
+ */
+void bsp_interrupt_vector_enable( rtems_vector_number vector)
+{
+ int base_index = get_siu_irq_base_index( vector);
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if (is_siu_irq( vector)) {
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable( level);
+
+ switch (base_index) {
+ case BSP_PER_IRQ_LOWEST_OFFSET:
+ BSP_enable_per_irq_at_siu( vector);
+ break;
+ case BSP_MAIN_IRQ_LOWEST_OFFSET:
+ BSP_enable_main_irq_at_siu( vector);
+ break;
+ case BSP_CRIT_IRQ_LOWEST_OFFSET:
+ BSP_enable_crit_irq_at_siu( vector);
+ break;
+ default:
+ bsp_interrupt_assert(0);
+ break;
+ }
+
+ rtems_interrupt_enable( level);
+ }
+}
+
+/*
+ * This function disables a given siu interrupt
+ */
+void bsp_interrupt_vector_disable( rtems_vector_number vector)
+{
+ int base_index = get_siu_irq_base_index( vector);
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if (is_siu_irq( vector)) {
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable( level);
+
+ switch (base_index) {
+ case BSP_PER_IRQ_LOWEST_OFFSET:
+ BSP_disable_per_irq_at_siu( vector);
+ break;
+ case BSP_MAIN_IRQ_LOWEST_OFFSET:
+ BSP_disable_main_irq_at_siu( vector);
+ break;
+ case BSP_CRIT_IRQ_LOWEST_OFFSET:
+ BSP_disable_crit_irq_at_siu( vector);
+ break;
+ default:
+ bsp_interrupt_assert(0);
+ break;
+ }
+
+ rtems_interrupt_enable( level);
+ }
+}
+
+#if (BENCHMARK_IRQ_PROCESSING == 0)
+void BSP_IRQ_Benchmarking_Reset( void)
+{
+}
+void BSP_IRQ_Benchmarking_Report( void)
+{
+}
+#else
+#include <stdio.h>
+uint64_t BSP_Starting_TBR;
+uint64_t BSP_Total_in_ISR;
+uint32_t BSP_ISR_Count;
+uint32_t BSP_Worst_ISR;
+
+#define BSP_COUNTED_IRQ 16
+uint32_t BSP_ISR_Count_Per [BSP_COUNTED_IRQ + 1];
+
+void BSP_IRQ_Benchmarking_Reset( void)
+{
+ int i;
+
+ BSP_Starting_TBR = PPC_Get_timebase_register();
+ BSP_Total_in_ISR = 0;
+ BSP_ISR_Count = 0;
+ BSP_Worst_ISR = 0;
+ for (i = 0; i < BSP_COUNTED_IRQ; i++)
+ BSP_ISR_Count_Per [i] = 0;
+}
+
+static const char *u64tostring( char *buffer, uint64_t v)
+{
+ sprintf( buffer, "%lld cycles %lld usecs", v, (v / 33));
+ return buffer;
+}
+
+void BSP_IRQ_Benchmarking_Report( void)
+{
+ uint64_t now;
+ char buffer [96];
+ int i;
+
+ now = PPC_Get_timebase_register();
+ printk( "Started at: %s\n", u64tostring( buffer, BSP_Starting_TBR));
+ printk( "Current : %s\n", u64tostring( buffer, now));
+ printk( "System up : %s\n", u64tostring( buffer, now - BSP_Starting_TBR));
+ printk( "ISRs : %d\n", BSP_ISR_Count);
+ printk( "ISRs ran : %s\n", u64tostring( buffer, BSP_Total_in_ISR));
+ printk( "Worst ISR : %s\n", u64tostring( buffer, BSP_Worst_ISR));
+ for (i = 0; i < BSP_COUNTED_IRQ; i++)
+ printk( "IRQ %d: %d\n", i, BSP_ISR_Count_Per [i]);
+ printk( "Ticks : %d\n", Clock_driver_ticks);
+}
+#endif
+
+static void dispatch(uint32_t irq, uint32_t offset, volatile uint32_t *maskreg)
+{
+ #if (ALLOW_IRQ_NESTING == 1)
+ uint32_t msr;
+ uint32_t mask = *maskreg;
+ #endif
+
+ irq += offset;
+
+ #if (ALLOW_IRQ_NESTING == 1)
+ *maskreg = mask | irqMaskTable [irq];
+ /* Make sure that the write operation completed (cache inhibited area) */
+ *maskreg;
+ msr = ppc_external_exceptions_enable();
+ #endif
+
+ bsp_interrupt_handler_dispatch(irq);
+
+ #if (ALLOW_IRQ_NESTING == 1)
+ ppc_external_exceptions_disable(msr);
+ *maskreg = mask;
+ #endif
+}
+
+/*
+ * High level IRQ handler called from shared_raw_irq_code_entry
+ */
+static int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned excNum)
+{
+ uint32_t irq;
+ uint32_t pmce;
+
+#if (BENCHMARK_IRQ_PROCESSING == 1)
+ uint64_t start,
+ stop,
+ thisTime;
+
+ start = PPC_Get_timebase_register();
+ BSP_ISR_Count++;
+ if (excNum < BSP_COUNTED_IRQ)
+ BSP_ISR_Count_Per [excNum]++;
+ else
+ printk( "not counting %d\n", excNum);
+#endif
+
+ /* get the content of main interrupt status register */
+ pmce = mpc5200.pmce;
+
+ /* critical interrupts are routed to the core_int, see premature
+ * initialization
+ */
+ while ((pmce & (PMCE_CSE_STICKY | PMCE_MSE_STICKY)) != 0) {
+ /* first: check for critical interrupt sources (hierarchical order)
+ * -> HI_int indicates peripheral sources
+ */
+ if ((pmce & PMCE_CSE_STICKY) != 0) {
+ /* get source of critical interrupt */
+ irq = PMCE_CSE_SOURCE(pmce);
+
+ switch (irq) {
+ /* peripheral HI_int interrupt source detected */
+ case 2:
+ /* check for valid peripheral interrupt source */
+ if ((pmce & PMCE_PSE_STICKY) != 0) {
+ /* get source of peripheral interrupt */
+ irq = PMCE_PSE_SOURCE(pmce);
+
+ dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
+ } else {
+ /* this case may not occur: no valid peripheral
+ * interrupt source */
+ printk( "No valid peripheral HI_int interrupt source\n");
+ }
+ break;
+
+ /* irq0, slice timer 1 or ccs wakeup detected */
+ case 0:
+ case 1:
+ case 3:
+
+ /* add proper offset for critical interrupts in the siu
+ * handler array */
+ irq += BSP_CRIT_IRQ_LOWEST_OFFSET;
+
+ /* Dispatch interrupt handlers */
+ bsp_interrupt_handler_dispatch( irq);
+
+ break;
+
+ default:
+ /* error: unknown interrupt source */
+ printk( "Unknown HI_int interrupt source\n");
+ break;
+ }
+ }
+
+ /* second: check for main interrupt sources (hierarchical order)
+ * -> LO_int indicates peripheral sources */
+ if ((pmce & PMCE_MSE_STICKY) != 0) {
+ /* get source of main interrupt */
+ irq = PMCE_MSE_SOURCE(pmce);
+
+ if (irq == 4) {
+ /* peripheral LO_int interrupt source detected */
+ /* check for valid peripheral interrupt source */
+ if ((pmce & PMCE_PSE_STICKY) != 0) {
+ /* get source of peripheral interrupt */
+ irq = PMCE_PSE_SOURCE(pmce);
+
+ dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
+ } else {
+ /* this case may not occur: no valid peripheral
+ * interrupt source */
+ printk( "No valid peripheral LO_int interrupt source\n");
+ }
+ } else if (irq <= 16) {
+ /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer
+ * 2 is always routed to SMI) */
+ dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask);
+ } else {
+ /* error: unknown interrupt source */
+ printk( "Unknown peripheral LO_int interrupt source\n");
+ }
+ }
+
+ /* force re-evaluation of interrupts */
+ mpc5200.pmce = PMCE_CSE_STICKY | PMCE_MSE_STICKY | PMCE_PSE_STICKY;
+
+ /* get the content of main interrupt status register */
+ pmce = mpc5200.pmce;
+ }
+
+#if (BENCHMARK_IRQ_PROCESSING == 1)
+ stop = PPC_Get_timebase_register();
+ thisTime = stop - start;
+ BSP_Total_in_ISR += thisTime;
+ if (thisTime > BSP_Worst_ISR)
+ BSP_Worst_ISR = thisTime;
+#endif
+
+ return 0;
+}
+
+/*
+ * setup irqMaskTable to support a priorized/nested interrupt environment
+ */
+static void setup_irqMaskTable( void)
+{
+ rtems_irq_prio prio = 0;
+ uint32_t i = 0,
+ j = 0,
+ mask = 0;
+
+ /* set up the priority dependent masks for peripheral interrupts */
+ for (i = BSP_PER_IRQ_LOWEST_OFFSET; i <= BSP_PER_IRQ_MAX_OFFSET; i++) {
+ prio = irqPrioTable [i];
+ mask = 0;
+
+ for (j = BSP_PER_IRQ_LOWEST_OFFSET; j <= BSP_PER_IRQ_MAX_OFFSET; j++) {
+ if (prio > irqPrioTable [j]) {
+ mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET));
+ }
+
+ if ((prio == irqPrioTable [j]) && (j >= i)) {
+ mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET));
+ }
+ }
+
+ irqMaskTable [i] = mask;
+ }
+
+ /* set up the priority dependent masks for main interrupts */
+ for (i = BSP_MAIN_IRQ_LOWEST_OFFSET; i <= BSP_MAIN_IRQ_MAX_OFFSET; i++) {
+ prio = irqPrioTable [i];
+ mask = 0;
+
+ for (j = BSP_MAIN_IRQ_LOWEST_OFFSET; j <= BSP_MAIN_IRQ_MAX_OFFSET; j++) {
+ if (prio > irqPrioTable [j]) {
+ mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET));
+ }
+
+ if ((prio == irqPrioTable [j]) && (j >= i)) {
+ mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET));
+ }
+ }
+
+ irqMaskTable [i] = mask;
+ }
+}
+
+/*
+ * Initialize MPC5x00 SIU interrupt management
+ */
+static void BSP_SIU_irq_init( void)
+{
+
+ /* disable all peripheral interrupts */
+ mpc5200.per_mask = 0xFFFFFC00;
+
+ /* peripheral interrupt priorities according to reset value */
+ mpc5200.per_pri_1 = 0xF0000000;
+ mpc5200.per_pri_2 = 0x00000000;
+ mpc5200.per_pri_3 = 0x00000000;
+
+ /* disable external interrupts IRQ0-4 / critical interrupts are routed to core_int */
+ mpc5200.ext_en_type = 0x0F000001;
+
+ /* disable main interrupts / crit. int. priorities according to reset values */
+ mpc5200.crit_pri_main_mask = 0x0001FFFF;
+
+ /* main priorities according to reset value */
+ mpc5200.main_pri_1 = 0;
+ mpc5200.main_pri_2 = 0;
+
+ /* reset all status indicators */
+ mpc5200.csa = 0x0001FFFF;
+ mpc5200.msa = 0x0001FFFF;
+ mpc5200.psa = 0x003FFFFF;
+ mpc5200.psa_be = 0x03000000;
+
+ setup_irqMaskTable();
+}
+
+rtems_status_code bsp_interrupt_facility_initialize( void)
+{
+ BSP_SIU_irq_init();
+
+ /* Install exception handler */
+ if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) {
+ return RTEMS_IO_ERROR;
+ }
+ if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, C_dispatch_irq_handler)) {
+ return RTEMS_IO_ERROR;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+void bsp_interrupt_handler_default( rtems_vector_number vector)
+{
+ if (vector != BSP_DECREMENTER) {
+ printk( "Spurious interrupt: 0x%08" PRIx32 "\n", vector);
+ }
+}
diff --git a/bsps/powerpc/gen83xx/irq/irq.c b/bsps/powerpc/gen83xx/irq/irq.c
new file mode 100644
index 0000000000..7a8ce3cc0b
--- /dev/null
+++ b/bsps/powerpc/gen83xx/irq/irq.c
@@ -0,0 +1,596 @@
+/*===============================================================*\
+| Project: RTEMS generic MPC83xx BSP |
++-----------------------------------------------------------------+
+| Copyright (c) 2007 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.org/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file integrates the IPIC irq controller |
+\*===============================================================*/
+
+#include <mpc83xx/mpc83xx.h>
+
+#include <rtems.h>
+
+#include <libcpu/powerpc-utility.h>
+#include <bsp/vectors.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+#define MPC83XX_IPIC_VECTOR_NUMBER 92
+
+#define MPC83XX_IPIC_IS_VALID_VECTOR( vector) ((vector) >= 0 && (vector) < MPC83XX_IPIC_VECTOR_NUMBER)
+
+#define MPC83XX_IPIC_INVALID_MASK_POSITION 255
+
+typedef struct {
+ volatile uint32_t *pend_reg;
+ volatile uint32_t *mask_reg;
+ const uint32_t bit_num;
+} BSP_isrc_rsc_t;
+
+/*
+ * data structure to handle all mask registers in the IPIC
+ *
+ * Mask positions:
+ * simsr [0] : 0 .. 31
+ * simsr [1] : 32 .. 63
+ * semsr : 64 .. 95
+ * sermr : 96 .. 127
+ */
+typedef struct {
+ uint32_t simsr_mask [2];
+ uint32_t semsr_mask;
+ uint32_t sermr_mask;
+} mpc83xx_ipic_mask_t;
+
+static const BSP_isrc_rsc_t mpc83xx_ipic_isrc_rsc [MPC83XX_IPIC_VECTOR_NUMBER] = {
+ /* vector 0 */
+ {&mpc83xx.ipic.sersr, &mpc83xx.ipic.sermr, 31},
+ {NULL, NULL, 0},
+ {NULL, NULL, 0},
+ {NULL, NULL, 0},
+ {NULL, NULL, 0},
+ {NULL, NULL, 0},
+ {NULL, NULL, 0},
+ {NULL, NULL, 0},
+ /* vector 8 */
+ {NULL, NULL, 0}, /* reserved vector 8 */
+ /* vector 9: UART1 SIxxR_H, Bit 24 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 24},
+ /* vector 10: UART2 SIxxR_H, Bit 25 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 25},
+ /* vector 11: SEC SIxxR_H, Bit 26 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 26},
+ {NULL, NULL, 0}, /* reserved vector 12 */
+ {NULL, NULL, 0}, /* reserved vector 13 */
+ /* vector 14: I2C1 SIxxR_H, Bit 29 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 29},
+ /* vector 15: I2C2 SIxxR_H, Bit 30 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 30},
+ /* vector 16: SPI SIxxR_H, Bit 31 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 31},
+ /* vector 17: IRQ1 SExxR , Bit 1 */
+ {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 1},
+ /* vector 18: IRQ2 SExxR , Bit 2 */
+ {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 2},
+ /* vector 19: IRQ3 SExxR , Bit 3 */
+ {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 3},
+ /* vector 20: IRQ4 SExxR , Bit 4 */
+ {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 4},
+ /* vector 21: IRQ5 SExxR , Bit 5 */
+ {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 5},
+ /* vector 22: IRQ6 SExxR , Bit 6 */
+ {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 6},
+ /* vector 23: IRQ7 SExxR , Bit 7 */
+ {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 7},
+ {NULL, NULL, 0}, /* reserved vector 24 */
+ {NULL, NULL, 0}, /* reserved vector 25 */
+ {NULL, NULL, 0}, /* reserved vector 26 */
+ {NULL, NULL, 0}, /* reserved vector 27 */
+ {NULL, NULL, 0}, /* reserved vector 28 */
+ {NULL, NULL, 0}, /* reserved vector 29 */
+ {NULL, NULL, 0}, /* reserved vector 30 */
+ {NULL, NULL, 0}, /* reserved vector 31 */
+ /* vector 32: TSEC1 Tx SIxxR_H , Bit 0 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 0},
+ /* vector 33: TSEC1 Rx SIxxR_H , Bit 1 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 1},
+ /* vector 34: TSEC1 Err SIxxR_H , Bit 2 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 2},
+ /* vector 35: TSEC2 Tx SIxxR_H , Bit 3 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 3},
+ /* vector 36: TSEC2 Rx SIxxR_H , Bit 4 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 4},
+ /* vector 37: TSEC2 Err SIxxR_H , Bit 5 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 5},
+ /* vector 38: USB DR SIxxR_H , Bit 6 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 6},
+ /* vector 39: USB MPH SIxxR_H , Bit 7 */
+ {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 7},
+ {NULL, NULL, 0}, /* reserved vector 40 */
+ {NULL, NULL, 0}, /* reserved vector 41 */
+ {NULL, NULL, 0}, /* reserved vector 42 */
+ {NULL, NULL, 0}, /* reserved vector 43 */
+ {NULL, NULL, 0}, /* reserved vector 44 */
+ {NULL, NULL, 0}, /* reserved vector 45 */
+ {NULL, NULL, 0}, /* reserved vector 46 */
+ {NULL, NULL, 0}, /* reserved vector 47 */
+ /* vector 48: IRQ0 SExxR , Bit 0 */
+ {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 0},
+ {NULL, NULL, 0}, /* reserved vector 49 */
+ {NULL, NULL, 0}, /* reserved vector 50 */
+ {NULL, NULL, 0}, /* reserved vector 51 */
+ {NULL, NULL, 0}, /* reserved vector 52 */
+ {NULL, NULL, 0}, /* reserved vector 53 */
+ {NULL, NULL, 0}, /* reserved vector 54 */
+ {NULL, NULL, 0}, /* reserved vector 55 */
+ {NULL, NULL, 0}, /* reserved vector 56 */
+ {NULL, NULL, 0}, /* reserved vector 57 */
+ {NULL, NULL, 0}, /* reserved vector 58 */
+ {NULL, NULL, 0}, /* reserved vector 59 */
+ {NULL, NULL, 0}, /* reserved vector 60 */
+ {NULL, NULL, 0}, /* reserved vector 61 */
+ {NULL, NULL, 0}, /* reserved vector 62 */
+ {NULL, NULL, 0}, /* reserved vector 63 */
+ /* vector 64: RTC SEC SIxxR_L , Bit 0 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 0},
+ /* vector 65: PIT SIxxR_L , Bit 1 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 1},
+ /* vector 66: PCI1 SIxxR_L , Bit 2 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 2},
+ /* vector 67: PCI2 SIxxR_L , Bit 3 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 3},
+ /* vector 68: RTC ALR SIxxR_L , Bit 4 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 4},
+ /* vector 69: MU SIxxR_L , Bit 5 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 5},
+ /* vector 70: SBA SIxxR_L , Bit 6 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 6},
+ /* vector 71: DMA SIxxR_L , Bit 7 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 7},
+ /* vector 72: GTM4 SIxxR_L , Bit 8 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 8},
+ /* vector 73: GTM8 SIxxR_L , Bit 9 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 9},
+ /* vector 74: GPIO1 SIxxR_L , Bit 10 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 10},
+ /* vector 75: GPIO2 SIxxR_L , Bit 11 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 11},
+ /* vector 76: DDR SIxxR_L , Bit 12 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 12},
+ /* vector 77: LBC SIxxR_L , Bit 13 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 13},
+ /* vector 78: GTM2 SIxxR_L , Bit 14 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 14},
+ /* vector 79: GTM6 SIxxR_L , Bit 15 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 15},
+ /* vector 80: PMC SIxxR_L , Bit 16 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 16},
+ {NULL, NULL, 0}, /* reserved vector 81 */
+ {NULL, NULL, 0}, /* reserved vector 82 */
+ {NULL, NULL, 0}, /* reserved vector 63 */
+ /* vector 84: GTM3 SIxxR_L , Bit 20 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 20},
+ /* vector 85: GTM7 SIxxR_L , Bit 21 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 21},
+ {NULL, NULL, 0}, /* reserved vector 81 */
+ {NULL, NULL, 0}, /* reserved vector 82 */
+ {NULL, NULL, 0}, /* reserved vector 63 */
+ {NULL, NULL, 0}, /* reserved vector 63 */
+ /* vector 90: GTM1 SIxxR_L , Bit 26 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 26},
+ /* vector 91: GTM5 SIxxR_L , Bit 27 */
+ {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 27}
+};
+
+static const uint8_t
+ mpc83xx_ipic_mask_position_table [MPC83XX_IPIC_VECTOR_NUMBER] = {
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ 7,
+ 6,
+ 5,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ 2,
+ 1,
+ 0,
+ 94,
+ 93,
+ 92,
+ 91,
+ 90,
+ 89,
+ 88,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ 31,
+ 30,
+ 29,
+ 28,
+ 27,
+ 26,
+ 25,
+ 24,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ 95,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ 63,
+ 62,
+ 61,
+ 60,
+ 59,
+ 58,
+ 57,
+ 56,
+ 55,
+ 54,
+ 53,
+ 52,
+ 51,
+ 50,
+ 49,
+ 48,
+ 47,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ 43,
+ 42,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ MPC83XX_IPIC_INVALID_MASK_POSITION,
+ 37,
+ 36
+};
+
+/*
+ * this array will be filled with mask values needed
+ * to temporarily disable all IRQ soures with lower or same
+ * priority of the current source (whose vector is the array index)
+ */
+static mpc83xx_ipic_mask_t mpc83xx_ipic_prio2mask [MPC83XX_IPIC_VECTOR_NUMBER];
+
+rtems_status_code mpc83xx_ipic_set_mask(
+ rtems_vector_number vector,
+ rtems_vector_number mask_vector,
+ bool mask
+)
+{
+ uint8_t pos = 0;
+ mpc83xx_ipic_mask_t *mask_entry;
+ uint32_t *mask_reg;
+ rtems_interrupt_level level;
+
+ /* Parameter check */
+ if (!MPC83XX_IPIC_IS_VALID_VECTOR( vector) ||
+ !MPC83XX_IPIC_IS_VALID_VECTOR( mask_vector)) {
+ return RTEMS_INVALID_NUMBER;
+ } else if (vector == mask_vector) {
+ return RTEMS_RESOURCE_IN_USE;
+ }
+
+ /* Position and mask entry */
+ pos = mpc83xx_ipic_mask_position_table [mask_vector];
+ mask_entry = &mpc83xx_ipic_prio2mask [vector];
+
+ /* Mask register and position */
+ if (pos < 32) {
+ mask_reg = &mask_entry->simsr_mask [0];
+ } else if (pos < 64) {
+ pos -= 32;
+ mask_reg = &mask_entry->simsr_mask [1];
+ } else if (pos < 96) {
+ pos -= 64;
+ mask_reg = &mask_entry->semsr_mask;
+ } else if (pos < 128) {
+ pos -= 96;
+ mask_reg = &mask_entry->sermr_mask;
+ } else {
+ return RTEMS_NOT_IMPLEMENTED;
+ }
+
+ /* Mask or unmask */
+ if (mask) {
+ rtems_interrupt_disable( level);
+ *mask_reg &= ~(1 << pos);
+ rtems_interrupt_enable( level);
+ } else {
+ rtems_interrupt_disable( level);
+ *mask_reg |= 1 << pos;
+ rtems_interrupt_enable( level);
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code mpc83xx_ipic_set_highest_priority_interrupt(
+ rtems_vector_number vector,
+ int type
+)
+{
+ rtems_interrupt_level level;
+ uint32_t reg = 0;
+
+ if (!MPC83XX_IPIC_IS_VALID_VECTOR( vector)) {
+ return RTEMS_INVALID_NUMBER;
+ } else if (type < 0 || type > MPC83XX_IPIC_INTERRUPT_CRITICAL) {
+ return RTEMS_INVALID_NUMBER;
+ }
+
+ rtems_interrupt_disable( level);
+ reg = mpc83xx.ipic.sicfr;
+ mpc83xx.ipic.sicfr = (reg & ~0x7f000300) | (vector << 24) | (type << 8);
+ rtems_interrupt_enable( level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * functions to enable/disable a source at the ipic
+ */
+void bsp_interrupt_vector_enable( rtems_vector_number vector)
+{
+ rtems_vector_number vecnum = vector - BSP_IPIC_IRQ_LOWEST_OFFSET;
+ const BSP_isrc_rsc_t *rsc_ptr;
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if (MPC83XX_IPIC_IS_VALID_VECTOR( vecnum)) {
+ rsc_ptr = &mpc83xx_ipic_isrc_rsc [vecnum];
+ if (rsc_ptr->mask_reg != NULL) {
+ uint32_t bit = 1U << (31 - rsc_ptr->bit_num);
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ *(rsc_ptr->mask_reg) |= bit;
+ rtems_interrupt_enable(level);
+ }
+ }
+}
+
+void bsp_interrupt_vector_disable( rtems_vector_number vector)
+{
+ rtems_vector_number vecnum = vector - BSP_IPIC_IRQ_LOWEST_OFFSET;
+ const BSP_isrc_rsc_t *rsc_ptr;
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if (MPC83XX_IPIC_IS_VALID_VECTOR( vecnum)) {
+ rsc_ptr = &mpc83xx_ipic_isrc_rsc [vecnum];
+ if (rsc_ptr->mask_reg != NULL) {
+ uint32_t bit = 1U << (31 - rsc_ptr->bit_num);
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ *(rsc_ptr->mask_reg) &= ~bit;
+ rtems_interrupt_enable(level);
+ }
+ }
+}
+
+/*
+ * IRQ Handler: this is called from the primary exception dispatcher
+ */
+static int BSP_irq_handle_at_ipic( unsigned excNum)
+{
+ int32_t vecnum;
+#ifdef GEN83XX_ENABLE_INTERRUPT_NESTING
+ mpc83xx_ipic_mask_t mask_save;
+ const mpc83xx_ipic_mask_t *mask_ptr;
+ uint32_t msr = 0;
+ rtems_interrupt_level level;
+#endif
+
+ /* Get vector number */
+ switch (excNum) {
+ case ASM_EXT_VECTOR:
+ vecnum = MPC83xx_VCR_TO_VEC( mpc83xx.ipic.sivcr);
+ break;
+ case ASM_E300_SYSMGMT_VECTOR:
+ vecnum = MPC83xx_VCR_TO_VEC( mpc83xx.ipic.smvcr);
+ break;
+ case ASM_E300_CRIT_VECTOR:
+ vecnum = MPC83xx_VCR_TO_VEC( mpc83xx.ipic.scvcr);
+ break;
+ default:
+ return 1;
+ }
+
+ /*
+ * Check the vector number, mask lower priority interrupts, enable
+ * exceptions and dispatch the handler.
+ */
+ if (MPC83XX_IPIC_IS_VALID_VECTOR( vecnum)) {
+#ifdef GEN83XX_ENABLE_INTERRUPT_NESTING
+ mask_ptr = &mpc83xx_ipic_prio2mask [vecnum];
+
+ rtems_interrupt_disable( level);
+
+ /* Save current mask registers */
+ mask_save.simsr_mask [0] = mpc83xx.ipic.simsr [0];
+ mask_save.simsr_mask [1] = mpc83xx.ipic.simsr [1];
+ mask_save.semsr_mask = mpc83xx.ipic.semsr;
+ mask_save.sermr_mask = mpc83xx.ipic.sermr;
+
+ /* Mask all lower priority interrupts */
+ mpc83xx.ipic.simsr [0] &= mask_ptr->simsr_mask [0];
+ mpc83xx.ipic.simsr [1] &= mask_ptr->simsr_mask [1];
+ mpc83xx.ipic.semsr &= mask_ptr->semsr_mask;
+ mpc83xx.ipic.sermr &= mask_ptr->sermr_mask;
+
+ rtems_interrupt_enable( level);
+
+ /* Enable all interrupts */
+ if (excNum != ASM_E300_CRIT_VECTOR) {
+ msr = ppc_external_exceptions_enable();
+ }
+#endif /* GEN83XX_ENABLE_INTERRUPT_NESTING */
+
+ /* Dispatch interrupt handlers */
+ bsp_interrupt_handler_dispatch( vecnum + BSP_IPIC_IRQ_LOWEST_OFFSET);
+
+#ifdef GEN83XX_ENABLE_INTERRUPT_NESTING
+ /* Restore machine state */
+ if (excNum != ASM_E300_CRIT_VECTOR) {
+ ppc_external_exceptions_disable( msr);
+ }
+
+ /* Restore initial masks */
+ rtems_interrupt_disable( level);
+ mpc83xx.ipic.simsr [0] = mask_save.simsr_mask [0];
+ mpc83xx.ipic.simsr [1] = mask_save.simsr_mask [1];
+ mpc83xx.ipic.semsr = mask_save.semsr_mask;
+ mpc83xx.ipic.sermr = mask_save.sermr_mask;
+ rtems_interrupt_enable( level);
+#endif /* GEN83XX_ENABLE_INTERRUPT_NESTING */
+ } else {
+ bsp_interrupt_handler_default( vecnum);
+ }
+
+ return 0;
+}
+
+/*
+ * Fill the array mpc83xx_ipic_prio2mask to allow masking of lower prio sources
+ * to implement nested interrupts.
+ */
+static rtems_status_code mpc83xx_ipic_calc_prio2mask(void)
+{
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+
+ /*
+ * FIXME: fill the array
+ */
+ return rc;
+}
+
+/*
+ * Activate the interrupt controller
+ */
+static rtems_status_code mpc83xx_ipic_initialize(void)
+{
+ /*
+ * mask off all interrupts
+ */
+ mpc83xx.ipic.simsr [0] = 0;
+ mpc83xx.ipic.simsr [1] = 0;
+ mpc83xx.ipic.semsr = 0;
+ mpc83xx.ipic.sermr = 0;
+ /*
+ * set desired configuration as defined in bspopts.h
+ * normally, the default values should be fine
+ */
+#if defined( BSP_SICFR_VAL) /* defined in bspopts.h ? */
+ mpc83xx.ipic.sicfr = BSP_SICFR_VAL;
+#endif
+
+ /*
+ * set desired priorities as defined in bspopts.h
+ * normally, the default values should be fine
+ */
+#if defined( BSP_SIPRR0_VAL) /* defined in bspopts.h ? */
+ mpc83xx.ipic.siprr [0] = BSP_SIPRR0_VAL;
+#endif
+
+#if defined( BSP_SIPRR1_VAL) /* defined in bspopts.h ? */
+ mpc83xx.ipic.siprr [1] = BSP_SIPRR1_VAL;
+#endif
+
+#if defined( BSP_SIPRR2_VAL) /* defined in bspopts.h ? */
+ mpc83xx.ipic.siprr [2] = BSP_SIPRR2_VAL;
+#endif
+
+#if defined( BSP_SIPRR3_VAL) /* defined in bspopts.h ? */
+ mpc83xx.ipic.siprr [3] = BSP_SIPRR3_VAL;
+#endif
+
+#if defined( BSP_SMPRR0_VAL) /* defined in bspopts.h ? */
+ mpc83xx.ipic.smprr [0] = BSP_SMPRR0_VAL;
+#endif
+
+#if defined( BSP_SMPRR1_VAL) /* defined in bspopts.h ? */
+ mpc83xx.ipic.smprr [1] = BSP_SMPRR1_VAL;
+#endif
+
+#if defined( BSP_SECNR_VAL) /* defined in bspopts.h ? */
+ mpc83xx.ipic.secnr = BSP_SECNR_VAL;
+#endif
+
+ /*
+ * calculate priority masks
+ */
+ return mpc83xx_ipic_calc_prio2mask();
+}
+
+static int mpc83xx_exception_handler(
+ BSP_Exception_frame *frame,
+ unsigned exception_number
+)
+{
+ return BSP_irq_handle_at_ipic( exception_number);
+}
+
+rtems_status_code bsp_interrupt_facility_initialize()
+{
+ /* Install exception handler */
+ if (ppc_exc_set_handler( ASM_EXT_VECTOR, mpc83xx_exception_handler)) {
+ return RTEMS_IO_ERROR;
+ }
+ if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, mpc83xx_exception_handler)) {
+ return RTEMS_IO_ERROR;
+ }
+ if (ppc_exc_set_handler( ASM_E300_CRIT_VECTOR, mpc83xx_exception_handler)) {
+ return RTEMS_IO_ERROR;
+ }
+
+ /* Initialize the interrupt controller */
+ return mpc83xx_ipic_initialize();
+}
diff --git a/bsps/powerpc/haleakala/irq/irq.c b/bsps/powerpc/haleakala/irq/irq.c
new file mode 100644
index 0000000000..c9607a032d
--- /dev/null
+++ b/bsps/powerpc/haleakala/irq/irq.c
@@ -0,0 +1,237 @@
+/*
+ *
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ *
+ * Middleware support for PPC405 by M.Hamel ADInstruments Ltd 2008
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq_supp.h>
+#include <bsp/vectors.h>
+#include <libcpu/powerpc-utility.h>
+
+
+/* PPC405EX UIC numbers */
+#define UIC_DCR_BASE 0xc0
+#define UIC0_SR (UIC_DCR_BASE+0x0) /* UIC status */
+#define UIC0_SRS (UIC_DCR_BASE+0x1) /* UIC status set */
+#define UIC0_ER (UIC_DCR_BASE+0x2) /* UIC enable */
+#define UIC0_CR (UIC_DCR_BASE+0x3) /* UIC critical */
+#define UIC0_PR (UIC_DCR_BASE+0x4) /* UIC polarity */
+#define UIC0_TR (UIC_DCR_BASE+0x5) /* UIC triggering */
+#define UIC0_MSR (UIC_DCR_BASE+0x6) /* UIC masked status */
+#define UIC0_VR (UIC_DCR_BASE+0x7) /* UIC vector */
+#define UIC0_VCR (UIC_DCR_BASE+0x8) /* UIC vector configuration */
+
+#define UIC1_SR (UIC_DCR_BASE+0x10) /* UIC status */
+#define UIC1_SRS (UIC_DCR_BASE+0x11) /* UIC status set */
+#define UIC1_ER (UIC_DCR_BASE+0x12) /* UIC enable */
+#define UIC1_CR (UIC_DCR_BASE+0x13) /* UIC critical */
+#define UIC1_PR (UIC_DCR_BASE+0x14) /* UIC polarity */
+#define UIC1_TR (UIC_DCR_BASE+0x15) /* UIC triggering */
+#define UIC1_MSR (UIC_DCR_BASE+0x16) /* UIC masked status */
+#define UIC1_VR (UIC_DCR_BASE+0x17) /* UIC vector */
+#define UIC1_VCR (UIC_DCR_BASE+0x18) /* UIC vector configuration */
+
+#define UIC2_SR (UIC_DCR_BASE+0x20) /* UIC status */
+#define UIC2_SRS (UIC_DCR_BASE+0x21) /* UIC status set */
+#define UIC2_ER (UIC_DCR_BASE+0x22) /* UIC enable */
+#define UIC2_CR (UIC_DCR_BASE+0x23) /* UIC critical */
+#define UIC2_PR (UIC_DCR_BASE+0x24) /* UIC polarity */
+#define UIC2_TR (UIC_DCR_BASE+0x25) /* UIC triggering */
+#define UIC2_MSR (UIC_DCR_BASE+0x26) /* UIC masked status */
+#define UIC2_VR (UIC_DCR_BASE+0x27) /* UIC vector */
+#define UIC2_VCR (UIC_DCR_BASE+0x28) /* UIC vector configuration */
+
+enum { kUICWords = 3 };
+
+static rtems_irq_connect_data* rtems_hdl_tblP;
+static rtems_irq_connect_data dflt_entry;
+
+static uint32_t gEnabledInts[kUICWords]; /* 1-bits mean enabled */
+static uint32_t gIntInhibited[kUICWords]; /* 1-bits disable, overriding gEnabledInts because the interrupt
+ is being processed in C_dispatch_irq_handler */
+
+static inline int IsUICIRQ(const rtems_irq_number irqLine)
+{
+ return (((int) irqLine <= BSP_UIC_IRQ_MAX_OFFSET) &&
+ ((int) irqLine >= BSP_UIC_IRQ_LOWEST_OFFSET)
+ );
+}
+
+static void WriteIState(void)
+/* Write the gEnabledInts state masked by gIntInhibited to the hardware */
+{
+ PPC_SET_DEVICE_CONTROL_REGISTER(UIC0_ER,
+ gEnabledInts[0] & ~gIntInhibited[0]);
+ PPC_SET_DEVICE_CONTROL_REGISTER(UIC1_ER,
+ gEnabledInts[1] & ~gIntInhibited[1]);
+ PPC_SET_DEVICE_CONTROL_REGISTER(UIC2_ER,
+ gEnabledInts[2] & ~gIntInhibited[2]);
+}
+
+void
+BSP_enable_irq_at_pic(const rtems_irq_number irq)
+/* Enable an interrupt; this can be called from inside C_dispatch_irq_handler */
+{
+ if (IsUICIRQ(irq)) {
+ /* Set relevant bit in the state, write state to the UIC */
+ gEnabledInts[irq>>5] |= (0x80000000 >> (irq & 0x1F));
+ WriteIState();
+ }
+}
+
+int
+BSP_disable_irq_at_pic(const rtems_irq_number irq)
+/* Enable an interrupt; this can be called from inside C_dispatch_irq_handler */
+{
+ if (IsUICIRQ(irq)) {
+ uint32_t oldState;
+ int iword = irq>>5;
+ uint32_t mask = (0x80000000 >> (irq & 0x1F));
+
+ oldState = gEnabledInts[iword] & mask;
+ gEnabledInts[iword] &= ~mask;
+ WriteIState();
+ return oldState ? 1 : 0;
+ } else
+ return -1;
+}
+
+int
+BSP_setup_the_pic(rtems_irq_global_settings* config)
+{
+ int i;
+
+ dflt_entry = config->defaultEntry;
+ rtems_hdl_tblP = config->irqHdlTbl;
+ for (i=0; i<kUICWords; i++)
+ gIntInhibited[i] = 0;
+
+ /* disable all interrupts */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC2_ER, 0x00000000);
+ /* Set Critical / Non Critical interrupts */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC2_CR, 0x00000000);
+ /* Set Interrupt Polarities */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC2_PR, 0xf7ffffff);
+ /* Set Interrupt Trigger Levels */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC2_TR, 0x01e1fff8);
+ /* Set Vect base=0,INT31 Highest priority */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC2_VR, 0x00000001);
+ /* clear all interrupts */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC2_SR, 0xffffffff);
+
+ /* disable all interrupts */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC1_ER, 0x00000000);
+ /* Set Critical / Non Critical interrupts */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC1_CR, 0x00000000);
+ /* Set Interrupt Polarities */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC1_PR, 0xfffac785);
+ /* Set Interrupt Trigger Levels */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC1_TR, 0x001d0040);
+ /* Set Vect base=0,INT31 Highest priority */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC1_VR, 0x00000001);
+ /* clear all interrupts */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC1_SR, 0xffffffff);
+
+ /* Disable all interrupts except cascade UIC0 and UIC1 */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC0_ER, 0x0000000a);
+ /* Set Critical / Non Critical interrupts */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC0_CR, 0x00000000);
+ /* Set Interrupt Polarities */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC0_PR, 0xffbfefef);
+ /* Set Interrupt Trigger Levels */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC0_TR, 0x00007000);
+ /* Set Vect base=0,INT31 Highest priority */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC0_VR, 0x00000001);
+ /* clear all interrupts */
+ PPC_SET_DEVICE_CONTROL_REGISTER (UIC0_SR, 0xffffffff);
+
+ return 1;
+}
+
+
+/*
+ * High level IRQ handler called from shared_raw_irq_code_entry; decode and
+ * dispatch. Note that this routine needs to be re-entrant
+ *
+ * No support for critical interrupts here yet
+ */
+
+int
+C_dispatch_irq_handler( BSP_Exception_frame* frame, unsigned int excNum )
+{
+ if (excNum == ASM_EXT_VECTOR) {
+ uint32_t active[kUICWords];
+
+ /* Fetch the masked flags that tell us what external ints are active.
+ Likely to be only one, but we need to handle more than one,
+ OR the flags into gIntInhibited */
+ active[0] = PPC_DEVICE_CONTROL_REGISTER(UIC0_MSR);
+ active[1] = PPC_DEVICE_CONTROL_REGISTER(UIC1_MSR);
+ active[2] = PPC_DEVICE_CONTROL_REGISTER(UIC2_MSR);
+ gIntInhibited[0] |= active[0];
+ gIntInhibited[1] |= active[1];
+ gIntInhibited[2] |= active[2];
+
+ /* ...and update the hardware so the active interrupts are disabled */
+ WriteIState();
+
+ /* Loop, calling bsp_irq_dispatch_list for each active interrupt */
+ while ((active[0] | active[1] | active[2]) != 0) {
+ uint32_t index = -1;
+ uint32_t bit, bmask;
+
+ /* Find an active interrupt, searching 0..2, bit 0..bit 31 (IBM order) */
+ do {
+ index++;
+ asm volatile (" cntlzw %0, %1":"=r" (bit):"r" (active[index]));
+ } while (bit==32);
+
+ /* Call the matching handler */
+ bsp_irq_dispatch_list(rtems_hdl_tblP, (index*32)+bit, dflt_entry.hdl);
+
+ /* Write a 1-bit to the appropriate status register to clear it */
+ bmask = 0x80000000 >> bit;
+ switch (index) {
+ case 0:
+ PPC_SET_DEVICE_CONTROL_REGISTER(UIC0_SR, bmask);
+ break;
+ case 1:
+ PPC_SET_DEVICE_CONTROL_REGISTER(UIC1_SR, bmask);
+ break;
+ case 2:
+ PPC_SET_DEVICE_CONTROL_REGISTER(UIC2_SR, bmask);
+ break;
+ }
+
+ /* Clear in the active record and gIntInhibited */
+ active[index] &= ~bmask;
+ gIntInhibited[index] &= ~bmask;
+ };
+
+ /* Update the hardware again so the interrupts we have handled are unmasked */
+ WriteIState();
+ return 0;
+
+ } else if (excNum == ASM_DEC_VECTOR) { /* 0x1000 remapped by C_dispatch_dec_handler_bookE */
+ bsp_irq_dispatch_list(rtems_hdl_tblP, BSP_PIT, dflt_entry.hdl);
+ return 0;
+
+ } else if (excNum == ASM_BOOKE_FIT_VECTOR) { /* 0x1010 mapped to 0x13 by ppc_get_vector_addr */
+ bsp_irq_dispatch_list(rtems_hdl_tblP, BSP_FIT, dflt_entry.hdl);
+ return 0;
+
+ } else if (excNum == ASM_BOOKE_WDOG_VECTOR) { /* 0x1020 mapped to 0x14 by ppc_get_vector_addr */
+ bsp_irq_dispatch_list(rtems_hdl_tblP, BSP_WDOG, dflt_entry.hdl);
+ return 0;
+
+ } else
+ return -1; /* unhandled interrupt, panic time */
+}
+
diff --git a/bsps/powerpc/haleakala/irq/irq_init.c b/bsps/powerpc/haleakala/irq/irq_init.c
new file mode 100644
index 0000000000..d48855a979
--- /dev/null
+++ b/bsps/powerpc/haleakala/irq/irq_init.c
@@ -0,0 +1,96 @@
+/*===============================================================*\
+| Project: RTEMS Haleakala BSP |
+| * by Michael Hamel ADInstruments Ltd 2008 |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.org/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the irq controller handler |
+\*===============================================================*/
+#include <libcpu/spr.h>
+#include <bsp/irq.h>
+#include <bsp.h>
+#include <bsp/vectors.h>
+#include <rtems/bspIo.h>
+#include <rtems/powerpc/powerpc.h>
+
+
+/*
+ * default on/off function
+ */
+static void nop_func(void)
+{
+}
+
+/*
+ * default isOn function
+ */
+static int not_connected(void)
+{
+ return 0;
+}
+
+static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
+static rtems_irq_global_settings initial_config;
+static rtems_irq_connect_data defaultIrq = {
+ .name = 0,
+ .hdl = NULL,
+ .handle = NULL,
+ .on = (rtems_irq_enable) nop_func,
+ .off = (rtems_irq_disable) nop_func,
+ .isOn = (rtems_irq_is_enabled) not_connected,
+#ifdef BSP_SHARED_HANDLER_SUPPORT
+ .next_handler = NULL
+#endif
+};
+
+static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={
+ /*
+ * Processor exceptions handled as interrupts
+ */
+ 0
+};
+
+ /*
+ * This code assumes the exceptions management setup has already
+ * been done. We just need to replace the exceptions that will
+ * be handled like interrupt. On mcp750/mpc750 and many PPC processors
+ * this means the decrementer exception and the external exception.
+ */
+
+void BSP_rtems_irq_mng_init(unsigned cpuId)
+{
+ int i;
+
+ /*
+ * re-init the rtemsIrq table
+ */
+ for (i = 0; i < BSP_IRQ_NUMBER; i++) {
+ rtemsIrq[i] = defaultIrq;
+ rtemsIrq[i].name = i;
+ }
+ /*
+ * Init initial Interrupt management config
+ */
+ initial_config.irqNb = BSP_IRQ_NUMBER;
+ initial_config.defaultEntry = defaultIrq;
+ initial_config.irqHdlTbl = rtemsIrq;
+ initial_config.irqBase = BSP_LOWEST_OFFSET;
+ initial_config.irqPrioTbl = irqPrioTable;
+
+ if (!BSP_rtems_irq_mngt_set(&initial_config)) {
+ /*
+ * put something here that will show the failure...
+ */
+ rtems_panic(
+ "Unable to initialize RTEMS interrupt management!!! System locked\n"
+ );
+ }
+
+ #ifdef TRACE_IRQ_INIT
+ printk("RTEMS IRQ management is now operational\n");
+ #endif
+}
diff --git a/bsps/powerpc/mpc8260ads/irq/irq.c b/bsps/powerpc/mpc8260ads/irq/irq.c
new file mode 100644
index 0000000000..baca1e0e05
--- /dev/null
+++ b/bsps/powerpc/mpc8260ads/irq/irq.c
@@ -0,0 +1,372 @@
+/*
+ *
+ * This file contains the implementation of the function described in irq.h
+ *
+ * Copyright (C) 1998, 1999 valette@crf.canon.fr
+ *
+ * Modified for mpc8260 Andy Dachs <a.dachs@sstl.co.uk>
+ * Surrey Satellite Technology Limited, 2000
+ * 21/4/2002 Added support for nested interrupts and improved
+ * masking operations. Now we compute priority mask based
+ * on table in irq_init.c
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <rtems.h>
+#include <rtems/bspIo.h>
+#include <bsp/vectors.h>
+#include <mpc8260.h>
+
+/*
+ * Check if symbolic IRQ name is an CPM IRQ
+ */
+static inline int is_cpm_irq(const rtems_irq_number irqLine)
+{
+ return (((int) irqLine <= BSP_CPM_IRQ_MAX_OFFSET) &
+ ((int) irqLine >= BSP_CPM_IRQ_LOWEST_OFFSET)
+ );
+}
+
+typedef struct {
+ uint32_t mask_h; /* mask for sipnr_h and simr_h */
+ uint32_t mask_l; /* mask for sipnr_l and simr_l */
+ uint32_t priority_h; /* mask this and lower priority ints */
+ uint32_t priority_l;
+} m82xxIrqMasks_t;
+
+static unsigned char irqPrioTable[BSP_CPM_IRQ_NUMBER]={
+ /*
+ * actual priorities for interrupt :
+ */
+ /*
+ * CPM Interrupts
+ */
+ 0, 45, 63, 44, 66, 68, 35, 39, 50, 62, 34, 0, 30, 40, 52, 58,
+ 2, 3, 0, 5, 15, 16, 17, 18, 49, 51, 0, 0, 0, 0, 0, 0,
+ 6, 7, 8, 0, 11, 12, 0, 0, 20, 21, 22, 23, 0, 0, 0, 0,
+ 29, 31, 33, 37, 38, 41, 47, 48, 55, 56, 57, 60, 64, 65, 69, 70,
+
+};
+
+/*
+ * Mask fields should have a '1' in the bit position for that
+ * interrupt.
+ * Priority masks calculated later based on priority table
+ */
+
+static m82xxIrqMasks_t SIU_MaskBit[BSP_CPM_IRQ_NUMBER] =
+{
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* err */
+ { 0x00000000, 0x00008000, 0x00000000, 0x00000000 }, /* i2c */
+ { 0x00000000, 0x00004000, 0x00000000, 0x00000000 }, /* spi */
+ { 0x00000000, 0x00002000, 0x00000000, 0x00000000 }, /* rtt */
+ { 0x00000000, 0x00001000, 0x00000000, 0x00000000 }, /* smc1 */
+ { 0x00000000, 0x00000800, 0x00000000, 0x00000000 }, /* smc2 */
+ { 0x00000000, 0x00000400, 0x00000000, 0x00000000 }, /* idma1 */
+ { 0x00000000, 0x00000200, 0x00000000, 0x00000000 }, /* idma2 */
+ { 0x00000000, 0x00000100, 0x00000000, 0x00000000 }, /* idma3 */
+ { 0x00000000, 0x00000080, 0x00000000, 0x00000000 }, /* idma4 */
+ { 0x00000000, 0x00000040, 0x00000000, 0x00000000 }, /* sdma */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x00000010, 0x00000000, 0x00000000 }, /* tmr1 */
+ { 0x00000000, 0x00000008, 0x00000000, 0x00000000 }, /* tmr2 */
+ { 0x00000000, 0x00000004, 0x00000000, 0x00000000 }, /* tmr3 */
+ { 0x00000000, 0x00000002, 0x00000000, 0x00000000 }, /* tmr4 */
+ { 0x00000004, 0x00000000, 0x00000000, 0x00000000 }, /* tmcnt */
+ { 0x00000002, 0x00000000, 0x00000000, 0x00000000 }, /* pit */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00004000, 0x00000000, 0x00000000, 0x00000000 }, /* irq1 */
+ { 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* irq2 */
+ { 0x00001000, 0x00000000, 0x00000000, 0x00000000 }, /* irq3 */
+ { 0x00000800, 0x00000000, 0x00000000, 0x00000000 }, /* irq4 */
+ { 0x00000400, 0x00000000, 0x00000000, 0x00000000 }, /* irq5 */
+ { 0x00000200, 0x00000000, 0x00000000, 0x00000000 }, /* irq6 */
+ { 0x00000100, 0x00000000, 0x00000000, 0x00000000 }, /* irq7 */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x80000000, 0x00000000, 0x00000000 }, /* fcc1 */
+ { 0x00000000, 0x40000000, 0x00000000, 0x00000000 }, /* fcc2 */
+ { 0x00000000, 0x20000000, 0x00000000, 0x00000000 }, /* fcc3 */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x08000000, 0x00000000, 0x00000000 }, /* mcc1 */
+ { 0x00000000, 0x04000000, 0x00000000, 0x00000000 }, /* mcc2 */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x00800000, 0x00000000, 0x00000000 }, /* scc1 */
+ { 0x00000000, 0x00400000, 0x00000000, 0x00000000 }, /* scc2 */
+ { 0x00000000, 0x00200000, 0x00000000, 0x00000000 }, /* scc3 */
+ { 0x00000000, 0x00100000, 0x00000000, 0x00000000 }, /* scc4 */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */
+ { 0x00010000, 0x00000000, 0x00000000, 0x00000000 }, /* pc15 */
+ { 0x00020000, 0x00000000, 0x00000000, 0x00000000 }, /* pc14 */
+ { 0x00040000, 0x00000000, 0x00000000, 0x00000000 }, /* pc13 */
+ { 0x00080000, 0x00000000, 0x00000000, 0x00000000 }, /* pc12 */
+ { 0x00100000, 0x00000000, 0x00000000, 0x00000000 }, /* pc11 */
+ { 0x00200000, 0x00000000, 0x00000000, 0x00000000 }, /* pc10 */
+ { 0x00400000, 0x00000000, 0x00000000, 0x00000000 }, /* pc9 */
+ { 0x00800000, 0x00000000, 0x00000000, 0x00000000 }, /* pc8 */
+ { 0x01000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc7 */
+ { 0x02000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc6 */
+ { 0x04000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc5 */
+ { 0x08000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc4 */
+ { 0x10000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc3 */
+ { 0x20000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc2 */
+ { 0x40000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc1 */
+ { 0x80000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc0 */
+
+};
+
+/*
+ * ------------------------ RTEMS Irq helper functions ----------------
+ */
+
+/*
+ * Caution : this function assumes the variable "internal_config"
+ * is already set and that the tables it contains are still valid
+ * and accessible.
+ */
+static void compute_SIU_IvectMask_from_prio (void)
+{
+ /*
+ * The actual masks defined
+ * correspond to the priorities defined
+ * for the SIU in irq_init.c.
+ */
+
+ int i,j;
+
+ for( i=0; i<BSP_CPM_IRQ_NUMBER; i++ )
+ {
+ for( j=0;j<BSP_CPM_IRQ_NUMBER; j++ )
+ if( irqPrioTable[j] < irqPrioTable[i] )
+ {
+ SIU_MaskBit[i].priority_h |= SIU_MaskBit[j].mask_h;
+ SIU_MaskBit[i].priority_l |= SIU_MaskBit[j].mask_l;
+ }
+ }
+
+}
+
+
+int BSP_irq_enable_at_cpm(const rtems_irq_number irqLine)
+{
+ int cpm_irq_index;
+
+ if (!is_cpm_irq(irqLine))
+ return 1;
+
+ cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
+
+ m8260.simr_h |= SIU_MaskBit[cpm_irq_index].mask_h;
+ m8260.simr_l |= SIU_MaskBit[cpm_irq_index].mask_l;
+
+ return 0;
+}
+
+int BSP_irq_disable_at_cpm(const rtems_irq_number irqLine)
+{
+ int cpm_irq_index;
+
+ if (!is_cpm_irq(irqLine))
+ return 1;
+
+ cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
+
+ m8260.simr_h &= ~(SIU_MaskBit[cpm_irq_index].mask_h);
+ m8260.simr_l &= ~(SIU_MaskBit[cpm_irq_index].mask_l);
+
+ return 0;
+}
+
+int BSP_irq_enabled_at_cpm(const rtems_irq_number irqLine)
+{
+ int cpm_irq_index;
+
+ if (!is_cpm_irq(irqLine))
+ return 0;
+
+ cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
+
+ return ((m8260.simr_h & SIU_MaskBit[cpm_irq_index].mask_h) ||
+ (m8260.simr_l & SIU_MaskBit[cpm_irq_index].mask_l));
+}
+
+#ifdef DISPATCH_HANDLER_STAT
+volatile unsigned int maxLoop = 0;
+#endif
+
+/*
+ * High level IRQ handler called from shared_raw_irq_code_entry
+ */
+static int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned excNum)
+{
+ register unsigned int irq;
+#if 0
+ register unsigned oldMask; /* old siu pic masks */
+#endif
+ register unsigned msr;
+ register unsigned new_msr;
+ register unsigned old_simr_h;
+ register unsigned old_simr_l;
+#ifdef DISPATCH_HANDLER_STAT
+ unsigned loopCounter;
+#endif
+
+ /*
+ * Handle decrementer interrupt
+ */
+ if (excNum == ASM_DEC_VECTOR) {
+ _CPU_MSR_GET(msr);
+ new_msr = msr | MSR_EE;
+ _CPU_MSR_SET(new_msr);
+
+ bsp_interrupt_handler_dispatch(BSP_DECREMENTER);
+
+ _CPU_MSR_SET(msr);
+
+ return 0;
+ }
+
+ /*
+ * Handle external interrupt generated by SIU on PPC core
+ */
+#ifdef DISPATCH_HANDLER_STAT
+ loopCounter = 0;
+#endif
+
+ while (1) {
+
+ if( ((m8260.sipnr_h & m8260.simr_h) | (m8260.sipnr_l & m8260.simr_l)) == 0 ) {
+#ifdef DISPATCH_HANDLER_STAT
+ if (loopCounter > maxLoop) maxLoop = loopCounter;
+#endif
+ break;
+ }
+
+ irq = (m8260.sivec >> 26) + BSP_CPM_IRQ_LOWEST_OFFSET;
+
+ /* Clear mask and pending register */
+ if( irq <= BSP_CPM_IRQ_MAX_OFFSET ) {
+ /* save interrupt masks */
+ old_simr_h = m8260.simr_h;
+ old_simr_l = m8260.simr_l;
+
+ /* mask off current interrupt and lower priority ones */
+ m8260.simr_h &= SIU_MaskBit[irq].priority_h;
+ m8260.simr_l &= SIU_MaskBit[irq].priority_l;
+
+ /* clear pending bit */
+ m8260.sipnr_h |= SIU_MaskBit[irq].mask_h;
+ m8260.sipnr_l |= SIU_MaskBit[irq].mask_l;
+
+ /*
+ * make sure, that the masking operations in
+ * ICTL and MSR are executed in order
+ */
+ __asm__ volatile("sync":::"memory");
+
+ /* re-enable external exceptions */
+ _CPU_MSR_GET(msr);
+ new_msr = msr | MSR_EE;
+ _CPU_MSR_SET(new_msr);
+
+ /* call handler */
+ bsp_interrupt_handler_dispatch(irq);
+
+ /* disable exceptions again */
+ _CPU_MSR_SET(msr);
+
+ /*
+ * make sure, that the masking operations in
+ * ICTL and MSR are executed in order
+ */
+ __asm__ volatile("sync":::"memory");
+
+ /* restore interrupt masks */
+ m8260.simr_h = old_simr_h;
+ m8260.simr_l = old_simr_l;
+
+ }
+#ifdef DISPATCH_HANDLER_STAT
+ ++ loopCounter;
+#endif
+ }
+ return 0;
+}
+
+/*
+ * Initialize CPM interrupt management
+ */
+static void
+BSP_CPM_irq_init(void)
+{
+ m8260.simr_l = 0;
+ m8260.simr_h = 0;
+ m8260.sipnr_l = 0xffffffff;
+ m8260.sipnr_h = 0xffffffff;
+ m8260.sicr = 0;
+
+ /*
+ * Initialize the interrupt priorities.
+ */
+ m8260.siprr = 0x05309770; /* reset value */
+ m8260.scprr_h = 0x05309770; /* reset value */
+ m8260.scprr_l = 0x05309770; /* reset value */
+
+}
+
+void bsp_interrupt_vector_enable( rtems_vector_number irqnum)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum));
+
+ if (is_cpm_irq(irqnum)) {
+ /*
+ * Enable interrupt at PIC level
+ */
+ BSP_irq_enable_at_cpm (irqnum);
+ }
+}
+
+void bsp_interrupt_vector_disable( rtems_vector_number irqnum)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum));
+
+ if (is_cpm_irq(irqnum)) {
+ /*
+ * disable interrupt at PIC level
+ */
+ BSP_irq_disable_at_cpm (irqnum);
+ }
+}
+
+rtems_status_code bsp_interrupt_facility_initialize()
+{
+ /* Install exception handler */
+ if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) {
+ return RTEMS_IO_ERROR;
+ }
+ if (ppc_exc_set_handler( ASM_DEC_VECTOR, C_dispatch_irq_handler)) {
+ return RTEMS_IO_ERROR;
+ }
+
+ /* Fill in priority masks */
+ compute_SIU_IvectMask_from_prio();
+
+ /* Initialize the interrupt controller */
+ BSP_CPM_irq_init();
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/powerpc/mvme3100/irq/irq_init.c b/bsps/powerpc/mvme3100/irq/irq_init.c
new file mode 100644
index 0000000000..c40692e688
--- /dev/null
+++ b/bsps/powerpc/mvme3100/irq/irq_init.c
@@ -0,0 +1,138 @@
+/* irq_init.c
+ *
+ * This file contains the implementation of rtems initialization
+ * related to interrupt handling.
+ *
+ * CopyRight (C) 1999 valette@crf.canon.fr
+ *
+ * Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
+ * to make it valid for MVME2300 Motorola boards.
+ *
+ * Till Straumann <strauman@slac.stanford.edu>, 12/20/2001:
+ * Use the new interface to openpic_init
+ *
+ * Adapted for the mvme3100 BSP by T. Straumann, 2007.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <libcpu/io.h>
+#include <bsp/pci.h>
+#include <bsp/openpic.h>
+#include <bsp/irq.h>
+#include <bsp.h>
+#include <bsp/vectors.h>
+#include <rtems/bspIo.h>
+
+static void nop_func(void *unused)
+{
+ printk("Unhandled IRQ\n");
+}
+
+static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
+static rtems_irq_global_settings initial_config;
+static rtems_irq_connect_data defaultIrq = {
+ /* vectorIdex, hdl , handle , on , off , isOn */
+ 0, nop_func , NULL , 0 , 0 , 0
+};
+
+static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={
+ /*
+ * actual priorities for interrupt :
+ * 0 means that only current interrupt is masked
+ * 255 means all other interrupts are masked
+ */
+ /*
+ * PCI Interrupts
+ */
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */
+ /*
+ * Processor exceptions handled as interrupts
+ */
+ 0
+};
+
+ /*
+ * This code assumes the exceptions management setup has already
+ * been done. We just need to replace the exceptions that will
+ * be handled like interrupt. On mcp750/mpc750 and many PPC processors
+ * this means the decrementer exception and the external exception.
+ */
+void BSP_rtems_irq_mng_init(unsigned cpuId)
+{
+ /* We should really have a way to find the number of sources
+ * the driver will use so that the size of the polarity-array
+ * matches the driver's idea of it.
+ */
+ unsigned char pol[56];
+ int i;
+
+ /* Note: The openpic driver initializes only as many
+ * 'pic-external' interrupt sources as reported
+ * by the feature register.
+ * The 8540's openpic supports 12 core-external
+ * and 23 core-internal (both of these groups
+ * are external to the PIC, i.e., 'pic-external')
+ * interrupts but between the corresponding
+ * banks of vector/priority registers there is
+ * a gap leaving space for 4 (unsupported) irqs.
+ * The driver, not knowing of this gap, would
+ * initialize the 12 core-external sources
+ * followed by 4 unsupported sources and 19
+ * core-internal sources thus leaving the last
+ * four core-internal sources uninitialized.
+ * Luckily, the feature register reports
+ * too many sources:
+ * - the 4 IPI plus 4 timer plus 4 messaging
+ * sources are included with the count
+ * - there are unused core-internal sources 24..32
+ * which are also supported by the pic
+ * bringing the reported number of sources to
+ * a count of 56 (12+32+4+4+4) which is enough
+ * so that all pic-external sources are covered
+ * and initialized.
+ *
+ * NOTE: All core-internal sources are active-high.
+ * The manual says that setting the polarity
+ * to 'low/0' will disable the interrupt but
+ * I found this not to be true: on the device
+ * I tested the interrupt was asserted hard.
+ */
+
+ /* core-external sources on the mvme3100 are active-low,
+ * core-internal sources are active high.
+ */
+ for (i=0; i<BSP_EXT_IRQ_NUMBER; i++)
+ pol[i]=0;
+ for (i=BSP_EXT_IRQ_NUMBER; i< BSP_EXT_IRQ_NUMBER + BSP_CORE_IRQ_NUMBER; i++)
+ pol[i]=1;
+
+ openpic_init(1, pol, 0, 0, 0, 0);
+
+ /*
+ * re-init the rtemsIrq table
+ */
+ for (i = 0; i < BSP_IRQ_NUMBER; i++) {
+ rtemsIrq[i] = defaultIrq;
+ rtemsIrq[i].name = i;
+ }
+ /*
+ * Init initial Interrupt management config
+ */
+ initial_config.irqNb = BSP_IRQ_NUMBER;
+ initial_config.defaultEntry = defaultIrq;
+ initial_config.irqHdlTbl = rtemsIrq;
+ initial_config.irqBase = BSP_LOWEST_OFFSET;
+ initial_config.irqPrioTbl = irqPrioTable;
+
+ if (!BSP_rtems_irq_mngt_set(&initial_config)) {
+ /*
+ * put something here that will show the failure...
+ */
+ rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
+ }
+}
diff --git a/bsps/powerpc/mvme5500/README.irq b/bsps/powerpc/mvme5500/README.irq
new file mode 100644
index 0000000000..fb31c4a5c3
--- /dev/null
+++ b/bsps/powerpc/mvme5500/README.irq
@@ -0,0 +1,20 @@
+README.irq : Shuchen Kate Feng <feng1@bnl.gov>, Sept. 2, 2007
+
+As per implementation in shared PPC code,
+the BSPirqPrioTable[96] listed in irq_init.c is where the
+software developers can change the levels of priority
+for all the interrupts based on the need of their
+applications. The IRQs can be eanbled dynamically via the
+BSP_enable_pic_irq(), or disbaled dynamically via the
+BSP_disable_pic_irq().
+
+
+Support for run-time priority setup could be
+added easily, but there is no action taken yet due to concerns
+over computer security at VME CPU level.
+
+
+The software developers are forbidden to setup picIsrTable[],
+as it is a powerful engine for the BSP to find the pending
+highest priority IRQ at run time. It ensures the fastest/faster
+interrupt service to the highest/higher priority IRQ, if pending.
diff --git a/bsps/powerpc/mvme5500/irq/BSP_irq.c b/bsps/powerpc/mvme5500/irq/BSP_irq.c
new file mode 100644
index 0000000000..eb36cc2a80
--- /dev/null
+++ b/bsps/powerpc/mvme5500/irq/BSP_irq.c
@@ -0,0 +1,483 @@
+/*
+ * This file contains the implementation of the function described in irq.h
+ */
+
+/*
+ * Copyright (C) 1998, 1999 valette@crf.canon.fr
+ *
+ * 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.
+ *
+ * Acknowledgement May 2004, to Till Straumann <strauman@slac.stanford.edu>
+ * for some inputs.
+ *
+ * Copyright 2003, 2004, 2005, 2007 Shuchen Kate Feng <feng1@bnl.gov>,
+ * NSLS, Brookhaven National Laboratory. All rights reserved.
+ *
+ * 1) Used GT_GPP_Value register instead of the GT_GPP_Interrupt_Cause
+ * register to monitor the cause of the level sensitive interrupts.
+ * (Copyright : NDA item)
+ * 2) The implementation of picPrioTable[] is an original work by the
+ * author to optimize the software IRQ priority scheduling because
+ * Discovery controller does not provide H/W IRQ priority schedule.
+ * It ensures the fastest/faster interrupt service to the
+ * highest/higher priority IRQ, if pendig.
+ * 3) _CPU_MSR_SET() needs RTEMS_COMPILER_MEMORY_BARRIER()
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <rtems/system.h>
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/intr.h>
+#include <libcpu/io.h>
+#include <libcpu/byteorder.h>
+#include <bsp/vectors.h>
+
+#include <rtems/bspIo.h> /* for printk */
+#include "bsp/gtreg.h"
+
+#define HI_INT_CAUSE 0x40000000
+
+#define MAX_IRQ_LOOP 20
+
+/* #define DEBUG_IRQ*/
+
+/*
+ * pointer to the mask representing the additionnal irq vectors
+ * that must be disabled when a particular entry is activated.
+ * They will be dynamically computed from the table given
+ * in BSP_rtems_irq_mngt_set();
+ * CAUTION : this table is accessed directly by interrupt routine
+ * prologue.
+ */
+static unsigned int BSP_irq_prio_mask_tbl[3][BSP_PIC_IRQ_NUMBER];
+
+/*
+ * location used to store initial tables used for interrupt
+ * management.BSP copy of the configuration
+ */
+static rtems_irq_global_settings BSP_config;
+static rtems_irq_connect_data* rtems_hdl_tbl;
+
+/*
+ * default handler connected on each irq after bsp initialization
+ * (locally cached copy)
+ */
+void (*default_rtems_hdl)(rtems_irq_hdl_param) = (void(*)(rtems_irq_hdl_param)) -1;
+
+
+static volatile unsigned *BSP_irqMask_reg[3];
+static volatile unsigned *BSP_irqCause_reg[3];
+static volatile unsigned BSP_irqMask_cache[3]={0,0,0};
+
+static int picPrioTblPtr=0;
+static unsigned int GPPIrqInTbl=0;
+static unsigned long long MainIrqInTbl=0;
+
+/*
+ * The software developers are forbidden to setup picPrioTable[],
+ * as it is a powerful engine for the BSP to find the pending
+ * highest priority IRQ at run time. It ensures the fastest/faster
+ * interrupt service to the highest/higher priority IRQ, if pendig.
+ *
+ * The picPrioTable[96] is updated dynamically at run time
+ * based on the priority levels set at BSPirqPrioTable[96],
+ * while the BSP_enable_irq_at_pic(), and BSP_disable_irq_at_pic()
+ * commands are invoked.
+ *
+ * The picPrioTable[96] lists the enabled CPU main and GPP external interrupt
+ * numbers [0 (lowest)- 95 (highest)] starting from the highest priority
+ * one to the lowest priority one. The highest priority interrupt is
+ * located at picPrioTable[0], and the lowest priority interrupt is located
+ * at picPrioTable[picPrioTblPtr-1].
+ *
+ *
+ */
+#define DynamicIsrTable
+#ifdef DynamicIsrTable
+/* BitNums for Main Interrupt Lo/High Cause, -1 means invalid bit */
+static unsigned int picPrioTable[BSP_PIC_IRQ_NUMBER]={
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1 };
+#else
+static unsigned int picPrioTable[BSP_PIC_IRQ_NUMBER]={
+ 80, 84, 76, 77, 32, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1 };
+#endif
+
+/*
+ * Check if IRQ is a MAIN CPU internal IRQ or GPP external IRQ
+ */
+static inline int is_pic_irq(const rtems_irq_number irqLine)
+{
+ return (((int) irqLine <= BSP_GPP_IRQ_MAX_OFFSET) &
+ ((int) irqLine >= BSP_MICL_IRQ_LOWEST_OFFSET)
+ );
+}
+
+/*
+ * Check if IRQ is a Porcessor IRQ
+ */
+static inline int is_processor_irq(const rtems_irq_number irqLine)
+{
+ return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) &
+ ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)
+ );
+}
+
+/*
+ * ------------------------ RTEMS Irq helper functions ----------------
+ */
+
+/*
+ * Caution : this function assumes the variable "BSP_config"
+ * is already set and that the tables it contains are still valid
+ * and accessible.
+ */
+static void compute_pic_masks_from_prio(void)
+{
+ int i,j, k, isGppMain;
+ unsigned long long irq_prio_mask=0;
+
+ /*
+ * Always mask at least current interrupt to prevent re-entrance
+ */
+ for (i=0; i <BSP_PIC_IRQ_NUMBER; i++) {
+ switch(i) {
+ case BSP_MAIN_GPP7_0_IRQ:
+ case BSP_MAIN_GPP15_8_IRQ:
+ case BSP_MAIN_GPP23_16_IRQ:
+ case BSP_MAIN_GPP31_24_IRQ:
+ for (k=0; k< 3; k++)
+ BSP_irq_prio_mask_tbl[k][i]=0;
+
+ irq_prio_mask =0;
+ isGppMain =1;
+ break;
+ default :
+ isGppMain =0;
+ irq_prio_mask = (unsigned long long) (1LLU << i);
+ break;
+ }
+ if ( isGppMain) continue;
+ for (j = 0; j <BSP_MAIN_IRQ_NUMBER; j++) {
+ /*
+ * Mask interrupts at PIC level that have a lower priority
+ * or <Till Straumann> a equal priority.
+ */
+ if (BSP_config.irqPrioTbl [i] >= BSP_config.irqPrioTbl [j])
+ irq_prio_mask |= (unsigned long long)(1LLU << j);
+ }
+
+
+ BSP_irq_prio_mask_tbl[0][i] = irq_prio_mask & 0xffffffff;
+ BSP_irq_prio_mask_tbl[1][i] = (irq_prio_mask>>32) & 0xffffffff;
+#if 0
+ printk("irq_mask_prio_tbl[%d]:0x%8x%8x\n",i,BSP_irq_prio_mask_tbl[1][i],
+ BSP_irq_prio_mask_tbl[0][i]);
+#endif
+
+ BSP_irq_prio_mask_tbl[2][i] = 1<<i;
+ /* Compute for the GPP priority interrupt mask */
+ for (j=BSP_GPP_IRQ_LOWEST_OFFSET; j <BSP_PROCESSOR_IRQ_LOWEST_OFFSET; j++) {
+ if (BSP_config.irqPrioTbl [i] >= BSP_config.irqPrioTbl [j])
+ BSP_irq_prio_mask_tbl[2][i] |= 1 << (j-BSP_GPP_IRQ_LOWEST_OFFSET);
+ }
+#if 0
+ printk("GPPirq_mask_prio_tbl[%d]:0x%8x\n",i,BSP_irq_prio_mask_tbl[2][i]);
+#endif
+ }
+}
+
+static void UpdateMainIrqTbl(int irqNum)
+{
+ int i=0, j, shifted=0;
+
+ switch (irqNum) {
+ case BSP_MAIN_GPP7_0_IRQ:
+ case BSP_MAIN_GPP15_8_IRQ:
+ case BSP_MAIN_GPP23_16_IRQ:
+ case BSP_MAIN_GPP31_24_IRQ:
+ return; /* Do nothing, let GPP take care of it */
+ break;
+ }
+#ifdef SHOW_MORE_INIT_SETTINGS
+ unsigned long val2, val1;
+#endif
+
+ /* If entry not in table*/
+ if ( ((irqNum<BSP_GPP_IRQ_LOWEST_OFFSET) &&
+ (!((unsigned long long)(1LLU << irqNum) & MainIrqInTbl))) ||
+ ((irqNum>BSP_MICH_IRQ_MAX_OFFSET) &&
+ (!(( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl))))
+ {
+ while ( picPrioTable[i]!=-1) {
+ if (BSP_config.irqPrioTbl[irqNum]>BSP_config.irqPrioTbl[picPrioTable[i]]) {
+ /* all other lower priority entries shifted right */
+ for (j=picPrioTblPtr;j>i; j--) {
+ picPrioTable[j]=picPrioTable[j-1];
+ }
+ picPrioTable[i]=irqNum;
+ shifted=1;
+ break;
+ }
+ i++;
+ }
+ if (!shifted) picPrioTable[picPrioTblPtr] =irqNum;
+
+ if (irqNum >BSP_MICH_IRQ_MAX_OFFSET)
+ GPPIrqInTbl |= (1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET));
+ else
+ MainIrqInTbl |= (unsigned long long)(1LLU << irqNum);
+ picPrioTblPtr++;
+ }
+#ifdef SHOW_MORE_INIT_SETTINGS
+ val2 = (MainIrqInTbl>>32) & 0xffffffff;
+ val1 = MainIrqInTbl&0xffffffff;
+ printk("irqNum %d, MainIrqInTbl 0x%x%x\n", irqNum, val2, val1);
+ BSP_printPicIsrTbl();
+#endif
+
+}
+
+
+static void CleanMainIrqTbl(int irqNum)
+{
+ int i, j;
+
+ switch (irqNum) {
+ case BSP_MAIN_GPP7_0_IRQ:
+ case BSP_MAIN_GPP15_8_IRQ:
+ case BSP_MAIN_GPP23_16_IRQ:
+ case BSP_MAIN_GPP31_24_IRQ:
+ return; /* Do nothing, let GPP take care of it */
+ break;
+ }
+ if ( ((irqNum<BSP_GPP_IRQ_LOWEST_OFFSET) &&
+ ((unsigned long long)(1LLU << irqNum) & MainIrqInTbl)) ||
+ ((irqNum>BSP_MICH_IRQ_MAX_OFFSET) &&
+ (( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl)))
+ { /* If entry in table*/
+ for (i=0; i<64; i++) {
+ if (picPrioTable[i]==irqNum) {/*remove it from the entry */
+ /* all other lower priority entries shifted left */
+ for (j=i;j<picPrioTblPtr; j++) {
+ picPrioTable[j]=picPrioTable[j+1];
+ }
+ if (irqNum >BSP_MICH_IRQ_MAX_OFFSET)
+ GPPIrqInTbl &= ~(1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET));
+ else
+ MainIrqInTbl &= ~(1LLU << irqNum);
+ picPrioTblPtr--;
+ break;
+ }
+ }
+ }
+}
+
+void BSP_enable_irq_at_pic(const rtems_irq_number irqNum)
+{
+ unsigned bitNum, regNum;
+ unsigned int level;
+
+ if ( !is_pic_irq(irqNum) )
+ return;
+
+ bitNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)%32;
+ regNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)>>5;
+
+ rtems_interrupt_disable(level);
+
+#ifdef DynamicIsrTable
+ UpdateMainIrqTbl((int) irqNum);
+#endif
+ BSP_irqMask_cache[regNum] |= (1 << bitNum);
+
+ out_le32((volatile uint32_t *)BSP_irqMask_reg[regNum], BSP_irqMask_cache[regNum]);
+ while (in_le32((volatile uint32_t *)BSP_irqMask_reg[regNum]) != BSP_irqMask_cache[regNum]);
+
+ rtems_interrupt_enable(level);
+}
+
+int BSP_disable_irq_at_pic(const rtems_irq_number irqNum)
+{
+ int rval;
+ unsigned bitNum, regNum;
+ unsigned int level;
+
+ if ( ! is_pic_irq(irqNum) )
+ return -1;
+
+ bitNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)%32;
+ regNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)>>5;
+
+ rtems_interrupt_disable(level);
+
+#ifdef DynamicIsrTable
+ CleanMainIrqTbl((int) irqNum);
+#endif
+
+ rval = BSP_irqMask_cache[regNum] & (1<<bitNum);
+
+ BSP_irqMask_cache[regNum] &= ~(1 << bitNum);
+
+ out_le32((volatile uint32_t *)BSP_irqMask_reg[regNum], BSP_irqMask_cache[regNum]);
+ while (in_le32((volatile uint32_t *)BSP_irqMask_reg[regNum]) != BSP_irqMask_cache[regNum]);
+
+ rtems_interrupt_enable(level);
+
+ return rval ? 1 : 0;
+}
+
+/* Use shared/irq : 2008 */
+int BSP_setup_the_pic(rtems_irq_global_settings* config)
+{
+ int i;
+
+ BSP_config = *config;
+ default_rtems_hdl = config->defaultEntry.hdl;
+ rtems_hdl_tbl = config->irqHdlTbl;
+
+ /* Get ready for discovery BSP */
+ BSP_irqMask_reg[0]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_CPU_INT_MASK_LO);
+ BSP_irqMask_reg[1]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_CPU_INT_MASK_HI);
+ BSP_irqCause_reg[0]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_MAIN_INT_CAUSE_LO);
+ BSP_irqCause_reg[1]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_MAIN_INT_CAUSE_HI);
+ BSP_irqMask_reg[2]= (volatile unsigned int *) (GT64x60_REG_BASE + GT_GPP_Interrupt_Mask);
+ BSP_irqCause_reg[2]= (volatile unsigned int *) (GT64x60_REG_BASE + GT_GPP_Value);
+
+ /* Page 401, Table 598:
+ * Comm Unit Arbiter Control register :
+ * bit 10:GPP interrupts as level sensitive(1) or edge sensitive(0).
+ * MOTload default is set as level sensitive(1). Set it agin to make sure.
+ */
+ out_le32((volatile uint32_t *)GT_CommUnitArb_Ctrl,
+ (in_le32((volatile uint32_t *)GT_CommUnitArb_Ctrl)| (1<<10)));
+
+#if 0
+ printk("BSP_irqMask_reg[0] = 0x%" PRIx32 ", BSP_irqCause_reg[0] 0x%" PRIx32 "\n",
+ in_le32((volatile uint32_t *)BSP_irqMask_reg[0]),
+ in_le32((volatile uint32_t *)BSP_irqCause_reg[0]));
+ printk("BSP_irqMask_reg[1] = 0x%" PRIx32 ", BSP_irqCause_reg[1] 0x%" PRIx32 "\n",
+ in_le32((volatile uint32_t *)BSP_irqMask_reg[1]),
+ in_le32((volatile uint32_t *)BSP_irqCause_reg[1]));
+ printk("BSP_irqMask_reg[2] = 0x%" PRIx32 ", BSP_irqCause_reg[2] 0x%" PRIx32 "\n",
+ in_le32((volatile uint32_t *)BSP_irqMask_reg[2]),
+ in_le32((volatile uint32_t *)BSP_irqCause_reg[2]));
+#endif
+
+ /* Initialize the interrupt related registers */
+ for (i=0; i<3; i++) {
+ out_le32((volatile uint32_t *)BSP_irqCause_reg[i], 0);
+ out_le32((volatile uint32_t *)BSP_irqMask_reg[i], 0);
+ }
+ in_le32((volatile uint32_t *)BSP_irqMask_reg[2]);
+ compute_pic_masks_from_prio();
+
+#if 0
+ printk("BSP_irqMask_reg[0] = 0x%" PRIx32 ", BSP_irqCause_reg[0] 0x%" PRIx32 "\n",
+ in_le32((volatile uint32_t *)BSP_irqMask_reg[0]),
+ in_le32((volatile uint32_t *)BSP_irqCause_reg[0]));
+ printk("BSP_irqMask_reg[1] = 0x%" PRIx32 ", BSP_irqCause_reg[1] 0x%" PRIx32 "\n",
+ in_le32((volatile uint32_t *)BSP_irqMask_reg[1]),
+ in_le32((volatile uint32_t *)BSP_irqCause_reg[1]));
+ printk("BSP_irqMask_reg[2] = 0x%" PRIx32 ", BSP_irqCause_reg[2] 0x%" PRIx32 "\n",
+ in_le32((volatile uint32_t *)BSP_irqMask_reg[2]),
+ in_le32((volatile uint32_t *)BSP_irqCause_reg[2]));
+#endif
+
+ /*
+ *
+ */
+ for (i=BSP_MICL_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET ; i++) {
+ if ( BSP_config.irqHdlTbl[i].hdl != BSP_config.defaultEntry.hdl) {
+ BSP_enable_irq_at_pic(i);
+ BSP_config.irqHdlTbl[i].on(&BSP_config.irqHdlTbl[i]);
+ }
+ else {
+ BSP_config.irqHdlTbl[i].off(&BSP_config.irqHdlTbl[i]);
+ BSP_disable_irq_at_pic(i);
+ }
+ }
+ for (i= BSP_MAIN_GPP7_0_IRQ; i < BSP_MAIN_GPP31_24_IRQ; i++)
+ BSP_enable_irq_at_pic(i);
+
+ return(1);
+}
+
+/*
+ * High level IRQ handler called from shared_raw_irq_code_entry
+ */
+int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum)
+{
+ unsigned long irqCause[3]={0, 0,0};
+ unsigned oldMask[3]={0,0,0};
+ int loop=0, i=0, j;
+ int irq=0, group=0;
+
+ if (excNum == ASM_DEC_VECTOR) {
+ bsp_irq_dispatch_list( rtems_hdl_tbl, BSP_DECREMENTER, default_rtems_hdl);
+ return 0;
+ }
+
+ for (j=0; j<3; j++ ) oldMask[j] = BSP_irqMask_cache[j];
+ for (j=0; j<3; j++) irqCause[j] = in_le32((volatile uint32_t *)BSP_irqCause_reg[j]) & in_le32((volatile uint32_t *)BSP_irqMask_reg[j]);
+
+ while (((irq = picPrioTable[i++])!=-1)&& (loop++ < MAX_IRQ_LOOP))
+ {
+ if (irqCause[group= irq/32] & ( 1<<(irq % 32))) {
+ for (j=0; j<3; j++)
+ BSP_irqMask_cache[j] &= (~ BSP_irq_prio_mask_tbl[j][irq]);
+
+ out_le32((volatile uint32_t *)BSP_irqMask_reg[0], BSP_irqMask_cache[0]);
+ out_le32((volatile uint32_t *)BSP_irqMask_reg[1], BSP_irqMask_cache[1]);
+ out_le32((volatile uint32_t *)BSP_irqMask_reg[2], BSP_irqMask_cache[2]);
+ in_le32((volatile uint32_t *)BSP_irqMask_reg[2]);
+
+ bsp_irq_dispatch_list( rtems_hdl_tbl, irq, default_rtems_hdl);
+
+ for (j=0; j<3; j++ ) BSP_irqMask_cache[j] = oldMask[j];
+
+ out_le32((volatile uint32_t *)BSP_irqMask_reg[0], oldMask[0]);
+ out_le32((volatile uint32_t *)BSP_irqMask_reg[1], oldMask[1]);
+ out_le32((volatile uint32_t *)BSP_irqMask_reg[2], oldMask[2]);
+ in_le32((volatile uint32_t *)BSP_irqMask_reg[2]);
+ }
+ }
+
+ return 0;
+}
+
+/* Only print part of the entries for now */
+void BSP_printPicIsrTbl(void)
+{
+ int i;
+
+ printf("picPrioTable[12]={ {irq# : ");
+ for (i=0; i<12; i++)
+ printf("%d,", picPrioTable[i]);
+ printf("}\n");
+
+ printf("GPPIrqInTbl: 0x%x :\n", GPPIrqInTbl);
+}
diff --git a/bsps/powerpc/mvme5500/irq/irq_init.c b/bsps/powerpc/mvme5500/irq/irq_init.c
new file mode 100644
index 0000000000..ede4014f22
--- /dev/null
+++ b/bsps/powerpc/mvme5500/irq/irq_init.c
@@ -0,0 +1,148 @@
+/* irq_init.c
+ *
+ * This file contains the implementation of rtems initialization
+ * related to interrupt handling.
+ *
+ * CopyRight (C) 1999 valette@crf.canon.fr
+ *
+ * Modified and added support for the MVME5500.
+ * Copyright 2003, 2004, 2005, Brookhaven National Laboratory and
+ * Shuchen Kate Feng <feng1@bnl.gov>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE
+ *
+ */
+#include <libcpu/io.h>
+#include <libcpu/spr.h>
+#include <bsp/irq.h>
+#include <bsp.h>
+#include <bsp/vectors.h> /* ASM_EXT_VECTOR, ASM_DEC_VECTOR ... */
+/*#define TRACE_IRQ_INIT*/
+
+/*
+ * default on/off function
+ */
+static void nop_func(void){}
+/*
+ * default isOn function
+ */
+static int not_connected(void) {return 0;}
+
+static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
+static rtems_irq_global_settings initial_config;
+
+static rtems_irq_connect_data defaultIrq = {
+ .name = 0,
+ .hdl = NULL,
+ .handle = NULL,
+ .on = (rtems_irq_enable) nop_func,
+ .off = (rtems_irq_disable) nop_func,
+ .isOn = (rtems_irq_is_enabled) not_connected,
+#ifdef BSP_SHARED_HANDLER_SUPPORT
+ .next_handler = NULL
+#endif
+};
+
+rtems_irq_prio BSPirqPrioTable[BSP_PIC_IRQ_NUMBER] = {
+ /*
+ * This table is where the developers can change the levels of priority
+ * based on the need of their applications.
+ *
+ * actual priorities for CPU MAIN and GPP interrupts (0-95)
+ *
+ * 0 means that only current interrupt is masked (lowest priority)
+ * 255 is only used by bits 24, 25, 26 and 27 of the CPU high
+ * interrupt Mask: (e.g. GPP7_0, GPP15_8, GPP23_16, GPP31_24).
+ * The IRQs of those four bits are always enabled. When it's used,
+ * the IRQ number is never listed in the dynamic picIsrTable[96].
+ *
+ * The priorities of GPP interrupts were decided by their own
+ * value set at BSPirqPrioTable.
+ *
+ */
+ /* CPU Main cause low interrupt */
+ /* 0-15 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 64/*Timer*/, 0, 0, 0, 0, 0, 0, 0,
+ /* 16-31 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* CPU Main cause high interrupt */
+ /* 32-47 */
+ 2/*10/100MHZ*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 48-63 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 255 /*GPP0-7*/, 255/*GPP8-15*/, 255/*GPP16-23*/, 255/*GPP24-31*/, 0, 0, 0, 0,
+ /* GPP interrupts */
+ /* GPP0-7 */
+ 1/*serial*/,0, 0, 0, 0, 0, 0, 0,
+ /* GPP8-15 */
+ 47/*PMC1A*/,46/*PMC1B*/,45/*PMC1C*/,44/*PMC1D*/,30/*VME0*/, 29/*VME1*/,3,1,
+ /* GPP16-23 */
+ 37/*PMC2A*/,36/*PMC2B*/,35/*PMC2C*/,34/*PMC2D*/,23/*1GHZ*/, 0,0,0,
+ /* GPP24-31 */
+ 7/*watchdog*/, 0,0,0,0,0,0,0
+};
+
+/*
+ * This code assumes the exceptions management setup has already
+ * been done. We just need to replace the exceptions that will
+ * be handled like interrupt. On MPC7455 and many PPC processors
+ * this means the decrementer exception and the external exception.
+ */
+void BSP_rtems_irq_mng_init(unsigned cpuId)
+{
+ int i;
+ rtems_interrupt_level level;
+
+ /*
+ * First initialize the Interrupt management hardware
+ */
+#ifdef TRACE_IRQ_INIT
+ printk("Initializing the interrupt controller of the GT64260\n");
+#endif
+
+#ifdef TRACE_IRQ_INIT
+ printk("Going to re-initialize the rtemsIrq table %d\n",BSP_IRQ_NUMBER);
+#endif
+ /*
+ * Initialize Rtems management interrupt table
+ */
+ /*
+ * re-init the rtemsIrq table
+ */
+ for (i = 0; i < BSP_IRQ_NUMBER; i++) {
+ rtemsIrq[i] = defaultIrq;
+ rtemsIrq[i].name = i;
+ }
+
+ /*
+ * Init initial Interrupt management config
+ */
+ initial_config.irqNb = BSP_IRQ_NUMBER;
+ initial_config.defaultEntry = defaultIrq;
+ initial_config.irqHdlTbl = rtemsIrq;
+ initial_config.irqBase = BSP_LOWEST_OFFSET;
+ initial_config.irqPrioTbl = BSPirqPrioTable;
+
+#ifdef TRACE_IRQ_INIT
+ printk("Going to setup irq mngt configuration\n");
+#endif
+
+ rtems_interrupt_disable(level);
+ (void) level; /* avoid set but not used warning */
+
+ if (!BSP_rtems_irq_mngt_set(&initial_config)) {
+ /*
+ * put something here that will show the failure...
+ */
+ rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
+ }
+#ifdef TRACE_IRQ_INIT
+ printk("Done setup irq mngt configuration\n");
+#endif
+
+#ifdef TRACE_IRQ_INIT
+ printk("RTEMS IRQ management is now operationnal\n");
+#endif
+}
diff --git a/bsps/powerpc/psim/irq/irq_init.c b/bsps/powerpc/psim/irq/irq_init.c
new file mode 100644
index 0000000000..3d2a82f2c0
--- /dev/null
+++ b/bsps/powerpc/psim/irq/irq_init.c
@@ -0,0 +1,125 @@
+/*
+ * This file contains the implementation of rtems initialization
+ * related to interrupt handling
+ */
+
+/*
+ * Copyright (C) 1999 valette@crf.canon.fr
+ *
+ * Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
+ * to make it valid for MVME2300 Motorola boards.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <libcpu/io.h>
+#include <libcpu/spr.h>
+#include <bsp/irq.h>
+#include <bsp.h>
+#include <psim.h>
+#include <bsp/vectors.h>
+#include <rtems/bspIo.h>
+#include <bsp/openpic.h>
+#include <bsp/irq-generic.h>
+
+static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
+static rtems_irq_global_settings initial_config;
+static rtems_irq_connect_data defaultIrq = {
+ /* vectorIdex, hdl , handle , on , off , isOn */
+ 0, NULL, NULL , NULL, NULL, NULL
+};
+static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={
+ /*
+ * Processor exceptions handled as interrupts
+ */
+ 0
+};
+
+ /*
+ * This code assumes the exceptions management setup has already
+ * been done. We just need to replace the exceptions that will
+ * be handled like interrupt. On mcp750/mpc750 and many PPC processors
+ * this means the decrementer exception and the external exception.
+ */
+void BSP_rtems_irq_mng_init(unsigned cpuId)
+{
+ int i;
+
+ /*
+ * First initialize the Interrupt management hardware
+ */
+ OpenPIC = (void*)PSIM.OpenPIC;
+ openpic_init(1,0,0,16,0,0);
+
+ /*
+ * Initialize Rtems management interrupt table
+ */
+ /*
+ * re-init the rtemsIrq table
+ */
+ for (i = 0; i < BSP_IRQ_NUMBER; i++) {
+ rtemsIrq[i] = defaultIrq;
+ rtemsIrq[i].name = i;
+ }
+ /*
+ * Init initial Interrupt management config
+ */
+ initial_config.irqNb = BSP_IRQ_NUMBER;
+ initial_config.defaultEntry = defaultIrq;
+ initial_config.irqHdlTbl = rtemsIrq;
+ initial_config.irqBase = BSP_LOWEST_OFFSET;
+ initial_config.irqPrioTbl = irqPrioTable;
+
+ for (i = BSP_PCI_IRQ_LOWEST_OFFSET; i< BSP_PCI_IRQ_NUMBER; i++ ) {
+ irqPrioTable[i] = 8;
+ }
+
+ if (!BSP_rtems_irq_mngt_set(&initial_config)) {
+ /*
+ * put something here that will show the failure...
+ */
+ rtems_panic(
+ "Unable to initialize RTEMS interrupt Management!!! System locked\n"
+ );
+ }
+
+ #ifdef TRACE_IRQ_INIT
+ printk("RTEMS IRQ management is now operationnal\n");
+ #endif
+}
+
+static int psim_exception_handler(
+ BSP_Exception_frame *frame,
+ unsigned exception_number
+)
+{
+ rtems_panic("Unexpected interrupt occured");
+ return 0;
+}
+
+/*
+ * functions to enable/disable a source at the ipic
+ */
+void bsp_interrupt_vector_enable( rtems_vector_number irqnum)
+{
+ /* FIXME: do something */
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum));
+}
+
+void bsp_interrupt_vector_disable( rtems_vector_number irqnum)
+{
+ /* FIXME: do something */
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum));
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ /* Install exception handler */
+ if (ppc_exc_set_handler( ASM_EXT_VECTOR, psim_exception_handler)) {
+ return RTEMS_IO_ERROR;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/powerpc/qemuppc/irq/irq_init.c b/bsps/powerpc/qemuppc/irq/irq_init.c
new file mode 100644
index 0000000000..24b15dcd49
--- /dev/null
+++ b/bsps/powerpc/qemuppc/irq/irq_init.c
@@ -0,0 +1,61 @@
+/*===============================================================*\
+| Project: RTEMS generic MPC83xx BSP |
++-----------------------------------------------------------------+
+| Copyright (c) 2007 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.org/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file integrates the IPIC irq controller |
+\*===============================================================*/
+
+#include <rtems.h>
+
+#include <libcpu/powerpc-utility.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/vectors.h>
+
+static int qemuppc_exception_handler(
+ BSP_Exception_frame *frame,
+ unsigned exception_number
+)
+{
+ rtems_panic("Unexpected interrupt occured");
+ return 0;
+}
+
+/*
+ * functions to enable/disable a source at the ipic
+ */
+void bsp_interrupt_vector_enable( rtems_vector_number irqnum)
+{
+ /* FIXME: do something */
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum));
+}
+
+void bsp_interrupt_vector_disable( rtems_vector_number irqnum)
+{
+ /* FIXME: do something */
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum));
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ /* Install exception handler */
+ if (ppc_exc_set_handler( ASM_EXT_VECTOR, qemuppc_exception_handler)) {
+ return RTEMS_IO_ERROR;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/powerpc/qoriq/irq/irq.c b/bsps/powerpc/qoriq/irq/irq.c
new file mode 100644
index 0000000000..625b9fce1b
--- /dev/null
+++ b/bsps/powerpc/qoriq/irq/irq.c
@@ -0,0 +1,387 @@
+/**
+ * @file
+ *
+ * @ingroup QorIQ
+ *
+ * @brief Interrupt implementation.
+ */
+
+/*
+ * Copyright (c) 2010, 2017 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <sys/param.h>
+
+#include <rtems.h>
+
+#include <libcpu/powerpc-utility.h>
+
+#include <asm/epapr_hcalls.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/vectors.h>
+#include <bsp/utility.h>
+#include <bsp/qoriq.h>
+
+#ifdef RTEMS_SMP
+#include <rtems/score/smpimpl.h>
+#endif
+
+RTEMS_INTERRUPT_LOCK_DEFINE(static, lock, "QorIQ IRQ")
+
+#define SPURIOUS 0xffff
+
+#ifdef QORIQ_IS_HYPERVISOR_GUEST
+
+void bsp_interrupt_set_affinity(
+ rtems_vector_number vector,
+ const Processor_mask *affinity
+)
+{
+ uint32_t config;
+ unsigned int priority;
+ uint32_t destination;
+ uint32_t new_destination;
+ rtems_interrupt_lock_context lock_context;
+
+ new_destination = _Processor_mask_Find_last_set(affinity) - 1;
+
+ rtems_interrupt_lock_acquire(&lock, &lock_context);
+ ev_int_get_config(vector, &config, &priority, &destination);
+ ev_int_set_config(vector, config, priority, new_destination);
+ rtems_interrupt_lock_release(&lock, &lock_context);
+}
+
+void bsp_interrupt_get_affinity(
+ rtems_vector_number vector,
+ Processor_mask *affinity
+)
+{
+ uint32_t config;
+ unsigned int priority;
+ uint32_t destination;
+
+ ev_int_get_config(vector, &config, &priority, &destination);
+ _Processor_mask_From_uint32_t(affinity, destination, 0);
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ ev_int_set_mask(vector, 0);
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+ ev_int_set_mask(vector, 1);
+}
+
+void bsp_interrupt_dispatch(uintptr_t exception_number)
+{
+ unsigned int vector;
+
+ if (exception_number == 10) {
+ qoriq_decrementer_dispatch();
+ return;
+ }
+
+#ifdef RTEMS_SMP
+ if (exception_number == 36) {
+ _SMP_Inter_processor_interrupt_handler();
+ return;
+ }
+#endif
+
+ /*
+ * This works only if the "has-external-proxy" property is present in the
+ * "epapr,hv-pic" device tree node.
+ */
+ vector = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_EPR);
+
+ if (vector != SPURIOUS) {
+ uint32_t msr;
+
+ msr = ppc_external_exceptions_enable();
+ bsp_interrupt_handler_dispatch(vector);
+ ppc_external_exceptions_disable(msr);
+
+ ev_int_eoi(vector);
+ } else {
+ bsp_interrupt_handler_default(vector);
+ }
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ unsigned int i;
+
+ for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) {
+ uint32_t config;
+ unsigned int priority;
+ uint32_t destination;
+ unsigned int err;
+
+ err = ev_int_get_config(i, &config, &priority, &destination);
+ if (err != EV_SUCCESS)
+ continue;
+
+ priority = QORIQ_PIC_PRIORITY_DEFAULT;
+
+ ev_int_set_config(i, config, priority, destination);
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+#else /* !QORIQ_IS_HYPERVISOR_GUEST */
+
+#define VPR_MSK BSP_BBIT32(0)
+#define VPR_A BSP_BBIT32(1)
+#define VPR_P BSP_BBIT32(8)
+#define VPR_S BSP_BBIT32(9)
+#define VPR_PRIORITY(val) BSP_BFLD32(val, 12, 15)
+#define VPR_PRIORITY_GET(reg) BSP_BFLD32GET(reg, 12, 15)
+#define VPR_PRIORITY_SET(reg, val) BSP_BFLD32SET(reg, val, 12, 15)
+#define VPR_VECTOR(val) BSP_BFLD32(val, 16, 31)
+#define VPR_VECTOR_GET(reg) BSP_BFLD32GET(reg, 16, 31)
+#define VPR_VECTOR_SET(reg, val) BSP_BFLD32SET(reg, val, 16, 31)
+
+#define GCR_RST BSP_BBIT32(0)
+#define GCR_M BSP_BBIT32(2)
+
+#define SRC_CFG_IDX(i) ((i) - QORIQ_IRQ_EXT_BASE)
+
+static const uint16_t src_cfg_offsets [] = {
+ [SRC_CFG_IDX(QORIQ_IRQ_EXT_0)] = 0x10000 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_EXT_1)] = 0x10020 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_EXT_2)] = 0x10040 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_EXT_3)] = 0x10060 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_EXT_4)] = 0x10080 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_EXT_5)] = 0x100a0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_EXT_6)] = 0x100c0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_EXT_7)] = 0x100e0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_EXT_8)] = 0x10100 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_EXT_9)] = 0x10120 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_EXT_10)] = 0x10140 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_EXT_11)] = 0x10160 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_IPI_0)] = 0x010a0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_IPI_1)] = 0x010b0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_IPI_2)] = 0x010c0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_IPI_3)] = 0x010d0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MI_0)] = 0x11600 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MI_1)] = 0x11620 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MI_2)] = 0x11640 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MI_3)] = 0x11660 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MI_4)] = 0x11680 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MI_5)] = 0x116a0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MI_6)] = 0x116c0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MI_7)] = 0x116e0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MSI_0)] = 0x11c00 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MSI_1)] = 0x11c20 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MSI_2)] = 0x11c40 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MSI_3)] = 0x11c60 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MSI_4)] = 0x11c80 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MSI_5)] = 0x11ca0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MSI_6)] = 0x11cc0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_MSI_7)] = 0x11ce0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_GT_A_0)] = 0x01120 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_GT_A_1)] = 0x01160 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_GT_A_2)] = 0x011a0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_GT_A_3)] = 0x011e0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_GT_B_0)] = 0x02120 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_GT_B_1)] = 0x02160 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_GT_B_2)] = 0x021a0 >> 4,
+ [SRC_CFG_IDX(QORIQ_IRQ_GT_B_3)] = 0x021e0 >> 4
+};
+
+static volatile qoriq_pic_src_cfg *get_src_cfg(rtems_vector_number vector)
+{
+ uint32_t n = MIN(RTEMS_ARRAY_SIZE(qoriq.pic.ii_0), QORIQ_IRQ_EXT_BASE);
+
+ if (vector < n) {
+ return &qoriq.pic.ii_0 [vector];
+ } else if (vector < QORIQ_IRQ_EXT_BASE) {
+ return &qoriq.pic.ii_1 [vector - n];
+ } else {
+ uintptr_t offs = ((uintptr_t)
+ src_cfg_offsets [vector - QORIQ_IRQ_EXT_BASE]) << 4;
+
+ return (volatile qoriq_pic_src_cfg *) ((uintptr_t) &qoriq.pic + offs);
+ }
+}
+
+rtems_status_code qoriq_pic_set_priority(
+ rtems_vector_number vector,
+ int new_priority,
+ int *old_priority
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ uint32_t old_vpr = 0;
+
+ if (bsp_interrupt_is_valid_vector(vector)) {
+ volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
+
+ if (QORIQ_PIC_PRIORITY_IS_VALID(new_priority)) {
+ rtems_interrupt_lock_context lock_context;
+
+ rtems_interrupt_lock_acquire(&lock, &lock_context);
+ old_vpr = src_cfg->vpr;
+ src_cfg->vpr = VPR_PRIORITY_SET(old_vpr, (uint32_t) new_priority);
+ rtems_interrupt_lock_release(&lock, &lock_context);
+ } else if (new_priority < 0) {
+ old_vpr = src_cfg->vpr;
+ } else {
+ sc = RTEMS_INVALID_PRIORITY;
+ }
+ } else {
+ sc = RTEMS_INVALID_ID;
+ }
+
+ if (old_priority != NULL) {
+ *old_priority = (int) VPR_PRIORITY_GET(old_vpr);
+ }
+
+ return sc;
+}
+
+void bsp_interrupt_set_affinity(
+ rtems_vector_number vector,
+ const Processor_mask *affinity
+)
+{
+ volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
+
+ src_cfg->dr = _Processor_mask_To_uint32_t(affinity, 0);
+}
+
+void bsp_interrupt_get_affinity(
+ rtems_vector_number vector,
+ Processor_mask *affinity
+)
+{
+ volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
+
+ _Processor_mask_From_uint32_t(affinity, src_cfg->dr, 0);
+}
+
+static void pic_vector_enable(rtems_vector_number vector, uint32_t msk)
+{
+ volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector);
+ rtems_interrupt_lock_context lock_context;
+
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ rtems_interrupt_lock_acquire(&lock, &lock_context);
+ src_cfg->vpr = (src_cfg->vpr & ~VPR_MSK) | msk;
+ rtems_interrupt_lock_release(&lock, &lock_context);
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ pic_vector_enable(vector, 0);
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ pic_vector_enable(vector, VPR_MSK);
+}
+
+void bsp_interrupt_dispatch(uintptr_t exception_number)
+{
+ rtems_vector_number vector = qoriq.pic.iack;
+
+ if (vector != SPURIOUS) {
+ uint32_t msr = ppc_external_exceptions_enable();
+
+ bsp_interrupt_handler_dispatch(vector);
+
+ ppc_external_exceptions_disable(msr);
+
+ qoriq.pic.eoi = 0;
+ qoriq.pic.whoami;
+ } else {
+ bsp_interrupt_handler_default(vector);
+ }
+}
+
+static bool pic_is_ipi(rtems_vector_number vector)
+{
+ return QORIQ_IRQ_IPI_0 <= vector && vector <= QORIQ_IRQ_IPI_3;
+}
+
+static void pic_reset(void)
+{
+ qoriq.pic.gcr = GCR_RST;
+ while ((qoriq.pic.gcr & GCR_RST) != 0) {
+ /* Wait */
+ }
+}
+
+static void pic_global_timer_init(void)
+{
+ int i = 0;
+
+ qoriq.pic.tcra = 0;
+ qoriq.pic.tcrb = 0;
+
+ for (i = 0; i < 4; ++i) {
+ qoriq.pic.gta [0].bcr = GTBCR_CI;
+ qoriq.pic.gtb [0].bcr = GTBCR_CI;
+ }
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ rtems_vector_number i = 0;
+ uint32_t processor_id = ppc_processor_id();
+
+ if (processor_id == 0) {
+ /* Core 0 must do the basic initialization */
+
+ pic_reset();
+
+ for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) {
+ volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(i);
+
+ src_cfg->vpr = VPR_MSK | VPR_P
+ | VPR_PRIORITY(QORIQ_PIC_PRIORITY_DEFAULT) | VPR_VECTOR(i);
+
+ if (!pic_is_ipi(i)) {
+ src_cfg->dr = 0x1;
+ }
+ }
+
+ qoriq.pic.mer03 = 0xf;
+ qoriq.pic.mer47 = 0xf;
+ qoriq.pic.svr = SPURIOUS;
+ qoriq.pic.gcr = GCR_M;
+
+ pic_global_timer_init();
+ }
+
+ qoriq.pic.ctpr = 0;
+
+ for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) {
+ qoriq.pic.iack;
+ qoriq.pic.eoi = 0;
+ qoriq.pic.whoami;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+#endif /* QORIQ_IS_HYPERVISOR_GUEST */
diff --git a/bsps/powerpc/shared/irq/i8259.c b/bsps/powerpc/shared/irq/i8259.c
new file mode 100644
index 0000000000..7363e87ba0
--- /dev/null
+++ b/bsps/powerpc/shared/irq/i8259.c
@@ -0,0 +1,149 @@
+/*
+ * This file contains the implementation of the function described in irq.h
+ * related to Intel 8259 Programmable Interrupt controller.
+ *
+ * Copyright (C) 1998, 1999 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/irq.h>
+
+/*-------------------------------------------------------------------------+
+| Cache for 1st and 2nd PIC IRQ line's status (enabled or disabled) register.
++--------------------------------------------------------------------------*/
+/*
+ * lower byte is interrupt mask on the master PIC.
+ * while upper bits are interrupt on the slave PIC.
+ */
+volatile rtems_i8259_masks i8259s_cache = 0xfffb;
+
+/*-------------------------------------------------------------------------+
+| Function: BSP_irq_disable_at_i8259s
+| Description: Mask IRQ line in appropriate PIC chip.
+| Global Variables: i8259s_cache
+| Arguments: vector_offset - number of IRQ line to mask.
+| Returns: original state or -1 on error.
++--------------------------------------------------------------------------*/
+int BSP_irq_disable_at_i8259s (const rtems_irq_number irqLine)
+{
+ unsigned short mask;
+ rtems_interrupt_level level;
+ int rval;
+
+ if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) ||
+ ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET)
+ )
+ return -1;
+
+ rtems_interrupt_disable(level);
+
+ mask = 1 << irqLine;
+ rval = i8259s_cache & mask ? 0 : 1;
+ i8259s_cache |= mask;
+
+ if (irqLine < 8)
+ {
+ outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
+ }
+ else
+ {
+ outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8));
+ }
+ rtems_interrupt_enable(level);
+
+ return rval;
+}
+
+/*-------------------------------------------------------------------------+
+| Function: BSP_irq_enable_at_i8259s
+| Description: Unmask IRQ line in appropriate PIC chip.
+| Global Variables: i8259s_cache
+| Arguments: irqLine - number of IRQ line to mask.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+int BSP_irq_enable_at_i8259s (const rtems_irq_number irqLine)
+{
+ unsigned short mask;
+ rtems_interrupt_level level;
+
+ if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) ||
+ ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET )
+ )
+ return 1;
+
+ rtems_interrupt_disable(level);
+
+ mask = ~(1 << irqLine);
+ i8259s_cache &= mask;
+
+ if (irqLine < 8)
+ {
+ outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
+ }
+ else
+ {
+ outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8));
+ }
+ rtems_interrupt_enable(level);
+
+ return 0;
+} /* mask_irq */
+
+int BSP_irq_enabled_at_i8259s (const rtems_irq_number irqLine)
+{
+ unsigned short mask;
+
+ if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) ||
+ ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET)
+ )
+ return 1;
+
+ mask = (1 << irqLine);
+ return (~(i8259s_cache & mask));
+}
+
+/*-------------------------------------------------------------------------+
+| Function: BSP_irq_ack_at_i8259s
+| Description: Signal generic End Of Interrupt (EOI) to appropriate PIC.
+| Global Variables: None.
+| Arguments: irqLine - number of IRQ line to acknowledge.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+int BSP_irq_ack_at_i8259s (const rtems_irq_number irqLine)
+{
+ if (irqLine >= 8) {
+ outport_byte(PIC_MASTER_COMMAND_IO_PORT, SLAVE_PIC_EOSI);
+ outport_byte(PIC_SLAVE_COMMAND_IO_PORT, (PIC_EOSI | (irqLine - 8)));
+ }
+ else {
+ outport_byte(PIC_MASTER_COMMAND_IO_PORT, (PIC_EOSI | irqLine));
+ }
+
+ return 0;
+
+} /* ackIRQ */
+
+void BSP_i8259s_init(void)
+{
+ /*
+ * init master 8259 interrupt controller
+ */
+ outport_byte(PIC_MASTER_COMMAND_IO_PORT, 0x11); /* Start init sequence */
+ outport_byte(PIC_MASTER_IMR_IO_PORT, 0x00);/* Vector base = 0 */
+ outport_byte(PIC_MASTER_IMR_IO_PORT, 0x04);/* edge tiggered, Cascade (slave) on IRQ2 */
+ outport_byte(PIC_MASTER_IMR_IO_PORT, 0x01);/* Select 8086 mode */
+ outport_byte(PIC_MASTER_IMR_IO_PORT, 0xFB); /* Mask all except cascade */
+ /*
+ * init slave interrupt controller
+ */
+ outport_byte(PIC_SLAVE_COMMAND_IO_PORT, 0x11); /* Start init sequence */
+ outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x08);/* Vector base = 8 */
+ outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x02);/* edge triggered, Cascade (slave) on IRQ2 */
+ outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x01); /* Select 8086 mode */
+ outport_byte(PIC_SLAVE_IMR_IO_PORT, 0xFF); /* Mask all */
+
+}
diff --git a/bsps/powerpc/shared/irq/irq_init.c b/bsps/powerpc/shared/irq/irq_init.c
new file mode 100644
index 0000000000..1a44992a5b
--- /dev/null
+++ b/bsps/powerpc/shared/irq/irq_init.c
@@ -0,0 +1,364 @@
+/* irq_init.c
+ *
+ * This file contains the implementation of rtems initialization
+ * related to interrupt handling.
+ *
+ * CopyRight (C) 1999 valette@crf.canon.fr
+ *
+ * Enhanced by Jay Kulpinski <jskulpin@eng01.gdds.com>
+ * to make it valid for MVME2300 Motorola boards.
+ *
+ * Till Straumann <strauman@slac.stanford.edu>, 12/20/2001:
+ * Use the new interface to openpic_init
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <libcpu/io.h>
+#include <libcpu/spr.h>
+#include <bsp/pci.h>
+#include <bsp/residual.h>
+#include <bsp/irq.h>
+#if BSP_PCI_IRQ_NUMBER > 0
+#include <bsp/openpic.h>
+#endif
+#include <bsp/irq_supp.h>
+#include <bsp.h>
+#include <bsp/motorola.h>
+#include <rtems/bspIo.h>
+
+typedef struct {
+ unsigned char bus; /* few chance the PCI/ISA bridge is not on first bus but ... */
+ unsigned char device;
+ unsigned char function;
+} pci_isa_bridge_device;
+
+pci_isa_bridge_device* via_82c586 = 0;
+#ifndef qemu
+static pci_isa_bridge_device bridge;
+#endif
+
+/*
+ * default methods
+ */
+static void nop_hdl(rtems_irq_hdl_param ignored)
+{
+}
+
+static void nop_irq_enable(const struct __rtems_irq_connect_data__*ignored)
+{
+}
+
+static int irq_is_connected(const struct __rtems_irq_connect_data__*ignored)
+{
+ return 0;
+}
+
+
+static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
+static rtems_irq_global_settings initial_config;
+static rtems_irq_connect_data defaultIrq = {
+ 0, /* vector */
+ nop_hdl, /* hdl */
+ NULL, /* handle */
+ nop_irq_enable, /* on */
+ nop_irq_enable, /* off */
+ irq_is_connected /* isOn */
+#ifdef BSP_SHARED_HANDLER_SUPPORT
+ , NULL /* next_handler */
+#endif
+};
+static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={
+ /*
+ * actual priorities for interrupt :
+ * 0 means that only current interrupt is masked
+ * 255 means all other interrupts are masked
+ */
+ /*
+ * ISA interrupts.
+ * The second entry has a priority of 255 because
+ * it is the slave pic entry and should always remain
+ * unmasked.
+ */
+ 0,0,
+ 255,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#if BSP_PCI_IRQ_NUMBER > 0
+ /*
+ * PCI Interrupts
+ */
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */
+#endif
+ /*
+ * Processor exceptions handled as interrupts
+ */
+ 0
+};
+
+#if BSP_PCI_IRQ_NUMBER > 0
+#if defined(mvme2100)
+static unsigned char mvme2100_openpic_initpolarities[16] = {
+ 0, /* Not used - should be disabled */
+ 0, /* DEC21143 Controller */
+ 0, /* PMC/PC-MIP Type I Slot 0 */
+ 0, /* PC-MIP Type I Slot 1 */
+ 0, /* PC-MIP Type II Slot 0 */
+ 0, /* PC-MIP Type II Slot 1 */
+ 0, /* Not used - should be disabled */
+ 0, /* PCI Expansion Interrupt A/Universe II (LINT0) */
+ 0, /* PCI Expansion Interrupt B/Universe II (LINT1) */
+ 0, /* PCI Expansion Interrupt C/Universe II (LINT2) */
+ 0, /* PCI Expansion Interrupt D/Universe II (LINT3) */
+ 0, /* Not used - should be disabled */
+ 0, /* Not used - should be disabled */
+ 1, /* 16550 UART */
+ 0, /* Front panel Abort Switch */
+ 0, /* RTC IRQ */
+};
+
+static unsigned char mvme2100_openpic_initsenses[] = {
+ 0, /* Not used - should be disabled */
+ 1, /* DEC21143 Controller */
+ 1, /* PMC/PC-MIP Type I Slot 0 */
+ 1, /* PC-MIP Type I Slot 1 */
+ 1, /* PC-MIP Type II Slot 0 */
+ 1, /* PC-MIP Type II Slot 1 */
+ 0, /* Not used - should be disabled */
+ 1, /* PCI Expansion Interrupt A/Universe II (LINT0) */
+ 1, /* PCI Expansion Interrupt B/Universe II (LINT1) */
+ 1, /* PCI Expansion Interrupt C/Universe II (LINT2) */
+ 1, /* PCI Expansion Interrupt D/Universe II (LINT3) */
+ 0, /* Not used - should be disabled */
+ 0, /* Not used - should be disabled */
+ 1, /* 16550 UART */
+ 0, /* Front panel Abort Switch */
+ 1, /* RTC IRQ */
+};
+#else
+static unsigned char mcp750_openpic_initpolarities[16] = {
+ 1, /* 8259 cascade */
+ 0, /* all the rest of them */
+};
+
+static unsigned char mcp750_openpic_initsenses[] = {
+ 1, /* MCP750_INT_PCB(8259) */
+ 0, /* MCP750_INT_FALCON_ECC_ERR */
+ 1, /* MCP750_INT_PCI_ETHERNET */
+ 1, /* MCP750_INT_PCI_PMC */
+ 1, /* MCP750_INT_PCI_WATCHDOG_TIMER1 */
+ 1, /* MCP750_INT_PCI_PRST_SIGNAL */
+ 1, /* MCP750_INT_PCI_FALL_SIGNAL */
+ 1, /* MCP750_INT_PCI_DEG_SIGNAL */
+ 1, /* MCP750_INT_PCI_BUS1_INTA */
+ 1, /* MCP750_INT_PCI_BUS1_INTB */
+ 1, /* MCP750_INT_PCI_BUS1_INTC */
+ 1, /* MCP750_INT_PCI_BUS1_INTD */
+ 1, /* MCP750_INT_PCI_BUS2_INTA */
+ 1, /* MCP750_INT_PCI_BUS2_INTB */
+ 1, /* MCP750_INT_PCI_BUS2_INTC */
+ 1, /* MCP750_INT_PCI_BUS2_INTD */
+};
+#endif
+#endif
+
+#if BSP_ISA_IRQ_NUMBER > 0 && !defined(qemu)
+void VIA_isa_bridge_interrupts_setup(void)
+{
+ pci_isa_bridge_device pci_dev;
+ uint32_t temp;
+ unsigned char tmp;
+ unsigned char maxBus;
+ unsigned found = 0;
+
+ maxBus = pci_bus_count();
+ pci_dev.function = 0; /* Assumes the bidge is the first function */
+
+ for (pci_dev.bus = 0; pci_dev.bus < maxBus; pci_dev.bus++) {
+#ifdef SCAN_PCI_PRINT
+ printk("isa_bridge_interrupts_setup: Scanning bus %d\n", pci_dev.bus);
+#endif
+ for (pci_dev.device = 0; pci_dev.device < PCI_MAX_DEVICES; pci_dev.device++) {
+#ifdef SCAN_PCI_PRINT
+ printk("isa_bridge_interrupts_setup: Scanning device %d\n", pci_dev.device);
+#endif
+ pci_read_config_dword(pci_dev.bus, pci_dev.device, pci_dev.function,
+ PCI_VENDOR_ID, &temp);
+#ifdef SCAN_PCI_PRINT
+ printk("Vendor/device = %x\n", temp);
+#endif
+ if ((temp == (((unsigned short) PCI_VENDOR_ID_VIA) | (PCI_DEVICE_ID_VIA_82C586_0 << 16)))
+ ) {
+ bridge = pci_dev;
+ via_82c586 = &bridge;
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ /*
+ * Should print : bus = 0, device = 11, function = 0 on a MCP750.
+ */
+ printk("Via PCI/ISA bridge found at bus = %d, device = %d, function = %d\n",
+ via_82c586->bus,
+ via_82c586->device,
+ via_82c586->function);
+#endif
+ found = 1;
+ goto loop_exit;
+
+ }
+ }
+ }
+loop_exit:
+ if (!found) rtems_panic("VIA_82C586 PCI/ISA bridge not found!n");
+
+ tmp = inb(0x810);
+ if ( !(tmp & 0x2)) {
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ printk("This is a second generation MCP750 board\n");
+ printk("We must reprogram the PCI/ISA bridge...\n");
+#endif
+ pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
+ 0x47, &tmp);
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp);
+#endif
+ /*
+ * Enable 4D0/4D1 ISA interrupt level/edge config registers
+ */
+ tmp |= 0x20;
+ pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
+ 0x47, tmp);
+ /*
+ * Now program the ISA interrupt edge/level
+ */
+ tmp = ELCRS_INT9_LVL | ELCRS_INT10_LVL | ELCRS_INT11_LVL;
+ outb(tmp, ISA8259_S_ELCR);
+ tmp = ELCRM_INT5_LVL;
+ outb(tmp, ISA8259_M_ELCR);
+ /*
+ * Set the Interrupt inputs to non-inverting level interrupt
+ */
+ pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
+ 0x54, &tmp);
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp);
+#endif
+ tmp = 0;
+ pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
+ 0x54, tmp);
+ }
+ else {
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ printk("This is a first generation MCP750 board\n");
+ printk("We just show the actual value used by PCI/ISA bridge\n");
+#endif
+ pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
+ 0x47, &tmp);
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp);
+#endif
+ /*
+ * Show the Interrupt inputs inverting/non-inverting level status
+ */
+ pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function,
+ 0x54, &tmp);
+#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS
+ printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp);
+#endif
+ }
+}
+#endif
+
+ /*
+ * This code assumes the exceptions management setup has already
+ * been done. We just need to replace the exceptions that will
+ * be handled like interrupt. On mcp750/mpc750 and many PPC processors
+ * this means the decrementer exception and the external exception.
+ */
+void BSP_rtems_irq_mng_init(unsigned cpuId)
+{
+#if BSP_ISA_IRQ_NUMBER > 0 && !defined(mvme2100)
+ int known_cpi_isa_bridge = 0;
+#endif
+ int i;
+
+ /*
+ * First initialize the Interrupt management hardware
+ */
+#if defined(mvme2100)
+#ifdef TRACE_IRQ_INIT
+ printk("Going to initialize EPIC interrupt controller (openpic compliant)\n");
+#endif
+ /* EPIC sources don't start at the regular place; define appropriate offset
+ * prior to initializing the PIC.
+ */
+ openpic_init(1, mvme2100_openpic_initpolarities, mvme2100_openpic_initsenses, 16, 16, BSP_bus_frequency);
+#else
+#if BSP_PCI_IRQ_NUMBER > 0
+#ifdef TRACE_IRQ_INIT
+ printk("Going to initialize raven interrupt controller (openpic compliant)\n");
+#endif
+ openpic_init(1, mcp750_openpic_initpolarities, mcp750_openpic_initsenses, 0, 0, 0);
+#ifdef TRACE_IRQ_INIT
+ printk("Going to initialize the PCI/ISA bridge IRQ related setting (VIA 82C586)\n");
+#endif
+#endif
+
+#if BSP_ISA_IRQ_NUMBER > 0
+ if ( currentBoard == MESQUITE ) {
+#ifndef qemu
+ VIA_isa_bridge_interrupts_setup();
+#endif
+ known_cpi_isa_bridge = 1;
+ }
+ if ( currentBoard == MVME_2300 ) {
+ /* nothing to do for W83C553 bridge */
+ known_cpi_isa_bridge = 1;
+ }
+ if ( currentBoard == MTX_WO_PP || currentBoard == MTX_W_PP ) {
+ /* W83C554, don't to anything at the moment. gregm 11/6/2002 */
+ known_cpi_isa_bridge = 1;
+ }
+
+ if (!known_cpi_isa_bridge) {
+ printk("Please add code for PCI/ISA bridge init to libbsp/powerpc/shared/irq/irq_init.c\n");
+ printk("If your card works correctly please add a test and set known_cpi_isa_bridge to true\n");
+ printk("currentBoard = %i\n", currentBoard);
+ }
+#ifdef TRACE_IRQ_INIT
+ printk("Going to initialize the ISA PC legacy IRQ management hardware\n");
+#endif
+ BSP_i8259s_init();
+#endif
+
+#endif
+
+ /*
+ * Initialize RTEMS management interrupt table
+ */
+ /*
+ * re-init the rtemsIrq table
+ */
+ for (i = 0; i < BSP_IRQ_NUMBER; i++) {
+ rtemsIrq[i] = defaultIrq;
+ rtemsIrq[i].name = i;
+ }
+ /*
+ * Init initial Interrupt management config
+ */
+ initial_config.irqNb = BSP_IRQ_NUMBER;
+ initial_config.defaultEntry = defaultIrq;
+ initial_config.irqHdlTbl = rtemsIrq;
+ initial_config.irqBase = BSP_LOWEST_OFFSET;
+ initial_config.irqPrioTbl = irqPrioTable;
+
+ if (!BSP_rtems_irq_mngt_set(&initial_config)) {
+ /*
+ * put something here that will show the failure...
+ */
+ rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
+ }
+
+#ifdef TRACE_IRQ_INIT
+ printk("RTEMS IRQ management is now operational\n");
+#endif
+}
diff --git a/bsps/powerpc/shared/irq/openpic.c b/bsps/powerpc/shared/irq/openpic.c
new file mode 100644
index 0000000000..556014964b
--- /dev/null
+++ b/bsps/powerpc/shared/irq/openpic.c
@@ -0,0 +1,622 @@
+/*
+ * openpic.c -- OpenPIC Interrupt Handling
+ *
+ * Copyright (C) 1997 Geert Uytterhoeven
+ *
+ * Modified to compile in RTEMS development environment
+ * by Eric Valette
+ *
+ * Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+/*
+ * Note: Interprocessor Interrupt (IPI) and Timer support is incomplete
+ */
+
+#include <rtems.h>
+#include <bsp.h>
+#include <rtems/bspIo.h>
+#include <bsp/openpic.h>
+#include <rtems/pci.h>
+#include <libcpu/io.h>
+#include <libcpu/byteorder.h>
+#include <rtems/bspIo.h>
+#include <inttypes.h>
+
+#ifndef NULL
+#define NULL 0
+#endif
+#define REGISTER_DEBUG
+#undef REGISTER_DEBUG
+
+volatile struct OpenPIC *OpenPIC = NULL;
+
+static unsigned int NumProcessors;
+static unsigned int NumSources;
+
+static unsigned int openpic_eoi_delay = 0;
+static int openpic_src_offst = 0;
+#define SOURCE(irq) Source[ (irq) + openpic_src_offst ]
+
+ /*
+ * Accesses to the current processor's registers
+ */
+
+#define THIS_CPU Processor[cpu]
+#define CHECK_THIS_CPU check_arg_cpu(cpu)
+
+ /*
+ * Sanity checks
+ */
+
+#if 1
+/* This software deliberately uses non-zero values to the method
+ * __builtin_return_address() and we want to avoid the GCC warning.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wframe-address"
+#define check_arg_ipi(ipi) \
+ if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
+ printk("openpic.c:%d: illegal ipi %d\n", __LINE__, ipi);
+#define check_arg_timer(timer) \
+ if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
+ printk("openpic.c:%d: illegal timer %d\n", __LINE__, timer);
+#define check_arg_vec(vec) \
+ if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
+ printk("openpic.c:%d: illegal vector %d\n", __LINE__, vec);
+#define check_arg_pri(pri) \
+ if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
+ printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri);
+#define check_arg_irq(irq) \
+ if (irq < 0 || irq >= NumSources) \
+ printk("openpic.c:%d: illegal irq %d from 0x%08" PRIxPTR ",[0x%08" PRIxPTR "],[[0x%08" PRIxPTR "]]\n", \
+ __LINE__, irq, (uintptr_t) __builtin_return_address(0), \
+ (uintptr_t) __builtin_return_address(1), (uintptr_t) __builtin_return_address(2) \
+ );
+#define check_arg_cpu(cpu) \
+ if (cpu < 0 || cpu >= NumProcessors) \
+ printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu);
+#else
+#define check_arg_ipi(ipi) do {} while (0)
+#define check_arg_timer(timer) do {} while (0)
+#define check_arg_vec(vec) do {} while (0)
+#define check_arg_pri(pri) do {} while (0)
+#define check_arg_irq(irq) do {} while (0)
+#define check_arg_cpu(cpu) do {} while (0)
+#endif
+
+ /*
+ * I/O functions
+ */
+
+static inline unsigned int openpic_read(volatile unsigned int *addr)
+{
+ unsigned int val;
+
+#ifdef BSP_OPEN_PIC_BIG_ENDIAN
+ val = in_be32((volatile uint32_t *)addr);
+#else
+ val = in_le32((volatile uint32_t *)addr);
+#endif
+#ifdef REGISTER_DEBUG
+ printk("openpic_read(0x%08x) = 0x%08x\n", (unsigned int)addr, val);
+#endif
+ return val;
+}
+
+static inline void openpic_write(volatile unsigned int *addr, unsigned int val)
+{
+#ifdef REGISTER_DEBUG
+ printk("openpic_write(0x%08x, 0x%08x)\n", (unsigned int)addr, val);
+#endif
+#ifdef BSP_OPEN_PIC_BIG_ENDIAN
+ out_be32((volatile uint32_t *)addr, val);
+#else
+ out_le32((volatile uint32_t *)addr, val);
+#endif
+}
+
+static inline unsigned int openpic_readfield(volatile unsigned int *addr, unsigned int mask)
+{
+ unsigned int val = openpic_read(addr);
+ return val & mask;
+}
+
+static inline void openpic_writefield(volatile unsigned int *addr, unsigned int mask,
+ unsigned int field)
+{
+ unsigned int val = openpic_read(addr);
+ openpic_write(addr, (val & ~mask) | (field & mask));
+}
+
+static inline void openpic_clearfield(volatile unsigned int *addr, unsigned int mask)
+{
+ openpic_writefield(addr, mask, 0);
+}
+
+static inline void openpic_setfield(volatile unsigned int *addr, unsigned int mask)
+{
+ openpic_writefield(addr, mask, mask);
+}
+
+ /*
+ * Update a Vector/Priority register in a safe manner. The interrupt will
+ * be disabled.
+ */
+
+static void openpic_safe_writefield(volatile unsigned int *addr, unsigned int mask,
+ unsigned int field)
+{
+ openpic_setfield(addr, OPENPIC_MASK);
+ /* wait until it's not in use */
+ while (openpic_read(addr) & OPENPIC_ACTIVITY);
+ openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
+}
+
+/* -------- Global Operations ---------------------------------------------- */
+
+ /*
+ * Initialize the OpenPIC
+ *
+ * Add some kludge to use the Motorola Raven OpenPIC which does not
+ * report vendor and device id, and gets the wrong number of interrupts.
+ * (Motorola did a great job on that one!)
+ *
+ * T. Straumann, 12/20/2001: polarities and senses are now passed as
+ * parameters, eliminated global vars.
+ * IRQ0 is no longer treated specially.
+ */
+
+void openpic_init(int main_pic, unsigned char *polarities, unsigned char *senses, int num_sources, int source_offset, unsigned long epic_freq)
+{
+ unsigned int t, i;
+ unsigned int vendorid, devid, stepping, timerfreq;
+ const char *version, *vendor, *device;
+
+ if (!OpenPIC)
+ rtems_panic("No OpenPIC found");
+
+ t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
+ switch (t & OPENPIC_FEATURE_VERSION_MASK) {
+ case 1:
+ version = "1.0";
+ break;
+ case 2:
+ version = "1.2";
+ break;
+ default:
+ version = "?";
+ break;
+ }
+ NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
+ OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
+ NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
+ OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
+ t = openpic_read(&OpenPIC->Global.Vendor_Identification);
+
+ vendorid = t & OPENPIC_VENDOR_ID_VENDOR_ID_MASK;
+ devid = (t & OPENPIC_VENDOR_ID_DEVICE_ID_MASK) >>
+ OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT;
+ stepping = (t & OPENPIC_VENDOR_ID_STEPPING_MASK) >>
+ OPENPIC_VENDOR_ID_STEPPING_SHIFT;
+
+ /* Kludge for the Raven */
+/*
+ pci_read_config_dword(0, 0, 0, 0, &t);
+*/
+ if (t == PCI_VENDOR_ID_MOTOROLA + (PCI_DEVICE_ID_MOTOROLA_RAVEN<<16)) {
+ vendor = "Motorola";
+ device = "Raven";
+ NumSources += 1;
+ }
+ else if (t == PCI_VENDOR_ID_MOTOROLA + (PCI_DEVICE_ID_MOTOROLA_HAWK<<16)) {
+ vendor = "Motorola";
+ device = "Hawk";
+ NumSources += 1;
+ } else {
+ switch (vendorid) {
+ case OPENPIC_VENDOR_ID_APPLE:
+ vendor = "Apple";
+ break;
+ default:
+ vendor = "Unknown";
+ break;
+ }
+ switch (devid) {
+ case OPENPIC_DEVICE_ID_APPLE_HYDRA:
+ device = "Hydra";
+ break;
+ default:
+ device = "Unknown";
+ break;
+ }
+ }
+ printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at 0x%08" PRIuPTR "\n", version,
+ NumProcessors, NumSources, (uintptr_t) OpenPIC);
+
+ printk("OpenPIC Vendor %d (%s), Device %d (%s), Stepping %d\n", vendorid,
+ vendor, devid, device, stepping);
+
+ /* Override if they desire */
+ if ( num_sources ) {
+ if ( NumSources != num_sources )
+ printk("Overriding NumSources (%i) from configuration with %i\n",
+ NumSources, num_sources);
+ NumSources = num_sources;
+ }
+
+ openpic_src_offst = source_offset;
+
+ timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
+ printk("OpenPIC timer frequency is ");
+ if (timerfreq)
+ printk("%d Hz\n", timerfreq);
+ else
+ printk("not set\n");
+
+ if ( main_pic )
+ {
+ /* Initialize timer interrupts */
+ for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
+ /* Disabled, Priority 0 */
+ openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
+ /* No processor */
+ openpic_maptimer(i, 0);
+ }
+
+ /* Initialize IPI interrupts */
+ for (i = 0; i < OPENPIC_NUM_IPI; i++) {
+ /* Disabled, Priority 0 */
+ openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
+ }
+
+ /* Initialize external interrupts */
+ for (i = 0; i < NumSources; i++) {
+ /* Enabled, Priority 8 */
+ openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i,
+ polarities ? polarities[i] : 0,
+ senses ? senses[i] : 1);
+ /* Processor 0 */
+ openpic_mapirq(i, 1<<0);
+ }
+
+ /* Initialize the spurious interrupt */
+ openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
+#if 0
+ if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
+ "82c59 cascade", NULL))
+ printk("Unable to get OpenPIC IRQ 0 for cascade\n");
+#endif
+ openpic_set_priority(0, 0);
+ openpic_disable_8259_pass_through();
+ }
+ if ( epic_freq ) {
+ /* Speed up the serial interface; if it is too slow then we might get spurious
+ * interrupts:
+ * After an ISR clears the interrupt condition at the source/device, the wire
+ * remains asserted during the propagation delay introduced by the serial interface
+ * (something really stupid). If the ISR returns while the wire is not released
+ * yet, then a spurious interrupt happens.
+ * The book says we should be careful if the serial clock is > 33MHz.
+ * Empirically, it seems that running it at 33MHz is fast enough. Otherwise,
+ * we should introduce a delay in openpic_eoi().
+ * The maximal delay are 16 (serial) clock cycles. If the divisor is 8
+ * [power-up default] then the lag is 2us [66MHz SDRAM clock; I assume this
+ * is equal to the bus frequency].
+ * FIXME: This should probably be a EPIC-specific piece in 'openpic.c'
+ * Unfortunately, there is no easy way of figuring out if the
+ * device is an EPIC or not.
+ */
+ uint32_t eicr_val, ratio;
+ /* On the 8240 this is the EICR register */
+ eicr_val = in_le32( (volatile uint32_t *)&OpenPIC->Global.Global_Configuration1 ) & ~(7<<28);
+ if ( (1<<27) & eicr_val ) {
+ /* serial interface mode enabled */
+
+ /* round to nearest integer:
+ * round(Bus_freq/33000000) = floor( 2*(Bus_freq/33e6) + 1 ) / 2
+ */
+ ratio = epic_freq / 16500000 + 1;
+ ratio >>= 2; /* EICR value is half actual divisor */
+ if ( 0==ratio )
+ ratio = 1;
+ out_le32((volatile uint32_t *)&OpenPIC->Global.Global_Configuration1, eicr_val | ((ratio &7) << 28));
+ /* Delay in TB cycles (assuming TB runs at 1/4 of the bus frequency) */
+ openpic_set_eoi_delay( 16 * (2*ratio) / 4 );
+ }
+ }
+}
+
+ /*
+ * Reset the OpenPIC
+ */
+
+void openpic_reset(void)
+{
+ openpic_setfield(&OpenPIC->Global.Global_Configuration0,
+ OPENPIC_CONFIG_RESET);
+}
+
+ /*
+ * Enable/disable 8259 Pass Through Mode
+ */
+
+void openpic_enable_8259_pass_through(void)
+{
+ openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
+ OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
+}
+
+void openpic_disable_8259_pass_through(void)
+{
+ openpic_setfield(&OpenPIC->Global.Global_Configuration0,
+ OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
+}
+
+ /*
+ * Find out the current interrupt
+ */
+
+unsigned int openpic_irq(unsigned int cpu)
+{
+ unsigned int vec;
+
+ check_arg_cpu(cpu);
+ vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
+ OPENPIC_VECTOR_MASK);
+ return vec;
+}
+
+ /*
+ * Signal end of interrupt (EOI) processing
+ */
+
+void openpic_eoi(unsigned int cpu)
+{
+ check_arg_cpu(cpu);
+ if ( openpic_eoi_delay )
+ rtems_bsp_delay_in_bus_cycles(openpic_eoi_delay);
+ openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
+}
+
+unsigned openpic_set_eoi_delay(unsigned tb_cycles)
+{
+unsigned rval = openpic_eoi_delay;
+ openpic_eoi_delay = tb_cycles;
+ return rval;
+}
+
+ /*
+ * Get/set the current task priority
+ */
+
+unsigned int openpic_get_priority(unsigned int cpu)
+{
+ CHECK_THIS_CPU;
+ return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
+ OPENPIC_CURRENT_TASK_PRIORITY_MASK);
+}
+
+void openpic_set_priority(unsigned int cpu, unsigned int pri)
+{
+ CHECK_THIS_CPU;
+ check_arg_pri(pri);
+ openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
+ OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
+}
+
+ /*
+ * Get/set the spurious vector
+ */
+
+unsigned int openpic_get_spurious(void)
+{
+ return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
+ OPENPIC_VECTOR_MASK);
+}
+
+void openpic_set_spurious(unsigned int vec)
+{
+ check_arg_vec(vec);
+ openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
+ vec);
+}
+
+ /*
+ * Initialize one or more CPUs
+ */
+
+void openpic_init_processor(unsigned int cpumask)
+{
+ openpic_write(&OpenPIC->Global.Processor_Initialization, cpumask);
+}
+
+/* -------- Interprocessor Interrupts -------------------------------------- */
+
+ /*
+ * Initialize an interprocessor interrupt (and disable it)
+ *
+ * ipi: OpenPIC interprocessor interrupt number
+ * pri: interrupt source priority
+ * vec: the vector it will produce
+ */
+
+void openpic_initipi(unsigned int ipi, unsigned int pri, unsigned int vec)
+{
+ check_arg_timer(ipi);
+ check_arg_pri(pri);
+ check_arg_vec(vec);
+ openpic_safe_writefield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
+ OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
+ (pri << OPENPIC_PRIORITY_SHIFT) | vec);
+}
+
+ /*
+ * Send an IPI to one or more CPUs
+ */
+
+void openpic_cause_IPI(unsigned int cpu, unsigned int ipi, unsigned int cpumask)
+{
+ CHECK_THIS_CPU;
+ check_arg_ipi(ipi);
+ openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpumask);
+}
+
+/* -------- Timer Interrupts ----------------------------------------------- */
+
+ /*
+ * Initialize a timer interrupt (and disable it)
+ *
+ * timer: OpenPIC timer number
+ * pri: interrupt source priority
+ * vec: the vector it will produce
+ */
+
+void openpic_inittimer(unsigned int timer, unsigned int pri, unsigned int vec)
+{
+ check_arg_timer(timer);
+ check_arg_pri(pri);
+ check_arg_vec(vec);
+ openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority,
+ OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
+ (pri << OPENPIC_PRIORITY_SHIFT) | vec);
+}
+
+ /*
+ * Map a timer interrupt to one or more CPUs
+ */
+
+void openpic_maptimer(unsigned int timer, unsigned int cpumask)
+{
+ check_arg_timer(timer);
+ openpic_write(&OpenPIC->Global.Timer[timer].Destination, cpumask);
+}
+
+ /*
+ * Set base count and / or enable / disable interrupt.
+ */
+
+
+void openpic_settimer(unsigned int timer, unsigned int base_count, int irq_enable)
+{
+ check_arg_timer(timer);
+ if ( base_count )
+ openpic_write(&OpenPIC->Global.Timer[timer].Base_Count, base_count);
+ if ( irq_enable )
+ openpic_clearfield(&OpenPIC->Global.Timer[timer].Vector_Priority, OPENPIC_MASK);
+ else
+ openpic_setfield(&OpenPIC->Global.Timer[timer].Vector_Priority, OPENPIC_MASK);
+}
+
+unsigned int openpic_gettimer(unsigned int timer)
+{
+ check_arg_timer(timer);
+ return (openpic_read(&OpenPIC->Global.Timer[timer].Current_Count) & ~OPENPIC_MASK);
+}
+
+/* -------- Interrupt Sources ---------------------------------------------- */
+
+ /*
+ * Enable/disable an interrupt source
+ */
+
+void openpic_enable_irq(unsigned int irq)
+{
+unsigned long flags;
+ check_arg_irq(irq);
+ rtems_interrupt_disable(flags);
+ openpic_clearfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK);
+ rtems_interrupt_enable(flags);
+}
+
+int openpic_disable_irq(unsigned int irq)
+{
+int rval;
+unsigned long flags;
+ check_arg_irq(irq);
+ if ( irq < 0 || irq >=NumSources )
+ return -1;
+ rtems_interrupt_disable(flags);
+ rval = openpic_readfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK) ? 0 : 1;
+ openpic_setfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK);
+ rtems_interrupt_enable(flags);
+ return rval;
+}
+
+ /*
+ * Initialize an interrupt source (and disable it!)
+ *
+ * irq: OpenPIC interrupt number
+ * pri: interrupt source priority
+ * vec: the vector it will produce
+ * pol: polarity (1 for positive, 0 for negative)
+ * sense: 1 for level, 0 for edge
+ */
+
+void openpic_initirq(unsigned int irq, unsigned int pri, unsigned int vec, int pol, int sense)
+{
+#if 0
+ printk("openpic_initirq: irq=%d pri=%d vec=%d pol=%d sense=%d\n",
+ irq, pri, vec, pol, sense);
+#endif
+
+ check_arg_irq(irq);
+ check_arg_pri(pri);
+ check_arg_vec(vec);
+ openpic_safe_writefield(&OpenPIC->SOURCE(irq).Vector_Priority,
+ OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
+ OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL,
+ (pri << OPENPIC_PRIORITY_SHIFT) | vec |
+ (pol ? OPENPIC_SENSE_POLARITY : 0) |
+ (sense ? OPENPIC_SENSE_LEVEL : 0));
+}
+
+ /*
+ * Map an interrupt source to one or more CPUs
+ */
+
+void openpic_mapirq(unsigned int irq, unsigned int cpumask)
+{
+ check_arg_irq(irq);
+ openpic_write(&OpenPIC->SOURCE(irq).Destination, cpumask);
+}
+
+ /*
+ * Get the current priority of an external interrupt
+ */
+unsigned int openpic_get_source_priority(unsigned int irq)
+{
+ check_arg_irq(irq);
+ return openpic_readfield(&OpenPIC->SOURCE(irq).Vector_Priority,
+ OPENPIC_PRIORITY_MASK) >> OPENPIC_PRIORITY_SHIFT;
+}
+
+void openpic_set_source_priority(unsigned int irq, unsigned int pri)
+{
+unsigned long flags;
+ check_arg_irq(irq);
+ check_arg_pri(pri);
+ rtems_interrupt_disable(flags);
+ openpic_writefield(
+ &OpenPIC->SOURCE(irq).Vector_Priority,
+ OPENPIC_PRIORITY_MASK,
+ pri << OPENPIC_PRIORITY_SHIFT);
+ rtems_interrupt_enable(flags);
+}
+ /*
+ * Set the sense for an interrupt source (and disable it!)
+ *
+ * sense: 1 for level, 0 for edge
+ */
+
+void openpic_set_sense(unsigned int irq, int sense)
+{
+ check_arg_irq(irq);
+ openpic_safe_writefield(&OpenPIC->SOURCE(irq).Vector_Priority,
+ OPENPIC_SENSE_LEVEL,
+ (sense ? OPENPIC_SENSE_LEVEL : 0));
+}
diff --git a/bsps/powerpc/shared/irq/openpic_i8259_irq.c b/bsps/powerpc/shared/irq/openpic_i8259_irq.c
new file mode 100644
index 0000000000..4a9c393f7f
--- /dev/null
+++ b/bsps/powerpc/shared/irq/openpic_i8259_irq.c
@@ -0,0 +1,331 @@
+/*
+ *
+ * This file contains the i8259/openpic-specific implementation of
+ * the function described in irq.h
+ *
+ * Copyright (C) 1998, 1999 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <stdlib.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq_supp.h>
+#ifndef BSP_HAS_NO_VME
+#include <bsp/VMEConfig.h>
+#endif
+#if BSP_PCI_IRQ_NUMBER > 0
+#include <bsp/openpic.h>
+#endif
+#include <libcpu/io.h>
+#include <bsp/vectors.h>
+#include <stdlib.h>
+
+#include <rtems/bspIo.h> /* for printk */
+
+#ifndef qemu
+#define RAVEN_INTR_ACK_REG 0xfeff0030
+#else
+#define RAVEN_INTR_ACK_REG 0xbffffff0
+#endif
+
+#if BSP_ISA_IRQ_NUMBER > 0
+/*
+ * pointer to the mask representing the additionnal irq vectors
+ * that must be disabled when a particular entry is activated.
+ * They will be dynamically computed from the priority table given
+ * in BSP_rtems_irq_mngt_set();
+ * CAUTION : this table is accessed directly by interrupt routine
+ * prologue.
+ */
+rtems_i8259_masks irq_mask_or_tbl[BSP_IRQ_NUMBER];
+#endif
+
+/*
+ * default handler connected on each irq after bsp initialization
+ */
+static rtems_irq_connect_data default_rtems_entry;
+
+static rtems_irq_connect_data* rtems_hdl_tbl;
+
+#if BSP_ISA_IRQ_NUMBER > 0
+/*
+ * Check if IRQ is an ISA IRQ
+ */
+static inline int is_isa_irq(const rtems_irq_number irqLine)
+{
+ return (((int) irqLine <= BSP_ISA_IRQ_MAX_OFFSET) &&
+ ((int) irqLine >= BSP_ISA_IRQ_LOWEST_OFFSET)
+ );
+}
+#endif
+
+#if BSP_PCI_IRQ_NUMBER > 0
+/*
+ * Check if IRQ is an OPENPIC IRQ
+ */
+static inline int is_pci_irq(const rtems_irq_number irqLine)
+{
+ return OpenPIC && (((int) irqLine <= BSP_PCI_IRQ_MAX_OFFSET) &&
+ ((int) irqLine >= BSP_PCI_IRQ_LOWEST_OFFSET)
+ );
+}
+#endif
+
+/*
+ * ------------------------ RTEMS Irq helper functions ----------------
+ */
+
+#if BSP_ISA_IRQ_NUMBER > 0
+/*
+ * Caution : this function assumes the variable "*config"
+ * is already set and that the tables it contains are still valid
+ * and accessible.
+ */
+static void compute_i8259_masks_from_prio (rtems_irq_global_settings* config)
+{
+ int i;
+ int j;
+ /*
+ * Always mask at least current interrupt to prevent re-entrance
+ */
+ for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) {
+ * ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i);
+ for (j = BSP_ISA_IRQ_LOWEST_OFFSET; j < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; j++) {
+ /*
+ * Mask interrupts at i8259 level that have a lower priority
+ */
+ if (config->irqPrioTbl [i] > config->irqPrioTbl [j]) {
+ * ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j);
+ }
+ }
+ }
+}
+#endif
+
+void
+BSP_enable_irq_at_pic(const rtems_irq_number name)
+{
+#if BSP_ISA_IRQ_NUMBER > 0
+ if (is_isa_irq(name)) {
+ /*
+ * Enable interrupt at PIC level
+ */
+ BSP_irq_enable_at_i8259s ((int) name - BSP_ISA_IRQ_LOWEST_OFFSET);
+ }
+#endif
+
+#if BSP_PCI_IRQ_NUMBER > 0
+ if (is_pci_irq(name)) {
+ /*
+ * Enable interrupt at OPENPIC level
+ */
+ openpic_enable_irq ((int) name - BSP_PCI_IRQ_LOWEST_OFFSET);
+ }
+#endif
+}
+
+int
+BSP_disable_irq_at_pic(const rtems_irq_number name)
+{
+#if BSP_ISA_IRQ_NUMBER > 0
+ if (is_isa_irq(name)) {
+ /*
+ * disable interrupt at PIC level
+ */
+ return BSP_irq_disable_at_i8259s ((int) name - BSP_ISA_IRQ_LOWEST_OFFSET);
+ }
+#endif
+#if BSP_PCI_IRQ_NUMBER > 0
+ if (is_pci_irq(name)) {
+ /*
+ * disable interrupt at OPENPIC level
+ */
+ return openpic_disable_irq ((int) name - BSP_PCI_IRQ_LOWEST_OFFSET);
+ }
+#endif
+ return -1;
+}
+
+/*
+ * RTEMS Global Interrupt Handler Management Routines
+ */
+int BSP_setup_the_pic(rtems_irq_global_settings* config)
+{
+ int i;
+ /*
+ * Store various code accelerators
+ */
+ default_rtems_entry = config->defaultEntry;
+ rtems_hdl_tbl = config->irqHdlTbl;
+
+ /*
+ * set up internal tables used by rtems interrupt prologue
+ */
+
+#if BSP_ISA_IRQ_NUMBER > 0
+ /*
+ * start with ISA IRQ
+ */
+ compute_i8259_masks_from_prio (config);
+
+ for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) {
+ if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
+ BSP_irq_enable_at_i8259s (i);
+ }
+ else {
+ BSP_irq_disable_at_i8259s (i);
+ }
+ }
+
+ if ( BSP_ISA_IRQ_NUMBER > 0 ) {
+ /*
+ * must enable slave pic anyway
+ */
+ BSP_irq_enable_at_i8259s (2);
+ }
+#endif
+
+#if BSP_PCI_IRQ_NUMBER > 0
+ if ( ! OpenPIC )
+ return 1;
+ /*
+ * continue with PCI IRQ
+ */
+ for (i=BSP_PCI_IRQ_LOWEST_OFFSET; i < BSP_PCI_IRQ_LOWEST_OFFSET + BSP_PCI_IRQ_NUMBER ; i++) {
+ /*
+ * Note that openpic_set_priority() sets the TASK priority of the PIC
+ */
+ openpic_set_source_priority(i - BSP_PCI_IRQ_LOWEST_OFFSET,
+ config->irqPrioTbl[i]);
+ if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
+ openpic_enable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET);
+ }
+ else {
+ openpic_disable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET);
+ }
+ }
+
+#ifdef BSP_PCI_ISA_BRIDGE_IRQ
+ /*
+ * Must enable PCI/ISA bridge IRQ
+ */
+ openpic_enable_irq (BSP_PCI_ISA_BRIDGE_IRQ);
+#endif
+#endif
+
+ return 1;
+}
+
+int _BSP_vme_bridge_irq = -1;
+
+unsigned BSP_spuriousIntr = 0;
+
+/*
+ * High level IRQ handler called from shared_raw_irq_code_entry
+ */
+int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum)
+{
+ register unsigned int irq;
+#if BSP_ISA_IRQ_NUMBER > 0
+ register unsigned isaIntr; /* boolean */
+ register unsigned oldMask = 0; /* old isa pic masks */
+ register unsigned newMask; /* new isa pic masks */
+#endif
+
+ if (excNum == ASM_DEC_VECTOR) {
+
+ bsp_irq_dispatch_list(rtems_hdl_tbl, BSP_DECREMENTER, default_rtems_entry.hdl);
+
+ return 0;
+
+ }
+
+#if BSP_PCI_IRQ_NUMBER > 0
+ if ( OpenPIC ) {
+ irq = openpic_irq(0);
+ if (irq == OPENPIC_VEC_SPURIOUS) {
+ ++BSP_spuriousIntr;
+ return 0;
+ }
+
+ /* some BSPs might want to use a different numbering... */
+ irq = irq - OPENPIC_VEC_SOURCE + BSP_PCI_IRQ_LOWEST_OFFSET;
+ } else {
+#if BSP_ISA_IRQ_NUMBER > 0
+#ifdef BSP_PCI_ISA_BRIDGE_IRQ
+ irq = BSP_PCI_ISA_BRIDGE_IRQ;
+#else
+#error "Configuration Error -- BSP with ISA + PCI IRQs MUST define BSP_PCI_ISA_BRIDGE_IRQ"
+#endif
+#else
+ rtems_panic("MUST have an OpenPIC if BSP has PCI IRQs but no ISA IRQs");
+ /* rtems_panic() never returns but the 'return' statement silences
+ * a compiler warning about 'irq' possibly being used w/o initialization.
+ */
+ return -1;
+#endif
+ }
+#endif
+
+#if BSP_ISA_IRQ_NUMBER > 0
+#ifdef BSP_PCI_ISA_BRIDGE_IRQ
+#if 0 == BSP_PCI_IRQ_NUMBER
+#error "Configuration Error -- BSP w/o PCI IRQs MUST NOT define BSP_PCI_ISA_BRIDGE_IRQ"
+#endif
+ isaIntr = (irq == BSP_PCI_ISA_BRIDGE_IRQ);
+#else
+ isaIntr = 1;
+#endif
+ if (isaIntr) {
+ /*
+ * Acknowledge and read 8259 vector
+ */
+ irq = (unsigned int) (*(unsigned char *) RAVEN_INTR_ACK_REG);
+ /*
+ * store current PIC mask
+ */
+ oldMask = i8259s_cache;
+ newMask = oldMask | irq_mask_or_tbl [irq];
+ i8259s_cache = newMask;
+ outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
+ outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8));
+ BSP_irq_ack_at_i8259s (irq);
+#if BSP_PCI_IRQ_NUMBER > 0
+ if ( OpenPIC )
+ openpic_eoi(0);
+#endif
+ }
+#endif
+
+ /* dispatch handlers */
+ bsp_irq_dispatch_list(rtems_hdl_tbl, irq, default_rtems_entry.hdl);
+
+#if BSP_ISA_IRQ_NUMBER > 0
+ if (isaIntr) {
+ i8259s_cache = oldMask;
+ outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff);
+ outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8));
+ }
+ else
+#endif
+ {
+#if BSP_PCI_IRQ_NUMBER > 0
+#ifdef BSP_PCI_VME_DRIVER_DOES_EOI
+ /* leave it to the VME bridge driver to do EOI, so
+ * it can re-enable the openpic while handling
+ * VME interrupts (-> VME priorities in software)
+ */
+ if (_BSP_vme_bridge_irq != irq && OpenPIC)
+#endif
+ openpic_eoi(0);
+#else
+ do {} while (0);
+#endif
+ }
+ return 0;
+}
diff --git a/bsps/powerpc/t32mppc/irq/irq.c b/bsps/powerpc/t32mppc/irq/irq.c
new file mode 100644
index 0000000000..5b2c34d2c9
--- /dev/null
+++ b/bsps/powerpc/t32mppc/irq/irq.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2012, 2017 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/irq-generic.h>
+#include <bsp/vectors.h>
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+}
+
+void bsp_interrupt_dispatch(uintptr_t exception_number)
+{
+ if (exception_number == 10) {
+ t32mppc_decrementer_dispatch();
+ } else {
+ bsp_interrupt_handler_default(0);
+ }
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/powerpc/tqm8xx/irq/irq.c b/bsps/powerpc/tqm8xx/irq/irq.c
new file mode 100644
index 0000000000..2a94c27d1b
--- /dev/null
+++ b/bsps/powerpc/tqm8xx/irq/irq.c
@@ -0,0 +1,231 @@
+/*===============================================================*\
+| Project: RTEMS TQM8xx BSP |
++-----------------------------------------------------------------+
+| This file has been adapted to MPC8xx by |
+| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> |
+| Copyright (c) 2008 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
+| |
+| See the other copyright notice below for the original parts. |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.org/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver |
+\*===============================================================*/
+/* derived from: generic MPC83xx BSP */
+
+#include <rtems.h>
+#include <mpc8xx.h>
+
+#include <libcpu/powerpc-utility.h>
+#include <bsp/vectors.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+/*
+ * functions to enable/disable a source at the SIU/CPM irq controller
+ */
+
+static rtems_status_code bsp_irq_disable_at_SIU(rtems_vector_number irqnum)
+{
+ rtems_vector_number vecnum = irqnum - BSP_SIU_IRQ_LOWEST_OFFSET;
+ m8xx.simask &= ~(1 << (31 - vecnum));
+ return RTEMS_SUCCESSFUL;
+}
+
+static rtems_status_code bsp_irq_enable_at_SIU(rtems_vector_number irqnum)
+{
+ rtems_vector_number vecnum = irqnum - BSP_SIU_IRQ_LOWEST_OFFSET;
+ m8xx.simask |= (1 << (31 - vecnum));
+ return RTEMS_SUCCESSFUL;
+}
+
+static rtems_status_code bsp_irq_disable_at_CPM(rtems_vector_number irqnum)
+{
+ rtems_vector_number vecnum = irqnum - BSP_CPM_IRQ_LOWEST_OFFSET;
+ m8xx.cimr &= ~(1 << (vecnum));
+ return RTEMS_SUCCESSFUL;
+}
+
+static rtems_status_code bsp_irq_enable_at_CPM(rtems_vector_number irqnum)
+{
+ rtems_vector_number vecnum = irqnum - BSP_CPM_IRQ_LOWEST_OFFSET;
+ m8xx.cimr |= (1 << (vecnum));
+ return RTEMS_SUCCESSFUL;
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if (BSP_IS_CPM_IRQ(vector)) {
+ bsp_irq_enable_at_CPM(vector);
+ } else if (BSP_IS_SIU_IRQ(vector)) {
+ bsp_irq_enable_at_SIU(vector);
+ }
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if (BSP_IS_CPM_IRQ(vector)) {
+ bsp_irq_disable_at_CPM(vector);
+ } else if (BSP_IS_SIU_IRQ(vector)) {
+ bsp_irq_disable_at_SIU(vector);
+ }
+}
+
+/*
+ * IRQ Handler: this is called from the primary exception dispatcher
+ */
+static int BSP_irq_handle_at_cpm(void)
+{
+ int32_t cpvecnum;
+ uint32_t msr;
+
+ /* Get vector number: write IACK=1, then read vectir */
+ m8xx.civr = 1;
+ cpvecnum = (m8xx.civr >> 11) + BSP_CPM_IRQ_LOWEST_OFFSET;
+
+ /*
+ * Check the vector number,
+ * enable exceptions and dispatch the handler.
+ * NOTE: lower-prio interrupts are automatically masked in CPIC
+ */
+ if (BSP_IS_CPM_IRQ(cpvecnum)) {
+ /* Enable all interrupts */
+ msr = ppc_external_exceptions_enable();
+ /* Dispatch interrupt handlers */
+ bsp_interrupt_handler_dispatch(cpvecnum);
+ /* Restore machine state */
+ ppc_external_exceptions_disable(msr);
+ }
+ else {
+ /* not valid vector */
+ bsp_interrupt_handler_default(cpvecnum);
+ }
+ /*
+ * clear "in-service" bit
+ */
+ m8xx.cisr = 1 << (cpvecnum - BSP_CPM_IRQ_LOWEST_OFFSET);
+
+ return 0;
+}
+
+static int BSP_irq_handle_at_siu( unsigned excNum)
+{
+ int32_t sivecnum;
+ uint32_t msr;
+ bool is_cpm_irq;
+ uint32_t simask_save;
+ /*
+ * check, if interrupt is pending
+ * and repeat as long as valid interrupts are pending
+ */
+ while (0 != (m8xx.simask & m8xx.sipend)) {
+ /* Get vector number */
+ sivecnum = (m8xx.sivec >> 26);
+ is_cpm_irq = (sivecnum == BSP_CPM_INTERRUPT);
+ /*
+ * Check the vector number, mask lower priority interrupts, enable
+ * exceptions and dispatch the handler.
+ */
+ if (BSP_IS_SIU_IRQ(sivecnum)) {
+ simask_save = m8xx.simask;
+ /*
+ * if this is the CPM interrupt, mask lower prio interrupts at SIU
+ * else mask lower and same priority interrupts
+ */
+ m8xx.simask &= ~0 << (32
+ - sivecnum
+ - ((is_cpm_irq) ? 1 : 0));
+
+ if (is_cpm_irq) {
+ BSP_irq_handle_at_cpm();
+ }
+ else {
+ /* Enable all interrupts */
+ msr = ppc_external_exceptions_enable();
+ /* Dispatch interrupt handlers */
+ bsp_interrupt_handler_dispatch(sivecnum + BSP_SIU_IRQ_LOWEST_OFFSET);
+ /* Restore machine state */
+ ppc_external_exceptions_disable(msr);
+ /*
+ * clear pending bit, if edge triggered interrupt input
+ */
+ m8xx.sipend = 1 << (31 - sivecnum);
+ }
+
+
+ /* Restore initial masks */
+ m8xx.simask = simask_save;
+ } else {
+ /* not valid vector */
+ bsp_interrupt_handler_default(sivecnum);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Activate the CPIC
+ */
+static rtems_status_code mpc8xx_cpic_initialize( void)
+{
+ /*
+ * mask off all interrupts
+ */
+ m8xx.cimr = 0;
+ /*
+ * make sure CPIC request proper level at SIU interrupt controller
+ */
+ m8xx.cicr = (0x00e41f80 |
+ ((BSP_CPM_INTERRUPT/2) << 13));
+ /*
+ * enable CPIC interrupt in SIU interrupt controller
+ */
+ return bsp_irq_enable_at_SIU(BSP_CPM_INTERRUPT);
+}
+
+/*
+ * Activate the SIU interrupt controller
+ */
+static rtems_status_code mpc8xx_siu_int_initialize( void)
+{
+ /*
+ * mask off all interrupts
+ */
+ m8xx.simask = 0;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+static int mpc8xx_exception_handler(BSP_Exception_frame *frame,
+ unsigned exception_number)
+{
+ return BSP_irq_handle_at_siu(exception_number);
+}
+
+rtems_status_code bsp_interrupt_facility_initialize()
+{
+ /* Install exception handler */
+ if (ppc_exc_set_handler(ASM_EXT_VECTOR, mpc8xx_exception_handler)) {
+ return RTEMS_IO_ERROR;
+ }
+ /* Initialize the SIU interrupt controller */
+ if (mpc8xx_siu_int_initialize()) {
+ return RTEMS_IO_ERROR;
+ }
+ /* Initialize the CPIC interrupt controller */
+ return mpc8xx_cpic_initialize();
+}
diff --git a/bsps/powerpc/virtex/irq/irq_init.c b/bsps/powerpc/virtex/irq/irq_init.c
new file mode 100644
index 0000000000..55194cb1e6
--- /dev/null
+++ b/bsps/powerpc/virtex/irq/irq_init.c
@@ -0,0 +1,167 @@
+/*===============================================================*\
+| Project: RTEMS virtex BSP |
++-----------------------------------------------------------------+
+| Partially based on the code references which are named below. |
+| Adaptions, modifications, enhancements and any recent parts of |
+| the code are: |
+| Copyright (c) 2007 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.org/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the irq controller handler |
+\*===============================================================*/
+
+/* Content moved from opbintctrl.c:
+ *
+ * This file contains definitions and declarations for the
+ * Xilinx Off Processor Bus (OPB) Interrupt Controller
+ *
+ * Author: Keith Robertson <kjrobert@alumni.uwaterloo.ca>
+ * COPYRIGHT (c) 2005 Linn Products Ltd, Scotland.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/vectors.h>
+
+#include <libcpu/powerpc-utility.h>
+
+/*
+ * Acknowledge a mask of interrupts.
+ */
+static void set_iar(uint32_t mask)
+{
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IAR)) = mask;
+}
+
+/*
+ * Set IER state. Used to (dis)enable a mask of vectors.
+ * If you only have to do one, use enable/disable_vector.
+ */
+static void set_ier(uint32_t mask)
+{
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IER)) = mask;
+}
+
+/*
+ * Retrieve contents of Interrupt Pending Register
+ */
+static uint32_t get_ipr(void)
+{
+ uint32_t c = *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IPR));
+ return c;
+}
+
+static void BSP_irq_enable_at_opbintc (rtems_irq_number irqnum)
+{
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_SIE))
+ = 1 << (irqnum - BSP_OPBINTC_IRQ_LOWEST_OFFSET);
+}
+
+static void BSP_irq_disable_at_opbintc (rtems_irq_number irqnum)
+{
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_CIE))
+ = 1 << (irqnum - BSP_OPBINTC_IRQ_LOWEST_OFFSET);
+}
+
+/*
+ * IRQ Handler: this is called from the primary exception dispatcher
+ */
+static void BSP_irq_handle_at_opbintc(void)
+{
+ uint32_t ipr;
+
+ /* Get pending interrupts */
+ ipr = get_ipr();
+
+ if (ipr != 0) {
+ /* Acknowledge all pending interrupts now and service them afterwards */
+ set_iar(ipr);
+
+ do {
+ /* Get highest priority pending interrupt */
+ uint32_t i = 31 - ppc_count_leading_zeros(ipr);
+
+ ipr &= ~(1U << i);
+
+ bsp_interrupt_handler_dispatch(i+BSP_OPBINTC_IRQ_LOWEST_OFFSET);
+ } while (ipr != 0);
+ }
+}
+
+/*
+ * activate the interrupt controller
+ */
+static void opb_intc_init(void)
+{
+ uint32_t i, mask = 0;
+
+ /* mask off all interrupts */
+ set_ier(0x0);
+
+ for (i = 0; i < OPB_INTC_IRQ_MAX; i++) {
+ mask |= (1 << i);
+ }
+
+ /* make sure interupt status register is clear before we enable the interrupt controller */
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_ISR)) = 0;
+
+ /* acknowledge all interrupt sources */
+ set_iar(mask);
+
+ /* Turn on normal hardware operation of interrupt controller */
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_MER)) =
+ (OPB_INTC_MER_HIE);
+
+ /* Enable master interrupt switch for the interrupt controller */
+ *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_MER)) =
+ (OPB_INTC_MER_HIE | OPB_INTC_MER_ME);
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if (BSP_IS_OPBINTC_IRQ(vector)) {
+ BSP_irq_enable_at_opbintc(vector);
+ }
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+ bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
+
+ if (BSP_IS_OPBINTC_IRQ(vector)) {
+ BSP_irq_disable_at_opbintc(vector);
+ }
+}
+
+static int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned int excNum)
+{
+ BSP_irq_handle_at_opbintc();
+
+ return 0;
+}
+
+rtems_status_code bsp_interrupt_facility_initialize(void)
+{
+ opb_intc_init();
+
+ ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/powerpc/virtex4/irq/irq_init.c b/bsps/powerpc/virtex4/irq/irq_init.c
new file mode 100644
index 0000000000..5feafaf4b6
--- /dev/null
+++ b/bsps/powerpc/virtex4/irq/irq_init.c
@@ -0,0 +1,326 @@
+/*===============================================================*\
+| Project: RTEMS virtex BSP |
++-----------------------------------------------------------------+
+| Partially based on the code references which are named below. |
+| Adaptions, modifications, enhancements and any recent parts of |
+| the code are: |
+| Copyright (c) 2007 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.org/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the irq controller handler |
+\*===============================================================*/
+#include <libcpu/spr.h>
+#include <bsp/irq.h>
+#include <bsp.h>
+#include <rtems/bspIo.h>
+#include <rtems/powerpc/powerpc.h>
+#include <bsp/vectors.h>
+
+static rtems_irq_connect_data rtemsIrqTbl[BSP_IRQ_NUMBER];
+rtems_irq_connect_data *BSP_rtems_irq_tbl;
+rtems_irq_global_settings* BSP_rtems_irq_config;
+
+/***********************************************************
+ * dummy functions for on/off/isOn calls
+ * these functions just do nothing fulfill the semantic
+ * requirements to enable/disable a certain interrupt or exception
+ */
+static void BSP_irq_nop_func(const rtems_irq_connect_data *unused)
+{
+ /*
+ * nothing to do
+ */
+}
+
+static void BSP_irq_nop_hdl(void *hdl)
+{
+ /*
+ * nothing to do
+ */
+}
+
+static int BSP_irq_isOn_func(const rtems_irq_connect_data *unused)
+{
+ /*
+ * nothing to do
+ */
+ return 0;
+}
+
+/***********************************************************
+ * interrupt handler and its enable/disable functions
+ ***********************************************************/
+
+/***********************************************************
+ * functions to enable/disable/query external/critical interrupts
+ */
+void BSP_irqexc_on_fnc(const rtems_irq_connect_data *conn_data)
+{
+ uint32_t msr_value;
+ /*
+ * get current MSR value
+ */
+ _CPU_MSR_GET(msr_value);
+
+ msr_value |= PPC_MSR_EE;
+ _CPU_MSR_SET(msr_value);
+}
+
+void BSP_irqexc_off_fnc(const rtems_irq_connect_data *unused)
+{
+ uint32_t msr_value;
+ /*
+ * get current MSR value
+ */
+ _CPU_MSR_GET(msr_value);
+
+ msr_value &= ~PPC_MSR_EE;
+ _CPU_MSR_SET(msr_value);
+}
+
+/***********************************************************
+ * High level IRQ handler called from shared_raw_irq_code_entry
+ */
+static int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum)
+{
+ /*
+ * Handle interrupt
+ */
+ switch(excNum) {
+ case ASM_EXT_VECTOR:
+ BSP_rtems_irq_tbl[BSP_EXT].hdl(BSP_rtems_irq_tbl[BSP_EXT].handle);
+ break;
+ case ASM_BOOKE_DEC_VECTOR:
+ BSP_rtems_irq_tbl[BSP_PIT].hdl(BSP_rtems_irq_tbl[BSP_PIT].handle);
+ break;
+#if 0 /* Critical interrupts not yet supported */
+ case ASM_BOOKE_CRIT_VECTOR:
+ BSP_rtems_irq_tbl[BSP_CRIT].hdl(BSP_rtems_irq_tbl[BSP_CRIT].handle);
+ break;
+#endif
+ }
+
+ return 0;
+}
+
+/***********************************************************
+ * functions to set/get/remove interrupt handlers
+ ***********************************************************/
+int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
+{
+ rtems_interrupt_level level;
+
+ /*
+ * check for valid irq name
+ * if invalid, print error and return 0
+ */
+ if (!BSP_IS_VALID_IRQ(irq->name)) {
+ printk("Invalid interrupt vector %d\n",irq->name);
+ return 0;
+ }
+
+ /*
+ * disable interrupts
+ */
+ rtems_interrupt_disable(level);
+
+ /*
+ * check, that default handler is installed now
+ */
+ if (rtemsIrqTbl[irq->name].hdl != BSP_rtems_irq_config->defaultEntry.hdl) {
+ rtems_interrupt_enable(level);
+ printk("IRQ vector %d already connected\n",irq->name);
+ return 0;
+ }
+
+ /*
+ * store new handler data
+ */
+ rtemsIrqTbl[irq->name] = *irq;
+
+ /*
+ * call "on" function to enable interrupt at device
+ */
+ irq->on(irq);
+
+ /*
+ * reenable interrupts
+ */
+ rtems_interrupt_enable(level);
+
+ return 1;
+}
+
+int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
+{
+ rtems_interrupt_level level;
+
+ /*
+ * check for valid IRQ name
+ */
+ if (!BSP_IS_VALID_IRQ(irq->name)) {
+ return 0;
+ }
+ rtems_interrupt_disable(level);
+
+ /*
+ * return current IRQ entry
+ */
+ *irq = rtemsIrqTbl[irq->name];
+ rtems_interrupt_enable(level);
+ return 1;
+}
+
+int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
+{
+ rtems_interrupt_level level;
+
+ /*
+ * check for valid IRQ name
+ */
+ if (!BSP_IS_VALID_IRQ(irq->name)) {
+ return 0;
+ }
+ rtems_interrupt_disable(level);
+
+ /*
+ * check, that specified handler is really connected now
+ */
+ if (rtemsIrqTbl[irq->name].hdl != irq->hdl) {
+ rtems_interrupt_enable(level);
+ return 0;
+ }
+
+ /*
+ * disable interrupt at source
+ */
+ irq->off(irq);
+
+ /*
+ * restore default interrupt handler
+ */
+ rtemsIrqTbl[irq->name] = BSP_rtems_irq_config->defaultEntry;
+
+ /*
+ * reenable interrupts
+ */
+ rtems_interrupt_enable(level);
+
+ return 1;
+}
+
+/***********************************************************
+ * functions to set/get the basic interrupt management setup
+ ***********************************************************/
+/*
+ * (Re) get info on current RTEMS interrupt management.
+ */
+int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** ret_ptr)
+{
+ *ret_ptr = BSP_rtems_irq_config;
+ return 0;
+}
+
+
+/*
+ * set management stuff
+ */
+int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
+{
+ int i;
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+
+ /*
+ * store given configuration
+ */
+ BSP_rtems_irq_config = config;
+ BSP_rtems_irq_tbl = BSP_rtems_irq_config->irqHdlTbl;
+
+ /*
+ * store any irq-like processor exceptions
+ */
+ for (i = BSP_PROCESSOR_IRQ_LOWEST_OFFSET;
+ i < BSP_PROCESSOR_IRQ_MAX_OFFSET;
+ i++) {
+ if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) {
+ if (BSP_rtems_irq_tbl[i].on != NULL) {
+ BSP_rtems_irq_tbl[i].on
+ (&(BSP_rtems_irq_tbl[i]));
+ }
+ }
+ else {
+ if (BSP_rtems_irq_tbl[i].off != NULL) {
+ BSP_rtems_irq_tbl[i].off
+ (&(BSP_rtems_irq_tbl[i]));
+ }
+ }
+ }
+ rtems_interrupt_enable(level);
+ return 1;
+}
+
+/*
+ * dummy for an empty IRQ handler entry
+ */
+static rtems_irq_connect_data emptyIrq = {
+ 0, /* IRQ Name */
+ BSP_irq_nop_hdl, /* handler function */
+ NULL, /* handle passed to handler */
+ BSP_irq_nop_func, /* on function */
+ BSP_irq_nop_func, /* off function */
+ BSP_irq_isOn_func /* isOn function */
+};
+
+static rtems_irq_global_settings initialConfig = {
+ BSP_IRQ_NUMBER, /* IRQ Number */
+ { 0, /* IRQ Name */
+ BSP_irq_nop_hdl, /* handler function */
+ NULL, /* handle passed to handler */
+ BSP_irq_nop_func, /* on function */
+ BSP_irq_nop_func, /* off function */
+ BSP_irq_isOn_func /* isOn function */
+ }, /* emptyIrq */
+ rtemsIrqTbl, /* irqHdlTbl */
+ 0, /* irqBase */
+ NULL /* irqPrioTbl */
+};
+
+void BSP_rtems_irq_mngt_init(unsigned cpuId)
+{
+ int i;
+
+ /*
+ * connect all exception vectors needed
+ */
+ ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler);
+ ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_irq_handler);
+
+ /*
+ * setup interrupt handlers table
+ */
+ for (i = 0;
+ i < BSP_IRQ_NUMBER;
+ i++) {
+ rtemsIrqTbl[i] = emptyIrq;
+ rtemsIrqTbl[i].name = i;
+ }
+
+ /*
+ * initialize interrupt management
+ */
+ if (!BSP_rtems_irq_mngt_set(&initialConfig)) {
+ rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
+ }
+}
diff --git a/bsps/powerpc/virtex5/irq/irq_init.c b/bsps/powerpc/virtex5/irq/irq_init.c
new file mode 100644
index 0000000000..1fea9214aa
--- /dev/null
+++ b/bsps/powerpc/virtex5/irq/irq_init.c
@@ -0,0 +1,343 @@
+/*===============================================================*\
+| Project: RTEMS virtex BSP |
++-----------------------------------------------------------------+
+| Partially based on the code references which are named below. |
+| Adaptions, modifications, enhancements and any recent parts of |
+| the code are: |
+| Copyright (c) 2007 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| |
+| http://www.rtems.org/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the irq controller handler |
+\*===============================================================*/
+#include <libcpu/spr.h>
+#include <bsp/irq.h>
+#include <bsp.h>
+#include <rtems/bspIo.h>
+#include <rtems/powerpc/powerpc.h>
+#include <bsp/vectors.h>
+
+static rtems_irq_connect_data rtemsIrqTbl[BSP_IRQ_NUMBER];
+rtems_irq_connect_data *BSP_rtems_irq_tbl;
+rtems_irq_global_settings* BSP_rtems_irq_config;
+
+/***********************************************************
+ * dummy functions for on/off/isOn calls
+ * these functions just do nothing fulfill the semantic
+ * requirements to enable/disable a certain interrupt or exception
+ */
+static void BSP_irq_nop_func(const rtems_irq_connect_data *unused)
+{
+ /*
+ * nothing to do
+ */
+}
+
+static void BSP_irq_nop_hdl(void *hdl)
+{
+ /*
+ * nothing to do
+ */
+}
+
+static int BSP_irq_isOn_func(const rtems_irq_connect_data *unused)
+{
+ /*
+ * nothing to do
+ */
+ return 0;
+}
+
+/***********************************************************
+ * interrupt handler and its enable/disable functions
+ ***********************************************************/
+
+/***********************************************************
+ * functions to enable/disable/query external/critical interrupts
+ */
+void BSP_irqexc_on_fnc(const rtems_irq_connect_data *conn_data)
+{
+ uint32_t msr_value;
+ /*
+ * get current MSR value
+ */
+ _CPU_MSR_GET(msr_value);
+
+ msr_value |= PPC_MSR_EE;
+ _CPU_MSR_SET(msr_value);
+}
+
+void BSP_irqexc_off_fnc(const rtems_irq_connect_data *unused)
+{
+ uint32_t msr_value;
+ /*
+ * get current MSR value
+ */
+ _CPU_MSR_GET(msr_value);
+
+ msr_value &= ~PPC_MSR_EE;
+ _CPU_MSR_SET(msr_value);
+}
+
+SPR_RW(BOOKE_TSR)
+
+static int C_dispatch_dec_handler (BSP_Exception_frame *frame, unsigned int excNum)
+{
+ /* Acknowledge the interrupt */
+ _write_BOOKE_TSR( BOOKE_TSR_DIS );
+
+ /* Handle the interrupt */
+ BSP_rtems_irq_tbl[BSP_DEC].hdl(BSP_rtems_irq_tbl[BSP_DEC].handle);
+
+ return 0;
+}
+
+
+/***********************************************************
+ * High level IRQ handler called from shared_raw_irq_code_entry
+ */
+static int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum)
+{
+ /*
+ * Handle interrupt
+ */
+ switch(excNum) {
+ case ASM_EXT_VECTOR:
+ BSP_rtems_irq_tbl[BSP_EXT].hdl(BSP_rtems_irq_tbl[BSP_EXT].handle);
+ break;
+#if 0 /* Dealt with by C_dispatch_dec_handler(), above */
+ case ASM_BOOKE_DEC_VECTOR:
+ _write_BOOKE_TSR( BOOKE_TSR_DIS );
+ BSP_rtems_irq_tbl[BSP_DEC].hdl(BSP_rtems_irq_tbl[BSP_DEC].handle);
+ break;
+#endif
+#if 0 /* Critical interrupts not yet supported */
+ case ASM_BOOKE_CRIT_VECTOR:
+ BSP_rtems_irq_tbl[BSP_CRIT].hdl(BSP_rtems_irq_tbl[BSP_CRIT].handle);
+ break;
+#endif
+ }
+
+ return 0;
+}
+
+/***********************************************************
+ * functions to set/get/remove interrupt handlers
+ ***********************************************************/
+int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
+{
+ rtems_interrupt_level level;
+
+ /*
+ * check for valid irq name
+ * if invalid, print error and return 0
+ */
+ if (!BSP_IS_VALID_IRQ(irq->name)) {
+ printk("Invalid interrupt vector %d\n",irq->name);
+ return 0;
+ }
+
+ /*
+ * disable interrupts
+ */
+ rtems_interrupt_disable(level);
+
+ /*
+ * check, that default handler is installed now
+ */
+ if (rtemsIrqTbl[irq->name].hdl != BSP_rtems_irq_config->defaultEntry.hdl) {
+ rtems_interrupt_enable(level);
+ printk("IRQ vector %d already connected\n",irq->name);
+ return 0;
+ }
+
+ /*
+ * store new handler data
+ */
+ rtemsIrqTbl[irq->name] = *irq;
+
+ /*
+ * call "on" function to enable interrupt at device
+ */
+ irq->on(irq);
+
+ /*
+ * reenable interrupts
+ */
+ rtems_interrupt_enable(level);
+
+ return 1;
+}
+
+int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
+{
+ rtems_interrupt_level level;
+
+ /*
+ * check for valid IRQ name
+ */
+ if (!BSP_IS_VALID_IRQ(irq->name)) {
+ return 0;
+ }
+ rtems_interrupt_disable(level);
+
+ /*
+ * return current IRQ entry
+ */
+ *irq = rtemsIrqTbl[irq->name];
+ rtems_interrupt_enable(level);
+ return 1;
+}
+
+int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
+{
+ rtems_interrupt_level level;
+
+ /*
+ * check for valid IRQ name
+ */
+ if (!BSP_IS_VALID_IRQ(irq->name)) {
+ return 0;
+ }
+ rtems_interrupt_disable(level);
+
+ /*
+ * check, that specified handler is really connected now
+ */
+ if (rtemsIrqTbl[irq->name].hdl != irq->hdl) {
+ rtems_interrupt_enable(level);
+ return 0;
+ }
+
+ /*
+ * disable interrupt at source
+ */
+ irq->off(irq);
+
+ /*
+ * restore default interrupt handler
+ */
+ rtemsIrqTbl[irq->name] = BSP_rtems_irq_config->defaultEntry;
+
+ /*
+ * reenable interrupts
+ */
+ rtems_interrupt_enable(level);
+
+ return 1;
+}
+
+/***********************************************************
+ * functions to set/get the basic interrupt management setup
+ ***********************************************************/
+/*
+ * (Re) get info on current RTEMS interrupt management.
+ */
+int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** ret_ptr)
+{
+ *ret_ptr = BSP_rtems_irq_config;
+ return 0;
+}
+
+
+/*
+ * set management stuff
+ */
+int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
+{
+ int i;
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+
+ /*
+ * store given configuration
+ */
+ BSP_rtems_irq_config = config;
+ BSP_rtems_irq_tbl = BSP_rtems_irq_config->irqHdlTbl;
+
+ /*
+ * store any irq-like processor exceptions
+ */
+ for (i = BSP_PROCESSOR_IRQ_LOWEST_OFFSET;
+ i < BSP_PROCESSOR_IRQ_MAX_OFFSET;
+ i++) {
+ if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) {
+ if (BSP_rtems_irq_tbl[i].on != NULL) {
+ BSP_rtems_irq_tbl[i].on
+ (&(BSP_rtems_irq_tbl[i]));
+ }
+ }
+ else {
+ if (BSP_rtems_irq_tbl[i].off != NULL) {
+ BSP_rtems_irq_tbl[i].off
+ (&(BSP_rtems_irq_tbl[i]));
+ }
+ }
+ }
+ rtems_interrupt_enable(level);
+ return 1;
+}
+
+/*
+ * dummy for an empty IRQ handler entry
+ */
+static rtems_irq_connect_data emptyIrq = {
+ 0, /* IRQ Name */
+ BSP_irq_nop_hdl, /* handler function */
+ NULL, /* handle passed to handler */
+ BSP_irq_nop_func, /* on function */
+ BSP_irq_nop_func, /* off function */
+ BSP_irq_isOn_func /* isOn function */
+};
+
+static rtems_irq_global_settings initialConfig = {
+ BSP_IRQ_NUMBER, /* IRQ number */
+ { 0, /* IRQ Name */
+ BSP_irq_nop_hdl, /* handler function */
+ NULL, /* handle passed to handler */
+ BSP_irq_nop_func, /* on function */
+ BSP_irq_nop_func, /* off function */
+ BSP_irq_isOn_func /* isOn function */
+ }, /* emptyIrq */
+ rtemsIrqTbl, /* irqHdlTbl */
+ 0, /* irqBase */
+ NULL /* irqPrioTbl */
+};
+
+void BSP_rtems_irq_mngt_init(unsigned cpuId)
+{
+ int i;
+
+ /*
+ * connect all exception vectors needed
+ */
+ ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler);
+ ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_dec_handler);
+
+ /*
+ * setup interrupt handlers table
+ */
+ for (i = 0;
+ i < BSP_IRQ_NUMBER;
+ i++) {
+ rtemsIrqTbl[i] = emptyIrq;
+ rtemsIrqTbl[i].name = i;
+ }
+
+ /*
+ * initialize interrupt management
+ */
+ if (!BSP_rtems_irq_mngt_set(&initialConfig)) {
+ rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
+ }
+}
diff --git a/bsps/riscv/riscv_generic/irq/irq.c b/bsps/riscv/riscv_generic/irq/irq.c
new file mode 100644
index 0000000000..8090dcea98
--- /dev/null
+++ b/bsps/riscv/riscv_generic/irq/irq.c
@@ -0,0 +1,60 @@
+/**
+ * @file
+ *
+ * @ingroup riscv_interrupt
+ *
+ * @brief Interrupt support.
+ */
+
+/*
+ * RISCV CPU Dependent Source
+ *
+ * Copyright (c) 2015 University of York.
+ * Hesham Almatary <hesham@alumni.york.ac.uk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+
+/* Almost all of the jobs that the following functions should
+ * do are implemented in cpukit
+ */
+
+void bsp_interrupt_handler_default(rtems_vector_number vector)
+{
+ printk("spurious interrupt: %u\n", vector);
+}
+
+rtems_status_code bsp_interrupt_facility_initialize()
+{
+ return RTEMS_NOT_IMPLEMENTED;
+}
+
+void bsp_interrupt_vector_enable(rtems_vector_number vector)
+{
+}
+
+void bsp_interrupt_vector_disable(rtems_vector_number vector)
+{
+}