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 52959b7375SPoul-Henning Kamp static MALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage"); 53698bfad7SPoul-Henning Kamp 54a87b5350SPoul-Henning Kamp /* 55a87b5350SPoul-Henning Kamp * This is the number of hash-buckets. Experiements with 'real-life' 56a87b5350SPoul-Henning Kamp * udev_t's show that a prime halfway between two powers of two works 57a87b5350SPoul-Henning Kamp * best. 58a87b5350SPoul-Henning Kamp */ 59698bfad7SPoul-Henning Kamp #define DEVT_HASH 83 60a87b5350SPoul-Henning Kamp 61a87b5350SPoul-Henning Kamp /* The number of dev_t's we can create before malloc(9) kick in. */ 62698bfad7SPoul-Henning Kamp #define DEVT_STASH 50 63698bfad7SPoul-Henning Kamp 64698bfad7SPoul-Henning Kamp static struct specinfo devt_stash[DEVT_STASH]; 65698bfad7SPoul-Henning Kamp 66e3975643SJake Burkholder static LIST_HEAD(, specinfo) dev_hash[DEVT_HASH]; 67d137acccSPoul-Henning Kamp 68e3975643SJake Burkholder static LIST_HEAD(, specinfo) dev_free; 6946eede00SPoul-Henning Kamp 709dcbe240SPoul-Henning Kamp devfs_create_t *devfs_create_hook; 71db901281SPoul-Henning Kamp devfs_destroy_t *devfs_destroy_hook; 72db901281SPoul-Henning Kamp int devfs_present; 73d137acccSPoul-Henning Kamp 74d137acccSPoul-Henning Kamp static int free_devt; 75d137acccSPoul-Henning Kamp SYSCTL_INT(_debug, OID_AUTO, free_devt, CTLFLAG_RW, &free_devt, 0, ""); 769dcbe240SPoul-Henning Kamp 772447bec8SPoul-Henning Kamp struct cdevsw * 782447bec8SPoul-Henning Kamp devsw(dev_t dev) 792447bec8SPoul-Henning Kamp { 807dc5cd04SPoul-Henning Kamp if (dev->si_devsw) 817dc5cd04SPoul-Henning Kamp return (dev->si_devsw); 823de280c4SPoul-Henning Kamp return(cdevsw[major(dev)]); 832447bec8SPoul-Henning Kamp } 842447bec8SPoul-Henning Kamp 852447bec8SPoul-Henning Kamp /* 862447bec8SPoul-Henning Kamp * Add a cdevsw entry 872447bec8SPoul-Henning Kamp */ 882447bec8SPoul-Henning Kamp 89f7ea2f55SJulian Elischer int 902447bec8SPoul-Henning Kamp cdevsw_add(struct cdevsw *newentry) 91f7ea2f55SJulian Elischer { 92bfbb9ce6SPoul-Henning Kamp 932447bec8SPoul-Henning Kamp if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) { 942447bec8SPoul-Henning Kamp printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 952447bec8SPoul-Henning Kamp newentry->d_name, newentry->d_maj); 96662761a7SPoul-Henning Kamp return (EINVAL); 97662761a7SPoul-Henning Kamp } 98f7ea2f55SJulian Elischer 99c31558b2SPoul-Henning Kamp if (cdevsw[newentry->d_maj]) { 100c31558b2SPoul-Henning Kamp printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n", 101c31558b2SPoul-Henning Kamp newentry->d_name, cdevsw[newentry->d_maj]->d_name); 102c31558b2SPoul-Henning Kamp } 103662761a7SPoul-Henning Kamp 1042447bec8SPoul-Henning Kamp cdevsw[newentry->d_maj] = newentry; 105f7ea2f55SJulian Elischer 106662761a7SPoul-Henning Kamp return (0); 107f7ea2f55SJulian Elischer } 108f7ea2f55SJulian Elischer 1099a9eb2b9SGreg Lehey /* 1109a9eb2b9SGreg Lehey * Remove a cdevsw entry 1119a9eb2b9SGreg Lehey */ 1129a9eb2b9SGreg Lehey 1139a9eb2b9SGreg Lehey int 1149a9eb2b9SGreg Lehey cdevsw_remove(struct cdevsw *oldentry) 1159a9eb2b9SGreg Lehey { 1169a9eb2b9SGreg Lehey if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) { 1179a9eb2b9SGreg Lehey printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 1189a9eb2b9SGreg Lehey oldentry->d_name, oldentry->d_maj); 1199a9eb2b9SGreg Lehey return EINVAL; 1209a9eb2b9SGreg Lehey } 1219a9eb2b9SGreg Lehey 1229a9eb2b9SGreg Lehey cdevsw[oldentry->d_maj] = NULL; 1239a9eb2b9SGreg Lehey 1249a9eb2b9SGreg Lehey return 0; 1259a9eb2b9SGreg Lehey } 1269a9eb2b9SGreg Lehey 127bfbb9ce6SPoul-Henning Kamp /* 128bfbb9ce6SPoul-Henning Kamp * dev_t and u_dev_t primitives 129bfbb9ce6SPoul-Henning Kamp */ 130bfbb9ce6SPoul-Henning Kamp 131bfbb9ce6SPoul-Henning Kamp int 132bfbb9ce6SPoul-Henning Kamp major(dev_t x) 133bfbb9ce6SPoul-Henning Kamp { 134698bfad7SPoul-Henning Kamp if (x == NODEV) 135698bfad7SPoul-Henning Kamp return NOUDEV; 136698bfad7SPoul-Henning Kamp return((x->si_udev >> 8) & 0xff); 137bfbb9ce6SPoul-Henning Kamp } 138bfbb9ce6SPoul-Henning Kamp 139bfbb9ce6SPoul-Henning Kamp int 140bfbb9ce6SPoul-Henning Kamp minor(dev_t x) 141bfbb9ce6SPoul-Henning Kamp { 142698bfad7SPoul-Henning Kamp if (x == NODEV) 143698bfad7SPoul-Henning Kamp return NOUDEV; 144698bfad7SPoul-Henning Kamp return(x->si_udev & 0xffff00ff); 145bfbb9ce6SPoul-Henning Kamp } 146bfbb9ce6SPoul-Henning Kamp 1479a27d579SPoul-Henning Kamp int 148b0d17ba6SPoul-Henning Kamp dev2unit(dev_t x) 1499a27d579SPoul-Henning Kamp { 1509a27d579SPoul-Henning Kamp int i; 1519a27d579SPoul-Henning Kamp 1529a27d579SPoul-Henning Kamp if (x == NODEV) 1539a27d579SPoul-Henning Kamp return NOUDEV; 1549a27d579SPoul-Henning Kamp i = minor(x); 1559a27d579SPoul-Henning Kamp return ((i & 0xff) | (i >> 8)); 1569a27d579SPoul-Henning Kamp } 1579a27d579SPoul-Henning Kamp 158b0d17ba6SPoul-Henning Kamp int 159b0d17ba6SPoul-Henning Kamp unit2minor(int unit) 160b0d17ba6SPoul-Henning Kamp { 161b0d17ba6SPoul-Henning Kamp 16215b6f00fSPoul-Henning Kamp KASSERT(unit <= 0xffffff, ("Invalid unit (%d) in unit2minor", unit)); 163b0d17ba6SPoul-Henning Kamp return ((unit & 0xff) | ((unit << 8) & ~0xffff)); 164b0d17ba6SPoul-Henning Kamp } 165b0d17ba6SPoul-Henning Kamp 1663f54a085SPoul-Henning Kamp static dev_t 1673f54a085SPoul-Henning Kamp allocdev(void) 168bfbb9ce6SPoul-Henning Kamp { 169698bfad7SPoul-Henning Kamp static int stashed; 1703f54a085SPoul-Henning Kamp struct specinfo *si; 171698bfad7SPoul-Henning Kamp 172698bfad7SPoul-Henning Kamp if (stashed >= DEVT_STASH) { 173698bfad7SPoul-Henning Kamp MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT, 1747cc0979fSDavid Malone M_USE_RESERVE | M_ZERO); 175d137acccSPoul-Henning Kamp } else if (LIST_FIRST(&dev_free)) { 176d137acccSPoul-Henning Kamp si = LIST_FIRST(&dev_free); 177d137acccSPoul-Henning Kamp LIST_REMOVE(si, si_hash); 178698bfad7SPoul-Henning Kamp } else { 179698bfad7SPoul-Henning Kamp si = devt_stash + stashed++; 1803344c5a1SPoul-Henning Kamp bzero(si, sizeof *si); 181d137acccSPoul-Henning Kamp si->si_flags |= SI_STASHED; 182698bfad7SPoul-Henning Kamp } 1833344c5a1SPoul-Henning Kamp LIST_INIT(&si->si_children); 184589c7af9SKirk McKusick TAILQ_INIT(&si->si_snapshots); 1853f54a085SPoul-Henning Kamp return (si); 1863f54a085SPoul-Henning Kamp } 1873f54a085SPoul-Henning Kamp 1883f54a085SPoul-Henning Kamp dev_t 1893f54a085SPoul-Henning Kamp makedev(int x, int y) 1903f54a085SPoul-Henning Kamp { 1913f54a085SPoul-Henning Kamp struct specinfo *si; 1923f54a085SPoul-Henning Kamp udev_t udev; 1933f54a085SPoul-Henning Kamp int hash; 1943f54a085SPoul-Henning Kamp 1953f54a085SPoul-Henning Kamp if (x == umajor(NOUDEV) && y == uminor(NOUDEV)) 1961fd7b93fSPoul-Henning Kamp panic("makedev of NOUDEV"); 1973f54a085SPoul-Henning Kamp udev = (x << 8) | y; 1983f54a085SPoul-Henning Kamp hash = udev % DEVT_HASH; 1993f54a085SPoul-Henning Kamp LIST_FOREACH(si, &dev_hash[hash], si_hash) { 2003f54a085SPoul-Henning Kamp if (si->si_udev == udev) 2013f54a085SPoul-Henning Kamp return (si); 2023f54a085SPoul-Henning Kamp } 2033f54a085SPoul-Henning Kamp si = allocdev(); 204698bfad7SPoul-Henning Kamp si->si_udev = udev; 205d137acccSPoul-Henning Kamp LIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); 206698bfad7SPoul-Henning Kamp return (si); 207bfbb9ce6SPoul-Henning Kamp } 208bfbb9ce6SPoul-Henning Kamp 209d137acccSPoul-Henning Kamp void 210d137acccSPoul-Henning Kamp freedev(dev_t dev) 211d137acccSPoul-Henning Kamp { 212d137acccSPoul-Henning Kamp 213d137acccSPoul-Henning Kamp if (!free_devt) 214d137acccSPoul-Henning Kamp return; 215d137acccSPoul-Henning Kamp if (SLIST_FIRST(&dev->si_hlist)) 216d137acccSPoul-Henning Kamp return; 217d137acccSPoul-Henning Kamp if (dev->si_devsw || dev->si_drv1 || dev->si_drv2) 218d137acccSPoul-Henning Kamp return; 219d137acccSPoul-Henning Kamp LIST_REMOVE(dev, si_hash); 220d137acccSPoul-Henning Kamp if (dev->si_flags & SI_STASHED) { 221d137acccSPoul-Henning Kamp bzero(dev, sizeof(*dev)); 2223344c5a1SPoul-Henning Kamp dev->si_flags |= SI_STASHED; 223d137acccSPoul-Henning Kamp LIST_INSERT_HEAD(&dev_free, dev, si_hash); 224d137acccSPoul-Henning Kamp } else { 225d137acccSPoul-Henning Kamp FREE(dev, M_DEVT); 226d137acccSPoul-Henning Kamp } 227d137acccSPoul-Henning Kamp } 228d137acccSPoul-Henning Kamp 229bfbb9ce6SPoul-Henning Kamp udev_t 230bfbb9ce6SPoul-Henning Kamp dev2udev(dev_t x) 231bfbb9ce6SPoul-Henning Kamp { 232698bfad7SPoul-Henning Kamp if (x == NODEV) 233698bfad7SPoul-Henning Kamp return NOUDEV; 234698bfad7SPoul-Henning Kamp return (x->si_udev); 235bfbb9ce6SPoul-Henning Kamp } 236bfbb9ce6SPoul-Henning Kamp 237bfbb9ce6SPoul-Henning Kamp dev_t 238bfbb9ce6SPoul-Henning Kamp udev2dev(udev_t x, int b) 239bfbb9ce6SPoul-Henning Kamp { 240fb01c24cSPoul-Henning Kamp 241fb01c24cSPoul-Henning Kamp if (x == NOUDEV) 242fb01c24cSPoul-Henning Kamp return (NODEV); 243d21c632cSPoul-Henning Kamp switch (b) { 244d21c632cSPoul-Henning Kamp case 0: 245bfbb9ce6SPoul-Henning Kamp return makedev(umajor(x), uminor(x)); 246d21c632cSPoul-Henning Kamp case 1: 247a16d0eb2SPoul-Henning Kamp return (NODEV); 248d21c632cSPoul-Henning Kamp default: 249d21c632cSPoul-Henning Kamp Debugger("udev2dev(...,X)"); 250d21c632cSPoul-Henning Kamp return NODEV; 251d21c632cSPoul-Henning Kamp } 252bfbb9ce6SPoul-Henning Kamp } 253bfbb9ce6SPoul-Henning Kamp 254bfbb9ce6SPoul-Henning Kamp int 255bfbb9ce6SPoul-Henning Kamp uminor(udev_t dev) 256bfbb9ce6SPoul-Henning Kamp { 257bfbb9ce6SPoul-Henning Kamp return(dev & 0xffff00ff); 258bfbb9ce6SPoul-Henning Kamp } 259bfbb9ce6SPoul-Henning Kamp 260bfbb9ce6SPoul-Henning Kamp int 261bfbb9ce6SPoul-Henning Kamp umajor(udev_t dev) 262bfbb9ce6SPoul-Henning Kamp { 263bfbb9ce6SPoul-Henning Kamp return((dev & 0xff00) >> 8); 264bfbb9ce6SPoul-Henning Kamp } 265bfbb9ce6SPoul-Henning Kamp 266bfbb9ce6SPoul-Henning Kamp udev_t 267f008cfccSPoul-Henning Kamp makeudev(int x, int y) 268bfbb9ce6SPoul-Henning Kamp { 269bfbb9ce6SPoul-Henning Kamp return ((x << 8) | y); 270bfbb9ce6SPoul-Henning Kamp } 271bfbb9ce6SPoul-Henning Kamp 2720ef1c826SPoul-Henning Kamp dev_t 2730ef1c826SPoul-Henning Kamp make_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, char *fmt, ...) 2740ef1c826SPoul-Henning Kamp { 2750ef1c826SPoul-Henning Kamp dev_t dev; 2760ef1c826SPoul-Henning Kamp va_list ap; 2770ef1c826SPoul-Henning Kamp int i; 2780ef1c826SPoul-Henning Kamp 27911586717SBrian Somers KASSERT(umajor(makeudev(devsw->d_maj, minor)) == devsw->d_maj, 28011586717SBrian Somers ("Invalid minor (%d) in make_dev", minor)); 28111586717SBrian Somers 2820ef1c826SPoul-Henning Kamp dev = makedev(devsw->d_maj, minor); 2835ef2707eSPoul-Henning Kamp if (dev->si_flags & SI_NAMED) { 2845ef2707eSPoul-Henning Kamp printf( "WARNING: Driver mistake: repeat make_dev(\"%s\")\n", 2855ef2707eSPoul-Henning Kamp dev->si_name); 2865ef2707eSPoul-Henning Kamp return (dev); 2875ef2707eSPoul-Henning Kamp } 2880ef1c826SPoul-Henning Kamp va_start(ap, fmt); 2898dc74b62SBoris Popov i = kvprintf(fmt, NULL, dev->si_name, 32, ap); 2900ef1c826SPoul-Henning Kamp dev->si_name[i] = '\0'; 2910ef1c826SPoul-Henning Kamp va_end(ap); 2920ef1c826SPoul-Henning Kamp dev->si_devsw = devsw; 2933f54a085SPoul-Henning Kamp dev->si_uid = uid; 2943f54a085SPoul-Henning Kamp dev->si_gid = gid; 2953f54a085SPoul-Henning Kamp dev->si_mode = perms; 2965ef2707eSPoul-Henning Kamp dev->si_flags |= SI_NAMED; 2971744fcd0SJulian Elischer 2989dcbe240SPoul-Henning Kamp if (devfs_create_hook) 2993f54a085SPoul-Henning Kamp devfs_create_hook(dev); 3003f54a085SPoul-Henning Kamp return (dev); 3013f54a085SPoul-Henning Kamp } 3023f54a085SPoul-Henning Kamp 3033344c5a1SPoul-Henning Kamp void 3043344c5a1SPoul-Henning Kamp dev_depends(dev_t pdev, dev_t cdev) 3053344c5a1SPoul-Henning Kamp { 3063344c5a1SPoul-Henning Kamp 3073344c5a1SPoul-Henning Kamp cdev->si_parent = pdev; 3083344c5a1SPoul-Henning Kamp cdev->si_flags |= SI_CHILD; 3093344c5a1SPoul-Henning Kamp LIST_INSERT_HEAD(&pdev->si_children, cdev, si_siblings); 3103344c5a1SPoul-Henning Kamp } 3113344c5a1SPoul-Henning Kamp 3123f54a085SPoul-Henning Kamp dev_t 3133f54a085SPoul-Henning Kamp make_dev_alias(dev_t pdev, char *fmt, ...) 3143f54a085SPoul-Henning Kamp { 3153f54a085SPoul-Henning Kamp dev_t dev; 3163f54a085SPoul-Henning Kamp va_list ap; 3173f54a085SPoul-Henning Kamp int i; 3183f54a085SPoul-Henning Kamp 3193f54a085SPoul-Henning Kamp dev = allocdev(); 3203f54a085SPoul-Henning Kamp dev->si_flags |= SI_ALIAS; 3215ef2707eSPoul-Henning Kamp dev->si_flags |= SI_NAMED; 3223344c5a1SPoul-Henning Kamp dev_depends(pdev, dev); 3233f54a085SPoul-Henning Kamp va_start(ap, fmt); 3243f54a085SPoul-Henning Kamp i = kvprintf(fmt, NULL, dev->si_name, 32, ap); 3253f54a085SPoul-Henning Kamp dev->si_name[i] = '\0'; 3263f54a085SPoul-Henning Kamp va_end(ap); 3273f54a085SPoul-Henning Kamp 3283f54a085SPoul-Henning Kamp if (devfs_create_hook) 3293f54a085SPoul-Henning Kamp devfs_create_hook(dev); 3300ef1c826SPoul-Henning Kamp return (dev); 3310ef1c826SPoul-Henning Kamp } 3320ef1c826SPoul-Henning Kamp 333d137acccSPoul-Henning Kamp void 33444d1184eSPoul-Henning Kamp destroy_dev(dev_t dev) 335d137acccSPoul-Henning Kamp { 3365ef2707eSPoul-Henning Kamp 3375ef2707eSPoul-Henning Kamp if (!(dev->si_flags & SI_NAMED)) { 3385ef2707eSPoul-Henning Kamp printf( "WARNING: Driver mistake: destroy_dev on %d/%d\n", 3395ef2707eSPoul-Henning Kamp major(dev), minor(dev)); 3405ef2707eSPoul-Henning Kamp return; 3415ef2707eSPoul-Henning Kamp } 3425ef2707eSPoul-Henning Kamp 343db901281SPoul-Henning Kamp if (devfs_destroy_hook) 344db901281SPoul-Henning Kamp devfs_destroy_hook(dev); 3453344c5a1SPoul-Henning Kamp if (dev->si_flags & SI_CHILD) { 3463344c5a1SPoul-Henning Kamp LIST_REMOVE(dev, si_siblings); 3473344c5a1SPoul-Henning Kamp dev->si_flags &= ~SI_CHILD; 3483344c5a1SPoul-Henning Kamp } 3493344c5a1SPoul-Henning Kamp while (!LIST_EMPTY(&dev->si_children)) 3503344c5a1SPoul-Henning Kamp destroy_dev(LIST_FIRST(&dev->si_children)); 351d137acccSPoul-Henning Kamp dev->si_drv1 = 0; 352d137acccSPoul-Henning Kamp dev->si_drv2 = 0; 353d137acccSPoul-Henning Kamp dev->si_devsw = 0; 3545ef2707eSPoul-Henning Kamp dev->si_flags &= ~SI_NAMED; 3555ef2707eSPoul-Henning Kamp dev->si_flags &= ~SI_ALIAS; 356d137acccSPoul-Henning Kamp freedev(dev); 357d137acccSPoul-Henning Kamp } 358d137acccSPoul-Henning Kamp 359c32cc149SBruce Evans const char * 360b8e49f68SBill Fumerola devtoname(dev_t dev) 361b8e49f68SBill Fumerola { 362d137acccSPoul-Henning Kamp char *p; 363c32cc149SBruce Evans int mynor; 364b8e49f68SBill Fumerola 365d137acccSPoul-Henning Kamp if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') { 366d137acccSPoul-Henning Kamp p = dev->si_name; 367d137acccSPoul-Henning Kamp if (devsw(dev)) 368d137acccSPoul-Henning Kamp sprintf(p, "#%s/", devsw(dev)->d_name); 369d137acccSPoul-Henning Kamp else 370d137acccSPoul-Henning Kamp sprintf(p, "#%d/", major(dev)); 371d137acccSPoul-Henning Kamp p += strlen(p); 372c32cc149SBruce Evans mynor = minor(dev); 373c32cc149SBruce Evans if (mynor < 0 || mynor > 255) 374c32cc149SBruce Evans sprintf(p, "%#x", (u_int)mynor); 375c32cc149SBruce Evans else 376c32cc149SBruce Evans sprintf(p, "%d", mynor); 377d137acccSPoul-Henning Kamp } 378b8e49f68SBill Fumerola return (dev->si_name); 379b8e49f68SBill Fumerola } 380db901281SPoul-Henning Kamp 381db901281SPoul-Henning Kamp int 382db901281SPoul-Henning Kamp dev_stdclone(char *name, char **namep, char *stem, int *unit) 383db901281SPoul-Henning Kamp { 384db901281SPoul-Henning Kamp int u, i; 385db901281SPoul-Henning Kamp 386db901281SPoul-Henning Kamp i = strlen(stem); 38756700d46SBrian Somers if (bcmp(stem, name, i) != 0) 38856700d46SBrian Somers return (0); 389db901281SPoul-Henning Kamp if (!isdigit(name[i])) 390db901281SPoul-Henning Kamp return (0); 391db901281SPoul-Henning Kamp u = 0; 392db901281SPoul-Henning Kamp while (isdigit(name[i])) { 393db901281SPoul-Henning Kamp u *= 10; 394db901281SPoul-Henning Kamp u += name[i++] - '0'; 395db901281SPoul-Henning Kamp } 396db901281SPoul-Henning Kamp *unit = u; 397db901281SPoul-Henning Kamp if (namep) 398db901281SPoul-Henning Kamp *namep = &name[i]; 399db901281SPoul-Henning Kamp if (name[i]) 400db901281SPoul-Henning Kamp return (2); 401db901281SPoul-Henning Kamp return (1); 402db901281SPoul-Henning Kamp } 4038d25eb2cSPoul-Henning Kamp 4048d25eb2cSPoul-Henning Kamp /* 4058d25eb2cSPoul-Henning Kamp * Helper sysctl for devname(3). We're given a {u}dev_t and return 4068d25eb2cSPoul-Henning Kamp * the name, if any, registered by the device driver. 4078d25eb2cSPoul-Henning Kamp */ 4088d25eb2cSPoul-Henning Kamp static int 4098d25eb2cSPoul-Henning Kamp sysctl_devname(SYSCTL_HANDLER_ARGS) 4108d25eb2cSPoul-Henning Kamp { 4118d25eb2cSPoul-Henning Kamp int error; 4128d25eb2cSPoul-Henning Kamp udev_t ud; 4138d25eb2cSPoul-Henning Kamp dev_t dev; 4148d25eb2cSPoul-Henning Kamp 4158d25eb2cSPoul-Henning Kamp error = SYSCTL_IN(req, &ud, sizeof (ud)); 4168d25eb2cSPoul-Henning Kamp if (error) 4178d25eb2cSPoul-Henning Kamp return (error); 4181fd7b93fSPoul-Henning Kamp if (ud == NOUDEV) 4191fd7b93fSPoul-Henning Kamp return(EINVAL); 4208d25eb2cSPoul-Henning Kamp dev = makedev(umajor(ud), uminor(ud)); 4218d25eb2cSPoul-Henning Kamp if (dev->si_name[0] == '\0') 4228d25eb2cSPoul-Henning Kamp error = ENOENT; 4238d25eb2cSPoul-Henning Kamp else 4248d25eb2cSPoul-Henning Kamp error = SYSCTL_OUT(req, dev->si_name, strlen(dev->si_name) + 1); 4258d25eb2cSPoul-Henning Kamp freedev(dev); 4268d25eb2cSPoul-Henning Kamp return (error); 4278d25eb2cSPoul-Henning Kamp } 4288d25eb2cSPoul-Henning Kamp 429fe4e3243SPoul-Henning Kamp SYSCTL_PROC(_kern, OID_AUTO, devname, CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY, 4308d25eb2cSPoul-Henning Kamp NULL, 0, sysctl_devname, "", "devname(3) handler"); 4318d25eb2cSPoul-Henning Kamp 432