From 2f0e3424ed6bcb975173592be454fab41a7d659a Mon Sep 17 00:00:00 2001 From: wollman Date: Sat, 14 Nov 1998 21:58:51 +0000 Subject: My changes to the new device interface: - Interface wth the new resource manager. - Allow for multiple drivers implementing a single devclass. - Remove ordering dependencies between header files. - Style cleanup. - Add DEVICE_SUSPEND and DEVICE_RESUME methods. - Move to a single-phase interrupt setup scheme. Kernel builds on the Alpha are brken until Doug gets a chance to incorporate these changes on that side. Agreed to in principle by: dfr --- sys/kern/bus_if.m | 84 +++++++++++---- sys/kern/device_if.m | 16 ++- sys/kern/kern_conf.c | 6 +- sys/kern/subr_bus.c | 267 ++++++++++++++++++++++++++++++++++++------------ sys/kern/subr_devstat.c | 4 +- 5 files changed, 286 insertions(+), 91 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/bus_if.m b/sys/kern/bus_if.m index 67950bf..fd4f648 100644 --- a/sys/kern/bus_if.m +++ b/sys/kern/bus_if.m @@ -23,7 +23,7 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # -# $Id: bus_if.m,v 1.3 1998/09/16 08:25:56 dfr Exp $ +# $Id: bus_if.m,v 1.4 1998/11/08 18:51:38 nsouch Exp $ # INTERFACE bus; @@ -57,7 +57,7 @@ METHOD int read_ivar { device_t dev; device_t child; int index; - u_long *result; + uintptr_t *result; }; # @@ -67,27 +67,75 @@ METHOD int write_ivar { device_t dev; device_t child; int index; - u_long value; + uintptr_t value; }; # -# Create an interrupt handler for the child device. The handler will -# be called with the value 'arg' as its only argument. This method -# does not activate the handler. -# -METHOD void* create_intr { - device_t dev; - device_t child; - int irq; - driver_intr_t *intr; - void *arg; +# Allocate a system resource attached to `dev' on behalf of `child'. +# The types are defined in ; the meaning of the +# resource-ID field varies from bus to bus (but *rid == 0 is always +# valid if the resource type is). start and end reflect the allowable +# range, and should be passed as `0UL' and `~0UL', respectively, if +# the client has no range restriction. count is the number of consecutive +# indices in the resource required. flags is a set of sharing flags +# as defined in . +# +# Returns a resource or a null pointer on failure. The caller is +# responsible for calling rman_activate_resource() when it actually +# uses the resource. +# +METHOD struct resource * alloc_resource { + device_t dev; + device_t child; + int type; + int *rid; + u_long start; + u_long end; + u_long count; + u_int flags; +}; + +METHOD int activate_resource { + device_t dev; + device_t child; + int type; + int rid; + struct resource *r; +}; + +METHOD int deactivate_resource { + device_t dev; + device_t child; + int type; + int rid; + struct resource *r; }; # -# Activate an interrupt handler previously created with -# BUS_CREATE_INTR. +# Free a resource allocated by the preceding method. The `rid' value +# must be the same as the one returned by BUS_ALLOC_RESOURCE (which +# is not necessarily the same as the one the client passed). # -METHOD int connect_intr { - device_t dev; - void *ih; +METHOD int release_resource { + device_t dev; + device_t child; + int type; + int rid; + struct resource *res; +}; + +METHOD int setup_intr { + device_t dev; + device_t child; + struct resource *irq; + driver_intr_t *intr; + void *arg; + void **cookiep; +}; + +METHOD int teardown_intr { + device_t dev; + device_t child; + struct resource *irq; + void *cookie; }; diff --git a/sys/kern/device_if.m b/sys/kern/device_if.m index b86de7a..f429e67 100644 --- a/sys/kern/device_if.m +++ b/sys/kern/device_if.m @@ -23,7 +23,7 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # -# $Id: device_if.m,v 1.1 1998/06/14 13:53:10 dfr Exp $ +# $Id: device_if.m,v 1.2 1998/11/08 18:35:53 nsouch Exp $ # INTERFACE device; @@ -67,3 +67,17 @@ METHOD int detach { METHOD int shutdown { device_t dev; }; + +# +# This is called by the power-management subsystem when a suspend has been +# requested by the user or by some automatic mechanism. This gives +# drivers a chance to veto the suspend or save their configuration before +# power is removed. +# +METHOD int suspend { + device_t dev; +}; + +METHOD int resume { + device_t dev; +}; diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c index d1925bf..df832f6 100644 --- a/sys/kern/kern_conf.c +++ b/sys/kern/kern_conf.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: kern_conf.c,v 1.27 1998/07/04 22:30:21 julian Exp $ + * $Id: kern_conf.c,v 1.28 1998/10/25 17:44:50 phk Exp $ */ #include @@ -166,7 +166,7 @@ cdevsw_add_generic(int bdev, int cdev, struct cdevsw *cdevsw) } int -cdevsw_module_handler(module_t mod, modeventtype_t what, void* arg) +cdevsw_module_handler(module_t mod, int what, void *arg) { struct cdevsw_module_data* data = (struct cdevsw_module_data*) arg; int error; @@ -190,7 +190,7 @@ cdevsw_module_handler(module_t mod, modeventtype_t what, void* arg) } int -bdevsw_module_handler(module_t mod, modeventtype_t what, void* arg) +bdevsw_module_handler(module_t mod, int what, void* arg) { struct bdevsw_module_data* data = (struct bdevsw_module_data*) arg; int error; diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index 58ff2a2..b40e8b9 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: subr_bus.c,v 1.8 1998/10/27 09:21:43 dfr Exp $ + * $Id: subr_bus.c,v 1.9 1998/11/13 09:39:37 dfr Exp $ */ #include @@ -668,6 +668,16 @@ device_get_desc(device_t dev) } void +device_print_prettyname(device_t dev) +{ + const char *name = device_get_name(dev); + + if (name == 0) + name = "(no driver assigned)"; + printf("%s%d: ", name, device_get_unit(dev)); +} + +void device_set_desc(device_t dev, const char* desc) { dev->desc = desc; @@ -807,9 +817,10 @@ device_probe_and_attach(device_t dev) dev->state = DS_NOTPRESENT; } } - } else - printf("%s%d: disabled, not probed.\n", - dev->devclass->name, dev->unit); + } else { + device_print_prettyname(dev); + printf("not probed (disabled)\n"); + } return 0; } @@ -855,7 +866,7 @@ static int resource_match_string(int i, char *resname, char *value) { int j; - struct resource *res; + struct config_resource *res; for (j = 0, res = devtab[i].resources; j < devtab[i].resource_count; j++, res++) @@ -867,10 +878,11 @@ resource_match_string(int i, char *resname, char *value) } static int -resource_find(const char *name, int unit, char *resname, struct resource **result) +resource_find(const char *name, int unit, char *resname, + struct config_resource **result) { int i, j; - struct resource *res; + struct config_resource *res; /* * First check specific instances, then generic. @@ -906,7 +918,7 @@ int resource_int_value(const char *name, int unit, char *resname, int *result) { int error; - struct resource *res; + struct config_resource *res; if ((error = resource_find(name, unit, resname, &res)) != 0) return error; if (res->type != RES_INT) @@ -919,7 +931,7 @@ int resource_long_value(const char *name, int unit, char *resname, long *result) { int error; - struct resource *res; + struct config_resource *res; if ((error = resource_find(name, unit, resname, &res)) != 0) return error; if (res->type != RES_LONG) @@ -932,7 +944,7 @@ int resource_string_value(const char *name, int unit, char *resname, char **result) { int error; - struct resource *res; + struct config_resource *res; if ((error = resource_find(name, unit, resname, &res)) != 0) return error; if (res->type != RES_STRING) @@ -1011,59 +1023,167 @@ bus_generic_shutdown(device_t dev) return 0; } +int +bus_generic_suspend(device_t dev) +{ + int error; + device_t child, child2; + + for (child = TAILQ_FIRST(&dev->children); + child; child = TAILQ_NEXT(child, link)) { + error = DEVICE_SUSPEND(child); + if (error) { + for (child2 = TAILQ_FIRST(&dev->children); + child2 && child2 != child; + child2 = TAILQ_NEXT(child2, link)) + DEVICE_RESUME(child2); + return (error); + } + } + return 0; +} + +int +bus_generic_resume(device_t dev) +{ + device_t child; + + for (child = TAILQ_FIRST(&dev->children); + child; child = TAILQ_NEXT(child, link)) { + DEVICE_RESUME(child); + /* if resume fails, there's nothing we can usefully do... */ + } + return 0; +} + void bus_generic_print_child(device_t dev, device_t child) { } int -bus_generic_read_ivar(device_t dev, device_t child, int index, u_long* result) +bus_generic_read_ivar(device_t dev, device_t child, int index, + uintptr_t * result) { return ENOENT; } int -bus_generic_write_ivar(device_t dev, device_t child, int index, u_long value) +bus_generic_write_ivar(device_t dev, device_t child, int index, + uintptr_t value) { return ENOENT; } -void * -bus_generic_create_intr(device_t dev, device_t child, int irq, driver_intr_t *intr, void *arg) +int +bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq, + driver_intr_t *intr, void *arg, void **cookiep) { - /* Propagate up the bus hierarchy until someone handles it. */ - if (dev->parent) - return BUS_CREATE_INTR(dev->parent, dev, irq, intr, arg); - else - return NULL; + /* Propagate up the bus hierarchy until someone handles it. */ + if (dev->parent) + return (BUS_SETUP_INTR(dev->parent, dev, irq, intr, arg, + cookiep)); + else + return (EINVAL); } int -bus_generic_connect_intr(device_t dev, void *ih) +bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq, + void *cookie) { - /* Propagate up the bus hierarchy until someone handles it. */ - if (dev->parent) - return BUS_CONNECT_INTR(dev->parent, ih); - else - return EINVAL; + /* Propagate up the bus hierarchy until someone handles it. */ + if (dev->parent) + return (BUS_TEARDOWN_INTR(dev->parent, dev, irq, cookie)); + else + return (EINVAL); } -static int root_create_intr(device_t dev, device_t child, - driver_intr_t *intr, void *arg) +int +bus_generic_activate_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) { - /* - * If an interrupt mapping gets to here something bad has happened. - * Should probably panic. - */ - return EINVAL; + /* Propagate up the bus hierarchy until someone handles it. */ + if (dev->parent) + return (BUS_ACTIVATE_RESOURCE(dev->parent, child, type, rid, + r)); + else + return (EINVAL); +} + +int +bus_generic_deactivate_resource(device_t dev, device_t child, int type, + int rid, struct resource *r) +{ + /* Propagate up the bus hierarchy until someone handles it. */ + if (dev->parent) + return (BUS_DEACTIVATE_RESOURCE(dev->parent, child, type, rid, + r)); + else + return (EINVAL); +} + +/* + * Some convenience functions to make it easier for drivers to use the + * resource-management functions. All these really do is hide the + * indirection through the parent's method table, making for slightly + * less-wordy code. In the future, it might make sense for this code + * to maintain some sort of a list of resources allocated by each device. + */ +struct resource * +bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end, + u_long count, u_int flags) +{ + if (dev->parent == 0) + return (0); + return (BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end, + count, flags)); +} + +int +bus_activate_resource(device_t dev, int type, int rid, struct resource *r) +{ + if (dev->parent == 0) + return (EINVAL); + return (BUS_ACTIVATE_RESOURCE(dev->parent, dev, type, rid, r)); +} + +int +bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r) +{ + if (dev->parent == 0) + return (EINVAL); + return (BUS_DEACTIVATE_RESOURCE(dev->parent, dev, type, rid, r)); +} + +int +bus_release_resource(device_t dev, int type, int rid, struct resource *r) +{ + if (dev->parent == 0) + return (EINVAL); + return (BUS_RELEASE_RESOURCE(dev->parent, dev, + type, rid, r)); +} + +static int +root_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg, + void **cookiep) +{ + /* + * If an interrupt mapping gets to here something bad has happened. + */ + panic("root_setup_intr"); } static device_method_t root_methods[] = { + /* Device interface */ + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + /* Bus interface */ DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), - DEVMETHOD(bus_create_intr, root_create_intr), + DEVMETHOD(bus_setup_intr, root_setup_intr), { 0, 0 } }; @@ -1075,11 +1195,11 @@ static driver_t root_driver = { 1, /* no softc */ }; -device_t root_bus; -devclass_t root_devclass; +device_t root_bus; +devclass_t root_devclass; static int -root_bus_module_handler(module_t mod, modeventtype_t what, void* arg) +root_bus_module_handler(module_t mod, int what, void* arg) { switch (what) { case MOD_LOAD: @@ -1104,7 +1224,7 @@ static moduledata_t root_bus_mod = { DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); void -root_bus_configure() +root_bus_configure(void) { device_t dev; @@ -1117,40 +1237,53 @@ root_bus_configure() } int -driver_module_handler(module_t mod, modeventtype_t what, void* arg) -{ - struct driver_module_data* data = (struct driver_module_data*) arg; - devclass_t bus_devclass = devclass_find_internal(data->busname, TRUE); - int error; +driver_module_handler(module_t mod, int what, void *arg) +{ + int error, i; + struct driver_module_data *dmd; + devclass_t bus_devclass; + + dmd = (struct driver_module_data *)arg; + bus_devclass = devclass_find_internal(dmd->dmd_busname, TRUE); + error = 0; + + switch (what) { + case MOD_LOAD: + for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { + PDEBUG(("Loading module: driver %s on bus %s", + DRIVERNAME(dmd->dmd_driver[i]), + dmd->dmd_busname)); + error = devclass_add_driver(bus_devclass, + dmd->dmd_drivers[i]); + } + if (error) + break; - switch (what) { - case MOD_LOAD: - PDEBUG(("Loading module: driver %s on bus %s", - DRIVERNAME(data->driver), data->busname)); - if (error = devclass_add_driver(bus_devclass, - data->driver)) - return error; - *data->devclass = - devclass_find_internal(data->driver->name, TRUE); - break; - - case MOD_UNLOAD: - PDEBUG(("Unloading module: driver %s from bus %s", - DRIVERNAME(data->driver), data->busname)); - if (error = devclass_delete_driver(bus_devclass, - data->driver)) - return error; - break; - } + /* + * The drivers loaded in this way are assumed to all + * implement the same devclass. + */ + *dmd->dmd_devclass = + devclass_find_internal(dmd->dmd_drivers[0]->name, + 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]); + } + break; + } - if (data->chainevh) - return data->chainevh(mod, what, data->chainarg); - else - return 0; + if (!error && dmd->dmd_chainevh) + error = dmd->dmd_chainevh(mod, what, dmd->dmd_chainarg); + return (error); } - - #ifdef BUS_DEBUG /* the _short versions avoid iteration by not calling anything that prints diff --git a/sys/kern/subr_devstat.c b/sys/kern/subr_devstat.c index 51c73df..04be0a3 100644 --- a/sys/kern/subr_devstat.c +++ b/sys/kern/subr_devstat.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: subr_devstat.c,v 1.3 1998/10/06 04:16:07 ken Exp $ + * $Id: subr_devstat.c,v 1.4 1998/10/14 20:44:05 ken Exp $ */ #include @@ -49,7 +49,7 @@ STAILQ_HEAD(devstatlist, devstat) device_statq; * and add it to the queue of devices. */ void -devstat_add_entry(struct devstat *ds, char *dev_name, +devstat_add_entry(struct devstat *ds, const char *dev_name, int unit_number, u_int32_t block_size, devstat_support_flags flags, devstat_type_flags device_type) -- cgit v1.1