subr_devsw.c revision 1.10.8.1 1 1.10.8.1 ad /* $NetBSD: subr_devsw.c,v 1.10.8.1 2007/04/13 20:56:18 ad Exp $ */
2 1.10.8.1 ad
3 1.2 gehenna /*-
4 1.10.8.1 ad * Copyright (c) 2001, 2002, 2007 The NetBSD Foundation, Inc.
5 1.2 gehenna * All rights reserved.
6 1.2 gehenna *
7 1.2 gehenna * This code is derived from software contributed to The NetBSD Foundation
8 1.10.8.1 ad * by MAEKAWA Masahide <gehenna (at) NetBSD.org>, and by Andrew Doran.
9 1.2 gehenna *
10 1.2 gehenna * Redistribution and use in source and binary forms, with or without
11 1.2 gehenna * modification, are permitted provided that the following conditions
12 1.2 gehenna * are met:
13 1.2 gehenna * 1. Redistributions of source code must retain the above copyright
14 1.2 gehenna * notice, this list of conditions and the following disclaimer.
15 1.2 gehenna * 2. Redistributions in binary form must reproduce the above copyright
16 1.2 gehenna * notice, this list of conditions and the following disclaimer in the
17 1.2 gehenna * documentation and/or other materials provided with the distribution.
18 1.2 gehenna * 3. All advertising materials mentioning features or use of this software
19 1.2 gehenna * must display the following acknowledgement:
20 1.2 gehenna * This product includes software developed by the NetBSD
21 1.2 gehenna * Foundation, Inc. and its contributors.
22 1.2 gehenna * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.2 gehenna * contributors may be used to endorse or promote products derived
24 1.2 gehenna * from this software without specific prior written permission.
25 1.2 gehenna *
26 1.2 gehenna * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.2 gehenna * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.2 gehenna * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.2 gehenna * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.2 gehenna * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.2 gehenna * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.2 gehenna * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.2 gehenna * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.2 gehenna * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.2 gehenna * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.2 gehenna * POSSIBILITY OF SUCH DAMAGE.
37 1.2 gehenna */
38 1.7 lukem
39 1.2 gehenna /*
40 1.10.8.1 ad * Overview
41 1.10.8.1 ad *
42 1.10.8.1 ad * subr_devsw.c: registers device drivers by name and by major
43 1.10.8.1 ad * number, and provides wrapper methods for performing I/O and
44 1.10.8.1 ad * other tasks on device drivers, keying on the device number
45 1.10.8.1 ad * (dev_t).
46 1.10.8.1 ad *
47 1.10.8.1 ad * When the system is built, the config(8) command generates
48 1.10.8.1 ad * static tables of device drivers built into the kernel image
49 1.10.8.1 ad * along with their associated methods. These are recorded in
50 1.10.8.1 ad * the cdevsw0 and bdevsw0 tables. Drivers can also be added to
51 1.10.8.1 ad * and removed from the system dynamically.
52 1.10.8.1 ad *
53 1.10.8.1 ad * Allocation
54 1.10.8.1 ad *
55 1.10.8.1 ad * When the system initially, only the statically allocated
56 1.10.8.1 ad * indexes (bdevsw0, cdevsw0) are used. If these overflow due
57 1.10.8.1 ad * to allocation, we allocate a fixed block of memory to hold
58 1.10.8.1 ad * the new, expanded index. This "fork" of the table is only
59 1.10.8.1 ad * ever performed once in order to guarantee that other threads
60 1.10.8.1 ad * may safely access the device tables:
61 1.10.8.1 ad *
62 1.10.8.1 ad * o Once a thread has a "reference" to the table via an earlier
63 1.10.8.1 ad * open() call, we know that the entry in the table must exist
64 1.10.8.1 ad * and so it is safe to access it.
65 1.10.8.1 ad *
66 1.10.8.1 ad * o Regardless of whether other threads see the old or new
67 1.10.8.1 ad * pointers, they will point to a correct device switch
68 1.10.8.1 ad * structure for the operation being performed.
69 1.10.8.1 ad *
70 1.10.8.1 ad * XXX Currently, the wrapper methods such as cdev_read() verify
71 1.10.8.1 ad * that a device driver does in fact exist before calling the
72 1.10.8.1 ad * associated driver method. This should be changed so that
73 1.10.8.1 ad * once the device is has been referenced (i.e. opened), calling
74 1.10.8.1 ad * the other methods should be valid until that reference is
75 1.10.8.1 ad * dropped.
76 1.2 gehenna */
77 1.10.8.1 ad
78 1.10.8.1 ad #include <sys/cdefs.h>
79 1.10.8.1 ad __KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.10.8.1 2007/04/13 20:56:18 ad Exp $");
80 1.10.8.1 ad
81 1.10.8.1 ad #include "opt_multiprocessor.h"
82 1.2 gehenna
83 1.2 gehenna #include <sys/param.h>
84 1.2 gehenna #include <sys/conf.h>
85 1.10.8.1 ad #include <sys/kmem.h>
86 1.2 gehenna #include <sys/systm.h>
87 1.10.8.1 ad #include <sys/proc.h>
88 1.10.8.1 ad #include <sys/buf.h>
89 1.10.8.1 ad #include <sys/tty.h>
90 1.10.8.1 ad #include <sys/poll.h>
91 1.2 gehenna
92 1.10.8.1 ad #define MAXDEVSW 512 /* the maximum major device number */
93 1.2 gehenna #define BDEVSW_SIZE (sizeof(struct bdevsw *))
94 1.2 gehenna #define CDEVSW_SIZE (sizeof(struct cdevsw *))
95 1.2 gehenna #define DEVSWCONV_SIZE (sizeof(struct devsw_conv))
96 1.2 gehenna
97 1.2 gehenna extern const struct bdevsw **bdevsw, *bdevsw0[];
98 1.2 gehenna extern const struct cdevsw **cdevsw, *cdevsw0[];
99 1.2 gehenna extern struct devsw_conv *devsw_conv, devsw_conv0[];
100 1.2 gehenna extern const int sys_bdevsws, sys_cdevsws;
101 1.2 gehenna extern int max_bdevsws, max_cdevsws, max_devsw_convs;
102 1.2 gehenna
103 1.2 gehenna static int bdevsw_attach(const char *, const struct bdevsw *, int *);
104 1.2 gehenna static int cdevsw_attach(const char *, const struct cdevsw *, int *);
105 1.10.8.1 ad static void devsw_detach_locked(const struct bdevsw *, const struct cdevsw *);
106 1.10.8.1 ad
107 1.10.8.1 ad static kmutex_t devsw_lock;
108 1.10.8.1 ad
109 1.10.8.1 ad void
110 1.10.8.1 ad devsw_init(void)
111 1.10.8.1 ad {
112 1.10.8.1 ad
113 1.10.8.1 ad KASSERT(sys_bdevsws < MAXDEVSW - 1);
114 1.10.8.1 ad KASSERT(sys_cdevsws < MAXDEVSW - 1);
115 1.10.8.1 ad
116 1.10.8.1 ad mutex_init(&devsw_lock, MUTEX_DEFAULT, IPL_NONE);
117 1.10.8.1 ad }
118 1.2 gehenna
119 1.2 gehenna int
120 1.2 gehenna devsw_attach(const char *devname, const struct bdevsw *bdev, int *bmajor,
121 1.2 gehenna const struct cdevsw *cdev, int *cmajor)
122 1.2 gehenna {
123 1.2 gehenna struct devsw_conv *conv;
124 1.2 gehenna char *name;
125 1.2 gehenna int error, i;
126 1.2 gehenna
127 1.2 gehenna if (devname == NULL || cdev == NULL)
128 1.2 gehenna return (EINVAL);
129 1.2 gehenna
130 1.10.8.1 ad mutex_enter(&devsw_lock);
131 1.10.8.1 ad
132 1.2 gehenna for (i = 0 ; i < max_devsw_convs ; i++) {
133 1.2 gehenna conv = &devsw_conv[i];
134 1.2 gehenna if (conv->d_name == NULL || strcmp(devname, conv->d_name) != 0)
135 1.2 gehenna continue;
136 1.2 gehenna
137 1.2 gehenna if (*bmajor < 0)
138 1.2 gehenna *bmajor = conv->d_bmajor;
139 1.2 gehenna if (*cmajor < 0)
140 1.2 gehenna *cmajor = conv->d_cmajor;
141 1.2 gehenna
142 1.10.8.1 ad if (*bmajor != conv->d_bmajor || *cmajor != conv->d_cmajor) {
143 1.10.8.1 ad error = EINVAL;
144 1.10.8.1 ad goto fail;
145 1.10.8.1 ad }
146 1.10.8.1 ad if ((*bmajor >= 0 && bdev == NULL) || *cmajor < 0) {
147 1.10.8.1 ad error = EINVAL;
148 1.10.8.1 ad goto fail;
149 1.10.8.1 ad }
150 1.2 gehenna
151 1.2 gehenna if ((*bmajor >= 0 && bdevsw[*bmajor] != NULL) ||
152 1.10.8.1 ad cdevsw[*cmajor] != NULL) {
153 1.10.8.1 ad error = EEXIST;
154 1.10.8.1 ad goto fail;
155 1.10.8.1 ad }
156 1.2 gehenna
157 1.2 gehenna if (bdev != NULL)
158 1.2 gehenna bdevsw[*bmajor] = bdev;
159 1.2 gehenna cdevsw[*cmajor] = cdev;
160 1.2 gehenna
161 1.10.8.1 ad mutex_exit(&devsw_lock);
162 1.2 gehenna return (0);
163 1.2 gehenna }
164 1.2 gehenna
165 1.2 gehenna error = bdevsw_attach(devname, bdev, bmajor);
166 1.10.8.1 ad if (error != 0)
167 1.10.8.1 ad goto fail;
168 1.2 gehenna error = cdevsw_attach(devname, cdev, cmajor);
169 1.2 gehenna if (error != 0) {
170 1.10.8.1 ad devsw_detach_locked(bdev, NULL);
171 1.10.8.1 ad goto fail;
172 1.2 gehenna }
173 1.2 gehenna
174 1.2 gehenna for (i = 0 ; i < max_devsw_convs ; i++) {
175 1.2 gehenna if (devsw_conv[i].d_name == NULL)
176 1.2 gehenna break;
177 1.2 gehenna }
178 1.2 gehenna if (i == max_devsw_convs) {
179 1.2 gehenna struct devsw_conv *newptr;
180 1.2 gehenna int old, new;
181 1.2 gehenna
182 1.2 gehenna old = max_devsw_convs;
183 1.2 gehenna new = old + 1;
184 1.2 gehenna
185 1.10.8.1 ad newptr = kmem_zalloc(new * DEVSWCONV_SIZE, KM_NOSLEEP);
186 1.2 gehenna if (newptr == NULL) {
187 1.10.8.1 ad devsw_detach_locked(bdev, cdev);
188 1.10.8.1 ad error = ENOMEM;
189 1.10.8.1 ad goto fail;
190 1.2 gehenna }
191 1.2 gehenna newptr[old].d_name = NULL;
192 1.2 gehenna newptr[old].d_bmajor = -1;
193 1.2 gehenna newptr[old].d_cmajor = -1;
194 1.2 gehenna memcpy(newptr, devsw_conv, old * DEVSWCONV_SIZE);
195 1.2 gehenna if (devsw_conv != devsw_conv0)
196 1.10.8.1 ad kmem_free(devsw_conv, old * DEVSWCONV_SIZE);
197 1.2 gehenna devsw_conv = newptr;
198 1.2 gehenna max_devsw_convs = new;
199 1.2 gehenna }
200 1.2 gehenna
201 1.6 itojun i = strlen(devname) + 1;
202 1.10.8.1 ad name = kmem_alloc(i, KM_NOSLEEP);
203 1.2 gehenna if (name == NULL) {
204 1.10.8.1 ad devsw_detach_locked(bdev, cdev);
205 1.10.8.1 ad goto fail;
206 1.2 gehenna }
207 1.6 itojun strlcpy(name, devname, i);
208 1.2 gehenna
209 1.2 gehenna devsw_conv[i].d_name = name;
210 1.2 gehenna devsw_conv[i].d_bmajor = *bmajor;
211 1.2 gehenna devsw_conv[i].d_cmajor = *cmajor;
212 1.2 gehenna
213 1.10.8.1 ad mutex_exit(&devsw_lock);
214 1.2 gehenna return (0);
215 1.10.8.1 ad fail:
216 1.10.8.1 ad mutex_exit(&devsw_lock);
217 1.10.8.1 ad return (error);
218 1.2 gehenna }
219 1.2 gehenna
220 1.2 gehenna static int
221 1.10 yamt bdevsw_attach(const char *devname, const struct bdevsw *devsw, int *devmajor)
222 1.2 gehenna {
223 1.10.8.1 ad const struct bdevsw **newptr;
224 1.2 gehenna int bmajor, i;
225 1.2 gehenna
226 1.10.8.1 ad KASSERT(mutex_owned(&devsw_lock));
227 1.10.8.1 ad
228 1.2 gehenna if (devsw == NULL)
229 1.2 gehenna return (0);
230 1.2 gehenna
231 1.2 gehenna if (*devmajor < 0) {
232 1.2 gehenna for (bmajor = sys_bdevsws ; bmajor < max_bdevsws ; bmajor++) {
233 1.2 gehenna if (bdevsw[bmajor] != NULL)
234 1.2 gehenna continue;
235 1.2 gehenna for (i = 0 ; i < max_devsw_convs ; i++) {
236 1.2 gehenna if (devsw_conv[i].d_bmajor == bmajor)
237 1.2 gehenna break;
238 1.2 gehenna }
239 1.2 gehenna if (i != max_devsw_convs)
240 1.2 gehenna continue;
241 1.2 gehenna break;
242 1.2 gehenna }
243 1.3 gehenna *devmajor = bmajor;
244 1.2 gehenna }
245 1.10.8.1 ad
246 1.2 gehenna if (*devmajor >= MAXDEVSW) {
247 1.10.8.1 ad printf("bdevsw_attach: block majors exhausted");
248 1.2 gehenna return (ENOMEM);
249 1.2 gehenna }
250 1.2 gehenna
251 1.2 gehenna if (*devmajor >= max_bdevsws) {
252 1.10.8.1 ad KASSERT(bdevsw == bdevsw0);
253 1.10.8.1 ad newptr = kmem_zalloc(MAXDEVSW * BDEVSW_SIZE, KM_NOSLEEP);
254 1.2 gehenna if (newptr == NULL)
255 1.2 gehenna return (ENOMEM);
256 1.10.8.1 ad memcpy(newptr, bdevsw, max_bdevsws * BDEVSW_SIZE);
257 1.2 gehenna bdevsw = newptr;
258 1.10.8.1 ad max_bdevsws = MAXDEVSW;
259 1.2 gehenna }
260 1.2 gehenna
261 1.2 gehenna if (bdevsw[*devmajor] != NULL)
262 1.2 gehenna return (EEXIST);
263 1.2 gehenna
264 1.2 gehenna bdevsw[*devmajor] = devsw;
265 1.2 gehenna
266 1.2 gehenna return (0);
267 1.2 gehenna }
268 1.2 gehenna
269 1.2 gehenna static int
270 1.10 yamt cdevsw_attach(const char *devname, const struct cdevsw *devsw, int *devmajor)
271 1.2 gehenna {
272 1.10.8.1 ad const struct cdevsw **newptr;
273 1.2 gehenna int cmajor, i;
274 1.2 gehenna
275 1.10.8.1 ad KASSERT(mutex_owned(&devsw_lock));
276 1.10.8.1 ad
277 1.2 gehenna if (*devmajor < 0) {
278 1.2 gehenna for (cmajor = sys_cdevsws ; cmajor < max_cdevsws ; cmajor++) {
279 1.2 gehenna if (cdevsw[cmajor] != NULL)
280 1.2 gehenna continue;
281 1.2 gehenna for (i = 0 ; i < max_devsw_convs ; i++) {
282 1.2 gehenna if (devsw_conv[i].d_cmajor == cmajor)
283 1.2 gehenna break;
284 1.2 gehenna }
285 1.2 gehenna if (i != max_devsw_convs)
286 1.2 gehenna continue;
287 1.2 gehenna break;
288 1.2 gehenna }
289 1.3 gehenna *devmajor = cmajor;
290 1.2 gehenna }
291 1.10.8.1 ad
292 1.2 gehenna if (*devmajor >= MAXDEVSW) {
293 1.10.8.1 ad printf("cdevsw_attach: character majors exhausted");
294 1.2 gehenna return (ENOMEM);
295 1.2 gehenna }
296 1.2 gehenna
297 1.2 gehenna if (*devmajor >= max_cdevsws) {
298 1.10.8.1 ad KASSERT(cdevsw == cdevsw0);
299 1.10.8.1 ad newptr = kmem_zalloc(MAXDEVSW * CDEVSW_SIZE, KM_NOSLEEP);
300 1.2 gehenna if (newptr == NULL)
301 1.2 gehenna return (ENOMEM);
302 1.10.8.1 ad memcpy(newptr, cdevsw, max_cdevsws * CDEVSW_SIZE);
303 1.2 gehenna cdevsw = newptr;
304 1.10.8.1 ad max_cdevsws = MAXDEVSW;
305 1.2 gehenna }
306 1.2 gehenna
307 1.2 gehenna if (cdevsw[*devmajor] != NULL)
308 1.2 gehenna return (EEXIST);
309 1.2 gehenna
310 1.2 gehenna cdevsw[*devmajor] = devsw;
311 1.2 gehenna
312 1.2 gehenna return (0);
313 1.2 gehenna }
314 1.2 gehenna
315 1.10.8.1 ad static void
316 1.10.8.1 ad devsw_detach_locked(const struct bdevsw *bdev, const struct cdevsw *cdev)
317 1.2 gehenna {
318 1.2 gehenna int i;
319 1.2 gehenna
320 1.10.8.1 ad KASSERT(mutex_owned(&devsw_lock));
321 1.10.8.1 ad
322 1.2 gehenna if (bdev != NULL) {
323 1.2 gehenna for (i = 0 ; i < max_bdevsws ; i++) {
324 1.2 gehenna if (bdevsw[i] != bdev)
325 1.2 gehenna continue;
326 1.2 gehenna bdevsw[i] = NULL;
327 1.2 gehenna break;
328 1.2 gehenna }
329 1.2 gehenna }
330 1.2 gehenna if (cdev != NULL) {
331 1.2 gehenna for (i = 0 ; i < max_cdevsws ; i++) {
332 1.2 gehenna if (cdevsw[i] != cdev)
333 1.2 gehenna continue;
334 1.2 gehenna cdevsw[i] = NULL;
335 1.2 gehenna break;
336 1.2 gehenna }
337 1.2 gehenna }
338 1.2 gehenna }
339 1.2 gehenna
340 1.10.8.1 ad void
341 1.10.8.1 ad devsw_detach(const struct bdevsw *bdev, const struct cdevsw *cdev)
342 1.10.8.1 ad {
343 1.10.8.1 ad
344 1.10.8.1 ad mutex_enter(&devsw_lock);
345 1.10.8.1 ad devsw_detach_locked(bdev, cdev);
346 1.10.8.1 ad mutex_exit(&devsw_lock);
347 1.10.8.1 ad }
348 1.10.8.1 ad
349 1.10.8.1 ad /*
350 1.10.8.1 ad * Look up a block device by number.
351 1.10.8.1 ad *
352 1.10.8.1 ad * => Caller must ensure that the device is attached.
353 1.10.8.1 ad */
354 1.2 gehenna const struct bdevsw *
355 1.2 gehenna bdevsw_lookup(dev_t dev)
356 1.2 gehenna {
357 1.2 gehenna int bmajor;
358 1.2 gehenna
359 1.2 gehenna if (dev == NODEV)
360 1.2 gehenna return (NULL);
361 1.2 gehenna bmajor = major(dev);
362 1.2 gehenna if (bmajor < 0 || bmajor >= max_bdevsws)
363 1.2 gehenna return (NULL);
364 1.2 gehenna
365 1.2 gehenna return (bdevsw[bmajor]);
366 1.2 gehenna }
367 1.2 gehenna
368 1.10.8.1 ad /*
369 1.10.8.1 ad * Look up a character device by number.
370 1.10.8.1 ad *
371 1.10.8.1 ad * => Caller must ensure that the device is attached.
372 1.10.8.1 ad */
373 1.2 gehenna const struct cdevsw *
374 1.2 gehenna cdevsw_lookup(dev_t dev)
375 1.2 gehenna {
376 1.2 gehenna int cmajor;
377 1.2 gehenna
378 1.2 gehenna if (dev == NODEV)
379 1.2 gehenna return (NULL);
380 1.2 gehenna cmajor = major(dev);
381 1.2 gehenna if (cmajor < 0 || cmajor >= max_cdevsws)
382 1.2 gehenna return (NULL);
383 1.2 gehenna
384 1.2 gehenna return (cdevsw[cmajor]);
385 1.2 gehenna }
386 1.2 gehenna
387 1.10.8.1 ad /*
388 1.10.8.1 ad * Look up a block device by reference to its operations set.
389 1.10.8.1 ad *
390 1.10.8.1 ad * => Caller must ensure that the device is not detached, and therefore
391 1.10.8.1 ad * that the returned major is still valid when dereferenced.
392 1.10.8.1 ad */
393 1.2 gehenna int
394 1.2 gehenna bdevsw_lookup_major(const struct bdevsw *bdev)
395 1.2 gehenna {
396 1.2 gehenna int bmajor;
397 1.2 gehenna
398 1.2 gehenna for (bmajor = 0 ; bmajor < max_bdevsws ; bmajor++) {
399 1.2 gehenna if (bdevsw[bmajor] == bdev)
400 1.2 gehenna return (bmajor);
401 1.2 gehenna }
402 1.2 gehenna
403 1.2 gehenna return (-1);
404 1.2 gehenna }
405 1.2 gehenna
406 1.10.8.1 ad /*
407 1.10.8.1 ad * Look up a character device by reference to its operations set.
408 1.10.8.1 ad *
409 1.10.8.1 ad * => Caller must ensure that the device is not detached, and therefore
410 1.10.8.1 ad * that the returned major is still valid when dereferenced.
411 1.10.8.1 ad */
412 1.2 gehenna int
413 1.2 gehenna cdevsw_lookup_major(const struct cdevsw *cdev)
414 1.2 gehenna {
415 1.2 gehenna int cmajor;
416 1.2 gehenna
417 1.2 gehenna for (cmajor = 0 ; cmajor < max_cdevsws ; cmajor++) {
418 1.2 gehenna if (cdevsw[cmajor] == cdev)
419 1.2 gehenna return (cmajor);
420 1.2 gehenna }
421 1.2 gehenna
422 1.2 gehenna return (-1);
423 1.2 gehenna }
424 1.2 gehenna
425 1.2 gehenna /*
426 1.2 gehenna * Convert from block major number to name.
427 1.10.8.1 ad *
428 1.10.8.1 ad * => Caller must ensure that the device is not detached, and therefore
429 1.10.8.1 ad * that the name pointer is still valid when dereferenced.
430 1.2 gehenna */
431 1.2 gehenna const char *
432 1.2 gehenna devsw_blk2name(int bmajor)
433 1.2 gehenna {
434 1.10.8.1 ad const char *name;
435 1.2 gehenna int cmajor, i;
436 1.2 gehenna
437 1.10.8.1 ad name = NULL;
438 1.10.8.1 ad cmajor = -1;
439 1.2 gehenna
440 1.10.8.1 ad mutex_enter(&devsw_lock);
441 1.10.8.1 ad if (bmajor < 0 || bmajor >= max_bdevsws || bdevsw[bmajor] == NULL) {
442 1.10.8.1 ad mutex_exit(&devsw_lock);
443 1.10.8.1 ad return (NULL);
444 1.2 gehenna }
445 1.10.8.1 ad for (i = 0 ; i < max_devsw_convs; i++) {
446 1.10.8.1 ad if (devsw_conv[i].d_bmajor == bmajor) {
447 1.10.8.1 ad cmajor = devsw_conv[i].d_cmajor;
448 1.10.8.1 ad break;
449 1.10.8.1 ad }
450 1.10.8.1 ad }
451 1.10.8.1 ad if (cmajor >= 0 && cmajor < max_cdevsws && cdevsw[cmajor] != NULL)
452 1.10.8.1 ad name = devsw_conv[i].d_name;
453 1.10.8.1 ad mutex_exit(&devsw_lock);
454 1.2 gehenna
455 1.10.8.1 ad return (name);
456 1.2 gehenna }
457 1.2 gehenna
458 1.2 gehenna /*
459 1.2 gehenna * Convert from device name to block major number.
460 1.10.8.1 ad *
461 1.10.8.1 ad * => Caller must ensure that the device is not detached, and therefore
462 1.10.8.1 ad * that the major number is still valid when dereferenced.
463 1.2 gehenna */
464 1.2 gehenna int
465 1.2 gehenna devsw_name2blk(const char *name, char *devname, size_t devnamelen)
466 1.2 gehenna {
467 1.2 gehenna struct devsw_conv *conv;
468 1.2 gehenna int bmajor, i;
469 1.2 gehenna
470 1.2 gehenna if (name == NULL)
471 1.2 gehenna return (-1);
472 1.2 gehenna
473 1.10.8.1 ad mutex_enter(&devsw_lock);
474 1.2 gehenna for (i = 0 ; i < max_devsw_convs ; i++) {
475 1.5 mrg size_t len;
476 1.5 mrg
477 1.2 gehenna conv = &devsw_conv[i];
478 1.2 gehenna if (conv->d_name == NULL)
479 1.2 gehenna continue;
480 1.5 mrg len = strlen(conv->d_name);
481 1.5 mrg if (strncmp(conv->d_name, name, len) != 0)
482 1.5 mrg continue;
483 1.5 mrg if (*(name +len) && !isdigit(*(name + len)))
484 1.2 gehenna continue;
485 1.2 gehenna bmajor = conv->d_bmajor;
486 1.2 gehenna if (bmajor < 0 || bmajor >= max_bdevsws ||
487 1.2 gehenna bdevsw[bmajor] == NULL)
488 1.5 mrg break;
489 1.2 gehenna if (devname != NULL) {
490 1.2 gehenna #ifdef DEVSW_DEBUG
491 1.2 gehenna if (strlen(conv->d_name) >= devnamelen)
492 1.2 gehenna printf("devsw_name2blk: too short buffer");
493 1.2 gehenna #endif /* DEVSW_DEBUG */
494 1.4 tsutsui strncpy(devname, conv->d_name, devnamelen);
495 1.2 gehenna devname[devnamelen - 1] = '\0';
496 1.2 gehenna }
497 1.10.8.1 ad mutex_exit(&devsw_lock);
498 1.2 gehenna return (bmajor);
499 1.2 gehenna }
500 1.2 gehenna
501 1.10.8.1 ad mutex_exit(&devsw_lock);
502 1.2 gehenna return (-1);
503 1.2 gehenna }
504 1.2 gehenna
505 1.2 gehenna /*
506 1.2 gehenna * Convert from character dev_t to block dev_t.
507 1.10.8.1 ad *
508 1.10.8.1 ad * => Caller must ensure that the device is not detached, and therefore
509 1.10.8.1 ad * that the major number is still valid when dereferenced.
510 1.2 gehenna */
511 1.2 gehenna dev_t
512 1.2 gehenna devsw_chr2blk(dev_t cdev)
513 1.2 gehenna {
514 1.2 gehenna int bmajor, cmajor, i;
515 1.10.8.1 ad dev_t rv;
516 1.2 gehenna
517 1.2 gehenna cmajor = major(cdev);
518 1.10.8.1 ad bmajor = -1;
519 1.10.8.1 ad rv = NODEV;
520 1.2 gehenna
521 1.10.8.1 ad mutex_enter(&devsw_lock);
522 1.10.8.1 ad if (cmajor < 0 || cmajor >= max_cdevsws || cdevsw[cmajor] == NULL) {
523 1.10.8.1 ad mutex_exit(&devsw_lock);
524 1.10.8.1 ad return (NODEV);
525 1.10.8.1 ad }
526 1.2 gehenna for (i = 0 ; i < max_devsw_convs ; i++) {
527 1.10.8.1 ad if (devsw_conv[i].d_cmajor == cmajor) {
528 1.10.8.1 ad bmajor = devsw_conv[i].d_bmajor;
529 1.10.8.1 ad break;
530 1.10.8.1 ad }
531 1.2 gehenna }
532 1.10.8.1 ad if (bmajor >= 0 && bmajor < max_bdevsws && bdevsw[bmajor] != NULL)
533 1.10.8.1 ad rv = makedev(bmajor, minor(cdev));
534 1.10.8.1 ad mutex_exit(&devsw_lock);
535 1.2 gehenna
536 1.10.8.1 ad return (rv);
537 1.2 gehenna }
538 1.2 gehenna
539 1.2 gehenna /*
540 1.2 gehenna * Convert from block dev_t to character dev_t.
541 1.10.8.1 ad *
542 1.10.8.1 ad * => Caller must ensure that the device is not detached, and therefore
543 1.10.8.1 ad * that the major number is still valid when dereferenced.
544 1.2 gehenna */
545 1.2 gehenna dev_t
546 1.2 gehenna devsw_blk2chr(dev_t bdev)
547 1.2 gehenna {
548 1.2 gehenna int bmajor, cmajor, i;
549 1.10.8.1 ad dev_t rv;
550 1.2 gehenna
551 1.2 gehenna bmajor = major(bdev);
552 1.10.8.1 ad cmajor = -1;
553 1.10.8.1 ad rv = NODEV;
554 1.2 gehenna
555 1.10.8.1 ad mutex_enter(&devsw_lock);
556 1.10.8.1 ad if (bmajor < 0 || bmajor >= max_bdevsws || bdevsw[bmajor] == NULL) {
557 1.10.8.1 ad mutex_exit(&devsw_lock);
558 1.10.8.1 ad return (NODEV);
559 1.10.8.1 ad }
560 1.2 gehenna for (i = 0 ; i < max_devsw_convs ; i++) {
561 1.10.8.1 ad if (devsw_conv[i].d_bmajor == bmajor) {
562 1.10.8.1 ad cmajor = devsw_conv[i].d_cmajor;
563 1.10.8.1 ad break;
564 1.10.8.1 ad }
565 1.2 gehenna }
566 1.10.8.1 ad if (cmajor >= 0 && cmajor < max_cdevsws && cdevsw[cmajor] != NULL)
567 1.10.8.1 ad rv = makedev(cmajor, minor(bdev));
568 1.10.8.1 ad mutex_exit(&devsw_lock);
569 1.10.8.1 ad
570 1.10.8.1 ad return (rv);
571 1.10.8.1 ad }
572 1.10.8.1 ad
573 1.10.8.1 ad /*
574 1.10.8.1 ad * Device access methods.
575 1.10.8.1 ad */
576 1.10.8.1 ad
577 1.10.8.1 ad #define DEV_LOCK(d) \
578 1.10.8.1 ad if ((d->d_flag & D_MPSAFE) == 0) { \
579 1.10.8.1 ad KERNEL_LOCK(1, curlwp); \
580 1.10.8.1 ad }
581 1.10.8.1 ad
582 1.10.8.1 ad #define DEV_UNLOCK(d) \
583 1.10.8.1 ad if ((d->d_flag & D_MPSAFE) == 0) { \
584 1.10.8.1 ad KERNEL_UNLOCK_ONE(curlwp); \
585 1.10.8.1 ad }
586 1.10.8.1 ad
587 1.10.8.1 ad int
588 1.10.8.1 ad bdev_open(dev_t dev, int flag, int devtype, lwp_t *l)
589 1.10.8.1 ad {
590 1.10.8.1 ad const struct bdevsw *d;
591 1.10.8.1 ad int rv;
592 1.10.8.1 ad
593 1.10.8.1 ad /*
594 1.10.8.1 ad * For open we need to lock, in order to synchronize
595 1.10.8.1 ad * with attach/detach.
596 1.10.8.1 ad */
597 1.10.8.1 ad mutex_enter(&devsw_lock);
598 1.10.8.1 ad d = bdevsw_lookup(dev);
599 1.10.8.1 ad mutex_exit(&devsw_lock);
600 1.10.8.1 ad if (d == NULL)
601 1.10.8.1 ad return ENXIO;
602 1.10.8.1 ad
603 1.10.8.1 ad DEV_LOCK(d);
604 1.10.8.1 ad rv = (*d->d_open)(dev, flag, devtype, l);
605 1.10.8.1 ad DEV_UNLOCK(d);
606 1.10.8.1 ad
607 1.10.8.1 ad return rv;
608 1.10.8.1 ad }
609 1.10.8.1 ad
610 1.10.8.1 ad int
611 1.10.8.1 ad bdev_close(dev_t dev, int flag, int devtype, lwp_t *l)
612 1.10.8.1 ad {
613 1.10.8.1 ad const struct bdevsw *d;
614 1.10.8.1 ad int rv;
615 1.10.8.1 ad
616 1.10.8.1 ad if ((d = bdevsw_lookup(dev)) == NULL)
617 1.10.8.1 ad return ENXIO;
618 1.10.8.1 ad
619 1.10.8.1 ad DEV_LOCK(d);
620 1.10.8.1 ad rv = (*d->d_close)(dev, flag, devtype, l);
621 1.10.8.1 ad DEV_UNLOCK(d);
622 1.10.8.1 ad
623 1.10.8.1 ad return rv;
624 1.10.8.1 ad }
625 1.10.8.1 ad
626 1.10.8.1 ad void
627 1.10.8.1 ad bdev_strategy(struct buf *bp)
628 1.10.8.1 ad {
629 1.10.8.1 ad const struct bdevsw *d;
630 1.10.8.1 ad
631 1.10.8.1 ad if ((d = bdevsw_lookup(bp->b_dev)) == NULL)
632 1.10.8.1 ad panic("bdev_strategy");
633 1.10.8.1 ad
634 1.10.8.1 ad DEV_LOCK(d);
635 1.10.8.1 ad (*d->d_strategy)(bp);
636 1.10.8.1 ad DEV_UNLOCK(d);
637 1.10.8.1 ad }
638 1.10.8.1 ad
639 1.10.8.1 ad int
640 1.10.8.1 ad bdev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
641 1.10.8.1 ad {
642 1.10.8.1 ad const struct bdevsw *d;
643 1.10.8.1 ad int rv;
644 1.10.8.1 ad
645 1.10.8.1 ad if ((d = bdevsw_lookup(dev)) == NULL)
646 1.10.8.1 ad return ENXIO;
647 1.10.8.1 ad
648 1.10.8.1 ad DEV_LOCK(d);
649 1.10.8.1 ad rv = (*d->d_ioctl)(dev, cmd, data, flag, l);
650 1.10.8.1 ad DEV_UNLOCK(d);
651 1.10.8.1 ad
652 1.10.8.1 ad return rv;
653 1.10.8.1 ad }
654 1.10.8.1 ad
655 1.10.8.1 ad int
656 1.10.8.1 ad bdev_dump(dev_t dev, daddr_t addr, void *data, size_t sz)
657 1.10.8.1 ad {
658 1.10.8.1 ad const struct bdevsw *d;
659 1.10.8.1 ad int rv;
660 1.10.8.1 ad
661 1.10.8.1 ad /*
662 1.10.8.1 ad * Dump can be called without the device open. Since it can
663 1.10.8.1 ad * currently only be called with the system paused (and in a
664 1.10.8.1 ad * potentially unstable state), we don't perform any locking.
665 1.10.8.1 ad */
666 1.10.8.1 ad if ((d = bdevsw_lookup(dev)) == NULL)
667 1.10.8.1 ad return ENXIO;
668 1.10.8.1 ad
669 1.10.8.1 ad /* DEV_LOCK(d); */
670 1.10.8.1 ad rv = (*d->d_dump)(dev, addr, data, sz);
671 1.10.8.1 ad /* DEV_UNLOCK(d); */
672 1.10.8.1 ad
673 1.10.8.1 ad return rv;
674 1.10.8.1 ad }
675 1.10.8.1 ad
676 1.10.8.1 ad int
677 1.10.8.1 ad bdev_type(dev_t dev)
678 1.10.8.1 ad {
679 1.10.8.1 ad const struct bdevsw *d;
680 1.10.8.1 ad
681 1.10.8.1 ad if ((d = bdevsw_lookup(dev)) == NULL)
682 1.10.8.1 ad return D_OTHER;
683 1.10.8.1 ad return d->d_flag & D_TYPEMASK;
684 1.10.8.1 ad }
685 1.10.8.1 ad
686 1.10.8.1 ad int
687 1.10.8.1 ad cdev_open(dev_t dev, int flag, int devtype, lwp_t *l)
688 1.10.8.1 ad {
689 1.10.8.1 ad const struct cdevsw *d;
690 1.10.8.1 ad int rv;
691 1.10.8.1 ad
692 1.10.8.1 ad /*
693 1.10.8.1 ad * For open we need to lock, in order to synchronize
694 1.10.8.1 ad * with attach/detach.
695 1.10.8.1 ad */
696 1.10.8.1 ad mutex_enter(&devsw_lock);
697 1.10.8.1 ad d = cdevsw_lookup(dev);
698 1.10.8.1 ad mutex_exit(&devsw_lock);
699 1.10.8.1 ad if (d == NULL)
700 1.10.8.1 ad return ENXIO;
701 1.10.8.1 ad
702 1.10.8.1 ad DEV_LOCK(d);
703 1.10.8.1 ad rv = (*d->d_open)(dev, flag, devtype, l);
704 1.10.8.1 ad DEV_UNLOCK(d);
705 1.10.8.1 ad
706 1.10.8.1 ad return rv;
707 1.10.8.1 ad }
708 1.10.8.1 ad
709 1.10.8.1 ad int
710 1.10.8.1 ad cdev_close(dev_t dev, int flag, int devtype, lwp_t *l)
711 1.10.8.1 ad {
712 1.10.8.1 ad const struct cdevsw *d;
713 1.10.8.1 ad int rv;
714 1.10.8.1 ad
715 1.10.8.1 ad if ((d = cdevsw_lookup(dev)) == NULL)
716 1.10.8.1 ad return ENXIO;
717 1.10.8.1 ad
718 1.10.8.1 ad DEV_LOCK(d);
719 1.10.8.1 ad rv = (*d->d_close)(dev, flag, devtype, l);
720 1.10.8.1 ad DEV_UNLOCK(d);
721 1.10.8.1 ad
722 1.10.8.1 ad return rv;
723 1.10.8.1 ad }
724 1.10.8.1 ad
725 1.10.8.1 ad int
726 1.10.8.1 ad cdev_read(dev_t dev, struct uio *uio, int flag)
727 1.10.8.1 ad {
728 1.10.8.1 ad const struct cdevsw *d;
729 1.10.8.1 ad int rv;
730 1.10.8.1 ad
731 1.10.8.1 ad if ((d = cdevsw_lookup(dev)) == NULL)
732 1.10.8.1 ad return ENXIO;
733 1.10.8.1 ad
734 1.10.8.1 ad DEV_LOCK(d);
735 1.10.8.1 ad rv = (*d->d_read)(dev, uio, flag);
736 1.10.8.1 ad DEV_UNLOCK(d);
737 1.10.8.1 ad
738 1.10.8.1 ad return rv;
739 1.10.8.1 ad }
740 1.10.8.1 ad
741 1.10.8.1 ad int
742 1.10.8.1 ad cdev_write(dev_t dev, struct uio *uio, int flag)
743 1.10.8.1 ad {
744 1.10.8.1 ad const struct cdevsw *d;
745 1.10.8.1 ad int rv;
746 1.10.8.1 ad
747 1.10.8.1 ad if ((d = cdevsw_lookup(dev)) == NULL)
748 1.10.8.1 ad return ENXIO;
749 1.10.8.1 ad
750 1.10.8.1 ad DEV_LOCK(d);
751 1.10.8.1 ad rv = (*d->d_write)(dev, uio, flag);
752 1.10.8.1 ad DEV_UNLOCK(d);
753 1.10.8.1 ad
754 1.10.8.1 ad return rv;
755 1.10.8.1 ad }
756 1.10.8.1 ad
757 1.10.8.1 ad int
758 1.10.8.1 ad cdev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
759 1.10.8.1 ad {
760 1.10.8.1 ad const struct cdevsw *d;
761 1.10.8.1 ad int rv;
762 1.10.8.1 ad
763 1.10.8.1 ad if ((d = cdevsw_lookup(dev)) == NULL)
764 1.10.8.1 ad return ENXIO;
765 1.10.8.1 ad
766 1.10.8.1 ad DEV_LOCK(d);
767 1.10.8.1 ad rv = (*d->d_ioctl)(dev, cmd, data, flag, l);
768 1.10.8.1 ad DEV_UNLOCK(d);
769 1.10.8.1 ad
770 1.10.8.1 ad return rv;
771 1.10.8.1 ad }
772 1.10.8.1 ad
773 1.10.8.1 ad void
774 1.10.8.1 ad cdev_stop(struct tty *tp, int flag)
775 1.10.8.1 ad {
776 1.10.8.1 ad const struct cdevsw *d;
777 1.10.8.1 ad
778 1.10.8.1 ad if ((d = cdevsw_lookup(tp->t_dev)) == NULL)
779 1.10.8.1 ad return;
780 1.10.8.1 ad
781 1.10.8.1 ad DEV_LOCK(d);
782 1.10.8.1 ad (*d->d_stop)(tp, flag);
783 1.10.8.1 ad DEV_UNLOCK(d);
784 1.10.8.1 ad }
785 1.10.8.1 ad
786 1.10.8.1 ad struct tty *
787 1.10.8.1 ad cdev_tty(dev_t dev)
788 1.10.8.1 ad {
789 1.10.8.1 ad const struct cdevsw *d;
790 1.10.8.1 ad struct tty * rv;
791 1.10.8.1 ad
792 1.10.8.1 ad if ((d = cdevsw_lookup(dev)) == NULL)
793 1.10.8.1 ad return NULL;
794 1.10.8.1 ad
795 1.10.8.1 ad DEV_LOCK(d);
796 1.10.8.1 ad rv = (*d->d_tty)(dev);
797 1.10.8.1 ad DEV_UNLOCK(d);
798 1.10.8.1 ad
799 1.10.8.1 ad return rv;
800 1.10.8.1 ad }
801 1.10.8.1 ad
802 1.10.8.1 ad int
803 1.10.8.1 ad cdev_poll(dev_t dev, int flag, lwp_t *l)
804 1.10.8.1 ad {
805 1.10.8.1 ad const struct cdevsw *d;
806 1.10.8.1 ad int rv;
807 1.10.8.1 ad
808 1.10.8.1 ad if ((d = cdevsw_lookup(dev)) == NULL)
809 1.10.8.1 ad return POLLERR;
810 1.10.8.1 ad
811 1.10.8.1 ad DEV_LOCK(d);
812 1.10.8.1 ad rv = (*d->d_poll)(dev, flag, l);
813 1.10.8.1 ad DEV_UNLOCK(d);
814 1.10.8.1 ad
815 1.10.8.1 ad return rv;
816 1.10.8.1 ad }
817 1.10.8.1 ad
818 1.10.8.1 ad paddr_t
819 1.10.8.1 ad cdev_mmap(dev_t dev, off_t off, int flag)
820 1.10.8.1 ad {
821 1.10.8.1 ad const struct cdevsw *d;
822 1.10.8.1 ad paddr_t rv;
823 1.10.8.1 ad
824 1.10.8.1 ad if ((d = cdevsw_lookup(dev)) == NULL)
825 1.10.8.1 ad return (paddr_t)-1LL;
826 1.10.8.1 ad
827 1.10.8.1 ad DEV_LOCK(d);
828 1.10.8.1 ad rv = (*d->d_mmap)(dev, off, flag);
829 1.10.8.1 ad DEV_UNLOCK(d);
830 1.10.8.1 ad
831 1.10.8.1 ad return rv;
832 1.10.8.1 ad }
833 1.10.8.1 ad
834 1.10.8.1 ad int
835 1.10.8.1 ad cdev_kqfilter(dev_t dev, struct knote *kn)
836 1.10.8.1 ad {
837 1.10.8.1 ad const struct cdevsw *d;
838 1.10.8.1 ad int rv;
839 1.10.8.1 ad
840 1.10.8.1 ad if ((d = cdevsw_lookup(dev)) == NULL)
841 1.10.8.1 ad return ENXIO;
842 1.10.8.1 ad
843 1.10.8.1 ad DEV_LOCK(d);
844 1.10.8.1 ad rv = (*d->d_kqfilter)(dev, kn);
845 1.10.8.1 ad DEV_UNLOCK(d);
846 1.10.8.1 ad
847 1.10.8.1 ad return rv;
848 1.10.8.1 ad }
849 1.10.8.1 ad
850 1.10.8.1 ad int
851 1.10.8.1 ad cdev_type(dev_t dev)
852 1.10.8.1 ad {
853 1.10.8.1 ad const struct cdevsw *d;
854 1.2 gehenna
855 1.10.8.1 ad if ((d = cdevsw_lookup(dev)) == NULL)
856 1.10.8.1 ad return D_OTHER;
857 1.10.8.1 ad return d->d_flag & D_TYPEMASK;
858 1.2 gehenna }
859