diff options
author | jhb <jhb@FreeBSD.org> | 2002-08-26 15:23:52 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2002-08-26 15:23:52 +0000 |
commit | 15f443149e7389b54e42173f1ae4a36dc6ffaff5 (patch) | |
tree | a5ad4cc7cb5c0003e6adc11941b43c0631029ea8 /sys/dev | |
parent | 76ee9d6272c26471e38c81e39273139854083d0d (diff) | |
download | FreeBSD-src-15f443149e7389b54e42173f1ae4a36dc6ffaff5.zip FreeBSD-src-15f443149e7389b54e42173f1ae4a36dc6ffaff5.tar.gz |
Various changes to make it easier to subclass the PCI bus device.
- Make the pci devclass a global variable.
- Add child devices in pci_attach() instead of pci_probe(). Change
pci_probe() to just check for a valid bus number from the associated
bridge and return -1000 if successful. This allows subclasses of the
PCI bus driver to override the generic driver.
- Move the code to load the vendor data into its own public function.
Really though, doing this at attach is just plain wrong. This should
really be done in the module load routine instead. As a side effect,
the 'busno' variable in pci_attach() is now no longer static (minor
bug that was harmless so far.)
- Change pci_add_children() to take an extra argument that is the size of
the device info structure passed to pci_read_device() and make it public
so subclasses of the PCI bus can call it in their attach routines.
- Move the bits to attach a probed PCI child to a PCI bus into a global
pci_add_child() function. This will allow subclasses that can detect
a PCI device not found in the normal PCI probe to add those devices in
their own attach routine. (I have seen this in the ACPI tree on my
laptop for example.) As a side effect, change the static function
pci_add_resources() to get the busno, slot, and func from the passed
in dinfo structure instead of requiring them as function arguments.
Tested on: i386, alpha, ia64, sparc64
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/pci.c | 86 | ||||
-rw-r--r-- | sys/dev/pci/pci_private.h | 5 |
2 files changed, 61 insertions, 30 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 1a2119b..96553cf 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -73,10 +73,9 @@ static int pci_porten(device_t pcib, int b, int s, int f); static int pci_memen(device_t pcib, int b, int s, int f); static int pci_add_map(device_t pcib, int b, int s, int f, int reg, struct resource_list *rl); -static void pci_add_resources(device_t pcib, int b, int s, int f, - device_t dev); -static void pci_add_children(device_t dev, int busno); +static void pci_add_resources(device_t pcib, device_t dev); static int pci_probe(device_t dev); +static int pci_attach(device_t dev); static int pci_describe_parse_line(char **ptr, int *vendor, int *device, char **desc); static char *pci_describe_device(device_t dev); @@ -85,7 +84,7 @@ static int pci_modevent(module_t mod, int what, void *arg); static device_method_t pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pci_probe), - DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_attach, pci_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), @@ -127,7 +126,7 @@ static driver_t pci_driver = { 0, /* no softc */ }; -static devclass_t pci_devclass; +devclass_t pci_devclass; DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0); DRIVER_MODULE(pci, acpi_pcib, pci_driver, pci_devclass, pci_modevent, 0); MODULE_VERSION(pci, 1); @@ -741,14 +740,17 @@ pci_add_map(device_t pcib, int b, int s, int f, int reg, } static void -pci_add_resources(device_t pcib, int b, int s, int f, device_t dev) +pci_add_resources(device_t pcib, device_t dev) { struct pci_devinfo *dinfo = device_get_ivars(dev); pcicfgregs *cfg = &dinfo->cfg; struct resource_list *rl = &dinfo->resources; struct pci_quirk *q; - int i; + int b, i, f, s; + b = cfg->bus; + s = cfg->slot; + f = cfg->func; for (i = 0; i < cfg->nummaps;) { i += pci_add_map(pcib, b, s, f, PCIR_MAPS + i*4, rl); } @@ -773,44 +775,59 @@ pci_add_resources(device_t pcib, int b, int s, int f, device_t dev) } } -static void -pci_add_children(device_t dev, int busno) +void +pci_add_children(device_t dev, int busno, size_t dinfo_size) { device_t pcib = device_get_parent(dev); + struct pci_devinfo *dinfo; int maxslots; - int s, f; + int s, f, pcifunchigh; - maxslots = PCIB_MAXSLOTS(pcib); - + KASSERT(dinfo_size >= sizeof(struct pci_devinfo), + ("dinfo_size too small")); + maxslots = PCIB_MAXSLOTS(pcib); for (s = 0; s <= maxslots; s++) { - int pcifunchigh = 0; + pcifunchigh = 0; for (f = 0; f <= pcifunchigh; f++) { - struct pci_devinfo *dinfo = pci_read_device(pcib, - busno, s, f, sizeof(struct pci_devinfo)); + dinfo = pci_read_device(pcib, busno, s, f, dinfo_size); if (dinfo != NULL) { if (dinfo->cfg.mfdev) pcifunchigh = PCI_FUNCMAX; - - dinfo->cfg.dev = device_add_child(dev, NULL, -1); - device_set_ivars(dinfo->cfg.dev, dinfo); - pci_add_resources(pcib, busno, s, f, - dinfo->cfg.dev); - pci_print_verbose(dinfo); + pci_add_child(dev, dinfo); } } } } +void +pci_add_child(device_t bus, struct pci_devinfo *dinfo) +{ + device_t pcib; + + pcib = device_get_parent(bus); + dinfo->cfg.dev = device_add_child(bus, NULL, -1); + device_set_ivars(dinfo->cfg.dev, dinfo); + pci_add_resources(pcib, dinfo->cfg.dev); + pci_print_verbose(dinfo); +} + static int pci_probe(device_t dev) { - static int once, busno; - caddr_t vendordata, info; + if (pcib_get_bus(dev) < 0) + return (ENXIO); + device_set_desc(dev, "PCI bus"); - if (bootverbose) - device_printf(dev, "physical bus=%d\n", pcib_get_bus(dev)); + /* Allow other subclasses to override this driver. */ + return (-1000); +} + +static int +pci_attach(device_t dev) +{ + int busno; /* * Since there can be multiple independantly numbered PCI @@ -819,9 +836,20 @@ pci_probe(device_t dev) * pcib what our bus number is. */ busno = pcib_get_bus(dev); - if (busno < 0) - return (ENXIO); - pci_add_children(dev, busno); + if (bootverbose) + device_printf(dev, "physical bus=%d\n", busno); + + pci_add_children(dev, busno, sizeof(struct pci_devinfo)); + + pci_load_vendor_data(); + return (bus_generic_attach(dev)); +} + +void +pci_load_vendor_data(void) +{ + caddr_t vendordata, info; + static int once; if (!once) { make_dev(&pcicdev, 0, UID_ROOT, GID_WHEEL, 0644, "pci"); @@ -836,8 +864,6 @@ pci_probe(device_t dev) } once++; } - - return (0); } int diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h index cb43cef..c82e3f5 100644 --- a/sys/dev/pci/pci_private.h +++ b/sys/dev/pci/pci_private.h @@ -37,6 +37,10 @@ * it with "subclass" busses. A more generic subclassing mechanism would * be nice, but is not present in the tree at this time. */ +extern devclass_t pci_devclass; + +void pci_add_children(device_t dev, int busno, size_t dinfo_size); +void pci_add_child(device_t bus, struct pci_devinfo *dinfo); int pci_print_child(device_t dev, device_t child); void pci_probe_nomatch(device_t dev, device_t child); int pci_read_ivar(device_t dev, device_t child, int which, @@ -64,5 +68,6 @@ struct pci_devinfo *pci_read_device(device_t pcib, int b, int s, int f, size_t size); void pci_print_verbose(struct pci_devinfo *dinfo); int pci_freecfg(struct pci_devinfo *dinfo); +void pci_load_vendor_data(void); #endif /* _PCI_PRIVATE_H_ */ |