summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/ebus.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/ebus.c')
-rw-r--r--arch/sparc64/kernel/ebus.c82
1 files changed, 63 insertions, 19 deletions
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
index 0b3d16007..903bcf445 100644
--- a/arch/sparc64/kernel/ebus.c
+++ b/arch/sparc64/kernel/ebus.c
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.44 1999/09/05 09:28:09 ecd Exp $
+/* $Id: ebus.c,v 1.46 1999/11/19 05:52:48 davem Exp $
* ebus.c: PCI to EBus bridge device.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -22,9 +22,6 @@
struct linux_ebus *ebus_chain = 0;
-extern void prom_ebus_ranges_init(struct linux_ebus *);
-extern void prom_ebus_intmap_init(struct linux_ebus *);
-
#ifdef CONFIG_SUN_OPENPROMIO
extern int openprom_init(void);
#endif
@@ -49,15 +46,49 @@ static inline void *ebus_alloc(size_t size)
return mem;
}
-void __init ebus_intmap_match(struct linux_ebus *ebus,
- struct linux_prom_registers *reg,
- int *interrupt)
+static void __init ebus_ranges_init(struct linux_ebus *ebus)
+{
+ int success;
+
+ ebus->num_ebus_ranges = 0;
+ success = prom_getproperty(ebus->prom_node, "ranges",
+ (char *)ebus->ebus_ranges,
+ sizeof(ebus->ebus_ranges));
+ if (success != -1)
+ ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges));
+}
+
+static void __init ebus_intmap_init(struct linux_ebus *ebus)
+{
+ int success;
+
+ ebus->num_ebus_intmap = 0;
+ success = prom_getproperty(ebus->prom_node, "interrupt-map",
+ (char *)ebus->ebus_intmap,
+ sizeof(ebus->ebus_intmap));
+ if (success == -1)
+ return;
+
+ ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap));
+
+ success = prom_getproperty(ebus->prom_node, "interrupt-map-mask",
+ (char *)&ebus->ebus_intmask,
+ sizeof(ebus->ebus_intmask));
+ if (success == -1) {
+ prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__);
+ prom_halt();
+ }
+}
+
+int __init ebus_intmap_match(struct linux_ebus *ebus,
+ struct linux_prom_registers *reg,
+ int *interrupt)
{
unsigned int hi, lo, irq;
int i;
if (!ebus->num_ebus_intmap)
- return;
+ return 0;
hi = reg->which_io & ebus->ebus_intmask.phys_hi;
lo = reg->phys_addr & ebus->ebus_intmask.phys_lo;
@@ -67,13 +98,10 @@ void __init ebus_intmap_match(struct linux_ebus *ebus,
(ebus->ebus_intmap[i].phys_lo == lo) &&
(ebus->ebus_intmap[i].interrupt == irq)) {
*interrupt = ebus->ebus_intmap[i].cinterrupt;
- return;
+ return 0;
}
}
-
- prom_printf("ebus: IRQ [%08x.%08x.%08x] not found in interrupt-map\n",
- reg->which_io, reg->phys_addr, *interrupt);
- prom_halt();
+ return -1;
}
void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
@@ -139,8 +167,16 @@ void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
struct pci_pbm_info *pbm = dev->bus->parent;
struct pci_controller_info *p = pbm->parent;
- ebus_intmap_match(dev->bus, preg, &irqs[i]);
- dev->irqs[i] = p->irq_build(p, dev->bus->self, irqs[i]);
+ if (ebus_intmap_match(dev->bus, preg, &irqs[i]) != -1) {
+ dev->irqs[i] = p->irq_build(p,
+ dev->bus->self,
+ irqs[i]);
+ } else {
+ /* If we get a bogus interrupt property, just
+ * record the raw value instead of punting.
+ */
+ dev->irqs[i] = irqs[i];
+ }
}
}
}
@@ -194,8 +230,16 @@ void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
struct pci_pbm_info *pbm = dev->bus->parent;
struct pci_controller_info *p = pbm->parent;
- ebus_intmap_match(dev->bus, &regs[0], &irqs[i]);
- dev->irqs[i] = p->irq_build(p, dev->bus->self, irqs[i]);
+ if (ebus_intmap_match(dev->bus, &regs[0], &irqs[i]) != -1) {
+ dev->irqs[i] = p->irq_build(p,
+ dev->bus->self,
+ irqs[i]);
+ } else {
+ /* If we get a bogus interrupt property, just
+ * record the raw value instead of punting.
+ */
+ dev->irqs[i] = irqs[i];
+ }
}
}
@@ -295,8 +339,8 @@ void __init ebus_init(void)
/* NOTE: Cache line size is in 32-bit word units. */
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 64/sizeof(u32));
- prom_ebus_ranges_init(ebus);
- prom_ebus_intmap_init(ebus);
+ ebus_ranges_init(ebus);
+ ebus_intmap_init(ebus);
nd = prom_getchild(ebusnd);
if (!nd)