subr_devsw.c revision 1.28.16.1 1 /* $NetBSD: subr_devsw.c,v 1.28.16.1 2012/02/18 07:35:32 mrg 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.28.16.1 2012/02/18 07:35:32 mrg Exp $");
73
74 #include <sys/param.h>
75 #include <sys/conf.h>
76 #include <sys/kmem.h>
77 #include <sys/systm.h>
78 #include <sys/poll.h>
79 #include <sys/tty.h>
80 #include <sys/cpu.h>
81 #include <sys/buf.h>
82 #include <sys/reboot.h>
83
84 #ifdef DEVSW_DEBUG
85 #define DPRINTF(x) printf x
86 #else /* DEVSW_DEBUG */
87 #define DPRINTF(x)
88 #endif /* DEVSW_DEBUG */
89
90 #define MAXDEVSW 512 /* the maximum of major device number */
91 #define BDEVSW_SIZE (sizeof(struct bdevsw *))
92 #define CDEVSW_SIZE (sizeof(struct cdevsw *))
93 #define DEVSWCONV_SIZE (sizeof(struct devsw_conv))
94
95 extern const struct bdevsw **bdevsw, *bdevsw0[];
96 extern const struct cdevsw **cdevsw, *cdevsw0[];
97 extern struct devsw_conv *devsw_conv, devsw_conv0[];
98 extern const int sys_bdevsws, sys_cdevsws;
99 extern int max_bdevsws, max_cdevsws, max_devsw_convs;
100
101 static int bdevsw_attach(const struct bdevsw *, devmajor_t *);
102 static int cdevsw_attach(const struct cdevsw *, devmajor_t *);
103 static void devsw_detach_locked(const struct bdevsw *, const struct cdevsw *);
104
105 kmutex_t device_lock;
106
107 void
108 devsw_init(void)
109 {
110
111 KASSERT(sys_bdevsws < MAXDEVSW - 1);
112 KASSERT(sys_cdevsws < MAXDEVSW - 1);
113 mutex_init(&device_lock, MUTEX_DEFAULT, IPL_NONE);
114 }
115
116 int
117 devsw_attach(const char *devname,
118 const struct bdevsw *bdev, devmajor_t *bmajor,
119 const struct cdevsw *cdev, devmajor_t *cmajor)
120 {
121 struct devsw_conv *conv;
122 char *name;
123 int error, i;
124 size_t len;
125
126 if (devname == NULL || cdev == NULL)
127 return (EINVAL);
128
129 mutex_enter(&device_lock);
130
131 for (i = 0 ; i < max_devsw_convs ; i++) {
132 conv = &devsw_conv[i];
133 if (conv->d_name == NULL || strcmp(devname, conv->d_name) != 0)
134 continue;
135
136 if (*bmajor < 0)
137 *bmajor = conv->d_bmajor;
138 if (*cmajor < 0)
139 *cmajor = conv->d_cmajor;
140
141 if (*bmajor != conv->d_bmajor || *cmajor != conv->d_cmajor) {
142 error = EINVAL;
143 goto fail;
144 }
145 if ((*bmajor >= 0 && bdev == NULL) || *cmajor < 0) {
146 error = EINVAL;
147 goto fail;
148 }
149
150 if ((*bmajor >= 0 && bdevsw[*bmajor] != NULL) ||
151 cdevsw[*cmajor] != NULL) {
152 error = EEXIST;
153 goto fail;
154 }
155
156 if (bdev != NULL)
157 bdevsw[*bmajor] = bdev;
158 cdevsw[*cmajor] = cdev;
159
160 mutex_exit(&device_lock);
161 return (0);
162 }
163
164 error = bdevsw_attach(bdev, bmajor);
165 if (error != 0)
166 goto fail;
167 error = cdevsw_attach(cdev, cmajor);
168 if (error != 0) {
169 devsw_detach_locked(bdev, NULL);
170 goto fail;
171 }
172
173 for (i = 0 ; i < max_devsw_convs ; i++) {
174 if (devsw_conv[i].d_name == NULL)
175 break;
176 }
177 if (i == max_devsw_convs) {
178 struct devsw_conv *newptr;
179 int old, new;
180
181 old = max_devsw_convs;
182 new = old + 1;
183
184 newptr = kmem_zalloc(new * DEVSWCONV_SIZE, KM_NOSLEEP);
185 if (newptr == NULL) {
186 devsw_detach_locked(bdev, cdev);
187 error = ENOMEM;
188 goto fail;
189 }
190 newptr[old].d_name = NULL;
191 newptr[old].d_bmajor = -1;
192 newptr[old].d_cmajor = -1;
193 memcpy(newptr, devsw_conv, old * DEVSWCONV_SIZE);
194 if (devsw_conv != devsw_conv0)
195 kmem_free(devsw_conv, old * DEVSWCONV_SIZE);
196 devsw_conv = newptr;
197 max_devsw_convs = new;
198 }
199
200 len = strlen(devname) + 1;
201 name = kmem_alloc(len, KM_NOSLEEP);
202 if (name == NULL) {
203 devsw_detach_locked(bdev, cdev);
204 error = ENOMEM;
205 goto fail;
206 }
207 strlcpy(name, devname, len);
208
209 devsw_conv[i].d_name = name;
210 devsw_conv[i].d_bmajor = *bmajor;
211 devsw_conv[i].d_cmajor = *cmajor;
212
213 mutex_exit(&device_lock);
214 return (0);
215 fail:
216 mutex_exit(&device_lock);
217 return (error);
218 }
219
220 static int
221 bdevsw_attach(const struct bdevsw *devsw, devmajor_t *devmajor)
222 {
223 const struct bdevsw **newptr;
224 devmajor_t bmajor;
225 int i;
226
227 KASSERT(mutex_owned(&device_lock));
228
229 if (devsw == NULL)
230 return (0);
231
232 if (*devmajor < 0) {
233 for (bmajor = sys_bdevsws ; bmajor < max_bdevsws ; bmajor++) {
234 if (bdevsw[bmajor] != NULL)
235 continue;
236 for (i = 0 ; i < max_devsw_convs ; i++) {
237 if (devsw_conv[i].d_bmajor == bmajor)
238 break;
239 }
240 if (i != max_devsw_convs)
241 continue;
242 break;
243 }
244 *devmajor = bmajor;
245 }
246
247 if (*devmajor >= MAXDEVSW) {
248 printf("bdevsw_attach: block majors exhausted");
249 return (ENOMEM);
250 }
251
252 if (*devmajor >= max_bdevsws) {
253 KASSERT(bdevsw == bdevsw0);
254 newptr = kmem_zalloc(MAXDEVSW * BDEVSW_SIZE, KM_NOSLEEP);
255 if (newptr == NULL)
256 return (ENOMEM);
257 memcpy(newptr, bdevsw, max_bdevsws * BDEVSW_SIZE);
258 bdevsw = newptr;
259 max_bdevsws = MAXDEVSW;
260 }
261
262 if (bdevsw[*devmajor] != NULL)
263 return (EEXIST);
264
265 bdevsw[*devmajor] = devsw;
266
267 return (0);
268 }
269
270 static int
271 cdevsw_attach(const struct cdevsw *devsw, devmajor_t *devmajor)
272 {
273 const struct cdevsw **newptr;
274 devmajor_t cmajor;
275 int i;
276
277 KASSERT(mutex_owned(&device_lock));
278
279 if (*devmajor < 0) {
280 for (cmajor = sys_cdevsws ; cmajor < max_cdevsws ; cmajor++) {
281 if (cdevsw[cmajor] != NULL)
282 continue;
283 for (i = 0 ; i < max_devsw_convs ; i++) {
284 if (devsw_conv[i].d_cmajor == cmajor)
285 break;
286 }
287 if (i != max_devsw_convs)
288 continue;
289 break;
290 }
291 *devmajor = cmajor;
292 }
293
294 if (*devmajor >= MAXDEVSW) {
295 printf("cdevsw_attach: character majors exhausted");
296 return (ENOMEM);
297 }
298
299 if (*devmajor >= max_cdevsws) {
300 KASSERT(cdevsw == cdevsw0);
301 newptr = kmem_zalloc(MAXDEVSW * CDEVSW_SIZE, KM_NOSLEEP);
302 if (newptr == NULL)
303 return (ENOMEM);
304 memcpy(newptr, cdevsw, max_cdevsws * CDEVSW_SIZE);
305 cdevsw = newptr;
306 max_cdevsws = MAXDEVSW;
307 }
308
309 if (cdevsw[*devmajor] != NULL)
310 return (EEXIST);
311
312 cdevsw[*devmajor] = devsw;
313
314 return (0);
315 }
316
317 static void
318 devsw_detach_locked(const struct bdevsw *bdev, const struct cdevsw *cdev)
319 {
320 int i;
321
322 KASSERT(mutex_owned(&device_lock));
323
324 if (bdev != NULL) {
325 for (i = 0 ; i < max_bdevsws ; i++) {
326 if (bdevsw[i] != bdev)
327 continue;
328 bdevsw[i] = NULL;
329 break;
330 }
331 }
332 if (cdev != NULL) {
333 for (i = 0 ; i < max_cdevsws ; i++) {
334 if (cdevsw[i] != cdev)
335 continue;
336 cdevsw[i] = NULL;
337 break;
338 }
339 }
340 }
341
342 int
343 devsw_detach(const struct bdevsw *bdev, const struct cdevsw *cdev)
344 {
345
346 mutex_enter(&device_lock);
347 devsw_detach_locked(bdev, cdev);
348 mutex_exit(&device_lock);
349 return 0;
350 }
351
352 /*
353 * Look up a block device by number.
354 *
355 * => Caller must ensure that the device is attached.
356 */
357 const struct bdevsw *
358 bdevsw_lookup(dev_t dev)
359 {
360 devmajor_t bmajor;
361
362 if (dev == NODEV)
363 return (NULL);
364 bmajor = major(dev);
365 if (bmajor < 0 || bmajor >= max_bdevsws)
366 return (NULL);
367
368 return (bdevsw[bmajor]);
369 }
370
371 /*
372 * Look up a character device by number.
373 *
374 * => Caller must ensure that the device is attached.
375 */
376 const struct cdevsw *
377 cdevsw_lookup(dev_t dev)
378 {
379 devmajor_t cmajor;
380
381 if (dev == NODEV)
382 return (NULL);
383 cmajor = major(dev);
384 if (cmajor < 0 || cmajor >= max_cdevsws)
385 return (NULL);
386
387 return (cdevsw[cmajor]);
388 }
389
390 /*
391 * Look up a block device by reference to its operations set.
392 *
393 * => Caller must ensure that the device is not detached, and therefore
394 * that the returned major is still valid when dereferenced.
395 */
396 devmajor_t
397 bdevsw_lookup_major(const struct bdevsw *bdev)
398 {
399 devmajor_t bmajor;
400
401 for (bmajor = 0 ; bmajor < max_bdevsws ; bmajor++) {
402 if (bdevsw[bmajor] == bdev)
403 return (bmajor);
404 }
405
406 return (NODEVMAJOR);
407 }
408
409 /*
410 * Look up a character device by reference to its operations set.
411 *
412 * => Caller must ensure that the device is not detached, and therefore
413 * that the returned major is still valid when dereferenced.
414 */
415 devmajor_t
416 cdevsw_lookup_major(const struct cdevsw *cdev)
417 {
418 devmajor_t cmajor;
419
420 for (cmajor = 0 ; cmajor < max_cdevsws ; cmajor++) {
421 if (cdevsw[cmajor] == cdev)
422 return (cmajor);
423 }
424
425 return (NODEVMAJOR);
426 }
427
428 /*
429 * Convert from block major number to name.
430 *
431 * => Caller must ensure that the device is not detached, and therefore
432 * that the name pointer is still valid when dereferenced.
433 */
434 const char *
435 devsw_blk2name(devmajor_t bmajor)
436 {
437 const char *name;
438 devmajor_t cmajor;
439 int i;
440
441 name = NULL;
442 cmajor = -1;
443
444 mutex_enter(&device_lock);
445 if (bmajor < 0 || bmajor >= max_bdevsws || bdevsw[bmajor] == NULL) {
446 mutex_exit(&device_lock);
447 return (NULL);
448 }
449 for (i = 0 ; i < max_devsw_convs; i++) {
450 if (devsw_conv[i].d_bmajor == bmajor) {
451 cmajor = devsw_conv[i].d_cmajor;
452 break;
453 }
454 }
455 if (cmajor >= 0 && cmajor < max_cdevsws && cdevsw[cmajor] != NULL)
456 name = devsw_conv[i].d_name;
457 mutex_exit(&device_lock);
458
459 return (name);
460 }
461
462 /*
463 * Convert char major number to device driver name.
464 */
465 const char *
466 cdevsw_getname(devmajor_t major)
467 {
468 const char *name;
469 int i;
470
471 name = NULL;
472
473 if (major < 0)
474 return (NULL);
475
476 mutex_enter(&device_lock);
477 for (i = 0 ; i < max_devsw_convs; i++) {
478 if (devsw_conv[i].d_cmajor == major) {
479 name = devsw_conv[i].d_name;
480 break;
481 }
482 }
483 mutex_exit(&device_lock);
484 return (name);
485 }
486
487 /*
488 * Convert block major number to device driver name.
489 */
490 const char *
491 bdevsw_getname(devmajor_t major)
492 {
493 const char *name;
494 int i;
495
496 name = NULL;
497
498 if (major < 0)
499 return (NULL);
500
501 mutex_enter(&device_lock);
502 for (i = 0 ; i < max_devsw_convs; i++) {
503 if (devsw_conv[i].d_bmajor == major) {
504 name = devsw_conv[i].d_name;
505 break;
506 }
507 }
508 mutex_exit(&device_lock);
509 return (name);
510 }
511
512 /*
513 * Convert from device name to block major number.
514 *
515 * => Caller must ensure that the device is not detached, and therefore
516 * that the major number is still valid when dereferenced.
517 */
518 devmajor_t
519 devsw_name2blk(const char *name, char *devname, size_t devnamelen)
520 {
521 struct devsw_conv *conv;
522 devmajor_t bmajor;
523 int i;
524
525 if (name == NULL)
526 return (NODEVMAJOR);
527
528 mutex_enter(&device_lock);
529 for (i = 0 ; i < max_devsw_convs ; i++) {
530 size_t len;
531
532 conv = &devsw_conv[i];
533 if (conv->d_name == NULL)
534 continue;
535 len = strlen(conv->d_name);
536 if (strncmp(conv->d_name, name, len) != 0)
537 continue;
538 if (*(name +len) && !isdigit(*(name + len)))
539 continue;
540 bmajor = conv->d_bmajor;
541 if (bmajor < 0 || bmajor >= max_bdevsws ||
542 bdevsw[bmajor] == NULL)
543 break;
544 if (devname != NULL) {
545 #ifdef DEVSW_DEBUG
546 if (strlen(conv->d_name) >= devnamelen)
547 printf("devsw_name2blk: too short buffer");
548 #endif /* DEVSW_DEBUG */
549 strncpy(devname, conv->d_name, devnamelen);
550 devname[devnamelen - 1] = '\0';
551 }
552 mutex_exit(&device_lock);
553 return (bmajor);
554 }
555
556 mutex_exit(&device_lock);
557 return (NODEVMAJOR);
558 }
559
560 /*
561 * Convert from device name to char major number.
562 *
563 * => Caller must ensure that the device is not detached, and therefore
564 * that the major number is still valid when dereferenced.
565 */
566 devmajor_t
567 devsw_name2chr(const char *name, char *devname, size_t devnamelen)
568 {
569 struct devsw_conv *conv;
570 devmajor_t cmajor;
571 int i;
572
573 if (name == NULL)
574 return (NODEVMAJOR);
575
576 mutex_enter(&device_lock);
577 for (i = 0 ; i < max_devsw_convs ; i++) {
578 size_t len;
579
580 conv = &devsw_conv[i];
581 if (conv->d_name == NULL)
582 continue;
583 len = strlen(conv->d_name);
584 if (strncmp(conv->d_name, name, len) != 0)
585 continue;
586 if (*(name +len) && !isdigit(*(name + len)))
587 continue;
588 cmajor = conv->d_cmajor;
589 if (cmajor < 0 || cmajor >= max_cdevsws ||
590 cdevsw[cmajor] == NULL)
591 break;
592 if (devname != NULL) {
593 #ifdef DEVSW_DEBUG
594 if (strlen(conv->d_name) >= devnamelen)
595 printf("devsw_name2chr: too short buffer");
596 #endif /* DEVSW_DEBUG */
597 strncpy(devname, conv->d_name, devnamelen);
598 devname[devnamelen - 1] = '\0';
599 }
600 mutex_exit(&device_lock);
601 return (cmajor);
602 }
603
604 mutex_exit(&device_lock);
605 return (NODEVMAJOR);
606 }
607
608 /*
609 * Convert from character dev_t to block dev_t.
610 *
611 * => Caller must ensure that the device is not detached, and therefore
612 * that the major number is still valid when dereferenced.
613 */
614 dev_t
615 devsw_chr2blk(dev_t cdev)
616 {
617 devmajor_t bmajor, cmajor;
618 int i;
619 dev_t rv;
620
621 cmajor = major(cdev);
622 bmajor = NODEVMAJOR;
623 rv = NODEV;
624
625 mutex_enter(&device_lock);
626 if (cmajor < 0 || cmajor >= max_cdevsws || cdevsw[cmajor] == NULL) {
627 mutex_exit(&device_lock);
628 return (NODEV);
629 }
630 for (i = 0 ; i < max_devsw_convs ; i++) {
631 if (devsw_conv[i].d_cmajor == cmajor) {
632 bmajor = devsw_conv[i].d_bmajor;
633 break;
634 }
635 }
636 if (bmajor >= 0 && bmajor < max_bdevsws && bdevsw[bmajor] != NULL)
637 rv = makedev(bmajor, minor(cdev));
638 mutex_exit(&device_lock);
639
640 return (rv);
641 }
642
643 /*
644 * Convert from block dev_t to character dev_t.
645 *
646 * => Caller must ensure that the device is not detached, and therefore
647 * that the major number is still valid when dereferenced.
648 */
649 dev_t
650 devsw_blk2chr(dev_t bdev)
651 {
652 devmajor_t bmajor, cmajor;
653 int i;
654 dev_t rv;
655
656 bmajor = major(bdev);
657 cmajor = NODEVMAJOR;
658 rv = NODEV;
659
660 mutex_enter(&device_lock);
661 if (bmajor < 0 || bmajor >= max_bdevsws || bdevsw[bmajor] == NULL) {
662 mutex_exit(&device_lock);
663 return (NODEV);
664 }
665 for (i = 0 ; i < max_devsw_convs ; i++) {
666 if (devsw_conv[i].d_bmajor == bmajor) {
667 cmajor = devsw_conv[i].d_cmajor;
668 break;
669 }
670 }
671 if (cmajor >= 0 && cmajor < max_cdevsws && cdevsw[cmajor] != NULL)
672 rv = makedev(cmajor, minor(bdev));
673 mutex_exit(&device_lock);
674
675 return (rv);
676 }
677
678 /*
679 * Device access methods.
680 */
681
682 #define DEV_LOCK(d) \
683 if ((mpflag = (d->d_flag & D_MPSAFE)) == 0) { \
684 KERNEL_LOCK(1, NULL); \
685 }
686
687 #define DEV_UNLOCK(d) \
688 if (mpflag == 0) { \
689 KERNEL_UNLOCK_ONE(NULL); \
690 }
691
692 int
693 bdev_open(dev_t dev, int flag, int devtype, lwp_t *l)
694 {
695 const struct bdevsw *d;
696 int rv, mpflag;
697
698 /*
699 * For open we need to lock, in order to synchronize
700 * with attach/detach.
701 */
702 mutex_enter(&device_lock);
703 d = bdevsw_lookup(dev);
704 mutex_exit(&device_lock);
705 if (d == NULL)
706 return ENXIO;
707
708 DEV_LOCK(d);
709 rv = (*d->d_open)(dev, flag, devtype, l);
710 DEV_UNLOCK(d);
711
712 return rv;
713 }
714
715 int
716 bdev_close(dev_t dev, int flag, int devtype, lwp_t *l)
717 {
718 const struct bdevsw *d;
719 int rv, mpflag;
720
721 if ((d = bdevsw_lookup(dev)) == NULL)
722 return ENXIO;
723
724 DEV_LOCK(d);
725 rv = (*d->d_close)(dev, flag, devtype, l);
726 DEV_UNLOCK(d);
727
728 return rv;
729 }
730
731 void
732 bdev_strategy(struct buf *bp)
733 {
734 const struct bdevsw *d;
735 int mpflag;
736
737 if ((d = bdevsw_lookup(bp->b_dev)) == NULL) {
738 bp->b_error = ENXIO;
739 bp->b_resid = bp->b_bcount;
740 biodone(bp);
741 return;
742 }
743
744 DEV_LOCK(d);
745 (*d->d_strategy)(bp);
746 DEV_UNLOCK(d);
747 }
748
749 int
750 bdev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
751 {
752 const struct bdevsw *d;
753 int rv, mpflag;
754
755 if ((d = bdevsw_lookup(dev)) == NULL)
756 return ENXIO;
757
758 DEV_LOCK(d);
759 rv = (*d->d_ioctl)(dev, cmd, data, flag, l);
760 DEV_UNLOCK(d);
761
762 return rv;
763 }
764
765 int
766 bdev_dump(dev_t dev, daddr_t addr, void *data, size_t sz)
767 {
768 const struct bdevsw *d;
769 int rv;
770
771 /*
772 * Dump can be called without the device open. Since it can
773 * currently only be called with the system paused (and in a
774 * potentially unstable state), we don't perform any locking.
775 */
776 if ((d = bdevsw_lookup(dev)) == NULL)
777 return ENXIO;
778
779 /* DEV_LOCK(d); */
780 rv = (*d->d_dump)(dev, addr, data, sz);
781 /* DEV_UNLOCK(d); */
782
783 return rv;
784 }
785
786 int
787 bdev_type(dev_t dev)
788 {
789 const struct bdevsw *d;
790
791 if ((d = bdevsw_lookup(dev)) == NULL)
792 return D_OTHER;
793 return d->d_flag & D_TYPEMASK;
794 }
795
796 int
797 bdev_size(dev_t dev)
798 {
799 const struct bdevsw *d;
800 int rv, mpflag = 0;
801
802 if ((d = bdevsw_lookup(dev)) == NULL ||
803 d->d_psize == NULL)
804 return -1;
805
806 /*
807 * Don't to try lock the device if we're dumping.
808 * XXX: is there a better way to test this?
809 */
810 if ((boothowto & RB_DUMP) == 0)
811 DEV_LOCK(d);
812 rv = (*d->d_psize)(dev);
813 if ((boothowto & RB_DUMP) == 0)
814 DEV_UNLOCK(d);
815
816 return rv;
817 }
818
819 int
820 cdev_open(dev_t dev, int flag, int devtype, lwp_t *l)
821 {
822 const struct cdevsw *d;
823 int rv, mpflag;
824
825 /*
826 * For open we need to lock, in order to synchronize
827 * with attach/detach.
828 */
829 mutex_enter(&device_lock);
830 d = cdevsw_lookup(dev);
831 mutex_exit(&device_lock);
832 if (d == NULL)
833 return ENXIO;
834
835 DEV_LOCK(d);
836 rv = (*d->d_open)(dev, flag, devtype, l);
837 DEV_UNLOCK(d);
838
839 return rv;
840 }
841
842 int
843 cdev_close(dev_t dev, int flag, int devtype, lwp_t *l)
844 {
845 const struct cdevsw *d;
846 int rv, mpflag;
847
848 if ((d = cdevsw_lookup(dev)) == NULL)
849 return ENXIO;
850
851 DEV_LOCK(d);
852 rv = (*d->d_close)(dev, flag, devtype, l);
853 DEV_UNLOCK(d);
854
855 return rv;
856 }
857
858 int
859 cdev_read(dev_t dev, struct uio *uio, int flag)
860 {
861 const struct cdevsw *d;
862 int rv, mpflag;
863
864 if ((d = cdevsw_lookup(dev)) == NULL)
865 return ENXIO;
866
867 DEV_LOCK(d);
868 rv = (*d->d_read)(dev, uio, flag);
869 DEV_UNLOCK(d);
870
871 return rv;
872 }
873
874 int
875 cdev_write(dev_t dev, struct uio *uio, int flag)
876 {
877 const struct cdevsw *d;
878 int rv, mpflag;
879
880 if ((d = cdevsw_lookup(dev)) == NULL)
881 return ENXIO;
882
883 DEV_LOCK(d);
884 rv = (*d->d_write)(dev, uio, flag);
885 DEV_UNLOCK(d);
886
887 return rv;
888 }
889
890 int
891 cdev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
892 {
893 const struct cdevsw *d;
894 int rv, mpflag;
895
896 if ((d = cdevsw_lookup(dev)) == NULL)
897 return ENXIO;
898
899 DEV_LOCK(d);
900 rv = (*d->d_ioctl)(dev, cmd, data, flag, l);
901 DEV_UNLOCK(d);
902
903 return rv;
904 }
905
906 void
907 cdev_stop(struct tty *tp, int flag)
908 {
909 const struct cdevsw *d;
910 int mpflag;
911
912 if ((d = cdevsw_lookup(tp->t_dev)) == NULL)
913 return;
914
915 DEV_LOCK(d);
916 (*d->d_stop)(tp, flag);
917 DEV_UNLOCK(d);
918 }
919
920 struct tty *
921 cdev_tty(dev_t dev)
922 {
923 const struct cdevsw *d;
924
925 if ((d = cdevsw_lookup(dev)) == NULL)
926 return NULL;
927
928 /* XXX Check if necessary. */
929 if (d->d_tty == NULL)
930 return NULL;
931
932 return (*d->d_tty)(dev);
933 }
934
935 int
936 cdev_poll(dev_t dev, int flag, lwp_t *l)
937 {
938 const struct cdevsw *d;
939 int rv, mpflag;
940
941 if ((d = cdevsw_lookup(dev)) == NULL)
942 return POLLERR;
943
944 DEV_LOCK(d);
945 rv = (*d->d_poll)(dev, flag, l);
946 DEV_UNLOCK(d);
947
948 return rv;
949 }
950
951 paddr_t
952 cdev_mmap(dev_t dev, off_t off, int flag)
953 {
954 const struct cdevsw *d;
955 paddr_t rv;
956 int mpflag;
957
958 if ((d = cdevsw_lookup(dev)) == NULL)
959 return (paddr_t)-1LL;
960
961 DEV_LOCK(d);
962 rv = (*d->d_mmap)(dev, off, flag);
963 DEV_UNLOCK(d);
964
965 return rv;
966 }
967
968 int
969 cdev_kqfilter(dev_t dev, struct knote *kn)
970 {
971 const struct cdevsw *d;
972 int rv, mpflag;
973
974 if ((d = cdevsw_lookup(dev)) == NULL)
975 return ENXIO;
976
977 DEV_LOCK(d);
978 rv = (*d->d_kqfilter)(dev, kn);
979 DEV_UNLOCK(d);
980
981 return rv;
982 }
983
984 int
985 cdev_type(dev_t dev)
986 {
987 const struct cdevsw *d;
988
989 if ((d = cdevsw_lookup(dev)) == NULL)
990 return D_OTHER;
991 return d->d_flag & D_TYPEMASK;
992 }
993