]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/devctl/devctl.c
Add LLVM openmp trunk r351319 (just before the release_80 branch point)
[FreeBSD/FreeBSD.git] / usr.sbin / devctl / devctl.c
1 /*-
2  * Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include <sys/linker_set.h>
30 #include <devctl.h>
31 #include <err.h>
32 #include <errno.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <strings.h>
37 #include <unistd.h>
38
39 struct devctl_command {
40         const char *name;
41         int (*handler)(int ac, char **av);
42 };
43
44 #define DEVCTL_DATASET(name)    devctl_ ## name ## _table
45
46 #define DEVCTL_COMMAND(set, name, function)                             \
47         static struct devctl_command function ## _devctl_command =      \
48         { #name, function };                                            \
49         DATA_SET(DEVCTL_DATASET(set), function ## _devctl_command)
50
51 #define DEVCTL_TABLE(set, name)                                         \
52         SET_DECLARE(DEVCTL_DATASET(name), struct devctl_command);       \
53                                                                         \
54         static int                                                      \
55         devctl_ ## name ## _table_handler(int ac, char **av)            \
56         {                                                               \
57                 return (devctl_table_handler(SET_BEGIN(DEVCTL_DATASET(name)), \
58                     SET_LIMIT(DEVCTL_DATASET(name)), ac, av));          \
59         }                                                               \
60         DEVCTL_COMMAND(set, name, devctl_ ## name ## _table_handler)
61
62 static int      devctl_table_handler(struct devctl_command **start,
63     struct devctl_command **end, int ac, char **av);
64
65 SET_DECLARE(DEVCTL_DATASET(top), struct devctl_command);
66
67 DEVCTL_TABLE(top, clear);
68 DEVCTL_TABLE(top, set);
69
70 static void
71 usage(void)
72 {
73         fprintf(stderr,
74             "usage: devctl attach device\n"
75             "       devctl detach [-f] device\n"
76             "       devctl disable [-f] device\n"
77             "       devctl enable device\n"
78             "       devctl suspend device\n"
79             "       devctl resume device\n"
80             "       devctl set driver [-f] device driver\n"
81             "       devctl clear driver [-f] device\n"
82             "       devctl rescan device\n"
83             "       devctl delete [-f] device\n"
84             "       devctl freeze\n"
85             "       devctl thaw\n");
86         exit(1);
87 }
88
89 static int
90 devctl_table_handler(struct devctl_command **start,
91     struct devctl_command **end, int ac, char **av)
92 {
93         struct devctl_command **cmd;
94
95         if (ac < 2) {
96                 warnx("The %s command requires a sub-command.", av[0]);
97                 return (EINVAL);
98         }
99         for (cmd = start; cmd < end; cmd++) {
100                 if (strcmp((*cmd)->name, av[1]) == 0)
101                         return ((*cmd)->handler(ac - 1, av + 1));
102         }
103
104         warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
105         return (ENOENT);
106 }
107
108 static int
109 help(int ac __unused, char **av __unused)
110 {
111
112         usage();
113         return (0);
114 }
115 DEVCTL_COMMAND(top, help, help);
116
117 static int
118 attach(int ac, char **av)
119 {
120
121         if (ac != 2)
122                 usage();
123         if (devctl_attach(av[1]) < 0)
124                 err(1, "Failed to attach %s", av[1]);
125         return (0);
126 }
127 DEVCTL_COMMAND(top, attach, attach);
128
129 static void
130 detach_usage(void)
131 {
132
133         fprintf(stderr, "usage: devctl detach [-f] device\n");
134         exit(1);
135 }
136
137 static int
138 detach(int ac, char **av)
139 {
140         bool force;
141         int ch;
142
143         force = false;
144         while ((ch = getopt(ac, av, "f")) != -1)
145                 switch (ch) {
146                 case 'f':
147                         force = true;
148                         break;
149                 default:
150                         detach_usage();
151                 }
152         ac -= optind;
153         av += optind;
154
155         if (ac != 1)
156                 detach_usage();
157         if (devctl_detach(av[0], force) < 0)
158                 err(1, "Failed to detach %s", av[0]);
159         return (0);
160 }
161 DEVCTL_COMMAND(top, detach, detach);
162
163 static void
164 disable_usage(void)
165 {
166
167         fprintf(stderr, "usage: devctl disable [-f] device\n");
168         exit(1);
169 }
170
171 static int
172 disable(int ac, char **av)
173 {
174         bool force;
175         int ch;
176
177         force = false;
178         while ((ch = getopt(ac, av, "f")) != -1)
179                 switch (ch) {
180                 case 'f':
181                         force = true;
182                         break;
183                 default:
184                         disable_usage();
185                 }
186         ac -= optind;
187         av += optind;
188
189         if (ac != 1)
190                 disable_usage();
191         if (devctl_disable(av[0], force) < 0)
192                 err(1, "Failed to disable %s", av[0]);
193         return (0);
194 }
195 DEVCTL_COMMAND(top, disable, disable);
196
197 static int
198 enable(int ac, char **av)
199 {
200
201         if (ac != 2)
202                 usage();
203         if (devctl_enable(av[1]) < 0)
204                 err(1, "Failed to enable %s", av[1]);
205         return (0);
206 }
207 DEVCTL_COMMAND(top, enable, enable);
208
209 static int
210 suspend(int ac, char **av)
211 {
212
213         if (ac != 2)
214                 usage();
215         if (devctl_suspend(av[1]) < 0)
216                 err(1, "Failed to suspend %s", av[1]);
217         return (0);
218 }
219 DEVCTL_COMMAND(top, suspend, suspend);
220
221 static int
222 resume(int ac, char **av)
223 {
224
225         if (ac != 2)
226                 usage();
227         if (devctl_resume(av[1]) < 0)
228                 err(1, "Failed to resume %s", av[1]);
229         return (0);
230 }
231 DEVCTL_COMMAND(top, resume, resume);
232
233 static void
234 set_driver_usage(void)
235 {
236
237         fprintf(stderr, "usage: devctl set driver [-f] device driver\n");
238         exit(1);
239 }
240
241 static int
242 set_driver(int ac, char **av)
243 {
244         bool force;
245         int ch;
246
247         force = false;
248         while ((ch = getopt(ac, av, "f")) != -1)
249                 switch (ch) {
250                 case 'f':
251                         force = true;
252                         break;
253                 default:
254                         set_driver_usage();
255                 }
256         ac -= optind;
257         av += optind;
258
259         if (ac != 2)
260                 set_driver_usage();
261         if (devctl_set_driver(av[0], av[1], force) < 0)
262                 err(1, "Failed to set %s driver to %s", av[0], av[1]);
263         return (0);
264 }
265 DEVCTL_COMMAND(set, driver, set_driver);
266
267 static void
268 clear_driver_usage(void)
269 {
270
271         fprintf(stderr, "usage: devctl clear driver [-f] device\n");
272         exit(1);
273 }
274
275 static int
276 clear_driver(int ac, char **av)
277 {
278         bool force;
279         int ch;
280
281         force = false;
282         while ((ch = getopt(ac, av, "f")) != -1)
283                 switch (ch) {
284                 case 'f':
285                         force = true;
286                         break;
287                 default:
288                         clear_driver_usage();
289                 }
290         ac -= optind;
291         av += optind;
292
293         if (ac != 1)
294                 clear_driver_usage();
295         if (devctl_clear_driver(av[0], force) < 0)
296                 err(1, "Failed to clear %s driver", av[0]);
297         return (0);
298 }
299 DEVCTL_COMMAND(clear, driver, clear_driver);
300
301 static int
302 rescan(int ac, char **av)
303 {
304
305         if (ac != 2)
306                 usage();
307         if (devctl_rescan(av[1]) < 0)
308                 err(1, "Failed to rescan %s", av[1]);
309         return (0);
310 }
311 DEVCTL_COMMAND(top, rescan, rescan);
312
313 static void
314 delete_usage(void)
315 {
316
317         fprintf(stderr, "usage: devctl delete [-f] device\n");
318         exit(1);
319 }
320
321 static int
322 delete(int ac, char **av)
323 {
324         bool force;
325         int ch;
326
327         force = false;
328         while ((ch = getopt(ac, av, "f")) != -1)
329                 switch (ch) {
330                 case 'f':
331                         force = true;
332                         break;
333                 default:
334                         delete_usage();
335                 }
336         ac -= optind;
337         av += optind;
338
339         if (ac != 1)
340                 delete_usage();
341         if (devctl_delete(av[0], force) < 0)
342                 err(1, "Failed to delete %s", av[0]);
343         return (0);
344 }
345 DEVCTL_COMMAND(top, delete, delete);
346
347 static void
348 freeze_usage(void)
349 {
350
351         fprintf(stderr, "usage: devctl freeze\n");
352         exit(1);
353 }
354
355 static int
356 freeze(int ac, char **av __unused)
357 {
358
359         if (ac != 1)
360                 freeze_usage();
361         if (devctl_freeze() < 0)
362                 err(1, "Failed to freeze probe/attach");
363         return (0);
364 }
365 DEVCTL_COMMAND(top, freeze, freeze);
366
367 static void
368 thaw_usage(void)
369 {
370
371         fprintf(stderr, "usage: devctl thaw\n");
372         exit(1);
373 }
374
375 static int
376 thaw(int ac, char **av __unused)
377 {
378
379         if (ac != 1)
380                 thaw_usage();
381         if (devctl_thaw() < 0)
382                 err(1, "Failed to thaw probe/attach");
383         return (0);
384 }
385 DEVCTL_COMMAND(top, thaw, thaw);
386
387 int
388 main(int ac, char *av[])
389 {
390         struct devctl_command **cmd;
391
392         if (ac == 1)
393                 usage();
394         ac--;
395         av++;
396
397         SET_FOREACH(cmd, DEVCTL_DATASET(top)) {
398                 if (strcmp((*cmd)->name, av[0]) == 0) {
399                         if ((*cmd)->handler(ac, av) != 0)
400                                 return (1);
401                         else
402                                 return (0);
403                 }
404         }
405         warnx("Unknown command %s.", av[0]);
406         return (1);
407 }