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 162b0d17ba6SPoul-Henning Kamp return ((unit & 0xff) | ((unit << 8) & ~0xffff)); 163b0d17ba6SPoul-Henning Kamp } 164b0d17ba6SPoul-Henning Kamp 1653f54a085SPoul-Henning Kamp static dev_t 1663f54a085SPoul-Henning Kamp allocdev(void) 167bfbb9ce6SPoul-Henning Kamp { 168698bfad7SPoul-Henning Kamp static int stashed; 1693f54a085SPoul-Henning Kamp struct specinfo *si; 170698bfad7SPoul-Henning Kamp 171698bfad7SPoul-Henning Kamp if (stashed >= DEVT_STASH) { 172698bfad7SPoul-Henning Kamp MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT, 1737cc0979fSDavid Malone M_USE_RESERVE | M_ZERO); 174d137acccSPoul-Henning Kamp } else if (LIST_FIRST(&dev_free)) { 175d137acccSPoul-Henning Kamp si = LIST_FIRST(&dev_free); 176d137acccSPoul-Henning Kamp LIST_REMOVE(si, si_hash); 177698bfad7SPoul-Henning Kamp } else { 178698bfad7SPoul-Henning Kamp si = devt_stash + stashed++; 179d137acccSPoul-Henning Kamp si->si_flags |= SI_STASHED; 180698bfad7SPoul-Henning Kamp } 1813f54a085SPoul-Henning Kamp LIST_INIT(&si->si_names); 1823f54a085SPoul-Henning Kamp return (si); 1833f54a085SPoul-Henning Kamp } 1843f54a085SPoul-Henning Kamp 1853f54a085SPoul-Henning Kamp dev_t 1863f54a085SPoul-Henning Kamp makedev(int x, int y) 1873f54a085SPoul-Henning Kamp { 1883f54a085SPoul-Henning Kamp struct specinfo *si; 1893f54a085SPoul-Henning Kamp udev_t udev; 1903f54a085SPoul-Henning Kamp int hash; 1913f54a085SPoul-Henning Kamp 1923f54a085SPoul-Henning Kamp if (x == umajor(NOUDEV) && y == uminor(NOUDEV)) 1931fd7b93fSPoul-Henning Kamp panic("makedev of NOUDEV"); 1943f54a085SPoul-Henning Kamp udev = (x << 8) | y; 1953f54a085SPoul-Henning Kamp hash = udev % DEVT_HASH; 1963f54a085SPoul-Henning Kamp LIST_FOREACH(si, &dev_hash[hash], si_hash) { 1973f54a085SPoul-Henning Kamp if (si->si_udev == udev) 1983f54a085SPoul-Henning Kamp return (si); 1993f54a085SPoul-Henning Kamp } 2003f54a085SPoul-Henning Kamp si = allocdev(); 201698bfad7SPoul-Henning Kamp si->si_udev = udev; 202d137acccSPoul-Henning Kamp LIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); 203698bfad7SPoul-Henning Kamp return (si); 204bfbb9ce6SPoul-Henning Kamp } 205bfbb9ce6SPoul-Henning Kamp 206d137acccSPoul-Henning Kamp void 207d137acccSPoul-Henning Kamp freedev(dev_t dev) 208d137acccSPoul-Henning Kamp { 2093f54a085SPoul-Henning Kamp dev_t adev; 210d137acccSPoul-Henning Kamp 211d137acccSPoul-Henning Kamp if (!free_devt) 212d137acccSPoul-Henning Kamp return; 213d137acccSPoul-Henning Kamp if (SLIST_FIRST(&dev->si_hlist)) 214d137acccSPoul-Henning Kamp return; 215d137acccSPoul-Henning Kamp if (dev->si_devsw || dev->si_drv1 || dev->si_drv2) 216d137acccSPoul-Henning Kamp return; 2173f54a085SPoul-Henning Kamp while (!LIST_EMPTY(&dev->si_names)) { 2183f54a085SPoul-Henning Kamp adev = LIST_FIRST(&dev->si_names); 2193f54a085SPoul-Henning Kamp adev->si_drv1 = NULL; 2203f54a085SPoul-Henning Kamp freedev(adev); 2213f54a085SPoul-Henning Kamp } 222d137acccSPoul-Henning Kamp LIST_REMOVE(dev, si_hash); 223d137acccSPoul-Henning Kamp if (dev->si_flags & SI_STASHED) { 224d137acccSPoul-Henning Kamp bzero(dev, sizeof(*dev)); 225d137acccSPoul-Henning Kamp LIST_INSERT_HEAD(&dev_free, dev, si_hash); 226d137acccSPoul-Henning Kamp } else { 227d137acccSPoul-Henning Kamp FREE(dev, M_DEVT); 228d137acccSPoul-Henning Kamp } 229d137acccSPoul-Henning Kamp } 230d137acccSPoul-Henning Kamp 231bfbb9ce6SPoul-Henning Kamp udev_t 232bfbb9ce6SPoul-Henning Kamp dev2udev(dev_t x) 233bfbb9ce6SPoul-Henning Kamp { 234698bfad7SPoul-Henning Kamp if (x == NODEV) 235698bfad7SPoul-Henning Kamp return NOUDEV; 236698bfad7SPoul-Henning Kamp return (x->si_udev); 237bfbb9ce6SPoul-Henning Kamp } 238bfbb9ce6SPoul-Henning Kamp 239bfbb9ce6SPoul-Henning Kamp dev_t 240bfbb9ce6SPoul-Henning Kamp udev2dev(udev_t x, int b) 241bfbb9ce6SPoul-Henning Kamp { 242fb01c24cSPoul-Henning Kamp 243fb01c24cSPoul-Henning Kamp if (x == NOUDEV) 244fb01c24cSPoul-Henning Kamp return (NODEV); 245d21c632cSPoul-Henning Kamp switch (b) { 246d21c632cSPoul-Henning Kamp case 0: 247bfbb9ce6SPoul-Henning Kamp return makedev(umajor(x), uminor(x)); 248d21c632cSPoul-Henning Kamp case 1: 249a16d0eb2SPoul-Henning Kamp return (NODEV); 250d21c632cSPoul-Henning Kamp default: 251d21c632cSPoul-Henning Kamp Debugger("udev2dev(...,X)"); 252d21c632cSPoul-Henning Kamp return NODEV; 253d21c632cSPoul-Henning Kamp } 254bfbb9ce6SPoul-Henning Kamp } 255bfbb9ce6SPoul-Henning Kamp 256bfbb9ce6SPoul-Henning Kamp int 257bfbb9ce6SPoul-Henning Kamp uminor(udev_t dev) 258bfbb9ce6SPoul-Henning Kamp { 259bfbb9ce6SPoul-Henning Kamp return(dev & 0xffff00ff); 260bfbb9ce6SPoul-Henning Kamp } 261bfbb9ce6SPoul-Henning Kamp 262bfbb9ce6SPoul-Henning Kamp int 263bfbb9ce6SPoul-Henning Kamp umajor(udev_t dev) 264bfbb9ce6SPoul-Henning Kamp { 265bfbb9ce6SPoul-Henning Kamp return((dev & 0xff00) >> 8); 266bfbb9ce6SPoul-Henning Kamp } 267bfbb9ce6SPoul-Henning Kamp 268bfbb9ce6SPoul-Henning Kamp udev_t 269f008cfccSPoul-Henning Kamp makeudev(int x, int y) 270bfbb9ce6SPoul-Henning Kamp { 271bfbb9ce6SPoul-Henning Kamp return ((x << 8) | y); 272bfbb9ce6SPoul-Henning Kamp } 273bfbb9ce6SPoul-Henning Kamp 2740ef1c826SPoul-Henning Kamp dev_t 2750ef1c826SPoul-Henning Kamp make_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, char *fmt, ...) 2760ef1c826SPoul-Henning Kamp { 2770ef1c826SPoul-Henning Kamp dev_t dev; 2780ef1c826SPoul-Henning Kamp va_list ap; 2790ef1c826SPoul-Henning Kamp int i; 2800ef1c826SPoul-Henning Kamp 28111586717SBrian Somers KASSERT(umajor(makeudev(devsw->d_maj, minor)) == devsw->d_maj, 28211586717SBrian Somers ("Invalid minor (%d) in make_dev", minor)); 28311586717SBrian Somers 2840ef1c826SPoul-Henning Kamp dev = makedev(devsw->d_maj, minor); 2855ef2707eSPoul-Henning Kamp if (dev->si_flags & SI_NAMED) { 2865ef2707eSPoul-Henning Kamp printf( "WARNING: Driver mistake: repeat make_dev(\"%s\")\n", 2875ef2707eSPoul-Henning Kamp dev->si_name); 2885ef2707eSPoul-Henning Kamp return (dev); 2895ef2707eSPoul-Henning Kamp } 2900ef1c826SPoul-Henning Kamp va_start(ap, fmt); 2918dc74b62SBoris Popov i = kvprintf(fmt, NULL, dev->si_name, 32, ap); 2920ef1c826SPoul-Henning Kamp dev->si_name[i] = '\0'; 2930ef1c826SPoul-Henning Kamp va_end(ap); 2940ef1c826SPoul-Henning Kamp dev->si_devsw = devsw; 2953f54a085SPoul-Henning Kamp dev->si_uid = uid; 2963f54a085SPoul-Henning Kamp dev->si_gid = gid; 2973f54a085SPoul-Henning Kamp dev->si_mode = perms; 2985ef2707eSPoul-Henning Kamp dev->si_flags |= SI_NAMED; 2991744fcd0SJulian Elischer 3009dcbe240SPoul-Henning Kamp if (devfs_create_hook) 3013f54a085SPoul-Henning Kamp devfs_create_hook(dev); 3023f54a085SPoul-Henning Kamp return (dev); 3033f54a085SPoul-Henning Kamp } 3043f54a085SPoul-Henning Kamp 3053f54a085SPoul-Henning Kamp dev_t 3063f54a085SPoul-Henning Kamp make_dev_alias(dev_t pdev, char *fmt, ...) 3073f54a085SPoul-Henning Kamp { 3083f54a085SPoul-Henning Kamp dev_t dev; 3093f54a085SPoul-Henning Kamp va_list ap; 3103f54a085SPoul-Henning Kamp int i; 3113f54a085SPoul-Henning Kamp 3123f54a085SPoul-Henning Kamp dev = allocdev(); 3133f54a085SPoul-Henning Kamp dev->si_flags |= SI_ALIAS; 3145ef2707eSPoul-Henning Kamp dev->si_flags |= SI_NAMED; 3153f54a085SPoul-Henning Kamp dev->si_drv1 = pdev; 3163f54a085SPoul-Henning Kamp LIST_INSERT_HEAD(&pdev->si_names, dev, si_hash); 3173f54a085SPoul-Henning Kamp 3183f54a085SPoul-Henning Kamp va_start(ap, fmt); 3193f54a085SPoul-Henning Kamp i = kvprintf(fmt, NULL, dev->si_name, 32, ap); 3203f54a085SPoul-Henning Kamp dev->si_name[i] = '\0'; 3213f54a085SPoul-Henning Kamp va_end(ap); 3223f54a085SPoul-Henning Kamp 3233f54a085SPoul-Henning Kamp if (devfs_create_hook) 3243f54a085SPoul-Henning Kamp devfs_create_hook(dev); 3250ef1c826SPoul-Henning Kamp return (dev); 3260ef1c826SPoul-Henning Kamp } 3270ef1c826SPoul-Henning Kamp 328d137acccSPoul-Henning Kamp void 32944d1184eSPoul-Henning Kamp destroy_dev(dev_t dev) 330d137acccSPoul-Henning Kamp { 3315ef2707eSPoul-Henning Kamp 3325ef2707eSPoul-Henning Kamp if (!(dev->si_flags & SI_NAMED)) { 3335ef2707eSPoul-Henning Kamp printf( "WARNING: Driver mistake: destroy_dev on %d/%d\n", 3345ef2707eSPoul-Henning Kamp major(dev), minor(dev)); 3355ef2707eSPoul-Henning Kamp return; 3365ef2707eSPoul-Henning Kamp } 3375ef2707eSPoul-Henning Kamp 338db901281SPoul-Henning Kamp if (devfs_destroy_hook) 339db901281SPoul-Henning Kamp devfs_destroy_hook(dev); 340d137acccSPoul-Henning Kamp dev->si_drv1 = 0; 341d137acccSPoul-Henning Kamp dev->si_drv2 = 0; 342d137acccSPoul-Henning Kamp dev->si_devsw = 0; 3435ef2707eSPoul-Henning Kamp dev->si_flags &= ~SI_NAMED; 3445ef2707eSPoul-Henning Kamp dev->si_flags &= ~SI_ALIAS; 345d137acccSPoul-Henning Kamp freedev(dev); 346d137acccSPoul-Henning Kamp } 347d137acccSPoul-Henning Kamp 348c32cc149SBruce Evans const char * 349b8e49f68SBill Fumerola devtoname(dev_t dev) 350b8e49f68SBill Fumerola { 351d137acccSPoul-Henning Kamp char *p; 352c32cc149SBruce Evans int mynor; 353b8e49f68SBill Fumerola 354d137acccSPoul-Henning Kamp if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') { 355d137acccSPoul-Henning Kamp p = dev->si_name; 356d137acccSPoul-Henning Kamp if (devsw(dev)) 357d137acccSPoul-Henning Kamp sprintf(p, "#%s/", devsw(dev)->d_name); 358d137acccSPoul-Henning Kamp else 359d137acccSPoul-Henning Kamp sprintf(p, "#%d/", major(dev)); 360d137acccSPoul-Henning Kamp p += strlen(p); 361c32cc149SBruce Evans mynor = minor(dev); 362c32cc149SBruce Evans if (mynor < 0 || mynor > 255) 363c32cc149SBruce Evans sprintf(p, "%#x", (u_int)mynor); 364c32cc149SBruce Evans else 365c32cc149SBruce Evans sprintf(p, "%d", mynor); 366d137acccSPoul-Henning Kamp } 367b8e49f68SBill Fumerola return (dev->si_name); 368b8e49f68SBill Fumerola } 369db901281SPoul-Henning Kamp 370db901281SPoul-Henning Kamp int 371db901281SPoul-Henning Kamp dev_stdclone(char *name, char **namep, char *stem, int *unit) 372db901281SPoul-Henning Kamp { 373db901281SPoul-Henning Kamp int u, i; 374db901281SPoul-Henning Kamp 375db901281SPoul-Henning Kamp if (bcmp(stem, name, strlen(stem)) != 0) 376db901281SPoul-Henning Kamp return (0); 377db901281SPoul-Henning Kamp i = strlen(stem); 378db901281SPoul-Henning Kamp if (!isdigit(name[i])) 379db901281SPoul-Henning Kamp return (0); 380db901281SPoul-Henning Kamp u = 0; 381db901281SPoul-Henning Kamp while (isdigit(name[i])) { 382db901281SPoul-Henning Kamp u *= 10; 383db901281SPoul-Henning Kamp u += name[i++] - '0'; 384db901281SPoul-Henning Kamp } 385db901281SPoul-Henning Kamp *unit = u; 386db901281SPoul-Henning Kamp if (namep) 387db901281SPoul-Henning Kamp *namep = &name[i]; 388db901281SPoul-Henning Kamp if (name[i]) 389db901281SPoul-Henning Kamp return (2); 390db901281SPoul-Henning Kamp return (1); 391db901281SPoul-Henning Kamp } 3928d25eb2cSPoul-Henning Kamp 3938d25eb2cSPoul-Henning Kamp /* 3948d25eb2cSPoul-Henning Kamp * Helper sysctl for devname(3). We're given a {u}dev_t and return 3958d25eb2cSPoul-Henning Kamp * the name, if any, registered by the device driver. 3968d25eb2cSPoul-Henning Kamp */ 3978d25eb2cSPoul-Henning Kamp static int 3988d25eb2cSPoul-Henning Kamp sysctl_devname(SYSCTL_HANDLER_ARGS) 3998d25eb2cSPoul-Henning Kamp { 4008d25eb2cSPoul-Henning Kamp int error; 4018d25eb2cSPoul-Henning Kamp udev_t ud; 4028d25eb2cSPoul-Henning Kamp dev_t dev; 4038d25eb2cSPoul-Henning Kamp 4048d25eb2cSPoul-Henning Kamp error = SYSCTL_IN(req, &ud, sizeof (ud)); 4058d25eb2cSPoul-Henning Kamp if (error) 4068d25eb2cSPoul-Henning Kamp return (error); 4071fd7b93fSPoul-Henning Kamp if (ud == NOUDEV) 4081fd7b93fSPoul-Henning Kamp return(EINVAL); 4098d25eb2cSPoul-Henning Kamp dev = makedev(umajor(ud), uminor(ud)); 4108d25eb2cSPoul-Henning Kamp if (dev->si_name[0] == '\0') 4118d25eb2cSPoul-Henning Kamp error = ENOENT; 4128d25eb2cSPoul-Henning Kamp else 4138d25eb2cSPoul-Henning Kamp error = SYSCTL_OUT(req, dev->si_name, strlen(dev->si_name) + 1); 4148d25eb2cSPoul-Henning Kamp freedev(dev); 4158d25eb2cSPoul-Henning Kamp return (error); 4168d25eb2cSPoul-Henning Kamp } 4178d25eb2cSPoul-Henning Kamp 418fe4e3243SPoul-Henning Kamp SYSCTL_PROC(_kern, OID_AUTO, devname, CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY, 4198d25eb2cSPoul-Henning Kamp NULL, 0, sysctl_devname, "", "devname(3) handler"); 4208d25eb2cSPoul-Henning Kamp 421