summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c
diff options
context:
space:
mode:
authorRalf Corsepius <ralf.corsepius@rtems.org>2005-12-31 05:09:26 +0000
committerRalf Corsepius <ralf.corsepius@rtems.org>2005-12-31 05:09:26 +0000
commitca680bc5890abe0d6bfe7eb4a40a0229f1b6bd36 (patch)
tree805a5ddce1250235d6133376ddabb5543eb2cf82 /c/src/lib/libbsp/powerpc/gen5200/irq/irq.c
parentAdd BuildRoot. (diff)
downloadrtems-ca680bc5890abe0d6bfe7eb4a40a0229f1b6bd36.tar.bz2
New (CVS import Thomas Doerfler <Thomas.Doerfler@embedded-brains.de>'s
submission).
Diffstat (limited to '')
-rw-r--r--c/src/lib/libbsp/powerpc/gen5200/irq/irq.c1141
1 files changed, 1141 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c b/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c
new file mode 100644
index 0000000000..2cde1fe025
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c
@@ -0,0 +1,1141 @@
+/*===============================================================*\
+| Project: RTEMS generic MPC5200 BSP |
++-----------------------------------------------------------------+
+| File: irq.c
++-----------------------------------------------------------------+
+| 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.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| this file contains the irq controller handler |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 01.12.05 creation doe |
+|*****************************************************************|
+|*CVS information: |
+|*(the following information is created automatically, |
+|*do not edit here) |
+|*****************************************************************|
+|* $Log$
+|* Revision 1.6 2005/12/09 08:57:03 thomas
+|* added/modifed file headers
+|*
+|* Revision 1.5 2005/12/06 14:30:42 thomas
+|* updated name for peripheral register block
+|*
+|* Revision 1.4 2005/12/06 14:11:12 thomas
+|* added EB file headers
+|*
+ *
+|*****************************************************************|
+\*===============================================================*/
+/***********************************************************************/
+/* */
+/* 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 found in the file LICENSE in this distribution or at */
+/* http://www.OARcorp.com/rtems/license.html. */
+/* */
+/*---------------------------------------------------------------------*/
+/* */
+/* 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 "../include/bsp.h"*/
+#include "../include/bsp.h"
+#include <rtems.h>
+/*#include "../irq/irq.h"*/
+#include "../irq/irq.h"
+/*#include <rtems/score/thread.h>*/
+#include <rtems/score/apiext.h>
+#include <rtems/bspIo.h>
+#include "../include/raw_exception.h"
+#include "../vectors/vectors.h"
+#include "../include/mpc5200.h"
+
+
+extern uint32_t irqMaskTable[];
+
+/*
+ * 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;
+
+/*
+ * 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 */
+ };
+
+/*
+ * 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));
+
+ }
+
+/*
+ * Check for SIU IRQ and return base index
+ */
+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 for SIU IRQ and return base index
+ */
+static inline int get_siu_irq_base_index(const rtems_irq_symbolic_name irqLine)
+ {
+
+ if(irqLine <= BSP_PER_IRQ_MAX_OFFSET)
+ return BSP_PER_IRQ_LOWEST_OFFSET;
+ else
+ if(irqLine <= BSP_MAIN_IRQ_MAX_OFFSET)
+ return BSP_MAIN_IRQ_LOWEST_OFFSET;
+ else
+ if(irqLine <= BSP_CRIT_IRQ_MAX_OFFSET)
+ return BSP_CRIT_IRQ_LOWEST_OFFSET;
+ else
+ return -1;
+
+ }
+
+
+static inline void BSP_enable_per_irq_at_siu(const rtems_irq_symbolic_name irqLine)
+ {
+ uint8_t lo_hi_ind = 0, prio_index_offset;
+ uint32_t *reg;
+ rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl;
+ volatile uint32_t per_pri_1,main_pri_1, crit_pri_main_mask, per_mask;
+
+ /* 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]);
+
+ main_pri_1 = mpc5200.main_pri_1;
+ crit_pri_main_mask = mpc5200.crit_pri_main_mask;
+ per_pri_1 = mpc5200.per_pri_1;
+ per_mask = mpc5200.per_mask;
+
+
+ }
+
+
+static inline void BSP_enable_main_irq_at_siu(const rtems_irq_symbolic_name irqLine)
+ {
+
+ uint8_t prio_index_offset;
+ uint32_t *reg;
+ rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl;
+
+ /* 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(const rtems_irq_symbolic_name irqLine)
+ {
+
+ uint8_t prio_index_offset;
+ uint32_t *reg;
+ rtems_irq_prio *irqPrioTable = internal_config->irqPrioTbl;
+
+ 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(const rtems_irq_symbolic_name 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(const rtems_irq_symbolic_name 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(const rtems_irq_symbolic_name 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));
+
+ }
+
+ }
+
+
+/*
+ * ------------------------ RTEMS Irq helper functions ----------------
+ */
+
+
+/*
+ * 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) )
+ return 0;
+ return 1;
+ }
+
+
+ /*
+ * This function enables a given siu interrupt
+ */
+int BSP_irq_enable_at_siu(const rtems_irq_symbolic_name irqLine)
+ {
+ int base_index;
+
+ if(is_siu_irq(irqLine))
+ {
+
+
+ if((base_index = get_siu_irq_base_index(irqLine)) != -1)
+ {
+
+ switch(base_index)
+ {
+
+ case BSP_PER_IRQ_LOWEST_OFFSET:
+ BSP_enable_per_irq_at_siu(irqLine);
+ break;
+
+ case BSP_MAIN_IRQ_LOWEST_OFFSET:
+ BSP_enable_main_irq_at_siu(irqLine);
+ break;
+
+ case BSP_CRIT_IRQ_LOWEST_OFFSET:
+ BSP_enable_crit_irq_at_siu(irqLine);
+ break;
+
+ default:
+ printk("No valid base index\n");
+ break;
+
+ }
+
+ }
+
+ }
+
+ return 0;
+
+ }
+
+/*
+ * This function disables a given siu interrupt
+ */
+int BSP_irq_disable_at_siu(const rtems_irq_symbolic_name irqLine)
+ {
+ int base_index;
+
+ if ( (base_index = get_siu_irq_base_index(irqLine)) == -1)
+ return 1;
+
+ switch(base_index)
+ {
+
+ case BSP_PER_IRQ_LOWEST_OFFSET:
+ BSP_disable_per_irq_at_siu(irqLine);
+
+ break;
+
+ case BSP_MAIN_IRQ_LOWEST_OFFSET:
+ BSP_disable_main_irq_at_siu(irqLine);
+ break;
+
+ case BSP_CRIT_IRQ_LOWEST_OFFSET:
+ BSP_disable_crit_irq_at_siu(irqLine);
+ break;
+
+ default:
+ printk("No valid base index\n");
+ break;
+
+ }
+
+ return 0;
+ }
+
+
+/*
+ * ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
+ */
+
+ /*
+ * This function removes the default entry and installs a device interrupt handler
+ */
+int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
+ {
+ unsigned int level;
+
+ if(!isValidInterrupt(irq->name))
+ {
+
+ printk("not a valid interrupt\n");
+ return 0;
+
+ }
+
+ /*
+ * Check if default handler is actually connected. If not issue an error.
+ * 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)
+ {
+
+ printk( "Default handler not there\n" );
+ return 0;
+
+ }
+
+ _CPU_ISR_Disable(level);
+
+ /*
+ * store the data provided by user
+ */
+ rtems_hdl_tbl[irq->name] = *irq;
+
+ if(is_siu_irq(irq->name))
+ {
+
+ /*
+ * Enable interrupt at siu level
+ */
+ BSP_irq_enable_at_siu(irq->name);
+
+ }
+ else
+ {
+
+ 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.
+ */
+
+
+ }
+ else
+ {
+
+ printk("not a valid interrupt\n");
+ return 0;
+
+ }
+
+ }
+
+
+ /*
+ * Enable interrupt on device
+ */
+ irq->on(irq);
+
+ _CPU_ISR_Enable(level);
+
+ return 1;
+
+ }
+
+
+ /*
+ * This function procures the current interrupt handler
+ */
+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;
+
+ }
+
+
+ /*
+ * This function removes a device interrupt handler and restores the default entry
+ */
+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.
+ * 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_siu_irq(irq->name))
+ {
+
+ /*
+ * disable interrupt at PIC 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 ----------------
+ */
+
+/*
+ * This function set up interrupt management dependent on the given configuration
+ */
+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 SIU IRQs
+ */
+ 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);
+
+ }
+
+ }
+
+ /*
+ * finish with Processor exceptions handled like IRQs
+ */
+ 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;
+
+ }
+
+
+/*
+ * 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 int msr;
+ register unsigned int new_msr;
+ register unsigned int pmce;
+ register unsigned int crit_pri_main_mask, per_mask;
+
+ switch(excNum)
+ {
+
+
+ /*
+ * Handle decrementer interrupt
+ */
+ case ASM_DEC_VECTOR:
+
+ /* call the module specific handler and pass the specific handler */
+ rtems_hdl_tbl[BSP_DECREMENTER].hdl(0);
+
+ return;
+
+ case ASM_SYSMGMT_VECTOR:
+
+ /* get the content of main interrupt status register */
+ pmce = mpc5200.pmce;
+
+ /* main interrupts may be routed to SMI, see bit SMI/INT select bit in main int. priorities */
+ while(CHK_MSE_STICKY(pmce))
+ {
+
+ /* check for main interrupt sources (hirarchical order) -> LO_int indicates peripheral sources */
+ if(CHK_MSE_STICKY(pmce))
+ {
+
+ /* get source of main interrupt */
+ irq = MSE_SOURCE(pmce);
+
+ switch(irq)
+ {
+
+ /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer 2 is always routed to SMI) */
+ case 0: /* slice timer 2 */
+ case 1:
+ case 2:
+ case 3:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+
+ /* add proper offset for main interrupts in the siu handler array */
+ irq += BSP_MAIN_IRQ_LOWEST_OFFSET;
+
+ /* save original mask and disable all lower priorized main interrupts*/
+ crit_pri_main_mask = mpc5200.crit_pri_main_mask;
+ mpc5200.crit_pri_main_mask |= irqMaskTable[irq];
+
+ /* enable interrupt nesting */
+ _CPU_MSR_GET(msr);
+ new_msr = msr | MSR_EE;
+ _CPU_MSR_SET(new_msr);
+
+ /* call the module specific handler and pass the specific handler */
+ rtems_hdl_tbl[irq].hdl(0);
+
+ /* disable interrupt nesting */
+ _CPU_MSR_SET(msr);
+
+ /* restore original interrupt mask */
+ mpc5200.crit_pri_main_mask = crit_pri_main_mask;
+
+ break;
+
+ /* peripheral LO_int interrupt source detected */
+ case 4:
+
+ /* check for valid peripheral interrupt source */
+ if(CHK_PSE_STICKY(pmce))
+ {
+
+ /* get source of peripheral interrupt */
+ irq = PSE_SOURCE(pmce);
+
+ /* add proper offset for peripheral interrupts in the siu handler array */
+ irq += BSP_PER_IRQ_LOWEST_OFFSET;
+
+ /* save original mask and disable all lower priorized main interrupts */
+ per_mask = mpc5200.per_mask;
+ mpc5200.per_mask |= irqMaskTable[irq];
+
+ /* enable interrupt nesting */
+ _CPU_MSR_GET(msr);
+ new_msr = msr | MSR_EE;
+ _CPU_MSR_SET(new_msr);
+
+ /* call the module specific handler and pass the specific handler */
+ rtems_hdl_tbl[irq].hdl(0);
+
+
+ /* disable interrupt nesting */
+ _CPU_MSR_SET(msr);
+
+ /* restore original interrupt mask */
+ mpc5200.per_mask = per_mask;
+
+ /* force re-evaluation of peripheral interrupts */
+ CLR_PSE_STICKY(mpc5200.pmce);
+
+ }
+ /* this case may not occur: no valid peripheral interrupt source */
+ else
+ {
+
+ printk("No valid peripheral LO_int interrupt source\n");
+
+ }
+
+ break;
+
+ /* error: unknown interrupt source */
+ default:
+ printk("Unknown peripheral LO_int interrupt source\n");
+ break;
+
+ }
+
+ /* force re-evaluation of main interrupts */
+ CLR_MSE_STICKY(mpc5200.pmce);
+
+ }
+
+ /* get the content of main interrupt status register */
+ pmce = mpc5200.pmce;
+
+ }
+
+ break;
+
+ case ASM_EXT_VECTOR:
+
+ /* get the content of main interrupt status register */
+ pmce = mpc5200.pmce;
+
+ /* critical interrupts may be routed to the core_int dependent on premature initialization, see bit 31 (CEbsH) */
+ while((CHK_CE_SHADOW(pmce) && CHK_CSE_STICKY(pmce)) || CHK_MSE_STICKY(pmce) || CHK_PSE_STICKY(pmce) )
+ {
+
+ /* first: check for critical interrupt sources (hirarchical order) -> HI_int indicates peripheral sources */
+ if(CHK_CE_SHADOW(pmce) && CHK_CSE_STICKY(pmce))
+ {
+
+ /* get source of critical interrupt */
+ irq = CSE_SOURCE(pmce);
+
+ switch(irq)
+ {
+ /* 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;
+
+ /* call the module specific handler and pass the specific handler */
+ rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
+
+ break;
+
+ /* peripheral HI_int interrupt source detected */
+ case 2:
+
+ /* check for valid peripheral interrupt source */
+ if(CHK_PSE_STICKY(pmce))
+ {
+
+ /* get source of peripheral interrupt */
+ irq = PSE_SOURCE(pmce);
+
+ /* add proper offset for peripheral interrupts in the siu handler array */
+ irq += BSP_PER_IRQ_LOWEST_OFFSET;
+
+ /* save original mask and disable all lower priorized main interrupts */
+ per_mask = mpc5200.per_mask;
+ mpc5200.per_mask |= irqMaskTable[irq];
+
+ /* enable interrupt nesting */
+ _CPU_MSR_GET(msr);
+ new_msr = msr | MSR_EE;
+ _CPU_MSR_SET(new_msr);
+
+ /* call the module specific handler and pass the specific handler */
+ rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
+
+
+ /* disable interrupt nesting */
+ _CPU_MSR_SET(msr);
+
+ /* restore original interrupt mask */
+ mpc5200.per_mask = per_mask;
+
+ /* force re-evaluation of peripheral interrupts */
+ CLR_PSE_STICKY(mpc5200.pmce);
+
+ }
+ /* this case may not occur: no valid peripheral interrupt source */
+ else
+ {
+
+ printk("No valid peripheral HI_int interrupt source\n");
+
+ }
+
+ break;
+
+ /* error: unknown interrupt source */
+ default:
+ printk("Unknown HI_int interrupt source\n");
+ break;
+
+ }
+
+ /* force re-evaluation of critical interrupts */
+ CLR_CSE_STICKY(mpc5200.pmce);
+
+ }
+
+ /* second: check for main interrupt sources (hirarchical order) -> LO_int indicates peripheral sources */
+ if(CHK_MSE_STICKY(pmce))
+ {
+
+ /* get source of main interrupt */
+ irq = MSE_SOURCE(pmce);
+
+ switch(irq)
+ {
+
+ /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer 2 is always routed to SMI) */
+ case 1:
+ case 2:
+ case 3:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+
+ /* add proper offset for main interrupts in the siu handler array */
+ irq += BSP_MAIN_IRQ_LOWEST_OFFSET;
+
+ /* save original mask and disable all lower priorized main interrupts*/
+ crit_pri_main_mask = mpc5200.crit_pri_main_mask;
+ mpc5200.crit_pri_main_mask |= irqMaskTable[irq];
+
+ /* enable interrupt nesting */
+ _CPU_MSR_GET(msr);
+ new_msr = msr | MSR_EE;
+ _CPU_MSR_SET(new_msr);
+
+ /* call the module specific handler and pass the specific handler */
+ rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
+
+ /* disable interrupt nesting */
+ _CPU_MSR_SET(msr);
+
+ /* restore original interrupt mask */
+ mpc5200.crit_pri_main_mask = crit_pri_main_mask;
+
+ break;
+
+ /* peripheral LO_int interrupt source detected */
+ case 4:
+
+ /* check for valid peripheral interrupt source */
+ if(CHK_PSE_STICKY(pmce))
+ {
+
+ /* get source of peripheral interrupt */
+ irq = PSE_SOURCE(pmce);
+
+ /* add proper offset for peripheral interrupts in the siu handler array */
+ irq += BSP_PER_IRQ_LOWEST_OFFSET;
+
+ /* save original mask and disable all lower priorized main interrupts */
+ per_mask = mpc5200.per_mask;
+ mpc5200.per_mask |= irqMaskTable[irq];
+
+ /* enable interrupt nesting */
+ _CPU_MSR_GET(msr);
+ new_msr = msr | MSR_EE;
+ _CPU_MSR_SET(new_msr);
+
+ /* call the module specific handler and pass the specific handler */
+ rtems_hdl_tbl[irq].hdl(rtems_hdl_tbl[irq].handle);
+
+
+ /* disable interrupt nesting */
+ _CPU_MSR_SET(msr);
+
+ /* restore original interrupt mask */
+ mpc5200.per_mask = per_mask;
+
+ /* force re-evaluation of peripheral interrupts */
+ CLR_PSE_STICKY(mpc5200.pmce);
+
+ }
+ /* this case may not occur: no valid peripheral interrupt source */
+ else
+ {
+
+ printk("No valid peripheral LO_int interrupt source\n");
+
+ }
+
+ break;
+
+ /* error: unknown interrupt source */
+ default:
+ printk("Unknown peripheral LO_int interrupt source\n");
+ break;
+
+ }
+
+ /* force re-evaluation of main interrupts */
+ CLR_MSE_STICKY(mpc5200.pmce);
+
+ }
+
+
+ /* get the content of main interrupt status register */
+ pmce = mpc5200.pmce;
+
+ }
+
+ break;
+
+ default:
+ printk("Unknown processor exception\n");
+ break;
+
+ } /* end of switch(excNum) */
+
+ return;
+
+ }
+
+
+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...
+ */
+}