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