summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_rman.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2005-03-24 18:13:11 +0000
committerphk <phk@FreeBSD.org>2005-03-24 18:13:11 +0000
commit72133122d480d071966ea6f0d04f570b8ee5ad30 (patch)
tree7e65b6818d46753edcc81dcb5d211d33ce61075c /sys/kern/subr_rman.c
parentb25337dcb44758ef450a424b013dae1a27de588d (diff)
downloadFreeBSD-src-72133122d480d071966ea6f0d04f570b8ee5ad30.zip
FreeBSD-src-72133122d480d071966ea6f0d04f570b8ee5ad30.tar.gz
Move implementation of hw.bus.rman sysctl to subr_rman.c so that
subr_bus.c doesn't need to peek inside struct resource. OK from: imp
Diffstat (limited to 'sys/kern/subr_rman.c')
-rw-r--r--sys/kern/subr_rman.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/sys/kern/subr_rman.c b/sys/kern/subr_rman.c
index 9901c41..f68dd24 100644
--- a/sys/kern/subr_rman.c
+++ b/sys/kern/subr_rman.c
@@ -713,3 +713,90 @@ rman_get_device(struct resource *r)
{
return (r->r_dev);
}
+
+/*
+ * Sysctl interface for scanning the resource lists.
+ *
+ * We take two input parameters; the index into the list of resource
+ * managers, and the resource offset into the list.
+ */
+static int
+sysctl_rman(SYSCTL_HANDLER_ARGS)
+{
+ int *name = (int *)arg1;
+ u_int namelen = arg2;
+ int rman_idx, res_idx;
+ struct rman *rm;
+ struct resource *res;
+ struct u_rman urm;
+ struct u_resource ures;
+ int error;
+
+ if (namelen != 3)
+ return (EINVAL);
+
+ if (bus_data_generation_check(name[0]))
+ return (EINVAL);
+ rman_idx = name[1];
+ res_idx = name[2];
+
+ /*
+ * Find the indexed resource manager
+ */
+ TAILQ_FOREACH(rm, &rman_head, rm_link) {
+ if (rman_idx-- == 0)
+ break;
+ }
+ if (rm == NULL)
+ return (ENOENT);
+
+ /*
+ * If the resource index is -1, we want details on the
+ * resource manager.
+ */
+ if (res_idx == -1) {
+ urm.rm_handle = (uintptr_t)rm;
+ strlcpy(urm.rm_descr, rm->rm_descr, RM_TEXTLEN);
+ urm.rm_start = rm->rm_start;
+ urm.rm_size = rm->rm_end - rm->rm_start + 1;
+ urm.rm_type = rm->rm_type;
+
+ error = SYSCTL_OUT(req, &urm, sizeof(urm));
+ return (error);
+ }
+
+ /*
+ * Find the indexed resource and return it.
+ */
+ TAILQ_FOREACH(res, &rm->rm_list, r_link) {
+ if (res_idx-- == 0) {
+ ures.r_handle = (uintptr_t)res;
+ ures.r_parent = (uintptr_t)res->r_rm;
+ ures.r_device = (uintptr_t)res->r_dev;
+ if (res->r_dev != NULL) {
+ if (device_get_name(res->r_dev) != NULL) {
+ snprintf(ures.r_devname, RM_TEXTLEN,
+ "%s%d",
+ device_get_name(res->r_dev),
+ device_get_unit(res->r_dev));
+ } else {
+ strlcpy(ures.r_devname, "nomatch",
+ RM_TEXTLEN);
+ }
+ } else {
+ ures.r_devname[0] = '\0';
+ }
+ ures.r_start = res->r_start;
+ ures.r_size = res->r_end - res->r_start + 1;
+ ures.r_flags = res->r_flags;
+
+ error = SYSCTL_OUT(req, &ures, sizeof(ures));
+ return (error);
+ }
+ }
+ return (ENOENT);
+}
+
+SYSCTL_NODE(_hw_bus, OID_AUTO, rman, CTLFLAG_RD, sysctl_rman,
+ "kernel resource manager");
+
OpenPOWER on IntegriCloud