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