patch-2.0.1 linux/arch/alpha/kernel/irq.c
Next file: linux/arch/alpha/kernel/osf_sys.c
Previous file: linux/arch/alpha/kernel/head.S
Back to the patch index
Back to the overall index
- Lines: 356
- Date:
Mon Jul 1 20:06:05 1996
- Orig file:
v2.0.0/linux/arch/alpha/kernel/irq.c
- Orig date:
Sun Jun 9 13:28:41 1996
diff -u --recursive --new-file v2.0.0/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
@@ -28,109 +28,83 @@
extern void timer_interrupt(struct pt_regs * regs);
-static unsigned char cache_21 = 0xff;
-static unsigned char cache_A1 = 0xff;
-
-#if NR_IRQS == 48
- static unsigned int cache_irq_mask = 0x7fffffff; /* enable EISA */
-#elif NR_IRQS == 33
- static unsigned int cache_804 = 0x00ffffef;
-#elif NR_IRQS == 32
-#ifdef CONFIG_ALPHA_MIKASA
- static unsigned short cache_536 = 0xffff;
-#else
- static unsigned char cache_26 = 0xdf;
- static unsigned char cache_27 = 0xff;
-#endif
+#if NR_IRQS > 64
+# error Unable to handle more than 64 irq levels.
#endif
-static void mask_irq(int irq)
-{
- unsigned long mask;
+/*
+ * 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):
+ * 16..47 PCI interrupts 0..31 (int at GRU_INT_MASK)
+ * Mikasa:
+ * 16..31 PCI interrupts 0..15 (short at I/O port 536)
+ * Other systems (not Mikasa) with 16 PCI interrupt lines:
+ * 16..23 PCI interrupts 0.. 7 (char at I/O port 26)
+ * 24..31 PCI interrupts 8..15 (char at I/O port 27)
+ * Systems with 17 PCI interrupt lines (e.g., Cabriolet and eb164):
+ * 16..32 PCI interrupts 0..31 (int at I/O port 804)
+ */
+static unsigned long irq_mask = ~0UL;
- if (irq < 16) {
- mask = 1 << (irq & 7);
- if (irq < 8) {
- cache_21 |= mask;
- outb(cache_21, 0x21);
- } else {
- cache_A1 |= mask;
- outb(cache_A1, 0xA1);
- }
+
+/*
+ * Update the hardware with the irq mask passed in MASK. The function
+ * exploits the fact that it is known that only bit IRQ has changed.
+ */
+static void update_hw(unsigned long irq, unsigned long mask)
+{
+ switch (irq) {
#if NR_IRQS == 48
- } else {
- mask = 1 << (irq - 16);
- cache_irq_mask |= mask;
- *(unsigned int *)GRU_INT_MASK = ~cache_irq_mask; /* invert */
+ default:
+ /* note inverted sense of mask bits: */
+ *(unsigned int *)GRU_INT_MASK = ~(mask >> 16);
+ mb();
+ break;
+
#elif NR_IRQS == 33
- } else {
- mask = 1 << (irq - 16);
- cache_804 |= mask;
- outl(cache_804, 0x804);
+ default:
+ outl(mask >> 16, 0x804);
+ break;
+
+#elif defined(CONFIG_ALPHA_MIKASA)
+ default:
+ outw(~(mask >> 16), 0x536); /* note invert */
+ break;
+
#elif NR_IRQS == 32
-#ifdef CONFIG_ALPHA_MIKASA
- } else {
- mask = 1 << (irq & 15);
- cache_536 |= mask;
- outw(~cache_536, 0x536); /* note invert */
-#else
- } else {
- mask = 1 << (irq & 7);
- if (irq < 24) {
- cache_26 |= mask;
- outb(cache_26, 0x26);
- } else {
- cache_27 |= mask;
- outb(cache_27, 0x27);
- }
-#endif
+ case 16 ... 23:
+ outb(mask >> 16, 0x26);
+ break;
+
+ default:
+ outb(mask >> 24, 0x27);
+ break;
#endif
+ /* handle ISA irqs last---fast devices belong on PCI... */
+
+ case 0 ... 7: /* ISA PIC1 */
+ outb(mask, 0x21);
+ break;
+
+ case 8 ...15: /* ISA PIC2 */
+ outb(mask >> 8, 0xA1);
+ break;
}
}
-static void unmask_irq(unsigned long irq)
+static inline void mask_irq(unsigned long irq)
{
- unsigned long mask;
-
- if (irq < 16) {
- mask = ~(1 << (irq & 7));
- if (irq < 8) {
- cache_21 &= mask;
- outb(cache_21, 0x21);
- } else {
- cache_A1 &= mask;
- outb(cache_A1, 0xA1);
- }
-#if NR_IRQS == 48
- } else {
- mask = ~(1 << (irq - 16));
- cache_irq_mask &= mask;
- *(unsigned int *)GRU_INT_MASK = ~cache_irq_mask; /* invert */
-#elif NR_IRQS == 33
- } else {
- mask = ~(1 << (irq - 16));
- cache_804 &= mask;
- outl(cache_804, 0x804);
-#elif NR_IRQS == 32
-#ifdef CONFIG_ALPHA_MIKASA
- } else {
- mask = ~(1 << (irq & 15));
- cache_536 &= mask;
- outw(~cache_536, 0x536); /* note invert */
-#else
- } else {
- mask = ~(1 << (irq & 7));
+ irq_mask |= (1UL << irq);
+ update_hw(irq, irq_mask);
+}
- if (irq < 24) {
- cache_26 &= mask;
- outb(cache_26, 0x26);
- } else {
- cache_27 &= mask;
- outb(cache_27, 0x27);
- }
-#endif
-#endif
- }
+static inline void unmask_irq(unsigned long irq)
+{
+ irq_mask &= ~(1UL << irq);
+ update_hw(irq, irq_mask);
}
void disable_irq(unsigned int irq_nr)
@@ -193,13 +167,16 @@
/* .. then the master */
outb(0xE0 | irq, 0x20);
}
+#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;
+ *(int *)GRU_INT_CLEAR = 0x80000000;
mb();
*(int *)GRU_INT_CLEAR = 0x00000000;
mb();
#endif /* CONFIG_ALPHA_ALCOR */
+#endif
}
int request_irq(unsigned int irq,
@@ -344,17 +321,6 @@
kstat.interrupts[irq]++;
action = irq_action[irq];
- if (action) {
- /* quick interrupts get executed with no extra overhead */
- if (action->flags & SA_INTERRUPT) {
- while (action) {
- action->handler(irq, action->dev_id, regs);
- action = action->next;
- }
- ack_irq(ack);
- return;
- }
- }
/*
* For normal interrupts, we mask it out, and then ACK it.
* This way another (more timing-critical) interrupt can
@@ -370,10 +336,10 @@
return;
if (action->flags & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
- while (action) {
+ do {
action->handler(irq, action->dev_id, regs);
action = action->next;
- }
+ } while (action);
unmask_irq(ack);
}
@@ -436,8 +402,8 @@
* write only. This is not true.
*/
pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */
- pic &= ~((cache_A1 << 8) | cache_21); /* apply mask */
- pic &= 0xFFFB; /* mask out cascade */
+ pic &= ~irq_mask; /* apply mask */
+ pic &= 0xFFFB; /* mask out cascade & hibits */
while (pic) {
j = ffz(~pic);
@@ -568,17 +534,13 @@
restore_flags(flags) ;
}
-#if NR_IRQS > 64
-# error Number of irqs limited to 64 due to interrupt-probing.
-#endif
-
/*
* Start listening for interrupts..
*/
unsigned long probe_irq_on(void)
{
struct irqaction * action;
- unsigned long irqs = 0, irqmask;
+ unsigned long irqs = 0;
unsigned long delay;
unsigned int i;
@@ -589,27 +551,15 @@
irqs |= (1 << i);
}
}
-
- /* wait for spurious interrupts to mask themselves out again */
+ /*
+ * Wait about 100ms for spurious interrupts to mask themselves
+ * out again...
+ */
for (delay = jiffies + HZ/10; delay > jiffies; )
- /* about 100 ms delay */;
-
+ barrier();
+
/* now filter out any obviously spurious interrupts */
- irqmask = (((unsigned long)cache_A1)<<8) | (unsigned long) cache_21;
-#if NR_IRQS == 48
- irqmask |= (unsigned long) cache_irq_mask << 16;
-#elif NR_IRQS == 33
- irqmask |= (unsigned long) cache_804 << 16;
-#elif NR_IRQS == 32
-#ifdef CONFIG_ALPHA_MIKASA
- irqmask |= (unsigned long) cache_536 << 16;
-#else
- irqmask |= ((((unsigned long)cache_26)<<16) |
- (((unsigned long)cache_27)<<24));
-#endif
-#endif
- irqs &= ~irqmask;
- return irqs;
+ return irqs & ~irq_mask;
}
/*
@@ -619,23 +569,9 @@
*/
int probe_irq_off(unsigned long irqs)
{
- unsigned long irqmask;
int i;
- irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
-#if NR_IRQS == 48
- irqmask |= (unsigned long) cache_irq_mask << 16;
-#elif NR_IRQS == 33
- irqmask |= (unsigned long) cache_804 << 16;
-#elif NR_IRQS == 32
-#ifdef CONFIG_ALPHA_MIKASA
- irqmask |= (unsigned long) cache_536 << 16;
-#else
- irqmask |= ((((unsigned long)cache_26)<<16) |
- (((unsigned long)cache_27)<<24));
-#endif
-#endif
- irqs &= irqmask & ~1; /* always mask out irq 0---it's the unused timer */
+ irqs &= irq_mask & ~1; /* always mask out irq 0---it's the unused timer */
#ifdef CONFIG_ALPHA_P2K
irqs &= ~(1 << 8); /* mask out irq 8 since that's the unused RTC input to PIC */
#endif
@@ -687,11 +623,11 @@
#elif NR_IRQS == 33
cabriolet_and_eb66p_device_interrupt(vector, ®s);
#elif NR_IRQS == 32
-#ifdef CONFIG_ALPHA_MIKASA
+# ifdef CONFIG_ALPHA_MIKASA
# error we got a problem here Charlie MIKASA should be SRM console
-#else
+# else
eb66_and_eb64p_device_interrupt(vector, ®s);
-#endif
+# endif
#elif NR_IRQS == 16
isa_device_interrupt(vector, ®s);
#endif
@@ -715,16 +651,18 @@
dma_outb(0, DMA1_CLR_MASK_REG);
dma_outb(0, DMA2_CLR_MASK_REG);
#if NR_IRQS == 48
- *(unsigned int *)GRU_INT_MASK = ~cache_irq_mask; /* invert */
+ *(unsigned int *)GRU_INT_MASK = ~(irq_mask >> 16); /* invert */
+ mb();
+ enable_irq(16 + 31); /* enable EISA PIC cascade */
#elif NR_IRQS == 33
- outl(cache_804, 0x804);
+ outl(irq_mask >> 16, 0x804);
+ enable_irq(16 + 4); /* enable SIO cascade */
+#elif defined(CONFIG_ALPHA_MIKASA)
+ outw(~(irq_mask >> 16), 0x536); /* note invert */
#elif NR_IRQS == 32
-#ifdef CONFIG_ALPHA_MIKASA
- outw(~cache_536, 0x536); /* note invert */
-#else
- outb(cache_26, 0x26);
- outb(cache_27, 0x27);
-#endif
+ outb(irq_mask >> 16, 0x26);
+ outb(irq_mask >> 24, 0x27);
+ enable_irq(16 + 5); /* enable SIO cascade */
#endif
enable_irq(2); /* enable cascade */
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov