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