hierarchy. The devinfo(8) utility can be used to view that information.
Ported by Sascha Wildner.
Obtained-from: FreeBSD
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD: src/gnu/usr.bin/groff/tmac/mdoc.local,v 1.2.2.19 2003/03/25 10:20:12 murray Exp $
-.\" $DragonFly: src/gnu/usr.bin/groff/tmac/mdoc.local,v 1.25 2008/09/14 20:03:06 swildner Exp $
+.\" $DragonFly: src/gnu/usr.bin/groff/tmac/mdoc.local,v 1.26 2008/09/30 12:20:29 hasso Exp $
.\"
.\" %beginstrip%
.
.ds doc-str-Lb-libcam Common Access Method User Library (libcam, \-lcam)
.ds doc-str-Lb-libcaps CAPS IPC Library (libcaps, \-lcaps)
.ds doc-str-Lb-libcipher FreeSec Crypt Library (libcipher, \-lcipher)
+.ds doc-str-Lb-libdevinfo Device and Resource Information Utility Library (libdevinfo, \-ldevinfo)
.ds doc-str-Lb-libdevstat Device Statistics Library (libdevstat, \-ldevstat)
.ds doc-str-Lb-libfetch File Transfer Library (libfetch, \-lfetch)
.ds doc-str-Lb-libftpio FTP Connection Management Library (libftpio, \-lftpio)
# @(#)Makefile 8.1 (Berkeley) 6/4/93
# $FreeBSD: src/lib/Makefile,v 1.107.2.16 2002/10/10 19:24:35 kbyanc Exp $
-# $DragonFly: src/lib/Makefile,v 1.34 2008/07/23 14:09:05 swildner Exp $
+# $DragonFly: src/lib/Makefile,v 1.35 2008/09/30 12:20:29 hasso Exp $
# To satisfy shared library or ELF linkage when only the libraries being
# built are visible:
SUBDIR= libarchive libbluetooth libcom_err libcrypt libm libmd \
libncurses libradius libskey libtacplus libutil libsbuf \
libalias libatm ${_libbind} ${_libbind9} libbz2 libc ${_libc_r} \
- libcalendar libcam libcompat libdevstat libedit libevent libfetch \
+ libcalendar libcam libcompat libdevinfo libdevstat libedit libevent libfetch \
libftpio libipsec libipx libisc libkcore libkinfo libkvm libmagic \
${_libmilter} ${_libncp} libnetgraph libopie libpam \
libpcap libposix1e libsdp libthread_xu libpthread librpcsvc ${_libsm} \
--- /dev/null
+# $FreeBSD: src/lib/libdevinfo/Makefile,v 1.4 2002/05/13 12:11:54 ru Exp $
+# $DragonFly: src/lib/libdevinfo/Makefile,v 1.1 2008/09/30 12:20:29 hasso Exp $
+
+LIB= devinfo
+SRCS= devinfo.c
+INCS= devinfo.h
+MAN= devinfo.3
+
+.include <bsd.lib.mk>
--- /dev/null
+.\"
+.\" Copyright (c) 2001 Michael Smith <msmith@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/lib/libdevinfo/devinfo.3,v 1.11 2006/09/17 21:27:35 ru Exp $
+.\" $DragonFly: src/lib/libdevinfo/devinfo.3,v 1.1 2008/09/30 12:20:29 hasso Exp $
+.\"
+.Dd September 30, 2008
+.Dt DEVINFO 3
+.Os
+.Sh NAME
+.Nm devinfo ,
+.Nm devinfo_init ,
+.Nm devinfo_free ,
+.Nm devinfo_handle_to_device ,
+.Nm devinfo_handle_to_resource ,
+.Nm devinfo_handle_to_rman ,
+.Nm devinfo_foreach_device_child ,
+.Nm devinfo_foreach_device_resource ,
+.Nm devinfo_foreach_rman_resource ,
+.Nm devinfo_foreach_rman
+.Nd device and resource information utility library
+.Sh LIBRARY
+.Lb libdevinfo
+.Sh SYNOPSIS
+.In devinfo.h
+.Ft int
+.Fn devinfo_init "void"
+.Ft void
+.Fn devinfo_free "void"
+.Ft struct devinfo_dev *
+.Fn devinfo_handle_to_device "devinfo_handle_t handle"
+.Ft struct devinfo_res *
+.Fn devinfo_handle_to_resource "devinfo_handle_t handle"
+.Ft struct devinfo_rman *
+.Fn devinfo_handle_to_rman "devinfo_handle_t handle"
+.Ft int
+.Fo devinfo_foreach_device_child
+.Fa "struct devinfo_dev *parent"
+.Fa "int \*[lp]*fn\*[rp]\*[lp]struct devinfo_dev *child, void *arg\*[rp]"
+.Fa "void *arg"
+.Fc
+.Ft int
+.Fo devinfo_foreach_device_resource
+.Fa "struct devinfo_dev *dev"
+.Fa "int \*[lp]*fn\*[rp]\*[lp]struct devinfo_dev *dev, \:struct devinfo_res *res, void *arg\*[rp]"
+.Fa "void *arg"
+.Fc
+.Ft int
+.Fo devinfo_foreach_rman_resource
+.Fa "struct devinfo_rman *rman"
+.Fa "int \*[lp]*fn\*[rp]\*[lp]struct devinfo_res *res, void *arg\*[rp]"
+.Fa "void *arg"
+.Fc
+.Ft int
+.Fo devinfo_foreach_rman
+.Fa "int \*[lp]*fn\*[rp]\*[lp]struct devinfo_rman *rman, void *arg\*[rp]"
+.Fa "void *arg"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm
+library provides access to the kernel's internal device hierarchy
+and to the I/O resource manager.
+The library uses a
+.Xr sysctl 3
+interface to obtain a snapshot of the kernel's state,
+which is then made available to the application.
+.Pp
+Due to the fact that the information may be logically arranged
+in a number of different fashions,
+the library does not attempt to impose any structure on the data.
+.Pp
+Device, resource, and resource manager information is returned in
+data structures defined in
+.In devinfo.h :
+.Bd -literal -offset indent
+struct devinfo_dev {
+ devinfo_handle_t dd_handle; /* device handle */
+ devinfo_handle_t dd_parent; /* parent handle */
+ char *dd_name; /* name of device */
+ char *dd_desc; /* device description */
+ char *dd_drivername; /* name of attached driver */
+ char *dd_pnpinfo; /* pnp info from parent bus */
+ char *dd_location; /* Where bus thinks dev at */
+ uint32_t dd_devflags; /* API flags */
+ uint16_t dd_flags; /* internal dev flags */
+ device_state_t dd_state; /* attachment state of dev */
+};
+
+struct devinfo_rman {
+ devinfo_handle_t dm_handle; /* resource manager handle */
+ u_long dm_start; /* resource start */
+ u_long dm_size; /* resource size */
+ char *dm_desc; /* resource description */
+};
+
+struct devinfo_res {
+ devinfo_handle_t dr_handle; /* resource handle */
+ devinfo_handle_t dr_rman; /* resource manager handle */
+ devinfo_handle_t dr_device; /* owning device */
+ u_long dr_start; /* region start */
+ u_long dr_size; /* region size */
+};
+.Ed
+.Pp
+The
+.Vt devinfo_handle_t
+values can be used to look up the correspondingly referenced structures.
+.Pp
+.Fn devinfo_init
+takes a snapshot of the kernel's internal device and resource state.
+It returns nonzero
+if after a number of retries a consistent snapshot cannot be obtained.
+.Fn devinfo_init
+must be called before any other functions can be used.
+.Pp
+.Fn devinfo_free
+releases the memory associated with the snapshot.
+Any pointers returned by other functions are invalidated by this,
+and
+.Fn devinfo_init
+must be called again before using any other functions.
+.Pp
+.Fn devinfo_handle_to_device ,
+.Fn devinfo_handle_to_resource
+and
+.Fn devinfo_handle_to_rman
+return pointers to
+.Vt devinfo_dev ,
+.Vt devinfo_res
+and
+.Vt devinfo_rman
+structures respectively based on the
+.Vt devinfo_handle_t
+passed to them.
+These functions can be used to traverse the tree from any node to any
+other node.
+If
+.Fn devinfo_handle_to_device
+is passed the constant
+.Dv DEVINFO_ROOT_DEVICE
+it will return the handle to the root of the device tree.
+.Pp
+.Fn devinfo_foreach_device_child
+invokes its callback argument
+.Fa fn
+on every device which is an immediate child of
+.Fa device .
+The
+.Fa fn
+function is also passed
+.Fa arg ,
+allowing state to be passed to the callback function.
+If
+.Fa fn
+returns a nonzero error value the traversal is halted,
+and
+.Fn devinfo_foreach_device_child
+returns the error value to its caller.
+.Pp
+.Fn devinfo_foreach_device_resource
+invokes its callback argument
+.Fa fn
+on every resource which is owned by
+.Fa device .
+The
+.Fa fn
+function is also passed
+.Fa device
+and
+.Fa arg ,
+allowing state to be passed to the callback function.
+If
+.Fa fn
+returns a nonzero error value the traversal is halted,
+and
+.Fn devinfo_foreach_device_resource
+returns the error value to its caller.
+.Pp
+.Fn devinfo_foreach_rman_resource
+invokes its callback argument
+.Fa fn
+on every resource within the resource manager
+.Fa rman .
+The
+.Fa fn
+function is also passed
+.Fa arg ,
+allowing state to be passed to the callback function.
+If
+.Fa fn
+returns a nonzero error value the traversal is halted,
+and
+.Fn devinfo_foreach_rman_resource
+returns the error value to its caller.
+.Pp
+.Fn devinfo_foreach_rman
+invokes its callback argument
+.Fa fn
+on every resource manager.
+The
+.Fa fn
+function is also passed
+.Fa arg ,
+allowing state to be passed to the callback function.
+If
+.Fa fn
+returns a nonzero error value the traversal is halted,
+and
+.Fn devinfo_foreach_rman
+returns the error value to its caller.
+.Sh SEE ALSO
+.Xr devstat 3
+.Sh HISTORY
+The
+.Nm
+library first appeared in
+.Fx 5.0
+and was imported into
+.Dx 1.11 .
+.Sh AUTHORS
+.An Michael Smith Aq msmith@FreeBSD.org
+.Sh BUGS
+This is the first implementation of the library,
+and the interface is still subject to refinement.
+.Pp
+The interface does not report device classes or drivers,
+making it hard to sort by class or driver.
--- /dev/null
+/*-
+ * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2000 BSDi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libdevinfo/devinfo.c,v 1.9 2006/07/17 09:33:24 stefanf Exp $
+ * $DragonFly: src/lib/libdevinfo/devinfo.c,v 1.1 2008/09/30 12:20:29 hasso Exp $
+ */
+
+/*
+ * An interface to the FreeBSD kernel's bus/device information interface.
+ *
+ * This interface is implemented with the
+ *
+ * hw.bus
+ * hw.bus.devices
+ * hw.bus.rman
+ *
+ * sysctls. The interface is not meant for general user application
+ * consumption.
+ *
+ * Device information is obtained by scanning a linear list of all devices
+ * maintained by the kernel. The actual device structure pointers are
+ * handed out as opaque handles in order to allow reconstruction of the
+ * logical toplogy in user space.
+ *
+ * Resource information is obtained by scanning the kernel's resource
+ * managers and fetching their contents. Ownership of resources is
+ * tracked using the device's structure pointer again as a handle.
+ *
+ * In order to ensure coherency of the library's picture of the kernel,
+ * a generation count is maintained by the kernel. The initial generation
+ * count is obtained (along with the interface version) from the hw.bus
+ * sysctl, and must be passed in with every request. If the generation
+ * number supplied by the library does not match the kernel's current
+ * generation number, the request is failed and the library must discard
+ * the data it has received and rescan.
+ *
+ * The information obtained from the kernel is exported to consumers of
+ * this library through a variety of interfaces.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "devinfo.h"
+#include "devinfo_var.h"
+
+static int devinfo_init_devices(int generation);
+static int devinfo_init_resources(int generation);
+
+TAILQ_HEAD(,devinfo_i_dev) devinfo_dev;
+TAILQ_HEAD(,devinfo_i_rman) devinfo_rman;
+TAILQ_HEAD(,devinfo_i_res) devinfo_res;
+
+static int devinfo_initted = 0;
+static int devinfo_generation = 0;
+
+#if 0
+# define debug(...) do { \
+ fprintf(stderr, "%s:", __func__); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+} while (0)
+#else
+# define debug(...)
+#endif
+
+/*
+ * Initialise our local database with the contents of the kernel's
+ * tables.
+ */
+int
+devinfo_init(void)
+{
+ struct u_businfo ubus;
+ size_t ub_size;
+ int error, retries;
+
+ if (!devinfo_initted) {
+ TAILQ_INIT(&devinfo_dev);
+ TAILQ_INIT(&devinfo_rman);
+ TAILQ_INIT(&devinfo_res);
+ }
+
+ /*
+ * Get the generation count and interface version, verify that we
+ * are compatible with the kernel.
+ */
+ for (retries = 0; retries < 10; retries++) {
+ debug("get interface version");
+ ub_size = sizeof(ubus);
+ if (sysctlbyname("hw.bus.info", &ubus,
+ &ub_size, NULL, 0) != 0) {
+ warn("sysctlbyname(\"hw.bus.info\", ...) failed");
+ return(EINVAL);
+ }
+ if ((ub_size != sizeof(ubus)) ||
+ (ubus.ub_version != BUS_USER_VERSION)) {
+ warn("kernel bus interface version mismatch");
+ return(EINVAL);
+ }
+ debug("generation count is %d", ubus.ub_generation);
+
+ /*
+ * Don't rescan if the generation count hasn't changed.
+ */
+ if (ubus.ub_generation == devinfo_generation)
+ return(0);
+
+ /*
+ * Generation count changed, rescan
+ */
+ devinfo_free();
+ devinfo_initted = 0;
+ devinfo_generation = 0;
+
+ if ((error = devinfo_init_devices(ubus.ub_generation)) != 0) {
+ devinfo_free();
+ if (error == EINVAL)
+ continue;
+ break;
+ }
+ if ((error = devinfo_init_resources(ubus.ub_generation)) != 0) {
+ devinfo_free();
+ if (error == EINVAL)
+ continue;
+ break;
+ }
+ devinfo_initted = 1;
+ devinfo_generation = ubus.ub_generation;
+ return(0);
+ }
+ debug("scan failed after %d retries", retries);
+ errno = error;
+ return(1);
+}
+
+static int
+devinfo_init_devices(int generation)
+{
+ struct u_device udev;
+ struct devinfo_i_dev *dd;
+ int dev_idx;
+ int dev_ptr;
+ int name2oid[2];
+ int oid[CTL_MAXNAME + 12];
+ size_t oidlen, rlen;
+ char *name;
+ int error;
+
+ /*
+ * Find the OID for the rman interface node.
+ * This is just the usual evil, undocumented sysctl juju.
+ */
+ name2oid[0] = 0;
+ name2oid[1] = 3;
+ oidlen = sizeof(oid);
+ name = "hw.bus.devices";
+ error = sysctl(name2oid, 2, oid, &oidlen, name, strlen(name));
+ if (error < 0) {
+ warnx("can't find hw.bus.devices sysctl node");
+ return(ENOENT);
+ }
+ oidlen /= sizeof(int);
+ if (oidlen > CTL_MAXNAME) {
+ warnx("hw.bus.devices oid is too large");
+ return(EINVAL);
+ }
+ oid[oidlen++] = generation;
+ dev_ptr = oidlen++;
+
+ /*
+ * Scan devices.
+ *
+ * Stop after a fairly insane number to avoid death in the case
+ * of kernel corruption.
+ */
+ for (dev_idx = 0; dev_idx < 1000; dev_idx++) {
+
+ /*
+ * Get the device information.
+ */
+ oid[dev_ptr] = dev_idx;
+ rlen = sizeof(udev);
+ error = sysctl(oid, oidlen, &udev, &rlen, NULL, 0);
+ if (error < 0) {
+ if (errno == ENOENT) /* end of list */
+ break;
+ if (errno != EINVAL) /* gen count skip, restart */
+ warn("sysctl hw.bus.devices.%d", dev_idx);
+ return(errno);
+ }
+ if ((dd = malloc(sizeof(*dd))) == NULL)
+ return(ENOMEM);
+ dd->dd_dev.dd_handle = udev.dv_handle;
+ dd->dd_dev.dd_parent = udev.dv_parent;
+ snprintf(dd->dd_name, sizeof(dd->dd_name), "%s", udev.dv_name);
+ dd->dd_dev.dd_name = &dd->dd_name[0];
+ snprintf(dd->dd_desc, sizeof(dd->dd_desc), "%s", udev.dv_desc);
+ dd->dd_dev.dd_desc = &dd->dd_desc[0];
+ snprintf(dd->dd_drivername, sizeof(dd->dd_drivername), "%s",
+ udev.dv_drivername);
+ dd->dd_dev.dd_drivername = &dd->dd_drivername[0];
+ snprintf(dd->dd_pnpinfo, sizeof(dd->dd_pnpinfo), "%s",
+ udev.dv_pnpinfo);
+ dd->dd_dev.dd_pnpinfo = &dd->dd_pnpinfo[0];
+ snprintf(dd->dd_location, sizeof(dd->dd_location), "%s",
+ udev.dv_location);
+ dd->dd_dev.dd_location = &dd->dd_location[0];
+ dd->dd_dev.dd_devflags = udev.dv_devflags;
+ dd->dd_dev.dd_flags = udev.dv_flags;
+ dd->dd_dev.dd_state = udev.dv_state;
+ TAILQ_INSERT_TAIL(&devinfo_dev, dd, dd_link);
+ }
+ debug("fetched %d devices", dev_idx);
+ return(0);
+}
+
+static int
+devinfo_init_resources(int generation)
+{
+ struct u_rman urman;
+ struct devinfo_i_rman *dm;
+ struct u_resource ures;
+ struct devinfo_i_res *dr;
+ int rman_idx, res_idx;
+ int rman_ptr, res_ptr;
+ int name2oid[2];
+ int oid[CTL_MAXNAME + 12];
+ size_t oidlen, rlen;
+ char *name;
+ int error;
+
+ /*
+ * Find the OID for the rman interface node.
+ * This is just the usual evil, undocumented sysctl juju.
+ */
+ name2oid[0] = 0;
+ name2oid[1] = 3;
+ oidlen = sizeof(oid);
+ name = "hw.bus.rman";
+ error = sysctl(name2oid, 2, oid, &oidlen, name, strlen(name));
+ if (error < 0) {
+ warnx("can't find hw.bus.rman sysctl node");
+ return(ENOENT);
+ }
+ oidlen /= sizeof(int);
+ if (oidlen > CTL_MAXNAME) {
+ warnx("hw.bus.rman oid is too large");
+ return(EINVAL);
+ }
+ oid[oidlen++] = generation;
+ rman_ptr = oidlen++;
+ res_ptr = oidlen++;
+
+ /*
+ * Scan resource managers.
+ *
+ * Stop after a fairly insane number to avoid death in the case
+ * of kernel corruption.
+ */
+ for (rman_idx = 0; rman_idx < 255; rman_idx++) {
+
+ /*
+ * Get the resource manager information.
+ */
+ oid[rman_ptr] = rman_idx;
+ oid[res_ptr] = -1;
+ rlen = sizeof(urman);
+ error = sysctl(oid, oidlen, &urman, &rlen, NULL, 0);
+ if (error < 0) {
+ if (errno == ENOENT) /* end of list */
+ break;
+ if (errno != EINVAL) /* gen count skip, restart */
+ warn("sysctl hw.bus.rman.%d", rman_idx);
+ return(errno);
+ }
+ if ((dm = malloc(sizeof(*dm))) == NULL)
+ return(ENOMEM);
+ dm->dm_rman.dm_handle = urman.rm_handle;
+ dm->dm_rman.dm_start = urman.rm_start;
+ dm->dm_rman.dm_size = urman.rm_size;
+ snprintf(dm->dm_desc, DEVINFO_STRLEN, "%s", urman.rm_descr);
+ dm->dm_rman.dm_desc = &dm->dm_desc[0];
+ TAILQ_INSERT_TAIL(&devinfo_rman, dm, dm_link);
+
+ /*
+ * Scan resources on this resource manager.
+ *
+ * Stop after a fairly insane number to avoid death in the case
+ * of kernel corruption.
+ */
+ for (res_idx = 0; res_idx < 1000; res_idx++) {
+ /*
+ * Get the resource information.
+ */
+ oid[res_ptr] = res_idx;
+ rlen = sizeof(ures);
+ error = sysctl(oid, oidlen, &ures, &rlen, NULL, 0);
+ if (error < 0) {
+ if (errno == ENOENT) /* end of list */
+ break;
+ if (errno != EINVAL) /* gen count skip */
+ warn("sysctl hw.bus.rman.%d.%d",
+ rman_idx, res_idx);
+ return(errno);
+ }
+ if ((dr = malloc(sizeof(*dr))) == NULL)
+ return(ENOMEM);
+ dr->dr_res.dr_handle = ures.r_handle;
+ dr->dr_res.dr_rman = ures.r_parent;
+ dr->dr_res.dr_device = ures.r_device;
+ dr->dr_res.dr_start = ures.r_start;
+ dr->dr_res.dr_size = ures.r_size;
+ TAILQ_INSERT_TAIL(&devinfo_res, dr, dr_link);
+ }
+ debug("fetched %d resources", res_idx);
+ }
+ debug("scanned %d resource managers", rman_idx);
+ return(0);
+}
+
+/*
+ * Free the list contents.
+ */
+void
+devinfo_free(void)
+{
+ struct devinfo_i_dev *dd;
+ struct devinfo_i_rman *dm;
+ struct devinfo_i_res *dr;
+
+ while ((dd = TAILQ_FIRST(&devinfo_dev)) != NULL) {
+ TAILQ_REMOVE(&devinfo_dev, dd, dd_link);
+ free(dd);
+ }
+ while ((dm = TAILQ_FIRST(&devinfo_rman)) != NULL) {
+ TAILQ_REMOVE(&devinfo_rman, dm, dm_link);
+ free(dm);
+ }
+ while ((dr = TAILQ_FIRST(&devinfo_res)) != NULL) {
+ TAILQ_REMOVE(&devinfo_res, dr, dr_link);
+ free(dr);
+ }
+ devinfo_initted = 0;
+ devinfo_generation = 0;
+}
+
+/*
+ * Find a device by its handle.
+ */
+struct devinfo_dev *
+devinfo_handle_to_device(devinfo_handle_t handle)
+{
+ struct devinfo_i_dev *dd;
+
+ /*
+ * Find the root device, whose parent is NULL
+ */
+ if (handle == DEVINFO_ROOT_DEVICE) {
+ TAILQ_FOREACH(dd, &devinfo_dev, dd_link)
+ if (dd->dd_dev.dd_parent == DEVINFO_ROOT_DEVICE)
+ return(&dd->dd_dev);
+ return(NULL);
+ }
+
+ /*
+ * Scan for the device
+ */
+ TAILQ_FOREACH(dd, &devinfo_dev, dd_link)
+ if (dd->dd_dev.dd_handle == handle)
+ return(&dd->dd_dev);
+ return(NULL);
+}
+
+/*
+ * Find a resource by its handle.
+ */
+struct devinfo_res *
+devinfo_handle_to_resource(devinfo_handle_t handle)
+{
+ struct devinfo_i_res *dr;
+
+ TAILQ_FOREACH(dr, &devinfo_res, dr_link)
+ if (dr->dr_res.dr_handle == handle)
+ return(&dr->dr_res);
+ return(NULL);
+}
+
+/*
+ * Find a resource manager by its handle.
+ */
+struct devinfo_rman *
+devinfo_handle_to_rman(devinfo_handle_t handle)
+{
+ struct devinfo_i_rman *dm;
+
+ TAILQ_FOREACH(dm, &devinfo_rman, dm_link)
+ if (dm->dm_rman.dm_handle == handle)
+ return(&dm->dm_rman);
+ return(NULL);
+}
+
+/*
+ * Iterate over the children of a device, calling (fn) on each. If
+ * (fn) returns nonzero, abort the scan and return.
+ */
+int
+devinfo_foreach_device_child(struct devinfo_dev *parent,
+ int (* fn)(struct devinfo_dev *child, void *arg),
+ void *arg)
+{
+ struct devinfo_i_dev *dd;
+ int error;
+
+ TAILQ_FOREACH(dd, &devinfo_dev, dd_link)
+ if (dd->dd_dev.dd_parent == parent->dd_handle)
+ if ((error = fn(&dd->dd_dev, arg)) != 0)
+ return(error);
+ return(0);
+}
+
+/*
+ * Iterate over all the resources owned by a device, calling (fn) on each.
+ * If (fn) returns nonzero, abort the scan and return.
+ */
+int
+devinfo_foreach_device_resource(struct devinfo_dev *dev,
+ int (* fn)(struct devinfo_dev *dev, struct devinfo_res *res, void *arg),
+ void *arg)
+{
+ struct devinfo_i_res *dr;
+ int error;
+
+ TAILQ_FOREACH(dr, &devinfo_res, dr_link)
+ if (dr->dr_res.dr_device == dev->dd_handle)
+ if ((error = fn(dev, &dr->dr_res, arg)) != 0)
+ return(error);
+ return(0);
+}
+
+/*
+ * Iterate over all the resources owned by a resource manager, calling (fn)
+ * on each. If (fn) returns nonzero, abort the scan and return.
+ */
+extern int
+devinfo_foreach_rman_resource(struct devinfo_rman *rman,
+ int (* fn)(struct devinfo_res *res, void *arg),
+ void *arg)
+{
+ struct devinfo_i_res *dr;
+ int error;
+
+ TAILQ_FOREACH(dr, &devinfo_res, dr_link)
+ if (dr->dr_res.dr_rman == rman->dm_handle)
+ if ((error = fn(&dr->dr_res, arg)) != 0)
+ return(error);
+ return(0);
+}
+
+/*
+ * Iterate over all the resource managers, calling (fn) on each. If (fn)
+ * returns nonzero, abort the scan and return.
+ */
+extern int
+devinfo_foreach_rman(int (* fn)(struct devinfo_rman *rman, void *arg),
+ void *arg)
+{
+ struct devinfo_i_rman *dm;
+ int error;
+
+ TAILQ_FOREACH(dm, &devinfo_rman, dm_link)
+ if ((error = fn(&dm->dm_rman, arg)) != 0)
+ return(error);
+ return(0);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2000 BSDi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libdevinfo/devinfo.h,v 1.5 2005/08/31 14:57:39 rodrigc Exp $
+ * $DragonFly: src/lib/libdevinfo/devinfo.h,v 1.1 2008/09/30 12:20:29 hasso Exp $
+ */
+
+#ifndef _DEVINFO_H_INCLUDED
+#define _DEVINFO_H_INCLUDED
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+typedef __uintptr_t devinfo_handle_t;
+#define DEVINFO_ROOT_DEVICE ((devinfo_handle_t)0)
+
+/*
+ * State of the device.
+ */
+/* XXX not sure if I want a copy here, or expose sys/bus.h */
+typedef enum devinfo_state {
+ DIS_NOTPRESENT, /* not probed or probe failed */
+ DIS_ALIVE, /* probe succeeded */
+ DIS_ATTACHED, /* attach method called */
+ DIS_BUSY /* device is open */
+} devinfo_state_t;
+
+struct devinfo_dev {
+ devinfo_handle_t dd_handle; /* device handle */
+ devinfo_handle_t dd_parent; /* parent handle */
+
+ char *dd_name; /* name of device */
+ char *dd_desc; /* device description */
+ char *dd_drivername; /* name of attached driver*/
+ char *dd_pnpinfo; /* pnp info from parent bus */
+ char *dd_location; /* Where bus thinks dev at */
+ uint32_t dd_devflags; /* API flags */
+ uint16_t dd_flags; /* internal dev flags */
+ devinfo_state_t dd_state; /* attacement state of dev */
+};
+
+struct devinfo_rman {
+ devinfo_handle_t dm_handle; /* resource manager handle */
+
+ unsigned long dm_start; /* resource start */
+ unsigned long dm_size; /* resource size */
+
+ char *dm_desc; /* resource description */
+};
+
+struct devinfo_res {
+ devinfo_handle_t dr_handle; /* resource handle */
+ devinfo_handle_t dr_rman; /* resource manager handle */
+ devinfo_handle_t dr_device; /* owning device */
+
+ unsigned long dr_start; /* region start */
+ unsigned long dr_size; /* region size */
+ /* XXX add flags */
+};
+
+__BEGIN_DECLS
+
+/*
+ * Acquire a coherent copy of the kernel's device and resource tables.
+ * This must return success (zero) before any other interfaces will
+ * function. Sets errno on failure.
+ */
+extern int devinfo_init(void);
+
+/*
+ * Release the storage associated with the internal copy of the device
+ * and resource tables. devinfo_init must be called before any attempt
+ * is made to use any other interfaces.
+ */
+extern void devinfo_free(void);
+
+/*
+ * Find a device/resource/resource manager by its handle.
+ */
+extern struct devinfo_dev
+ *devinfo_handle_to_device(devinfo_handle_t handle);
+extern struct devinfo_res
+ *devinfo_handle_to_resource(devinfo_handle_t handle);
+extern struct devinfo_rman
+ *devinfo_handle_to_rman(devinfo_handle_t handle);
+
+/*
+ * Iterate over the children of a device, calling (fn) on each. If
+ * (fn) returns nonzero, abort the scan and return.
+ */
+extern int
+ devinfo_foreach_device_child(struct devinfo_dev *parent,
+ int (* fn)(struct devinfo_dev *child, void *arg),
+ void *arg);
+
+/*
+ * Iterate over all the resources owned by a device, calling (fn) on each.
+ * If (fn) returns nonzero, abort the scan and return.
+ */
+extern int
+ devinfo_foreach_device_resource(struct devinfo_dev *dev,
+ int (* fn)(struct devinfo_dev *dev,
+ struct devinfo_res *res, void *arg),
+ void *arg);
+
+/*
+ * Iterate over all the resources owned by a resource manager, calling (fn)
+ * on each. If (fn) returns nonzero, abort the scan and return.
+ */
+extern int
+ devinfo_foreach_rman_resource(struct devinfo_rman *rman,
+ int (* fn)(struct devinfo_res *res, void *arg),
+ void *arg);
+
+/*
+ * Iterate over all the resource managers, calling (fn) on each. If (fn)
+ * returns nonzero, abort the scan and return.
+ */
+extern int
+ devinfo_foreach_rman(int (* fn)(struct devinfo_rman *rman, void *arg),
+ void *arg);
+
+__END_DECLS
+
+#endif /* ! _DEVINFO_H_INCLUDED */
--- /dev/null
+/*-
+ * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2000 BSDi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libdevinfo/devinfo_var.h,v 1.3 2003/02/17 18:56:00 imp Exp $
+ * $DragonFly: src/lib/libdevinfo/devinfo_var.h,v 1.1 2008/09/30 12:20:29 hasso Exp $
+ */
+
+#define _KERNEL_STRUCTURES
+
+#include <sys/rman.h>
+#include <sys/bus.h>
+
+/*
+ * This is defined by the version 1 interface.
+ */
+#define DEVINFO_STRLEN 32
+
+/*
+ * Devices.
+ *
+ * Internal structure contains string buffers and list linkage;
+ */
+struct devinfo_i_dev {
+ struct devinfo_dev dd_dev;
+ char dd_name[DEVINFO_STRLEN];
+ char dd_desc[DEVINFO_STRLEN];
+ char dd_drivername[DEVINFO_STRLEN];
+ char dd_pnpinfo[DEVINFO_STRLEN * 4];
+ char dd_location[DEVINFO_STRLEN * 4];
+ uint32_t dd_devflags;
+ uint16_t dd_flags;
+ device_state_t dd_state;
+ TAILQ_ENTRY(devinfo_i_dev) dd_link;
+};
+
+/*
+ * Resources.
+ *
+ * Internal structures contain string buffers and list linkage;
+ */
+struct devinfo_i_rman {
+ struct devinfo_rman dm_rman;
+ char dm_desc[32];
+ TAILQ_ENTRY(devinfo_i_rman) dm_link;
+};
+
+struct devinfo_i_res {
+ struct devinfo_res dr_res;
+ TAILQ_ENTRY(devinfo_i_res) dr_link;
+};
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/kern/subr_bus.c,v 1.54.2.9 2002/10/10 15:13:32 jhb Exp $
- * $DragonFly: src/sys/kern/subr_bus.c,v 1.44 2008/09/29 06:59:45 hasso Exp $
+ * $DragonFly: src/sys/kern/subr_bus.c,v 1.45 2008/09/30 12:20:29 hasso Exp $
*/
#include "opt_bus.h"
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
-#ifdef DEVICE_SYSCTLS
-#include <sys/sysctl.h>
-#endif
#include <sys/kobj.h>
#include <sys/bus_private.h>
+#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/thread2.h>
+SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL);
+
MALLOC_DEFINE(M_BUS, "bus", "Bus data structures");
#ifdef BUS_DEBUG
#define print_devclass_list() /* nop */
#endif
-#ifdef DEVICE_SYSCTLS
-static void device_register_oids(device_t dev);
-static void device_unregister_oids(device_t dev);
-#endif
static void device_attach_async(device_t dev);
static void device_attach_thread(void *arg);
static int device_doattach(device_t dev);
static int numasyncthreads;
TUNABLE_INT("kern.do_async_attach", &do_async_attach);
+TAILQ_HEAD(,device) bus_data_devices;
+static int bus_data_generation = 1;
+
kobj_method_t null_methods[] = {
{ 0, 0 }
};
dc->maxunit = 0;
TAILQ_INIT(&dc->drivers);
TAILQ_INSERT_TAIL(&devclasses, dc, link);
+
+ bus_data_generation_update();
+
}
if (parentname && dc && !dc->parent)
dc->parent = devclass_find_internal(parentname, NULL, FALSE);
}
}
+ bus_data_generation_update();
return(0);
}
kobj_class_uninstantiate(driver);
+ bus_data_generation_update();
return(0);
}
dev->devclass = dc;
ksnprintf(dev->nameunit, buflen, "%s%d", dc->name, dev->unit);
-#ifdef DEVICE_SYSCTLS
- device_register_oids(dev);
-#endif
-
return(0);
}
kfree(dev->nameunit, M_BUS);
dev->nameunit = NULL;
-#ifdef DEVICE_SYSCTLS
- device_unregister_oids(dev);
-#endif
-
return(0);
}
dev->state = DS_NOTPRESENT;
+ TAILQ_INSERT_TAIL(&bus_data_devices, dev, devlink);
+ bus_data_generation_update();
+
return(dev);
}
TAILQ_INSERT_TAIL(&dev->children, child, link);
}
+ bus_data_generation_update();
return(child);
}
if (child->devclass)
devclass_delete_device(child->devclass, child);
TAILQ_REMOVE(&dev->children, child, link);
+ TAILQ_REMOVE(&bus_data_devices, child, devlink);
device_set_desc(child, NULL);
kobj_delete((kobj_t)child, M_BUS);
+ bus_data_generation_update();
return(0);
}
*/
DEVICE_PROBE(child);
}
+
+ bus_data_generation_update();
child->state = DS_ALIVE;
return(0);
}
strcpy(dev->desc, desc);
dev->flags |= DF_DESCMALLOCED;
}
- } else
+ } else {
/* Avoid a -Wcast-qual warning */
dev->desc = (char *)(uintptr_t) desc;
-
-#ifdef DEVICE_SYSCTLS
- {
- struct sysctl_oid *oid = &dev->oid[1];
- oid->oid_arg1 = dev->desc ? dev->desc : "";
- oid->oid_arg2 = dev->desc ? strlen(dev->desc) : 0;
}
-#endif
+
+ bus_data_generation_update();
}
void
device_set_devclass(device_t dev, const char *classname)
{
devclass_t dc;
+ int error;
if (!classname) {
if (dev->devclass)
if (!dc)
return(ENOMEM);
- return(devclass_add_device(dc, dev));
+ error = devclass_add_device(dc, dev);
+
+ bus_data_generation_update();
+ return(error);
}
int
return(ENOMEM);
}
}
- } else
+ } else {
kobj_init((kobj_t) dev, &null_class);
+ }
+
+ bus_data_generation_update();
return(0);
}
return(err);
dev->unit = unit;
err = devclass_add_device(dc, dev);
- return(err);
-}
-
-#ifdef DEVICE_SYSCTLS
-
-/*
- * Sysctl nodes for devices.
- */
-
-SYSCTL_NODE(_hw, OID_AUTO, devices, CTLFLAG_RW, 0, "A list of all devices");
-
-static int
-sysctl_handle_children(SYSCTL_HANDLER_ARGS)
-{
- device_t dev = arg1;
- device_t child;
- int first = 1, error = 0;
-
- TAILQ_FOREACH(child, &dev->children, link)
- if (child->nameunit) {
- if (!first) {
- error = SYSCTL_OUT(req, ",", 1);
- if (error)
- return error;
- } else
- first = 0;
- error = SYSCTL_OUT(req, child->nameunit,
- strlen(child->nameunit));
- if (error)
- return(error);
- }
-
- error = SYSCTL_OUT(req, "", 1);
-
- return(error);
-}
-
-static int
-sysctl_handle_state(SYSCTL_HANDLER_ARGS)
-{
- device_t dev = arg1;
-
- switch (dev->state) {
- case DS_NOTPRESENT:
- return SYSCTL_OUT(req, "notpresent", sizeof("notpresent"));
- case DS_ALIVE:
- return SYSCTL_OUT(req, "alive", sizeof("alive"));
- case DS_INPROGRESS:
- return SYSCTL_OUT(req, "in-progress", sizeof("in-progress"));
- case DS_ATTACHED:
- return SYSCTL_OUT(req, "attached", sizeof("attached"));
- case DS_BUSY:
- return SYSCTL_OUT(req, "busy", sizeof("busy"));
- default:
- return (0);
- }
-}
-
-static void
-device_register_oids(device_t dev)
-{
- struct sysctl_oid* oid;
-
- oid = &dev->oid[0];
- bzero(oid, sizeof(*oid));
- oid->oid_parent = &sysctl__hw_devices_children;
- oid->oid_number = OID_AUTO;
- oid->oid_kind = CTLTYPE_NODE | CTLFLAG_RW;
- oid->oid_arg1 = &dev->oidlist[0];
- oid->oid_arg2 = 0;
- oid->oid_name = dev->nameunit;
- oid->oid_handler = 0;
- oid->oid_fmt = "N";
- SLIST_INIT(&dev->oidlist[0]);
- sysctl_register_oid(oid);
-
- oid = &dev->oid[1];
- bzero(oid, sizeof(*oid));
- oid->oid_parent = &dev->oidlist[0];
- oid->oid_number = OID_AUTO;
- oid->oid_kind = CTLTYPE_STRING | CTLFLAG_RD;
- oid->oid_arg1 = dev->desc ? dev->desc : "";
- oid->oid_arg2 = dev->desc ? strlen(dev->desc) : 0;
- oid->oid_name = "desc";
- oid->oid_handler = sysctl_handle_string;
- oid->oid_fmt = "A";
- sysctl_register_oid(oid);
-
- oid = &dev->oid[2];
- bzero(oid, sizeof(*oid));
- oid->oid_parent = &dev->oidlist[0];
- oid->oid_number = OID_AUTO;
- oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD;
- oid->oid_arg1 = dev;
- oid->oid_arg2 = 0;
- oid->oid_name = "children";
- oid->oid_handler = sysctl_handle_children;
- oid->oid_fmt = "A";
- sysctl_register_oid(oid);
-
- oid = &dev->oid[3];
- bzero(oid, sizeof(*oid));
- oid->oid_parent = &dev->oidlist[0];
- oid->oid_number = OID_AUTO;
- oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD;
- oid->oid_arg1 = dev;
- oid->oid_arg2 = 0;
- oid->oid_name = "state";
- oid->oid_handler = sysctl_handle_state;
- oid->oid_fmt = "A";
- sysctl_register_oid(oid);
-}
+ if (err)
+ return(err);
-static void
-device_unregister_oids(device_t dev)
-{
- sysctl_unregister_oid(&dev->oid[0]);
- sysctl_unregister_oid(&dev->oid[1]);
- sysctl_unregister_oid(&dev->oid[2]);
+ bus_data_generation_update();
+ return(0);
}
-#endif
-
/*======================================*/
/*
* Access functions for device resources.
struct resource_list_entry *rle = resource_list_find(rl, type, rid);
if (rle) {
+ if (rle->res != NULL)
+ panic("resource_list_delete: resource has not been released");
SLIST_REMOVE(rl, rle, resource_list_entry, link);
kfree(rle, M_BUS);
}
if (!rle)
return(0); /* no resource of that type/rid */
+
if (rle->res)
panic("resource_list_alloc: resource entry is busy");
{
switch (what) {
case MOD_LOAD:
+ TAILQ_INIT(&bus_data_devices);
root_bus = make_device(NULL, "root", 0);
root_bus->desc = "System root bus";
kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);
return(0);
return(value);
}
+
+/*
+ * User-space access to the device tree.
+ *
+ * We implement a small set of nodes:
+ *
+ * hw.bus Single integer read method to obtain the
+ * current generation count.
+ * hw.bus.devices Reads the entire device tree in flat space.
+ * hw.bus.rman Resource manager interface
+ *
+ * We might like to add the ability to scan devclasses and/or drivers to
+ * determine what else is currently loaded/available.
+ */
+
+static int
+sysctl_bus(SYSCTL_HANDLER_ARGS)
+{
+ struct u_businfo ubus;
+
+ ubus.ub_version = BUS_USER_VERSION;
+ ubus.ub_generation = bus_data_generation;
+
+ return (SYSCTL_OUT(req, &ubus, sizeof(ubus)));
+}
+SYSCTL_NODE(_hw_bus, OID_AUTO, info, CTLFLAG_RW, sysctl_bus,
+ "bus-related data");
+
+static int
+sysctl_devices(SYSCTL_HANDLER_ARGS)
+{
+ int *name = (int *)arg1;
+ u_int namelen = arg2;
+ int index;
+ struct device *dev;
+ struct u_device udev; /* XXX this is a bit big */
+ int error;
+
+ if (namelen != 2)
+ return (EINVAL);
+
+ if (bus_data_generation_check(name[0]))
+ return (EINVAL);
+
+ index = name[1];
+
+ /*
+ * Scan the list of devices, looking for the requested index.
+ */
+ TAILQ_FOREACH(dev, &bus_data_devices, devlink) {
+ if (index-- == 0)
+ break;
+ }
+ if (dev == NULL)
+ return (ENOENT);
+
+ /*
+ * Populate the return array.
+ */
+ bzero(&udev, sizeof(udev));
+ udev.dv_handle = (uintptr_t)dev;
+ udev.dv_parent = (uintptr_t)dev->parent;
+ if (dev->nameunit != NULL)
+ strlcpy(udev.dv_name, dev->nameunit, sizeof(udev.dv_name));
+ if (dev->desc != NULL)
+ strlcpy(udev.dv_desc, dev->desc, sizeof(udev.dv_desc));
+ if (dev->driver != NULL && dev->driver->name != NULL)
+ strlcpy(udev.dv_drivername, dev->driver->name,
+ sizeof(udev.dv_drivername));
+ bus_child_pnpinfo_str(dev, udev.dv_pnpinfo, sizeof(udev.dv_pnpinfo));
+ bus_child_location_str(dev, udev.dv_location, sizeof(udev.dv_location));
+ udev.dv_devflags = dev->devflags;
+ udev.dv_flags = dev->flags;
+ udev.dv_state = dev->state;
+ error = SYSCTL_OUT(req, &udev, sizeof(udev));
+ return (error);
+}
+
+SYSCTL_NODE(_hw_bus, OID_AUTO, devices, CTLFLAG_RD, sysctl_devices,
+ "system device tree");
+
+int
+bus_data_generation_check(int generation)
+{
+ if (generation != bus_data_generation)
+ return (1);
+
+ /* XXX generate optimised lists here? */
+ return (0);
+}
+
+void
+bus_data_generation_update(void)
+{
+ bus_data_generation++;
+}
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/kern/subr_rman.c,v 1.10.2.1 2001/06/05 08:06:08 imp Exp $
- * $DragonFly: src/sys/kern/subr_rman.c,v 1.14 2008/01/05 14:02:38 swildner Exp $
+ * $DragonFly: src/sys/kern/subr_rman.c,v 1.15 2008/09/30 12:20:29 hasso Exp $
*/
/*
return(RF_ALIGNMENT_LOG2(i));
}
+
+/*
+ * 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.
+ */
+ CIRCLEQ_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) {
+ ksnprintf(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");
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/sys/bus.h,v 1.30.2.5 2004/03/17 17:54:25 njl Exp $
- * $DragonFly: src/sys/sys/bus.h,v 1.29 2008/09/29 06:59:45 hasso Exp $
+ * $DragonFly: src/sys/sys/bus.h,v 1.30 2008/09/30 12:20:29 hasso Exp $
*/
#ifndef _SYS_BUS_H_
typedef void driver_intr_t(void*);
+/*
+ * Interface information structure.
+ */
+struct u_businfo {
+ int ub_version; /* interface version */
+#define BUS_USER_VERSION 1
+ int ub_generation; /* generation count */
+};
+
+/*
+ * State of the device.
+ */
+typedef enum device_state {
+ DS_NOTPRESENT, /* not probed or probe failed */
+ DS_ALIVE, /* probe succeeded */
+ DS_INPROGRESS, /* attach in progress */
+ DS_ATTACHED, /* attach method called */
+ DS_BUSY /* device is open */
+} device_state_t;
+
+/*
+ * Device information exported to userspace.
+ */
+struct u_device {
+ uintptr_t dv_handle;
+ uintptr_t dv_parent;
+
+ char dv_name[32]; /* Name of device in tree. */
+ char dv_desc[32]; /* Driver description */
+ char dv_drivername[32]; /* Driver name */
+ char dv_pnpinfo[128]; /* Plug and play info */
+ char dv_location[128]; /* Where is the device? */
+ uint32_t dv_devflags; /* API Flags for device */
+ uint16_t dv_flags; /* flags for dev date */
+ device_state_t dv_state; /* State of attachment */
+ /* XXX more driver info? */
+};
+
/*
* Interrupt features mask. Note that DragonFly no longer implements
* INTR_TYPE_* flags.
typedef int (*devop_t)(void);
-typedef enum device_state {
- DS_NOTPRESENT, /* not probed or probe failed */
- DS_ALIVE, /* probe succeeded */
- DS_INPROGRESS, /* attach in progress */
- DS_ATTACHED, /* attach method called */
- DS_BUSY /* device is open */
-} device_state_t;
-
/*
* Definitions for drivers which need to keep simple lists of resources
* for their child devices.
const char *value);
int resource_count(void);
+/*
+ * Functions for maintaining and checking consistency of
+ * bus information exported to userspace.
+ */
+int bus_data_generation_check(int generation);
+void bus_data_generation_update(void);
+
/**
* Some convenience defines for probe routines to return. These are just
* suggested values, and there's nothing magical about them.
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/sys/bus_private.h,v 1.11.2.2 2000/08/03 00:25:22 peter Exp $
- * $DragonFly: src/sys/sys/bus_private.h,v 1.9 2007/05/01 00:05:18 dillon Exp $
+ * $DragonFly: src/sys/sys/bus_private.h,v 1.10 2008/09/30 12:20:29 hasso Exp $
*/
#ifndef _SYS_BUS_PRIVATE_H_
* Device hierarchy.
*/
TAILQ_ENTRY(device) link; /* list of devices in parent */
+ TAILQ_ENTRY(device) devlink; /* global device list membership */
device_t parent;
device_list_t children; /* list of subordinate devices */
#define DF_ASYNCPROBE 0x0080 /* can be probed with its own thread */
u_char order; /* order from device_add_child_ordered() */
u_char pad;
-#ifdef DEVICE_SYSCTLS
- struct sysctl_oid oid[4];
- struct sysctl_oid_list oidlist[1];
-#endif
void *ivars;
void *softc;
};
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/sys/rman.h,v 1.5.2.1 2001/06/05 08:06:07 imp Exp $
- * $DragonFly: src/sys/sys/rman.h,v 1.10 2006/10/25 20:56:03 dillon Exp $
+ * $DragonFly: src/sys/sys/rman.h,v 1.11 2008/09/30 12:20:29 hasso Exp $
*/
#ifndef _SYS_RMAN_H_
#include <sys/bus.h> /* bus_space_tag_t */
#endif
+#define RF_ALLOCATED 0x0001 /* resource has been reserved */
+#define RF_ACTIVE 0x0002 /* resource allocation has been activated */
+#define RF_SHAREABLE 0x0004 /* resource permits contemporaneous sharing */
+#define RF_TIMESHARE 0x0008 /* resource permits time-division sharing */
+#define RF_WANTED 0x0010 /* somebody is waiting for this resource */
+#define RF_FIRSTSHARE 0x0020 /* first in sharing list */
+#define RF_PREFETCHABLE 0x0040 /* resource is prefetchable */
+#define RF_OPTIONAL 0x0080 /* for bus_alloc_resources() */
+
+#define RF_ALIGNMENT_SHIFT 10 /* alignment size bit starts bit 10 */
+#define RF_ALIGNMENT_MASK (0x003F << RF_ALIGNMENT_SHIFT)
+ /* resource address alignemnt size bit mask */
+#define RF_ALIGNMENT_LOG2(x) ((x) << RF_ALIGNMENT_SHIFT)
+#define RF_ALIGNMENT(x) (((x) & RF_ALIGNMENT_MASK) >> RF_ALIGNMENT_SHIFT)
+
+enum rman_type { RMAN_UNINIT = 0, RMAN_GAUGE, RMAN_ARRAY };
+
+/*
+ * String length exported to userspace for resource names, etc.
+ */
+#define RM_TEXTLEN 32
+
+/*
+ * Userspace-exported structures.
+ */
+struct u_resource {
+ uintptr_t r_handle; /* resource uniquifier */
+ uintptr_t r_parent; /* parent rman */
+ uintptr_t r_device; /* device owning this resource */
+ char r_devname[RM_TEXTLEN]; /* device name XXX obsolete */
+
+ u_long r_start; /* offset in resource space */
+ u_long r_size; /* size in resource space */
+ u_int r_flags; /* RF_* flags */
+};
+
+struct u_rman {
+ uintptr_t rm_handle; /* rman uniquifier */
+ char rm_descr[RM_TEXTLEN]; /* rman description */
+
+ u_long rm_start; /* base of managed region */
+ u_long rm_size; /* size of managed region */
+ enum rman_type rm_type; /* region type */
+};
+
+#ifdef _KERNEL
/*
* We use a linked list rather than a bitmap because we need to be able to
* represent potentially huge objects (like all of a processor's physical
struct rman *r_rm; /* resource manager from whence this came */
};
-#define RF_ALLOCATED 0x0001 /* resource has been reserved */
-#define RF_ACTIVE 0x0002 /* resource allocation has been activated */
-#define RF_SHAREABLE 0x0004 /* resource permits contemporaneous sharing */
-#define RF_TIMESHARE 0x0008 /* resource permits time-division sharing */
-#define RF_WANTED 0x0010 /* somebody is waiting for this resource */
-#define RF_FIRSTSHARE 0x0020 /* first in sharing list */
-#define RF_PREFETCHABLE 0x0040 /* resource is prefetchable */
-
-#define RF_ALIGNMENT_SHIFT 10 /* alignment size bit starts bit 10 */
-#define RF_ALIGNMENT_MASK (0x003F << RF_ALIGNMENT_SHIFT)
- /* resource address alignemnt size bit mask */
-#define RF_ALIGNMENT_LOG2(x) ((x) << RF_ALIGNMENT_SHIFT)
-#define RF_ALIGNMENT(x) (((x) & RF_ALIGNMENT_MASK) >> RF_ALIGNMENT_SHIFT)
-
-enum rman_type { RMAN_UNINIT = 0, RMAN_GAUGE, RMAN_ARRAY };
-
struct lwkt_token;
struct lwkt_tokref;
};
TAILQ_HEAD(rman_head, rman);
-#ifdef _KERNEL
-
int rman_activate_resource(struct resource *r);
int rman_await_resource(struct resource *r, struct lwkt_tokref *ilock, int slpflags, int timo);
int rman_deactivate_resource(struct resource *r);
*
* @(#)sysctl.h 8.1 (Berkeley) 6/2/93
* $FreeBSD: src/sys/sys/sysctl.h,v 1.81.2.10 2003/05/01 22:48:09 trhodes Exp $
- * $DragonFly: src/sys/sys/sysctl.h,v 1.28 2008/08/03 11:00:32 sephe Exp $
+ * $DragonFly: src/sys/sys/sysctl.h,v 1.29 2008/09/30 12:20:29 hasso Exp $
*/
#ifndef _SYS_SYSCTL_H_
SYSCTL_DECL(_debug);
SYSCTL_DECL(_debug_sizeof);
SYSCTL_DECL(_hw);
+SYSCTL_DECL(_hw_bus);
SYSCTL_DECL(_machdep);
SYSCTL_DECL(_user);
SYSCTL_DECL(_compat);
# From: @(#)Makefile 5.20 (Berkeley) 6/12/93
# $FreeBSD: src/usr.sbin/Makefile,v 1.183.2.14 2003/04/16 11:01:51 ru Exp $
-# $DragonFly: src/usr.sbin/Makefile,v 1.48 2008/08/30 16:07:59 hasso Exp $
+# $DragonFly: src/usr.sbin/Makefile,v 1.49 2008/09/30 12:20:29 hasso Exp $
.include "../sys/platform/${MACHINE_PLATFORM}/Makefile.inc"
crunch \
daemon \
dconschat \
+ devinfo \
dev_mkdb \
dntpd \
edquota \
--- /dev/null
+# $FreeBSD: src/usr.sbin/devinfo/Makefile,v 1.6 2002/05/12 14:23:15 rwatson Exp $
+# $DragonFly: src/usr.sbin/devinfo/Makefile,v 1.1 2008/09/30 12:20:29 hasso Exp $
+
+PROG= devinfo
+MAN= devinfo.8
+
+WARNS?= 2
+
+DPADD= ${LIBDEVINFO}
+LDADD= -ldevinfo
+
+.include <bsd.prog.mk>
--- /dev/null
+.\"
+.\" Copyright (c) 2002 Hiten Pandya
+.\" Copyright (c) 2002 Robert N. M. Watson
+.\"
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/usr.sbin/devinfo/devinfo.8,v 1.9 2006/09/29 16:46:01 ru Exp $
+.\" $DragonFly: src/usr.sbin/devinfo/devinfo.8,v 1.1 2008/09/30 12:20:29 hasso Exp $
+.\"
+.Dd September 30, 2008
+.Os
+.Dt DEVINFO 8
+.Sh NAME
+.Nm devinfo
+.Nd print information about system device configuration
+.Sh SYNOPSIS
+.Nm
+.Op Fl rv
+.Nm
+.Fl u
+.Sh DESCRIPTION
+The
+.Nm
+utility, without any arguments, shows the hierarchy of devices available
+in the system, starting from the
+.Dq nexus
+device.
+.Pp
+The following options are accepted.
+.Bl -tag -width indent
+.It Fl r
+Causes hardware resource information (such as IRQ, I/O ports, I/O memory
+addresses) to be also listed, under each device that has reserved those resources.
+.It Fl u
+Displays the same information as with
+.Fl r
+but sorts by resource type rather than by device, allowing to review the
+set of system resources by usage and available resources.
+I.e., it lists all
+the IRQ consumers together.
+.It Fl v
+Display all devices in the driver tree, not just those that are attached or
+busy.
+Without this flag, only those devices that have attached are reported.
+.El
+.Sh SEE ALSO
+.Xr systat 1 ,
+.Xr devinfo 3 ,
+.Xr iostat 8 ,
+.Xr pciconf 8 ,
+.Xr pnpinfo 8 ,
+.Xr vmstat 8 ,
+.Xr devclass 9 ,
+.Xr device 9
+.Sh AUTHORS
+.An Mike Smith Aq msmith@FreeBSD.org
--- /dev/null
+/*-
+ * Copyright (c) 2000, 2001 Michael Smith
+ * Copyright (c) 2000 BSDi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/usr.sbin/devinfo/devinfo.c,v 1.7 2007/10/27 13:06:15 jhb Exp $
+ * $DragonFly: src/usr.sbin/devinfo/devinfo.c,v 1.1 2008/09/30 12:20:29 hasso Exp $
+ */
+
+/*
+ * Print information about system device configuration.
+ */
+
+#include <sys/types.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "devinfo.h"
+
+int rflag;
+int vflag;
+
+static void print_resource(struct devinfo_res *);
+static int print_device_matching_resource(struct devinfo_res *, void *);
+static int print_device_rman_resources(struct devinfo_rman *, void *);
+static int print_device(struct devinfo_dev *, void *);
+static int print_rman_resource(struct devinfo_res *, void *);
+static int print_rman(struct devinfo_rman *, void *);
+
+struct indent_arg
+{
+ int indent;
+ void *arg;
+};
+
+/*
+ * Print a resource.
+ */
+void
+print_resource(struct devinfo_res *res)
+{
+ struct devinfo_rman *rman;
+ int hexmode;
+
+ rman = devinfo_handle_to_rman(res->dr_rman);
+ hexmode = (rman->dm_size > 1000) || (rman->dm_size == 0);
+ printf(hexmode ? "0x%lx" : "%lu", res->dr_start);
+ if (res->dr_size > 1)
+ printf(hexmode ? "-0x%lx" : "-%lu",
+ res->dr_start + res->dr_size - 1);
+}
+
+/*
+ * Print resource information if this resource matches the
+ * given device.
+ *
+ * If the given indent is 0, return an indicator that a matching
+ * resource exists.
+ */
+int
+print_device_matching_resource(struct devinfo_res *res, void *arg)
+{
+ struct indent_arg *ia = (struct indent_arg *)arg;
+ struct devinfo_dev *dev = (struct devinfo_dev *)ia->arg;
+ int i;
+
+ if (devinfo_handle_to_device(res->dr_device) == dev) {
+ /* in 'detect' mode, found a match */
+ if (ia->indent == 0)
+ return(1);
+ for (i = 0; i < ia->indent; i++)
+ printf(" ");
+ print_resource(res);
+ printf("\n");
+ }
+ return(0);
+}
+
+/*
+ * Print resource information for this device and resource manager.
+ */
+int
+print_device_rman_resources(struct devinfo_rman *rman, void *arg)
+{
+ struct indent_arg *ia = (struct indent_arg *)arg;
+ int indent, i;
+
+ indent = ia->indent;
+
+ /* check whether there are any resources matching this device */
+ ia->indent = 0;
+ if (devinfo_foreach_rman_resource(rman,
+ print_device_matching_resource, ia) != 0) {
+
+ /* there are, print header */
+ for (i = 0; i < indent; i++)
+ printf(" ");
+ printf("%s:\n", rman->dm_desc);
+
+ /* print resources */
+ ia->indent = indent + 4;
+ devinfo_foreach_rman_resource(rman,
+ print_device_matching_resource, ia);
+ }
+ ia->indent = indent;
+ return(0);
+}
+
+/*
+ * Print information about a device.
+ */
+int
+print_device(struct devinfo_dev *dev, void *arg)
+{
+ struct indent_arg ia;
+ int i, indent;
+
+ if (vflag || (dev->dd_name[0] != 0 && dev->dd_state >= DIS_ATTACHED)) {
+ indent = (int)(intptr_t)arg;
+ for (i = 0; i < indent; i++)
+ printf(" ");
+ printf("%s", dev->dd_name[0] ? dev->dd_name : "unknown");
+ if (vflag && *dev->dd_pnpinfo)
+ printf(" pnpinfo %s", dev->dd_pnpinfo);
+ if (vflag && *dev->dd_location)
+ printf(" at %s", dev->dd_location);
+ printf("\n");
+ if (rflag) {
+ ia.indent = indent + 4;
+ ia.arg = dev;
+ devinfo_foreach_rman(print_device_rman_resources,
+ (void *)&ia);
+ }
+ }
+
+ return(devinfo_foreach_device_child(dev, print_device,
+ (void *)((char *)arg + 2)));
+}
+
+/*
+ * Print information about a resource under a resource manager.
+ */
+int
+print_rman_resource(struct devinfo_res *res, void *arg __unused)
+{
+ struct devinfo_dev *dev;
+
+ printf(" ");
+ print_resource(res);
+ dev = devinfo_handle_to_device(res->dr_device);
+ if ((dev != NULL) && (dev->dd_name[0] != 0)) {
+ printf(" (%s)", dev->dd_name);
+ } else {
+ printf(" ----");
+ }
+ printf("\n");
+ return(0);
+}
+
+/*
+ * Print information about a resource manager.
+ */
+int
+print_rman(struct devinfo_rman *rman, void *arg __unused)
+{
+ printf("%s:\n", rman->dm_desc);
+ devinfo_foreach_rman_resource(rman, print_rman_resource, 0);
+ return(0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct devinfo_dev *root;
+ int c, uflag;
+
+ uflag = 0;
+ while ((c = getopt(argc, argv, "ruv")) != -1) {
+ switch(c) {
+ case 'r':
+ rflag++;
+ break;
+ case 'u':
+ uflag++;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ default:
+ fprintf(stderr, "%s\n%s\n",
+ "usage: devinfo [-rv]",
+ " devinfo -u");
+ exit(1);
+ }
+ }
+
+ if (devinfo_init())
+ err(1, "devinfo_init");
+
+ if ((root = devinfo_handle_to_device(DEVINFO_ROOT_DEVICE)) == NULL)
+ errx(1, "can't find root device");
+
+ /* print resource usage? */
+ if (uflag) {
+ devinfo_foreach_rman(print_rman, NULL);
+ } else {
+ /* print device hierarchy */
+ devinfo_foreach_device_child(root, print_device, (void *)0);
+ }
+ return(0);
+}
.\" $FreeBSD: src/usr.sbin/pciconf/pciconf.8,v 1.8.2.9 2003/03/11 22:31:30 trhodes Exp $
-.\" $DragonFly: src/usr.sbin/pciconf/pciconf.8,v 1.3 2008/07/23 14:14:44 swildner Exp $
+.\" $DragonFly: src/usr.sbin/pciconf/pciconf.8,v 1.4 2008/09/30 12:20:29 hasso Exp $
.\" Copyright (c) 1997
.\" Stefan Esser <se@FreeBSD.org>. All rights reserved.
.\"
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr pci 4 ,
+.Xr devinfo 8 ,
.Xr kldload 8
.Sh HISTORY
The