1 /*- 2 * Copyright (c) 2000, 2001 Michael Smith 3 * Copyright (c) 2000 BSDi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 30 /* 31 * Print information about system device configuration. 32 */ 33 34 #include <sys/types.h> 35 #include <err.h> 36 #include <stdio.h> 37 #include <unistd.h> 38 #include "devinfo.h" 39 40 int rflag; 41 42 struct indent_arg 43 { 44 int indent; 45 void *arg; 46 }; 47 48 /* 49 * Print a resource. 50 */ 51 void 52 print_resource(struct devinfo_res *res) 53 { 54 struct devinfo_rman *rman; 55 int hexmode; 56 57 rman = devinfo_handle_to_rman(res->dr_rman); 58 hexmode = (rman->dm_size > 100) || (rman->dm_size == 0); 59 printf(hexmode ? "0x%lx" : "%lu", res->dr_start); 60 if (res->dr_size > 1) 61 printf(hexmode ? "-0x%lx" : "-%lu", 62 res->dr_start + res->dr_size - 1); 63 } 64 65 /* 66 * Print resource information if this resource matches the 67 * given device. 68 * 69 * If the given indent is 0, return an indicator that a matching 70 * resource exists. 71 */ 72 int 73 print_device_matching_resource(struct devinfo_res *res, void *arg) 74 { 75 struct indent_arg *ia = (struct indent_arg *)arg; 76 struct devinfo_dev *dev = (struct devinfo_dev *)ia->arg; 77 int i; 78 79 if (devinfo_handle_to_device(res->dr_device) == dev) { 80 /* in 'detect' mode, found a match */ 81 if (ia->indent == 0) 82 return(1); 83 for (i = 0; i < ia->indent; i++) 84 printf(" "); 85 print_resource(res); 86 printf("\n"); 87 } 88 return(0); 89 } 90 91 /* 92 * Print resource information for this device and resource manager. 93 */ 94 int 95 print_device_rman_resources(struct devinfo_rman *rman, void *arg) 96 { 97 struct indent_arg *ia = (struct indent_arg *)arg; 98 struct devinfo_dev *dev; 99 int indent, i; 100 101 indent = ia->indent; 102 dev = (struct devinfo_dev *)ia->arg; 103 104 /* check whether there are any resources matching this device */ 105 ia->indent = 0; 106 if (devinfo_foreach_rman_resource(rman, 107 print_device_matching_resource, ia) != 0) { 108 109 /* there are, print header */ 110 for (i = 0; i < indent; i++) 111 printf(" "); 112 printf("%s:\n", rman->dm_desc); 113 114 /* print resources */ 115 ia->indent = indent + 4; 116 devinfo_foreach_rman_resource(rman, 117 print_device_matching_resource, ia); 118 } 119 ia->indent = indent; 120 return(0); 121 } 122 123 /* 124 * Print information about a device. 125 */ 126 int 127 print_device(struct devinfo_dev *dev, void *arg) 128 { 129 struct indent_arg ia; 130 int i, indent; 131 132 if (dev->dd_name[0] != 0) { 133 indent = (int)arg; 134 for (i = 0; i < indent; i++) 135 printf(" "); 136 printf("%s\n", dev->dd_name); 137 if (rflag) { 138 ia.indent = indent + 4; 139 ia.arg = dev; 140 devinfo_foreach_rman(print_device_rman_resources, 141 (void *)&ia); 142 } 143 } 144 145 return(devinfo_foreach_device_child(dev, print_device, 146 (void *)(indent + 2))); 147 } 148 149 /* 150 * Print information about a resource under a resource manager. 151 */ 152 int 153 print_rman_resource(struct devinfo_res *res, void *arg) 154 { 155 struct devinfo_dev *dev; 156 157 printf(" "); 158 print_resource(res); 159 dev = devinfo_handle_to_device(res->dr_device); 160 if ((dev != NULL) && (dev->dd_name[0] != 0)) { 161 printf(" (%s)", dev->dd_name); 162 } else { 163 printf(" ----"); 164 } 165 printf("\n"); 166 return(0); 167 } 168 169 /* 170 * Print information about a resource manager. 171 */ 172 int 173 print_rman(struct devinfo_rman *rman, void *arg) 174 { 175 printf("%s:\n", rman->dm_desc); 176 devinfo_foreach_rman_resource(rman, print_rman_resource, 0); 177 return(0); 178 } 179 180 int 181 main(int argc, char *argv[]) 182 { 183 struct devinfo_dev *root; 184 int c, uflag; 185 186 uflag = 0; 187 while ((c = getopt(argc, argv, "ru")) != -1) { 188 switch(c) { 189 case 'r': 190 rflag++; 191 break; 192 case 'u': 193 uflag++; 194 break; 195 default: 196 errx(1, "usage: %s [-ru]", argv[0]); 197 } 198 } 199 200 if (devinfo_init()) 201 err(1, "devinfo_init"); 202 203 if ((root = devinfo_handle_to_device(DEVINFO_ROOT_DEVICE)) == NULL) 204 errx(1, "can't find root device"); 205 206 /* print resource usage? */ 207 if (uflag) { 208 devinfo_foreach_rman(print_rman, NULL); 209 } else { 210 /* print device hierarchy */ 211 devinfo_foreach_device_child(root, print_device, (void *)0); 212 } 213 return(0); 214 } 215