164de8019SJohn Baldwin /*-
264de8019SJohn Baldwin * Copyright (c) 2014 John Baldwin <[email protected]>
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 __FBSDID("$FreeBSD$");
2864de8019SJohn Baldwin
2964de8019SJohn Baldwin #include <sys/linker_set.h>
3064de8019SJohn Baldwin #include <devctl.h>
3164de8019SJohn Baldwin #include <err.h>
3264de8019SJohn Baldwin #include <errno.h>
3364de8019SJohn Baldwin #include <stdio.h>
3464de8019SJohn Baldwin #include <stdlib.h>
3564de8019SJohn Baldwin #include <string.h>
3664de8019SJohn Baldwin #include <strings.h>
3764de8019SJohn Baldwin #include <unistd.h>
3864de8019SJohn Baldwin
3964de8019SJohn Baldwin struct devctl_command {
4064de8019SJohn Baldwin const char *name;
4164de8019SJohn Baldwin int (*handler)(int ac, char **av);
4264de8019SJohn Baldwin };
4364de8019SJohn Baldwin
4464de8019SJohn Baldwin #define DEVCTL_DATASET(name) devctl_ ## name ## _table
4564de8019SJohn Baldwin
4664de8019SJohn Baldwin #define DEVCTL_COMMAND(set, name, function) \
4764de8019SJohn Baldwin static struct devctl_command function ## _devctl_command = \
4864de8019SJohn Baldwin { #name, function }; \
4964de8019SJohn Baldwin DATA_SET(DEVCTL_DATASET(set), function ## _devctl_command)
5064de8019SJohn Baldwin
5164de8019SJohn Baldwin #define DEVCTL_TABLE(set, name) \
5264de8019SJohn Baldwin SET_DECLARE(DEVCTL_DATASET(name), struct devctl_command); \
5364de8019SJohn Baldwin \
5464de8019SJohn Baldwin static int \
5564de8019SJohn Baldwin devctl_ ## name ## _table_handler(int ac, char **av) \
5664de8019SJohn Baldwin { \
5764de8019SJohn Baldwin return (devctl_table_handler(SET_BEGIN(DEVCTL_DATASET(name)), \
5864de8019SJohn Baldwin SET_LIMIT(DEVCTL_DATASET(name)), ac, av)); \
5964de8019SJohn Baldwin } \
6064de8019SJohn Baldwin DEVCTL_COMMAND(set, name, devctl_ ## name ## _table_handler)
6164de8019SJohn Baldwin
6264de8019SJohn Baldwin static int devctl_table_handler(struct devctl_command **start,
6364de8019SJohn Baldwin struct devctl_command **end, int ac, char **av);
6464de8019SJohn Baldwin
6564de8019SJohn Baldwin SET_DECLARE(DEVCTL_DATASET(top), struct devctl_command);
6664de8019SJohn Baldwin
67e05ec081SJohn Baldwin DEVCTL_TABLE(top, clear);
6864de8019SJohn Baldwin DEVCTL_TABLE(top, set);
6964de8019SJohn Baldwin
7064de8019SJohn Baldwin static void
usage(void)7164de8019SJohn Baldwin usage(void)
7264de8019SJohn Baldwin {
735fa29797SWarner Losh fprintf(stderr,
745fa29797SWarner Losh "usage: devctl attach device\n"
755fa29797SWarner Losh " devctl detach [-f] device\n"
765fa29797SWarner Losh " devctl disable [-f] device\n"
775fa29797SWarner Losh " devctl enable device\n"
785fa29797SWarner Losh " devctl suspend device\n"
795fa29797SWarner Losh " devctl resume device\n"
805fa29797SWarner Losh " devctl set driver [-f] device driver\n"
815fa29797SWarner Losh " devctl clear driver [-f] device\n"
825fa29797SWarner Losh " devctl rescan device\n"
835fa29797SWarner Losh " devctl delete [-f] device\n"
845fa29797SWarner Losh " devctl freeze\n"
854fbf8e1cSKonstantin Belousov " devctl thaw\n"
864fbf8e1cSKonstantin Belousov " devctl reset [-d] device\n"
874fbf8e1cSKonstantin Belousov );
8864de8019SJohn Baldwin exit(1);
8964de8019SJohn Baldwin }
9064de8019SJohn Baldwin
9164de8019SJohn Baldwin static int
devctl_table_handler(struct devctl_command ** start,struct devctl_command ** end,int ac,char ** av)9264de8019SJohn Baldwin devctl_table_handler(struct devctl_command **start,
9364de8019SJohn Baldwin struct devctl_command **end, int ac, char **av)
9464de8019SJohn Baldwin {
9564de8019SJohn Baldwin struct devctl_command **cmd;
9664de8019SJohn Baldwin
9764de8019SJohn Baldwin if (ac < 2) {
9864de8019SJohn Baldwin warnx("The %s command requires a sub-command.", av[0]);
9964de8019SJohn Baldwin return (EINVAL);
10064de8019SJohn Baldwin }
10164de8019SJohn Baldwin for (cmd = start; cmd < end; cmd++) {
10264de8019SJohn Baldwin if (strcmp((*cmd)->name, av[1]) == 0)
10364de8019SJohn Baldwin return ((*cmd)->handler(ac - 1, av + 1));
10464de8019SJohn Baldwin }
10564de8019SJohn Baldwin
10664de8019SJohn Baldwin warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
10764de8019SJohn Baldwin return (ENOENT);
10864de8019SJohn Baldwin }
10964de8019SJohn Baldwin
11064de8019SJohn Baldwin static int
help(int ac __unused,char ** av __unused)11164de8019SJohn Baldwin help(int ac __unused, char **av __unused)
11264de8019SJohn Baldwin {
11364de8019SJohn Baldwin
11464de8019SJohn Baldwin usage();
11564de8019SJohn Baldwin return (0);
11664de8019SJohn Baldwin }
11764de8019SJohn Baldwin DEVCTL_COMMAND(top, help, help);
11864de8019SJohn Baldwin
11964de8019SJohn Baldwin static int
attach(int ac,char ** av)12064de8019SJohn Baldwin attach(int ac, char **av)
12164de8019SJohn Baldwin {
12264de8019SJohn Baldwin
12364de8019SJohn Baldwin if (ac != 2)
12464de8019SJohn Baldwin usage();
12564de8019SJohn Baldwin if (devctl_attach(av[1]) < 0)
12664de8019SJohn Baldwin err(1, "Failed to attach %s", av[1]);
12764de8019SJohn Baldwin return (0);
12864de8019SJohn Baldwin }
12964de8019SJohn Baldwin DEVCTL_COMMAND(top, attach, attach);
13064de8019SJohn Baldwin
13164de8019SJohn Baldwin static void
detach_usage(void)13264de8019SJohn Baldwin detach_usage(void)
13364de8019SJohn Baldwin {
13464de8019SJohn Baldwin
13564de8019SJohn Baldwin fprintf(stderr, "usage: devctl detach [-f] device\n");
13664de8019SJohn Baldwin exit(1);
13764de8019SJohn Baldwin }
13864de8019SJohn Baldwin
13964de8019SJohn Baldwin static int
detach(int ac,char ** av)14064de8019SJohn Baldwin detach(int ac, char **av)
14164de8019SJohn Baldwin {
14264de8019SJohn Baldwin bool force;
14364de8019SJohn Baldwin int ch;
14464de8019SJohn Baldwin
14564de8019SJohn Baldwin force = false;
14664de8019SJohn Baldwin while ((ch = getopt(ac, av, "f")) != -1)
14764de8019SJohn Baldwin switch (ch) {
14864de8019SJohn Baldwin case 'f':
14964de8019SJohn Baldwin force = true;
15064de8019SJohn Baldwin break;
15164de8019SJohn Baldwin default:
15264de8019SJohn Baldwin detach_usage();
15364de8019SJohn Baldwin }
15464de8019SJohn Baldwin ac -= optind;
15564de8019SJohn Baldwin av += optind;
15664de8019SJohn Baldwin
15764de8019SJohn Baldwin if (ac != 1)
15864de8019SJohn Baldwin detach_usage();
15964de8019SJohn Baldwin if (devctl_detach(av[0], force) < 0)
16064de8019SJohn Baldwin err(1, "Failed to detach %s", av[0]);
16164de8019SJohn Baldwin return (0);
16264de8019SJohn Baldwin }
16364de8019SJohn Baldwin DEVCTL_COMMAND(top, detach, detach);
16464de8019SJohn Baldwin
16564de8019SJohn Baldwin static void
disable_usage(void)16664de8019SJohn Baldwin disable_usage(void)
16764de8019SJohn Baldwin {
16864de8019SJohn Baldwin
16964de8019SJohn Baldwin fprintf(stderr, "usage: devctl disable [-f] device\n");
17064de8019SJohn Baldwin exit(1);
17164de8019SJohn Baldwin }
17264de8019SJohn Baldwin
17364de8019SJohn Baldwin static int
disable(int ac,char ** av)17464de8019SJohn Baldwin disable(int ac, char **av)
17564de8019SJohn Baldwin {
17664de8019SJohn Baldwin bool force;
17764de8019SJohn Baldwin int ch;
17864de8019SJohn Baldwin
17964de8019SJohn Baldwin force = false;
18064de8019SJohn Baldwin while ((ch = getopt(ac, av, "f")) != -1)
18164de8019SJohn Baldwin switch (ch) {
18264de8019SJohn Baldwin case 'f':
18364de8019SJohn Baldwin force = true;
18464de8019SJohn Baldwin break;
18564de8019SJohn Baldwin default:
18664de8019SJohn Baldwin disable_usage();
18764de8019SJohn Baldwin }
18864de8019SJohn Baldwin ac -= optind;
18964de8019SJohn Baldwin av += optind;
19064de8019SJohn Baldwin
19164de8019SJohn Baldwin if (ac != 1)
19264de8019SJohn Baldwin disable_usage();
19364de8019SJohn Baldwin if (devctl_disable(av[0], force) < 0)
19464de8019SJohn Baldwin err(1, "Failed to disable %s", av[0]);
19564de8019SJohn Baldwin return (0);
19664de8019SJohn Baldwin }
19764de8019SJohn Baldwin DEVCTL_COMMAND(top, disable, disable);
19864de8019SJohn Baldwin
19964de8019SJohn Baldwin static int
enable(int ac,char ** av)20064de8019SJohn Baldwin enable(int ac, char **av)
20164de8019SJohn Baldwin {
20264de8019SJohn Baldwin
20364de8019SJohn Baldwin if (ac != 2)
20464de8019SJohn Baldwin usage();
20564de8019SJohn Baldwin if (devctl_enable(av[1]) < 0)
20664de8019SJohn Baldwin err(1, "Failed to enable %s", av[1]);
20764de8019SJohn Baldwin return (0);
20864de8019SJohn Baldwin }
20964de8019SJohn Baldwin DEVCTL_COMMAND(top, enable, enable);
21064de8019SJohn Baldwin
21164de8019SJohn Baldwin static int
suspend(int ac,char ** av)21264de8019SJohn Baldwin suspend(int ac, char **av)
21364de8019SJohn Baldwin {
21464de8019SJohn Baldwin
21564de8019SJohn Baldwin if (ac != 2)
21664de8019SJohn Baldwin usage();
21764de8019SJohn Baldwin if (devctl_suspend(av[1]) < 0)
21864de8019SJohn Baldwin err(1, "Failed to suspend %s", av[1]);
21964de8019SJohn Baldwin return (0);
22064de8019SJohn Baldwin }
22164de8019SJohn Baldwin DEVCTL_COMMAND(top, suspend, suspend);
22264de8019SJohn Baldwin
22364de8019SJohn Baldwin static int
resume(int ac,char ** av)22464de8019SJohn Baldwin resume(int ac, char **av)
22564de8019SJohn Baldwin {
22664de8019SJohn Baldwin
22764de8019SJohn Baldwin if (ac != 2)
22864de8019SJohn Baldwin usage();
22964de8019SJohn Baldwin if (devctl_resume(av[1]) < 0)
23064de8019SJohn Baldwin err(1, "Failed to resume %s", av[1]);
23164de8019SJohn Baldwin return (0);
23264de8019SJohn Baldwin }
23364de8019SJohn Baldwin DEVCTL_COMMAND(top, resume, resume);
23464de8019SJohn Baldwin
23564de8019SJohn Baldwin static void
set_driver_usage(void)23664de8019SJohn Baldwin set_driver_usage(void)
23764de8019SJohn Baldwin {
23864de8019SJohn Baldwin
23964de8019SJohn Baldwin fprintf(stderr, "usage: devctl set driver [-f] device driver\n");
24064de8019SJohn Baldwin exit(1);
24164de8019SJohn Baldwin }
24264de8019SJohn Baldwin
24364de8019SJohn Baldwin static int
set_driver(int ac,char ** av)24464de8019SJohn Baldwin set_driver(int ac, char **av)
24564de8019SJohn Baldwin {
24664de8019SJohn Baldwin bool force;
24764de8019SJohn Baldwin int ch;
24864de8019SJohn Baldwin
24964de8019SJohn Baldwin force = false;
25064de8019SJohn Baldwin while ((ch = getopt(ac, av, "f")) != -1)
25164de8019SJohn Baldwin switch (ch) {
25264de8019SJohn Baldwin case 'f':
25364de8019SJohn Baldwin force = true;
25464de8019SJohn Baldwin break;
25564de8019SJohn Baldwin default:
25664de8019SJohn Baldwin set_driver_usage();
25764de8019SJohn Baldwin }
25864de8019SJohn Baldwin ac -= optind;
25964de8019SJohn Baldwin av += optind;
26064de8019SJohn Baldwin
26164de8019SJohn Baldwin if (ac != 2)
26264de8019SJohn Baldwin set_driver_usage();
26364de8019SJohn Baldwin if (devctl_set_driver(av[0], av[1], force) < 0)
26464de8019SJohn Baldwin err(1, "Failed to set %s driver to %s", av[0], av[1]);
26564de8019SJohn Baldwin return (0);
26664de8019SJohn Baldwin }
26764de8019SJohn Baldwin DEVCTL_COMMAND(set, driver, set_driver);
26864de8019SJohn Baldwin
269e05ec081SJohn Baldwin static void
clear_driver_usage(void)270e05ec081SJohn Baldwin clear_driver_usage(void)
271e05ec081SJohn Baldwin {
272e05ec081SJohn Baldwin
273e05ec081SJohn Baldwin fprintf(stderr, "usage: devctl clear driver [-f] device\n");
274e05ec081SJohn Baldwin exit(1);
275e05ec081SJohn Baldwin }
276e05ec081SJohn Baldwin
277e05ec081SJohn Baldwin static int
clear_driver(int ac,char ** av)278e05ec081SJohn Baldwin clear_driver(int ac, char **av)
279e05ec081SJohn Baldwin {
280e05ec081SJohn Baldwin bool force;
281e05ec081SJohn Baldwin int ch;
282e05ec081SJohn Baldwin
283e05ec081SJohn Baldwin force = false;
284e05ec081SJohn Baldwin while ((ch = getopt(ac, av, "f")) != -1)
285e05ec081SJohn Baldwin switch (ch) {
286e05ec081SJohn Baldwin case 'f':
287e05ec081SJohn Baldwin force = true;
288e05ec081SJohn Baldwin break;
289e05ec081SJohn Baldwin default:
290e05ec081SJohn Baldwin clear_driver_usage();
291e05ec081SJohn Baldwin }
292e05ec081SJohn Baldwin ac -= optind;
293e05ec081SJohn Baldwin av += optind;
294e05ec081SJohn Baldwin
295e05ec081SJohn Baldwin if (ac != 1)
296e05ec081SJohn Baldwin clear_driver_usage();
297e05ec081SJohn Baldwin if (devctl_clear_driver(av[0], force) < 0)
298e05ec081SJohn Baldwin err(1, "Failed to clear %s driver", av[0]);
299e05ec081SJohn Baldwin return (0);
300e05ec081SJohn Baldwin }
301e05ec081SJohn Baldwin DEVCTL_COMMAND(clear, driver, clear_driver);
302e05ec081SJohn Baldwin
303a907c691SJohn Baldwin static int
rescan(int ac,char ** av)304a907c691SJohn Baldwin rescan(int ac, char **av)
305a907c691SJohn Baldwin {
306a907c691SJohn Baldwin
307a907c691SJohn Baldwin if (ac != 2)
308a907c691SJohn Baldwin usage();
309a907c691SJohn Baldwin if (devctl_rescan(av[1]) < 0)
310a907c691SJohn Baldwin err(1, "Failed to rescan %s", av[1]);
311a907c691SJohn Baldwin return (0);
312a907c691SJohn Baldwin }
313a907c691SJohn Baldwin DEVCTL_COMMAND(top, rescan, rescan);
314a907c691SJohn Baldwin
31588eb5c50SJohn Baldwin static void
delete_usage(void)31688eb5c50SJohn Baldwin delete_usage(void)
31788eb5c50SJohn Baldwin {
31888eb5c50SJohn Baldwin
31988eb5c50SJohn Baldwin fprintf(stderr, "usage: devctl delete [-f] device\n");
32088eb5c50SJohn Baldwin exit(1);
32188eb5c50SJohn Baldwin }
32288eb5c50SJohn Baldwin
32388eb5c50SJohn Baldwin static int
delete(int ac,char ** av)32488eb5c50SJohn Baldwin delete(int ac, char **av)
32588eb5c50SJohn Baldwin {
32688eb5c50SJohn Baldwin bool force;
32788eb5c50SJohn Baldwin int ch;
32888eb5c50SJohn Baldwin
32988eb5c50SJohn Baldwin force = false;
33088eb5c50SJohn Baldwin while ((ch = getopt(ac, av, "f")) != -1)
33188eb5c50SJohn Baldwin switch (ch) {
33288eb5c50SJohn Baldwin case 'f':
33388eb5c50SJohn Baldwin force = true;
33488eb5c50SJohn Baldwin break;
33588eb5c50SJohn Baldwin default:
33688eb5c50SJohn Baldwin delete_usage();
33788eb5c50SJohn Baldwin }
33888eb5c50SJohn Baldwin ac -= optind;
33988eb5c50SJohn Baldwin av += optind;
34088eb5c50SJohn Baldwin
34188eb5c50SJohn Baldwin if (ac != 1)
34288eb5c50SJohn Baldwin delete_usage();
34388eb5c50SJohn Baldwin if (devctl_delete(av[0], force) < 0)
34488eb5c50SJohn Baldwin err(1, "Failed to delete %s", av[0]);
34588eb5c50SJohn Baldwin return (0);
34688eb5c50SJohn Baldwin }
34788eb5c50SJohn Baldwin DEVCTL_COMMAND(top, delete, delete);
34888eb5c50SJohn Baldwin
3495fa29797SWarner Losh static void
freeze_usage(void)3505fa29797SWarner Losh freeze_usage(void)
3515fa29797SWarner Losh {
3525fa29797SWarner Losh
3535fa29797SWarner Losh fprintf(stderr, "usage: devctl freeze\n");
3545fa29797SWarner Losh exit(1);
3555fa29797SWarner Losh }
3565fa29797SWarner Losh
3575fa29797SWarner Losh static int
freeze(int ac,char ** av __unused)3585fa29797SWarner Losh freeze(int ac, char **av __unused)
3595fa29797SWarner Losh {
3605fa29797SWarner Losh
3615fa29797SWarner Losh if (ac != 1)
3625fa29797SWarner Losh freeze_usage();
3635fa29797SWarner Losh if (devctl_freeze() < 0)
3645fa29797SWarner Losh err(1, "Failed to freeze probe/attach");
3655fa29797SWarner Losh return (0);
3665fa29797SWarner Losh }
3675fa29797SWarner Losh DEVCTL_COMMAND(top, freeze, freeze);
3685fa29797SWarner Losh
3695fa29797SWarner Losh static void
thaw_usage(void)3705fa29797SWarner Losh thaw_usage(void)
3715fa29797SWarner Losh {
3725fa29797SWarner Losh
3735fa29797SWarner Losh fprintf(stderr, "usage: devctl thaw\n");
3745fa29797SWarner Losh exit(1);
3755fa29797SWarner Losh }
3765fa29797SWarner Losh
3775fa29797SWarner Losh static int
thaw(int ac,char ** av __unused)3785fa29797SWarner Losh thaw(int ac, char **av __unused)
3795fa29797SWarner Losh {
3805fa29797SWarner Losh
3815fa29797SWarner Losh if (ac != 1)
3825fa29797SWarner Losh thaw_usage();
3835fa29797SWarner Losh if (devctl_thaw() < 0)
3845fa29797SWarner Losh err(1, "Failed to thaw probe/attach");
3855fa29797SWarner Losh return (0);
3865fa29797SWarner Losh }
3875fa29797SWarner Losh DEVCTL_COMMAND(top, thaw, thaw);
3885fa29797SWarner Losh
3894fbf8e1cSKonstantin Belousov static void
reset_usage(void)3904fbf8e1cSKonstantin Belousov reset_usage(void)
3914fbf8e1cSKonstantin Belousov {
3924fbf8e1cSKonstantin Belousov
3934fbf8e1cSKonstantin Belousov fprintf(stderr, "usage: devctl reset [-d] device\n");
3944fbf8e1cSKonstantin Belousov exit(1);
3954fbf8e1cSKonstantin Belousov }
3964fbf8e1cSKonstantin Belousov
3974fbf8e1cSKonstantin Belousov static int
reset(int ac,char ** av)3984fbf8e1cSKonstantin Belousov reset(int ac, char **av)
3994fbf8e1cSKonstantin Belousov {
400*ca34d6aeSKonstantin Belousov bool detach_drv;
4014fbf8e1cSKonstantin Belousov int ch;
4024fbf8e1cSKonstantin Belousov
403*ca34d6aeSKonstantin Belousov detach_drv = false;
4044fbf8e1cSKonstantin Belousov while ((ch = getopt(ac, av, "d")) != -1)
4054fbf8e1cSKonstantin Belousov switch (ch) {
4064fbf8e1cSKonstantin Belousov case 'd':
407*ca34d6aeSKonstantin Belousov detach_drv = true;
4084fbf8e1cSKonstantin Belousov break;
4094fbf8e1cSKonstantin Belousov default:
4104fbf8e1cSKonstantin Belousov reset_usage();
4114fbf8e1cSKonstantin Belousov }
4124fbf8e1cSKonstantin Belousov ac -= optind;
4134fbf8e1cSKonstantin Belousov av += optind;
4144fbf8e1cSKonstantin Belousov
4154fbf8e1cSKonstantin Belousov if (ac != 1)
4164fbf8e1cSKonstantin Belousov reset_usage();
417*ca34d6aeSKonstantin Belousov if (devctl_reset(av[0], detach_drv) < 0)
4184fbf8e1cSKonstantin Belousov err(1, "Failed to reset %s", av[0]);
4194fbf8e1cSKonstantin Belousov return (0);
4204fbf8e1cSKonstantin Belousov }
4214fbf8e1cSKonstantin Belousov DEVCTL_COMMAND(top, reset, reset);
4224fbf8e1cSKonstantin Belousov
42364de8019SJohn Baldwin int
main(int ac,char * av[])42464de8019SJohn Baldwin main(int ac, char *av[])
42564de8019SJohn Baldwin {
42664de8019SJohn Baldwin struct devctl_command **cmd;
42764de8019SJohn Baldwin
42864de8019SJohn Baldwin if (ac == 1)
42964de8019SJohn Baldwin usage();
43064de8019SJohn Baldwin ac--;
43164de8019SJohn Baldwin av++;
43264de8019SJohn Baldwin
43364de8019SJohn Baldwin SET_FOREACH(cmd, DEVCTL_DATASET(top)) {
43464de8019SJohn Baldwin if (strcmp((*cmd)->name, av[0]) == 0) {
43564de8019SJohn Baldwin if ((*cmd)->handler(ac, av) != 0)
43664de8019SJohn Baldwin return (1);
43764de8019SJohn Baldwin else
43864de8019SJohn Baldwin return (0);
43964de8019SJohn Baldwin }
44064de8019SJohn Baldwin }
44164de8019SJohn Baldwin warnx("Unknown command %s.", av[0]);
44264de8019SJohn Baldwin return (1);
44364de8019SJohn Baldwin }
444