patch-2.0.7 linux/arch/alpha/kernel/irq.c

Next file: linux/arch/alpha/kernel/lca.c
Previous file: linux/arch/alpha/kernel/bios32.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.6/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
@@ -35,9 +35,9 @@
 /*
  * Shadow-copy of masked interrupts.
  *  The bits are used as follows:
- *	 0.. 7	first ISA PIC (irq level 0..7)
- *	 8..15	second ISA PIC (irq level 8..15)
- *   Systems with 32 PCI interrupt lines (e.g., Alcor):
+ *	 0.. 7	first (E)ISA PIC (irq level 0..7)
+ *	 8..15	second (E)ISA PIC (irq level 8..15)
+ *   Systems with PCI interrupt lines managed by GRU (e.g., Alcor, XLT):
  *	16..47	PCI interrupts 0..31 (int at GRU_INT_MASK)
  *   Mikasa:
  *	16..31	PCI interrupts 0..15 (short at I/O port 536)
@@ -60,8 +60,7 @@
 #if NR_IRQS == 48
 	      default:
 		/* note inverted sense of mask bits: */
-		*(unsigned int *)GRU_INT_MASK = ~(mask >> 16);
-		mb();
+		*(unsigned int *)GRU_INT_MASK = ~(mask >> 16); mb();
 		break;
 
 #elif NR_IRQS == 33
@@ -166,17 +165,12 @@
 		}
 		/* .. then the master */
 		outb(0xE0 | irq, 0x20);
+#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
+		/* on ALCOR/XLT, need to dismiss interrupt via GRU */
+		*(int *)GRU_INT_CLEAR = 0x80000000; mb();
+		*(int *)GRU_INT_CLEAR = 0x00000000; mb();
+#endif /* ALCOR || XLT */
 	}
-#if 0
-	/* This is not needed since all interrupt are level-sensitive */
-#if defined(CONFIG_ALPHA_ALCOR)
-	/* on ALCOR, need to dismiss interrupt via GRU */
-	*(int *)GRU_INT_CLEAR = 0x80000000;
-	mb();
-	*(int *)GRU_INT_CLEAR = 0x00000000;
-	mb();
-#endif /* CONFIG_ALPHA_ALCOR */
-#endif
 }
 
 int request_irq(unsigned int irq, 
@@ -413,6 +407,42 @@
 #endif
 }
 
+#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
+/* we have to conditionally compile this because of GRU_xxx symbols */
+static inline void alcor_and_xlt_device_interrupt(unsigned long vector,
+                                                  struct pt_regs * regs)
+{
+        unsigned long pld;
+        unsigned int i;
+        unsigned long flags;
+
+        save_flags(flags);
+        cli();
+
+        /* read the interrupt summary register of the GRU */
+        pld = (*(unsigned int *)GRU_INT_REQ) & GRU_INT_REQ_BITS;
+
+#if 0
+        printk("[0x%08lx/0x%04x]", pld, inb(0x20) | (inb(0xA0) << 8));
+#endif
+
+        /*
+         * Now for every possible bit set, work through them and call
+         * the appropriate interrupt handler.
+         */
+        while (pld) {
+                i = ffz(~pld);
+                pld &= pld - 1; /* clear least bit set */
+                if (i == 31) {
+                        isa_device_interrupt(vector, regs);
+                } else {
+                        device_interrupt(16 + i, 16 + i, regs);
+                }
+        }
+        restore_flags(flags);
+}
+#endif /* ALCOR || XLT */
+
 static inline void cabriolet_and_eb66p_device_interrupt(unsigned long vector,
 							struct pt_regs * regs)
 {
@@ -655,6 +685,8 @@
 #if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_ALPHA_NONAME) || \
     defined(CONFIG_ALPHA_P2K) || defined(CONFIG_ALPHA_SRM)
 			srm_device_interrupt(vector, &regs);
+#elif NR_IRQS == 48
+			alcor_and_xlt_device_interrupt(vector, &regs);
 #elif NR_IRQS == 33
 			cabriolet_and_eb66p_device_interrupt(vector, &regs);
 #elif defined(CONFIG_ALPHA_MIKASA)
@@ -684,9 +716,8 @@
 	dma_outb(0, DMA1_CLR_MASK_REG);
 	dma_outb(0, DMA2_CLR_MASK_REG);
 #if NR_IRQS == 48
-	*(unsigned int *)GRU_INT_MASK = ~(irq_mask >> 16);	/* invert */
-	mb();
-	enable_irq(16 + 31);	/* enable EISA PIC cascade */
+	*(unsigned int *)GRU_INT_MASK = ~(irq_mask >> 16); mb();/* invert */
+	enable_irq(16 + 31);	/* enable (E)ISA PIC cascade */
 #elif NR_IRQS == 33
 	outl(irq_mask >> 16, 0x804);
 	enable_irq(16 +  4);	/* enable SIO cascade */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov