summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/beatnik/irq/discovery_pic.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/powerpc/beatnik/irq/discovery_pic.c')
-rw-r--r--c/src/lib/libbsp/powerpc/beatnik/irq/discovery_pic.c993
1 files changed, 0 insertions, 993 deletions
diff --git a/c/src/lib/libbsp/powerpc/beatnik/irq/discovery_pic.c b/c/src/lib/libbsp/powerpc/beatnik/irq/discovery_pic.c
deleted file mode 100644
index f77125c4a7..0000000000
--- a/c/src/lib/libbsp/powerpc/beatnik/irq/discovery_pic.c
+++ /dev/null
@@ -1,993 +0,0 @@
-/* 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