summaryrefslogtreecommitdiffstats
path: root/arch/alpha/kernel/sys_takara.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha/kernel/sys_takara.c')
-rw-r--r--arch/alpha/kernel/sys_takara.c90
1 files changed, 70 insertions, 20 deletions
diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c
index 95adc3b39..c554a9fa1 100644
--- a/arch/alpha/kernel/sys_takara.c
+++ b/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 @@ takara_device_interrupt(unsigned long vector, struct pt_regs *regs)
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 @@ takara_map_irq(struct pci_dev *dev, int slot, int pin)
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 @@ struct alpha_machine_vector takara_mv __initmv = {
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,