xref: /freebsd/sys/kern/kern_conf.c (revision 3642298923e528d795e3a30ec165d2b469e28b40)
1 /*-
2  * Copyright (c) 1999-2002 Poul-Henning Kamp
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <sys/param.h>
31 #include <sys/kernel.h>
32 #include <sys/systm.h>
33 #include <sys/bio.h>
34 #include <sys/lock.h>
35 #include <sys/mutex.h>
36 #include <sys/sysctl.h>
37 #include <sys/module.h>
38 #include <sys/malloc.h>
39 #include <sys/conf.h>
40 #include <sys/vnode.h>
41 #include <sys/queue.h>
42 #include <sys/poll.h>
43 #include <sys/ctype.h>
44 #include <sys/tty.h>
45 #include <sys/ucred.h>
46 #include <machine/stdarg.h>
47 
48 #include <fs/devfs/devfs_int.h>
49 
50 static MALLOC_DEFINE(M_DEVT, "cdev", "cdev storage");
51 
52 static struct mtx devmtx;
53 static void freedev(struct cdev *dev);
54 static void destroy_devl(struct cdev *dev);
55 static struct cdev *make_dev_credv(struct cdevsw *devsw, int minornr,
56 	    struct ucred *cr, uid_t uid, gid_t gid, int mode, const char *fmt,
57 	    va_list ap);
58 
59 void
60 dev_lock(void)
61 {
62 	if (!mtx_initialized(&devmtx))
63 		mtx_init(&devmtx, "cdev", NULL, MTX_DEF);
64 	mtx_lock(&devmtx);
65 }
66 
67 void
68 dev_unlock(void)
69 {
70 
71 	mtx_unlock(&devmtx);
72 }
73 
74 void
75 dev_ref(struct cdev *dev)
76 {
77 
78 	mtx_assert(&devmtx, MA_NOTOWNED);
79 	mtx_lock(&devmtx);
80 	dev->si_refcount++;
81 	mtx_unlock(&devmtx);
82 }
83 
84 void
85 dev_refl(struct cdev *dev)
86 {
87 
88 	mtx_assert(&devmtx, MA_OWNED);
89 	dev->si_refcount++;
90 }
91 
92 void
93 dev_rel(struct cdev *dev)
94 {
95 	int flag = 0;
96 
97 	mtx_assert(&devmtx, MA_NOTOWNED);
98 	dev_lock();
99 	dev->si_refcount--;
100 	KASSERT(dev->si_refcount >= 0,
101 	    ("dev_rel(%s) gave negative count", devtoname(dev)));
102 	if (dev->si_usecount == 0 &&
103 	    (dev->si_flags & SI_CHEAPCLONE) && (dev->si_flags & SI_NAMED))
104 	if (dev->si_devsw == NULL && dev->si_refcount == 0) {
105 		LIST_REMOVE(dev, si_list);
106 		flag = 1;
107 	}
108 	dev_unlock();
109 	if (flag)
110 		freedev(dev);
111 }
112 
113 struct cdevsw *
114 dev_refthread(struct cdev *dev)
115 {
116 	struct cdevsw *csw;
117 
118 	mtx_assert(&devmtx, MA_NOTOWNED);
119 	dev_lock();
120 	csw = dev->si_devsw;
121 	if (csw != NULL)
122 		dev->si_threadcount++;
123 	dev_unlock();
124 	return (csw);
125 }
126 
127 void
128 dev_relthread(struct cdev *dev)
129 {
130 
131 	mtx_assert(&devmtx, MA_NOTOWNED);
132 	dev_lock();
133 	dev->si_threadcount--;
134 	dev_unlock();
135 }
136 
137 int
138 nullop(void)
139 {
140 
141 	return (0);
142 }
143 
144 int
145 eopnotsupp(void)
146 {
147 
148 	return (EOPNOTSUPP);
149 }
150 
151 static int
152 enxio(void)
153 {
154 	return (ENXIO);
155 }
156 
157 static int
158 enodev(void)
159 {
160 	return (ENODEV);
161 }
162 
163 /* Define a dead_cdevsw for use when devices leave unexpectedly. */
164 
165 #define dead_open	(d_open_t *)enxio
166 #define dead_close	(d_close_t *)enxio
167 #define dead_read	(d_read_t *)enxio
168 #define dead_write	(d_write_t *)enxio
169 #define dead_ioctl	(d_ioctl_t *)enxio
170 #define dead_poll	(d_poll_t *)enodev
171 #define dead_mmap	(d_mmap_t *)enodev
172 
173 static void
174 dead_strategy(struct bio *bp)
175 {
176 
177 	biofinish(bp, NULL, ENXIO);
178 }
179 
180 #define dead_dump	(dumper_t *)enxio
181 #define dead_kqfilter	(d_kqfilter_t *)enxio
182 
183 static struct cdevsw dead_cdevsw = {
184 	.d_version =	D_VERSION,
185 	.d_flags =	D_NEEDGIANT, /* XXX: does dead_strategy need this ? */
186 	.d_open =	dead_open,
187 	.d_close =	dead_close,
188 	.d_read =	dead_read,
189 	.d_write =	dead_write,
190 	.d_ioctl =	dead_ioctl,
191 	.d_poll =	dead_poll,
192 	.d_mmap =	dead_mmap,
193 	.d_strategy =	dead_strategy,
194 	.d_name =	"dead",
195 	.d_dump =	dead_dump,
196 	.d_kqfilter =	dead_kqfilter
197 };
198 
199 /* Default methods if driver does not specify method */
200 
201 #define null_open	(d_open_t *)nullop
202 #define null_close	(d_close_t *)nullop
203 #define no_read		(d_read_t *)enodev
204 #define no_write	(d_write_t *)enodev
205 #define no_ioctl	(d_ioctl_t *)enodev
206 #define no_mmap		(d_mmap_t *)enodev
207 #define no_kqfilter	(d_kqfilter_t *)enodev
208 
209 static void
210 no_strategy(struct bio *bp)
211 {
212 
213 	biofinish(bp, NULL, ENODEV);
214 }
215 
216 static int
217 no_poll(struct cdev *dev __unused, int events, struct thread *td __unused)
218 {
219 	/*
220 	 * Return true for read/write.  If the user asked for something
221 	 * special, return POLLNVAL, so that clients have a way of
222 	 * determining reliably whether or not the extended
223 	 * functionality is present without hard-coding knowledge
224 	 * of specific filesystem implementations.
225 	 * Stay in sync with vop_nopoll().
226 	 */
227 	if (events & ~POLLSTANDARD)
228 		return (POLLNVAL);
229 
230 	return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
231 }
232 
233 #define no_dump		(dumper_t *)enodev
234 
235 static int
236 giant_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
237 {
238 	int retval;
239 
240 	mtx_lock(&Giant);
241 	retval = dev->si_devsw->d_gianttrick->
242 	    d_open(dev, oflags, devtype, td);
243 	mtx_unlock(&Giant);
244 	return (retval);
245 }
246 
247 static int
248 giant_fdopen(struct cdev *dev, int oflags, struct thread *td, int fdidx)
249 {
250 	int retval;
251 
252 	mtx_lock(&Giant);
253 	retval = dev->si_devsw->d_gianttrick->
254 	    d_fdopen(dev, oflags, td, fdidx);
255 	mtx_unlock(&Giant);
256 	return (retval);
257 }
258 
259 static int
260 giant_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
261 {
262 	int retval;
263 
264 	mtx_lock(&Giant);
265 	retval = dev->si_devsw->d_gianttrick->
266 	    d_close(dev, fflag, devtype, td);
267 	mtx_unlock(&Giant);
268 	return (retval);
269 }
270 
271 static void
272 giant_strategy(struct bio *bp)
273 {
274 
275 	mtx_lock(&Giant);
276 	bp->bio_dev->si_devsw->d_gianttrick->
277 	    d_strategy(bp);
278 	mtx_unlock(&Giant);
279 }
280 
281 static int
282 giant_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
283 {
284 	int retval;
285 
286 	mtx_lock(&Giant);
287 	retval = dev->si_devsw->d_gianttrick->
288 	    d_ioctl(dev, cmd, data, fflag, td);
289 	mtx_unlock(&Giant);
290 	return (retval);
291 }
292 
293 static int
294 giant_read(struct cdev *dev, struct uio *uio, int ioflag)
295 {
296 	int retval;
297 
298 	mtx_lock(&Giant);
299 	retval = dev->si_devsw->d_gianttrick->
300 	    d_read(dev, uio, ioflag);
301 	mtx_unlock(&Giant);
302 	return (retval);
303 }
304 
305 static int
306 giant_write(struct cdev *dev, struct uio *uio, int ioflag)
307 {
308 	int retval;
309 
310 	mtx_lock(&Giant);
311 	retval = dev->si_devsw->d_gianttrick->
312 		d_write(dev, uio, ioflag);
313 	mtx_unlock(&Giant);
314 	return (retval);
315 }
316 
317 static int
318 giant_poll(struct cdev *dev, int events, struct thread *td)
319 {
320 	int retval;
321 
322 	mtx_lock(&Giant);
323 	retval = dev->si_devsw->d_gianttrick->
324 	    d_poll(dev, events, td);
325 	mtx_unlock(&Giant);
326 	return (retval);
327 }
328 
329 static int
330 giant_kqfilter(struct cdev *dev, struct knote *kn)
331 {
332 	int retval;
333 
334 	mtx_lock(&Giant);
335 	retval = dev->si_devsw->d_gianttrick->
336 	    d_kqfilter(dev, kn);
337 	mtx_unlock(&Giant);
338 	return (retval);
339 }
340 
341 static int
342 giant_mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
343 {
344 	int retval;
345 
346 	mtx_lock(&Giant);
347 	retval = dev->si_devsw->d_gianttrick->
348 	    d_mmap(dev, offset, paddr, nprot);
349 	mtx_unlock(&Giant);
350 	return (retval);
351 }
352 
353 
354 /*
355  * struct cdev * and u_dev_t primitives
356  */
357 
358 int
359 minor(struct cdev *x)
360 {
361 	if (x == NULL)
362 		return NODEV;
363 	return(x->si_drv0 & MAXMINOR);
364 }
365 
366 int
367 dev2unit(struct cdev *x)
368 {
369 
370 	if (x == NULL)
371 		return NODEV;
372 	return (minor2unit(minor(x)));
373 }
374 
375 u_int
376 minor2unit(u_int _minor)
377 {
378 
379 	KASSERT((_minor & ~MAXMINOR) == 0, ("Illegal minor %x", _minor));
380 	return ((_minor & 0xff) | ((_minor >> 8) & 0xffff00));
381 }
382 
383 int
384 unit2minor(int unit)
385 {
386 
387 	KASSERT(unit <= 0xffffff, ("Invalid unit (%d) in unit2minor", unit));
388 	return ((unit & 0xff) | ((unit << 8) & ~0xffff));
389 }
390 
391 static struct cdev *
392 allocdev(void)
393 {
394 	struct cdev *si;
395 
396 	si = malloc(sizeof *si, M_DEVT, M_USE_RESERVE | M_ZERO | M_WAITOK);
397 	si->si_name = si->__si_namebuf;
398 	LIST_INIT(&si->si_children);
399 	LIST_INIT(&si->si_alist);
400 	return (si);
401 }
402 
403 static struct cdev *
404 newdev(struct cdevsw *csw, int y, struct cdev *si)
405 {
406 	struct cdev *si2;
407 	dev_t	udev;
408 
409 	mtx_assert(&devmtx, MA_OWNED);
410 	udev = y;
411 	LIST_FOREACH(si2, &csw->d_devs, si_list) {
412 		if (si2->si_drv0 == udev) {
413 			freedev(si);
414 			return (si2);
415 		}
416 	}
417 	si->si_drv0 = udev;
418 	LIST_INSERT_HEAD(&csw->d_devs, si, si_list);
419 	return (si);
420 }
421 
422 static void
423 freedev(struct cdev *dev)
424 {
425 
426 	if (dev->si_cred != NULL)
427 		crfree(dev->si_cred);
428 	free(dev, M_DEVT);
429 }
430 
431 int
432 uminor(dev_t dev)
433 {
434 	return (dev & MAXMINOR);
435 }
436 
437 int
438 umajor(dev_t dev)
439 {
440 	return ((dev & ~MAXMINOR) >> 8);
441 }
442 
443 static void
444 fini_cdevsw(struct cdevsw *devsw)
445 {
446 	struct cdevsw *gt;
447 
448 	if (devsw->d_gianttrick != NULL) {
449 		gt = devsw->d_gianttrick;
450 		memcpy(devsw, gt, sizeof *devsw);
451 		free(gt, M_DEVT);
452 		devsw->d_gianttrick = NULL;
453 	}
454 	devsw->d_flags &= ~D_INIT;
455 }
456 
457 static void
458 prep_cdevsw(struct cdevsw *devsw)
459 {
460 	struct cdevsw *dsw2;
461 
462 	if (devsw->d_flags & D_NEEDGIANT)
463 		dsw2 = malloc(sizeof *dsw2, M_DEVT, M_WAITOK);
464 	else
465 		dsw2 = NULL;
466 	dev_lock();
467 
468 	if (devsw->d_version != D_VERSION_01) {
469 		printf(
470 		    "WARNING: Device driver \"%s\" has wrong version %s\n",
471 		    devsw->d_name, "and is disabled.  Recompile KLD module.");
472 		devsw->d_open = dead_open;
473 		devsw->d_close = dead_close;
474 		devsw->d_read = dead_read;
475 		devsw->d_write = dead_write;
476 		devsw->d_ioctl = dead_ioctl;
477 		devsw->d_poll = dead_poll;
478 		devsw->d_mmap = dead_mmap;
479 		devsw->d_strategy = dead_strategy;
480 		devsw->d_dump = dead_dump;
481 		devsw->d_kqfilter = dead_kqfilter;
482 	}
483 
484 	if (devsw->d_flags & D_TTY) {
485 		if (devsw->d_ioctl == NULL)	devsw->d_ioctl = ttyioctl;
486 		if (devsw->d_read == NULL)	devsw->d_read = ttyread;
487 		if (devsw->d_write == NULL)	devsw->d_write = ttywrite;
488 		if (devsw->d_kqfilter == NULL)	devsw->d_kqfilter = ttykqfilter;
489 		if (devsw->d_poll == NULL)	devsw->d_poll = ttypoll;
490 	}
491 
492 	if (devsw->d_flags & D_NEEDGIANT) {
493 		if (devsw->d_gianttrick == NULL) {
494 			memcpy(dsw2, devsw, sizeof *dsw2);
495 			devsw->d_gianttrick = dsw2;
496 		} else
497 			free(dsw2, M_DEVT);
498 	}
499 
500 #define FIXUP(member, noop, giant) 				\
501 	do {							\
502 		if (devsw->member == NULL) {			\
503 			devsw->member = noop;			\
504 		} else if (devsw->d_flags & D_NEEDGIANT)	\
505 			devsw->member = giant;			\
506 		}						\
507 	while (0)
508 
509 	FIXUP(d_open,		null_open,	giant_open);
510 	FIXUP(d_fdopen,		NULL,		giant_fdopen);
511 	FIXUP(d_close,		null_close,	giant_close);
512 	FIXUP(d_read,		no_read,	giant_read);
513 	FIXUP(d_write,		no_write,	giant_write);
514 	FIXUP(d_ioctl,		no_ioctl,	giant_ioctl);
515 	FIXUP(d_poll,		no_poll,	giant_poll);
516 	FIXUP(d_mmap,		no_mmap,	giant_mmap);
517 	FIXUP(d_strategy,	no_strategy,	giant_strategy);
518 	FIXUP(d_kqfilter,	no_kqfilter,	giant_kqfilter);
519 
520 	if (devsw->d_dump == NULL)	devsw->d_dump = no_dump;
521 
522 	LIST_INIT(&devsw->d_devs);
523 
524 	devsw->d_flags |= D_INIT;
525 
526 	dev_unlock();
527 }
528 
529 static struct cdev *
530 make_dev_credv(struct cdevsw *devsw, int minornr, struct ucred *cr, uid_t uid,
531     gid_t gid, int mode, const char *fmt, va_list ap)
532 {
533 	struct cdev *dev;
534 	int i;
535 
536 	KASSERT((minornr & ~MAXMINOR) == 0,
537 	    ("Invalid minor (0x%x) in make_dev", minornr));
538 
539 	if (!(devsw->d_flags & D_INIT))
540 		prep_cdevsw(devsw);
541 	dev = allocdev();
542 	dev_lock();
543 	dev = newdev(devsw, minornr, dev);
544 	if (dev->si_flags & SI_CHEAPCLONE &&
545 	    dev->si_flags & SI_NAMED &&
546 	    dev->si_devsw == devsw) {
547 		/*
548 		 * This is allowed as it removes races and generally
549 		 * simplifies cloning devices.
550 		 * XXX: still ??
551 		 */
552 		dev_unlock();
553 		return (dev);
554 	}
555 	KASSERT(!(dev->si_flags & SI_NAMED),
556 	    ("make_dev() by driver %s on pre-existing device (min=%x, name=%s)",
557 	    devsw->d_name, minor(dev), devtoname(dev)));
558 
559 	i = vsnrprintf(dev->__si_namebuf, sizeof dev->__si_namebuf, 32, fmt, ap);
560 	if (i > (sizeof dev->__si_namebuf - 1)) {
561 		printf("WARNING: Device name truncated! (%s)\n",
562 		    dev->__si_namebuf);
563 	}
564 
565 	dev->si_devsw = devsw;
566 	dev->si_flags |= SI_NAMED;
567 	if (cr != NULL)
568 		dev->si_cred = crhold(cr);
569 	else
570 		dev->si_cred = NULL;
571 	dev->si_uid = uid;
572 	dev->si_gid = gid;
573 	dev->si_mode = mode;
574 
575 	devfs_create(dev);
576 	dev_unlock();
577 	return (dev);
578 }
579 
580 struct cdev *
581 make_dev(struct cdevsw *devsw, int minornr, uid_t uid, gid_t gid, int mode,
582     const char *fmt, ...)
583 {
584 	struct cdev *dev;
585 	va_list ap;
586 
587 	va_start(ap, fmt);
588 	dev = make_dev_credv(devsw, minornr, NULL, uid, gid, mode, fmt, ap);
589 	va_end(ap);
590 	return (dev);
591 }
592 
593 struct cdev *
594 make_dev_cred(struct cdevsw *devsw, int minornr, struct ucred *cr, uid_t uid,
595     gid_t gid, int mode, const char *fmt, ...)
596 {
597 	struct cdev *dev;
598 	va_list ap;
599 
600 	va_start(ap, fmt);
601 	dev = make_dev_credv(devsw, minornr, cr, uid, gid, mode, fmt, ap);
602 	va_end(ap);
603 
604 	return (dev);
605 }
606 
607 void
608 dev_depends(struct cdev *pdev, struct cdev *cdev)
609 {
610 
611 	dev_lock();
612 	cdev->si_parent = pdev;
613 	cdev->si_flags |= SI_CHILD;
614 	LIST_INSERT_HEAD(&pdev->si_children, cdev, si_siblings);
615 	dev_unlock();
616 }
617 
618 struct cdev *
619 make_dev_alias(struct cdev *pdev, const char *fmt, ...)
620 {
621 	struct cdev *dev;
622 	va_list ap;
623 	int i;
624 
625 	dev = allocdev();
626 	dev_lock();
627 	dev->si_flags |= SI_ALIAS;
628 	dev->si_flags |= SI_NAMED;
629 	va_start(ap, fmt);
630 	i = vsnrprintf(dev->__si_namebuf, sizeof dev->__si_namebuf, 32, fmt, ap);
631 	if (i > (sizeof dev->__si_namebuf - 1)) {
632 		printf("WARNING: Device name truncated! (%s)\n",
633 		    dev->__si_namebuf);
634 	}
635 	va_end(ap);
636 
637 	devfs_create(dev);
638 	dev_unlock();
639 	dev_depends(pdev, dev);
640 	return (dev);
641 }
642 
643 static void
644 destroy_devl(struct cdev *dev)
645 {
646 	struct cdevsw *csw;
647 
648 	mtx_assert(&devmtx, MA_OWNED);
649 	KASSERT(dev->si_flags & SI_NAMED,
650 	    ("WARNING: Driver mistake: destroy_dev on %d\n", minor(dev)));
651 
652 	devfs_destroy(dev);
653 
654 	/* Remove name marking */
655 	dev->si_flags &= ~SI_NAMED;
656 
657 	/* If we are a child, remove us from the parents list */
658 	if (dev->si_flags & SI_CHILD) {
659 		LIST_REMOVE(dev, si_siblings);
660 		dev->si_flags &= ~SI_CHILD;
661 	}
662 
663 	/* Kill our children */
664 	while (!LIST_EMPTY(&dev->si_children))
665 		destroy_devl(LIST_FIRST(&dev->si_children));
666 
667 	/* Remove from clone list */
668 	if (dev->si_flags & SI_CLONELIST) {
669 		LIST_REMOVE(dev, si_clone);
670 		dev->si_flags &= ~SI_CLONELIST;
671 	}
672 
673 	csw = dev->si_devsw;
674 	dev->si_devsw = NULL;	/* already NULL for SI_ALIAS */
675 	while (csw != NULL && csw->d_purge != NULL && dev->si_threadcount) {
676 		printf("Purging %lu threads from %s\n",
677 		    dev->si_threadcount, devtoname(dev));
678 		csw->d_purge(dev);
679 		msleep(csw, &devmtx, PRIBIO, "devprg", hz/10);
680 	}
681 	if (csw != NULL && csw->d_purge != NULL)
682 		printf("All threads purged from %s\n", devtoname(dev));
683 
684 	dev->si_drv1 = 0;
685 	dev->si_drv2 = 0;
686 	bzero(&dev->__si_u, sizeof(dev->__si_u));
687 
688 	if (!(dev->si_flags & SI_ALIAS)) {
689 		/* Remove from cdevsw list */
690 		LIST_REMOVE(dev, si_list);
691 
692 		/* If cdevsw has no struct cdev *'s, clean it */
693 		if (LIST_EMPTY(&csw->d_devs))
694 			fini_cdevsw(csw);
695 	}
696 	dev->si_flags &= ~SI_ALIAS;
697 
698 	if (dev->si_refcount > 0) {
699 		LIST_INSERT_HEAD(&dead_cdevsw.d_devs, dev, si_list);
700 	} else {
701 		freedev(dev);
702 	}
703 }
704 
705 void
706 destroy_dev(struct cdev *dev)
707 {
708 
709 	dev_lock();
710 	destroy_devl(dev);
711 	dev_unlock();
712 }
713 
714 const char *
715 devtoname(struct cdev *dev)
716 {
717 	char *p;
718 	struct cdevsw *csw;
719 	int mynor;
720 
721 	if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') {
722 		p = dev->si_name;
723 		csw = dev_refthread(dev);
724 		if (csw != NULL) {
725 			sprintf(p, "(%s)", csw->d_name);
726 			dev_relthread(dev);
727 		}
728 		p += strlen(p);
729 		mynor = minor(dev);
730 		if (mynor < 0 || mynor > 255)
731 			sprintf(p, "/%#x", (u_int)mynor);
732 		else
733 			sprintf(p, "/%d", mynor);
734 	}
735 	return (dev->si_name);
736 }
737 
738 int
739 dev_stdclone(char *name, char **namep, const char *stem, int *unit)
740 {
741 	int u, i;
742 
743 	i = strlen(stem);
744 	if (bcmp(stem, name, i) != 0)
745 		return (0);
746 	if (!isdigit(name[i]))
747 		return (0);
748 	u = 0;
749 	if (name[i] == '0' && isdigit(name[i+1]))
750 		return (0);
751 	while (isdigit(name[i])) {
752 		u *= 10;
753 		u += name[i++] - '0';
754 	}
755 	if (u > 0xffffff)
756 		return (0);
757 	*unit = u;
758 	if (namep)
759 		*namep = &name[i];
760 	if (name[i])
761 		return (2);
762 	return (1);
763 }
764 
765 /*
766  * Helper functions for cloning device drivers.
767  *
768  * The objective here is to make it unnecessary for the device drivers to
769  * use rman or similar to manage their unit number space.  Due to the way
770  * we do "on-demand" devices, using rman or other "private" methods
771  * will be very tricky to lock down properly once we lock down this file.
772  *
773  * Instead we give the drivers these routines which puts the struct cdev *'s
774  * that are to be managed on their own list, and gives the driver the ability
775  * to ask for the first free unit number or a given specified unit number.
776  *
777  * In addition these routines support paired devices (pty, nmdm and similar)
778  * by respecting a number of "flag" bits in the minor number.
779  *
780  */
781 
782 struct clonedevs {
783 	LIST_HEAD(,cdev)	head;
784 };
785 
786 void
787 clone_setup(struct clonedevs **cdp)
788 {
789 
790 	*cdp = malloc(sizeof **cdp, M_DEVBUF, M_WAITOK | M_ZERO);
791 	LIST_INIT(&(*cdp)->head);
792 }
793 
794 int
795 clone_create(struct clonedevs **cdp, struct cdevsw *csw, int *up, struct cdev **dp, u_int extra)
796 {
797 	struct clonedevs *cd;
798 	struct cdev *dev, *ndev, *dl, *de;
799 	int unit, low, u;
800 
801 	KASSERT(*cdp != NULL,
802 	    ("clone_setup() not called in driver \"%s\"", csw->d_name));
803 	KASSERT(!(extra & CLONE_UNITMASK),
804 	    ("Illegal extra bits (0x%x) in clone_create", extra));
805 	KASSERT(*up <= CLONE_UNITMASK,
806 	    ("Too high unit (0x%x) in clone_create", *up));
807 
808 	if (!(csw->d_flags & D_INIT))
809 		prep_cdevsw(csw);
810 
811 	/*
812 	 * Search the list for a lot of things in one go:
813 	 *   A preexisting match is returned immediately.
814 	 *   The lowest free unit number if we are passed -1, and the place
815 	 *	 in the list where we should insert that new element.
816 	 *   The place to insert a specified unit number, if applicable
817 	 *       the end of the list.
818 	 */
819 	unit = *up;
820 	ndev = allocdev();
821 	dev_lock();
822 	low = extra;
823 	de = dl = NULL;
824 	cd = *cdp;
825 	LIST_FOREACH(dev, &cd->head, si_clone) {
826 		KASSERT(dev->si_flags & SI_CLONELIST,
827 		    ("Dev %p(%s) should be on clonelist", dev, dev->si_name));
828 		u = dev2unit(dev);
829 		if (u == (unit | extra)) {
830 			*dp = dev;
831 			freedev(ndev);
832 			dev_unlock();
833 			return (0);
834 		}
835 		if (unit == -1 && u == low) {
836 			low++;
837 			de = dev;
838 			continue;
839 		}
840 		if (u > (unit | extra)) {
841 			dl = dev;
842 			break;
843 		}
844 	}
845 	if (unit == -1)
846 		unit = low & CLONE_UNITMASK;
847 	dev = newdev(csw, unit2minor(unit | extra), ndev);
848 	if (dev->si_flags & SI_CLONELIST) {
849 		printf("dev %p (%s) is on clonelist\n", dev, dev->si_name);
850 		printf("unit=%d\n", unit);
851 		LIST_FOREACH(dev, &cd->head, si_clone) {
852 			printf("\t%p %s\n", dev, dev->si_name);
853 		}
854 		panic("foo");
855 	}
856 	KASSERT(!(dev->si_flags & SI_CLONELIST),
857 	    ("Dev %p(%s) should not be on clonelist", dev, dev->si_name));
858 	if (dl != NULL)
859 		LIST_INSERT_BEFORE(dl, dev, si_clone);
860 	else if (de != NULL)
861 		LIST_INSERT_AFTER(de, dev, si_clone);
862 	else
863 		LIST_INSERT_HEAD(&cd->head, dev, si_clone);
864 	dev->si_flags |= SI_CLONELIST;
865 	*up = unit;
866 	dev_unlock();
867 	return (1);
868 }
869 
870 /*
871  * Kill everything still on the list.  The driver should already have
872  * disposed of any softc hung of the struct cdev *'s at this time.
873  */
874 void
875 clone_cleanup(struct clonedevs **cdp)
876 {
877 	struct cdev *dev, *tdev;
878 	struct clonedevs *cd;
879 
880 	cd = *cdp;
881 	if (cd == NULL)
882 		return;
883 	dev_lock();
884 	LIST_FOREACH_SAFE(dev, &cd->head, si_clone, tdev) {
885 		KASSERT(dev->si_flags & SI_CLONELIST,
886 		    ("Dev %p(%s) should be on clonelist", dev, dev->si_name));
887 		KASSERT(dev->si_flags & SI_NAMED,
888 		    ("Driver has goofed in cloning underways udev %x", dev->si_drv0));
889 		destroy_devl(dev);
890 	}
891 	dev_unlock();
892 	free(cd, M_DEVBUF);
893 	*cdp = NULL;
894 }
895