--- FreeBSD/src/sys/kern/subr_bus.c Sat Jul 8 11:06:14 2006 +++ p4/arm/src/sys/kern/subr_bus.c Mon Jul 10 16:49:30 2006 @@ -1690,10 +1697,10 @@ int device_probe_child(device_t dev, device_t child) { - devclass_t dc; + devclass_t dc, childdc; driverlink_t best = 0; driverlink_t dl; - int result, pri = 0; + int unit, result, pri = 0; int hasclass = (child->devclass != 0); GIANT_REQUIRED; @@ -1717,7 +1724,18 @@ device_set_driver(child, dl->driver); if (!hasclass) device_set_devclass(child, dl->driver->name); - + if (child->flags & DF_WILDCARD) { + unit = child->unit; + BUS_HINT_DEVICE_UNIT(dev, child, &unit); + if (unit != child->unit) { + childdc = child->devclass; + devclass_delete_device(childdc, child); + if (childdc->devices[unit] != NULL) + continue; + child->unit = unit; + devclass_add_device(childdc, child); + } + } /* Fetch any flags for the device before probing. */ resource_int_value(dl->driver->name, child->unit, "flags", &child->devflags); @@ -1797,6 +1815,16 @@ if (!child->devclass) device_set_devclass(child, best->driver->name); device_set_driver(child, best->driver); + if (child->flags & DF_WILDCARD) { + unit = child->unit; + BUS_HINT_DEVICE_UNIT(dev, child, &unit); + if (unit != child->unit) { + childdc = child->devclass; + devclass_delete_device(childdc, child); + child->unit = unit; + devclass_add_device(childdc, child); + } + } resource_int_value(best->driver->name, child->unit, "flags", &child->devflags); @@ -2480,33 +2508,6 @@ return (DEVICE_SHUTDOWN(dev)); } -/** - * @brief Set the unit number of a device - * - * This function can be used to override the unit number used for a - * device (e.g. to wire a device to a pre-configured unit number). - */ -int -device_set_unit(device_t dev, int unit) -{ - devclass_t dc; - int err; - - dc = device_get_devclass(dev); - if (unit < dc->maxunit && dc->devices[unit]) - return (EBUSY); - err = devclass_delete_device(dc, dev); - if (err) - return (err); - dev->unit = unit; - err = devclass_add_device(dc, dev); - if (err) - return (err); - - bus_data_generation_update(); - return (0); -} - /*======================================*/ /* * Some useful method implementations to make life easier for bus drivers. --- FreeBSD/src/sys/kern/bus_if.m Sat Jul 8 11:06:14 2006 +++ p4/arm/src/sys/kern/bus_if.m Mon Jul 10 15:37:30 2006 @@ -528,4 +528,21 @@ device_t _dev; const char * _dname; int _dunit; +}; + +/** + * @brief Asks the bus to give us a hand hinting this device. + * + * Before we probe a child of a bus that's been wildcarded, we call the + * bus to see if there's any 'hints' as to unit number for the child + * presented for this kind of device. + * + * @param _dev the bus device + * @param _child child to hint + * @param _dunit the unit number of the device + */ +METHOD void hint_device_unit { + device_t _dev; + device_t _child; + int *_dunit; }; --- FreeBSD/src/sys/sys/bus.h Sat Jul 8 11:06:15 2006 +++ p4/arm/src/sys/sys/bus.h Sun Jul 9 02:14:59 2006 @@ -375,7 +375,6 @@ int device_set_driver(device_t dev, driver_t *driver); void device_set_flags(device_t dev, u_int32_t flags); void device_set_softc(device_t dev, void *softc); -int device_set_unit(device_t dev, int unit); /* XXX DONT USE XXX */ int device_shutdown(device_t dev); void device_unbusy(device_t dev); void device_verbose(device_t dev); Only in FreeBSD/src/sys/dev/pci: CVS diff -u FreeBSD/src/sys/dev/pci/pci.c p4/arm/src/sys/dev/pci/pci.c --- FreeBSD/src/sys/dev/pci/pci.c Thu May 11 16:13:21 2006 +++ p4/arm/src/sys/dev/pci/pci.c Mon Jul 10 17:23:21 2006 @@ -119,6 +119,7 @@ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_child_pnpinfo_str, pci_child_pnpinfo_str_method), DEVMETHOD(bus_child_location_str, pci_child_location_str_method), + DEVMETHOD(bus_hint_device_unit, pci_hint_device_unit), /* PCI interface */ DEVMETHOD(pci_read_config, pci_read_config_method), @@ -1997,6 +1998,21 @@ cfg->subvendor, cfg->subdevice, cfg->baseclass, cfg->subclass, cfg->progif); return (0); +} + +void +pci_hint_device_unit(device_t bus, device_t child, int *unit) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + int i; + char buf[10]; + + snprintf(buf, sizeof(buf), "%d:%d:%d", dinfo->cfg.bus, dinfo->cfg.slot, + dinfo->cfg.func); + i = 0; + resource_find_dev(&i, device_get_name(child), unit, "location", buf); + + return; } int diff -u FreeBSD/src/sys/dev/pci/pci_private.h p4/arm/src/sys/dev/pci/pci_private.h --- FreeBSD/src/sys/dev/pci/pci_private.h Fri Jan 20 15:00:50 2006 +++ p4/arm/src/sys/dev/pci/pci_private.h Mon Jul 10 17:23:54 2006 @@ -76,6 +76,8 @@ char *buf, size_t buflen); int pci_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf, size_t buflen); +void pci_hint_device_unit(device_t bus, device_t child, + int *unit); int pci_assign_interrupt_method(device_t dev, device_t child); int pci_resume(device_t dev); int pci_suspend(device_t dev); diff -u FreeBSD/src/sys/dev/acpica/acpi.c p4/arm/src/sys/dev/acpica/acpi.c --- FreeBSD/src/sys/dev/acpica/acpi.c Sun Jun 11 21:35:29 2006 +++ p4/arm/src/sys/dev/acpica/acpi.c Mon Jul 10 17:33:55 2006 @@ -149,9 +149,10 @@ static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS); static int acpi_pm_func(u_long cmd, void *arg, ...); static int acpi_child_location_str_method(device_t acdev, device_t child, - char *buf, size_t buflen); + char *buf, size_t buflen); static int acpi_child_pnpinfo_str_method(device_t acdev, device_t child, - char *buf, size_t buflen); + char *buf, size_t buflen); +static void acpi_hint_device_unit(device_t bus, device_t child, int *unit); static device_method_t acpi_methods[] = { /* Device interface */ @@ -182,6 +183,7 @@ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_hint_device_unit, acpi_hint_device_unit), /* ACPI bus */ DEVMETHOD(acpi_id_probe, acpi_device_id_probe), @@ -810,6 +812,29 @@ return (0); } + +static void +acpi_hint_device_unit(device_t bus, device_t child, int *unit) +{ + int i; + char buf[10]; + char *kind = NULL; + u_long start, len; + + if (bus_get_resource(child, SYS_RES_IOPORT, 0, &start, &len) == 0) + kind = "port"; + else if (bus_get_resource(child, SYS_RES_MEMORY, 0, &start, &len) == 0) + kind = "maddr"; + if (kind == NULL) + return; + snprintf(buf, sizeof(buf), "0x%lx", start); + i = 0; + resource_find_dev(&i, device_get_name(child), unit, kind, buf); + // NOTE: We eat units on ANY bus, not just acpi because acpi + // should be a specialization of isa, but isn't atm. + return; +} + /* * Handle per-device ivars Only in FreeBSD/src/sys/dev/sio: CVS diff -u FreeBSD/src/sys/dev/sio/sio_pci.c p4/arm/src/sys/dev/sio/sio_pci.c --- FreeBSD/src/sys/dev/sio/sio_pci.c Sat May 28 22:42:25 2005 +++ p4/arm/src/sys/dev/sio/sio_pci.c Sun Jul 9 02:14:58 2006 @@ -43,7 +43,6 @@ #include static int sio_pci_attach(device_t dev); -static void sio_pci_kludge_unit(device_t dev); static int sio_pci_probe(device_t dev); static device_method_t sio_pci_methods[] = { @@ -101,37 +100,7 @@ id++; if (id->desc == NULL) return (ENXIO); - sio_pci_kludge_unit(dev); return (sioattach(dev, id->rid, 0UL)); -} - -/* - * Don't cut and paste this to other drivers. It is a horrible kludge - * which will fail to work and also be unnecessary in future versions. - */ -static void -sio_pci_kludge_unit(dev) - device_t dev; -{ - devclass_t dc; - int err; - int start; - int unit; - - unit = 0; - start = 0; - while (resource_int_value("sio", unit, "port", &start) == 0 && - start > 0) - unit++; - if (device_get_unit(dev) < unit) { - dc = device_get_devclass(dev); - while (devclass_get_device(dc, unit)) - unit++; - device_printf(dev, "moving to sio%d\n", unit); - err = device_set_unit(dev, unit); /* EVIL DO NOT COPY */ - if (err) - device_printf(dev, "error moving device %d\n", err); - } } static int