164de8019SJohn Baldwin /*-
264de8019SJohn Baldwin * Copyright (c) 2014 John Baldwin <[email protected]>
364de8019SJohn Baldwin * All rights reserved.
464de8019SJohn Baldwin *
564de8019SJohn Baldwin * Redistribution and use in source and binary forms, with or without
664de8019SJohn Baldwin * modification, are permitted provided that the following conditions
764de8019SJohn Baldwin * are met:
864de8019SJohn Baldwin * 1. Redistributions of source code must retain the above copyright
964de8019SJohn Baldwin * notice, this list of conditions and the following disclaimer.
1064de8019SJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright
1164de8019SJohn Baldwin * notice, this list of conditions and the following disclaimer in the
1264de8019SJohn Baldwin * documentation and/or other materials provided with the distribution.
1364de8019SJohn Baldwin *
1464de8019SJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1564de8019SJohn Baldwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1664de8019SJohn Baldwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1764de8019SJohn Baldwin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1864de8019SJohn Baldwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1964de8019SJohn Baldwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2064de8019SJohn Baldwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2164de8019SJohn Baldwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2264de8019SJohn Baldwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2364de8019SJohn Baldwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2464de8019SJohn Baldwin * SUCH DAMAGE.
2564de8019SJohn Baldwin */
2664de8019SJohn Baldwin
2764de8019SJohn Baldwin #include <sys/cdefs.h>
2864de8019SJohn Baldwin __FBSDID("$FreeBSD$");
2964de8019SJohn Baldwin
3064de8019SJohn Baldwin #include <sys/linker_set.h>
3164de8019SJohn Baldwin #include <devctl.h>
3264de8019SJohn Baldwin #include <err.h>
3364de8019SJohn Baldwin #include <errno.h>
3464de8019SJohn Baldwin #include <stdio.h>
3564de8019SJohn Baldwin #include <stdlib.h>
3664de8019SJohn Baldwin #include <string.h>
3764de8019SJohn Baldwin #include <strings.h>
3864de8019SJohn Baldwin #include <unistd.h>
3964de8019SJohn Baldwin
4064de8019SJohn Baldwin struct devctl_command {
4164de8019SJohn Baldwin const char *name;
4264de8019SJohn Baldwin int (*handler)(int ac, char **av);
4364de8019SJohn Baldwin };
4464de8019SJohn Baldwin
4564de8019SJohn Baldwin #define DEVCTL_DATASET(name) devctl_ ## name ## _table
4664de8019SJohn Baldwin
4764de8019SJohn Baldwin #define DEVCTL_COMMAND(set, name, function) \
4864de8019SJohn Baldwin static struct devctl_command function ## _devctl_command = \
4964de8019SJohn Baldwin { #name, function }; \
5064de8019SJohn Baldwin DATA_SET(DEVCTL_DATASET(set), function ## _devctl_command)
5164de8019SJohn Baldwin
5264de8019SJohn Baldwin #define DEVCTL_TABLE(set, name) \
5364de8019SJohn Baldwin SET_DECLARE(DEVCTL_DATASET(name), struct devctl_command); \
5464de8019SJohn Baldwin \
5564de8019SJohn Baldwin static int \
5664de8019SJohn Baldwin devctl_ ## name ## _table_handler(int ac, char **av) \
5764de8019SJohn Baldwin { \
5864de8019SJohn Baldwin return (devctl_table_handler(SET_BEGIN(DEVCTL_DATASET(name)), \
5964de8019SJohn Baldwin SET_LIMIT(DEVCTL_DATASET(name)), ac, av)); \
6064de8019SJohn Baldwin } \
6164de8019SJohn Baldwin DEVCTL_COMMAND(set, name, devctl_ ## name ## _table_handler)
6264de8019SJohn Baldwin
6364de8019SJohn Baldwin static int devctl_table_handler(struct devctl_command **start,
6464de8019SJohn Baldwin struct devctl_command **end, int ac, char **av);
6564de8019SJohn Baldwin
6664de8019SJohn Baldwin SET_DECLARE(DEVCTL_DATASET(top), struct devctl_command);
6764de8019SJohn Baldwin
68e05ec081SJohn Baldwin DEVCTL_TABLE(top, clear);
6964de8019SJohn Baldwin DEVCTL_TABLE(top, set);
7064de8019SJohn Baldwin
7164de8019SJohn Baldwin static void
usage(void)7264de8019SJohn Baldwin usage(void)
7364de8019SJohn Baldwin {
745fa29797SWarner Losh fprintf(stderr,
755fa29797SWarner Losh "usage: devctl attach device\n"
765fa29797SWarner Losh " devctl detach [-f] device\n"
775fa29797SWarner Losh " devctl disable [-f] device\n"
785fa29797SWarner Losh " devctl enable device\n"
795fa29797SWarner Losh " devctl suspend device\n"
805fa29797SWarner Losh " devctl resume device\n"
815fa29797SWarner Losh " devctl set driver [-f] device driver\n"
825fa29797SWarner Losh " devctl clear driver [-f] device\n"
835fa29797SWarner Losh " devctl rescan device\n"
845fa29797SWarner Losh " devctl delete [-f] device\n"
855fa29797SWarner Losh " devctl freeze\n"
86*f6feb11fSKonstantin Belousov " devctl thaw\n"
87*f6feb11fSKonstantin Belousov " devctl reset [-d] device\n"
88*f6feb11fSKonstantin Belousov );
8964de8019SJohn Baldwin exit(1);
9064de8019SJohn Baldwin }
9164de8019SJohn Baldwin
9264de8019SJohn Baldwin static int
devctl_table_handler(struct devctl_command ** start,struct devctl_command ** end,int ac,char ** av)9364de8019SJohn Baldwin devctl_table_handler(struct devctl_command **start,
9464de8019SJohn Baldwin struct devctl_command **end, int ac, char **av)
9564de8019SJohn Baldwin {
9664de8019SJohn Baldwin struct devctl_command **cmd;
9764de8019SJohn Baldwin
9864de8019SJohn Baldwin if (ac < 2) {
9964de8019SJohn Baldwin warnx("The %s command requires a sub-command.", av[0]);
10064de8019SJohn Baldwin return (EINVAL);
10164de8019SJohn Baldwin }
10264de8019SJohn Baldwin for (cmd = start; cmd < end; cmd++) {
10364de8019SJohn Baldwin if (strcmp((*cmd)->name, av[1]) == 0)
10464de8019SJohn Baldwin return ((*cmd)->handler(ac - 1, av + 1));
10564de8019SJohn Baldwin }
10664de8019SJohn Baldwin
10764de8019SJohn Baldwin warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
10864de8019SJohn Baldwin return (ENOENT);
10964de8019SJohn Baldwin }
11064de8019SJohn Baldwin
11164de8019SJohn Baldwin static int
help(int ac __unused,char ** av __unused)11264de8019SJohn Baldwin help(int ac __unused, char **av __unused)
11364de8019SJohn Baldwin {
11464de8019SJohn Baldwin
11564de8019SJohn Baldwin usage();
11664de8019SJohn Baldwin return (0);
11764de8019SJohn Baldwin }
11864de8019SJohn Baldwin DEVCTL_COMMAND(top, help, help);
11964de8019SJohn Baldwin
12064de8019SJohn Baldwin static int
attach(int ac,char ** av)12164de8019SJohn Baldwin attach(int ac, char **av)
12264de8019SJohn Baldwin {
12364de8019SJohn Baldwin
12464de8019SJohn Baldwin if (ac != 2)
12564de8019SJohn Baldwin usage();
12664de8019SJohn Baldwin if (devctl_attach(av[1]) < 0)
12764de8019SJohn Baldwin err(1, "Failed to attach %s", av[1]);
12864de8019SJohn Baldwin return (0);
12964de8019SJohn Baldwin }
13064de8019SJohn Baldwin DEVCTL_COMMAND(top, attach, attach);
13164de8019SJohn Baldwin
13264de8019SJohn Baldwin static void
detach_usage(void)13364de8019SJohn Baldwin detach_usage(void)
13464de8019SJohn Baldwin {
13564de8019SJohn Baldwin
13664de8019SJohn Baldwin fprintf(stderr, "usage: devctl detach [-f] device\n");
13764de8019SJohn Baldwin exit(1);
13864de8019SJohn Baldwin }
13964de8019SJohn Baldwin
14064de8019SJohn Baldwin static int
detach(int ac,char ** av)14164de8019SJohn Baldwin detach(int ac, char **av)
14264de8019SJohn Baldwin {
14364de8019SJohn Baldwin bool force;
14464de8019SJohn Baldwin int ch;
14564de8019SJohn Baldwin
14664de8019SJohn Baldwin force = false;
14764de8019SJohn Baldwin while ((ch = getopt(ac, av, "f")) != -1)
14864de8019SJohn Baldwin switch (ch) {
14964de8019SJohn Baldwin case 'f':
15064de8019SJohn Baldwin force = true;
15164de8019SJohn Baldwin break;
15264de8019SJohn Baldwin default:
15364de8019SJohn Baldwin detach_usage();
15464de8019SJohn Baldwin }
15564de8019SJohn Baldwin ac -= optind;
15664de8019SJohn Baldwin av += optind;
15764de8019SJohn Baldwin
15864de8019SJohn Baldwin if (ac != 1)
15964de8019SJohn Baldwin detach_usage();
16064de8019SJohn Baldwin if (devctl_detach(av[0], force) < 0)
16164de8019SJohn Baldwin err(1, "Failed to detach %s", av[0]);
16264de8019SJohn Baldwin return (0);
16364de8019SJohn Baldwin }
16464de8019SJohn Baldwin DEVCTL_COMMAND(top, detach, detach);
16564de8019SJohn Baldwin
16664de8019SJohn Baldwin static void
disable_usage(void)16764de8019SJohn Baldwin disable_usage(void)
16864de8019SJohn Baldwin {
16964de8019SJohn Baldwin
17064de8019SJohn Baldwin fprintf(stderr, "usage: devctl disable [-f] device\n");
17164de8019SJohn Baldwin exit(1);
17264de8019SJohn Baldwin }
17364de8019SJohn Baldwin
17464de8019SJohn Baldwin static int
disable(int ac,char ** av)17564de8019SJohn Baldwin disable(int ac, char **av)
17664de8019SJohn Baldwin {
17764de8019SJohn Baldwin bool force;
17864de8019SJohn Baldwin int ch;
17964de8019SJohn Baldwin
18064de8019SJohn Baldwin force = false;
18164de8019SJohn Baldwin while ((ch = getopt(ac, av, "f")) != -1)
18264de8019SJohn Baldwin switch (ch) {
18364de8019SJohn Baldwin case 'f':
18464de8019SJohn Baldwin force = true;
18564de8019SJohn Baldwin break;
18664de8019SJohn Baldwin default:
18764de8019SJohn Baldwin disable_usage();
18864de8019SJohn Baldwin }
18964de8019SJohn Baldwin ac -= optind;
19064de8019SJohn Baldwin av += optind;
19164de8019SJohn Baldwin
19264de8019SJohn Baldwin if (ac != 1)
19364de8019SJohn Baldwin disable_usage();
19464de8019SJohn Baldwin if (devctl_disable(av[0], force) < 0)
19564de8019SJohn Baldwin err(1, "Failed to disable %s", av[0]);
19664de8019SJohn Baldwin return (0);
19764de8019SJohn Baldwin }
19864de8019SJohn Baldwin DEVCTL_COMMAND(top, disable, disable);
19964de8019SJohn Baldwin
20064de8019SJohn Baldwin static int
enable(int ac,char ** av)20164de8019SJohn Baldwin enable(int ac, char **av)
20264de8019SJohn Baldwin {
20364de8019SJohn Baldwin
20464de8019SJohn Baldwin if (ac != 2)
20564de8019SJohn Baldwin usage();
20664de8019SJohn Baldwin if (devctl_enable(av[1]) < 0)
20764de8019SJohn Baldwin err(1, "Failed to enable %s", av[1]);
20864de8019SJohn Baldwin return (0);
20964de8019SJohn Baldwin }
21064de8019SJohn Baldwin DEVCTL_COMMAND(top, enable, enable);
21164de8019SJohn Baldwin
21264de8019SJohn Baldwin static int
suspend(int ac,char ** av)21364de8019SJohn Baldwin suspend(int ac, char **av)
21464de8019SJohn Baldwin {
21564de8019SJohn Baldwin
21664de8019SJohn Baldwin if (ac != 2)
21764de8019SJohn Baldwin usage();
21864de8019SJohn Baldwin if (devctl_suspend(av[1]) < 0)
21964de8019SJohn Baldwin err(1, "Failed to suspend %s", av[1]);
22064de8019SJohn Baldwin return (0);
22164de8019SJohn Baldwin }
22264de8019SJohn Baldwin DEVCTL_COMMAND(top, suspend, suspend);
22364de8019SJohn Baldwin
22464de8019SJohn Baldwin static int
resume(int ac,char ** av)22564de8019SJohn Baldwin resume(int ac, char **av)
22664de8019SJohn Baldwin {
22764de8019SJohn Baldwin
22864de8019SJohn Baldwin if (ac != 2)
22964de8019SJohn Baldwin usage();
23064de8019SJohn Baldwin if (devctl_resume(av[1]) < 0)
23164de8019SJohn Baldwin err(1, "Failed to resume %s", av[1]);
23264de8019SJohn Baldwin return (0);
23364de8019SJohn Baldwin }
23464de8019SJohn Baldwin DEVCTL_COMMAND(top, resume, resume);
23564de8019SJohn Baldwin
23664de8019SJohn Baldwin static void
set_driver_usage(void)23764de8019SJohn Baldwin set_driver_usage(void)
23864de8019SJohn Baldwin {
23964de8019SJohn Baldwin
24064de8019SJohn Baldwin fprintf(stderr, "usage: devctl set driver [-f] device driver\n");
24164de8019SJohn Baldwin exit(1);
24264de8019SJohn Baldwin }
24364de8019SJohn Baldwin
24464de8019SJohn Baldwin static int
set_driver(int ac,char ** av)24564de8019SJohn Baldwin set_driver(int ac, char **av)
24664de8019SJohn Baldwin {
24764de8019SJohn Baldwin bool force;
24864de8019SJohn Baldwin int ch;
24964de8019SJohn Baldwin
25064de8019SJohn Baldwin force = false;
25164de8019SJohn Baldwin while ((ch = getopt(ac, av, "f")) != -1)
25264de8019SJohn Baldwin switch (ch) {
25364de8019SJohn Baldwin case 'f':
25464de8019SJohn Baldwin force = true;
25564de8019SJohn Baldwin break;
25664de8019SJohn Baldwin default:
25764de8019SJohn Baldwin set_driver_usage();
25864de8019SJohn Baldwin }
25964de8019SJohn Baldwin ac -= optind;
26064de8019SJohn Baldwin av += optind;
26164de8019SJohn Baldwin
26264de8019SJohn Baldwin if (ac != 2)
26364de8019SJohn Baldwin set_driver_usage();
26464de8019SJohn Baldwin if (devctl_set_driver(av[0], av[1], force) < 0)
26564de8019SJohn Baldwin err(1, "Failed to set %s driver to %s", av[0], av[1]);
26664de8019SJohn Baldwin return (0);
26764de8019SJohn Baldwin }
26864de8019SJohn Baldwin DEVCTL_COMMAND(set, driver, set_driver);
26964de8019SJohn Baldwin
270e05ec081SJohn Baldwin static void
clear_driver_usage(void)271e05ec081SJohn Baldwin clear_driver_usage(void)
272e05ec081SJohn Baldwin {
273e05ec081SJohn Baldwin
274e05ec081SJohn Baldwin fprintf(stderr, "usage: devctl clear driver [-f] device\n");
275e05ec081SJohn Baldwin exit(1);
276e05ec081SJohn Baldwin }
277e05ec081SJohn Baldwin
278e05ec081SJohn Baldwin static int
clear_driver(int ac,char ** av)279e05ec081SJohn Baldwin clear_driver(int ac, char **av)
280e05ec081SJohn Baldwin {
281e05ec081SJohn Baldwin bool force;
282e05ec081SJohn Baldwin int ch;
283e05ec081SJohn Baldwin
284e05ec081SJohn Baldwin force = false;
285e05ec081SJohn Baldwin while ((ch = getopt(ac, av, "f")) != -1)
286e05ec081SJohn Baldwin switch (ch) {
287e05ec081SJohn Baldwin case 'f':
288e05ec081SJohn Baldwin force = true;
289e05ec081SJohn Baldwin break;
290e05ec081SJohn Baldwin default:
291e05ec081SJohn Baldwin clear_driver_usage();
292e05ec081SJohn Baldwin }
293e05ec081SJohn Baldwin ac -= optind;
294e05ec081SJohn Baldwin av += optind;
295e05ec081SJohn Baldwin
296e05ec081SJohn Baldwin if (ac != 1)
297e05ec081SJohn Baldwin clear_driver_usage();
298e05ec081SJohn Baldwin if (devctl_clear_driver(av[0], force) < 0)
299e05ec081SJohn Baldwin err(1, "Failed to clear %s driver", av[0]);
300e05ec081SJohn Baldwin return (0);
301e05ec081SJohn Baldwin }
302e05ec081SJohn Baldwin DEVCTL_COMMAND(clear, driver, clear_driver);
303e05ec081SJohn Baldwin
304a907c691SJohn Baldwin static int
rescan(int ac,char ** av)305a907c691SJohn Baldwin rescan(int ac, char **av)
306a907c691SJohn Baldwin {
307a907c691SJohn Baldwin
308a907c691SJohn Baldwin if (ac != 2)
309a907c691SJohn Baldwin usage();
310a907c691SJohn Baldwin if (devctl_rescan(av[1]) < 0)
311a907c691SJohn Baldwin err(1, "Failed to rescan %s", av[1]);
312a907c691SJohn Baldwin return (0);
313a907c691SJohn Baldwin }
314a907c691SJohn Baldwin DEVCTL_COMMAND(top, rescan, rescan);
315a907c691SJohn Baldwin
31688eb5c50SJohn Baldwin static void
delete_usage(void)31788eb5c50SJohn Baldwin delete_usage(void)
31888eb5c50SJohn Baldwin {
31988eb5c50SJohn Baldwin
32088eb5c50SJohn Baldwin fprintf(stderr, "usage: devctl delete [-f] device\n");
32188eb5c50SJohn Baldwin exit(1);
32288eb5c50SJohn Baldwin }
32388eb5c50SJohn Baldwin
32488eb5c50SJohn Baldwin static int
delete(int ac,char ** av)32588eb5c50SJohn Baldwin delete(int ac, char **av)
32688eb5c50SJohn Baldwin {
32788eb5c50SJohn Baldwin bool force;
32888eb5c50SJohn Baldwin int ch;
32988eb5c50SJohn Baldwin
33088eb5c50SJohn Baldwin force = false;
33188eb5c50SJohn Baldwin while ((ch = getopt(ac, av, "f")) != -1)
33288eb5c50SJohn Baldwin switch (ch) {
33388eb5c50SJohn Baldwin case 'f':
33488eb5c50SJohn Baldwin force = true;
33588eb5c50SJohn Baldwin break;
33688eb5c50SJohn Baldwin default:
33788eb5c50SJohn Baldwin delete_usage();
33888eb5c50SJohn Baldwin }
33988eb5c50SJohn Baldwin ac -= optind;
34088eb5c50SJohn Baldwin av += optind;
34188eb5c50SJohn Baldwin
34288eb5c50SJohn Baldwin if (ac != 1)
34388eb5c50SJohn Baldwin delete_usage();
34488eb5c50SJohn Baldwin if (devctl_delete(av[0], force) < 0)
34588eb5c50SJohn Baldwin err(1, "Failed to delete %s", av[0]);
34688eb5c50SJohn Baldwin return (0);
34788eb5c50SJohn Baldwin }
34888eb5c50SJohn Baldwin DEVCTL_COMMAND(top, delete, delete);
34988eb5c50SJohn Baldwin
3505fa29797SWarner Losh static void
freeze_usage(void)3515fa29797SWarner Losh freeze_usage(void)
3525fa29797SWarner Losh {
3535fa29797SWarner Losh
3545fa29797SWarner Losh fprintf(stderr, "usage: devctl freeze\n");
3555fa29797SWarner Losh exit(1);
3565fa29797SWarner Losh }
3575fa29797SWarner Losh
3585fa29797SWarner Losh static int
freeze(int ac,char ** av __unused)3595fa29797SWarner Losh freeze(int ac, char **av __unused)
3605fa29797SWarner Losh {
3615fa29797SWarner Losh
3625fa29797SWarner Losh if (ac != 1)
3635fa29797SWarner Losh freeze_usage();
3645fa29797SWarner Losh if (devctl_freeze() < 0)
3655fa29797SWarner Losh err(1, "Failed to freeze probe/attach");
3665fa29797SWarner Losh return (0);
3675fa29797SWarner Losh }
3685fa29797SWarner Losh DEVCTL_COMMAND(top, freeze, freeze);
3695fa29797SWarner Losh
3705fa29797SWarner Losh static void
thaw_usage(void)3715fa29797SWarner Losh thaw_usage(void)
3725fa29797SWarner Losh {
3735fa29797SWarner Losh
3745fa29797SWarner Losh fprintf(stderr, "usage: devctl thaw\n");
3755fa29797SWarner Losh exit(1);
3765fa29797SWarner Losh }
3775fa29797SWarner Losh
3785fa29797SWarner Losh static int
thaw(int ac,char ** av __unused)3795fa29797SWarner Losh thaw(int ac, char **av __unused)
3805fa29797SWarner Losh {
3815fa29797SWarner Losh
3825fa29797SWarner Losh if (ac != 1)
3835fa29797SWarner Losh thaw_usage();
3845fa29797SWarner Losh if (devctl_thaw() < 0)
3855fa29797SWarner Losh err(1, "Failed to thaw probe/attach");
3865fa29797SWarner Losh return (0);
3875fa29797SWarner Losh }
3885fa29797SWarner Losh DEVCTL_COMMAND(top, thaw, thaw);
3895fa29797SWarner Losh
390*f6feb11fSKonstantin Belousov static void
reset_usage(void)391*f6feb11fSKonstantin Belousov reset_usage(void)
392*f6feb11fSKonstantin Belousov {
393*f6feb11fSKonstantin Belousov
394*f6feb11fSKonstantin Belousov fprintf(stderr, "usage: devctl reset [-d] device\n");
395*f6feb11fSKonstantin Belousov exit(1);
396*f6feb11fSKonstantin Belousov }
397*f6feb11fSKonstantin Belousov
398*f6feb11fSKonstantin Belousov static int
reset(int ac,char ** av)399*f6feb11fSKonstantin Belousov reset(int ac, char **av)
400*f6feb11fSKonstantin Belousov {
401*f6feb11fSKonstantin Belousov bool detach_drv;
402*f6feb11fSKonstantin Belousov int ch;
403*f6feb11fSKonstantin Belousov
404*f6feb11fSKonstantin Belousov detach_drv = false;
405*f6feb11fSKonstantin Belousov while ((ch = getopt(ac, av, "d")) != -1)
406*f6feb11fSKonstantin Belousov switch (ch) {
407*f6feb11fSKonstantin Belousov case 'd':
408*f6feb11fSKonstantin Belousov detach_drv = true;
409*f6feb11fSKonstantin Belousov break;
410*f6feb11fSKonstantin Belousov default:
411*f6feb11fSKonstantin Belousov reset_usage();
412*f6feb11fSKonstantin Belousov }
413*f6feb11fSKonstantin Belousov ac -= optind;
414*f6feb11fSKonstantin Belousov av += optind;
415*f6feb11fSKonstantin Belousov
416*f6feb11fSKonstantin Belousov if (ac != 1)
417*f6feb11fSKonstantin Belousov reset_usage();
418*f6feb11fSKonstantin Belousov if (devctl_reset(av[0], detach_drv) < 0)
419*f6feb11fSKonstantin Belousov err(1, "Failed to reset %s", av[0]);
420*f6feb11fSKonstantin Belousov return (0);
421*f6feb11fSKonstantin Belousov }
422*f6feb11fSKonstantin Belousov DEVCTL_COMMAND(top, reset, reset);
423*f6feb11fSKonstantin Belousov
42464de8019SJohn Baldwin int
main(int ac,char * av[])42564de8019SJohn Baldwin main(int ac, char *av[])
42664de8019SJohn Baldwin {
42764de8019SJohn Baldwin struct devctl_command **cmd;
42864de8019SJohn Baldwin
42964de8019SJohn Baldwin if (ac == 1)
43064de8019SJohn Baldwin usage();
43164de8019SJohn Baldwin ac--;
43264de8019SJohn Baldwin av++;
43364de8019SJohn Baldwin
43464de8019SJohn Baldwin SET_FOREACH(cmd, DEVCTL_DATASET(top)) {
43564de8019SJohn Baldwin if (strcmp((*cmd)->name, av[0]) == 0) {
43664de8019SJohn Baldwin if ((*cmd)->handler(ac, av) != 0)
43764de8019SJohn Baldwin return (1);
43864de8019SJohn Baldwin else
43964de8019SJohn Baldwin return (0);
44064de8019SJohn Baldwin }
44164de8019SJohn Baldwin }
44264de8019SJohn Baldwin warnx("Unknown command %s.", av[0]);
44364de8019SJohn Baldwin return (1);
44464de8019SJohn Baldwin }
445