|
|
| version 1.16, 2004/04/01 08:41:24 | version 1.17, 2004/04/15 13:31:41 |
|---|---|
| Line 107 DEFINE_CLASS(null, null_methods, 0); | Line 107 DEFINE_CLASS(null, null_methods, 0); |
| static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses); | static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses); |
| static devclass_t | static devclass_t |
| devclass_find_internal(const char *classname, int create) | devclass_find_internal(const char *classname, const char *parentname, |
| int create) | |
| { | { |
| devclass_t dc; | devclass_t dc; |
| Line 117 devclass_find_internal(const char *class | Line 118 devclass_find_internal(const char *class |
| TAILQ_FOREACH(dc, &devclasses, link) | TAILQ_FOREACH(dc, &devclasses, link) |
| if (!strcmp(dc->name, classname)) | if (!strcmp(dc->name, classname)) |
| return(dc); | break; |
| PDEBUG(("%s not found%s", classname, (create? ", creating": ""))); | if (create && !dc) { |
| if (create) { | PDEBUG(("creating %s", classname)); |
| dc = malloc(sizeof(struct devclass) + strlen(classname) + 1, | dc = malloc(sizeof(struct devclass) + strlen(classname) + 1, |
| M_BUS, M_INTWAIT | M_ZERO); | M_BUS, M_INTWAIT | M_ZERO); |
| if (!dc) | if (!dc) |
| return NULL; | return(NULL); |
| dc->parent = NULL; | |
| dc->name = (char*) (dc + 1); | dc->name = (char*) (dc + 1); |
| strcpy(dc->name, classname); | strcpy(dc->name, classname); |
| dc->devices = NULL; | dc->devices = NULL; |
| Line 132 devclass_find_internal(const char *class | Line 134 devclass_find_internal(const char *class |
| TAILQ_INIT(&dc->drivers); | TAILQ_INIT(&dc->drivers); |
| TAILQ_INSERT_TAIL(&devclasses, dc, link); | TAILQ_INSERT_TAIL(&devclasses, dc, link); |
| } | } |
| if (parentname && dc && !dc->parent) | |
| dc->parent = devclass_find_internal(parentname, NULL, FALSE); | |
| return(dc); | return(dc); |
| } | } |
| Line 139 devclass_find_internal(const char *class | Line 143 devclass_find_internal(const char *class |
| devclass_t | devclass_t |
| devclass_create(const char *classname) | devclass_create(const char *classname) |
| { | { |
| return(devclass_find_internal(classname, TRUE)); | return(devclass_find_internal(classname, NULL, TRUE)); |
| } | } |
| devclass_t | devclass_t |
| devclass_find(const char *classname) | devclass_find(const char *classname) |
| { | { |
| return(devclass_find_internal(classname, FALSE)); | return(devclass_find_internal(classname, NULL, FALSE)); |
| } | } |
| int | int |
| Line 171 devclass_add_driver(devclass_t dc, drive | Line 175 devclass_add_driver(devclass_t dc, drive |
| /* | /* |
| * Make sure the devclass which the driver is implementing exists. | * Make sure the devclass which the driver is implementing exists. |
| */ | */ |
| devclass_find_internal(driver->name, TRUE); | devclass_find_internal(driver->name, NULL, TRUE); |
| dl->driver = driver; | dl->driver = driver; |
| TAILQ_INSERT_TAIL(&dc->drivers, dl, link); | TAILQ_INSERT_TAIL(&dc->drivers, dl, link); |
| Line 256 devclass_find_driver_internal(devclass_t | Line 260 devclass_find_driver_internal(devclass_t |
| return(NULL); | return(NULL); |
| } | } |
| driver_t * | kobj_class_t |
| devclass_find_driver(devclass_t dc, const char *classname) | devclass_find_driver(devclass_t dc, const char *classname) |
| { | { |
| driverlink_t dl; | driverlink_t dl; |
| Line 329 devclass_get_maxunit(devclass_t dc) | Line 333 devclass_get_maxunit(devclass_t dc) |
| return(dc->maxunit); | return(dc->maxunit); |
| } | } |
| void | |
| devclass_set_parent(devclass_t dc, devclass_t pdc) | |
| { | |
| dc->parent = pdc; | |
| } | |
| devclass_t | |
| devclass_get_parent(devclass_t dc) | |
| { | |
| return(dc->parent); | |
| } | |
| static int | static int |
| devclass_alloc_unit(devclass_t dc, int *unitp) | devclass_alloc_unit(devclass_t dc, int *unitp) |
| { | { |
| Line 441 make_device(device_t parent, const char | Line 457 make_device(device_t parent, const char |
| PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit)); | PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit)); |
| if (name != NULL) { | if (name != NULL) { |
| dc = devclass_find_internal(name, TRUE); | dc = devclass_find_internal(name, NULL, TRUE); |
| if (!dc) { | if (!dc) { |
| printf("make_device: can't find device class %s\n", name); | printf("make_device: can't find device class %s\n", name); |
| return(NULL); | return(NULL); |
| Line 619 device_probe_child(device_t dev, device_ | Line 635 device_probe_child(device_t dev, device_ |
| if (child->state == DS_ALIVE) | if (child->state == DS_ALIVE) |
| return(0); | return(0); |
| for (dl = first_matching_driver(dc, child); dl; | for (; dc; dc = dc->parent) { |
| dl = next_matching_driver(dc, child, dl)) { | for (dl = first_matching_driver(dc, child); dl; |
| PDEBUG(("Trying %s", DRIVERNAME(dl->driver))); | dl = next_matching_driver(dc, child, dl)) { |
| device_set_driver(child, dl->driver); | PDEBUG(("Trying %s", DRIVERNAME(dl->driver))); |
| if (!hasclass) | device_set_driver(child, dl->driver); |
| device_set_devclass(child, dl->driver->name); | if (!hasclass) |
| result = DEVICE_PROBE(child); | device_set_devclass(child, dl->driver->name); |
| if (!hasclass) | result = DEVICE_PROBE(child); |
| device_set_devclass(child, 0); | if (!hasclass) |
| device_set_devclass(child, 0); | |
| /* | /* |
| * If the driver returns SUCCESS, there can be no higher match | * If the driver returns SUCCESS, there can be |
| * for this device. | * no higher match for this device. |
| */ | */ |
| if (result == 0) { | if (result == 0) { |
| best = dl; | best = dl; |
| pri = 0; | pri = 0; |
| break; | break; |
| } | } |
| /* | /* |
| * The driver returned an error so it certainly doesn't match. | * The driver returned an error so it |
| */ | * certainly doesn't match. |
| if (result > 0) { | */ |
| device_set_driver(child, 0); | if (result > 0) { |
| continue; | device_set_driver(child, 0); |
| } | continue; |
| } | |
| /* | |
| * A priority lower than SUCCESS, remember the | |
| * best matching driver. Initialise the value | |
| * of pri for the first match. | |
| */ | |
| if (best == 0 || result > pri) { | |
| best = dl; | |
| pri = result; | |
| continue; | |
| } | |
| } | |
| /* | /* |
| * A priority lower than SUCCESS, remember the best matching | * If we have unambiguous match in this devclass, |
| * driver. Initialise the value of pri for the first match. | * don't look in the parent. |
| */ | */ |
| if (best == 0 || result > pri) { | if (best && pri == 0) |
| best = dl; | break; |
| pri = result; | |
| continue; | |
| } | |
| } | } |
| /* | /* |
| Line 959 device_set_devclass(device_t dev, const | Line 985 device_set_devclass(device_t dev, const |
| return(EINVAL); | return(EINVAL); |
| } | } |
| dc = devclass_find_internal(classname, TRUE); | dc = devclass_find_internal(classname, NULL, TRUE); |
| if (!dc) | if (!dc) |
| return(ENOMEM); | return(ENOMEM); |
| Line 2254 root_bus_module_handler(module_t mod, in | Line 2280 root_bus_module_handler(module_t mod, in |
| kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver); | kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver); |
| root_bus->driver = &root_driver; | root_bus->driver = &root_driver; |
| root_bus->state = DS_ATTACHED; | root_bus->state = DS_ATTACHED; |
| root_devclass = devclass_find_internal("root", FALSE); | root_devclass = devclass_find_internal("root", NULL, FALSE); |
| return(0); | return(0); |
| case MOD_SHUTDOWN: | case MOD_SHUTDOWN: |
| Line 2286 root_bus_configure(void) | Line 2312 root_bus_configure(void) |
| int | int |
| driver_module_handler(module_t mod, int what, void *arg) | driver_module_handler(module_t mod, int what, void *arg) |
| { | { |
| int error, i; | int error; |
| struct driver_module_data *dmd; | struct driver_module_data *dmd; |
| devclass_t bus_devclass; | devclass_t bus_devclass; |
| kobj_class_t driver; | |
| const char *parentname; | |
| dmd = (struct driver_module_data *)arg; | dmd = (struct driver_module_data *)arg; |
| bus_devclass = devclass_find_internal(dmd->dmd_busname, TRUE); | bus_devclass = devclass_find_internal(dmd->dmd_busname, NULL, TRUE); |
| error = 0; | error = 0; |
| switch (what) { | switch (what) { |
| Line 2299 driver_module_handler(module_t mod, int | Line 2327 driver_module_handler(module_t mod, int |
| if (dmd->dmd_chainevh) | if (dmd->dmd_chainevh) |
| error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); | error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); |
| for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { | driver = dmd->dmd_driver; |
| PDEBUG(("Loading module: driver %s on bus %s", | PDEBUG(("Loading module: driver %s on bus %s", |
| DRIVERNAME(dmd->dmd_drivers[i]), | DRIVERNAME(driver), dmd->dmd_busname)); |
| dmd->dmd_busname)); | error = devclass_add_driver(bus_devclass, driver); |
| error = devclass_add_driver(bus_devclass, | |
| dmd->dmd_drivers[i]); | |
| } | |
| if (error) | if (error) |
| break; | break; |
| /* | /* |
| * The drivers loaded in this way are assumed to all | * If the driver has any base classes, make the |
| * implement the same devclass. | * devclass inherit from the devclass of the driver's |
| * first base class. This will allow the system to | |
| * search for drivers in both devclasses for children | |
| * of a device using this driver. | |
| */ | */ |
| *dmd->dmd_devclass = | if (driver->baseclasses) |
| devclass_find_internal(dmd->dmd_drivers[0]->name, | parentname = driver->baseclasses[0]->name; |
| TRUE); | else |
| parentname = NULL; | |
| *dmd->dmd_devclass = devclass_find_internal(driver->name, | |
| parentname, TRUE); | |
| break; | break; |
| case MOD_UNLOAD: | case MOD_UNLOAD: |
| for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { | PDEBUG(("Unloading module: driver %s from bus %s", |
| PDEBUG(("Unloading module: driver %s from bus %s", | DRIVERNAME(dmd->dmd_driver), dmd->dmd_busname)); |
| DRIVERNAME(dmd->dmd_drivers[i]), | error = devclass_delete_driver(bus_devclass, dmd->dmd_driver); |
| dmd->dmd_busname)); | |
| error = devclass_delete_driver(bus_devclass, | |
| dmd->dmd_drivers[i]); | |
| } | |
| if (!error && dmd->dmd_chainevh) | if (!error && dmd->dmd_chainevh) |
| error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); | error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); |