patch-2.1.132 linux/include/asm-arm/arch-ebsa285/irq.h

Next file: linux/include/asm-arm/arch-ebsa285/irqs.h
Previous file: linux/include/asm-arm/arch-ebsa285/ide.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-ebsa285/irq.h linux/include/asm-arm/arch-ebsa285/irq.h
@@ -5,8 +5,11 @@
  *
  * Changelog:
  *   22-08-1998	RMK	Restructured IRQ routines
+ *   03-09-1998	PJB	Merged CATS support
  */
 
+#include <linux/config.h>
+
 static void ebsa285_mask_irq(unsigned int irq)
 {
 	*CSR_IRQ_DISABLE = 1 << irq;
@@ -16,7 +19,73 @@
 {
 	*CSR_IRQ_ENABLE = 1 << irq;
 }
+
+#ifdef CONFIG_CATS
+
+/*
+ * This contains the irq mask for both 8259A irq controllers,
+ */
+static unsigned int isa_irq_mask = 0xffff;
+
+#define cached_21	(isa_irq_mask & 0xff)
+#define cached_A1	((isa_irq_mask >> 8) & 0xff)
+
+#define update_8259(_irq)			\
+	if ((_irq) & 8)				\
+		outb(cached_A1, 0xa1);		\
+	else					\
+		outb(cached_21, 0x21);
+
+static void isa_interrupt(int irq, void *h, struct pt_regs *regs)
+{
+	asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
+	unsigned int irqbits = inb(0x20) | (inb(0xa0) << 8), irqnr = 0;
+	irqbits &= ~(1<<2);	/* don't try to service the cascade */
+	while (irqbits) {
+		if (irqbits & 1)
+			do_IRQ(32 + irqnr, regs);
+		irqbits >>= 1;
+		irqnr++;
+	}
+}
+
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+
+static struct irqaction irq_isa = 
+		{ isa_interrupt, SA_INTERRUPT, 0, "ISA PIC", NULL, NULL };
+static struct irqaction irq_cascade = 
+		{ no_action, 0, 0, "cascade", NULL, NULL };
+
+static void cats_mask_and_ack_isa_irq(unsigned int irq)
+{
+	isa_irq_mask |= (1 << (irq - 32));
+	update_8259(irq);
+	if (irq & 8) {
+		inb(0xA1);	/* DUMMY */
+		outb(cached_A1,0xA1);
+		outb(0x62,0x20);	/* Specific EOI to cascade */
+		outb(0x20,0xA0);
+	} else {
+		inb(0x21);	/* DUMMY */
+		outb(cached_21,0x21);
+		outb(0x20,0x20);
+	}
+}
+
+static void cats_mask_isa_irq(unsigned int irq)
+{
+	isa_irq_mask |= (1 << (irq - 32));
+	update_8259(irq);
+}
+
+static void cats_unmask_isa_irq(unsigned int irq)
+{
+	isa_irq_mask &= ~(1 << (irq - 32));
+	update_8259(irq);
+}
  
+#endif 
+
 static __inline__ void irq_init_irq(void)
 {
 	int irq;
@@ -27,8 +96,45 @@
 	for (irq = 0; irq < NR_IRQS; irq++) {
 		irq_desc[irq].valid	= 1;
 		irq_desc[irq].probe_ok	= 1;
-		irq_desc[irq].mask_ack	= ebsa285_mask_irq;
-		irq_desc[irq].mask	= ebsa285_mask_irq;
-		irq_desc[irq].unmask	= ebsa285_unmask_irq;
+#ifdef CONFIG_CATS
+		if (machine_is_cats() && IRQ_IS_ISA(irq)) {
+			irq_desc[irq].mask_ack	= cats_mask_and_ack_isa_irq;
+			irq_desc[irq].mask	= cats_mask_isa_irq;
+			irq_desc[irq].unmask	= cats_unmask_isa_irq;
+		} else
+#endif
+		{
+			irq_desc[irq].mask_ack	= ebsa285_mask_irq;
+			irq_desc[irq].mask	= ebsa285_mask_irq;
+			irq_desc[irq].unmask	= ebsa285_unmask_irq;
+		}
+	}
+
+#ifdef CONFIG_CATS
+	if (machine_is_cats()) {
+		request_region(0x20, 2, "pic1");
+		request_region(0xa0, 2, "pic2");
+
+		/* set up master 8259 */
+		outb(0x11, 0x20);
+		outb(0, 0x21);
+		outb(1<<2, 0x21);
+		outb(0x1, 0x21);
+		outb(0xff, 0x21);
+		outb(0x68, 0x20);
+		outb(0xa, 0x20);
+		
+		/* set up slave 8259 */
+		outb(0x11, 0xa0);
+		outb(0, 0xa1);
+		outb(2, 0xa1);
+		outb(0x1, 0xa1);
+		outb(0xff, 0xa1);
+		outb(0x68, 0xa0);
+		outb(0xa, 0xa0);
+
+		setup_arm_irq(IRQ_ISA_PIC, &irq_isa);
+		setup_arm_irq(IRQ_ISA_CASCADE, &irq_cascade);
 	}
+#endif
 }

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