patch-2.3.8 linux/arch/alpha/kernel/sys_takara.c

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

diff -u --recursive --new-file v2.3.7/linux/arch/alpha/kernel/sys_takara.c linux/arch/alpha/kernel/sys_takara.c
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the TAKARA.
  */
@@ -30,11 +30,21 @@
 #include "machvec.h"
 
 
-/*
- * WARNING WARNING WARNING
- *
- * This port is missing an update_irq_hw implementation.
- */
+static void 
+takara_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+	unsigned int regaddr;
+
+	if (irq <= 15) {
+		if (irq <= 7)
+			outb(mask, 0x21);	/* ISA PIC1 */
+		else
+			outb(mask >> 8, 0xA1);	/* ISA PIC2 */
+	} else if (irq <= 31) {
+		regaddr = 0x510 + ((irq - 16) & 0x0c);
+		outl((mask >> ((irq - 16) & 0x0c)) & 0xf0000Ul, regaddr);
+	}
+}
 
 static void
 takara_device_interrupt(unsigned long vector, struct pt_regs *regs)
@@ -68,28 +78,45 @@
 		if (intstatus & 4) handle_irq(16+2, 16+2, regs);
 		if (intstatus & 2) handle_irq(16+1, 16+1, regs);
 		if (intstatus & 1) handle_irq(16+0, 16+0, regs);
-	} else
+	} else {
 		isa_device_interrupt (vector, regs);
+	}
+}
+
+static void 
+takara_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+	int irq = (vector - 0x800) >> 4;
+
+	if (irq > 15)
+		irq = ((vector - 0x800) >> 6) + 12;
+	
+	handle_irq(irq, irq, regs);
 }
 
 static void __init
 takara_init_irq(void)
 {
-	unsigned int ctlreg;
-
 	STANDARD_INIT_IRQ_PROLOG;
 
-	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 */
-	outw(ctlreg >> 16, 0x502);
-	outw(ctlreg & 0xFFFF, 0x500);
+	if (alpha_using_srm)
+		alpha_mv.device_interrupt = takara_srm_device_interrupt;
+
+	if (!alpha_using_srm) {
+		unsigned int ctlreg = inl(0x500);
+
+		/* Return to non-accelerated mode.  */
+		ctlreg &= ~0x8000;
+		outl(ctlreg, 0x500);
+
+		/* Enable the PCI interrupt register.  */
+		ctlreg = 0x05107c00;
+		outl(ctlreg, 0x500);
+	}
+
 	enable_irq(2);
 }
 
-
 /*
  * The Takara has PCI devices 1, 2, and 3 configured to slots 20,
  * 19, and 18 respectively, in the default configuration. They can
@@ -123,12 +150,35 @@
 	return COMMON_TABLE_LOOKUP;
 }
 
+static int __init
+takara_swizzle(struct pci_dev *dev, int *pinp)
+{
+	int slot = PCI_SLOT(dev->devfn);
+	int pin = *pinp;
+	unsigned int ctlreg = inl(0x500);
+	unsigned int busslot = PCI_SLOT(dev->bus->self->devfn);
+
+	/* Check first for built-in bridges.  */
+	if (busslot > 16 && ((1<<(36-busslot)) & ctlreg)) {
+		if (pin == 1)
+			pin += (20 - busslot);
+		else {
+			/* Must be a card-based bridge.  */
+			printk(KERN_WARNING "takara_swizzle: cannot handle "
+			       "card-bridge behind builtin bridge yet.\n");
+		}
+	}
+
+	*pinp = pin;
+	return slot;
+}
+
 static void __init
 takara_pci_fixup(void)
 {
 	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(takara_map_irq, common_swizzle);
-	enable_ide(0x26e);
+	common_pci_fixup(takara_map_irq, takara_swizzle);
+	/* enable_ide(0x26e); */
 }
 
 
@@ -147,7 +197,7 @@
 
 	nr_irqs:		20,
 	irq_probe_mask:		_PROBE_MASK(20),
-	update_irq_hw:		NULL,
+	update_irq_hw:		takara_update_irq_hw,
 	ack_irq:		generic_ack_irq,
 	device_interrupt:	takara_device_interrupt,
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)