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

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

diff -u --recursive --new-file v2.0.33/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
@@ -27,6 +27,7 @@
 #include <asm/dma.h>
 
 extern void timer_interrupt(struct pt_regs * regs);
+extern void cserve_update_hw(unsigned long, unsigned long);
 
 #if NR_IRQS > 64
 #  error Unable to handle more than 64 irq levels.
@@ -42,7 +43,8 @@
  *	 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)
+ *    or PYXIS (e.g. Miata, PC164-LX)
+ *	16..47	PCI interrupts 0..31 (xxx_INT_MASK reg)
  *   Mikasa:
  *	16..31	PCI interrupts 0..15 (short at I/O port 536)
  *   Other systems (not Mikasa) with 16 PCI interrupt lines:
@@ -50,13 +52,43 @@
  *	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)
+ *   Takara:
+ *      16..19  PCI interrupts A thru D
+ *   For SABLE, which is really baroque, we manage 40 IRQ's, but the
+ *   hardware really only supports 24, not via normal ISA PIC,
+ *   but cascaded custom 8259's, etc.
+ *	 0-7  (char at 536)
+ *	 8-15 (char at 53a)
+ *	16-23 (char at 53c)
  */
 static unsigned long irq_mask = ~0UL;
 
+#ifdef CONFIG_ALPHA_SABLE
+/* note that the vector reported by the SRM PALcode corresponds to the
+   interrupt mask bits, but we have to manage via more normal IRQs */
+static char sable_irq_to_mask[NR_IRQS] = {
+	-1,  6, -1,  8, 15, 12,  7,  9, /* pseudo PIC  0-7  */
+	-1, 16, 17, 18,  3, -1, 21, 22, /* pseudo PIC  8-15 */
+	-1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7  */
+	-1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */
+	 2,  1,  0,  4,  5, -1, -1, -1, /* pseudo PCI */
+	};
+#define IRQ_TO_MASK(irq) (sable_irq_to_mask[(irq)])
+static char sable_mask_to_irq[NR_IRQS] = {
+	34, 33, 32, 12, 35, 36,  1,  6, /* mask 0-7  */
+	 3,  7, -1, -1,  5, -1, -1,  4, /* mask 8-15  */
+	 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23  */
+	};
+#else /* CONFIG_ALPHA_SABLE */
+#define IRQ_TO_MASK(irq) (irq)
+#endif /* CONFIG_ALPHA_SABLE */
 
 /*
  * 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.
+ *
+ * There deliberately isn't a case in here for the Takara since it
+ * wouldn't work anyway because the interrupt controller is bizarre.
  */
 static void update_hw(unsigned long irq, unsigned long mask)
 {
@@ -65,32 +97,111 @@
 	mask |= 0x7ff00000UL << 16;
 #endif
 	switch (irq) {
-#if NR_IRQS == 48
-	      default:
+
+#ifdef CONFIG_ALPHA_SABLE
+  /* SABLE does everything different, so we manage it that way... :-( */
+  /* the "irq" argument is really the mask bit number */
+	case 0 ... 7:
+	  outb(mask, 0x537);
+	  break;
+	case 8 ... 15:
+	  outb(mask >> 8, 0x53b);
+	  break;
+	case 16 ... 23:
+	  outb(mask >> 16, 0x53d);
+	  break;
+#else /* SABLE */
+
+#if defined(CONFIG_ALPHA_NORITAKE)
+	  /* note inverted sense of mask bits: */
+	case 16 ... 31:
+	  outw(~(mask >> 16), 0x54a);
+	  break;
+	case 32 ... 47:
+	  outw(~(mask >> 32), 0x54c);
+	  break;
+#endif /* NORITAKE */
+
+#if defined(CONFIG_ALPHA_MIATA)
+	case 16 ... 47:
+	  { unsigned long temp;
+	  /* note inverted sense of mask bits: */
+	  /* make CERTAIN none of the bogus ints get enabled */
+	  *(unsigned long *)PYXIS_INT_MASK =
+	    ~((long)mask >> 16) & ~0x400000000000063bUL; mb();
+	  temp = *(unsigned long *)PYXIS_INT_MASK;
+	  break;
+	  }
+#endif /* MIATA */
+
+#if defined(CONFIG_ALPHA_RUFFIAN)
+	case 16 ... 47:
+	  { unsigned long temp;
+	  /* note inverted sense of mask bits: */
+	  /* make CERTAIN none of the bogus ints get enabled */
+	  *(unsigned long *)PYXIS_INT_MASK =
+	    ~((long)mask >> 16) & 0x00000000ffffffbfUL; mb();
+	  temp = *(unsigned long *)PYXIS_INT_MASK;
+	  break;
+	  }
+#endif /* RUFFIAN */
+
+#if defined(CONFIG_ALPHA_SX164)
+	case 16 ... 39:
+#if defined(CONFIG_ALPHA_SRM)
+	  cserve_update_hw(irq, mask);
+	  break;
+#else
+	  { unsigned long temp;
+	  /* make CERTAIN none of the bogus ints get enabled */
+	  *(unsigned long *)PYXIS_INT_MASK =
+	      ~((long)mask >> 16) & ~0x000000000000003bUL; mb();
+	  temp = *(unsigned long *)PYXIS_INT_MASK;
+	  break;
+	  }
+#endif /* SRM */
+#endif /* SX164 */
+
+#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
+	case 16 ... 47:
 		/* note inverted sense of mask bits: */
 		*(unsigned int *)GRU_INT_MASK = ~(mask >> 16); mb();
 		break;
+#endif /* ALCOR || XLT */
 
-#elif NR_IRQS == 33
-	      default:
-		outl(mask >> 16, 0x804);
+#if defined(CONFIG_ALPHA_CABRIOLET) || \
+    defined(CONFIG_ALPHA_EB66P)     || \
+    defined(CONFIG_ALPHA_EB164)     || \
+    defined(CONFIG_ALPHA_PC164)     || \
+    defined(CONFIG_ALPHA_LX164)
+#if defined(CONFIG_ALPHA_SRM)
+      case 16 ... 34:
+	cserve_update_hw(irq, mask);
+        break;
+#else /* SRM */
+      case 16 ... 34:
+	outl(irq_mask >> 16, 0x804);
 		break;
+#endif /* SRM */
+#endif /* CABRIO || EB66P || EB164 || PC164 || LX164 */
 
-#elif defined(CONFIG_ALPHA_MIKASA)
-	      default:
+#if defined(CONFIG_ALPHA_MIKASA)
+	case 16 ... 31:
 		outw(~(mask >> 16), 0x536); /* note invert */
 		break;
+#endif /* MIKASA */
 
-#elif NR_IRQS == 32
+#if defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
 	      case 16 ... 23:
 		outb(mask >> 16, 0x26);
 		break;
-
-	      default:
+	case 24 ... 31:
 		outb(mask >> 24, 0x27);
 		break;
-#endif
+#endif /* EB66 || EB64P */
+
 		/* handle ISA irqs last---fast devices belong on PCI... */
+	/* this is common for all except SABLE! */
 
 	      case  0 ... 7:	/* ISA PIC1 */
 		outb(mask, 0x21);
@@ -99,7 +210,10 @@
 	      case  8 ...15:	/* ISA PIC2 */
 		outb(mask >> 8, 0xA1);
 		break;
-	}
+
+#endif /* SABLE */
+
+	} /* end switch (irq) */
 }
 
 static inline void mask_irq(unsigned long irq)
@@ -120,7 +234,7 @@
 
 	save_flags(flags);
 	cli();
-	mask_irq(irq_nr);
+	mask_irq(IRQ_TO_MASK(irq_nr));
 	restore_flags(flags);
 }
 
@@ -130,7 +244,7 @@
 
 	save_flags(flags);
 	cli();
-	unmask_irq(irq_nr);
+	unmask_irq(IRQ_TO_MASK(irq_nr));
 	restore_flags(flags);
 }
 
@@ -164,7 +278,32 @@
 
 static inline void ack_irq(int irq)
 {
+#ifdef CONFIG_ALPHA_SABLE
+  /* note that the "irq" here is really the mask bit number */
+	switch (irq) {
+	case 0 ... 7:
+	  outb(0xE0 | (irq - 0), 0x536);
+	  outb(0xE0 | 1, 0x534); /* slave 0 */
+	  break;
+	case 8 ... 15:
+	  outb(0xE0 | (irq - 8), 0x53a);
+	  outb(0xE0 | 3, 0x534); /* slave 1 */
+	  break;
+	case 16 ... 24:
+	  outb(0xE0 | (irq - 16), 0x53c);
+	  outb(0xE0 | 4, 0x534); /* slave 2 */
+	  break;
+	}
+#else /* CONFIG_ALPHA_SABLE */
 	if (irq < 16) {
+#if defined(CONFIG_ALPHA_RUFFIAN)
+		/* ack pyxis ISA interrupt */
+		*(unsigned long *)PYXIS_INT_REQ = (0x01UL << 7);
+		if (irq > 7) {
+			outb(0x20,0xa0);
+		}
+		outb(0x20,0x20);
+#else /* RUFFIAN */
 		/* ACK the interrupt making it the lowest priority */
 		/*  First the slave .. */
 		if (irq > 7) {
@@ -178,7 +317,16 @@
 		*(int *)GRU_INT_CLEAR = 0x80000000; mb();
 		*(int *)GRU_INT_CLEAR = 0x00000000; mb();
 #endif /* ALCOR || XLT */
+#endif /* RUFFIAN */  
 	}
+#if defined(CONFIG_ALPHA_RUFFIAN)
+        else {
+	  /* ack pyxis int */
+	  *(unsigned long *)PYXIS_INT_REQ = (1UL << (irq-16));
+        }
+#endif /* RUFFIAN */        
+
+#endif /* CONFIG_ALPHA_SABLE */
 }
 
 int request_irq(unsigned int irq, 
@@ -236,7 +384,7 @@
 	*p = action;
 
 	if (!shared)
-		unmask_irq(irq);
+		unmask_irq(IRQ_TO_MASK(irq));
 
 	restore_flags(flags);
 	return 0;
@@ -264,7 +412,7 @@
 		cli();
 		*p = action->next;
 		if (!irq[irq_action])
-			mask_irq(irq);
+			mask_irq(IRQ_TO_MASK(irq));
 		restore_flags(flags);
 		kfree(action);
 		return;
@@ -323,25 +471,39 @@
 	struct irqaction * action;
 
 	if ((unsigned) irq > NR_IRQS) {
-		printk("device_interrupt: unexpected interrupt %d\n", irq);
+		printk("device_interrupt: illegal interrupt %d\n", irq);
+		return;
+	}
+
+#if defined(CONFIG_ALPHA_RUFFIAN)
+	/* RUFFIAN uses ISA IRQ #0 to deliver clock ticks */
+	if (irq == 0) {
+		timer_interrupt(regs);
+		ack_irq(0);
 		return;
 	}
+#endif /* RUFFIAN */
 
 	kstat.interrupts[irq]++;
 	action = irq_action[irq];
+
 	/*
 	 * For normal interrupts, we mask it out, and then ACK it.
 	 * This way another (more timing-critical) interrupt can
 	 * come through while we're doing this one.
 	 *
-	 * Note! A irq without a handler gets masked and acked, but
+	 * Note! An irq without a handler gets masked and acked, but
 	 * never unmasked. The autoirq stuff depends on this (it looks
 	 * at the masks before and after doing the probing).
 	 */
 	mask_irq(ack);
 	ack_irq(ack);
-	if (!action)
+	if (!action) {
+#if 1
+		printk("device_interrupt: unexpected interrupt %d\n", irq);
+#endif
 		return;
+	}
 	if (action->flags & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
 	do {
@@ -365,6 +527,8 @@
 #	define IACK_SC	LCA_IACK_SC
 #elif defined(CONFIG_ALPHA_CIA)
 #	define IACK_SC	CIA_IACK_SC
+#elif defined(CONFIG_ALPHA_PYXIS)
+#	define IACK_SC	PYXIS_IACK_SC
 #else
 	/*
 	 * This is bogus but necessary to get it to compile
@@ -554,8 +718,185 @@
 	restore_flags(flags);
 }
 
+#if defined(CONFIG_ALPHA_MIATA) || defined(CONFIG_ALPHA_SX164)
+/* we have to conditionally compile this because of PYXIS_xxx symbols */
+static inline void miata_device_interrupt(unsigned long vector,
+                                                  struct pt_regs * regs)
+{
+        unsigned long pld, tmp;
+        unsigned int i;
+        unsigned long flags;
+
+        save_flags(flags);
+        cli();
+
+        /* read the interrupt summary register of PYXIS */
+        pld = (*(volatile unsigned long *)PYXIS_INT_REQ);
+
+#if 0
+        printk("[0x%08lx/0x%08lx/0x%04x]", pld,
+	       *(volatile unsigned long *)PYXIS_INT_MASK,
+	       inb(0x20) | (inb(0xA0) << 8));
+#endif
+
+#ifdef CONFIG_ALPHA_MIATA
+	/* for now, AND off any bits we are not interested in: */
+	/*  HALT (2), timer (6), ISA Bridge (7), 21142 (8) */
+	/*  then all the PCI slots/INTXs (12-31) */
+/* maybe HALT should only be used for SRM console boots? */
+	pld &= 0x00000000fffff9c4UL;
+#endif /* MIATA */
+#ifdef CONFIG_ALPHA_SX164
+	/* for now, AND off any bits we are not interested in: */
+	/*  HALT (2), timer (6), ISA Bridge (7) */
+	/*  then all the PCI slots/INTXs (8-23) */
+/* HALT should only be used for SRM console boots */
+	pld &= 0x0000000000ffffc0UL;
+#endif /* SX164 */
+
+        /*
+         * 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 == 7) {
+                        isa_device_interrupt(vector, regs);
+		} else if (i == 6)
+			continue;
+                else { /* if not timer int */
+                        device_interrupt(16 + i, 16 + i, regs);
+                }
+		*(unsigned long *)PYXIS_INT_REQ = 1UL << i; mb();
+		tmp = *(volatile unsigned long *)PYXIS_INT_REQ;
+        }
+        restore_flags(flags);
+}
+#endif /* MIATA || SX164 */
+
+static inline void noritake_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 registers */
+        /* read the interrupt summary registers of NORITAKE */
+        pld = ((unsigned long) inw(0x544) << 32) |
+	      ((unsigned long) inw(0x542) << 16) |
+	      ((unsigned long) inb(0xa0)  <<  8) |
+	      ((unsigned long) inb(0x20));
+
+#if 0
+        printk("[0x%08lx]", pld);
+#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 < 16) {
+			isa_device_interrupt(vector, regs);
+		} else {
+			device_interrupt(i, i, regs);
+		}
+        }
+        restore_flags(flags);
+}
+
 #endif /* CONFIG_PCI */
 
+#if defined(CONFIG_ALPHA_RUFFIAN)
+static inline void ruffian_device_interrupt(unsigned long vector,
+					    struct pt_regs * regs)
+
+{
+	unsigned long pld, tmp;
+        unsigned int i;
+        unsigned long flags;
+
+        save_flags(flags);
+        cli();
+
+        /* read the interrupt summary register of PYXIS */
+        pld = (*(volatile unsigned long *)PYXIS_INT_REQ);
+
+        /* for now, AND off any bits we are not interested in:
+         *  HALT (2), timer (6), ISA Bridge (7), 21142 (8)
+         *  then all the PCI slots/INTXs (12-31) 
+         *  flash(5) :DWH:
+         */
+        pld &= 0x00000000ffffff9fUL;/* was ffff7f */
+
+        /*
+         * 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 == 7) {
+			isa_device_interrupt(vector, regs);
+                } else { /* if not timer int */
+			device_interrupt(16 + i,16 + i,regs);
+                }
+                *(unsigned long *)PYXIS_INT_REQ = 1UL << i; mb();
+                tmp = *(volatile unsigned long *)PYXIS_INT_REQ;
+        }
+        restore_flags(flags);
+}
+#endif /* RUFFIAN */
+
+static inline void takara_device_interrupt(unsigned long vector,
+					   struct pt_regs * regs)
+{
+	unsigned long flags;
+	unsigned intstatus;
+
+	save_flags(flags);
+	cli();
+
+	/*
+	 * The PALcode will have passed us vectors 0x800 or 0x810,
+	 * which are fairly arbitrary values and serve only to tell
+	 * us whether an interrupt has come in on IRQ0 or IRQ1. If
+	 * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
+	 * probably ISA, but PCI interrupts can come through IRQ0
+	 * as well if the interrupt controller isn't in accelerated
+	 * mode.
+	 *
+	 * OTOH, the accelerator thing doesn't seem to be working
+	 * overly well, so what we'll do instead is try directly
+	 * examining the Master Interrupt Register to see if it's a
+	 * PCI interrupt, and if _not_ then we'll pass it on to the
+	 * ISA handler.
+	 */
+
+	intstatus = inw(0x500) & 15;
+	if (intstatus) {
+		/*
+		 * This is a PCI interrupt. Check each bit and
+		 * despatch an interrupt if it's set.
+		 */
+		if (intstatus & 8) device_interrupt(16+3, 16+3, regs);
+		if (intstatus & 4) device_interrupt(16+2, 16+2, regs);
+		if (intstatus & 2) device_interrupt(16+1, 16+1, regs);
+		if (intstatus & 1) device_interrupt(16+0, 16+0, regs);
+	} else
+		isa_device_interrupt (vector, regs);
+
+	restore_flags(flags);
+}
+
 /*
  * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
  * 0x9X0 for the local motherboard interrupts..
@@ -587,6 +928,9 @@
 	save_flags(flags);
 	cli();
 
+#if 0
+printk("srm_device_interrupt: vector 0x%lx\n", vector);
+#endif
 
 	ack = irq = (vector - 0x800) >> 4;
 
@@ -608,11 +952,69 @@
 		irq = 7;
 #endif /* CONFIG_ALPHA_JENSEN */
 
+#ifdef CONFIG_ALPHA_MIATA
+        /*
+         * I really hate to do this, but the MIATA SRM console ignores the
+         *  low 8 bits in the interrupt summary register, and reports the
+         *  vector 0x80 *lower* than I expected from the bit numbering in
+         *  the documentation.
+         * This was done because the low 8 summary bits really aren't used
+         *  for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't
+         *  used for this purpose, as PIC interrupts are delivered as the
+         *  vectors 0x800-0x8f0).
+         * But I really don't want to change the fixup code for allocation
+         *  of IRQs, nor the irq_mask maintenance stuff, both of which look
+         *  nice and clean now.
+         * So, here's this grotty hack... :-(
+         */
+        if (irq >= 16)
+		ack = irq = irq + 8;
+#endif /* CONFIG_ALPHA_MIATA */
+
+#ifdef CONFIG_ALPHA_NORITAKE
+        /*
+         * I really hate to do this, but the NORITAKE SRM console reports
+         *  PCI vectors *lower* than I expected from the bit numbering in
+         *  the documentation.
+         * But I really don't want to change the fixup code for allocation
+         *  of IRQs, nor the irq_mask maintenance stuff, both of which look
+         *  nice and clean now.
+         * So, here's this grotty hack... :-(
+         */
+        if (irq >= 16)
+		ack = irq = irq + 1;
+#endif /* CONFIG_ALPHA_NORITAKE */
+
+#ifdef CONFIG_ALPHA_SABLE
+	irq = sable_mask_to_irq[(ack)];
+#if 0
+	if (irq == 5 || irq == 9 || irq == 10 || irq == 11 ||
+	    irq == 14 || irq == 15)
+	printk("srm_device_interrupt: vector=0x%lx  ack=0x%x  irq=0x%x\n",
+	       vector, ack, irq);
+#endif
+#endif /* CONFIG_ALPHA_SABLE */
+
 	device_interrupt(irq, ack, regs);
 
 	restore_flags(flags) ;
 }
 
+/* PROBE_MASK is the bitset of irqs that we consider for autoprobing: */
+#if defined(CONFIG_ALPHA_P2K)
+  /* always mask out unused timer irq 0 and RTC irq 8 */
+# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~0x101UL)
+#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
+  /* always mask out unused timer irq 0, "irqs" 20-30, and the EISA cascade: */
+# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~0xfff000000001UL)
+#elif defined(CONFIG_ALPHA_RUFFIAN)
+  /* must leave timer irq 0 in the mask */
+# define PROBE_MASK ((1UL << NR_IRQS) - 1)
+#else
+  /* always mask out unused timer irq 0: */
+# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~1UL)
+#endif
+
 /*
  * Start listening for interrupts..
  */
@@ -624,10 +1026,13 @@
 	unsigned int i;
 
 	for (i = NR_IRQS - 1; i > 0; i--) {
+		if (!(PROBE_MASK & (1UL << i))) {
+			continue;
+                }
 		action = irq_action[i];
 		if (!action) {
 			enable_irq(i);
-			irqs |= (1 << i);
+			irqs |= (1UL << i);
 		}
 	}
 	/*
@@ -650,10 +1055,7 @@
 {
 	int i;
 	
-	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
+	irqs &= irq_mask;
 	if (!irqs)
 		return 0;
 	i = ffz(~irqs);
@@ -676,6 +1078,14 @@
 	extern void cia_machine_check(unsigned long vector, unsigned long la,
 					struct pt_regs * regs);
 	cia_machine_check(vector, la, regs);
+#elif defined(CONFIG_ALPHA_PYXIS)
+	extern void pyxis_machine_check(unsigned long vector, unsigned long la,
+					struct pt_regs * regs);
+	pyxis_machine_check(vector, la, regs);
+#elif defined(CONFIG_ALPHA_T2)
+	extern void t2_machine_check(unsigned long vector, unsigned long la,
+				     struct pt_regs * regs);
+	t2_machine_check(vector, la, regs);
 #else
 	printk("Machine check\n");
 #endif
@@ -685,6 +1095,9 @@
 	unsigned long a3, unsigned long a4, unsigned long a5,
 	struct pt_regs regs)
 {
+#if 0
+printk("do_entInt: type 0x%lx\n", type);
+#endif
 	switch (type) {
 		case 0:
 			printk("Interprocessor interrupt? You must be kidding\n");
@@ -699,17 +1112,30 @@
 #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
+#else /* everyone else */
+
+#if defined(CONFIG_ALPHA_MIATA) || defined(CONFIG_ALPHA_SX164)
+			miata_device_interrupt(vector, &regs);
+#elif defined(CONFIG_ALPHA_NORITAKE)
+			noritake_device_interrupt(vector, &regs);
+#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
 			alcor_and_xlt_device_interrupt(vector, &regs);
-#elif NR_IRQS == 33
+#elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P) || \
+      defined(CONFIG_ALPHA_EB164)     || defined(CONFIG_ALPHA_PC164) || \
+      defined(CONFIG_ALPHA_LX164)
 			cabriolet_and_eb66p_device_interrupt(vector, &regs);
 #elif defined(CONFIG_ALPHA_MIKASA)
 			mikasa_device_interrupt(vector, &regs);
-#elif NR_IRQS == 32
+#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
 			eb66_and_eb64p_device_interrupt(vector, &regs);
+#elif defined(CONFIG_ALPHA_RUFFIAN)
+                        ruffian_device_interrupt(vector, &regs);
+#elif defined(CONFIG_ALPHA_TAKARA)
+			takara_device_interrupt(vector, &regs);
 #elif NR_IRQS == 16
 			isa_device_interrupt(vector, &regs);
 #endif
+#endif /* everyone else */
 			return;
 		case 4:
 			printk("Performance counter interrupt\n");
@@ -724,23 +1150,141 @@
 
 void init_IRQ(void)
 {
+	unsigned int temp;
+
 	wrent(entInt, 0);
-	dma_outb(0, DMA1_RESET_REG);
-	dma_outb(0, DMA2_RESET_REG);
-	dma_outb(0, DMA1_CLR_MASK_REG);
-	dma_outb(0, DMA2_CLR_MASK_REG);
-#if NR_IRQS == 48
+
+	outb(0, DMA1_RESET_REG);
+	outb(0, DMA2_RESET_REG);
+
+/* FIXME FIXME FIXME FIXME FIXME */
+#if !defined(CONFIG_ALPHA_SX164)
+	outb(0, DMA1_CLR_MASK_REG);
+	/* we need to figure out why this fails on the SX164 */
+	outb(0, DMA2_CLR_MASK_REG);
+#endif /* !SX164 */
+/* end FIXMEs */
+
+#if defined(CONFIG_ALPHA_SABLE)
+	outb(irq_mask      , 0x537); /* slave 0 */
+	outb(irq_mask >>  8, 0x53b); /* slave 1 */
+	outb(irq_mask >> 16, 0x53d); /* slave 2 */
+	outb(0x44, 0x535);	/* enable cascades in master */
+#else /* everybody but SABLE */
+
+#if defined(CONFIG_ALPHA_MIATA)
+	/* note invert on MASK bits */
+        *(unsigned long *)PYXIS_INT_MASK  =
+	  ~((long)irq_mask >> 16) & ~0x400000000000063bUL; mb();
+#if 0
+	/* these break on MiataGL so we'll try not to do it at all */
+        *(unsigned long *)PYXIS_INT_HILO  = 0x000000B2UL; mb();/* ISA/NMI HI */
+        *(unsigned long *)PYXIS_RT_COUNT  = 0UL; mb();/* clear count */
+#endif
+	/* clear upper timer */
+        *(unsigned long *)PYXIS_INT_REQ  = 0x4000000000000180UL; mb();
+
+	/* Send -INTA pulses to clear any pending interrupts ...*/
+	temp = *(volatile unsigned int *) IACK_SC;
+
+	enable_irq(16 + 2);	/* enable HALT switch - SRM only? */
+        enable_irq(16 + 6);     /* enable timer */
+        enable_irq(16 + 7);     /* enable ISA PIC cascade */
+#endif /* MIATA */
+
+#if defined(CONFIG_ALPHA_SX164)
+#if !defined(CONFIG_ALPHA_SRM)
+	/* note invert on MASK bits */
+        *(unsigned long *)PYXIS_INT_MASK  = ~((long)irq_mask >> 16); mb();
+#if 0
+        *(unsigned long *)PYXIS_INT_HILO  = 0x000000B2UL; mb();/* ISA/NMI HI */
+        *(unsigned long *)PYXIS_RT_COUNT  = 0UL; mb();/* clear count */
+#endif
+#endif /* !SRM */
+        enable_irq(16 + 6);     /* enable timer */
+        enable_irq(16 + 7);     /* enable ISA PIC cascade */
+#endif /* SX164 */
+
+#if defined(CONFIG_ALPHA_NORITAKE)
+	outw(~(irq_mask >> 16), 0x54a); /* note invert */
+	outw(~(irq_mask >> 32), 0x54c); /* note invert */
+#endif /* NORITAKE */
+
+#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
 	*(unsigned int *)GRU_INT_MASK = ~(irq_mask >> 16); mb();/* invert */
+	*(unsigned int *)GRU_INT_EDGE  = 0UL; mb();/* all are level */
+	*(unsigned int *)GRU_INT_HILO  = 0x80000000UL; mb();/* ISA only HI */
+	*(unsigned int *)GRU_INT_CLEAR = 0UL; mb();/* all clear */
 	enable_irq(16 + 31);	/* enable (E)ISA PIC cascade */
-#elif NR_IRQS == 33
+#endif /* ALCOR || XLT */
+
+#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P) || \
+    defined(CONFIG_ALPHA_PC164)     || defined(CONFIG_ALPHA_LX164) || \
+    defined(CONFIG_ALPHA_EB164)
+#if !defined(CONFIG_ALPHA_SRM)
 	outl(irq_mask >> 16, 0x804);
+#endif /* !SRM */
+	/* Send -INTA pulses to clear any pending interrupts ...*/
+	temp = *(volatile unsigned int *) IACK_SC;
 	enable_irq(16 +  4);	/* enable SIO cascade */
-#elif defined(CONFIG_ALPHA_MIKASA)
+#endif /* CABRIO || EB66P || PC164 || LX164 || EB164 */
+
+#if defined(CONFIG_ALPHA_MIKASA)
 	outw(~(irq_mask >> 16), 0x536); /* note invert */
-#elif NR_IRQS == 32
+#endif /* MIKASA */
+
+#if defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
 	outb(irq_mask >> 16, 0x26);
 	outb(irq_mask >> 24, 0x27);
 	enable_irq(16 +  5);	/* enable SIO cascade */
-#endif
-	enable_irq(2);		/* enable cascade */
+#endif /* EB66 || EB64P */
+
+#if defined(CONFIG_ALPHA_RUFFIAN)
+	/* invert 6&7 for i82371 */
+	*(unsigned long *)PYXIS_INT_HILO  = 0x000000c0UL;mb();
+	*(unsigned long *)PYXIS_INT_CNFG  = 0x00002064UL;mb();   /* all clear */
+	*(unsigned long *)PYXIS_INT_MASK  = ((long)0x00000000UL);mb();
+	*(unsigned long *)PYXIS_INT_REQ   = 0xffffffffUL;mb();
+
+	outb(0x11,0xA0);
+	outb(0x08,0xA1);
+	outb(0x02,0xA1);
+	outb(0x01,0xA1);
+	outb(0xFF,0xA1);
+	
+	outb(0x11,0x20);
+	outb(0x00,0x21);
+	outb(0x04,0x21);
+	outb(0x01,0x21);
+	outb(0xFF,0x21);
+	
+	/* Send -INTA pulses to clear any pending interrupts ...*/
+	temp = *(volatile unsigned int *) IACK_SC;
+	
+	/* Finish writing the 82C59A PIC Operation Control Words */
+	outb(0x20,0xA0);
+	outb(0x20,0x20);
+	
+	/* Turn on the interrupt controller, the timer interrupt  */
+	enable_irq(16 + 7);     /* enable ISA PIC cascade */
+	enable_irq(0);          /* enable timer */
+#endif /* RUFFIAN */
+
+#ifdef CONFIG_ALPHA_TAKARA
+	{
+		unsigned int ctlreg = inl(0x500);
+		ctlreg &= ~0x8000;     /* return to non-accelerated mode */
+		outw(ctlreg >> 16, 0x502);
+		outw(ctlreg & 0xFFFF, 0x500);
+		ctlreg = 0x05107c00;   /* enable the PCI interrupt register */
+		printk("Setting to 0x%08x\n", ctlreg);
+		outw(ctlreg >> 16, 0x502);
+		outw(ctlreg & 0xFFFF, 0x500);
+	}
+#endif /* TAKARA */
+
+	/* and finally, everyone but SABLE does this */
+	enable_irq(2);		/* enable 2nd PIC cascade */
+
+#endif /* SABLE */
 }

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