1 /*-
2 * Copyright (c) 2014 John Baldwin <[email protected]>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/types.h>
31 #include <sys/bus.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <string.h>
35 #include "devctl.h"
36
37 static int
devctl_request(u_long cmd,struct devreq * req)38 devctl_request(u_long cmd, struct devreq *req)
39 {
40 static int devctl2_fd = -1;
41
42 if (devctl2_fd == -1) {
43 devctl2_fd = open("/dev/devctl2", O_RDONLY);
44 if (devctl2_fd == -1)
45 return (-1);
46 }
47 return (ioctl(devctl2_fd, cmd, req));
48 }
49
50 static int
devctl_simple_request(u_long cmd,const char * name,int flags)51 devctl_simple_request(u_long cmd, const char *name, int flags)
52 {
53 struct devreq req;
54
55 memset(&req, 0, sizeof(req));
56 if (strlcpy(req.dr_name, name, sizeof(req.dr_name)) >=
57 sizeof(req.dr_name)) {
58 errno = EINVAL;
59 return (-1);
60 }
61 req.dr_flags = flags;
62 return (devctl_request(cmd, &req));
63 }
64
65 int
devctl_attach(const char * device)66 devctl_attach(const char *device)
67 {
68
69 return (devctl_simple_request(DEV_ATTACH, device, 0));
70 }
71
72 int
devctl_detach(const char * device,bool force)73 devctl_detach(const char *device, bool force)
74 {
75
76 return (devctl_simple_request(DEV_DETACH, device, force ?
77 DEVF_FORCE_DETACH : 0));
78 }
79
80 int
devctl_enable(const char * device)81 devctl_enable(const char *device)
82 {
83
84 return (devctl_simple_request(DEV_ENABLE, device, 0));
85 }
86
87 int
devctl_disable(const char * device,bool force_detach)88 devctl_disable(const char *device, bool force_detach)
89 {
90
91 return (devctl_simple_request(DEV_DISABLE, device, force_detach ?
92 DEVF_FORCE_DETACH : 0));
93 }
94
95 int
devctl_suspend(const char * device)96 devctl_suspend(const char *device)
97 {
98
99 return (devctl_simple_request(DEV_SUSPEND, device, 0));
100 }
101
102 int
devctl_resume(const char * device)103 devctl_resume(const char *device)
104 {
105
106 return (devctl_simple_request(DEV_RESUME, device, 0));
107 }
108
109 int
devctl_set_driver(const char * device,const char * driver,bool force)110 devctl_set_driver(const char *device, const char *driver, bool force)
111 {
112 struct devreq req;
113
114 memset(&req, 0, sizeof(req));
115 if (strlcpy(req.dr_name, device, sizeof(req.dr_name)) >=
116 sizeof(req.dr_name)) {
117 errno = EINVAL;
118 return (-1);
119 }
120 req.dr_data = __DECONST(char *, driver);
121 if (force)
122 req.dr_flags |= DEVF_SET_DRIVER_DETACH;
123 return (devctl_request(DEV_SET_DRIVER, &req));
124 }
125
126 int
devctl_clear_driver(const char * device,bool force)127 devctl_clear_driver(const char *device, bool force)
128 {
129
130 return (devctl_simple_request(DEV_CLEAR_DRIVER, device, force ?
131 DEVF_CLEAR_DRIVER_DETACH : 0));
132 }
133
134 int
devctl_rescan(const char * device)135 devctl_rescan(const char *device)
136 {
137
138 return (devctl_simple_request(DEV_RESCAN, device, 0));
139 }
140
141 int
devctl_delete(const char * device,bool force)142 devctl_delete(const char *device, bool force)
143 {
144
145 return (devctl_simple_request(DEV_DELETE, device, force ?
146 DEVF_FORCE_DELETE : 0));
147 }
148
149 int
devctl_freeze(void)150 devctl_freeze(void)
151 {
152
153 return (devctl_simple_request(DEV_FREEZE, "", 0));
154 }
155
156 int
devctl_thaw(void)157 devctl_thaw(void)
158 {
159
160 return (devctl_simple_request(DEV_THAW, "", 0));
161 }
162
163 int
devctl_reset(const char * device,bool detach)164 devctl_reset(const char *device, bool detach)
165 {
166
167 return (devctl_simple_request(DEV_RESET, device, detach ?
168 DEVF_RESET_DETACH : 0));
169 }
170