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++; 180d137acccSPoul-Henning Kamp si->si_flags |= SI_STASHED; 181698bfad7SPoul-Henning Kamp } 1823f54a085SPoul-Henning Kamp LIST_INIT(&si->si_names); 183589c7af9SKirk McKusick TAILQ_INIT(&si->si_snapshots); 1843f54a085SPoul-Henning Kamp return (si); 1853f54a085SPoul-Henning Kamp } 1863f54a085SPoul-Henning Kamp 1873f54a085SPoul-Henning Kamp dev_t 1883f54a085SPoul-Henning Kamp makedev(int x, int y) 1893f54a085SPoul-Henning Kamp { 1903f54a085SPoul-Henning Kamp struct specinfo *si; 1913f54a085SPoul-Henning Kamp udev_t udev; 1923f54a085SPoul-Henning Kamp int hash; 1933f54a085SPoul-Henning Kamp 1943f54a085SPoul-Henning Kamp if (x == umajor(NOUDEV) && y == uminor(NOUDEV)) 1951fd7b93fSPoul-Henning Kamp panic("makedev of NOUDEV"); 1963f54a085SPoul-Henning Kamp udev = (x << 8) | y; 1973f54a085SPoul-Henning Kamp hash = udev % DEVT_HASH; 1983f54a085SPoul-Henning Kamp LIST_FOREACH(si, &dev_hash[hash], si_hash) { 1993f54a085SPoul-Henning Kamp if (si->si_udev == udev) 2003f54a085SPoul-Henning Kamp return (si); 2013f54a085SPoul-Henning Kamp } 2023f54a085SPoul-Henning Kamp si = allocdev(); 203698bfad7SPoul-Henning Kamp si->si_udev = udev; 204d137acccSPoul-Henning Kamp LIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); 205698bfad7SPoul-Henning Kamp return (si); 206bfbb9ce6SPoul-Henning Kamp } 207bfbb9ce6SPoul-Henning Kamp 208d137acccSPoul-Henning Kamp void 209d137acccSPoul-Henning Kamp freedev(dev_t dev) 210d137acccSPoul-Henning Kamp { 2113f54a085SPoul-Henning Kamp dev_t adev; 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; 2193f54a085SPoul-Henning Kamp while (!LIST_EMPTY(&dev->si_names)) { 2203f54a085SPoul-Henning Kamp adev = LIST_FIRST(&dev->si_names); 2213f54a085SPoul-Henning Kamp adev->si_drv1 = NULL; 2223f54a085SPoul-Henning Kamp freedev(adev); 2233f54a085SPoul-Henning Kamp } 224d137acccSPoul-Henning Kamp LIST_REMOVE(dev, si_hash); 225d137acccSPoul-Henning Kamp if (dev->si_flags & SI_STASHED) { 226d137acccSPoul-Henning Kamp bzero(dev, sizeof(*dev)); 227d137acccSPoul-Henning Kamp LIST_INSERT_HEAD(&dev_free, dev, si_hash); 228d137acccSPoul-Henning Kamp } else { 229d137acccSPoul-Henning Kamp FREE(dev, M_DEVT); 230d137acccSPoul-Henning Kamp } 231d137acccSPoul-Henning Kamp } 232d137acccSPoul-Henning Kamp 233bfbb9ce6SPoul-Henning Kamp udev_t 234bfbb9ce6SPoul-Henning Kamp dev2udev(dev_t x) 235bfbb9ce6SPoul-Henning Kamp { 236698bfad7SPoul-Henning Kamp if (x == NODEV) 237698bfad7SPoul-Henning Kamp return NOUDEV; 238698bfad7SPoul-Henning Kamp return (x->si_udev); 239bfbb9ce6SPoul-Henning Kamp } 240bfbb9ce6SPoul-Henning Kamp 241bfbb9ce6SPoul-Henning Kamp dev_t 242bfbb9ce6SPoul-Henning Kamp udev2dev(udev_t x, int b) 243bfbb9ce6SPoul-Henning Kamp { 244fb01c24cSPoul-Henning Kamp 245fb01c24cSPoul-Henning Kamp if (x == NOUDEV) 246fb01c24cSPoul-Henning Kamp return (NODEV); 247d21c632cSPoul-Henning Kamp switch (b) { 248d21c632cSPoul-Henning Kamp case 0: 249bfbb9ce6SPoul-Henning Kamp return makedev(umajor(x), uminor(x)); 250d21c632cSPoul-Henning Kamp case 1: 251a16d0eb2SPoul-Henning Kamp return (NODEV); 252d21c632cSPoul-Henning Kamp default: 253d21c632cSPoul-Henning Kamp Debugger("udev2dev(...,X)"); 254d21c632cSPoul-Henning Kamp return NODEV; 255d21c632cSPoul-Henning Kamp } 256bfbb9ce6SPoul-Henning Kamp } 257bfbb9ce6SPoul-Henning Kamp 258bfbb9ce6SPoul-Henning Kamp int 259bfbb9ce6SPoul-Henning Kamp uminor(udev_t dev) 260bfbb9ce6SPoul-Henning Kamp { 261bfbb9ce6SPoul-Henning Kamp return(dev & 0xffff00ff); 262bfbb9ce6SPoul-Henning Kamp } 263bfbb9ce6SPoul-Henning Kamp 264bfbb9ce6SPoul-Henning Kamp int 265bfbb9ce6SPoul-Henning Kamp umajor(udev_t dev) 266bfbb9ce6SPoul-Henning Kamp { 267bfbb9ce6SPoul-Henning Kamp return((dev & 0xff00) >> 8); 268bfbb9ce6SPoul-Henning Kamp } 269bfbb9ce6SPoul-Henning Kamp 270bfbb9ce6SPoul-Henning Kamp udev_t 271f008cfccSPoul-Henning Kamp makeudev(int x, int y) 272bfbb9ce6SPoul-Henning Kamp { 273bfbb9ce6SPoul-Henning Kamp return ((x << 8) | y); 274bfbb9ce6SPoul-Henning Kamp } 275bfbb9ce6SPoul-Henning Kamp 2760ef1c826SPoul-Henning Kamp dev_t 2770ef1c826SPoul-Henning Kamp make_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, char *fmt, ...) 2780ef1c826SPoul-Henning Kamp { 2790ef1c826SPoul-Henning Kamp dev_t dev; 2800ef1c826SPoul-Henning Kamp va_list ap; 2810ef1c826SPoul-Henning Kamp int i; 2820ef1c826SPoul-Henning Kamp 28311586717SBrian Somers KASSERT(umajor(makeudev(devsw->d_maj, minor)) == devsw->d_maj, 28411586717SBrian Somers ("Invalid minor (%d) in make_dev", minor)); 28511586717SBrian Somers 2860ef1c826SPoul-Henning Kamp dev = makedev(devsw->d_maj, minor); 2875ef2707eSPoul-Henning Kamp if (dev->si_flags & SI_NAMED) { 2885ef2707eSPoul-Henning Kamp printf( "WARNING: Driver mistake: repeat make_dev(\"%s\")\n", 2895ef2707eSPoul-Henning Kamp dev->si_name); 2905ef2707eSPoul-Henning Kamp return (dev); 2915ef2707eSPoul-Henning Kamp } 2920ef1c826SPoul-Henning Kamp va_start(ap, fmt); 2938dc74b62SBoris Popov i = kvprintf(fmt, NULL, dev->si_name, 32, ap); 2940ef1c826SPoul-Henning Kamp dev->si_name[i] = '\0'; 2950ef1c826SPoul-Henning Kamp va_end(ap); 2960ef1c826SPoul-Henning Kamp dev->si_devsw = devsw; 2973f54a085SPoul-Henning Kamp dev->si_uid = uid; 2983f54a085SPoul-Henning Kamp dev->si_gid = gid; 2993f54a085SPoul-Henning Kamp dev->si_mode = perms; 3005ef2707eSPoul-Henning Kamp dev->si_flags |= SI_NAMED; 3011744fcd0SJulian Elischer 3029dcbe240SPoul-Henning Kamp if (devfs_create_hook) 3033f54a085SPoul-Henning Kamp devfs_create_hook(dev); 3043f54a085SPoul-Henning Kamp return (dev); 3053f54a085SPoul-Henning Kamp } 3063f54a085SPoul-Henning Kamp 3073f54a085SPoul-Henning Kamp dev_t 3083f54a085SPoul-Henning Kamp make_dev_alias(dev_t pdev, char *fmt, ...) 3093f54a085SPoul-Henning Kamp { 3103f54a085SPoul-Henning Kamp dev_t dev; 3113f54a085SPoul-Henning Kamp va_list ap; 3123f54a085SPoul-Henning Kamp int i; 3133f54a085SPoul-Henning Kamp 3143f54a085SPoul-Henning Kamp dev = allocdev(); 3153f54a085SPoul-Henning Kamp dev->si_flags |= SI_ALIAS; 3165ef2707eSPoul-Henning Kamp dev->si_flags |= SI_NAMED; 3173f54a085SPoul-Henning Kamp dev->si_drv1 = pdev; 3183f54a085SPoul-Henning Kamp LIST_INSERT_HEAD(&pdev->si_names, dev, si_hash); 3193f54a085SPoul-Henning Kamp 3203f54a085SPoul-Henning Kamp va_start(ap, fmt); 3213f54a085SPoul-Henning Kamp i = kvprintf(fmt, NULL, dev->si_name, 32, ap); 3223f54a085SPoul-Henning Kamp dev->si_name[i] = '\0'; 3233f54a085SPoul-Henning Kamp va_end(ap); 3243f54a085SPoul-Henning Kamp 3253f54a085SPoul-Henning Kamp if (devfs_create_hook) 3263f54a085SPoul-Henning Kamp devfs_create_hook(dev); 3270ef1c826SPoul-Henning Kamp return (dev); 3280ef1c826SPoul-Henning Kamp } 3290ef1c826SPoul-Henning Kamp 330d137acccSPoul-Henning Kamp void 33144d1184eSPoul-Henning Kamp destroy_dev(dev_t dev) 332d137acccSPoul-Henning Kamp { 3335ef2707eSPoul-Henning Kamp 3345ef2707eSPoul-Henning Kamp if (!(dev->si_flags & SI_NAMED)) { 3355ef2707eSPoul-Henning Kamp printf( "WARNING: Driver mistake: destroy_dev on %d/%d\n", 3365ef2707eSPoul-Henning Kamp major(dev), minor(dev)); 3375ef2707eSPoul-Henning Kamp return; 3385ef2707eSPoul-Henning Kamp } 3395ef2707eSPoul-Henning Kamp 340db901281SPoul-Henning Kamp if (devfs_destroy_hook) 341db901281SPoul-Henning Kamp devfs_destroy_hook(dev); 342d137acccSPoul-Henning Kamp dev->si_drv1 = 0; 343d137acccSPoul-Henning Kamp dev->si_drv2 = 0; 344d137acccSPoul-Henning Kamp dev->si_devsw = 0; 3455ef2707eSPoul-Henning Kamp dev->si_flags &= ~SI_NAMED; 3465ef2707eSPoul-Henning Kamp dev->si_flags &= ~SI_ALIAS; 347d137acccSPoul-Henning Kamp freedev(dev); 348d137acccSPoul-Henning Kamp } 349d137acccSPoul-Henning Kamp 350c32cc149SBruce Evans const char * 351b8e49f68SBill Fumerola devtoname(dev_t dev) 352b8e49f68SBill Fumerola { 353d137acccSPoul-Henning Kamp char *p; 354c32cc149SBruce Evans int mynor; 355b8e49f68SBill Fumerola 356d137acccSPoul-Henning Kamp if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') { 357d137acccSPoul-Henning Kamp p = dev->si_name; 358d137acccSPoul-Henning Kamp if (devsw(dev)) 359d137acccSPoul-Henning Kamp sprintf(p, "#%s/", devsw(dev)->d_name); 360d137acccSPoul-Henning Kamp else 361d137acccSPoul-Henning Kamp sprintf(p, "#%d/", major(dev)); 362d137acccSPoul-Henning Kamp p += strlen(p); 363c32cc149SBruce Evans mynor = minor(dev); 364c32cc149SBruce Evans if (mynor < 0 || mynor > 255) 365c32cc149SBruce Evans sprintf(p, "%#x", (u_int)mynor); 366c32cc149SBruce Evans else 367c32cc149SBruce Evans sprintf(p, "%d", mynor); 368d137acccSPoul-Henning Kamp } 369b8e49f68SBill Fumerola return (dev->si_name); 370b8e49f68SBill Fumerola } 371db901281SPoul-Henning Kamp 372db901281SPoul-Henning Kamp int 373db901281SPoul-Henning Kamp dev_stdclone(char *name, char **namep, char *stem, int *unit) 374db901281SPoul-Henning Kamp { 375db901281SPoul-Henning Kamp int u, i; 376db901281SPoul-Henning Kamp 377db901281SPoul-Henning Kamp i = strlen(stem); 37856700d46SBrian Somers if (bcmp(stem, name, i) != 0) 37956700d46SBrian Somers return (0); 380db901281SPoul-Henning Kamp if (!isdigit(name[i])) 381db901281SPoul-Henning Kamp return (0); 382db901281SPoul-Henning Kamp u = 0; 383db901281SPoul-Henning Kamp while (isdigit(name[i])) { 384db901281SPoul-Henning Kamp u *= 10; 385db901281SPoul-Henning Kamp u += name[i++] - '0'; 386db901281SPoul-Henning Kamp } 387db901281SPoul-Henning Kamp *unit = u; 388db901281SPoul-Henning Kamp if (namep) 389db901281SPoul-Henning Kamp *namep = &name[i]; 390db901281SPoul-Henning Kamp if (name[i]) 391db901281SPoul-Henning Kamp return (2); 392db901281SPoul-Henning Kamp return (1); 393db901281SPoul-Henning Kamp } 3948d25eb2cSPoul-Henning Kamp 3958d25eb2cSPoul-Henning Kamp /* 3968d25eb2cSPoul-Henning Kamp * Helper sysctl for devname(3). We're given a {u}dev_t and return 3978d25eb2cSPoul-Henning Kamp * the name, if any, registered by the device driver. 3988d25eb2cSPoul-Henning Kamp */ 3998d25eb2cSPoul-Henning Kamp static int 4008d25eb2cSPoul-Henning Kamp sysctl_devname(SYSCTL_HANDLER_ARGS) 4018d25eb2cSPoul-Henning Kamp { 4028d25eb2cSPoul-Henning Kamp int error; 4038d25eb2cSPoul-Henning Kamp udev_t ud; 4048d25eb2cSPoul-Henning Kamp dev_t dev; 4058d25eb2cSPoul-Henning Kamp 4068d25eb2cSPoul-Henning Kamp error = SYSCTL_IN(req, &ud, sizeof (ud)); 4078d25eb2cSPoul-Henning Kamp if (error) 4088d25eb2cSPoul-Henning Kamp return (error); 4091fd7b93fSPoul-Henning Kamp if (ud == NOUDEV) 4101fd7b93fSPoul-Henning Kamp return(EINVAL); 4118d25eb2cSPoul-Henning Kamp dev = makedev(umajor(ud), uminor(ud)); 4128d25eb2cSPoul-Henning Kamp if (dev->si_name[0] == '\0') 4138d25eb2cSPoul-Henning Kamp error = ENOENT; 4148d25eb2cSPoul-Henning Kamp else 4158d25eb2cSPoul-Henning Kamp error = SYSCTL_OUT(req, dev->si_name, strlen(dev->si_name) + 1); 4168d25eb2cSPoul-Henning Kamp freedev(dev); 4178d25eb2cSPoul-Henning Kamp return (error); 4188d25eb2cSPoul-Henning Kamp } 4198d25eb2cSPoul-Henning Kamp 420fe4e3243SPoul-Henning Kamp SYSCTL_PROC(_kern, OID_AUTO, devname, CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY, 4218d25eb2cSPoul-Henning Kamp NULL, 0, sysctl_devname, "", "devname(3) handler"); 4228d25eb2cSPoul-Henning Kamp 423