175752Smsmith/*-
275752Smsmith * Copyright (c) 2000, 2001 Michael Smith
375752Smsmith * Copyright (c) 2000 BSDi
475752Smsmith * All rights reserved.
575752Smsmith *
675752Smsmith * Redistribution and use in source and binary forms, with or without
775752Smsmith * modification, are permitted provided that the following conditions
875752Smsmith * are met:
975752Smsmith * 1. Redistributions of source code must retain the above copyright
1075752Smsmith *    notice, this list of conditions and the following disclaimer.
1175752Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1275752Smsmith *    notice, this list of conditions and the following disclaimer in the
1375752Smsmith *    documentation and/or other materials provided with the distribution.
1475752Smsmith *
1575752Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1675752Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1775752Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1875752Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1975752Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2075752Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2175752Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2275752Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2375752Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2475752Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2575752Smsmith * SUCH DAMAGE.
2675752Smsmith */
2775752Smsmith
2875752Smsmith/*
2975752Smsmith * Print information about system device configuration.
3075752Smsmith */
3175752Smsmith
32124128Scharnier#include <sys/cdefs.h>
33124128Scharnier__FBSDID("$FreeBSD$");
34124128Scharnier
3575752Smsmith#include <sys/types.h>
3675752Smsmith#include <err.h>
3775752Smsmith#include <stdio.h>
38162799Sru#include <stdlib.h>
3975752Smsmith#include <unistd.h>
4075752Smsmith#include "devinfo.h"
4175752Smsmith
42227252Sedstatic int	rflag;
43227252Sedstatic int	vflag;
4475752Smsmith
4587553Smikehstatic void	print_resource(struct devinfo_res *);
4687553Smikehstatic int	print_device_matching_resource(struct devinfo_res *, void *);
4787553Smikehstatic int	print_device_rman_resources(struct devinfo_rman *, void *);
4887553Smikehstatic int	print_device(struct devinfo_dev *, void *);
4987553Smikehstatic int	print_rman_resource(struct devinfo_res *, void *);
5087553Smikehstatic int	print_rman(struct devinfo_rman *, void *);
5187553Smikeh
5275752Smsmithstruct indent_arg
5375752Smsmith{
5475752Smsmith	int	indent;
5575752Smsmith	void	*arg;
5675752Smsmith};
5775752Smsmith
5875752Smsmith/*
5975752Smsmith * Print a resource.
6075752Smsmith */
6175752Smsmithvoid
6275752Smsmithprint_resource(struct devinfo_res *res)
6375752Smsmith{
6475752Smsmith	struct devinfo_rman	*rman;
6575752Smsmith	int			hexmode;
6675752Smsmith
6775752Smsmith	rman = devinfo_handle_to_rman(res->dr_rman);
68173057Sjhb	hexmode =  (rman->dm_size > 1000) || (rman->dm_size == 0);
6975752Smsmith	printf(hexmode ? "0x%lx" : "%lu", res->dr_start);
7075752Smsmith	if (res->dr_size > 1)
7175752Smsmith		printf(hexmode ? "-0x%lx" : "-%lu",
7275752Smsmith		    res->dr_start + res->dr_size - 1);
7375752Smsmith}
7475752Smsmith
7575752Smsmith/*
7675752Smsmith * Print resource information if this resource matches the
7775752Smsmith * given device.
7875752Smsmith *
7975752Smsmith * If the given indent is 0, return an indicator that a matching
8075752Smsmith * resource exists.
8175752Smsmith */
8275752Smsmithint
8375752Smsmithprint_device_matching_resource(struct devinfo_res *res, void *arg)
8475752Smsmith{
8575752Smsmith	struct indent_arg	*ia = (struct indent_arg *)arg;
8675752Smsmith	struct devinfo_dev	*dev = (struct devinfo_dev *)ia->arg;
8775752Smsmith	int			i;
8875752Smsmith
8975752Smsmith	if (devinfo_handle_to_device(res->dr_device) == dev) {
9075752Smsmith		/* in 'detect' mode, found a match */
9175752Smsmith		if (ia->indent == 0)
9275752Smsmith			return(1);
9375752Smsmith		for (i = 0; i < ia->indent; i++)
9475752Smsmith			printf(" ");
9575752Smsmith		print_resource(res);
9675752Smsmith		printf("\n");
9775752Smsmith	}
9875752Smsmith	return(0);
9975752Smsmith}
10075752Smsmith
10175752Smsmith/*
10275752Smsmith * Print resource information for this device and resource manager.
10375752Smsmith */
10475752Smsmithint
10575752Smsmithprint_device_rman_resources(struct devinfo_rman *rman, void *arg)
10675752Smsmith{
10775752Smsmith	struct indent_arg	*ia = (struct indent_arg *)arg;
10875752Smsmith	int			indent, i;
10975752Smsmith
11075752Smsmith	indent = ia->indent;
11175752Smsmith
11275752Smsmith	/* check whether there are any resources matching this device */
11375752Smsmith	ia->indent = 0;
11475752Smsmith	if (devinfo_foreach_rman_resource(rman,
11575752Smsmith	    print_device_matching_resource, ia) != 0) {
11675752Smsmith
11775752Smsmith		/* there are, print header */
11875752Smsmith		for (i = 0; i < indent; i++)
11975752Smsmith			printf(" ");
12075752Smsmith		printf("%s:\n", rman->dm_desc);
12175752Smsmith
12275752Smsmith		/* print resources */
12375752Smsmith		ia->indent = indent + 4;
12475752Smsmith		devinfo_foreach_rman_resource(rman,
12575752Smsmith		    print_device_matching_resource, ia);
12675752Smsmith	}
12775752Smsmith	ia->indent = indent;
12875752Smsmith	return(0);
12975752Smsmith}
13075752Smsmith
13175752Smsmith/*
13275752Smsmith * Print information about a device.
13375752Smsmith */
13475752Smsmithint
13575752Smsmithprint_device(struct devinfo_dev *dev, void *arg)
13675752Smsmith{
13775752Smsmith	struct indent_arg	ia;
13875752Smsmith	int			i, indent;
13975752Smsmith
140199291Sattilio	if (vflag || (dev->dd_name[0] != 0 && dev->dd_state >= DS_ATTACHED)) {
14187553Smikeh		indent = (int)(intptr_t)arg;
14275752Smsmith		for (i = 0; i < indent; i++)
14375752Smsmith			printf(" ");
144111046Simp		printf("%s", dev->dd_name[0] ? dev->dd_name : "unknown");
145111046Simp		if (vflag && *dev->dd_pnpinfo)
146111046Simp			printf(" pnpinfo %s", dev->dd_pnpinfo);
147111046Simp		if (vflag && *dev->dd_location)
148111046Simp			printf(" at %s", dev->dd_location);
149111046Simp		printf("\n");
15075752Smsmith		if (rflag) {
15175752Smsmith			ia.indent = indent + 4;
15275752Smsmith			ia.arg = dev;
15375752Smsmith			devinfo_foreach_rman(print_device_rman_resources,
15475752Smsmith			    (void *)&ia);
15575752Smsmith		}
15675752Smsmith	}
15775752Smsmith
15875752Smsmith	return(devinfo_foreach_device_child(dev, print_device,
15987553Smikeh	    (void *)((char *)arg + 2)));
16075752Smsmith}
16175752Smsmith
16275752Smsmith/*
16375752Smsmith * Print information about a resource under a resource manager.
16475752Smsmith */
16575752Smsmithint
16687553Smikehprint_rman_resource(struct devinfo_res *res, void *arg __unused)
16775752Smsmith{
16875752Smsmith	struct devinfo_dev	*dev;
16975752Smsmith
17075752Smsmith	printf("    ");
17175752Smsmith	print_resource(res);
17275752Smsmith	dev = devinfo_handle_to_device(res->dr_device);
17375752Smsmith	if ((dev != NULL) && (dev->dd_name[0] != 0)) {
17475752Smsmith		printf(" (%s)", dev->dd_name);
17575752Smsmith	} else {
17675752Smsmith		printf(" ----");
17775752Smsmith	}
17875752Smsmith	printf("\n");
17975752Smsmith	return(0);
18075752Smsmith}
18175752Smsmith
18275752Smsmith/*
18375752Smsmith * Print information about a resource manager.
18475752Smsmith */
18575752Smsmithint
18687553Smikehprint_rman(struct devinfo_rman *rman, void *arg __unused)
18775752Smsmith{
18875752Smsmith	printf("%s:\n", rman->dm_desc);
18975752Smsmith	devinfo_foreach_rman_resource(rman, print_rman_resource, 0);
19075752Smsmith	return(0);
19175752Smsmith}
19275752Smsmith
19375752Smsmithint
19475752Smsmithmain(int argc, char *argv[])
19575752Smsmith{
19675752Smsmith	struct devinfo_dev	*root;
19775752Smsmith	int			c, uflag;
19875752Smsmith
19975752Smsmith	uflag = 0;
200103663Simp	while ((c = getopt(argc, argv, "ruv")) != -1) {
20175752Smsmith		switch(c) {
20275752Smsmith		case 'r':
20375752Smsmith			rflag++;
20475752Smsmith			break;
20575752Smsmith		case 'u':
20675752Smsmith			uflag++;
20775752Smsmith			break;
208103663Simp		case 'v':
209103663Simp			vflag++;
210103663Simp			break;
21175752Smsmith		default:
212162799Sru			fprintf(stderr, "%s\n%s\n",
213162799Sru			    "usage: devinfo [-rv]",
214162799Sru			    "       devinfo -u");
215162799Sru			exit(1);
21675752Smsmith		}
21775752Smsmith	}
21875752Smsmith
21975752Smsmith	if (devinfo_init())
22075752Smsmith		err(1, "devinfo_init");
22175752Smsmith
22275752Smsmith	if ((root = devinfo_handle_to_device(DEVINFO_ROOT_DEVICE)) == NULL)
22375752Smsmith		errx(1, "can't find root device");
22475752Smsmith
22575752Smsmith	/* print resource usage? */
22675752Smsmith	if (uflag) {
22775752Smsmith		devinfo_foreach_rman(print_rman, NULL);
22875752Smsmith	} else {
22975752Smsmith		/* print device hierarchy */
23075752Smsmith		devinfo_foreach_device_child(root, print_device, (void *)0);
23175752Smsmith	}
23275752Smsmith	return(0);
23375752Smsmith}
234