summaryrefslogtreecommitdiff
path: root/sys/arch/macppc
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2016-07-04 09:30:19 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2016-07-04 09:30:19 +0000
commit57d0ae3281583ba663d1c0429e061c7ae1779117 (patch)
treed163f994f427d9188ef6ac3b8799570f2991e6a5 /sys/arch/macppc
parent60182bff1635bc9fff8c90aee5f5b4df2889d4f2 (diff)
On Quad-G5 make hpb(4) attach first when iterating PCI buses.
This allows openpic(4) to properly map interrupt for the devices instead of possibly dereferencing garbage. Found the hardway by and ok jmatthew@
Diffstat (limited to 'sys/arch/macppc')
-rw-r--r--sys/arch/macppc/pci/pci_machdep.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/sys/arch/macppc/pci/pci_machdep.c b/sys/arch/macppc/pci/pci_machdep.c
index fdb522ae2fc..169899c8ac9 100644
--- a/sys/arch/macppc/pci/pci_machdep.c
+++ b/sys/arch/macppc/pci/pci_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pci_machdep.c,v 1.6 2015/03/30 13:54:14 mpi Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.7 2016/07/04 09:30:18 mpi Exp $ */
/*
* Copyright (c) 2013 Martin Pieuchot
@@ -247,6 +247,7 @@ ofw_enumerate_pcibus(struct pci_softc *sc,
pci_chipset_tag_t pc = sc->sc_pc;
struct ofw_pci_register reg;
int len, node, b, d, f, ret;
+ uint32_t val = 0;
char compat[32];
pcireg_t bhlcr;
pcitag_t tag;
@@ -265,10 +266,50 @@ ofw_enumerate_pcibus(struct pci_softc *sc,
return (ret);
}
+ /*
+ * An HT-PCI bridge is needed for interrupt mapping, attach it first
+ */
+ if (len > 0 && strcmp(compat, "u3-ht") == 0) {
+ int snode;
+
+ for (snode = OF_child(node); snode; snode = OF_peer(snode)) {
+ val = 0;
+ if ((OF_getprop(snode, "shasta-interrupt-sequencer",
+ &val, sizeof(val)) < sizeof(val)) || val != 1)
+ continue;
+
+ if (OF_getprop(snode, "reg", &reg, sizeof(reg))
+ < sizeof(reg))
+ continue;
+
+ b = OFW_PCI_PHYS_HI_BUS(reg.phys_hi);
+ d = OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi);
+ f = OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi);
+
+ tag = PCITAG_CREATE(snode, b, d, f);
+
+ bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
+ if (PCI_HDRTYPE_TYPE(bhlcr) > 2)
+ continue;
+
+ ret = pci_probe_device(sc, tag, match, pap);
+ if (match != NULL && ret != 0)
+ return (ret);
+ }
+ }
+
for (node = OF_child(node); node; node = OF_peer(node)) {
if (OF_getprop(node, "reg", &reg, sizeof(reg)) < sizeof(reg))
continue;
+ /*
+ * Skip HT-PCI bridge, it has been attached before.
+ */
+ val = 0;
+ if ((OF_getprop(node, "shasta-interrupt-sequencer", &val,
+ sizeof(val)) >= sizeof(val)) && val == 1)
+ continue;
+
b = OFW_PCI_PHYS_HI_BUS(reg.phys_hi);
d = OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi);
f = OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi);