Index: dev/aic7xxx/ahc_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/aic7xxx/ahc_pci.c,v retrieving revision 1.56 diff -u -r1.56 ahc_pci.c --- dev/aic7xxx/ahc_pci.c 2 Sep 2003 17:30:34 -0000 1.56 +++ dev/aic7xxx/ahc_pci.c 21 Sep 2003 10:37:11 -0000 @@ -57,7 +57,6 @@ }; DRIVER_MODULE(ahc_pci, pci, ahc_pci_driver, ahc_devclass, 0, 0); -DRIVER_MODULE(ahc_pci, cardbus, ahc_pci_driver, ahc_devclass, 0, 0); MODULE_DEPEND(ahc_pci, ahc, 1, 1, 1); MODULE_VERSION(ahc_pci, 1); Index: dev/aic7xxx/ahd_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/aic7xxx/ahd_pci.c,v retrieving revision 1.11 diff -u -r1.11 ahd_pci.c --- dev/aic7xxx/ahd_pci.c 2 Sep 2003 17:30:34 -0000 1.11 +++ dev/aic7xxx/ahd_pci.c 21 Sep 2003 10:37:11 -0000 @@ -60,7 +60,6 @@ static devclass_t ahd_devclass; DRIVER_MODULE(ahd, pci, ahd_pci_driver, ahd_devclass, 0, 0); -DRIVER_MODULE(ahd, cardbus, ahd_pci_driver, ahd_devclass, 0, 0); MODULE_DEPEND(ahd_pci, ahd, 1, 1, 1); MODULE_VERSION(ahd_pci, 1); Index: dev/ath/if_ath_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/ath/if_ath_pci.c,v retrieving revision 1.3 diff -u -r1.3 if_ath_pci.c --- dev/ath/if_ath_pci.c 13 Aug 2003 21:29:35 -0000 1.3 +++ dev/ath/if_ath_pci.c 21 Sep 2003 10:37:11 -0000 @@ -297,7 +297,6 @@ }; static devclass_t ath_devclass; DRIVER_MODULE(if_ath, pci, ath_pci_driver, ath_devclass, 0, 0); -DRIVER_MODULE(if_ath, cardbus, ath_pci_driver, ath_devclass, 0, 0); MODULE_VERSION(if_ath, 1); MODULE_DEPEND(if_ath, ath_hal, 1, 1, 1); /* Atheros HAL */ MODULE_DEPEND(if_ath, wlan, 1, 1, 1); /* 802.11 media layer */ Index: dev/cardbus/cardbus.c =================================================================== RCS file: /home/ncvs/src/sys/dev/cardbus/cardbus.c,v retrieving revision 1.40 diff -u -r1.40 cardbus.c --- dev/cardbus/cardbus.c 24 Aug 2003 17:46:02 -0000 1.40 +++ dev/cardbus/cardbus.c 22 Sep 2003 08:16:58 -0000 @@ -349,30 +349,13 @@ DEVMETHOD(device_probe, cardbus_probe), DEVMETHOD(device_attach, cardbus_attach), DEVMETHOD(device_detach, cardbus_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, cardbus_suspend), DEVMETHOD(device_resume, cardbus_resume), /* Bus interface */ - DEVMETHOD(bus_print_child, pci_print_child), - DEVMETHOD(bus_probe_nomatch, pci_probe_nomatch), DEVMETHOD(bus_read_ivar, cardbus_read_ivar), DEVMETHOD(bus_write_ivar, cardbus_write_ivar), DEVMETHOD(bus_driver_added, cardbus_driver_added), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_get_resource_list,pci_get_resource_list), - DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), - DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), - DEVMETHOD(bus_delete_resource, pci_delete_resource), - DEVMETHOD(bus_alloc_resource, pci_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - 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_child_pnpinfo_str, pci_child_pnpinfo_str_method), - DEVMETHOD(bus_child_location_str, pci_child_location_str_method), /* Card Interface */ DEVMETHOD(card_attach_card, cardbus_attach_card), @@ -380,25 +363,12 @@ DEVMETHOD(card_cis_read, cardbus_cis_read), DEVMETHOD(card_cis_free, cardbus_cis_free), - /* Cardbus/PCI interface */ - DEVMETHOD(pci_read_config, pci_read_config_method), - DEVMETHOD(pci_write_config, pci_write_config_method), - DEVMETHOD(pci_enable_busmaster, pci_enable_busmaster_method), - DEVMETHOD(pci_disable_busmaster, pci_disable_busmaster_method), - DEVMETHOD(pci_enable_io, pci_enable_io_method), - DEVMETHOD(pci_disable_io, pci_disable_io_method), - DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method), - DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method), - DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method), - {0,0} }; -static driver_t cardbus_driver = { - "cardbus", - cardbus_methods, - 0 /* no softc */ -}; +DECLARE_CLASS(pci_driver); +DEFINE_CLASS_INHERITS1(cardbus, cardbus_driver, cardbus_methods, + 0, pci_driver); static devclass_t cardbus_devclass; Index: dev/firewire/fwohci_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/firewire/fwohci_pci.c,v retrieving revision 1.33 diff -u -r1.33 fwohci_pci.c --- dev/firewire/fwohci_pci.c 22 Aug 2003 07:33:20 -0000 1.33 +++ dev/firewire/fwohci_pci.c 21 Sep 2003 10:37:11 -0000 @@ -458,4 +458,3 @@ static devclass_t fwohci_devclass; DRIVER_MODULE(fwohci, pci, fwohci_driver, fwohci_devclass, 0, 0); -DRIVER_MODULE(fwohci, cardbus, fwohci_driver, fwohci_devclass, 0, 0); Index: dev/fxp/if_fxp.c =================================================================== RCS file: /home/ncvs/src/sys/dev/fxp/if_fxp.c,v retrieving revision 1.194 diff -u -r1.194 if_fxp.c --- dev/fxp/if_fxp.c 5 Sep 2003 22:37:31 -0000 1.194 +++ dev/fxp/if_fxp.c 21 Sep 2003 10:37:11 -0000 @@ -279,7 +279,6 @@ static devclass_t fxp_devclass; DRIVER_MODULE(fxp, pci, fxp_driver, fxp_devclass, 0, 0); -DRIVER_MODULE(fxp, cardbus, fxp_driver, fxp_devclass, 0, 0); DRIVER_MODULE(miibus, fxp, miibus_driver, miibus_devclass, 0, 0); static int fxp_rnr; Index: dev/pci/pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/pci/pci.c,v retrieving revision 1.233 diff -u -r1.233 pci.c --- dev/pci/pci.c 17 Sep 2003 08:32:44 -0000 1.233 +++ dev/pci/pci.c 22 Sep 2003 08:17:35 -0000 @@ -125,11 +125,7 @@ { 0, 0 } }; -static driver_t pci_driver = { - "pci", - pci_methods, - 0, /* no softc */ -}; +DEFINE_CLASS(pci, pci_driver, pci_methods, 0); devclass_t pci_devclass; DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0); Index: dev/puc/puc_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/puc/puc_pci.c,v retrieving revision 1.7 diff -u -r1.7 puc_pci.c --- dev/puc/puc_pci.c 6 Sep 2003 21:48:50 -0000 1.7 +++ dev/puc/puc_pci.c 21 Sep 2003 10:37:11 -0000 @@ -164,7 +164,6 @@ }; DRIVER_MODULE(puc, pci, puc_pci_driver, puc_devclass, 0, 0); -DRIVER_MODULE(puc, cardbus, puc_pci_driver, puc_devclass, 0, 0); #define rdspio(indx) (bus_space_write_1(bst, bsh, efir, indx), \ Index: dev/re/if_re.c =================================================================== RCS file: /home/ncvs/src/sys/dev/re/if_re.c,v retrieving revision 1.9 diff -u -r1.9 if_re.c --- dev/re/if_re.c 19 Sep 2003 02:35:03 -0000 1.9 +++ dev/re/if_re.c 21 Sep 2003 10:37:11 -0000 @@ -269,7 +269,6 @@ static devclass_t re_devclass; DRIVER_MODULE(re, pci, re_driver, re_devclass, 0, 0); -DRIVER_MODULE(re, cardbus, re_driver, re_devclass, 0, 0); DRIVER_MODULE(miibus, re, miibus_driver, miibus_devclass, 0, 0); #define EE_SET(x) \ Index: dev/sio/sio_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sio/sio_pci.c,v retrieving revision 1.13 diff -u -r1.13 sio_pci.c --- dev/sio/sio_pci.c 24 Aug 2003 18:03:44 -0000 1.13 +++ dev/sio/sio_pci.c 21 Sep 2003 10:37:11 -0000 @@ -160,4 +160,3 @@ } DRIVER_MODULE(sio, pci, sio_pci_driver, sio_devclass, 0, 0); -DRIVER_MODULE(sio, cardbus, sio_pci_driver, sio_devclass, 0, 0); Index: dev/uart/uart_bus_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/uart/uart_bus_pci.c,v retrieving revision 1.1 diff -u -r1.1 uart_bus_pci.c --- dev/uart/uart_bus_pci.c 6 Sep 2003 23:13:47 -0000 1.1 +++ dev/uart/uart_bus_pci.c 21 Sep 2003 10:37:11 -0000 @@ -115,4 +115,3 @@ } DRIVER_MODULE(uart, pci, uart_pci_driver, uart_devclass, 0, 0); -DRIVER_MODULE(uart, cardbus, uart_pci_driver, uart_devclass, 0, 0); Index: dev/usb/ehci_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/usb/ehci_pci.c,v retrieving revision 1.6 diff -u -r1.6 ehci_pci.c --- dev/usb/ehci_pci.c 24 Aug 2003 17:55:54 -0000 1.6 +++ dev/usb/ehci_pci.c 21 Sep 2003 10:37:11 -0000 @@ -334,4 +334,3 @@ static devclass_t ehci_devclass; DRIVER_MODULE(ehci, pci, ehci_driver, ehci_devclass, 0, 0); -DRIVER_MODULE(ehci, cardbus, ehci_driver, ehci_devclass, 0, 0); Index: dev/usb/ohci_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/usb/ohci_pci.c,v retrieving revision 1.34 diff -u -r1.34 ohci_pci.c --- dev/usb/ohci_pci.c 3 Sep 2003 07:40:17 -0000 1.34 +++ dev/usb/ohci_pci.c 21 Sep 2003 10:37:10 -0000 @@ -325,4 +325,3 @@ static devclass_t ohci_devclass; DRIVER_MODULE(ohci, pci, ohci_driver, ohci_devclass, 0, 0); -DRIVER_MODULE(ohci, cardbus, ohci_driver, ohci_devclass, 0, 0); Index: dev/usb/uhci_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/usb/uhci_pci.c,v retrieving revision 1.49 diff -u -r1.49 uhci_pci.c --- dev/usb/uhci_pci.c 24 Aug 2003 17:55:55 -0000 1.49 +++ dev/usb/uhci_pci.c 21 Sep 2003 10:37:09 -0000 @@ -412,4 +412,3 @@ static devclass_t uhci_devclass; DRIVER_MODULE(uhci, pci, uhci_driver, uhci_devclass, 0, 0); -DRIVER_MODULE(uhci, cardbus, uhci_driver, uhci_devclass, 0, 0); Index: i386/isa/isa_compat.c =================================================================== RCS file: /home/ncvs/src/sys/i386/isa/isa_compat.c,v retrieving revision 1.28 diff -u -r1.28 isa_compat.c --- i386/isa/isa_compat.c 5 Sep 2003 14:55:11 -0000 1.28 +++ i386/isa/isa_compat.c 21 Sep 2003 10:02:14 -0000 @@ -48,6 +48,11 @@ #include #include +struct isa_compat_driver { + KOBJ_CLASS_FIELDS; + void* priv; +}; + struct isa_compat_resources { struct resource *ports; struct resource *memory; @@ -137,6 +142,7 @@ static int isa_compat_probe(device_t dev) { + struct isa_compat_driver *drv; struct isa_device *dvp = device_get_softc(dev); struct isa_compat_resources res; u_long start, count; @@ -149,7 +155,8 @@ /* * Fill in the isa_device fields. */ - dvp->id_driver = device_get_driver(dev)->priv; + drv = (struct isa_compat_driver *)device_get_driver(dev); + dvp->id_driver = drv->priv; if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &start, &count) == 0) dvp->id_iobase = start; @@ -267,12 +274,13 @@ compat_isa_handler(module_t mod, int type, void *data) { struct isa_driver *id = (struct isa_driver *)data; - driver_t *driver; + struct isa_compat_driver *driver; devclass_t isa_devclass = devclass_find("isa"); switch (type) { case MOD_LOAD: - driver = malloc(sizeof(driver_t), M_DEVBUF, M_NOWAIT | M_ZERO); + driver = malloc(sizeof(struct isa_compat_driver), + M_DEVBUF, M_NOWAIT | M_ZERO); if (!driver) return ENOMEM; driver->name = id->name; @@ -287,7 +295,7 @@ driver->name); #endif } - devclass_add_driver(isa_devclass, driver); + devclass_add_driver(isa_devclass, (kobj_class_t) driver); break; case MOD_UNLOAD: printf("%s: module unload not supported!\n", id->name); Index: kern/subr_bus.c =================================================================== RCS file: /home/ncvs/src/sys/kern/subr_bus.c,v retrieving revision 1.131 diff -u -r1.131 subr_bus.c --- kern/subr_bus.c 10 Sep 2003 21:37:10 -0000 1.131 +++ kern/subr_bus.c 22 Sep 2003 08:18:19 -0000 @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1997,1998 Doug Rabson + * Copyright (c) 1997,1998,2003 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -62,8 +62,8 @@ */ typedef struct driverlink *driverlink_t; struct driverlink { - driver_t *driver; - TAILQ_ENTRY(driverlink) link; /* list of drivers in devclass */ + kobj_class_t driver; + TAILQ_ENTRY(driverlink) link; /* list of drivers in devclass */ }; /* @@ -75,6 +75,7 @@ struct devclass { TAILQ_ENTRY(devclass) link; + devclass_t parent; /* parent in devclass hierarchy */ driver_list_t drivers; /* bus devclasses store drivers for bus */ char *name; device_t *devices; /* array of devices indexed by unit */ @@ -499,7 +500,7 @@ { 0, 0 } }; -DEFINE_CLASS(null, null_methods, 0); +DEFINE_CLASS(null, null_class, null_methods, 0); /* * Devclass implementation @@ -508,7 +509,8 @@ static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses); 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; @@ -518,15 +520,16 @@ TAILQ_FOREACH(dc, &devclasses, link) { if (!strcmp(dc->name, classname)) - return (dc); + break; } - PDEBUG(("%s not found%s", classname, (create? ", creating": ""))); - if (create) { + if (create && !dc) { + PDEBUG(("creating %s", classname)); dc = malloc(sizeof(struct devclass) + strlen(classname) + 1, M_BUS, M_NOWAIT|M_ZERO); if (!dc) return (NULL); + dc->parent = NULL; dc->name = (char*) (dc + 1); strcpy(dc->name, classname); TAILQ_INIT(&dc->drivers); @@ -534,6 +537,9 @@ bus_data_generation_update(); } + if (parentname && dc && !dc->parent) { + dc->parent = devclass_find_internal(parentname, 0, FALSE); + } return (dc); } @@ -541,13 +547,13 @@ devclass_t devclass_create(const char *classname) { - return (devclass_find_internal(classname, TRUE)); + return (devclass_find_internal(classname, 0, TRUE)); } devclass_t devclass_find(const char *classname) { - return (devclass_find_internal(classname, FALSE)); + return (devclass_find_internal(classname, 0, FALSE)); } int @@ -573,7 +579,7 @@ /* * Make sure the devclass which the driver is implementing exists. */ - devclass_find_internal(driver->name, TRUE); + devclass_find_internal(driver->name, 0, TRUE); dl->driver = driver; TAILQ_INSERT_TAIL(&dc->drivers, dl, link); @@ -667,7 +673,7 @@ return (NULL); } -driver_t * +kobj_class_t devclass_find_driver(devclass_t dc, const char *classname) { driverlink_t dl; @@ -750,6 +756,18 @@ return (unit); } +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 devclass_alloc_unit(devclass_t dc, int *unitp) { @@ -856,7 +874,7 @@ PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit)); if (name) { - dc = devclass_find_internal(name, TRUE); + dc = devclass_find_internal(name, 0, TRUE); if (!dc) { printf("make_device: can't find device class %s\n", name); @@ -1042,44 +1060,54 @@ if (child->state == DS_ALIVE) return (0); - for (dl = first_matching_driver(dc, child); - dl; - dl = next_matching_driver(dc, child, dl)) { - PDEBUG(("Trying %s", DRIVERNAME(dl->driver))); - device_set_driver(child, dl->driver); - if (!hasclass) - device_set_devclass(child, dl->driver->name); - result = DEVICE_PROBE(child); - if (!hasclass) - device_set_devclass(child, 0); + for (; dc; dc = dc->parent) { + for (dl = first_matching_driver(dc, child); + dl; + dl = next_matching_driver(dc, child, dl)) { + PDEBUG(("Trying %s", DRIVERNAME(dl->driver))); + device_set_driver(child, dl->driver); + if (!hasclass) + device_set_devclass(child, dl->driver->name); + result = DEVICE_PROBE(child); + if (!hasclass) + device_set_devclass(child, 0); - /* - * If the driver returns SUCCESS, there can be no higher match - * for this device. - */ - if (result == 0) { - best = dl; - pri = 0; - break; - } + /* + * If the driver returns SUCCESS, there can be + * no higher match for this device. + */ + if (result == 0) { + best = dl; + pri = 0; + break; + } - /* - * The driver returned an error so it certainly doesn't match. - */ - if (result > 0) { - device_set_driver(child, 0); - continue; - } + /* + * The driver returned an error so it + * certainly doesn't match. + */ + if (result > 0) { + 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 - * driver. Initialise the value of pri for the first match. + * If we have an unambiguous match in this devclass, + * don't look in the parent. */ - if (best == 0 || result > pri) { - best = dl; - pri = result; - continue; - } + if (best && pri == 0) + break; } /* @@ -1376,7 +1404,7 @@ return (EINVAL); } - dc = devclass_find_internal(classname, TRUE); + dc = devclass_find_internal(classname, 0, TRUE); if (!dc) return (ENOMEM); @@ -2241,7 +2269,7 @@ kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver); root_bus->driver = &root_driver; root_bus->state = DS_ATTACHED; - root_devclass = devclass_find_internal("root", FALSE); + root_devclass = devclass_find_internal("root", 0, FALSE); devinit(); return (0); @@ -2275,12 +2303,13 @@ int driver_module_handler(module_t mod, int what, void *arg) { - int error, i; + int error; struct driver_module_data *dmd; devclass_t bus_devclass; + kobj_class_t driver; dmd = (struct driver_module_data *)arg; - bus_devclass = devclass_find_internal(dmd->dmd_busname, TRUE); + bus_devclass = devclass_find_internal(dmd->dmd_busname, 0, TRUE); error = 0; switch (what) { @@ -2288,31 +2317,38 @@ if (dmd->dmd_chainevh) error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); - for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { - PDEBUG(("Loading module: driver %s on bus %s", - DRIVERNAME(dmd->dmd_drivers[i]), dmd->dmd_busname)); - error = devclass_add_driver(bus_devclass, - dmd->dmd_drivers[i]); - } + driver = dmd->dmd_driver; + PDEBUG(("Loading module: driver %s on bus %s", + DRIVERNAME(driver), dmd->dmd_busname)); + error = devclass_add_driver(bus_devclass, driver); if (error) break; /* - * The drivers loaded in this way are assumed to all - * implement the same devclass. + * If the driver has any base classes, make the + * 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 = - devclass_find_internal(dmd->dmd_drivers[0]->name, TRUE); + if (driver->baseclasses) { + const char *parentname; + parentname = driver->baseclasses[0]->name; + *dmd->dmd_devclass = + devclass_find_internal(driver->name, + parentname, TRUE); + } else { + *dmd->dmd_devclass = + devclass_find_internal(driver->name, 0, TRUE); + } break; case MOD_UNLOAD: - for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { - PDEBUG(("Unloading module: driver %s from bus %s", - DRIVERNAME(dmd->dmd_drivers[i]), - dmd->dmd_busname)); - error = devclass_delete_driver(bus_devclass, - dmd->dmd_drivers[i]); - } + PDEBUG(("Unloading module: driver %s from bus %s", + DRIVERNAME(dmd->dmd_driver), + dmd->dmd_busname)); + error = devclass_delete_driver(bus_devclass, + dmd->dmd_driver); if (!error && dmd->dmd_chainevh) error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); Index: kern/subr_kobj.c =================================================================== RCS file: /home/ncvs/src/sys/kern/subr_kobj.c,v retrieving revision 1.7 diff -u -r1.7 subr_kobj.c --- kern/subr_kobj.c 14 Aug 2003 21:16:46 -0000 1.7 +++ kern/subr_kobj.c 21 Sep 2003 10:20:19 -0000 @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000 Doug Rabson + * Copyright (c) 2000,2003 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,6 +38,8 @@ #include #endif #include +#include +#include #ifdef TEST #include "usertest.h" @@ -57,12 +59,22 @@ #endif +static struct mtx kobj_mtx; static int kobj_next_id = 1; SYSCTL_UINT(_kern, OID_AUTO, kobj_methodcount, CTLFLAG_RD, &kobj_next_id, 0, ""); -static int +static void +kobj_init_mutex(void *arg) +{ + + mtx_init(&kobj_mtx, "kobj", NULL, MTX_DEF); +} + +SYSINIT(kobj, SI_SUB_LOCK, SI_ORDER_ANY, kobj_init_mutex, NULL) + +int kobj_error_method(void) { return ENXIO; @@ -72,7 +84,6 @@ kobj_register_method(struct kobjop_desc *desc) { if (desc->id == 0) { - KASSERT((kobj_next_id < KOBJ_CACHE_SIZE), ("kobj method table overflow")); desc->id = kobj_next_id++; } } @@ -119,7 +130,9 @@ ops = malloc(sizeof(struct kobj_ops), M_KOBJ, M_NOWAIT); if (!ops) panic("kobj_compile_methods: out of memory"); + mtx_lock(&kobj_mtx); kobj_class_compile_common(cls, ops); + mtx_unlock(&kobj_mtx); } void @@ -128,27 +141,62 @@ /* * Increment refs to make sure that the ops table is not freed. */ + mtx_lock(&kobj_mtx); cls->refs++; kobj_class_compile_common(cls, ops); + mtx_unlock(&kobj_mtx); } -void -kobj_lookup_method(kobj_method_t *methods, - kobj_method_t *ce, - kobjop_desc_t desc) +static kobj_method_t* +kobj_lookup_method_class(kobj_class_t cls, kobjop_desc_t desc) { - ce->desc = desc; - for (; methods && methods->desc; methods++) { - if (methods->desc == desc) { - ce->func = methods->func; - return; + kobj_method_t *methods = cls->methods; + kobj_method_t *ce; + + for (ce = methods; ce && ce->desc; ce++) { + if (ce->desc == desc) { + return ce; } } - if (desc->deflt) - ce->func = desc->deflt; - else - ce->func = kobj_error_method; - return; + + return 0; +} + +static kobj_method_t* +kobj_lookup_method_mi(kobj_class_t cls, + kobjop_desc_t desc) +{ + kobj_method_t *ce; + kobj_class_t *basep; + + ce = kobj_lookup_method_class(cls, desc); + if (ce) + return ce; + + basep = cls->baseclasses; + if (basep) { + for (; *basep; basep++) { + ce = kobj_lookup_method_mi(*basep, desc); + if (ce) + return ce; + } + } + + return 0; +} + +kobj_method_t* +kobj_lookup_method(kobj_class_t cls, + kobj_method_t **cep, + kobjop_desc_t desc) +{ + kobj_method_t *ce; + + ce = kobj_lookup_method_mi(cls, desc); + if (!ce) + ce = desc->deflt; + *cep = ce; + return ce; } void @@ -156,18 +204,32 @@ { int i; kobj_method_t *m; + void* ops = 0; - /* - * Unregister any methods which are no longer used. - */ - for (i = 0, m = cls->methods; m->desc; i++, m++) - kobj_unregister_method(m->desc); + mtx_lock(&kobj_mtx); /* - * Free memory and clean up. + * Protect against a race between kobj_create and + * kobj_delete. */ - free(cls->ops, M_KOBJ); - cls->ops = 0; + if (cls->refs == 0) { + /* + * Unregister any methods which are no longer used. + */ + for (i = 0, m = cls->methods; m->desc; i++, m++) + kobj_unregister_method(m->desc); + + /* + * Free memory and clean up. + */ + ops = cls->ops; + cls->ops = 0; + } + + mtx_unlock(&kobj_mtx); + + if (ops) + free(ops, M_KOBJ); } kobj_t @@ -191,28 +253,46 @@ void kobj_init(kobj_t obj, kobj_class_t cls) { + retry: + mtx_lock(&kobj_mtx); + /* * Consider compiling the class' method table. */ - if (!cls->ops) + if (!cls->ops) { + /* + * kobj_class_compile doesn't want the lock held + * because of the call to malloc - we drop the lock + * and re-try. + */ + mtx_unlock(&kobj_mtx); kobj_class_compile(cls); + goto retry; + } obj->ops = cls->ops; cls->refs++; + + mtx_unlock(&kobj_mtx); } void kobj_delete(kobj_t obj, struct malloc_type *mtype) { kobj_class_t cls = obj->ops->cls; + int refs; /* * Consider freeing the compiled method table for the class * after its last instance is deleted. As an optimisation, we * should defer this for a short while to avoid thrashing. */ + mtx_lock(&kobj_mtx); cls->refs--; - if (!cls->refs) + refs = cls->refs; + mtx_unlock(&kobj_mtx); + + if (!refs) kobj_class_free(cls); obj->ops = 0; Index: pci/if_dc.c =================================================================== RCS file: /home/ncvs/src/sys/pci/if_dc.c,v retrieving revision 1.125 diff -u -r1.125 if_dc.c --- pci/if_dc.c 16 Sep 2003 05:01:27 -0000 1.125 +++ pci/if_dc.c 21 Sep 2003 10:37:11 -0000 @@ -332,7 +332,6 @@ "do not mdevget in dc driver"); #endif -DRIVER_MODULE(dc, cardbus, dc_driver, dc_devclass, 0, 0); DRIVER_MODULE(dc, pci, dc_driver, dc_devclass, 0, 0); DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0); Index: pci/if_rl.c =================================================================== RCS file: /home/ncvs/src/sys/pci/if_rl.c,v retrieving revision 1.120 diff -u -r1.120 if_rl.c --- pci/if_rl.c 11 Sep 2003 04:05:01 -0000 1.120 +++ pci/if_rl.c 21 Sep 2003 10:35:23 -0000 @@ -253,7 +253,6 @@ static devclass_t rl_devclass; DRIVER_MODULE(rl, pci, rl_driver, rl_devclass, 0, 0); -DRIVER_MODULE(rl, cardbus, rl_driver, rl_devclass, 0, 0); DRIVER_MODULE(miibus, rl, miibus_driver, miibus_devclass, 0, 0); #define EE_SET(x) \ Index: pci/if_xl.c =================================================================== RCS file: /home/ncvs/src/sys/pci/if_xl.c,v retrieving revision 1.153 diff -u -r1.153 if_xl.c --- pci/if_xl.c 14 Sep 2003 16:33:48 -0000 1.153 +++ pci/if_xl.c 21 Sep 2003 09:17:53 -0000 @@ -293,7 +293,6 @@ static devclass_t xl_devclass; -DRIVER_MODULE(xl, cardbus, xl_driver, xl_devclass, 0, 0); DRIVER_MODULE(xl, pci, xl_driver, xl_devclass, 0, 0); DRIVER_MODULE(miibus, xl, miibus_driver, miibus_devclass, 0, 0); Index: sys/bus.h =================================================================== RCS file: /home/ncvs/src/sys/sys/bus.h,v retrieving revision 1.55 diff -u -r1.55 bus.h --- sys/bus.h 10 Sep 2003 21:37:10 -0000 1.55 +++ sys/bus.h 21 Sep 2003 09:57:20 -0000 @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1997,1998 Doug Rabson + * Copyright (c) 1997,1998,2003 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -75,7 +75,7 @@ * Forward declarations */ typedef struct device *device_t; -typedef struct driver driver_t; +typedef struct kobj_class driver_t; typedef struct devclass *devclass_t; #define device_method_t kobj_method_t @@ -124,9 +124,12 @@ typedef int (*devop_t)(void); +/* + * This structure is deprecated. Use the kobj(9) macro DEFINE_CLASS to + * declare classes which implement device drivers. + */ struct driver { KOBJ_CLASS_FIELDS; - void *priv; /* driver private data */ }; /* @@ -345,17 +348,19 @@ /* * Access functions for devclass. */ -int devclass_add_driver(devclass_t dc, driver_t *driver); -int devclass_delete_driver(devclass_t dc, driver_t *driver); +int devclass_add_driver(devclass_t dc, kobj_class_t driver); +int devclass_delete_driver(devclass_t dc, kobj_class_t driver); devclass_t devclass_create(const char *classname); devclass_t devclass_find(const char *classname); -driver_t *devclass_find_driver(devclass_t dc, const char *classname); +kobj_class_t devclass_find_driver(devclass_t dc, const char *classname); const char *devclass_get_name(devclass_t dc); device_t devclass_get_device(devclass_t dc, int unit); void *devclass_get_softc(devclass_t dc, int unit); int devclass_get_devices(devclass_t dc, device_t **listp, int *countp); int devclass_get_maxunit(devclass_t dc); int devclass_find_free_unit(devclass_t dc, int unit); +void devclass_set_parent(devclass_t dc, devclass_t pdc); +devclass_t devclass_get_parent(devclass_t dc); /* * Access functions for device resources. @@ -407,40 +412,16 @@ int (*dmd_chainevh)(struct module *, int, void *); void *dmd_chainarg; const char *dmd_busname; - driver_t **dmd_drivers; - int dmd_ndrivers; + kobj_class_t dmd_driver; devclass_t *dmd_devclass; }; #define DRIVER_MODULE(name, busname, driver, devclass, evh, arg) \ \ -static driver_t *name##_##busname##_driver_list[] = { &driver }; \ -static struct driver_module_data name##_##busname##_driver_mod = { \ - evh, arg, \ - #busname, \ - name##_##busname##_driver_list, \ - (sizeof name##_##busname##_driver_list) / \ - (sizeof name##_##busname##_driver_list[0]), \ - &devclass \ -}; \ - \ -static moduledata_t name##_##busname##_mod = { \ - #busname "/" #name, \ - driver_module_handler, \ - &name##_##busname##_driver_mod \ -}; \ -DECLARE_MODULE(name##_##busname, name##_##busname##_mod, \ - SI_SUB_DRIVERS, SI_ORDER_MIDDLE) - -#define MULTI_DRIVER_MODULE(name, busname, drivers, devclass, evh, arg) \ - \ -static driver_t name##_##busname##_driver_list[] = drivers; \ static struct driver_module_data name##_##busname##_driver_mod = { \ evh, arg, \ #busname, \ - name##_##busname##_driver_list, \ - (sizeof name##_##busname##_driver_list) / \ - (sizeof name##_##busname##_driver_list[0]), \ + (kobj_class_t) &driver, \ &devclass \ }; \ \ Index: sys/kobj.h =================================================================== RCS file: /home/ncvs/src/sys/sys/kobj.h,v retrieving revision 1.7 diff -u -r1.7 kobj.h --- sys/kobj.h 10 Jun 2002 22:40:26 -0000 1.7 +++ sys/kobj.h 22 Sep 2003 08:15:54 -0000 @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000 Doug Rabson + * Copyright (c) 2000,2003 Doug Rabson * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,6 +55,7 @@ const char *name; /* class name */ \ kobj_method_t *methods; /* method table */ \ size_t size; /* object size */ \ + kobj_class_t *baseclasses; /* base classes */ \ u_int refs; /* reference count */ \ kobj_ops_t ops /* compiled method table */ @@ -79,13 +80,13 @@ #define KOBJ_CACHE_SIZE 256 struct kobj_ops { - kobj_method_t cache[KOBJ_CACHE_SIZE]; + kobj_method_t *cache[KOBJ_CACHE_SIZE]; kobj_class_t cls; }; struct kobjop_desc { - unsigned int id; /* unique ID */ - kobjop_t deflt; /* default implementation */ + unsigned int id; /* unique ID */ + kobj_method_t *deflt; /* default implementation */ }; /* @@ -93,13 +94,71 @@ */ #define KOBJMETHOD(NAME, FUNC) { &NAME##_desc, (kobjop_t) FUNC } -#define DEFINE_CLASS(name, methods, size) \ - \ -struct kobj_class name ## _class = { \ - #name, methods, size \ +/* + * Declare a class (which should be defined in another file. + */ +#define DECLARE_CLASS(name) extern struct kobj_class name + +/* + * Define a class. Use like this: + * + * DEFINE_CLASS(foo, foo_methods, sizeof(foo_softc)); + */ +#define DEFINE_CLASS(name, classvar, methods, size) \ + \ +struct kobj_class classvar = { \ + #name, methods, size, 0 \ +} + +/* + * Define a class inheriting a single base class. Use like this: + * + * DEFINE_CLASS_INHERITS1(foo, foo_methods, sizeof(foo_softc), bar); + */ +#define DEFINE_CLASS_INHERITS1(name, classvar, \ + methods, size, \ + base1) \ + \ +static kobj_class_t name ## _baseclasses[] = \ + { &base1, 0 }; \ +struct kobj_class classvar = { \ + #name, methods, size, name ## _baseclasses \ +} + +/* + * Define a class inheriting two base classes. Use like this: + * + * DEFINE_CLASS_INHERITS2(foo, foo_methods, sizeof(foo_softc), bar, baz); + */ +#define DEFINE_CLASS_INHERITS2(name, methods, size, \ + base1, base2) \ + \ +static kobj_class_t name ## _baseclasses[] = \ + { &base1, \ + &base2, 0 }; \ +struct kobj_class name ## _class = { \ + #name, methods, size, name ## _baseclasses \ } /* + * Define a class inheriting three base classes. Use like this: + * + * DEFINE_CLASS_INHERITS3(foo, foo_methods, sizeof(foo_softc), + * bar, baz, foobar); + */ +#define DEFINE_CLASS_INHERITS3(name, methods, size, \ + base1, base2, base3) \ + \ +static kobj_class_t name ## _baseclasses[] = \ + { &base1, \ + &base2, \ + &base3, 0 }; \ +struct kobj_class name ## _class = { \ + #name, methods, size, name ## _baseclasses \ +} + + +/* * Compile the method table in a class. */ void kobj_class_compile(kobj_class_t cls); @@ -149,21 +208,29 @@ * Lookup the method in the cache and if it isn't there look it up the * slow way. */ -#define KOBJOPLOOKUP(OPS,OP) do { \ - kobjop_desc_t _desc = &OP##_##desc; \ - kobj_method_t *_ce = \ - &OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)]; \ - if (_ce->desc != _desc) { \ - KOBJOPMISS; \ - kobj_lookup_method(OPS->cls->methods, _ce, _desc); \ - } else { \ - KOBJOPHIT; \ - } \ - _m = _ce->func; \ +#define KOBJOPLOOKUP(OPS,OP) do { \ + kobjop_desc_t _desc = &OP##_##desc; \ + kobj_method_t **_cep = \ + &OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)]; \ + kobj_method_t *_ce = *_cep; \ + if (!_ce || _ce->desc != _desc) { \ + KOBJOPMISS; \ + _ce = kobj_lookup_method(OPS->cls, \ + _cep, _desc); \ + } else { \ + KOBJOPHIT; \ + } \ + _m = _ce->func; \ } while(0) -void kobj_lookup_method(kobj_method_t *methods, - kobj_method_t *ce, - kobjop_desc_t desc); +kobj_method_t* kobj_lookup_method(kobj_class_t cls, + kobj_method_t **cep, + kobjop_desc_t desc); + + +/* + * Default method implementation. Returns ENXIO. + */ +int kobj_error_method(void); #endif /* !_SYS_KOBJ_H_ */ Index: tools/makeobjops.awk =================================================================== RCS file: /home/ncvs/src/sys/tools/makeobjops.awk,v retrieving revision 1.2 diff -u -r1.2 makeobjops.awk --- tools/makeobjops.awk 20 Aug 2002 03:06:30 -0000 1.2 +++ tools/makeobjops.awk 10 Sep 2003 12:54:56 -0000 @@ -283,7 +283,7 @@ firstvar = varnames[1]; if (default == "") - default = "0"; + default = "kobj_error_method"; # the method description printh("extern struct kobjop_desc " mname "_desc;"); @@ -293,8 +293,12 @@ line_width, length(prototype))); # Print out the method desc + printc("struct kobj_method " mname "_method_default = {"); + printc("\t&" mname "_desc, (kobjop_t) " default); + printc("};\n"); + printc("struct kobjop_desc " mname "_desc = {"); - printc("\t0, (kobjop_t) " default); + printc("\t0, &" mname "_method_default"); printc("};\n"); # Print out the method itself