kern_conf.c revision 135726
121308Sache/*-
221308Sache * Copyright (c) 1999-2002 Poul-Henning Kamp
3157184Sache * All rights reserved.
421308Sache *
521308Sache * Redistribution and use in source and binary forms, with or without
621308Sache * modification, are permitted provided that the following conditions
721308Sache * are met:
821308Sache * 1. Redistributions of source code must retain the above copyright
921308Sache *    notice, this list of conditions and the following disclaimer.
1058310Sache * 2. Redistributions in binary form must reproduce the above copyright
1121308Sache *    notice, this list of conditions and the following disclaimer in the
1221308Sache *    documentation and/or other materials provided with the distribution.
1321308Sache *
1421308Sache * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1521308Sache * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1621308Sache * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1721308Sache * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1821308Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1921308Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2021308Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2158310Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2221308Sache * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2321308Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2421308Sache * SUCH DAMAGE.
2521308Sache */
2621308Sache
2721308Sache#include <sys/cdefs.h>
2821308Sache__FBSDID("$FreeBSD: head/sys/kern/kern_conf.c 135726 2004-09-24 08:30:57Z phk $");
2921308Sache
3021308Sache#include <sys/param.h>
3121308Sache#include <sys/kernel.h>
3221308Sache#include <sys/systm.h>
3321308Sache#include <sys/bio.h>
3421308Sache#include <sys/lock.h>
3521308Sache#include <sys/mutex.h>
3621308Sache#include <sys/sysctl.h>
3721308Sache#include <sys/module.h>
3821308Sache#include <sys/malloc.h>
3921308Sache#include <sys/conf.h>
4021308Sache#include <sys/vnode.h>
4121308Sache#include <sys/queue.h>
4221308Sache#include <sys/poll.h>
4321308Sache#include <sys/ctype.h>
4421308Sache#include <sys/tty.h>
4521308Sache#include <machine/stdarg.h>
4621308Sache
4721308Sachestatic MALLOC_DEFINE(M_DEVT, "cdev", "cdev storage");
4858310Sache
4958310Sache/* Built at compile time from sys/conf/majors */
5021308Sacheextern unsigned char reserved_majors[256];
5121308Sache
5221308Sache/*
5321308Sache * This is the number of hash-buckets.  Experiments with 'real-life'
5421308Sache * dev_t's show that a prime halfway between two powers of two works
5521308Sache * best.
5621308Sache */
5721308Sache#define DEVT_HASH 83
5821308Sache
5921308Sache/* The number of struct cdev *'s we can create before malloc(9) kick in.  */
6021308Sache#define DEVT_STASH 50
6121308Sache
6221308Sachestatic struct cdev devt_stash[DEVT_STASH];
6321308Sache
6475406Sachestatic LIST_HEAD(, cdev) dev_hash[DEVT_HASH];
6521308Sache
6621308Sachestatic LIST_HEAD(, cdev) dev_free;
6721308Sache
6858310Sachestatic int free_devt;
6958310SacheSYSCTL_INT(_debug, OID_AUTO, free_devt, CTLFLAG_RW, &free_devt, 0, "");
7058310Sache
7158310Sachestatic struct mtx devmtx;
7258310Sachestatic void freedev(struct cdev *dev);
7358310Sachestatic struct cdev *newdev(int x, int y);
7458310Sache
7547558Sache
76136644Sachevoid
77136644Sachedev_lock(void)
78136644Sache{
79136644Sache	if (!mtx_initialized(&devmtx))
80119610Sache		mtx_init(&devmtx, "cdev", NULL, MTX_DEF);
81119610Sache	mtx_lock(&devmtx);
8247558Sache}
8347558Sache
8447558Sachevoid
8547558Sachedev_unlock(void)
8647558Sache{
8747558Sache
8847558Sache	mtx_unlock(&devmtx);
8947558Sache}
9047558Sache
9147558Sachevoid
92136644Sachedev_ref(struct cdev *dev)
93136644Sache{
9447558Sache
9547558Sache	dev_lock();
9647558Sache	dev->si_refcount++;
9747558Sache	dev_unlock();
9847558Sache}
9921308Sache
10021308Sachevoid
10121308Sachedev_rel(struct cdev *dev)
10221308Sache{
10321308Sache
10421308Sache	dev->si_refcount--;
10547558Sache	KASSERT(dev->si_refcount >= 0,
10647558Sache	    ("dev_rel(%s) gave negative count", devtoname(dev)));
10726497Sache	if (dev->si_devsw == NULL && dev->si_refcount == 0) {
10826497Sache		LIST_REMOVE(dev, si_list);
10921308Sache		freedev(dev);
11021308Sache	}
11121308Sache}
11221308Sachestruct cdevsw *
11321308Sachedev_refthread(struct cdev *dev)
11421308Sache{
11521308Sache	struct cdevsw *csw;
11621308Sache
11721308Sache	mtx_assert(&devmtx, MA_NOTOWNED);
11821308Sache	dev_lock();
11921308Sache	csw = dev->si_devsw;
12021308Sache	if (csw != NULL)
12121308Sache		dev->si_threadcount++;
12221308Sache	dev_unlock();
12321308Sache	return (csw);
12426497Sache}
12526497Sache
12626497Sachevoid
12721308Sachedev_relthread(struct cdev *dev)
12821308Sache{
12975406Sache
13075406Sache	mtx_assert(&devmtx, MA_NOTOWNED);
13121308Sache	dev_lock();
13221308Sache	dev->si_threadcount--;
13321308Sache	dev_unlock();
134157184Sache}
13521308Sache
136157184Sacheint
137157184Sachenullop(void)
138157184Sache{
13926497Sache
14021308Sache	return (0);
14121308Sache}
14221308Sache
14321308Sacheint
14421308Sacheeopnotsupp(void)
14547558Sache{
14647558Sache
14721308Sache	return (EOPNOTSUPP);
148157184Sache}
14921308Sache
15021308Sachestatic int
15121308Sacheenxio(void)
15221308Sache{
15321308Sache	return (ENXIO);
154157184Sache}
15521308Sache
156157184Sachestatic int
157157184Sacheenodev(void)
15847558Sache{
159157184Sache	return (ENODEV);
16047558Sache}
16121308Sache
16221308Sache/* Define a dead_cdevsw for use when devices leave unexpectedly. */
163165670Sache
16421308Sache#define dead_open	(d_open_t *)enxio
16521308Sache#define dead_close	(d_close_t *)enxio
16621308Sache#define dead_read	(d_read_t *)enxio
16721308Sache#define dead_write	(d_write_t *)enxio
16821308Sache#define dead_ioctl	(d_ioctl_t *)enxio
16921308Sache#define dead_poll	(d_poll_t *)enodev
17021308Sache#define dead_mmap	(d_mmap_t *)enodev
17121308Sache
17258310Sachestatic void
17358310Sachedead_strategy(struct bio *bp)
17458310Sache{
17558310Sache
176157184Sache	biofinish(bp, NULL, ENXIO);
17721308Sache}
178157184Sache
179157184Sache#define dead_dump	(dumper_t *)enxio
180157184Sache#define dead_kqfilter	(d_kqfilter_t *)enxio
18121308Sache
18221308Sachestatic struct cdevsw dead_cdevsw = {
18321308Sache	.d_version =	D_VERSION,
18421308Sache	.d_flags =	D_NEEDGIANT, /* XXX: does dead_strategy need this ? */
18521308Sache	.d_open =	dead_open,
18621308Sache	.d_close =	dead_close,
18721308Sache	.d_read =	dead_read,
18821308Sache	.d_write =	dead_write,
18921308Sache	.d_ioctl =	dead_ioctl,
19021308Sache	.d_poll =	dead_poll,
19147558Sache	.d_mmap =	dead_mmap,
19221308Sache	.d_strategy =	dead_strategy,
19321308Sache	.d_name =	"dead",
19475406Sache	.d_maj =	255,
19521308Sache	.d_dump =	dead_dump,
19621308Sache	.d_kqfilter =	dead_kqfilter
19721308Sache};
19821308Sache
19921308Sache/* Default methods if driver does not specify method */
20047558Sache
20121308Sache#define null_open	(d_open_t *)nullop
20221308Sache#define null_close	(d_close_t *)nullop
20321308Sache#define no_read		(d_read_t *)enodev
20421308Sache#define no_write	(d_write_t *)enodev
20526497Sache#define no_ioctl	(d_ioctl_t *)enodev
20626497Sache#define no_mmap		(d_mmap_t *)enodev
20726497Sache#define no_kqfilter	(d_kqfilter_t *)enodev
20826497Sache
20926497Sachestatic void
21026497Sacheno_strategy(struct bio *bp)
21126497Sache{
21247558Sache
21326497Sache	biofinish(bp, NULL, ENODEV);
21426497Sache}
21575406Sache
21647558Sachestatic int
21721308Sacheno_poll(struct cdev *dev __unused, int events, struct thread *td __unused)
21821308Sache{
21921308Sache	/*
22021308Sache	 * Return true for read/write.  If the user asked for something
22121308Sache	 * special, return POLLNVAL, so that clients have a way of
22221308Sache	 * determining reliably whether or not the extended
22375406Sache	 * functionality is present without hard-coding knowledge
22421308Sache	 * of specific filesystem implementations.
22521308Sache	 * Stay in sync with vop_nopoll().
22621308Sache	 */
22721308Sache	if (events & ~POLLSTANDARD)
22821308Sache		return (POLLNVAL);
22921308Sache
23021308Sache	return (events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
23121308Sache}
23221308Sache
23321308Sache#define no_dump		(dumper_t *)enodev
23421308Sache
23521308Sache/*
23621308Sache * struct cdev * and u_dev_t primitives
23721308Sache */
23821308Sache
23921308Sacheint
24021308Sachemajor(struct cdev *x)
24121308Sache{
24221308Sache	if (x == NULL)
24321308Sache		return NODEV;
24421308Sache	return((x->si_udev >> 8) & 0xff);
24521308Sache}
24621308Sache
24721308Sacheint
24821308Sacheminor(struct cdev *x)
24921308Sache{
25058310Sache	if (x == NULL)
25121308Sache		return NODEV;
25221308Sache	return(x->si_udev & 0xffff00ff);
25321308Sache}
25421308Sache
255136644Sacheint
25621308Sachedev2unit(struct cdev *x)
25721308Sache{
25858310Sache	int i;
25921308Sache
26058310Sache	if (x == NULL)
26121308Sache		return NODEV;
26258310Sache	i = minor(x);
26358310Sache	return ((i & 0xff) | (i >> 8));
26458310Sache}
26558310Sache
26658310Sacheint
26758310Sacheunit2minor(int unit)
26858310Sache{
26921308Sache
27021308Sache	KASSERT(unit <= 0xffffff, ("Invalid unit (%d) in unit2minor", unit));
27121308Sache	return ((unit & 0xff) | ((unit << 8) & ~0xffff));
27247558Sache}
27347558Sache
27447558Sachestatic struct cdev *
27547558Sacheallocdev(void)
27647558Sache{
27747558Sache	static int stashed;
27847558Sache	struct cdev *si;
27947558Sache
28047558Sache	if (LIST_FIRST(&dev_free)) {
28147558Sache		si = LIST_FIRST(&dev_free);
28247558Sache		LIST_REMOVE(si, si_hash);
28347558Sache	} else if (stashed >= DEVT_STASH) {
28447558Sache		MALLOC(si, struct cdev *, sizeof(*si), M_DEVT,
28547558Sache		    M_USE_RESERVE | M_ZERO | M_WAITOK);
28647558Sache	} else {
28721308Sache		si = devt_stash + stashed++;
28821308Sache		bzero(si, sizeof *si);
28921308Sache		si->si_flags |= SI_STASHED;
29021308Sache	}
29121308Sache	si->__si_namebuf[0] = '\0';
292165670Sache	si->si_name = si->__si_namebuf;
293165670Sache	LIST_INIT(&si->si_children);
294165670Sache	return (si);
295165670Sache}
29621308Sache
297165670Sachestatic struct cdev *
298165670Sachenewdev(int x, int y)
299165670Sache{
300165670Sache	struct cdev *si;
301165670Sache	dev_t	udev;
302165670Sache	int hash;
303165670Sache
304165670Sache	if (x == umajor(NODEV) && y == uminor(NODEV))
305165670Sache		panic("newdev of NODEV");
306165670Sache	udev = (x << 8) | y;
307165670Sache	hash = udev % DEVT_HASH;
308165670Sache	LIST_FOREACH(si, &dev_hash[hash], si_hash) {
309165670Sache		if (si->si_udev == udev)
310165670Sache			return (si);
311165670Sache	}
312165670Sache	si = allocdev();
313165670Sache	si->si_udev = udev;
314165670Sache	LIST_INSERT_HEAD(&dev_hash[hash], si, si_hash);
315165670Sache	return (si);
316165670Sache}
317165670Sache
318165670Sachestatic void
319165670Sachefreedev(struct cdev *dev)
320165670Sache{
321165670Sache
322165670Sache	if (dev->si_flags & SI_STASHED) {
32347558Sache		bzero(dev, sizeof(*dev));
32447558Sache		dev->si_flags |= SI_STASHED;
325165670Sache		LIST_INSERT_HEAD(&dev_free, dev, si_hash);
326165670Sache	} else {
327165670Sache		FREE(dev, M_DEVT);
328165670Sache	}
329165670Sache}
33047558Sache
33147558Sachedev_t
332157184Sachedev2udev(struct cdev *x)
33347558Sache{
334157184Sache	if (x == NULL)
33521308Sache		return (NODEV);
336157184Sache	return (x->si_udev);
33747558Sache}
33847558Sache
33947558Sachestruct cdev *
34021308Sachefindcdev(dev_t udev)
34147558Sache{
34247558Sache	struct cdev *si;
34347558Sache	int hash;
34447558Sache
34547558Sache	if (udev == NODEV)
34647558Sache		return (NULL);
34721308Sache	hash = udev % DEVT_HASH;
348157184Sache	LIST_FOREACH(si, &dev_hash[hash], si_hash) {
34921308Sache		if (si->si_udev == udev)
35021308Sache			return (si);
35147558Sache	}
35221308Sache	return (NULL);
35321308Sache}
35421308Sache
35547558Sacheint
35621308Sacheuminor(dev_t dev)
35721308Sache{
35847558Sache	return (dev & 0xffff00ff);
35947558Sache}
36047558Sache
36126497Sacheint
36247558Sacheumajor(dev_t dev)
363165670Sache{
364165670Sache	return ((dev & 0xff00) >> 8);
365165670Sache}
366165670Sache
36747558Sachestatic void
36821308Sachefind_major(struct cdevsw *devsw)
36921308Sache{
37047558Sache	int i;
37147558Sache
37247558Sache	for (i = NUMCDEVSW - 1; i > 0; i--)
37347558Sache		if (reserved_majors[i] != i)
37447558Sache			break;
37521308Sache	KASSERT(i > 0, ("Out of major numbers (%s)", devsw->d_name));
37621308Sache	devsw->d_maj = i;
37721308Sache	reserved_majors[i] = i;
37821308Sache	devsw->d_flags |= D_ALLOCMAJ;
37921308Sache}
38021308Sache
38121308Sachestatic void
38221308Sachefini_cdevsw(struct cdevsw *devsw)
38321308Sache{
38421308Sache	if (devsw->d_flags & D_ALLOCMAJ) {
38547558Sache		reserved_majors[devsw->d_maj] = 0;
38647558Sache		devsw->d_maj = MAJOR_AUTO;
38747558Sache		devsw->d_flags &= ~D_ALLOCMAJ;
38821308Sache	} else if (devsw->d_maj == 0)
38947558Sache		devsw->d_maj = 256;
39047558Sache	devsw->d_flags &= ~D_INIT;
391157184Sache}
39247558Sache
393157184Sachestatic void
394157184Sacheprep_cdevsw(struct cdevsw *devsw)
39547558Sache{
396157184Sache
39721308Sache	dev_lock();
39821308Sache
39947558Sache	if (devsw->d_version != D_VERSION_00) {
40047558Sache		printf(
40121308Sache		    "WARNING: Device driver \"%s\" has wrong version %s\n",
40221308Sache		    devsw->d_name, "and is disabled.  Recompile KLD module.");
40347558Sache		devsw->d_open = dead_open;
40421308Sache		devsw->d_close = dead_close;
40521308Sache		devsw->d_read = dead_read;
40647558Sache		devsw->d_write = dead_write;
40747558Sache		devsw->d_ioctl = dead_ioctl;
40847558Sache		devsw->d_poll = dead_poll;
40926497Sache		devsw->d_mmap = dead_mmap;
41047558Sache		devsw->d_strategy = dead_strategy;
41147558Sache		devsw->d_dump = dead_dump;
41221308Sache		devsw->d_kqfilter = dead_kqfilter;
41321308Sache	}
41447558Sache
41547558Sache	if (devsw->d_flags & D_TTY) {
41647558Sache		if (devsw->d_ioctl == NULL)	devsw->d_ioctl = ttyioctl;
41747558Sache		if (devsw->d_read == NULL)	devsw->d_read = ttyread;
41847558Sache		if (devsw->d_write == NULL)	devsw->d_write = ttywrite;
41947558Sache		if (devsw->d_kqfilter == NULL)	devsw->d_kqfilter = ttykqfilter;
42021308Sache		if (devsw->d_poll == NULL)	devsw->d_poll = ttypoll;
42121308Sache	}
42221308Sache
42321308Sache	if (devsw->d_open == NULL)	devsw->d_open = null_open;
42447558Sache	if (devsw->d_close == NULL)	devsw->d_close = null_close;
42547558Sache	if (devsw->d_read == NULL)	devsw->d_read = no_read;
42647558Sache	if (devsw->d_write == NULL)	devsw->d_write = no_write;
42747558Sache	if (devsw->d_ioctl == NULL)	devsw->d_ioctl = no_ioctl;
42847558Sache	if (devsw->d_poll == NULL)	devsw->d_poll = no_poll;
42947558Sache	if (devsw->d_mmap == NULL)	devsw->d_mmap = no_mmap;
43047558Sache	if (devsw->d_strategy == NULL)	devsw->d_strategy = no_strategy;
431157184Sache	if (devsw->d_dump == NULL)	devsw->d_dump = no_dump;
432157184Sache	if (devsw->d_kqfilter == NULL)	devsw->d_kqfilter = no_kqfilter;
433165670Sache
43447558Sache	LIST_INIT(&devsw->d_devs);
43547558Sache
43647558Sache	devsw->d_flags |= D_INIT;
43747558Sache
43847558Sache	if (devsw->d_maj == MAJOR_AUTO) {
43947558Sache		find_major(devsw);
44047558Sache	} else {
441157184Sache		if (devsw->d_maj == 256)	/* XXX: tty_cons.c is magic */
442157184Sache			devsw->d_maj = 0;
44347558Sache		KASSERT(devsw->d_maj >= 0 && devsw->d_maj < 256,
44447558Sache		    ("Invalid major (%d) in make_dev", devsw->d_maj));
44547558Sache		if (reserved_majors[devsw->d_maj] != devsw->d_maj) {
44647558Sache			printf("WARNING: driver \"%s\" used %s %d\n",
44747558Sache			    devsw->d_name, "unreserved major device number",
44847558Sache			    devsw->d_maj);
44947558Sache			reserved_majors[devsw->d_maj] = devsw->d_maj;
45047558Sache		}
45147558Sache	}
45247558Sache	dev_unlock();
45347558Sache}
45447558Sache
45575406Sachestruct cdev *
45647558Sachemake_dev(struct cdevsw *devsw, int minornr, uid_t uid, gid_t gid, int perms, const char *fmt, ...)
45747558Sache{
45847558Sache	struct cdev *dev;
45947558Sache	va_list ap;
46047558Sache	int i;
46147558Sache
46247558Sache	KASSERT((minornr & ~0xffff00ff) == 0,
463157184Sache	    ("Invalid minor (0x%x) in make_dev", minornr));
46447558Sache
46547558Sache	if (!(devsw->d_flags & D_INIT))
46621308Sache		prep_cdevsw(devsw);
467	dev = newdev(devsw->d_maj, minornr);
468	if (dev->si_flags & SI_CHEAPCLONE &&
469	    dev->si_flags & SI_NAMED &&
470	    dev->si_devsw == devsw) {
471		/*
472		 * This is allowed as it removes races and generally
473		 * simplifies cloning devices.
474		 * XXX: still ??
475		 */
476		return (dev);
477	}
478	dev_lock();
479	KASSERT(!(dev->si_flags & SI_NAMED),
480	    ("make_dev() by driver %s on pre-existing device (maj=%d, min=%d, name=%s)",
481	    devsw->d_name, major(dev), minor(dev), devtoname(dev)));
482
483	va_start(ap, fmt);
484	i = vsnrprintf(dev->__si_namebuf, sizeof dev->__si_namebuf, 32, fmt, ap);
485	if (i > (sizeof dev->__si_namebuf - 1)) {
486		printf("WARNING: Device name truncated! (%s)\n",
487		    dev->__si_namebuf);
488	}
489	va_end(ap);
490	dev->si_devsw = devsw;
491	dev->si_uid = uid;
492	dev->si_gid = gid;
493	dev->si_mode = perms;
494	dev->si_flags |= SI_NAMED;
495
496	LIST_INSERT_HEAD(&devsw->d_devs, dev, si_list);
497	devfs_create(dev);
498	dev_unlock();
499	return (dev);
500}
501
502int
503dev_named(struct cdev *pdev, const char *name)
504{
505	struct cdev *cdev;
506
507	if (strcmp(devtoname(pdev), name) == 0)
508		return (1);
509	LIST_FOREACH(cdev, &pdev->si_children, si_siblings)
510		if (strcmp(devtoname(cdev), name) == 0)
511			return (1);
512	return (0);
513}
514
515void
516dev_depends(struct cdev *pdev, struct cdev *cdev)
517{
518
519	dev_lock();
520	cdev->si_parent = pdev;
521	cdev->si_flags |= SI_CHILD;
522	LIST_INSERT_HEAD(&pdev->si_children, cdev, si_siblings);
523	dev_unlock();
524}
525
526struct cdev *
527make_dev_alias(struct cdev *pdev, const char *fmt, ...)
528{
529	struct cdev *dev;
530	va_list ap;
531	int i;
532
533	dev = allocdev();
534	dev_lock();
535	dev->si_flags |= SI_ALIAS;
536	dev->si_flags |= SI_NAMED;
537	va_start(ap, fmt);
538	i = vsnrprintf(dev->__si_namebuf, sizeof dev->__si_namebuf, 32, fmt, ap);
539	if (i > (sizeof dev->__si_namebuf - 1)) {
540		printf("WARNING: Device name truncated! (%s)\n",
541		    dev->__si_namebuf);
542	}
543	va_end(ap);
544
545	devfs_create(dev);
546	dev_unlock();
547	dev_depends(pdev, dev);
548	return (dev);
549}
550
551static void
552idestroy_dev(struct cdev *dev)
553{
554	if (!(dev->si_flags & SI_NAMED)) {
555		printf( "WARNING: Driver mistake: destroy_dev on %d/%d\n",
556		    major(dev), minor(dev));
557		panic("don't do that");
558	}
559
560	devfs_destroy(dev);
561
562	/* Remove name marking */
563	dev->si_flags &= ~SI_NAMED;
564
565	/* If we are a child, remove us from the parents list */
566	if (dev->si_flags & SI_CHILD) {
567		LIST_REMOVE(dev, si_siblings);
568		dev->si_flags &= ~SI_CHILD;
569	}
570
571	/* Kill our children */
572	while (!LIST_EMPTY(&dev->si_children))
573		idestroy_dev(LIST_FIRST(&dev->si_children));
574
575	/* Remove from clone list */
576	if (dev->si_flags & SI_CLONELIST) {
577		LIST_REMOVE(dev, si_clone);
578		dev->si_flags &= ~SI_CLONELIST;
579	}
580
581	if (!(dev->si_flags & SI_ALIAS)) {
582		/* Remove from cdevsw list */
583		LIST_REMOVE(dev, si_list);
584
585		/* If cdevsw has no struct cdev *'s, clean it */
586		if (LIST_EMPTY(&dev->si_devsw->d_devs))
587			fini_cdevsw(dev->si_devsw);
588
589		LIST_REMOVE(dev, si_hash);
590	}
591	dev->si_drv1 = 0;
592	dev->si_drv2 = 0;
593	dev->si_devsw = NULL;
594	bzero(&dev->__si_u, sizeof(dev->__si_u));
595	dev->si_flags &= ~SI_ALIAS;
596	if (dev->si_refcount > 0) {
597		LIST_INSERT_HEAD(&dead_cdevsw.d_devs, dev, si_list);
598	} else {
599		freedev(dev);
600	}
601}
602
603void
604destroy_dev(struct cdev *dev)
605{
606
607	dev_lock();
608	idestroy_dev(dev);
609	dev_unlock();
610}
611
612const char *
613devtoname(struct cdev *dev)
614{
615	char *p;
616	struct cdevsw *csw;
617	int mynor;
618
619	if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') {
620		p = dev->si_name;
621		sprintf(p, "#%d", major(dev));
622		p += strlen(p);
623		csw = dev_refthread(dev);
624		if (csw != NULL) {
625			sprintf(p, "(%s)", csw->d_name);
626			dev_relthread(dev);
627		}
628		p += strlen(p);
629		mynor = minor(dev);
630		if (mynor < 0 || mynor > 255)
631			sprintf(p, "/%#x", (u_int)mynor);
632		else
633			sprintf(p, "/%d", mynor);
634	}
635	return (dev->si_name);
636}
637
638int
639dev_stdclone(char *name, char **namep, const char *stem, int *unit)
640{
641	int u, i;
642
643	i = strlen(stem);
644	if (bcmp(stem, name, i) != 0)
645		return (0);
646	if (!isdigit(name[i]))
647		return (0);
648	u = 0;
649	if (name[i] == '0' && isdigit(name[i+1]))
650		return (0);
651	while (isdigit(name[i])) {
652		u *= 10;
653		u += name[i++] - '0';
654	}
655	if (u > 0xffffff)
656		return (0);
657	*unit = u;
658	if (namep)
659		*namep = &name[i];
660	if (name[i])
661		return (2);
662	return (1);
663}
664
665/*
666 * Helper functions for cloning device drivers.
667 *
668 * The objective here is to make it unnecessary for the device drivers to
669 * use rman or similar to manage their unit number space.  Due to the way
670 * we do "on-demand" devices, using rman or other "private" methods
671 * will be very tricky to lock down properly once we lock down this file.
672 *
673 * Instead we give the drivers these routines which puts the struct cdev *'s
674 * that are to be managed on their own list, and gives the driver the ability
675 * to ask for the first free unit number or a given specified unit number.
676 *
677 * In addition these routines support paired devices (pty, nmdm and similar)
678 * by respecting a number of "flag" bits in the minor number.
679 *
680 */
681
682struct clonedevs {
683	LIST_HEAD(,cdev)	head;
684};
685
686void
687clone_setup(struct clonedevs **cdp)
688{
689
690	*cdp = malloc(sizeof **cdp, M_DEVBUF, M_WAITOK | M_ZERO);
691	LIST_INIT(&(*cdp)->head);
692}
693
694int
695clone_create(struct clonedevs **cdp, struct cdevsw *csw, int *up, struct cdev **dp, u_int extra)
696{
697	struct clonedevs *cd;
698	struct cdev *dev, *dl, *de;
699	int unit, low, u;
700
701	KASSERT(*cdp != NULL,
702	    ("clone_setup() not called in driver \"%s\"", csw->d_name));
703	KASSERT(!(extra & CLONE_UNITMASK),
704	    ("Illegal extra bits (0x%x) in clone_create", extra));
705	KASSERT(*up <= CLONE_UNITMASK,
706	    ("Too high unit (0x%x) in clone_create", *up));
707
708	if (csw->d_maj == MAJOR_AUTO)
709		find_major(csw);
710
711	/*
712	 * Search the list for a lot of things in one go:
713	 *   A preexisting match is returned immediately.
714	 *   The lowest free unit number if we are passed -1, and the place
715	 *	 in the list where we should insert that new element.
716	 *   The place to insert a specified unit number, if applicable
717	 *       the end of the list.
718	 */
719	unit = *up;
720	low = extra;
721	de = dl = NULL;
722	cd = *cdp;
723	LIST_FOREACH(dev, &cd->head, si_clone) {
724		u = dev2unit(dev);
725		if (u == (unit | extra)) {
726			*dp = dev;
727			return (0);
728		}
729		if (unit == -1 && u == low) {
730			low++;
731			de = dev;
732			continue;
733		}
734		if (u > (unit | extra)) {
735			dl = dev;
736			break;
737		}
738		de = dev;
739	}
740	if (unit == -1)
741		unit = low & CLONE_UNITMASK;
742	dev = newdev(csw->d_maj, unit2minor(unit | extra));
743	KASSERT(!(dev->si_flags & SI_CLONELIST),
744	    ("Dev %p should not be on clonelist", dev));
745	if (dl != NULL)
746		LIST_INSERT_BEFORE(dl, dev, si_clone);
747	else if (de != NULL)
748		LIST_INSERT_AFTER(de, dev, si_clone);
749	else
750		LIST_INSERT_HEAD(&cd->head, dev, si_clone);
751	dev->si_flags |= SI_CLONELIST;
752	*up = unit;
753	return (1);
754}
755
756/*
757 * Kill everything still on the list.  The driver should already have
758 * disposed of any softc hung of the struct cdev *'s at this time.
759 */
760void
761clone_cleanup(struct clonedevs **cdp)
762{
763	struct cdev *dev, *tdev;
764	struct clonedevs *cd;
765
766	cd = *cdp;
767	if (cd == NULL)
768		return;
769	LIST_FOREACH_SAFE(dev, &cd->head, si_clone, tdev) {
770		KASSERT(dev->si_flags & SI_NAMED,
771		    ("Driver has goofed in cloning underways udev %x", dev->si_udev));
772		destroy_dev(dev);
773	}
774	free(cd, M_DEVBUF);
775	*cdp = NULL;
776}
777
778/*
779 * Helper sysctl for devname(3).  We're given a struct cdev * and return
780 * the name, if any, registered by the device driver.
781 */
782static int
783sysctl_devname(SYSCTL_HANDLER_ARGS)
784{
785	int error;
786	dev_t ud;
787	struct cdev *dev;
788
789	error = SYSCTL_IN(req, &ud, sizeof (ud));
790	if (error)
791		return (error);
792	if (ud == NODEV)
793		return(EINVAL);
794	dev = findcdev(ud);
795	if (dev == NULL)
796		error = ENOENT;
797	else
798		error = SYSCTL_OUT(req, dev->si_name, strlen(dev->si_name) + 1);
799	return (error);
800}
801
802SYSCTL_PROC(_kern, OID_AUTO, devname, CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY,
803	NULL, 0, sysctl_devname, "", "devname(3) handler");
804