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