diff --git a/usr.sbin/devinfo/Makefile b/usr.sbin/devinfo/Makefile new file mode 100644 index 000000000000..a3f978688346 --- /dev/null +++ b/usr.sbin/devinfo/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +PROG= devinfo +LDADD= -ldevinfo +CFLAGS= -Wall +NOMAN= yes + +.include diff --git a/usr.sbin/devinfo/devinfo.c b/usr.sbin/devinfo/devinfo.c new file mode 100644 index 000000000000..6f9bc5b15adf --- /dev/null +++ b/usr.sbin/devinfo/devinfo.c @@ -0,0 +1,214 @@ +/*- + * 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$ + */ + +/* + * Print information about system device configuration. + */ + +#include +#include +#include +#include +#include "devinfo.h" + +int rflag; + +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 > 100) || (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; + struct devinfo_dev *dev; + int indent, i; + + indent = ia->indent; + dev = (struct devinfo_dev *)ia->arg; + + /* 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 (dev->dd_name[0] != 0) { + indent = (int)arg; + for (i = 0; i < indent; i++) + printf(" "); + printf("%s\n", dev->dd_name); + 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 *)(indent + 2))); +} + +/* + * Print information about a resource under a resource manager. + */ +int +print_rman_resource(struct devinfo_res *res, void *arg) +{ + 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) +{ + 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, "ru")) != -1) { + switch(c) { + case 'r': + rflag++; + break; + case 'u': + uflag++; + break; + default: + errx(1, "usage: %s [-ru]", argv[0]); + } + } + + 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); +}