xref: /freebsd/usr.sbin/devinfo/devinfo.c (revision 41466b50c1d5bfd1cf6adaae547a579a75d7c04e)
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