diff options
author | Peter Wemm <peter@FreeBSD.org> | 2000-09-05 00:53:34 +0000 |
---|---|---|
committer | Peter Wemm <peter@FreeBSD.org> | 2000-09-05 00:53:34 +0000 |
commit | 4d8ea19f7c6400fce602cf6667a9c199ea336592 (patch) | |
tree | 74bf4b0d512192840fd7962c12518a38b5126c0c /sys/i386/pci/pci_bus.c | |
parent | 741f2944a923416890811b3a591d2e8d0e6e1710 (diff) | |
download | src-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.c | 108 |
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 |