summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/mbx8xx/irq
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2001-04-06 15:52:03 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2001-04-06 15:52:03 +0000
commit35bb69b1cd7d5a54f5727195cc7b5f06a7cb2344 (patch)
treed7435f5a462d5e266b113b29ee4ad4ed9e21f4af /c/src/lib/libbsp/powerpc/mbx8xx/irq
parent2001-03-26 Zoltan Kocsi <zoltan@bendor.com.au> (diff)
downloadrtems-35bb69b1cd7d5a54f5727195cc7b5f06a7cb2344.tar.bz2
2001-03-30 Eric Valette <valette@crf.canon.fr>
* clock/.cvsignore, clock/Makefile.am, clock/p_clock.c, include/8xx_immap.h, include/commproc.h, include/mbx.h, irq/.cvsignore, irq/Makefile.am, irq/irq.c, irq/irq.h, irq/irq_asm.S, irq/irq_init.c, vectors/.cvsignore, vectors/Makefile.am, vectors/vectors.S, vectors/vectors.h, vectors/vectors_init.c: New files. * Makefile.am, configure.in, console/console.c, include/Makefile.am, network/network.c, startup/Makefile.am, startup/bspstart.c, startup/imbx8xx.c, startup/linkcmds, startup/mmutlbtab.c, startup/start.S, wrapup/Makefile.am: The modifications to this BSP reflect the conversion of the mpc8xx CPU to the "new exception processing model."
Diffstat (limited to 'c/src/lib/libbsp/powerpc/mbx8xx/irq')
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/irq/.cvsignore2
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/irq/Makefile.am46
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.c506
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.h331
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_asm.S329
-rw-r--r--c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_init.c162
6 files changed, 1376 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/irq/.cvsignore b/c/src/lib/libbsp/powerpc/mbx8xx/irq/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/irq/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/irq/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/irq/Makefile.am
new file mode 100644
index 0000000000..4b5bc87fe4
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/irq/Makefile.am
@@ -0,0 +1,46 @@
+##
+## $Id$
+##
+
+AUTOMAKE_OPTIONS = foreign 1.4
+
+C_FILES = irq.c irq_init.c
+C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
+
+H_FILES = irq.h
+
+S_FILES = irq_asm.S
+S_O_FILES = $(S_FILES:%.S=$(ARCH)/%.o)
+
+OBJS = $(C_O_FILES) $(S_O_FILES)
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../../../../../../automake/compile.am
+include $(top_srcdir)/../../../../../../automake/lib.am
+
+SORDID_HACK:
+ rm -f $(PROJECT_INCLUDE)/bsp/irq.h
+
+$(PROJECT_INCLUDE)/bsp:
+ $(mkinstalldirs) $@
+
+$(PROJECT_INCLUDE)/bsp/%.h: %.h
+ $(INSTALL_DATA) $< $@
+
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp \
+ $(H_FILES:%.h=$(PROJECT_INCLUDE)/bsp/%.h)
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+$(PGM): $(OBJS)
+ $(make-rel)
+
+# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
+
+all-local: SORDID_HACK $(PREINSTALL_FILES) $(ARCH) $(OBJS) $(PGM)
+
+EXTRA_DIST = irq.c irq.h irq_asm.S irq_init.c
+
+include $(top_srcdir)/../../../../../../automake/local.am
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.c b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.c
new file mode 100644
index 0000000000..7e9e003c12
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.c
@@ -0,0 +1,506 @@
+/*
+ *
+ * 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 found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/apiext.h>
+#include <libcpu/raw_exception.h>
+#include <bsp/vectors.h>
+#include <libcpu/cpu.h>
+#include <bsp/8xx_immap.h>
+#include <bsp/mbx.h>
+#include <bsp/commproc.h>
+
+/*
+ * default handler connected on each irq after bsp initialization
+ */
+static rtems_irq_connect_data default_rtems_entry;
+
+/*
+ * location used to store initial tables used for interrupt
+ * management.
+ */
+static rtems_irq_global_settings* internal_config;
+static rtems_irq_connect_data* rtems_hdl_tbl;
+
+/*
+ * Check if symbolic IRQ name is an SIU IRQ
+ */
+static inline int is_siu_irq(const rtems_irq_symbolic_name irqLine)
+{
+ return (((int) irqLine <= BSP_SIU_IRQ_MAX_OFFSET) &
+ ((int) irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET)
+ );
+}
+
+/*
+ * Check if symbolic IRQ name is an CPM IRQ
+ */
+static inline int is_cpm_irq(const rtems_irq_symbolic_name irqLine)
+{
+ return (((int) irqLine <= BSP_CPM_IRQ_MAX_OFFSET) &
+ ((int) irqLine >= BSP_CPM_IRQ_LOWEST_OFFSET)
+ );
+}
+
+/*
+ * Check if symbolic IRQ name is a Processor IRQ
+ */
+static inline int is_processor_irq(const rtems_irq_symbolic_name irqLine)
+{
+ return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) &
+ ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)
+ );
+}
+
+
+/*
+ * masks used to mask off the interrupts. For exmaple, for ILVL2, the
+ * mask is used to mask off interrupts ILVL2, IRQ3, ILVL3, ... IRQ7
+ * and ILVL7.
+ *
+ */
+const static unsigned int SIU_IvectMask[BSP_SIU_IRQ_NUMBER] =
+{
+ /* IRQ0 ILVL0 IRQ1 ILVL1 */
+ 0x00000000, 0x80000000, 0xC0000000, 0xE0000000,
+
+ /* IRQ2 ILVL2 IRQ3 ILVL3 */
+ 0xF0000000, 0xF8000000, 0xFC000000, 0xFE000000,
+
+ /* IRQ4 ILVL4 IRQ5 ILVL5 */
+ 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,
+
+ /* IRQ6 ILVL6 IRQ7 ILVL7 */
+ 0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000
+};
+
+/*
+ * ------------------------ 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 ()
+{
+ /*
+ * In theory this is feasible. No time to code it yet. See i386/shared/irq.c
+ * for an example based on 8259 controller mask. The actual masks defined
+ * correspond to the priorities defined for the SIU in irq_init.c.
+ */
+}
+
+/*
+ * This function check that the value given for the irq line
+ * is valid.
+ */
+
+static int isValidInterrupt(int irq)
+{
+ if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET) || (irq == BSP_CPM_INTERRUPT) )
+ return 0;
+ return 1;
+}
+
+int BSP_irq_enable_at_cpm(const rtems_irq_symbolic_name irqLine)
+{
+ int cpm_irq_index;
+
+ if (!is_cpm_irq(irqLine))
+ return 1;
+
+ cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << cpm_irq_index);
+
+ return 0;
+}
+
+int BSP_irq_disable_at_cpm(const rtems_irq_symbolic_name irqLine)
+{
+ int cpm_irq_index;
+
+ if (!is_cpm_irq(irqLine))
+ return 1;
+
+ cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << cpm_irq_index);
+
+ return 0;
+}
+
+int BSP_irq_enabled_at_cpm(const rtems_irq_symbolic_name irqLine)
+{
+ int cpm_irq_index;
+
+ if (!is_cpm_irq(irqLine))
+ return 0;
+
+ cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
+ return (((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr & (1 << cpm_irq_index));
+}
+
+int BSP_irq_enable_at_siu(const rtems_irq_symbolic_name irqLine)
+{
+ int siu_irq_index;
+
+ if (!is_siu_irq(irqLine))
+ return 1;
+
+ siu_irq_index = ((int) (irqLine) - BSP_SIU_IRQ_LOWEST_OFFSET);
+ ppc_cached_irq_mask |= (1 << (31-siu_irq_index));
+ ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
+
+ return 0;
+}
+
+int BSP_irq_disable_at_siu(const rtems_irq_symbolic_name irqLine)
+{
+ int siu_irq_index;
+
+ if (!is_siu_irq(irqLine))
+ return 1;
+
+ siu_irq_index = ((int) (irqLine) - BSP_SIU_IRQ_LOWEST_OFFSET);
+ ppc_cached_irq_mask &= ~(1 << (31-siu_irq_index));
+ ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
+
+ return 0;
+}
+
+int BSP_irq_enabled_at_siu (const rtems_irq_symbolic_name irqLine)
+{
+ int siu_irq_index;
+
+ if (!is_siu_irq(irqLine))
+ return 0;
+
+ siu_irq_index = ((int) (irqLine) - BSP_SIU_IRQ_LOWEST_OFFSET);
+ return ppc_cached_irq_mask & (1 << (31-siu_irq_index));
+}
+
+/*
+ * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
+ */
+
+int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
+{
+ unsigned int level;
+
+ if (!isValidInterrupt(irq->name)) {
+ 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 (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
+ return 0;
+ }
+
+ _CPU_ISR_Disable(level);
+
+ /*
+ * store the data provided by user
+ */
+ rtems_hdl_tbl[irq->name] = *irq;
+
+ if (is_cpm_irq(irq->name)) {
+ /*
+ * Enable interrupt at PIC level
+ */
+ BSP_irq_enable_at_cpm (irq->name);
+ }
+
+ if (is_siu_irq(irq->name)) {
+ /*
+ * Enable interrupt at SIU level
+ */
+ BSP_irq_enable_at_siu (irq->name);
+ }
+
+ if (is_processor_irq(irq->name)) {
+ /*
+ * Should Enable exception at processor level but not needed. Will restore
+ * EE flags at the end of the routine anyway.
+ */
+ }
+ /*
+ * Enable interrupt on device
+ */
+ irq->on(irq);
+
+ _CPU_ISR_Enable(level);
+
+ return 1;
+}
+
+
+int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
+{
+ if (!isValidInterrupt(irq->name)) {
+ return 0;
+ }
+ *irq = rtems_hdl_tbl[irq->name];
+ return 1;
+}
+
+int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
+{
+ unsigned int level;
+
+ if (!isValidInterrupt(irq->name)) {
+ 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 (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
+ return 0;
+ }
+ _CPU_ISR_Disable(level);
+
+ if (is_cpm_irq(irq->name)) {
+ /*
+ * disable interrupt at PIC level
+ */
+ BSP_irq_disable_at_cpm (irq->name);
+ }
+ if (is_siu_irq(irq->name)) {
+ /*
+ * disable interrupt at OPENPIC level
+ */
+ BSP_irq_disable_at_siu (irq->name);
+ }
+ if (is_processor_irq(irq->name)) {
+ /*
+ * disable exception at processor level
+ */
+ }
+
+ /*
+ * Disable interrupt on device
+ */
+ irq->off(irq);
+
+ /*
+ * restore the default irq value
+ */
+ rtems_hdl_tbl[irq->name] = default_rtems_entry;
+
+ _CPU_ISR_Enable(level);
+
+ return 1;
+}
+
+/*
+ * ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
+ */
+
+int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
+{
+ int i;
+ unsigned int level;
+ /*
+ * Store various code accelerators
+ */
+ internal_config = config;
+ default_rtems_entry = config->defaultEntry;
+ rtems_hdl_tbl = config->irqHdlTbl;
+
+ _CPU_ISR_Disable(level);
+ /*
+ * start with CPM IRQ
+ */
+ for (i=BSP_CPM_IRQ_LOWEST_OFFSET; i < BSP_CPM_IRQ_LOWEST_OFFSET + BSP_CPM_IRQ_NUMBER ; i++) {
+ if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
+ BSP_irq_enable_at_cpm (i);
+ rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
+ }
+ else {
+ rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
+ BSP_irq_disable_at_cpm (i);
+ }
+ }
+
+ /*
+ * continue with PCI IRQ
+ */
+ /*
+ * set up internal tables used by rtems interrupt prologue
+ */
+ compute_SIU_IvectMask_from_prio ();
+
+ for (i=BSP_SIU_IRQ_LOWEST_OFFSET; i < BSP_SIU_IRQ_LOWEST_OFFSET + BSP_SIU_IRQ_NUMBER ; i++) {
+ if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
+ BSP_irq_enable_at_siu (i);
+ rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
+ }
+ else {
+ rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
+ BSP_irq_disable_at_siu (i);
+ }
+ }
+ /*
+ * Must enable CPM interrupt on SIU. CPM on SIU Interrupt level has already been
+ * set up in BSP_CPM_irq_init.
+ */
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
+ BSP_irq_enable_at_siu (BSP_CPM_INTERRUPT);
+ /*
+ * finish with Processor exceptions handled like IRQ
+ */
+ for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER; i++) {
+ if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
+ rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
+ }
+ else {
+ rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
+ }
+ }
+ _CPU_ISR_Enable(level);
+ return 1;
+}
+
+int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
+{
+ *config = internal_config;
+ return 0;
+}
+
+#ifdef DISPATCH_HANDLER_STAT
+volatile unsigned int maxLoop = 0;
+#endif
+
+/*
+ * High level IRQ handler called from shared_raw_irq_code_entry
+ */
+void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
+{
+ register unsigned int irq;
+ register unsigned cpmIntr; /* boolean */
+ register unsigned oldMask; /* old siu pic masks */
+ register unsigned msr;
+ register unsigned new_msr;
+ unsigned loopCounter;
+
+ /*
+ * Handle decrementer interrupt
+ */
+ if (excNum == ASM_DEC_VECTOR) {
+ _CPU_MSR_GET(msr);
+ new_msr = msr | MSR_EE;
+ _CPU_MSR_SET(new_msr);
+
+ rtems_hdl_tbl[BSP_DECREMENTER].hdl();
+
+ _CPU_MSR_SET(msr);
+ return;
+ }
+ /*
+ * Handle external interrupt generated by SIU on PPC core
+ */
+#ifdef DISPATCH_HANDLER_STAT
+ loopCounter = 0;
+#endif
+ while (1) {
+ if ((ppc_cached_irq_mask & ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend) == 0) {
+#ifdef DISPATCH_HANDLER_STAT
+ if (loopCounter > maxLoop) maxLoop = loopCounter;
+#endif
+ break;
+ }
+ irq = (((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec >> 26);
+ cpmIntr = (irq == BSP_CPM_INTERRUPT);
+ /*
+ * Disable the interrupt of the same and lower priority.
+ */
+ oldMask = ppc_cached_irq_mask;
+ ppc_cached_irq_mask = oldMask & SIU_IvectMask[irq];
+ ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
+ /*
+ * Acknowledge current interrupt. This has no effect on internal level interrupt.
+ */
+ ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = (1 << (31 - irq));
+
+ if (cpmIntr) {
+ /*
+ * We will reenable the SIU CPM interrupt to allow nesting of CPM interrupt.
+ * We must before acknowledege the current irq at CPM level to avoid trigerring
+ * the interrupt again.
+ */
+ /*
+ * Acknowledge and get the vector.
+ */
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1;
+ irq = (((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr >> 11);
+ /*
+ * transform IRQ to normalized irq table index.
+ */
+ irq += BSP_CPM_IRQ_LOWEST_OFFSET;
+ /*
+ * Unmask CPM interrupt at SIU level
+ */
+ ppc_cached_irq_mask |= (1 << (31 - BSP_CPM_INTERRUPT));
+ ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
+ }
+ _CPU_MSR_GET(msr);
+ new_msr = msr | MSR_EE;
+ _CPU_MSR_SET(new_msr);
+
+ rtems_hdl_tbl[irq].hdl();
+
+ _CPU_MSR_SET(msr);
+
+ if (cpmIntr) {
+ irq -= BSP_CPM_IRQ_LOWEST_OFFSET;
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr = (1 << irq);
+ }
+ ppc_cached_irq_mask |= (oldMask & ~(SIU_IvectMask[irq]));
+ ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
+#ifdef DISPATCH_HANDLER_STAT
+ ++ loopCounter;
+#endif
+ }
+}
+
+
+
+void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
+{
+ /*
+ * Process pending signals that have not already been
+ * processed by _Thread_Displatch. This happens quite
+ * unfrequently : the ISR must have posted an action
+ * to the current running thread.
+ */
+ if ( _Thread_Do_post_task_switch_extension ||
+ _Thread_Executing->do_post_task_switch_extension ) {
+ _Thread_Executing->do_post_task_switch_extension = FALSE;
+ _API_extensions_Run_postswitch();
+ }
+ /*
+ * I plan to process other thread related events here.
+ * This will include DEBUG session requested from keyboard...
+ */
+}
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.h b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.h
new file mode 100644
index 0000000000..2f0b46179f
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.h
@@ -0,0 +1,331 @@
+/* irq.h
+ *
+ * This include file describe the data structure and the functions implemented
+ * by rtems to write interrupt handlers.
+ *
+ * CopyRight (C) 1999 valette@crf.canon.fr
+ *
+ * This code is heavilly inspired by the public specification of STREAM V2
+ * that can be found at :
+ *
+ * <http://www.chorus.com/Documentation/index.html> by following
+ * the STREAM API Specification Document link.
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#ifndef LIBBSP_POWERPC_MBX8XX_IRQ_IRQ_H
+#define LIBBSP_POWERPC_MBX8XX_IRQ_IRQ_H
+
+
+#define BSP_ASM_IRQ_VECTOR_BASE 0x0
+
+#ifndef ASM
+
+extern volatile unsigned int ppc_cached_irq_mask;
+
+/*
+ * Symblolic IRQ names and related definitions.
+ */
+
+typedef enum {
+ /* Base vector for our SIU IRQ handlers. */
+ BSP_SIU_VECTOR_BASE = BSP_ASM_IRQ_VECTOR_BASE,
+ /*
+ * SIU IRQ handler related definitions
+ */
+ BSP_SIU_IRQ_NUMBER = 16, /* 16 reserved but in the future... */
+ BSP_SIU_IRQ_LOWEST_OFFSET = 0,
+ BSP_SIU_IRQ_MAX_OFFSET = BSP_SIU_IRQ_LOWEST_OFFSET + BSP_SIU_IRQ_NUMBER - 1,
+ /*
+ * CPM IRQ handlers related definitions
+ * CAUTION : BSP_CPM_IRQ_LOWEST_OFFSET should be equal to OPENPIC_VEC_SOURCE
+ */
+ BSP_CPM_IRQ_NUMBER = 32,
+ BSP_CPM_IRQ_LOWEST_OFFSET = BSP_SIU_IRQ_NUMBER + BSP_SIU_VECTOR_BASE,
+ BSP_CPM_IRQ_MAX_OFFSET = BSP_CPM_IRQ_LOWEST_OFFSET + BSP_CPM_IRQ_NUMBER - 1,
+ /*
+ * PowerPc exceptions handled as interrupt where a rtems managed interrupt
+ * handler might be connected
+ */
+ BSP_PROCESSOR_IRQ_NUMBER = 1,
+ BSP_PROCESSOR_IRQ_LOWEST_OFFSET = BSP_CPM_IRQ_MAX_OFFSET + 1,
+ BSP_PROCESSOR_IRQ_MAX_OFFSET = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER - 1,
+ /*
+ * Summary
+ */
+ BSP_IRQ_NUMBER = BSP_PROCESSOR_IRQ_MAX_OFFSET + 1,
+ BSP_LOWEST_OFFSET = BSP_SIU_IRQ_LOWEST_OFFSET,
+ BSP_MAX_OFFSET = BSP_PROCESSOR_IRQ_MAX_OFFSET,
+ /*
+ * Some SIU IRQ symbolic name definition. Please note that
+ * INT IRQ are defined but a single one will be used to
+ * redirect all CPM interrupt.
+ */
+ BSP_SIU_EXT_IRQ_0 = 0,
+ BSP_SIU_INT_IRQ_0 = 1,
+
+ BSP_SIU_EXT_IRQ_1 = 2,
+ BSP_SIU_INT_IRQ_1 = 3,
+
+ BSP_SIU_EXT_IRQ_2 = 4,
+ BSP_SIU_INT_IRQ_2 = 5,
+
+ BSP_SIU_EXT_IRQ_3 = 6,
+ BSP_SIU_INT_IRQ_3 = 7,
+
+ BSP_SIU_EXT_IRQ_4 = 8,
+ BSP_SIU_INT_IRQ_4 = 9,
+
+ BSP_SIU_EXT_IRQ_5 = 10,
+ BSP_SIU_INT_IRQ_5 = 11,
+
+ BSP_SIU_EXT_IRQ_6 = 12,
+ BSP_SIU_INT_IRQ_6 = 13,
+
+ BSP_SIU_EXT_IRQ_7 = 14,
+ BSP_SIU_INT_IRQ_7 = 15,
+ /*
+ * Symbolic name for CPM interrupt on SIU Internal level 2
+ */
+ BSP_CPM_INTERRUPT = BSP_SIU_INT_IRQ_2,
+ BSP_PERIODIC_TIMER = BSP_SIU_INT_IRQ_6,
+ BSP_FAST_ETHERNET_CTRL = BSP_SIU_INT_IRQ_3,
+ /*
+ * Some CPM IRQ symbolic name definition
+ */
+ BSP_CPM_IRQ_ERROR = BSP_CPM_IRQ_LOWEST_OFFSET,
+ BSP_CPM_IRQ_PARALLEL_IO_PC4 = BSP_CPM_IRQ_LOWEST_OFFSET + 1,
+ BSP_CPM_IRQ_PARALLEL_IO_PC5 = BSP_CPM_IRQ_LOWEST_OFFSET + 2,
+ BSP_CPM_IRQ_SMC2_OR_PIP = BSP_CPM_IRQ_LOWEST_OFFSET + 3,
+ BSP_CPM_IRQ_SMC1 = BSP_CPM_IRQ_LOWEST_OFFSET + 4,
+ BSP_CPM_IRQ_SPI = BSP_CPM_IRQ_LOWEST_OFFSET + 5,
+ BSP_CPM_IRQ_PARALLEL_IO_PC6 = BSP_CPM_IRQ_LOWEST_OFFSET + 6,
+ BSP_CPM_IRQ_TIMER_4 = BSP_CPM_IRQ_LOWEST_OFFSET + 7,
+
+ BSP_CPM_IRQ_PARALLEL_IO_PC7 = BSP_CPM_IRQ_LOWEST_OFFSET + 9,
+ BSP_CPM_IRQ_PARALLEL_IO_PC8 = BSP_CPM_IRQ_LOWEST_OFFSET + 10,
+ BSP_CPM_IRQ_PARALLEL_IO_PC9 = BSP_CPM_IRQ_LOWEST_OFFSET + 11,
+ BSP_CPM_IRQ_TIMER_3 = BSP_CPM_IRQ_LOWEST_OFFSET + 12,
+
+ BSP_CPM_IRQ_PARALLEL_IO_PC10 = BSP_CPM_IRQ_LOWEST_OFFSET + 14,
+ BSP_CPM_IRQ_PARALLEL_IO_PC11 = BSP_CPM_IRQ_LOWEST_OFFSET + 15,
+ BSP_CPM_I2C = BSP_CPM_IRQ_LOWEST_OFFSET + 16,
+ BSP_CPM_RISC_TIMER_TABLE = BSP_CPM_IRQ_LOWEST_OFFSET + 17,
+ BSP_CPM_IRQ_TIMER_2 = BSP_CPM_IRQ_LOWEST_OFFSET + 18,
+
+ BSP_CPM_IDMA2 = BSP_CPM_IRQ_LOWEST_OFFSET + 20,
+ BSP_CPM_IDMA1 = BSP_CPM_IRQ_LOWEST_OFFSET + 21,
+ BSP_CPM_SDMA_CHANNEL_BUS_ERR = BSP_CPM_IRQ_LOWEST_OFFSET + 22,
+ BSP_CPM_IRQ_PARALLEL_IO_PC12 = BSP_CPM_IRQ_LOWEST_OFFSET + 23,
+ BSP_CPM_IRQ_PARALLEL_IO_PC13 = BSP_CPM_IRQ_LOWEST_OFFSET + 24,
+ BSP_CPM_IRQ_TIMER_1 = BSP_CPM_IRQ_LOWEST_OFFSET + 25,
+ BSP_CPM_IRQ_PARALLEL_IO_PC14 = BSP_CPM_IRQ_LOWEST_OFFSET + 26,
+ BSP_CPM_IRQ_SCC4 = BSP_CPM_IRQ_LOWEST_OFFSET + 27,
+ BSP_CPM_IRQ_SCC3 = BSP_CPM_IRQ_LOWEST_OFFSET + 28,
+ BSP_CPM_IRQ_SCC2 = BSP_CPM_IRQ_LOWEST_OFFSET + 29,
+ BSP_CPM_IRQ_SCC1 = BSP_CPM_IRQ_LOWEST_OFFSET + 30,
+ BSP_CPM_IRQ_PARALLEL_IO_PC15 = BSP_CPM_IRQ_LOWEST_OFFSET + 31,
+ /*
+ * Some Processor exception handled as rtems IRQ symbolic name definition
+ */
+ BSP_DECREMENTER = BSP_PROCESSOR_IRQ_LOWEST_OFFSET
+
+}rtems_irq_symbolic_name;
+
+#define CPM_INTERRUPT
+
+
+/*
+ * Type definition for RTEMS managed interrupts
+ */
+typedef unsigned char rtems_irq_prio;
+struct __rtems_irq_connect_data__; /* forward declaratiuon */
+
+typedef void (*rtems_irq_hdl) (void);
+typedef void (*rtems_irq_enable) (const struct __rtems_irq_connect_data__*);
+typedef void (*rtems_irq_disable) (const struct __rtems_irq_connect_data__*);
+typedef int (*rtems_irq_is_enabled) (const struct __rtems_irq_connect_data__*);
+
+typedef struct __rtems_irq_connect_data__ {
+ /*
+ * IRQ line
+ */
+ rtems_irq_symbolic_name name;
+ /*
+ * handler. See comment on handler properties below in function prototype.
+ */
+ rtems_irq_hdl hdl;
+ /*
+ * function for enabling interrupts at device level (ONLY!).
+ * The BSP code will automatically enable it at SIU level and CPM level.
+ * RATIONALE : anyway such code has to exist in current driver code.
+ * It is usually called immediately AFTER connecting the interrupt handler.
+ * RTEMS may well need such a function when restoring normal interrupt
+ * processing after a debug session.
+ *
+ */
+ rtems_irq_enable on;
+ /*
+ * function for disabling interrupts at device level (ONLY!).
+ * The code will disable it at SIU and CPM level. RATIONALE : anyway
+ * such code has to exist for clean shutdown. It is usually called
+ * BEFORE disconnecting the interrupt. RTEMS may well need such
+ * a function when disabling normal interrupt processing for
+ * a debug session. May well be a NOP function.
+ */
+ rtems_irq_disable off;
+ /*
+ * function enabling to know what interrupt may currently occur
+ * if someone manipulates the i8259s interrupt mask without care...
+ */
+ rtems_irq_is_enabled isOn;
+}rtems_irq_connect_data;
+
+typedef struct {
+ /*
+ * size of all the table fields (*Tbl) described below.
+ */
+ unsigned int irqNb;
+ /*
+ * Default handler used when disconnecting interrupts.
+ */
+ rtems_irq_connect_data defaultEntry;
+ /*
+ * Table containing initials/current value.
+ */
+ rtems_irq_connect_data* irqHdlTbl;
+ /*
+ * actual value of BSP_SIU_IRQ_VECTOR_BASE...
+ */
+ rtems_irq_symbolic_name irqBase;
+ /*
+ * software priorities associated with interrupts.
+ * if irqPrio [i] > intrPrio [j] it means that
+ * interrupt handler hdl connected for interrupt name i
+ * will not be interrupted by the handler connected for interrupt j
+ * The interrupt source will be physically masked at i8259 level.
+ */
+ rtems_irq_prio* irqPrioTbl;
+}rtems_irq_global_settings;
+
+
+
+
+/*-------------------------------------------------------------------------+
+| Function Prototypes.
++--------------------------------------------------------------------------*/
+/*
+ * ------------------------ PPC SIU Mngt Routines -------
+ */
+
+/*
+ * function to disable a particular irq at 8259 level. After calling
+ * this function, even if the device asserts the interrupt line it will
+ * not be propagated further to the processor
+ */
+int BSP_irq_disable_at_siu (const rtems_irq_symbolic_name irqLine);
+/*
+ * function to enable a particular irq at 8259 level. After calling
+ * this function, if the device asserts the interrupt line it will
+ * be propagated further to the processor
+ */
+int BSP_irq_enable_at_siu (const rtems_irq_symbolic_name irqLine);
+/*
+ * function to acknoledge a particular irq at 8259 level. After calling
+ * this function, if a device asserts an enabled interrupt line it will
+ * be propagated further to the processor. Mainly usefull for people
+ * writting raw handlers as this is automagically done for rtems managed
+ * handlers.
+ */
+int BSP_irq_ack_at_siu (const rtems_irq_symbolic_name irqLine);
+/*
+ * function to check if a particular irq is enabled at 8259 level. After calling
+ */
+int BSP_irq_enabled_at_siu (const rtems_irq_symbolic_name irqLine);
+/*
+ * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
+ */
+/*
+ * function to connect a particular irq handler. This hanlder will NOT be called
+ * directly as the result of the corresponding interrupt. Instead, a RTEMS
+ * irq prologue will be called that will :
+ *
+ * 1) save the C scratch registers,
+ * 2) switch to a interrupt stack if the interrupt is not nested,
+ * 4) modify them to disable the current interrupt at SIU level (and may
+ * be others depending on software priorities)
+ * 5) aknowledge the SIU',
+ * 6) demask the processor,
+ * 7) call the application handler
+ *
+ * As a result the hdl function provided
+ *
+ * a) can perfectly be written is C,
+ * b) may also well directly call the part of the RTEMS API that can be used
+ * from interrupt level,
+ * c) It only responsible for handling the jobs that need to be done at
+ * the device level including (aknowledging/re-enabling the interrupt at device,
+ * level, getting the data,...)
+ *
+ * When returning from the function, the following will be performed by
+ * the RTEMS irq epilogue :
+ *
+ * 1) masks the interrupts again,
+ * 2) restore the original SIU interrupt masks
+ * 3) switch back on the orinal stack if needed,
+ * 4) perform rescheduling when necessary,
+ * 5) restore the C scratch registers...
+ * 6) restore initial execution flow
+ *
+ */
+int BSP_install_rtems_irq_handler (const rtems_irq_connect_data*);
+/*
+ * function to get the current RTEMS irq handler for ptr->name. It enables to
+ * define hanlder chain...
+ */
+int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* ptr);
+/*
+ * function to get disconnect the RTEMS irq handler for ptr->name.
+ * This function checks that the value given is the current one for safety reason.
+ * The user can use the previous function to get it.
+ */
+int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data*);
+
+/*
+ * ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
+ */
+/*
+ * (Re) Initialize the RTEMS interrupt management.
+ *
+ * The result of calling this function will be the same as if each individual
+ * handler (config->irqHdlTbl[i].hdl) different from "config->defaultEntry.hdl"
+ * has been individualy connected via
+ * BSP_install_rtems_irq_handler(&config->irqHdlTbl[i])
+ * And each handler currently equal to config->defaultEntry.hdl
+ * has been previously disconnected via
+ * BSP_remove_rtems_irq_handler (&config->irqHdlTbl[i])
+ *
+ * This is to say that all information given will be used and not just
+ * only the space.
+ *
+ * CAUTION : the various table address contained in config will be used
+ * directly by the interrupt mangement code in order to save
+ * data size so they must stay valid after the call => they should
+ * not be modified or declared on a stack.
+ */
+
+int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config);
+/*
+ * (Re) get info on current RTEMS interrupt management.
+ */
+int BSP_rtems_irq_mngt_get(rtems_irq_global_settings**);
+
+extern void BSP_rtems_irq_mng_init(unsigned cpuId);
+#endif
+
+#endif
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_asm.S b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_asm.S
new file mode 100644
index 0000000000..914ab67a4d
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_asm.S
@@ -0,0 +1,329 @@
+/*
+ * This file contains the assembly code for the PowerPC
+ * IRQ veneers for RTEMS.
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * Modified to support the MCP750.
+ * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
+ *
+ *
+ * $Id$
+ */
+
+#include <bsp/vectors.h>
+#include <libcpu/cpu.h>
+#include <libcpu/raw_exception.h>
+#include <rtems/score/cpuopts.h> /* for PPC_HAS_FPU */
+#include "asm.h"
+
+
+#define SYNC \
+ sync; \
+ isync
+
+ .text
+ .p2align 5
+
+ PUBLIC_VAR(decrementer_exception_vector_prolog_code)
+
+SYM (decrementer_exception_vector_prolog_code):
+ /*
+ * let room for exception frame
+ */
+ stwu r1, - (EXCEPTION_FRAME_END)(r1)
+ stw r4, GPR4_OFFSET(r1)
+ li r4, ASM_DEC_VECTOR
+ ba shared_raw_irq_code_entry
+
+ PUBLIC_VAR (decrementer_exception_vector_prolog_code_size)
+
+ decrementer_exception_vector_prolog_code_size = . - decrementer_exception_vector_prolog_code
+
+ PUBLIC_VAR(external_exception_vector_prolog_code)
+
+SYM (external_exception_vector_prolog_code):
+ /*
+ * let room for exception frame
+ */
+ stwu r1, - (EXCEPTION_FRAME_END)(r1)
+ stw r4, GPR4_OFFSET(r1)
+ li r4, ASM_EXT_VECTOR
+ ba shared_raw_irq_code_entry
+
+ PUBLIC_VAR (external_exception_vector_prolog_code_size)
+
+ external_exception_vector_prolog_code_size = . - external_exception_vector_prolog_code
+
+ PUBLIC_VAR(shared_raw_irq_code_entry)
+ PUBLIC_VAR(C_dispatch_irq_handler)
+
+ .p2align 5
+SYM (shared_raw_irq_code_entry):
+ /*
+ * Entry conditions :
+ * Registers already saved : R1, R4
+ * R1 : points to a location with enough room for the
+ * interrupt frame
+ * R4 : vector number
+ */
+ /*
+ * Save SRR0/SRR1 As soon As possible as it is the minimal needed
+ * to reenable exception processing
+ */
+ stw r0, GPR0_OFFSET(r1)
+ stw r2, GPR2_OFFSET(r1)
+ stw r3, GPR3_OFFSET(r1)
+
+ mfsrr0 r0
+ mfsrr1 r2
+ mfmsr r3
+
+ stw r0, SRR0_FRAME_OFFSET(r1)
+ stw r2, SRR1_FRAME_OFFSET(r1)
+ /*
+ * Enable data and instruction address translation, exception recovery
+ *
+ * also, on CPUs with FP, enable FP so that FP context can be
+ * saved and restored (using FP instructions)
+ */
+#if (PPC_HAS_FPU == 0)
+ ori r3, r3, MSR_RI | MSR_IR | MSR_DR
+#else
+ ori r3, r3, MSR_RI | MSR_IR | MSR_DR | MSR_FP
+#endif
+ mtmsr r3
+ SYNC
+ /*
+ * Push C scratch registers on the current stack. It may
+ * actually be the thread stack or the interrupt stack.
+ * Anyway we have to make it in order to be able to call C/C++
+ * functions. Depending on the nesting interrupt level, we will
+ * switch to the right stack later.
+ */
+ stw r5, GPR5_OFFSET(r1)
+ stw r6, GPR6_OFFSET(r1)
+ stw r7, GPR7_OFFSET(r1)
+ stw r8, GPR8_OFFSET(r1)
+ stw r9, GPR9_OFFSET(r1)
+ stw r10, GPR10_OFFSET(r1)
+ stw r11, GPR11_OFFSET(r1)
+ stw r12, GPR12_OFFSET(r1)
+ stw r13, GPR13_OFFSET(r1)
+
+ mfcr r5
+ mfctr r6
+ mfxer r7
+ mflr r8
+
+ stw r5, EXC_CR_OFFSET(r1)
+ stw r6, EXC_CTR_OFFSET(r1)
+ stw r7, EXC_XER_OFFSET(r1)
+ stw r8, EXC_LR_OFFSET(r1)
+
+ /*
+ * Add some non volatile registers to store information
+ * that will be used when returning from C handler
+ */
+ stw r14, GPR14_OFFSET(r1)
+ stw r15, GPR15_OFFSET(r1)
+ /*
+ * save current stack pointer location in R14
+ */
+ addi r14, r1, 0
+ /*
+ * store part of _Thread_Dispatch_disable_level address in R15
+ */
+ addis r15,0, _Thread_Dispatch_disable_level@ha
+ /*
+ * Get current nesting level in R2
+ */
+ mfspr r2, SPRG0
+ /*
+ * Check if stack switch is necessary
+ */
+ cmpwi r2,0
+ bne nested
+ mfspr r1, SPRG1
+
+nested:
+ /*
+ * Start Incrementing nesting level in R2
+ */
+ addi r2,r2,1
+ /*
+ * Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level
+ */
+ lwz r6,_Thread_Dispatch_disable_level@l(r15)
+ /*
+ * store new nesting level in SPRG0
+ */
+ mtspr SPRG0, r2
+
+ addi r6, r6, 1
+ mfmsr r5
+ /*
+ * store new _Thread_Dispatch_disable_level value
+ */
+ stw r6, _Thread_Dispatch_disable_level@l(r15)
+ /*
+ * We are now running on the interrupt stack. External and decrementer
+ * exceptions are still disabled. I see no purpose trying to optimize
+ * further assembler code.
+ */
+ /*
+ * Call C exception handler for decrementer Interrupt frame is passed just
+ * in case...
+ */
+ addi r3, r14, 0x8
+ bl C_dispatch_irq_handler /* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4) */
+ /*
+ * start decrementing nesting level. Note : do not test result against 0
+ * value as an easy exit condition because if interrupt nesting level > 1
+ * then _Thread_Dispatch_disable_level > 1
+ */
+ mfspr r2, SPRG0
+ /*
+ * start decrementing _Thread_Dispatch_disable_level
+ */
+ lwz r3,_Thread_Dispatch_disable_level@l(r15)
+ addi r2, r2, -1 /* Continue decrementing nesting level */
+ addi r3, r3, -1 /* Continue decrementing _Thread_Dispatch_disable_level */
+ mtspr SPRG0, r2 /* End decrementing nesting level */
+ stw r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */
+ cmpwi r3, 0
+ /*
+ * switch back to original stack (done here just optimize registers
+ * contention. Could have been done before...)
+ */
+ addi r1, r14, 0
+ bne easy_exit /* if (_Thread_Dispatch_disable_level != 0) goto easy_exit */
+ /*
+ * Here we are running again on the thread system stack.
+ * We have interrupt nesting level = _Thread_Dispatch_disable_level = 0.
+ * Interrupt are still disabled. Time to check if scheduler request to
+ * do something with the current thread...
+ */
+ addis r4, 0, _Context_Switch_necessary@ha
+ lwz r5, _Context_Switch_necessary@l(r4)
+ cmpwi r5, 0
+ bne switch
+
+ addis r6, 0, _ISR_Signals_to_thread_executing@ha
+ lwz r7, _ISR_Signals_to_thread_executing@l(r6)
+ cmpwi r7, 0
+ li r8, 0
+ beq easy_exit
+ stw r8, _ISR_Signals_to_thread_executing@l(r6)
+ /*
+ * going to call _ThreadProcessSignalsFromIrq
+ * Push a complete exception like frame...
+ */
+ stmw r16, GPR16_OFFSET(r1)
+ addi r3, r1, 0x8
+ /*
+ * compute SP at exception entry
+ */
+ addi r2, r1, EXCEPTION_FRAME_END
+ /*
+ * store it at the right place
+ */
+ stw r2, GPR1_OFFSET(r1)
+ /*
+ * Call High Level signal handling code
+ */
+ bl _ThreadProcessSignalsFromIrq
+ /*
+ * start restoring exception like frame
+ */
+ lwz r31, EXC_CTR_OFFSET(r1)
+ lwz r30, EXC_XER_OFFSET(r1)
+ lwz r29, EXC_CR_OFFSET(r1)
+ lwz r28, EXC_LR_OFFSET(r1)
+
+ mtctr r31
+ mtxer r30
+ mtcr r29
+ mtlr r28
+
+ lmw r4, GPR4_OFFSET(r1)
+ lwz r2, GPR2_OFFSET(r1)
+ lwz r0, GPR0_OFFSET(r1)
+
+ /*
+ * Disable data and instruction translation. Make path non recoverable...
+ */
+ mfmsr r3
+ xori r3, r3, MSR_RI | MSR_IR | MSR_DR
+ mtmsr r3
+ SYNC
+ /*
+ * Restore rfi related settings
+ */
+
+ lwz r3, SRR1_FRAME_OFFSET(r1)
+ mtsrr1 r3
+ lwz r3, SRR0_FRAME_OFFSET(r1)
+ mtsrr0 r3
+
+ lwz r3, GPR3_OFFSET(r1)
+ addi r1,r1, EXCEPTION_FRAME_END
+ SYNC
+ rfi
+
+switch:
+ bl SYM (_Thread_Dispatch)
+
+easy_exit:
+ /*
+ * start restoring interrupt frame
+ */
+ lwz r3, EXC_CTR_OFFSET(r1)
+ lwz r4, EXC_XER_OFFSET(r1)
+ lwz r5, EXC_CR_OFFSET(r1)
+ lwz r6, EXC_LR_OFFSET(r1)
+
+ mtctr r3
+ mtxer r4
+ mtcr r5
+ mtlr r6
+
+ lwz r15, GPR15_OFFSET(r1)
+ lwz r14, GPR14_OFFSET(r1)
+ lwz r13, GPR13_OFFSET(r1)
+ lwz r12, GPR12_OFFSET(r1)
+ lwz r11, GPR11_OFFSET(r1)
+ lwz r10, GPR10_OFFSET(r1)
+ lwz r9, GPR9_OFFSET(r1)
+ lwz r8, GPR8_OFFSET(r1)
+ lwz r7, GPR7_OFFSET(r1)
+ lwz r6, GPR6_OFFSET(r1)
+ lwz r5, GPR5_OFFSET(r1)
+
+ /*
+ * Disable nested exception processing, data and instruction
+ * translation.
+ */
+ mfmsr r3
+ xori r3, r3, MSR_RI | MSR_IR | MSR_DR
+ mtmsr r3
+ SYNC
+ /*
+ * Restore rfi related settings
+ */
+
+ lwz r4, SRR1_FRAME_OFFSET(r1)
+ lwz r2, SRR0_FRAME_OFFSET(r1)
+ lwz r3, GPR3_OFFSET(r1)
+ lwz r0, GPR0_OFFSET(r1)
+
+ mtsrr1 r4
+ mtsrr0 r2
+ lwz r4, GPR4_OFFSET(r1)
+ lwz r2, GPR2_OFFSET(r1)
+ addi r1,r1, EXCEPTION_FRAME_END
+ SYNC
+ rfi
+
diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_init.c b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_init.c
new file mode 100644
index 0000000000..9834c40145
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_init.c
@@ -0,0 +1,162 @@
+/* irq_init.c
+ *
+ * This file contains the implementation of rtems initialization
+ * related to interrupt handling.
+ *
+ * CopyRight (C) 2001 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.
+ *
+ * $Id$
+ */
+#include <bsp/irq.h>
+#include <bsp.h>
+#include <libcpu/raw_exception.h>
+#include <bsp/8xx_immap.h>
+#include <bsp/mbx.h>
+#include <bsp/commproc.h>
+
+extern unsigned int external_exception_vector_prolog_code_size;
+extern void external_exception_vector_prolog_code();
+extern unsigned int decrementer_exception_vector_prolog_code_size;
+extern void decrementer_exception_vector_prolog_code();
+
+volatile unsigned int ppc_cached_irq_mask;
+
+/*
+ * default on/off function
+ */
+static void nop_func(){}
+/*
+ * default isOn function
+ */
+static int not_connected() {return 0;}
+/*
+ * default possible isOn function
+ */
+static int connected() {return 1;}
+
+static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
+static rtems_irq_global_settings initial_config;
+static rtems_irq_connect_data defaultIrq = {
+ /* vectorIdex, hdl , on , off , isOn */
+ 0, nop_func , nop_func , nop_func , not_connected
+};
+static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={
+ /*
+ * actual rpiorities for interrupt :
+ * 0 means that only current interrupt is masked
+ * 255 means all other interrupts are masked
+ */
+ /*
+ * SIU interrupts.
+ */
+ 7,7, 6,6, 5,5, 4,4, 3,3, 2,2, 1,1, 0,0,
+ /*
+ * CPM Interrupts
+ */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ /*
+ * Processor exceptions handled as interrupts
+ */
+ 0
+};
+
+void BSP_SIU_irq_init()
+{
+ /*
+ * In theory we should initialize two registers at least :
+ * SIMASK, SIEL. SIMASK is reset at 0 value meaning no interrupt. But
+ * we should take care that a monitor may have restoreed to another value.
+ * If someone find a reasonnable value for SIEL, AND THE NEED TO CHANGE IT
+ * please feel free to add it here.
+ */
+ ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = 0;
+ ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 0xffff0000;
+ ppc_cached_irq_mask = 0;
+ ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel = ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel;
+}
+
+/*
+ * Initialize CPM interrupt management
+ */
+void
+BSP_CPM_irq_init(void)
+{
+ /*
+ * Initialize the CPM interrupt controller.
+ */
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr =
+#ifdef mpc860
+ (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
+#else
+ (CICR_SCB_SCC2 | CICR_SCA_SCC1) |
+#endif
+ ((BSP_CPM_INTERRUPT/2) << 13) | CICR_HP_MASK;
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0;
+
+ ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
+}
+
+void BSP_rtems_irq_mng_init(unsigned cpuId)
+{
+ rtems_raw_except_connect_data vectorDesc;
+ int i;
+
+ BSP_SIU_irq_init();
+ BSP_CPM_irq_init();
+ /*
+ * 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_ASM_IRQ_VECTOR_BASE;
+ initial_config.irqPrioTbl = irqPrioTable;
+
+ if (!BSP_rtems_irq_mngt_set(&initial_config)) {
+ /*
+ * put something here that will show the failure...
+ */
+ BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
+ }
+
+ /*
+ * We must connect the raw irq handler for the two
+ * expected interrupt sources : decrementer and external interrupts.
+ */
+ vectorDesc.exceptIndex = ASM_DEC_VECTOR;
+ vectorDesc.hdl.vector = ASM_DEC_VECTOR;
+ vectorDesc.hdl.raw_hdl = decrementer_exception_vector_prolog_code;
+ vectorDesc.hdl.raw_hdl_size = (unsigned) &decrementer_exception_vector_prolog_code_size;
+ vectorDesc.on = nop_func;
+ vectorDesc.off = nop_func;
+ vectorDesc.isOn = connected;
+ if (!mpc8xx_set_exception (&vectorDesc)) {
+ BSP_panic("Unable to initialize RTEMS decrementer raw exception\n");
+ }
+ vectorDesc.exceptIndex = ASM_EXT_VECTOR;
+ vectorDesc.hdl.vector = ASM_EXT_VECTOR;
+ vectorDesc.hdl.raw_hdl = external_exception_vector_prolog_code;
+ vectorDesc.hdl.raw_hdl_size = (unsigned) &external_exception_vector_prolog_code_size;
+ if (!mpc8xx_set_exception (&vectorDesc)) {
+ BSP_panic("Unable to initialize RTEMS external raw exception\n");
+ }
+#ifdef TRACE_IRQ_INIT
+ printk("RTEMS IRQ management is now operationnal\n");
+#endif
+}
+