1ce7894eeSMike Smith /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 31de7b4b8SPedro F. Giffuni * 4ce7894eeSMike Smith * Copyright (c) 2000, 2001 Michael Smith 5ce7894eeSMike Smith * Copyright (c) 2000 BSDi 6ce7894eeSMike Smith * All rights reserved. 7ce7894eeSMike Smith * 8ce7894eeSMike Smith * Redistribution and use in source and binary forms, with or without 9ce7894eeSMike Smith * modification, are permitted provided that the following conditions 10ce7894eeSMike Smith * are met: 11ce7894eeSMike Smith * 1. Redistributions of source code must retain the above copyright 12ce7894eeSMike Smith * notice, this list of conditions and the following disclaimer. 13ce7894eeSMike Smith * 2. Redistributions in binary form must reproduce the above copyright 14ce7894eeSMike Smith * notice, this list of conditions and the following disclaimer in the 15ce7894eeSMike Smith * documentation and/or other materials provided with the distribution. 16ce7894eeSMike Smith * 17ce7894eeSMike Smith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18ce7894eeSMike Smith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19ce7894eeSMike Smith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20ce7894eeSMike Smith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21ce7894eeSMike Smith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22ce7894eeSMike Smith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23ce7894eeSMike Smith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24ce7894eeSMike Smith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25ce7894eeSMike Smith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26ce7894eeSMike Smith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27ce7894eeSMike Smith * SUCH DAMAGE. 28ce7894eeSMike Smith */ 29ce7894eeSMike Smith 30ce7894eeSMike Smith /* 31ce7894eeSMike Smith * Print information about system device configuration. 32ce7894eeSMike Smith */ 33ce7894eeSMike Smith 34ce7894eeSMike Smith #include <sys/types.h> 35ce7894eeSMike Smith #include <err.h> 36b98d2b35SWarner Losh #include <errno.h> 37ce7894eeSMike Smith #include <stdio.h> 38d20241a6SRuslan Ermilov #include <stdlib.h> 3933860097SWarner Losh #include <string.h> 40ce7894eeSMike Smith #include <unistd.h> 41ce7894eeSMike Smith #include "devinfo.h" 42ce7894eeSMike Smith 43e8f386b4SEd Schouten static int rflag; 44e8f386b4SEd Schouten static int vflag; 45ce7894eeSMike Smith 4684e0df3fSMike Heffner static void print_resource(struct devinfo_res *); 4784e0df3fSMike Heffner static int print_device_matching_resource(struct devinfo_res *, void *); 4884e0df3fSMike Heffner static int print_device_rman_resources(struct devinfo_rman *, void *); 4984e0df3fSMike Heffner static int print_device(struct devinfo_dev *, void *); 5084e0df3fSMike Heffner static int print_rman_resource(struct devinfo_res *, void *); 5184e0df3fSMike Heffner static int print_rman(struct devinfo_rman *, void *); 5284e0df3fSMike Heffner 53ce7894eeSMike Smith struct indent_arg 54ce7894eeSMike Smith { 55ce7894eeSMike Smith int indent; 56ce7894eeSMike Smith void *arg; 57ce7894eeSMike Smith }; 58ce7894eeSMike Smith 59ce7894eeSMike Smith /* 60ce7894eeSMike Smith * Print a resource. 61ce7894eeSMike Smith */ 62ce7894eeSMike Smith void 63ce7894eeSMike Smith print_resource(struct devinfo_res *res) 64ce7894eeSMike Smith { 65ce7894eeSMike Smith struct devinfo_rman *rman; 66ce7894eeSMike Smith int hexmode; 67ce7894eeSMike Smith 68ce7894eeSMike Smith rman = devinfo_handle_to_rman(res->dr_rman); 69d9cec0a0SJohn Baldwin hexmode = (rman->dm_size > 1000) || (rman->dm_size == 0); 70da1b038aSJustin Hibbits printf(hexmode ? "0x%jx" : "%ju", res->dr_start); 71ce7894eeSMike Smith if (res->dr_size > 1) 72da1b038aSJustin Hibbits printf(hexmode ? "-0x%jx" : "-%ju", 73ce7894eeSMike Smith res->dr_start + res->dr_size - 1); 74ce7894eeSMike Smith } 75ce7894eeSMike Smith 76ce7894eeSMike Smith /* 77ce7894eeSMike Smith * Print resource information if this resource matches the 78ce7894eeSMike Smith * given device. 79ce7894eeSMike Smith * 80ce7894eeSMike Smith * If the given indent is 0, return an indicator that a matching 81ce7894eeSMike Smith * resource exists. 82ce7894eeSMike Smith */ 83ce7894eeSMike Smith int 84ce7894eeSMike Smith print_device_matching_resource(struct devinfo_res *res, void *arg) 85ce7894eeSMike Smith { 86ce7894eeSMike Smith struct indent_arg *ia = (struct indent_arg *)arg; 87ce7894eeSMike Smith struct devinfo_dev *dev = (struct devinfo_dev *)ia->arg; 88ce7894eeSMike Smith int i; 89ce7894eeSMike Smith 90ce7894eeSMike Smith if (devinfo_handle_to_device(res->dr_device) == dev) { 91ce7894eeSMike Smith /* in 'detect' mode, found a match */ 92ce7894eeSMike Smith if (ia->indent == 0) 93ce7894eeSMike Smith return(1); 94ce7894eeSMike Smith for (i = 0; i < ia->indent; i++) 95ce7894eeSMike Smith printf(" "); 96ce7894eeSMike Smith print_resource(res); 97ce7894eeSMike Smith printf("\n"); 98ce7894eeSMike Smith } 99ce7894eeSMike Smith return(0); 100ce7894eeSMike Smith } 101ce7894eeSMike Smith 102ce7894eeSMike Smith /* 103ce7894eeSMike Smith * Print resource information for this device and resource manager. 104ce7894eeSMike Smith */ 105ce7894eeSMike Smith int 106ce7894eeSMike Smith print_device_rman_resources(struct devinfo_rman *rman, void *arg) 107ce7894eeSMike Smith { 108ce7894eeSMike Smith struct indent_arg *ia = (struct indent_arg *)arg; 109ce7894eeSMike Smith int indent, i; 110ce7894eeSMike Smith 111ce7894eeSMike Smith indent = ia->indent; 112ce7894eeSMike Smith 113ce7894eeSMike Smith /* check whether there are any resources matching this device */ 114ce7894eeSMike Smith ia->indent = 0; 115ce7894eeSMike Smith if (devinfo_foreach_rman_resource(rman, 116ce7894eeSMike Smith print_device_matching_resource, ia) != 0) { 117ce7894eeSMike Smith 118ce7894eeSMike Smith /* there are, print header */ 119ce7894eeSMike Smith for (i = 0; i < indent; i++) 120ce7894eeSMike Smith printf(" "); 121ce7894eeSMike Smith printf("%s:\n", rman->dm_desc); 122ce7894eeSMike Smith 123ce7894eeSMike Smith /* print resources */ 124ce7894eeSMike Smith ia->indent = indent + 4; 125ce7894eeSMike Smith devinfo_foreach_rman_resource(rman, 126ce7894eeSMike Smith print_device_matching_resource, ia); 127ce7894eeSMike Smith } 128ce7894eeSMike Smith ia->indent = indent; 129ce7894eeSMike Smith return(0); 130ce7894eeSMike Smith } 131ce7894eeSMike Smith 132b68de894SWarner Losh static void 133b68de894SWarner Losh print_dev(struct devinfo_dev *dev) 134b68de894SWarner Losh { 135b68de894SWarner Losh 136b68de894SWarner Losh printf("%s", dev->dd_name[0] ? dev->dd_name : "unknown"); 13760516a51SJohn Baldwin if (vflag && *dev->dd_desc) 13860516a51SJohn Baldwin printf(" <%s>", dev->dd_desc); 139b68de894SWarner Losh if (vflag && *dev->dd_pnpinfo) 140b68de894SWarner Losh printf(" pnpinfo %s", dev->dd_pnpinfo); 141b68de894SWarner Losh if (vflag && *dev->dd_location) 142b68de894SWarner Losh printf(" at %s", dev->dd_location); 143b68de894SWarner Losh if (!(dev->dd_flags & DF_ENABLED)) 144b68de894SWarner Losh printf(" (disabled)"); 145b68de894SWarner Losh else if (dev->dd_flags & DF_SUSPENDED) 146b68de894SWarner Losh printf(" (suspended)"); 147b68de894SWarner Losh } 148b68de894SWarner Losh 149b68de894SWarner Losh 150ce7894eeSMike Smith /* 151ce7894eeSMike Smith * Print information about a device. 152ce7894eeSMike Smith */ 153ce7894eeSMike Smith int 154ce7894eeSMike Smith print_device(struct devinfo_dev *dev, void *arg) 155ce7894eeSMike Smith { 156ce7894eeSMike Smith struct indent_arg ia; 157ce7894eeSMike Smith int i, indent; 158ce7894eeSMike Smith 15912628101SAttilio Rao if (vflag || (dev->dd_name[0] != 0 && dev->dd_state >= DS_ATTACHED)) { 16084e0df3fSMike Heffner indent = (int)(intptr_t)arg; 161ce7894eeSMike Smith for (i = 0; i < indent; i++) 162ce7894eeSMike Smith printf(" "); 163b68de894SWarner Losh print_dev(dev); 164696a3d28SWarner Losh printf("\n"); 165ce7894eeSMike Smith if (rflag) { 166ce7894eeSMike Smith ia.indent = indent + 4; 167ce7894eeSMike Smith ia.arg = dev; 168ce7894eeSMike Smith devinfo_foreach_rman(print_device_rman_resources, 169ce7894eeSMike Smith (void *)&ia); 170ce7894eeSMike Smith } 171ce7894eeSMike Smith } 172ce7894eeSMike Smith 173ce7894eeSMike Smith return(devinfo_foreach_device_child(dev, print_device, 17484e0df3fSMike Heffner (void *)((char *)arg + 2))); 175ce7894eeSMike Smith } 176ce7894eeSMike Smith 177ce7894eeSMike Smith /* 178ce7894eeSMike Smith * Print information about a resource under a resource manager. 179ce7894eeSMike Smith */ 180ce7894eeSMike Smith int 18184e0df3fSMike Heffner print_rman_resource(struct devinfo_res *res, void *arg __unused) 182ce7894eeSMike Smith { 183ce7894eeSMike Smith struct devinfo_dev *dev; 184ce7894eeSMike Smith 185ce7894eeSMike Smith printf(" "); 186ce7894eeSMike Smith print_resource(res); 187ce7894eeSMike Smith dev = devinfo_handle_to_device(res->dr_device); 188*b8529e7cSJohn Baldwin if (dev != NULL) { 189*b8529e7cSJohn Baldwin if (dev->dd_name[0] != 0) { 190ce7894eeSMike Smith printf(" (%s)", dev->dd_name); 191ce7894eeSMike Smith } else { 192*b8529e7cSJohn Baldwin printf(" (unknown)"); 193*b8529e7cSJohn Baldwin if (vflag && *dev->dd_pnpinfo) 194*b8529e7cSJohn Baldwin printf(" pnpinfo %s", dev->dd_pnpinfo); 195*b8529e7cSJohn Baldwin if (vflag && *dev->dd_location) 196*b8529e7cSJohn Baldwin printf(" at %s", dev->dd_location); 197*b8529e7cSJohn Baldwin } 198*b8529e7cSJohn Baldwin } else { 199ce7894eeSMike Smith printf(" ----"); 200ce7894eeSMike Smith } 201ce7894eeSMike Smith printf("\n"); 202ce7894eeSMike Smith return(0); 203ce7894eeSMike Smith } 204ce7894eeSMike Smith 205ce7894eeSMike Smith /* 206ce7894eeSMike Smith * Print information about a resource manager. 207ce7894eeSMike Smith */ 208ce7894eeSMike Smith int 20984e0df3fSMike Heffner print_rman(struct devinfo_rman *rman, void *arg __unused) 210ce7894eeSMike Smith { 211ce7894eeSMike Smith printf("%s:\n", rman->dm_desc); 212ce7894eeSMike Smith devinfo_foreach_rman_resource(rman, print_rman_resource, 0); 213ce7894eeSMike Smith return(0); 214ce7894eeSMike Smith } 215ce7894eeSMike Smith 21633860097SWarner Losh static int 21733860097SWarner Losh print_path(struct devinfo_dev *dev, void *xname) 21833860097SWarner Losh { 21933860097SWarner Losh const char *name = xname; 22033860097SWarner Losh int rv; 22133860097SWarner Losh 22233860097SWarner Losh if (strcmp(dev->dd_name, name) == 0) { 223b68de894SWarner Losh print_dev(dev); 224b68de894SWarner Losh if (vflag) 225b68de894SWarner Losh printf("\n"); 22633860097SWarner Losh return (1); 22733860097SWarner Losh } 22833860097SWarner Losh 22933860097SWarner Losh rv = devinfo_foreach_device_child(dev, print_path, xname); 230b68de894SWarner Losh if (rv == 1) { 231b68de894SWarner Losh printf(" "); 232b68de894SWarner Losh print_dev(dev); 233b68de894SWarner Losh if (vflag) 234b68de894SWarner Losh printf("\n"); 235b68de894SWarner Losh } 23633860097SWarner Losh return (rv); 23733860097SWarner Losh } 23833860097SWarner Losh 239b68de894SWarner Losh static void __dead2 240b68de894SWarner Losh usage(void) 241b68de894SWarner Losh { 242b68de894SWarner Losh fprintf(stderr, "%s\n%s\n%s\n", 243b68de894SWarner Losh "usage: devinfo [-rv]", 244*b8529e7cSJohn Baldwin " devinfo -u [-v]", 2454d86ab42SAlexander Motin " devinfo -p dev [-v]"); 246b68de894SWarner Losh exit(1); 247b68de894SWarner Losh } 248b68de894SWarner Losh 249ce7894eeSMike Smith int 250ce7894eeSMike Smith main(int argc, char *argv[]) 251ce7894eeSMike Smith { 252ce7894eeSMike Smith struct devinfo_dev *root; 253b98d2b35SWarner Losh int c, uflag, rv; 254b68de894SWarner Losh char *path = NULL; 255ce7894eeSMike Smith 256ce7894eeSMike Smith uflag = 0; 25733860097SWarner Losh while ((c = getopt(argc, argv, "p:ruv")) != -1) { 258ce7894eeSMike Smith switch(c) { 25933860097SWarner Losh case 'p': 26033860097SWarner Losh path = optarg; 26133860097SWarner Losh break; 262ce7894eeSMike Smith case 'r': 263ce7894eeSMike Smith rflag++; 264ce7894eeSMike Smith break; 265ce7894eeSMike Smith case 'u': 266ce7894eeSMike Smith uflag++; 267ce7894eeSMike Smith break; 2687f156483SWarner Losh case 'v': 2697f156483SWarner Losh vflag++; 2707f156483SWarner Losh break; 271ce7894eeSMike Smith default: 27233860097SWarner Losh usage(); 273ce7894eeSMike Smith } 274ce7894eeSMike Smith } 275ce7894eeSMike Smith 27633860097SWarner Losh if (path && (rflag || uflag)) 27733860097SWarner Losh usage(); 27833860097SWarner Losh 279b98d2b35SWarner Losh if ((rv = devinfo_init()) != 0) { 280b98d2b35SWarner Losh errno = rv; 281ce7894eeSMike Smith err(1, "devinfo_init"); 282b98d2b35SWarner Losh } 283ce7894eeSMike Smith 284ce7894eeSMike Smith if ((root = devinfo_handle_to_device(DEVINFO_ROOT_DEVICE)) == NULL) 285ce7894eeSMike Smith errx(1, "can't find root device"); 286ce7894eeSMike Smith 28733860097SWarner Losh if (path) { 28833860097SWarner Losh if (devinfo_foreach_device_child(root, print_path, (void *)path) == 0) 28933860097SWarner Losh errx(1, "%s: Not found", path); 290b68de894SWarner Losh if (!vflag) 29133860097SWarner Losh printf("\n"); 29233860097SWarner Losh } else if (uflag) { 293ce7894eeSMike Smith /* print resource usage? */ 294ce7894eeSMike Smith devinfo_foreach_rman(print_rman, NULL); 295ce7894eeSMike Smith } else { 296ce7894eeSMike Smith /* print device hierarchy */ 297ce7894eeSMike Smith devinfo_foreach_device_child(root, print_device, (void *)0); 298ce7894eeSMike Smith } 299ce7894eeSMike Smith return(0); 300ce7894eeSMike Smith } 301