xref: /freebsd/sys/kern/kern_conf.c (revision 8d25eb2c3a292113d6fd5b0f35ae3e3a40870a4f)
126453f35SJulian Elischer /*-
226453f35SJulian Elischer  * Parts Copyright (c) 1995 Terrence R. Lambert
326453f35SJulian Elischer  * Copyright (c) 1995 Julian R. Elischer
426453f35SJulian Elischer  * All rights reserved.
526453f35SJulian Elischer  *
626453f35SJulian Elischer  * Redistribution and use in source and binary forms, with or without
726453f35SJulian Elischer  * modification, are permitted provided that the following conditions
826453f35SJulian Elischer  * are met:
926453f35SJulian Elischer  * 1. Redistributions of source code must retain the above copyright
1026453f35SJulian Elischer  *    notice, this list of conditions and the following disclaimer.
1126453f35SJulian Elischer  * 2. Redistributions in binary form must reproduce the above copyright
1226453f35SJulian Elischer  *    notice, this list of conditions and the following disclaimer in the
1326453f35SJulian Elischer  *    documentation and/or other materials provided with the distribution.
1426453f35SJulian Elischer  * 3. All advertising materials mentioning features or use of this software
1526453f35SJulian Elischer  *    must display the following acknowledgement:
1626453f35SJulian Elischer  *      This product includes software developed by Terrence R. Lambert.
1726453f35SJulian Elischer  * 4. The name Terrence R. Lambert may not be used to endorse or promote
1826453f35SJulian Elischer  *    products derived from this software without specific prior written
1926453f35SJulian Elischer  *    permission.
2026453f35SJulian Elischer  *
2126453f35SJulian Elischer  * THIS SOFTWARE IS PROVIDED BY Julian R. Elischer ``AS IS'' AND ANY
2226453f35SJulian Elischer  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2326453f35SJulian Elischer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2426453f35SJulian Elischer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
2526453f35SJulian Elischer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2626453f35SJulian Elischer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2726453f35SJulian Elischer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2826453f35SJulian Elischer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2926453f35SJulian Elischer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3026453f35SJulian Elischer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3126453f35SJulian Elischer  * SUCH DAMAGE.
3226453f35SJulian Elischer  *
33c3aac50fSPeter Wemm  * $FreeBSD$
3426453f35SJulian Elischer  */
3526453f35SJulian Elischer 
3626453f35SJulian Elischer #include <sys/param.h>
37698bfad7SPoul-Henning Kamp #include <sys/kernel.h>
38d137acccSPoul-Henning Kamp #include <sys/sysctl.h>
39f8a760b3SJulian Elischer #include <sys/systm.h>
40ecbb00a2SDoug Rabson #include <sys/module.h>
41698bfad7SPoul-Henning Kamp #include <sys/malloc.h>
4226453f35SJulian Elischer #include <sys/conf.h>
431dfcbb0cSJulian Elischer #include <sys/vnode.h>
44698bfad7SPoul-Henning Kamp #include <sys/queue.h>
45db901281SPoul-Henning Kamp #include <sys/ctype.h>
460ef1c826SPoul-Henning Kamp #include <machine/stdarg.h>
471dfcbb0cSJulian Elischer 
482447bec8SPoul-Henning Kamp #define cdevsw_ALLOCSTART	(NUMCDEVSW/2)
491dfcbb0cSJulian Elischer 
502447bec8SPoul-Henning Kamp struct cdevsw 	*cdevsw[NUMCDEVSW];
511dfcbb0cSJulian Elischer 
52698bfad7SPoul-Henning Kamp static int	bmaj2cmaj[NUMCDEVSW];
53698bfad7SPoul-Henning Kamp 
54698bfad7SPoul-Henning Kamp MALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage");
55698bfad7SPoul-Henning Kamp 
56a87b5350SPoul-Henning Kamp /*
57a87b5350SPoul-Henning Kamp  * This is the number of hash-buckets.  Experiements with 'real-life'
58a87b5350SPoul-Henning Kamp  * udev_t's show that a prime halfway between two powers of two works
59a87b5350SPoul-Henning Kamp  * best.
60a87b5350SPoul-Henning Kamp  */
61698bfad7SPoul-Henning Kamp #define DEVT_HASH 83
62a87b5350SPoul-Henning Kamp 
63a87b5350SPoul-Henning Kamp /* The number of dev_t's we can create before malloc(9) kick in.  */
64698bfad7SPoul-Henning Kamp #define DEVT_STASH 50
65698bfad7SPoul-Henning Kamp 
66698bfad7SPoul-Henning Kamp static struct specinfo devt_stash[DEVT_STASH];
67698bfad7SPoul-Henning Kamp 
68e3975643SJake Burkholder static LIST_HEAD(, specinfo) dev_hash[DEVT_HASH];
69d137acccSPoul-Henning Kamp 
70e3975643SJake Burkholder static LIST_HEAD(, specinfo) dev_free;
7146eede00SPoul-Henning Kamp 
729dcbe240SPoul-Henning Kamp devfs_create_t *devfs_create_hook;
73db901281SPoul-Henning Kamp devfs_destroy_t *devfs_destroy_hook;
74db901281SPoul-Henning Kamp int devfs_present;
75d137acccSPoul-Henning Kamp 
76d137acccSPoul-Henning Kamp static int free_devt;
77d137acccSPoul-Henning Kamp SYSCTL_INT(_debug, OID_AUTO, free_devt, CTLFLAG_RW, &free_devt, 0, "");
789dcbe240SPoul-Henning Kamp 
792447bec8SPoul-Henning Kamp struct cdevsw *
802447bec8SPoul-Henning Kamp devsw(dev_t dev)
812447bec8SPoul-Henning Kamp {
827dc5cd04SPoul-Henning Kamp 	if (dev->si_devsw)
837dc5cd04SPoul-Henning Kamp 		return (dev->si_devsw);
843de280c4SPoul-Henning Kamp         return(cdevsw[major(dev)]);
852447bec8SPoul-Henning Kamp }
862447bec8SPoul-Henning Kamp 
872447bec8SPoul-Henning Kamp /*
882447bec8SPoul-Henning Kamp  *  Add a cdevsw entry
892447bec8SPoul-Henning Kamp  */
902447bec8SPoul-Henning Kamp 
91f7ea2f55SJulian Elischer int
922447bec8SPoul-Henning Kamp cdevsw_add(struct cdevsw *newentry)
93f7ea2f55SJulian Elischer {
94f7ea2f55SJulian Elischer 	int i;
95bfbb9ce6SPoul-Henning Kamp 	static int setup;
96bfbb9ce6SPoul-Henning Kamp 
97bfbb9ce6SPoul-Henning Kamp 	if (!setup) {
982447bec8SPoul-Henning Kamp 		for (i = 0; i < NUMCDEVSW; i++)
99bfbb9ce6SPoul-Henning Kamp 			if (!bmaj2cmaj[i])
100698bfad7SPoul-Henning Kamp 				bmaj2cmaj[i] = 254;
101bfbb9ce6SPoul-Henning Kamp 		setup++;
102bfbb9ce6SPoul-Henning Kamp 	}
103f7ea2f55SJulian Elischer 
1042447bec8SPoul-Henning Kamp 	if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) {
1052447bec8SPoul-Henning Kamp 		printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n",
1062447bec8SPoul-Henning Kamp 		    newentry->d_name, newentry->d_maj);
107662761a7SPoul-Henning Kamp 		return (EINVAL);
108662761a7SPoul-Henning Kamp 	}
109662761a7SPoul-Henning Kamp 	if (newentry->d_bmaj >= NUMCDEVSW) {
110662761a7SPoul-Henning Kamp 		printf("%s: ERROR: driver has bogus cdevsw->d_bmaj = %d\n",
111662761a7SPoul-Henning Kamp 		    newentry->d_name, newentry->d_bmaj);
112662761a7SPoul-Henning Kamp 		return (EINVAL);
113662761a7SPoul-Henning Kamp 	}
114662761a7SPoul-Henning Kamp 	if (newentry->d_bmaj >= 0 && (newentry->d_flags & D_DISK) == 0) {
115662761a7SPoul-Henning Kamp 		printf("ERROR: \"%s\" bmaj but is not a disk\n",
116662761a7SPoul-Henning Kamp 		    newentry->d_name);
117662761a7SPoul-Henning Kamp 		return (EINVAL);
118f7ea2f55SJulian Elischer 	}
119f7ea2f55SJulian Elischer 
120c31558b2SPoul-Henning Kamp 	if (cdevsw[newentry->d_maj]) {
121c31558b2SPoul-Henning Kamp 		printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n",
122c31558b2SPoul-Henning Kamp 		    newentry->d_name, cdevsw[newentry->d_maj]->d_name);
123c31558b2SPoul-Henning Kamp 	}
124662761a7SPoul-Henning Kamp 
1252447bec8SPoul-Henning Kamp 	cdevsw[newentry->d_maj] = newentry;
126f7ea2f55SJulian Elischer 
127662761a7SPoul-Henning Kamp 	if (newentry->d_bmaj < 0)
128662761a7SPoul-Henning Kamp 		return (0);
129662761a7SPoul-Henning Kamp 
130698bfad7SPoul-Henning Kamp 	if (bmaj2cmaj[newentry->d_bmaj] != 254) {
131c31558b2SPoul-Henning Kamp 		printf("WARNING: \"%s\" is usurping \"%s\"'s bmaj\n",
132c31558b2SPoul-Henning Kamp 		    newentry->d_name,
133c31558b2SPoul-Henning Kamp 		    cdevsw[bmaj2cmaj[newentry->d_bmaj]]->d_name);
134c31558b2SPoul-Henning Kamp 	}
1352447bec8SPoul-Henning Kamp 	bmaj2cmaj[newentry->d_bmaj] = newentry->d_maj;
136662761a7SPoul-Henning Kamp 	return (0);
137f7ea2f55SJulian Elischer }
138f7ea2f55SJulian Elischer 
1399a9eb2b9SGreg Lehey /*
1409a9eb2b9SGreg Lehey  *  Remove a cdevsw entry
1419a9eb2b9SGreg Lehey  */
1429a9eb2b9SGreg Lehey 
1439a9eb2b9SGreg Lehey int
1449a9eb2b9SGreg Lehey cdevsw_remove(struct cdevsw *oldentry)
1459a9eb2b9SGreg Lehey {
1469a9eb2b9SGreg Lehey 	if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) {
1479a9eb2b9SGreg Lehey 		printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n",
1489a9eb2b9SGreg Lehey 		    oldentry->d_name, oldentry->d_maj);
1499a9eb2b9SGreg Lehey 		return EINVAL;
1509a9eb2b9SGreg Lehey 	}
1519a9eb2b9SGreg Lehey 
1529a9eb2b9SGreg Lehey 	cdevsw[oldentry->d_maj] = NULL;
1539a9eb2b9SGreg Lehey 
1549a9eb2b9SGreg Lehey 	if (oldentry->d_bmaj >= 0 && oldentry->d_bmaj < NUMCDEVSW)
15532c0c324SGreg Lehey 		bmaj2cmaj[oldentry->d_bmaj] = 254;
1569a9eb2b9SGreg Lehey 
1579a9eb2b9SGreg Lehey 	return 0;
1589a9eb2b9SGreg Lehey }
1599a9eb2b9SGreg Lehey 
160bfbb9ce6SPoul-Henning Kamp /*
161bfbb9ce6SPoul-Henning Kamp  * dev_t and u_dev_t primitives
162bfbb9ce6SPoul-Henning Kamp  */
163bfbb9ce6SPoul-Henning Kamp 
164bfbb9ce6SPoul-Henning Kamp int
165bfbb9ce6SPoul-Henning Kamp major(dev_t x)
166bfbb9ce6SPoul-Henning Kamp {
167698bfad7SPoul-Henning Kamp 	if (x == NODEV)
168698bfad7SPoul-Henning Kamp 		return NOUDEV;
169698bfad7SPoul-Henning Kamp 	return((x->si_udev >> 8) & 0xff);
170bfbb9ce6SPoul-Henning Kamp }
171bfbb9ce6SPoul-Henning Kamp 
172bfbb9ce6SPoul-Henning Kamp int
173bfbb9ce6SPoul-Henning Kamp minor(dev_t x)
174bfbb9ce6SPoul-Henning Kamp {
175698bfad7SPoul-Henning Kamp 	if (x == NODEV)
176698bfad7SPoul-Henning Kamp 		return NOUDEV;
177698bfad7SPoul-Henning Kamp 	return(x->si_udev & 0xffff00ff);
178bfbb9ce6SPoul-Henning Kamp }
179bfbb9ce6SPoul-Henning Kamp 
1809a27d579SPoul-Henning Kamp int
1819a27d579SPoul-Henning Kamp lminor(dev_t x)
1829a27d579SPoul-Henning Kamp {
1839a27d579SPoul-Henning Kamp 	int i;
1849a27d579SPoul-Henning Kamp 
1859a27d579SPoul-Henning Kamp 	if (x == NODEV)
1869a27d579SPoul-Henning Kamp 		return NOUDEV;
1879a27d579SPoul-Henning Kamp 	i = minor(x);
1889a27d579SPoul-Henning Kamp 	return ((i & 0xff) | (i >> 8));
1899a27d579SPoul-Henning Kamp }
1909a27d579SPoul-Henning Kamp 
191bfbb9ce6SPoul-Henning Kamp dev_t
1926fcd8a7cSPoul-Henning Kamp makebdev(int x, int y)
1936fcd8a7cSPoul-Henning Kamp {
194fb01c24cSPoul-Henning Kamp 
195fb01c24cSPoul-Henning Kamp 	if (x == umajor(NOUDEV) && y == uminor(NOUDEV))
196fb01c24cSPoul-Henning Kamp 		Debugger("makebdev of NOUDEV");
1973de280c4SPoul-Henning Kamp 	return (makedev(bmaj2cmaj[x], y));
1986fcd8a7cSPoul-Henning Kamp }
1996fcd8a7cSPoul-Henning Kamp 
2003f54a085SPoul-Henning Kamp static dev_t
2013f54a085SPoul-Henning Kamp allocdev(void)
202bfbb9ce6SPoul-Henning Kamp {
203698bfad7SPoul-Henning Kamp 	static int stashed;
2043f54a085SPoul-Henning Kamp 	struct specinfo *si;
205698bfad7SPoul-Henning Kamp 
206698bfad7SPoul-Henning Kamp 	if (stashed >= DEVT_STASH) {
207698bfad7SPoul-Henning Kamp 		MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT,
208698bfad7SPoul-Henning Kamp 		    M_USE_RESERVE);
209d137acccSPoul-Henning Kamp 		bzero(si, sizeof(*si));
210d137acccSPoul-Henning Kamp 	} else if (LIST_FIRST(&dev_free)) {
211d137acccSPoul-Henning Kamp 		si = LIST_FIRST(&dev_free);
212d137acccSPoul-Henning Kamp 		LIST_REMOVE(si, si_hash);
213698bfad7SPoul-Henning Kamp 	} else {
214698bfad7SPoul-Henning Kamp 		si = devt_stash + stashed++;
215d137acccSPoul-Henning Kamp 		si->si_flags |= SI_STASHED;
216698bfad7SPoul-Henning Kamp 	}
2173f54a085SPoul-Henning Kamp 	LIST_INIT(&si->si_names);
2183f54a085SPoul-Henning Kamp 	return (si);
2193f54a085SPoul-Henning Kamp }
2203f54a085SPoul-Henning Kamp 
2213f54a085SPoul-Henning Kamp dev_t
2223f54a085SPoul-Henning Kamp makedev(int x, int y)
2233f54a085SPoul-Henning Kamp {
2243f54a085SPoul-Henning Kamp 	struct specinfo *si;
2253f54a085SPoul-Henning Kamp 	udev_t	udev;
2263f54a085SPoul-Henning Kamp 	int hash;
2273f54a085SPoul-Henning Kamp 
2283f54a085SPoul-Henning Kamp 	if (x == umajor(NOUDEV) && y == uminor(NOUDEV))
2293f54a085SPoul-Henning Kamp 		Debugger("makedev of NOUDEV");
2303f54a085SPoul-Henning Kamp 	udev = (x << 8) | y;
2313f54a085SPoul-Henning Kamp 	hash = udev % DEVT_HASH;
2323f54a085SPoul-Henning Kamp 	LIST_FOREACH(si, &dev_hash[hash], si_hash) {
2333f54a085SPoul-Henning Kamp 		if (si->si_udev == udev)
2343f54a085SPoul-Henning Kamp 			return (si);
2353f54a085SPoul-Henning Kamp 	}
2363f54a085SPoul-Henning Kamp 	si = allocdev();
237698bfad7SPoul-Henning Kamp 	si->si_udev = udev;
238d137acccSPoul-Henning Kamp 	LIST_INSERT_HEAD(&dev_hash[hash], si, si_hash);
239698bfad7SPoul-Henning Kamp         return (si);
240bfbb9ce6SPoul-Henning Kamp }
241bfbb9ce6SPoul-Henning Kamp 
242d137acccSPoul-Henning Kamp void
243d137acccSPoul-Henning Kamp freedev(dev_t dev)
244d137acccSPoul-Henning Kamp {
2453f54a085SPoul-Henning Kamp 	dev_t adev;
246d137acccSPoul-Henning Kamp 
247d137acccSPoul-Henning Kamp 	if (!free_devt)
248d137acccSPoul-Henning Kamp 		return;
249d137acccSPoul-Henning Kamp 	if (SLIST_FIRST(&dev->si_hlist))
250d137acccSPoul-Henning Kamp 		return;
251d137acccSPoul-Henning Kamp 	if (dev->si_devsw || dev->si_drv1 || dev->si_drv2)
252d137acccSPoul-Henning Kamp 		return;
2533f54a085SPoul-Henning Kamp 	while (!LIST_EMPTY(&dev->si_names)) {
2543f54a085SPoul-Henning Kamp 		adev = LIST_FIRST(&dev->si_names);
2553f54a085SPoul-Henning Kamp 		adev->si_drv1 = NULL;
2563f54a085SPoul-Henning Kamp 		freedev(adev);
2573f54a085SPoul-Henning Kamp 	}
258d137acccSPoul-Henning Kamp 	LIST_REMOVE(dev, si_hash);
259d137acccSPoul-Henning Kamp 	if (dev->si_flags & SI_STASHED) {
260d137acccSPoul-Henning Kamp 		bzero(dev, sizeof(*dev));
261d137acccSPoul-Henning Kamp 		LIST_INSERT_HEAD(&dev_free, dev, si_hash);
262d137acccSPoul-Henning Kamp 	} else {
263d137acccSPoul-Henning Kamp 		FREE(dev, M_DEVT);
264d137acccSPoul-Henning Kamp 	}
265d137acccSPoul-Henning Kamp }
266d137acccSPoul-Henning Kamp 
267bfbb9ce6SPoul-Henning Kamp udev_t
268bfbb9ce6SPoul-Henning Kamp dev2udev(dev_t x)
269bfbb9ce6SPoul-Henning Kamp {
270698bfad7SPoul-Henning Kamp 	if (x == NODEV)
271698bfad7SPoul-Henning Kamp 		return NOUDEV;
272698bfad7SPoul-Henning Kamp 	return (x->si_udev);
273bfbb9ce6SPoul-Henning Kamp }
274bfbb9ce6SPoul-Henning Kamp 
275bfbb9ce6SPoul-Henning Kamp dev_t
276bfbb9ce6SPoul-Henning Kamp udev2dev(udev_t x, int b)
277bfbb9ce6SPoul-Henning Kamp {
278fb01c24cSPoul-Henning Kamp 
279fb01c24cSPoul-Henning Kamp 	if (x == NOUDEV)
280fb01c24cSPoul-Henning Kamp 		return (NODEV);
281d21c632cSPoul-Henning Kamp 	switch (b) {
282d21c632cSPoul-Henning Kamp 		case 0:
283bfbb9ce6SPoul-Henning Kamp 			return makedev(umajor(x), uminor(x));
284d21c632cSPoul-Henning Kamp 		case 1:
285d21c632cSPoul-Henning Kamp 			return makebdev(umajor(x), uminor(x));
286d21c632cSPoul-Henning Kamp 		default:
287d21c632cSPoul-Henning Kamp 			Debugger("udev2dev(...,X)");
288d21c632cSPoul-Henning Kamp 			return NODEV;
289d21c632cSPoul-Henning Kamp 	}
290bfbb9ce6SPoul-Henning Kamp }
291bfbb9ce6SPoul-Henning Kamp 
292bfbb9ce6SPoul-Henning Kamp int
293bfbb9ce6SPoul-Henning Kamp uminor(udev_t dev)
294bfbb9ce6SPoul-Henning Kamp {
295bfbb9ce6SPoul-Henning Kamp 	return(dev & 0xffff00ff);
296bfbb9ce6SPoul-Henning Kamp }
297bfbb9ce6SPoul-Henning Kamp 
298bfbb9ce6SPoul-Henning Kamp int
299bfbb9ce6SPoul-Henning Kamp umajor(udev_t dev)
300bfbb9ce6SPoul-Henning Kamp {
301bfbb9ce6SPoul-Henning Kamp 	return((dev & 0xff00) >> 8);
302bfbb9ce6SPoul-Henning Kamp }
303bfbb9ce6SPoul-Henning Kamp 
304bfbb9ce6SPoul-Henning Kamp udev_t
305f008cfccSPoul-Henning Kamp makeudev(int x, int y)
306bfbb9ce6SPoul-Henning Kamp {
307bfbb9ce6SPoul-Henning Kamp         return ((x << 8) | y);
308bfbb9ce6SPoul-Henning Kamp }
309bfbb9ce6SPoul-Henning Kamp 
3100ef1c826SPoul-Henning Kamp dev_t
3110ef1c826SPoul-Henning Kamp make_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, char *fmt, ...)
3120ef1c826SPoul-Henning Kamp {
3130ef1c826SPoul-Henning Kamp 	dev_t	dev;
3140ef1c826SPoul-Henning Kamp 	va_list ap;
3150ef1c826SPoul-Henning Kamp 	int i;
3160ef1c826SPoul-Henning Kamp 
3170ef1c826SPoul-Henning Kamp 	dev = makedev(devsw->d_maj, minor);
3180ef1c826SPoul-Henning Kamp 	va_start(ap, fmt);
3198dc74b62SBoris Popov 	i = kvprintf(fmt, NULL, dev->si_name, 32, ap);
3200ef1c826SPoul-Henning Kamp 	dev->si_name[i] = '\0';
3210ef1c826SPoul-Henning Kamp 	va_end(ap);
3220ef1c826SPoul-Henning Kamp 	dev->si_devsw = devsw;
3233f54a085SPoul-Henning Kamp 	dev->si_uid = uid;
3243f54a085SPoul-Henning Kamp 	dev->si_gid = gid;
3253f54a085SPoul-Henning Kamp 	dev->si_mode = perms;
3261744fcd0SJulian Elischer 
3279dcbe240SPoul-Henning Kamp 	if (devfs_create_hook)
3283f54a085SPoul-Henning Kamp 		devfs_create_hook(dev);
3293f54a085SPoul-Henning Kamp 	return (dev);
3303f54a085SPoul-Henning Kamp }
3313f54a085SPoul-Henning Kamp 
3323f54a085SPoul-Henning Kamp dev_t
3333f54a085SPoul-Henning Kamp make_dev_alias(dev_t pdev, char *fmt, ...)
3343f54a085SPoul-Henning Kamp {
3353f54a085SPoul-Henning Kamp 	dev_t	dev;
3363f54a085SPoul-Henning Kamp 	va_list ap;
3373f54a085SPoul-Henning Kamp 	int i;
3383f54a085SPoul-Henning Kamp 
3393f54a085SPoul-Henning Kamp 	dev = allocdev();
3403f54a085SPoul-Henning Kamp 	dev->si_flags |= SI_ALIAS;
3413f54a085SPoul-Henning Kamp 	dev->si_drv1 = pdev;
3423f54a085SPoul-Henning Kamp 	LIST_INSERT_HEAD(&pdev->si_names, dev, si_hash);
3433f54a085SPoul-Henning Kamp 
3443f54a085SPoul-Henning Kamp 	va_start(ap, fmt);
3453f54a085SPoul-Henning Kamp 	i = kvprintf(fmt, NULL, dev->si_name, 32, ap);
3463f54a085SPoul-Henning Kamp 	dev->si_name[i] = '\0';
3473f54a085SPoul-Henning Kamp 	va_end(ap);
3483f54a085SPoul-Henning Kamp 
3493f54a085SPoul-Henning Kamp 	if (devfs_create_hook)
3503f54a085SPoul-Henning Kamp 		devfs_create_hook(dev);
3510ef1c826SPoul-Henning Kamp 	return (dev);
3520ef1c826SPoul-Henning Kamp }
3530ef1c826SPoul-Henning Kamp 
354d137acccSPoul-Henning Kamp void
35544d1184eSPoul-Henning Kamp destroy_dev(dev_t dev)
356d137acccSPoul-Henning Kamp {
357db901281SPoul-Henning Kamp 	if (devfs_destroy_hook)
358db901281SPoul-Henning Kamp 		devfs_destroy_hook(dev);
359d137acccSPoul-Henning Kamp 	dev->si_drv1 = 0;
360d137acccSPoul-Henning Kamp 	dev->si_drv2 = 0;
361d137acccSPoul-Henning Kamp 	dev->si_devsw = 0;
362d137acccSPoul-Henning Kamp 	freedev(dev);
363d137acccSPoul-Henning Kamp }
364d137acccSPoul-Henning Kamp 
365c32cc149SBruce Evans const char *
366b8e49f68SBill Fumerola devtoname(dev_t dev)
367b8e49f68SBill Fumerola {
368d137acccSPoul-Henning Kamp 	char *p;
369c32cc149SBruce Evans 	int mynor;
370b8e49f68SBill Fumerola 
371d137acccSPoul-Henning Kamp 	if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') {
372d137acccSPoul-Henning Kamp 		p = dev->si_name;
373d137acccSPoul-Henning Kamp 		if (devsw(dev))
374d137acccSPoul-Henning Kamp 			sprintf(p, "#%s/", devsw(dev)->d_name);
375d137acccSPoul-Henning Kamp 		else
376d137acccSPoul-Henning Kamp 			sprintf(p, "#%d/", major(dev));
377d137acccSPoul-Henning Kamp 		p += strlen(p);
378c32cc149SBruce Evans 		mynor = minor(dev);
379c32cc149SBruce Evans 		if (mynor < 0 || mynor > 255)
380c32cc149SBruce Evans 			sprintf(p, "%#x", (u_int)mynor);
381c32cc149SBruce Evans 		else
382c32cc149SBruce Evans 			sprintf(p, "%d", mynor);
383d137acccSPoul-Henning Kamp 	}
384b8e49f68SBill Fumerola 	return (dev->si_name);
385b8e49f68SBill Fumerola }
386db901281SPoul-Henning Kamp 
387db901281SPoul-Henning Kamp int
388db901281SPoul-Henning Kamp dev_stdclone(char *name, char **namep, char *stem, int *unit)
389db901281SPoul-Henning Kamp {
390db901281SPoul-Henning Kamp 	int u, i;
391db901281SPoul-Henning Kamp 
392db901281SPoul-Henning Kamp 	if (bcmp(stem, name, strlen(stem)) != 0)
393db901281SPoul-Henning Kamp 		return (0);
394db901281SPoul-Henning Kamp 	i = strlen(stem);
395db901281SPoul-Henning Kamp 	if (!isdigit(name[i]))
396db901281SPoul-Henning Kamp 		return (0);
397db901281SPoul-Henning Kamp 	u = 0;
398db901281SPoul-Henning Kamp 	while (isdigit(name[i])) {
399db901281SPoul-Henning Kamp 		u *= 10;
400db901281SPoul-Henning Kamp 		u += name[i++] - '0';
401db901281SPoul-Henning Kamp 	}
402db901281SPoul-Henning Kamp 	*unit = u;
403db901281SPoul-Henning Kamp 	if (namep)
404db901281SPoul-Henning Kamp 		*namep = &name[i];
405db901281SPoul-Henning Kamp 	if (name[i])
406db901281SPoul-Henning Kamp 		return (2);
407db901281SPoul-Henning Kamp 	return (1);
408db901281SPoul-Henning Kamp }
4098d25eb2cSPoul-Henning Kamp 
4108d25eb2cSPoul-Henning Kamp /*
4118d25eb2cSPoul-Henning Kamp  * Helper sysctl for devname(3).  We're given a {u}dev_t and return
4128d25eb2cSPoul-Henning Kamp  * the name, if any, registered by the device driver.
4138d25eb2cSPoul-Henning Kamp  */
4148d25eb2cSPoul-Henning Kamp static int
4158d25eb2cSPoul-Henning Kamp sysctl_devname(SYSCTL_HANDLER_ARGS)
4168d25eb2cSPoul-Henning Kamp {
4178d25eb2cSPoul-Henning Kamp 	int error;
4188d25eb2cSPoul-Henning Kamp 	udev_t ud;
4198d25eb2cSPoul-Henning Kamp 	dev_t dev;
4208d25eb2cSPoul-Henning Kamp 
4218d25eb2cSPoul-Henning Kamp 	error = SYSCTL_IN(req, &ud, sizeof (ud));
4228d25eb2cSPoul-Henning Kamp 	if (error)
4238d25eb2cSPoul-Henning Kamp 		return (error);
4248d25eb2cSPoul-Henning Kamp 	dev = makedev(umajor(ud), uminor(ud));
4258d25eb2cSPoul-Henning Kamp 	if (dev->si_name[0] == '\0')
4268d25eb2cSPoul-Henning Kamp 		error = ENOENT;
4278d25eb2cSPoul-Henning Kamp 	else
4288d25eb2cSPoul-Henning Kamp 		error = SYSCTL_OUT(req, dev->si_name, strlen(dev->si_name) + 1);
4298d25eb2cSPoul-Henning Kamp 	freedev(dev);
4308d25eb2cSPoul-Henning Kamp 	return (error);
4318d25eb2cSPoul-Henning Kamp }
4328d25eb2cSPoul-Henning Kamp 
4338d25eb2cSPoul-Henning Kamp SYSCTL_PROC(_kern, OID_AUTO, devname, CTLTYPE_OPAQUE|CTLFLAG_RW,
4348d25eb2cSPoul-Henning Kamp 	NULL, 0, sysctl_devname, "", "devname(3) handler");
4358d25eb2cSPoul-Henning Kamp 
436