aboutsummaryrefslogtreecommitdiff
path: root/sys/i386/pci/pci_bus.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2000-09-05 00:53:34 +0000
committerPeter Wemm <peter@FreeBSD.org>2000-09-05 00:53:34 +0000
commit4d8ea19f7c6400fce602cf6667a9c199ea336592 (patch)
tree74bf4b0d512192840fd7962c12518a38b5126c0c /sys/i386/pci/pci_bus.c
parent741f2944a923416890811b3a591d2e8d0e6e1710 (diff)
downloadsrc-4d8ea19f7c6400fce602cf6667a9c199ea336592.tar.gz
src-4d8ea19f7c6400fce602cf6667a9c199ea336592.zip
Catch a few more bogosities in certain chipsets before they mess us up.
Some have dual host->PCI bridges for the same logical pci bus (!), eg: some of the RCC chipsets. This is a 32/64 bit 33/66MHz and dual pci voltage motherboard so persumably there are electical or signalling differences but they are otherwise the same logical bus. The new PCI probe code however was getting somewhat upset about it and ended up creating two pci bridges to the same logical bus, which caused devices on that logical bus to appear and be probed twice. The ACPI data on this box correctly identifies this stuff, so bring on ACPI! :-)
Notes
Notes: svn path=/head/; revision=65459
Diffstat (limited to 'sys/i386/pci/pci_bus.c')
-rw-r--r--sys/i386/pci/pci_bus.c108
1 files changed, 89 insertions, 19 deletions
diff --git a/sys/i386/pci/pci_bus.c b/sys/i386/pci/pci_bus.c
index 41e222600b32..2dd66945609e 100644
--- a/sys/i386/pci/pci_bus.c
+++ b/sys/i386/pci/pci_bus.c
@@ -595,6 +595,8 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
u_int32_t id;
u_int8_t class, subclass, busnum;
const char *s;
+ device_t *devs;
+ int ndevs, i;
id = nexus_pcib_read_config(0, bus, slot, func,
PCIR_DEVVENDOR, 4);
@@ -608,26 +610,48 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
s = nexus_pcib_is_host_bridge(bus, slot, func,
id, class, subclass,
&busnum);
- if (s) {
- /*
- * Add at priority 100 to make sure we
- * go after any motherboard resources
- */
- child = BUS_ADD_CHILD(parent, 100,
- "pcib", busnum);
- device_set_desc(child, s);
-
- ivar = malloc(sizeof ivar[0], M_DEVBUF,
- M_NOWAIT);
- if (ivar == NULL)
- panic("out of memory");
- device_set_ivars(child, ivar);
- ivar[0] = busnum;
-
- found = 1;
- if (id == 0x12258086)
- found824xx = 1;
+ if (s == NULL)
+ continue;
+
+ /*
+ * Check to see if the physical bus has already
+ * been seen. Eg: hybrid 32 and 64 bit host
+ * bridges to the same logical bus.
+ */
+ if (device_get_children(parent, &devs, &ndevs) == 0) {
+ for (i = 0; s != NULL && i < ndevs; i++) {
+ if (strcmp(device_get_name(devs[i]),
+ "pcib") != 0)
+ continue;
+ ivar = device_get_ivars(devs[i]);
+ if (ivar == NULL)
+ continue;
+ if (busnum == *ivar)
+ s = NULL;
+ }
+ free(devs, M_TEMP);
}
+
+ if (s == NULL)
+ continue;
+ /*
+ * Add at priority 100 to make sure we
+ * go after any motherboard resources
+ */
+ child = BUS_ADD_CHILD(parent, 100,
+ "pcib", busnum);
+ device_set_desc(child, s);
+
+ ivar = malloc(sizeof ivar[0], M_DEVBUF,
+ M_NOWAIT);
+ if (ivar == NULL)
+ panic("out of memory");
+ device_set_ivars(child, ivar);
+ ivar[0] = busnum;
+
+ found = 1;
+ if (id == 0x12258086)
+ found824xx = 1;
}
}
if (found824xx && bus == 0) {
@@ -734,6 +758,52 @@ static driver_t nexus_pcib_driver = {
DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0);
+
+/*
+ * Provide a device to "eat" the host->pci bridges that we dug up above
+ * and stop them showing up twice on the probes. This also stops them
+ * showing up as 'none' in pciconf -l.
+ */
+static int
+pci_hostb_probe(device_t dev)
+{
+
+ if (pci_get_class(dev) == PCIC_BRIDGE &&
+ pci_get_subclass(dev) == PCIS_BRIDGE_HOST) {
+ device_set_desc(dev, "Host to PCI bridge");
+ device_quiet(dev);
+ return 0;
+ }
+ return ENXIO;
+}
+
+static int
+pci_hostb_attach(device_t dev)
+{
+
+ return 0;
+}
+
+static device_method_t pci_hostb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, pci_hostb_probe),
+ DEVMETHOD(device_attach, pci_hostb_attach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ { 0, 0 }
+};
+static driver_t pci_hostb_driver = {
+ "hostb",
+ pci_hostb_methods,
+ 1,
+};
+static devclass_t pci_hostb_devclass;
+
+DRIVER_MODULE(hostb, pci, pci_hostb_driver, pci_hostb_devclass, 0, 0);
+
+
/*
* Install placeholder to claim the resources owned by the
* PCI bus interface. This could be used to extract the