fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / mips / ddb5xxx / ddb5477 / irq.c
index 0ae8336..a8bd2e6 100644 (file)
@@ -10,7 +10,6 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -75,15 +74,10 @@ set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger)
 
 extern void vrc5477_irq_init(u32 base);
 extern void mips_cpu_irq_init(u32 base);
-extern asmlinkage void ddb5477_handle_int(void);
-extern int setup_irq(unsigned int irq, struct irqaction *irqaction);  
-static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL };
+static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 
-void
-ddb5477_irq_setup(void)
+void __init arch_init_irq(void)
 {
-       db_run(printk("ddb5477_irq_setup invoked.\n"));
-
        /* by default, we disable all interrupts and route all vrc5477
         * interrupts to pin 0 (irq 2) */
        ddb_out32(DDB_INTCTRL0, 0);
@@ -97,7 +91,7 @@ ddb5477_irq_setup(void)
        /* setup PCI interrupt attributes */
        set_pci_int_attr(PCI0, INTA, ACTIVE_LOW, LEVEL_SENSE);
        set_pci_int_attr(PCI0, INTB, ACTIVE_LOW, LEVEL_SENSE);
-       if (mips_machtype == MACH_NEC_ROCKHOPPERII) 
+       if (mips_machtype == MACH_NEC_ROCKHOPPERII)
                set_pci_int_attr(PCI0, INTC, ACTIVE_HIGH, LEVEL_SENSE);
        else
                set_pci_int_attr(PCI0, INTC, ACTIVE_LOW, LEVEL_SENSE);
@@ -137,10 +131,7 @@ ddb5477_irq_setup(void)
 
        /* setup cascade interrupts */
        setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade);
-       setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);      
-
-       /* hook up the first-level interrupt handler */
-       set_except_vector(0, ddb5477_handle_int);
+       setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);
 }
 
 u8 i8259_interrupt_ack(void)
@@ -162,8 +153,7 @@ u8 i8259_interrupt_ack(void)
  * the first level int-handler will jump here if it is a vrc5477 irq
  */
 #define        NUM_5477_IRQS   32
-asmlinkage void
-vrc5477_irq_dispatch(struct pt_regs *regs)
+static void vrc5477_irq_dispatch(void)
 {
        u32 intStatus;
        u32 bitmask;
@@ -187,7 +177,7 @@ vrc5477_irq_dispatch(struct pt_regs *regs)
                /* check for i8259 interrupts */
                if (intStatus & (1 << VRC5477_I8259_CASCADE)) {
                        int i8259_irq = i8259_interrupt_ack();
-                       do_IRQ(I8259_IRQ_BASE + i8259_irq, regs);
+                       do_IRQ(I8259_IRQ_BASE + i8259_irq);
                        return;
                }
        }
@@ -195,8 +185,26 @@ vrc5477_irq_dispatch(struct pt_regs *regs)
        for (i=0, bitmask=1; i<= NUM_5477_IRQS; bitmask <<=1, i++) {
                /* do we need to "and" with the int mask? */
                if (intStatus & bitmask) {
-                       do_IRQ(VRC5477_IRQ_BASE + i, regs);
+                       do_IRQ(VRC5477_IRQ_BASE + i);
                        return;
                }
        }
 }
+
+#define VR5477INTS (STATUSF_IP2|STATUSF_IP3|STATUSF_IP4|STATUSF_IP5|STATUSF_IP6)
+
+asmlinkage void plat_irq_dispatch(void)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status();
+
+       if (pending & STATUSF_IP7)
+               do_IRQ(CPU_IRQ_BASE + 7);
+       else if (pending & VR5477INTS)
+               vrc5477_irq_dispatch();
+       else if (pending & STATUSF_IP0)
+               do_IRQ(CPU_IRQ_BASE);
+       else if (pending & STATUSF_IP1)
+               do_IRQ(CPU_IRQ_BASE + 1);
+       else
+               spurious_interrupt();
+}