diff options
author | des <des@FreeBSD.org> | 2004-06-04 10:23:00 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2004-06-04 10:23:00 +0000 |
commit | 7fec1d493133d2b669b572d3dca639704968dd51 (patch) | |
tree | 399940cb8da5617d996f6b5712b08fa15438a026 /sys/kern/subr_bus.c | |
parent | 87b856667a621219e131b677f5a09e0938f1e5f8 (diff) | |
download | FreeBSD-src-7fec1d493133d2b669b572d3dca639704968dd51.zip FreeBSD-src-7fec1d493133d2b669b572d3dca639704968dd51.tar.gz |
Add a devclass level to the dev sysctl tree, in order to support per-
class variables in addition to per-device variables. In plain English,
this means that dev.foo0.bar is now called dev.foo.0.bar, and it is
possible to to have dev.foo.bar as well.
Diffstat (limited to 'sys/kern/subr_bus.c')
-rw-r--r-- | sys/kern/subr_bus.c | 74 |
1 files changed, 64 insertions, 10 deletions
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index 3ff1f5f..e997897 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -81,6 +81,9 @@ struct devclass { char *name; device_t *devices; /* array of devices indexed by unit */ int maxunit; /* size of devices array */ + + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *sysctl_tree; }; /* @@ -193,7 +196,50 @@ void print_devclass_list(void); */ enum { - DEVICE_SYSCTL_CLASS, + DEVCLASS_SYSCTL_PARENT, +}; + +static int +devclass_sysctl_handler(SYSCTL_HANDLER_ARGS) +{ + devclass_t dc = (devclass_t)arg1; + const char *value; + char *buf; + int error; + + buf = NULL; + switch (arg2) { + case DEVCLASS_SYSCTL_PARENT: + value = dc->parent ? dc->parent->name : NULL; + break; + default: + return (EINVAL); + } + if (value == NULL) + value = "?"; + error = SYSCTL_OUT(req, value, strlen(value)); + if (buf != NULL) + free(buf, M_BUS); + return (error); +} + +static void +devclass_sysctl_init(devclass_t dc) +{ + + if (dc->sysctl_tree != NULL) + return; + sysctl_ctx_init(&dc->sysctl_ctx); + dc->sysctl_tree = SYSCTL_ADD_NODE(&dc->sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_dev), OID_AUTO, dc->name, + CTLFLAG_RD, 0, ""); + SYSCTL_ADD_PROC(&dc->sysctl_ctx, SYSCTL_CHILDREN(dc->sysctl_tree), + OID_AUTO, "%parent", CTLFLAG_RD, + dc, DEVCLASS_SYSCTL_PARENT, devclass_sysctl_handler, "A", + "parent class"); +} + +enum { DEVICE_SYSCTL_DESC, DEVICE_SYSCTL_DRIVER, DEVICE_SYSCTL_LOCATION, @@ -211,9 +257,6 @@ device_sysctl_handler(SYSCTL_HANDLER_ARGS) buf = NULL; switch (arg2) { - case DEVICE_SYSCTL_CLASS: - value = dev->devclass ? dev->devclass->name : NULL; - break; case DEVICE_SYSCTL_DESC: value = dev->desc; break; @@ -245,18 +288,17 @@ device_sysctl_handler(SYSCTL_HANDLER_ARGS) static void device_sysctl_init(device_t dev) { + devclass_t dc = dev->devclass; if (dev->sysctl_tree != NULL) return; + devclass_sysctl_init(dc); sysctl_ctx_init(&dev->sysctl_ctx); dev->sysctl_tree = SYSCTL_ADD_NODE(&dev->sysctl_ctx, - SYSCTL_STATIC_CHILDREN(_dev), OID_AUTO, dev->nameunit, + SYSCTL_CHILDREN(dc->sysctl_tree), OID_AUTO, + dev->nameunit + strlen(dc->name), CTLFLAG_RD, 0, ""); SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree), - OID_AUTO, "%class", CTLFLAG_RD, - dev, DEVICE_SYSCTL_CLASS, device_sysctl_handler, "A", - "device class name"); - SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree), OID_AUTO, "%desc", CTLFLAG_RD, dev, DEVICE_SYSCTL_DESC, device_sysctl_handler, "A", "device description"); @@ -275,7 +317,7 @@ device_sysctl_init(device_t dev) SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree), OID_AUTO, "%parent", CTLFLAG_RD, dev, DEVICE_SYSCTL_PARENT, device_sysctl_handler, "A", - "device parent"); + "parent device"); } static void @@ -915,6 +957,18 @@ devclass_get_parent(devclass_t dc) return (dc->parent); } +struct sysctl_ctx_list * +devclass_get_sysctl_ctx(devclass_t dc) +{ + return (&dc->sysctl_ctx); +} + +struct sysctl_oid * +devclass_get_sysctl_tree(devclass_t dc) +{ + return (dc->sysctl_tree); +} + static int devclass_alloc_unit(devclass_t dc, int *unitp) { |