xref: /freebsd/usr.sbin/devctl/devctl.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
164de8019SJohn Baldwin /*-
264de8019SJohn Baldwin  * Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
364de8019SJohn Baldwin  *
464de8019SJohn Baldwin  * Redistribution and use in source and binary forms, with or without
564de8019SJohn Baldwin  * modification, are permitted provided that the following conditions
664de8019SJohn Baldwin  * are met:
764de8019SJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
864de8019SJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
964de8019SJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
1064de8019SJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
1164de8019SJohn Baldwin  *    documentation and/or other materials provided with the distribution.
1264de8019SJohn Baldwin  *
1364de8019SJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1464de8019SJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1564de8019SJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1664de8019SJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1764de8019SJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1864de8019SJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1964de8019SJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2064de8019SJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2164de8019SJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2264de8019SJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2364de8019SJohn Baldwin  * SUCH DAMAGE.
2464de8019SJohn Baldwin  */
2564de8019SJohn Baldwin 
2664de8019SJohn Baldwin #include <sys/cdefs.h>
2764de8019SJohn Baldwin #include <sys/linker_set.h>
2864de8019SJohn Baldwin #include <devctl.h>
2964de8019SJohn Baldwin #include <err.h>
3064de8019SJohn Baldwin #include <errno.h>
3164de8019SJohn Baldwin #include <stdio.h>
3264de8019SJohn Baldwin #include <stdlib.h>
3364de8019SJohn Baldwin #include <string.h>
3464de8019SJohn Baldwin #include <strings.h>
3564de8019SJohn Baldwin #include <unistd.h>
3664de8019SJohn Baldwin 
3764de8019SJohn Baldwin struct devctl_command {
3864de8019SJohn Baldwin 	const char *name;
3964de8019SJohn Baldwin 	int (*handler)(int ac, char **av);
4064de8019SJohn Baldwin };
4164de8019SJohn Baldwin 
4264de8019SJohn Baldwin #define	DEVCTL_DATASET(name)	devctl_ ## name ## _table
4364de8019SJohn Baldwin 
4464de8019SJohn Baldwin #define	DEVCTL_COMMAND(set, name, function)				\
4564de8019SJohn Baldwin 	static struct devctl_command function ## _devctl_command =	\
4664de8019SJohn Baldwin 	{ #name, function };						\
4764de8019SJohn Baldwin 	DATA_SET(DEVCTL_DATASET(set), function ## _devctl_command)
4864de8019SJohn Baldwin 
4964de8019SJohn Baldwin #define	DEVCTL_TABLE(set, name)						\
5064de8019SJohn Baldwin 	SET_DECLARE(DEVCTL_DATASET(name), struct devctl_command);	\
5164de8019SJohn Baldwin 									\
5264de8019SJohn Baldwin 	static int							\
5364de8019SJohn Baldwin 	devctl_ ## name ## _table_handler(int ac, char **av)		\
5464de8019SJohn Baldwin 	{								\
5564de8019SJohn Baldwin 		return (devctl_table_handler(SET_BEGIN(DEVCTL_DATASET(name)), \
5664de8019SJohn Baldwin 		    SET_LIMIT(DEVCTL_DATASET(name)), ac, av));		\
5764de8019SJohn Baldwin 	}								\
5864de8019SJohn Baldwin 	DEVCTL_COMMAND(set, name, devctl_ ## name ## _table_handler)
5964de8019SJohn Baldwin 
6064de8019SJohn Baldwin static int	devctl_table_handler(struct devctl_command **start,
6164de8019SJohn Baldwin     struct devctl_command **end, int ac, char **av);
6264de8019SJohn Baldwin 
6364de8019SJohn Baldwin SET_DECLARE(DEVCTL_DATASET(top), struct devctl_command);
6464de8019SJohn Baldwin 
65e05ec081SJohn Baldwin DEVCTL_TABLE(top, clear);
6664de8019SJohn Baldwin DEVCTL_TABLE(top, set);
6764de8019SJohn Baldwin 
6864de8019SJohn Baldwin static void
usage(void)6964de8019SJohn Baldwin usage(void)
7064de8019SJohn Baldwin {
715fa29797SWarner Losh 	fprintf(stderr,
725fa29797SWarner Losh 	    "usage: devctl attach device\n"
735fa29797SWarner Losh 	    "       devctl detach [-f] device\n"
745fa29797SWarner Losh 	    "       devctl disable [-f] device\n"
755fa29797SWarner Losh 	    "       devctl enable device\n"
765fa29797SWarner Losh 	    "       devctl suspend device\n"
775fa29797SWarner Losh 	    "       devctl resume device\n"
785fa29797SWarner Losh 	    "       devctl set driver [-f] device driver\n"
795fa29797SWarner Losh 	    "       devctl clear driver [-f] device\n"
805fa29797SWarner Losh 	    "       devctl rescan device\n"
815fa29797SWarner Losh 	    "       devctl delete [-f] device\n"
825fa29797SWarner Losh 	    "       devctl freeze\n"
834fbf8e1cSKonstantin Belousov 	    "       devctl thaw\n"
844fbf8e1cSKonstantin Belousov 	    "       devctl reset [-d] device\n"
85*f5366026SWarner Losh 	    "       devctl getpath locator device\n"
864fbf8e1cSKonstantin Belousov 	    );
8764de8019SJohn Baldwin 	exit(1);
8864de8019SJohn Baldwin }
8964de8019SJohn Baldwin 
9064de8019SJohn Baldwin static int
devctl_table_handler(struct devctl_command ** start,struct devctl_command ** end,int ac,char ** av)9164de8019SJohn Baldwin devctl_table_handler(struct devctl_command **start,
9264de8019SJohn Baldwin     struct devctl_command **end, int ac, char **av)
9364de8019SJohn Baldwin {
9464de8019SJohn Baldwin 	struct devctl_command **cmd;
9564de8019SJohn Baldwin 
9664de8019SJohn Baldwin 	if (ac < 2) {
9764de8019SJohn Baldwin 		warnx("The %s command requires a sub-command.", av[0]);
9864de8019SJohn Baldwin 		return (EINVAL);
9964de8019SJohn Baldwin 	}
10064de8019SJohn Baldwin 	for (cmd = start; cmd < end; cmd++) {
10164de8019SJohn Baldwin 		if (strcmp((*cmd)->name, av[1]) == 0)
10264de8019SJohn Baldwin 			return ((*cmd)->handler(ac - 1, av + 1));
10364de8019SJohn Baldwin 	}
10464de8019SJohn Baldwin 
10564de8019SJohn Baldwin 	warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
10664de8019SJohn Baldwin 	return (ENOENT);
10764de8019SJohn Baldwin }
10864de8019SJohn Baldwin 
10964de8019SJohn Baldwin static int
help(int ac __unused,char ** av __unused)11064de8019SJohn Baldwin help(int ac __unused, char **av __unused)
11164de8019SJohn Baldwin {
11264de8019SJohn Baldwin 
11364de8019SJohn Baldwin 	usage();
11464de8019SJohn Baldwin 	return (0);
11564de8019SJohn Baldwin }
11664de8019SJohn Baldwin DEVCTL_COMMAND(top, help, help);
11764de8019SJohn Baldwin 
11864de8019SJohn Baldwin static int
attach(int ac,char ** av)11964de8019SJohn Baldwin attach(int ac, char **av)
12064de8019SJohn Baldwin {
12164de8019SJohn Baldwin 
12264de8019SJohn Baldwin 	if (ac != 2)
12364de8019SJohn Baldwin 		usage();
12464de8019SJohn Baldwin 	if (devctl_attach(av[1]) < 0)
12564de8019SJohn Baldwin 		err(1, "Failed to attach %s", av[1]);
12664de8019SJohn Baldwin 	return (0);
12764de8019SJohn Baldwin }
12864de8019SJohn Baldwin DEVCTL_COMMAND(top, attach, attach);
12964de8019SJohn Baldwin 
13064de8019SJohn Baldwin static void
detach_usage(void)13164de8019SJohn Baldwin detach_usage(void)
13264de8019SJohn Baldwin {
13364de8019SJohn Baldwin 
13464de8019SJohn Baldwin 	fprintf(stderr, "usage: devctl detach [-f] device\n");
13564de8019SJohn Baldwin 	exit(1);
13664de8019SJohn Baldwin }
13764de8019SJohn Baldwin 
13864de8019SJohn Baldwin static int
detach(int ac,char ** av)13964de8019SJohn Baldwin detach(int ac, char **av)
14064de8019SJohn Baldwin {
14164de8019SJohn Baldwin 	bool force;
14264de8019SJohn Baldwin 	int ch;
14364de8019SJohn Baldwin 
14464de8019SJohn Baldwin 	force = false;
14564de8019SJohn Baldwin 	while ((ch = getopt(ac, av, "f")) != -1)
14664de8019SJohn Baldwin 		switch (ch) {
14764de8019SJohn Baldwin 		case 'f':
14864de8019SJohn Baldwin 			force = true;
14964de8019SJohn Baldwin 			break;
15064de8019SJohn Baldwin 		default:
15164de8019SJohn Baldwin 			detach_usage();
15264de8019SJohn Baldwin 		}
15364de8019SJohn Baldwin 	ac -= optind;
15464de8019SJohn Baldwin 	av += optind;
15564de8019SJohn Baldwin 
15664de8019SJohn Baldwin 	if (ac != 1)
15764de8019SJohn Baldwin 		detach_usage();
15864de8019SJohn Baldwin 	if (devctl_detach(av[0], force) < 0)
15964de8019SJohn Baldwin 		err(1, "Failed to detach %s", av[0]);
16064de8019SJohn Baldwin 	return (0);
16164de8019SJohn Baldwin }
16264de8019SJohn Baldwin DEVCTL_COMMAND(top, detach, detach);
16364de8019SJohn Baldwin 
16464de8019SJohn Baldwin static void
disable_usage(void)16564de8019SJohn Baldwin disable_usage(void)
16664de8019SJohn Baldwin {
16764de8019SJohn Baldwin 
16864de8019SJohn Baldwin 	fprintf(stderr, "usage: devctl disable [-f] device\n");
16964de8019SJohn Baldwin 	exit(1);
17064de8019SJohn Baldwin }
17164de8019SJohn Baldwin 
17264de8019SJohn Baldwin static int
disable(int ac,char ** av)17364de8019SJohn Baldwin disable(int ac, char **av)
17464de8019SJohn Baldwin {
17564de8019SJohn Baldwin 	bool force;
17664de8019SJohn Baldwin 	int ch;
17764de8019SJohn Baldwin 
17864de8019SJohn Baldwin 	force = false;
17964de8019SJohn Baldwin 	while ((ch = getopt(ac, av, "f")) != -1)
18064de8019SJohn Baldwin 		switch (ch) {
18164de8019SJohn Baldwin 		case 'f':
18264de8019SJohn Baldwin 			force = true;
18364de8019SJohn Baldwin 			break;
18464de8019SJohn Baldwin 		default:
18564de8019SJohn Baldwin 			disable_usage();
18664de8019SJohn Baldwin 		}
18764de8019SJohn Baldwin 	ac -= optind;
18864de8019SJohn Baldwin 	av += optind;
18964de8019SJohn Baldwin 
19064de8019SJohn Baldwin 	if (ac != 1)
19164de8019SJohn Baldwin 		disable_usage();
19264de8019SJohn Baldwin 	if (devctl_disable(av[0], force) < 0)
19364de8019SJohn Baldwin 		err(1, "Failed to disable %s", av[0]);
19464de8019SJohn Baldwin 	return (0);
19564de8019SJohn Baldwin }
19664de8019SJohn Baldwin DEVCTL_COMMAND(top, disable, disable);
19764de8019SJohn Baldwin 
19864de8019SJohn Baldwin static int
enable(int ac,char ** av)19964de8019SJohn Baldwin enable(int ac, char **av)
20064de8019SJohn Baldwin {
20164de8019SJohn Baldwin 
20264de8019SJohn Baldwin 	if (ac != 2)
20364de8019SJohn Baldwin 		usage();
20464de8019SJohn Baldwin 	if (devctl_enable(av[1]) < 0)
20564de8019SJohn Baldwin 		err(1, "Failed to enable %s", av[1]);
20664de8019SJohn Baldwin 	return (0);
20764de8019SJohn Baldwin }
20864de8019SJohn Baldwin DEVCTL_COMMAND(top, enable, enable);
20964de8019SJohn Baldwin 
21064de8019SJohn Baldwin static int
suspend(int ac,char ** av)21164de8019SJohn Baldwin suspend(int ac, char **av)
21264de8019SJohn Baldwin {
21364de8019SJohn Baldwin 
21464de8019SJohn Baldwin 	if (ac != 2)
21564de8019SJohn Baldwin 		usage();
21664de8019SJohn Baldwin 	if (devctl_suspend(av[1]) < 0)
21764de8019SJohn Baldwin 		err(1, "Failed to suspend %s", av[1]);
21864de8019SJohn Baldwin 	return (0);
21964de8019SJohn Baldwin }
22064de8019SJohn Baldwin DEVCTL_COMMAND(top, suspend, suspend);
22164de8019SJohn Baldwin 
22264de8019SJohn Baldwin static int
resume(int ac,char ** av)22364de8019SJohn Baldwin resume(int ac, char **av)
22464de8019SJohn Baldwin {
22564de8019SJohn Baldwin 
22664de8019SJohn Baldwin 	if (ac != 2)
22764de8019SJohn Baldwin 		usage();
22864de8019SJohn Baldwin 	if (devctl_resume(av[1]) < 0)
22964de8019SJohn Baldwin 		err(1, "Failed to resume %s", av[1]);
23064de8019SJohn Baldwin 	return (0);
23164de8019SJohn Baldwin }
23264de8019SJohn Baldwin DEVCTL_COMMAND(top, resume, resume);
23364de8019SJohn Baldwin 
23464de8019SJohn Baldwin static void
set_driver_usage(void)23564de8019SJohn Baldwin set_driver_usage(void)
23664de8019SJohn Baldwin {
23764de8019SJohn Baldwin 
23864de8019SJohn Baldwin 	fprintf(stderr, "usage: devctl set driver [-f] device driver\n");
23964de8019SJohn Baldwin 	exit(1);
24064de8019SJohn Baldwin }
24164de8019SJohn Baldwin 
24264de8019SJohn Baldwin static int
set_driver(int ac,char ** av)24364de8019SJohn Baldwin set_driver(int ac, char **av)
24464de8019SJohn Baldwin {
24564de8019SJohn Baldwin 	bool force;
24664de8019SJohn Baldwin 	int ch;
24764de8019SJohn Baldwin 
24864de8019SJohn Baldwin 	force = false;
24964de8019SJohn Baldwin 	while ((ch = getopt(ac, av, "f")) != -1)
25064de8019SJohn Baldwin 		switch (ch) {
25164de8019SJohn Baldwin 		case 'f':
25264de8019SJohn Baldwin 			force = true;
25364de8019SJohn Baldwin 			break;
25464de8019SJohn Baldwin 		default:
25564de8019SJohn Baldwin 			set_driver_usage();
25664de8019SJohn Baldwin 		}
25764de8019SJohn Baldwin 	ac -= optind;
25864de8019SJohn Baldwin 	av += optind;
25964de8019SJohn Baldwin 
26064de8019SJohn Baldwin 	if (ac != 2)
26164de8019SJohn Baldwin 		set_driver_usage();
26264de8019SJohn Baldwin 	if (devctl_set_driver(av[0], av[1], force) < 0)
26364de8019SJohn Baldwin 		err(1, "Failed to set %s driver to %s", av[0], av[1]);
26464de8019SJohn Baldwin 	return (0);
26564de8019SJohn Baldwin }
26664de8019SJohn Baldwin DEVCTL_COMMAND(set, driver, set_driver);
26764de8019SJohn Baldwin 
268e05ec081SJohn Baldwin static void
clear_driver_usage(void)269e05ec081SJohn Baldwin clear_driver_usage(void)
270e05ec081SJohn Baldwin {
271e05ec081SJohn Baldwin 
272e05ec081SJohn Baldwin 	fprintf(stderr, "usage: devctl clear driver [-f] device\n");
273e05ec081SJohn Baldwin 	exit(1);
274e05ec081SJohn Baldwin }
275e05ec081SJohn Baldwin 
276e05ec081SJohn Baldwin static int
clear_driver(int ac,char ** av)277e05ec081SJohn Baldwin clear_driver(int ac, char **av)
278e05ec081SJohn Baldwin {
279e05ec081SJohn Baldwin 	bool force;
280e05ec081SJohn Baldwin 	int ch;
281e05ec081SJohn Baldwin 
282e05ec081SJohn Baldwin 	force = false;
283e05ec081SJohn Baldwin 	while ((ch = getopt(ac, av, "f")) != -1)
284e05ec081SJohn Baldwin 		switch (ch) {
285e05ec081SJohn Baldwin 		case 'f':
286e05ec081SJohn Baldwin 			force = true;
287e05ec081SJohn Baldwin 			break;
288e05ec081SJohn Baldwin 		default:
289e05ec081SJohn Baldwin 			clear_driver_usage();
290e05ec081SJohn Baldwin 		}
291e05ec081SJohn Baldwin 	ac -= optind;
292e05ec081SJohn Baldwin 	av += optind;
293e05ec081SJohn Baldwin 
294e05ec081SJohn Baldwin 	if (ac != 1)
295e05ec081SJohn Baldwin 		clear_driver_usage();
296e05ec081SJohn Baldwin 	if (devctl_clear_driver(av[0], force) < 0)
297e05ec081SJohn Baldwin 		err(1, "Failed to clear %s driver", av[0]);
298e05ec081SJohn Baldwin 	return (0);
299e05ec081SJohn Baldwin }
300e05ec081SJohn Baldwin DEVCTL_COMMAND(clear, driver, clear_driver);
301e05ec081SJohn Baldwin 
302a907c691SJohn Baldwin static int
rescan(int ac,char ** av)303a907c691SJohn Baldwin rescan(int ac, char **av)
304a907c691SJohn Baldwin {
305a907c691SJohn Baldwin 
306a907c691SJohn Baldwin 	if (ac != 2)
307a907c691SJohn Baldwin 		usage();
308a907c691SJohn Baldwin 	if (devctl_rescan(av[1]) < 0)
309a907c691SJohn Baldwin 		err(1, "Failed to rescan %s", av[1]);
310a907c691SJohn Baldwin 	return (0);
311a907c691SJohn Baldwin }
312a907c691SJohn Baldwin DEVCTL_COMMAND(top, rescan, rescan);
313a907c691SJohn Baldwin 
31488eb5c50SJohn Baldwin static void
delete_usage(void)31588eb5c50SJohn Baldwin delete_usage(void)
31688eb5c50SJohn Baldwin {
31788eb5c50SJohn Baldwin 
31888eb5c50SJohn Baldwin 	fprintf(stderr, "usage: devctl delete [-f] device\n");
31988eb5c50SJohn Baldwin 	exit(1);
32088eb5c50SJohn Baldwin }
32188eb5c50SJohn Baldwin 
32288eb5c50SJohn Baldwin static int
delete(int ac,char ** av)32388eb5c50SJohn Baldwin delete(int ac, char **av)
32488eb5c50SJohn Baldwin {
32588eb5c50SJohn Baldwin 	bool force;
32688eb5c50SJohn Baldwin 	int ch;
32788eb5c50SJohn Baldwin 
32888eb5c50SJohn Baldwin 	force = false;
32988eb5c50SJohn Baldwin 	while ((ch = getopt(ac, av, "f")) != -1)
33088eb5c50SJohn Baldwin 		switch (ch) {
33188eb5c50SJohn Baldwin 		case 'f':
33288eb5c50SJohn Baldwin 			force = true;
33388eb5c50SJohn Baldwin 			break;
33488eb5c50SJohn Baldwin 		default:
33588eb5c50SJohn Baldwin 			delete_usage();
33688eb5c50SJohn Baldwin 		}
33788eb5c50SJohn Baldwin 	ac -= optind;
33888eb5c50SJohn Baldwin 	av += optind;
33988eb5c50SJohn Baldwin 
34088eb5c50SJohn Baldwin 	if (ac != 1)
34188eb5c50SJohn Baldwin 		delete_usage();
34288eb5c50SJohn Baldwin 	if (devctl_delete(av[0], force) < 0)
34388eb5c50SJohn Baldwin 		err(1, "Failed to delete %s", av[0]);
34488eb5c50SJohn Baldwin 	return (0);
34588eb5c50SJohn Baldwin }
34688eb5c50SJohn Baldwin DEVCTL_COMMAND(top, delete, delete);
34788eb5c50SJohn Baldwin 
3485fa29797SWarner Losh static void
freeze_usage(void)3495fa29797SWarner Losh freeze_usage(void)
3505fa29797SWarner Losh {
3515fa29797SWarner Losh 
3525fa29797SWarner Losh 	fprintf(stderr, "usage: devctl freeze\n");
3535fa29797SWarner Losh 	exit(1);
3545fa29797SWarner Losh }
3555fa29797SWarner Losh 
3565fa29797SWarner Losh static int
freeze(int ac,char ** av __unused)3575fa29797SWarner Losh freeze(int ac, char **av __unused)
3585fa29797SWarner Losh {
3595fa29797SWarner Losh 
3605fa29797SWarner Losh 	if (ac != 1)
3615fa29797SWarner Losh 		freeze_usage();
3625fa29797SWarner Losh 	if (devctl_freeze() < 0)
3635fa29797SWarner Losh 		err(1, "Failed to freeze probe/attach");
3645fa29797SWarner Losh 	return (0);
3655fa29797SWarner Losh }
3665fa29797SWarner Losh DEVCTL_COMMAND(top, freeze, freeze);
3675fa29797SWarner Losh 
3685fa29797SWarner Losh static void
thaw_usage(void)3695fa29797SWarner Losh thaw_usage(void)
3705fa29797SWarner Losh {
3715fa29797SWarner Losh 
3725fa29797SWarner Losh 	fprintf(stderr, "usage: devctl thaw\n");
3735fa29797SWarner Losh 	exit(1);
3745fa29797SWarner Losh }
3755fa29797SWarner Losh 
3765fa29797SWarner Losh static int
thaw(int ac,char ** av __unused)3775fa29797SWarner Losh thaw(int ac, char **av __unused)
3785fa29797SWarner Losh {
3795fa29797SWarner Losh 
3805fa29797SWarner Losh 	if (ac != 1)
3815fa29797SWarner Losh 		thaw_usage();
3825fa29797SWarner Losh 	if (devctl_thaw() < 0)
3835fa29797SWarner Losh 		err(1, "Failed to thaw probe/attach");
3845fa29797SWarner Losh 	return (0);
3855fa29797SWarner Losh }
3865fa29797SWarner Losh DEVCTL_COMMAND(top, thaw, thaw);
3875fa29797SWarner Losh 
3884fbf8e1cSKonstantin Belousov static void
reset_usage(void)3894fbf8e1cSKonstantin Belousov reset_usage(void)
3904fbf8e1cSKonstantin Belousov {
3914fbf8e1cSKonstantin Belousov 
3924fbf8e1cSKonstantin Belousov 	fprintf(stderr, "usage: devctl reset [-d] device\n");
3934fbf8e1cSKonstantin Belousov 	exit(1);
3944fbf8e1cSKonstantin Belousov }
3954fbf8e1cSKonstantin Belousov 
3964fbf8e1cSKonstantin Belousov static int
reset(int ac,char ** av)3974fbf8e1cSKonstantin Belousov reset(int ac, char **av)
3984fbf8e1cSKonstantin Belousov {
399ca34d6aeSKonstantin Belousov 	bool detach_drv;
4004fbf8e1cSKonstantin Belousov 	int ch;
4014fbf8e1cSKonstantin Belousov 
402ca34d6aeSKonstantin Belousov 	detach_drv = false;
4034fbf8e1cSKonstantin Belousov 	while ((ch = getopt(ac, av, "d")) != -1)
4044fbf8e1cSKonstantin Belousov 		switch (ch) {
4054fbf8e1cSKonstantin Belousov 		case 'd':
406ca34d6aeSKonstantin Belousov 			detach_drv = true;
4074fbf8e1cSKonstantin Belousov 			break;
4084fbf8e1cSKonstantin Belousov 		default:
4094fbf8e1cSKonstantin Belousov 			reset_usage();
4104fbf8e1cSKonstantin Belousov 		}
4114fbf8e1cSKonstantin Belousov 	ac -= optind;
4124fbf8e1cSKonstantin Belousov 	av += optind;
4134fbf8e1cSKonstantin Belousov 
4144fbf8e1cSKonstantin Belousov 	if (ac != 1)
4154fbf8e1cSKonstantin Belousov 		reset_usage();
416ca34d6aeSKonstantin Belousov 	if (devctl_reset(av[0], detach_drv) < 0)
4174fbf8e1cSKonstantin Belousov 		err(1, "Failed to reset %s", av[0]);
4184fbf8e1cSKonstantin Belousov 	return (0);
4194fbf8e1cSKonstantin Belousov }
4204fbf8e1cSKonstantin Belousov DEVCTL_COMMAND(top, reset, reset);
4214fbf8e1cSKonstantin Belousov 
422*f5366026SWarner Losh static int
getpath(int ac,char ** av)423*f5366026SWarner Losh getpath(int ac, char **av)
424*f5366026SWarner Losh {
425*f5366026SWarner Losh 	char *buffer = NULL;
426*f5366026SWarner Losh 
427*f5366026SWarner Losh 	if (ac != 3)
428*f5366026SWarner Losh 		usage();
429*f5366026SWarner Losh 	if (devctl_getpath(av[2], av[1], &buffer) < 0)
430*f5366026SWarner Losh 		err(1, "Failed to get path via %s to %s", av[1], av[2]);
431*f5366026SWarner Losh 	printf("%s\n", buffer);
432*f5366026SWarner Losh 	free(buffer);
433*f5366026SWarner Losh 	return (0);
434*f5366026SWarner Losh }
435*f5366026SWarner Losh DEVCTL_COMMAND(top, getpath, getpath);
436*f5366026SWarner Losh 
43764de8019SJohn Baldwin int
main(int ac,char * av[])43864de8019SJohn Baldwin main(int ac, char *av[])
43964de8019SJohn Baldwin {
44064de8019SJohn Baldwin 	struct devctl_command **cmd;
44164de8019SJohn Baldwin 
44264de8019SJohn Baldwin 	if (ac == 1)
44364de8019SJohn Baldwin 		usage();
44464de8019SJohn Baldwin 	ac--;
44564de8019SJohn Baldwin 	av++;
44664de8019SJohn Baldwin 
44764de8019SJohn Baldwin 	SET_FOREACH(cmd, DEVCTL_DATASET(top)) {
44864de8019SJohn Baldwin 		if (strcmp((*cmd)->name, av[0]) == 0) {
44964de8019SJohn Baldwin 			if ((*cmd)->handler(ac, av) != 0)
45064de8019SJohn Baldwin 				return (1);
45164de8019SJohn Baldwin 			else
45264de8019SJohn Baldwin 				return (0);
45364de8019SJohn Baldwin 		}
45464de8019SJohn Baldwin 	}
45564de8019SJohn Baldwin 	warnx("Unknown command %s.", av[0]);
45664de8019SJohn Baldwin 	return (1);
45764de8019SJohn Baldwin }
458