summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>1998-11-14 21:58:51 +0000
committerwollman <wollman@FreeBSD.org>1998-11-14 21:58:51 +0000
commit2f0e3424ed6bcb975173592be454fab41a7d659a (patch)
tree570ac1a59a276154fa1ecdf8529f4edc007e8800 /sys/kern
parentd0ac456c883f5146f0c93ef654a57e02ffbffb87 (diff)
downloadFreeBSD-src-2f0e3424ed6bcb975173592be454fab41a7d659a.zip
FreeBSD-src-2f0e3424ed6bcb975173592be454fab41a7d659a.tar.gz
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
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/bus_if.m84
-rw-r--r--sys/kern/device_if.m16
-rw-r--r--sys/kern/kern_conf.c6
-rw-r--r--sys/kern/subr_bus.c267
-rw-r--r--sys/kern/subr_devstat.c4
5 files changed, 286 insertions, 91 deletions
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 <machine/resource.h>; 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 <sys/rman.h>.
+#
+# 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 <sys/param.h>
@@ -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 <sys/param.h>
@@ -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 <sys/param.h>
@@ -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)
OpenPOWER on IntegriCloud