Files
rtems/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c
Till Straumann a9e62c242f 2007-12-08 Till Straumann <strauman@slac.stanford.edu>
* ep1a/irq/irq.c, gen5200/irq/irq.c, gen83xx/irq/irq_init.c,
	mbx8xx/irq/irq.c, mpc8260ads/irq/irq.c, mvme5500/irq/irq.c,
	psim/irq/no_pic.c, score603e/irq/irq.c, shared/irq/irq_supp.h,
	shared/irq/openpic_i8259_irq.c, virtex/irq/irq_init.c:
	let C_dispatch_irq_handler() return zero to indicate to
	low-level exception handling code that the exception
	was handled (not used yet).
2007-12-08 17:26:19 +00:00

994 lines
29 KiB
C

/*===============================================================*\
| 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.com/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 found in the file LICENSE in this distribution or at */
/* http://www.rtems.com/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 <bsp.h>
#include <rtems.h>
#include "../irq/irq.h"
#include <rtems/score/apiext.h>
#include <rtems/bspIo.h>
#include <libcpu/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;
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(
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)
{
rtems_interrupt_level 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;
}
rtems_interrupt_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
*/
if (irq->on)
irq->on(irq);
rtems_interrupt_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)
{
rtems_interrupt_level 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;
}
rtems_interrupt_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
*/
if (irq->off)
irq->off(irq);
/*
* restore the default irq value
*/
rtems_hdl_tbl[irq->name] = default_rtems_entry;
rtems_interrupt_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;
rtems_interrupt_level level;
/*
* Store various code accelerators
*/
internal_config = config;
default_rtems_entry = config->defaultEntry;
rtems_hdl_tbl = config->irqHdlTbl;
rtems_interrupt_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);
if (rtems_hdl_tbl[i].on)
rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
} else {
if (rtems_hdl_tbl[i].off)
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) {
if (rtems_hdl_tbl[i].on)
rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
} else {
if (rtems_hdl_tbl[i].off)
rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
}
}
rtems_interrupt_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
*/
int 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 0;
case ASM_60X_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);
} else {
/* this case may not occur: no valid peripheral
* interrupt source
*/
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 (hierarchical 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);
_CPU_MSR_SET(msr);
/* restore original interrupt mask */
mpc5200.per_mask = per_mask;
/* force re-evaluation of peripheral interrupts */
CLR_PSE_STICKY(mpc5200.pmce);
} else {
/* this case may not occur: no valid peripheral
* interrupt source */
printk("No valid peripheral HI_int interrupt source\n");
}
break;
default:
/* error: unknown interrupt source */
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 (hierarchical 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);
} else {
/* this case may not occur: no valid peripheral
* interrupt source */
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 0;
}
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...
*/
}