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 * 33b8e49f68SBill Fumerola * $Id: kern_conf.c,v 1.57 1999/08/15 09:32:47 phk Exp $ 3426453f35SJulian Elischer */ 3526453f35SJulian Elischer 3626453f35SJulian Elischer #include <sys/param.h> 37698bfad7SPoul-Henning Kamp #include <sys/kernel.h> 38f8a760b3SJulian Elischer #include <sys/systm.h> 39ecbb00a2SDoug Rabson #include <sys/module.h> 40698bfad7SPoul-Henning Kamp #include <sys/malloc.h> 4126453f35SJulian Elischer #include <sys/conf.h> 421dfcbb0cSJulian Elischer #include <sys/vnode.h> 43698bfad7SPoul-Henning Kamp #include <sys/queue.h> 440ef1c826SPoul-Henning Kamp #include <machine/stdarg.h> 451dfcbb0cSJulian Elischer 462447bec8SPoul-Henning Kamp #define cdevsw_ALLOCSTART (NUMCDEVSW/2) 471dfcbb0cSJulian Elischer 482447bec8SPoul-Henning Kamp struct cdevsw *cdevsw[NUMCDEVSW]; 491dfcbb0cSJulian Elischer 50698bfad7SPoul-Henning Kamp static int bmaj2cmaj[NUMCDEVSW]; 51698bfad7SPoul-Henning Kamp 52698bfad7SPoul-Henning Kamp MALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage"); 53698bfad7SPoul-Henning Kamp 54698bfad7SPoul-Henning Kamp #define DEVT_HASH 83 55698bfad7SPoul-Henning Kamp #define DEVT_STASH 50 56698bfad7SPoul-Henning Kamp 57698bfad7SPoul-Henning Kamp static struct specinfo devt_stash[DEVT_STASH]; 58698bfad7SPoul-Henning Kamp 59698bfad7SPoul-Henning Kamp static SLIST_HEAD(devt_hash_head, specinfo) dev_hash[DEVT_HASH]; 6046eede00SPoul-Henning Kamp 611dfcbb0cSJulian Elischer /* 621dfcbb0cSJulian Elischer * Routine to convert from character to block device number. 631dfcbb0cSJulian Elischer * 641dfcbb0cSJulian Elischer * A minimal stub routine can always return NODEV. 651dfcbb0cSJulian Elischer */ 661dfcbb0cSJulian Elischer dev_t 671dfcbb0cSJulian Elischer chrtoblk(dev_t dev) 681dfcbb0cSJulian Elischer { 691dfcbb0cSJulian Elischer struct cdevsw *cd; 701dfcbb0cSJulian Elischer 714be2eb8cSPoul-Henning Kamp if((cd = devsw(dev)) != NULL) { 72f7ea2f55SJulian Elischer if (cd->d_bmaj != -1) 73d21c632cSPoul-Henning Kamp return(makebdev(cd->d_bmaj,minor(dev))); 741dfcbb0cSJulian Elischer } 751dfcbb0cSJulian Elischer return(NODEV); 761dfcbb0cSJulian Elischer } 7726453f35SJulian Elischer 782447bec8SPoul-Henning Kamp struct cdevsw * 792447bec8SPoul-Henning Kamp devsw(dev_t dev) 802447bec8SPoul-Henning Kamp { 817dc5cd04SPoul-Henning Kamp if (dev->si_devsw) 827dc5cd04SPoul-Henning Kamp return (dev->si_devsw); 833de280c4SPoul-Henning Kamp return(cdevsw[major(dev)]); 842447bec8SPoul-Henning Kamp } 852447bec8SPoul-Henning Kamp 862447bec8SPoul-Henning Kamp /* 872447bec8SPoul-Henning Kamp * Add a cdevsw entry 882447bec8SPoul-Henning Kamp */ 892447bec8SPoul-Henning Kamp 90f7ea2f55SJulian Elischer int 912447bec8SPoul-Henning Kamp cdevsw_add(struct cdevsw *newentry) 92f7ea2f55SJulian Elischer { 93f7ea2f55SJulian Elischer int i; 94bfbb9ce6SPoul-Henning Kamp static int setup; 95bfbb9ce6SPoul-Henning Kamp 96bfbb9ce6SPoul-Henning Kamp if (!setup) { 972447bec8SPoul-Henning Kamp for (i = 0; i < NUMCDEVSW; i++) 98bfbb9ce6SPoul-Henning Kamp if (!bmaj2cmaj[i]) 99698bfad7SPoul-Henning Kamp bmaj2cmaj[i] = 254; 100bfbb9ce6SPoul-Henning Kamp setup++; 101bfbb9ce6SPoul-Henning Kamp } 102f7ea2f55SJulian Elischer 1032447bec8SPoul-Henning Kamp if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) { 1042447bec8SPoul-Henning Kamp printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 1052447bec8SPoul-Henning Kamp newentry->d_name, newentry->d_maj); 106f7ea2f55SJulian Elischer return EINVAL; 107f7ea2f55SJulian Elischer } 108f7ea2f55SJulian Elischer 109c31558b2SPoul-Henning Kamp if (cdevsw[newentry->d_maj]) { 110c31558b2SPoul-Henning Kamp printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n", 111c31558b2SPoul-Henning Kamp newentry->d_name, cdevsw[newentry->d_maj]->d_name); 112c31558b2SPoul-Henning Kamp } 1132447bec8SPoul-Henning Kamp cdevsw[newentry->d_maj] = newentry; 114f7ea2f55SJulian Elischer 115c31558b2SPoul-Henning Kamp if (newentry->d_bmaj >= 0 && newentry->d_bmaj < NUMCDEVSW) { 116698bfad7SPoul-Henning Kamp if (bmaj2cmaj[newentry->d_bmaj] != 254) { 117c31558b2SPoul-Henning Kamp printf("WARNING: \"%s\" is usurping \"%s\"'s bmaj\n", 118c31558b2SPoul-Henning Kamp newentry->d_name, 119c31558b2SPoul-Henning Kamp cdevsw[bmaj2cmaj[newentry->d_bmaj]]->d_name); 120c31558b2SPoul-Henning Kamp } 1212447bec8SPoul-Henning Kamp bmaj2cmaj[newentry->d_bmaj] = newentry->d_maj; 122c31558b2SPoul-Henning Kamp } 1232447bec8SPoul-Henning Kamp 124f7ea2f55SJulian Elischer return 0; 125f7ea2f55SJulian Elischer } 126f7ea2f55SJulian Elischer 1279a9eb2b9SGreg Lehey /* 1289a9eb2b9SGreg Lehey * Remove a cdevsw entry 1299a9eb2b9SGreg Lehey */ 1309a9eb2b9SGreg Lehey 1319a9eb2b9SGreg Lehey int 1329a9eb2b9SGreg Lehey cdevsw_remove(struct cdevsw *oldentry) 1339a9eb2b9SGreg Lehey { 1349a9eb2b9SGreg Lehey if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) { 1359a9eb2b9SGreg Lehey printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 1369a9eb2b9SGreg Lehey oldentry->d_name, oldentry->d_maj); 1379a9eb2b9SGreg Lehey return EINVAL; 1389a9eb2b9SGreg Lehey } 1399a9eb2b9SGreg Lehey 1409a9eb2b9SGreg Lehey cdevsw[oldentry->d_maj] = NULL; 1419a9eb2b9SGreg Lehey 1429a9eb2b9SGreg Lehey if (oldentry->d_bmaj >= 0 && oldentry->d_bmaj < NUMCDEVSW) 14332c0c324SGreg Lehey bmaj2cmaj[oldentry->d_bmaj] = 254; 1449a9eb2b9SGreg Lehey 1459a9eb2b9SGreg Lehey return 0; 1469a9eb2b9SGreg Lehey } 1479a9eb2b9SGreg Lehey 148ecbb00a2SDoug Rabson int 14946eede00SPoul-Henning Kamp devsw_module_handler(module_t mod, int what, void* arg) 150ecbb00a2SDoug Rabson { 15146eede00SPoul-Henning Kamp struct devsw_module_data* data = (struct devsw_module_data*) arg; 1526d4ce7aaSDoug Rabson int error = 0; 153ecbb00a2SDoug Rabson 154ecbb00a2SDoug Rabson switch (what) { 155ecbb00a2SDoug Rabson case MOD_LOAD: 1562447bec8SPoul-Henning Kamp error = cdevsw_add(data->cdevsw); 1576ca34d85SDoug Rabson if (!error && data->chainevh) 1586ca34d85SDoug Rabson error = data->chainevh(mod, what, data->chainarg); 159ecbb00a2SDoug Rabson return error; 160ecbb00a2SDoug Rabson 161ecbb00a2SDoug Rabson case MOD_UNLOAD: 1626ca34d85SDoug Rabson if (data->chainevh) { 1636ca34d85SDoug Rabson error = data->chainevh(mod, what, data->chainarg); 1646ca34d85SDoug Rabson if (error) 165ecbb00a2SDoug Rabson return error; 1666ca34d85SDoug Rabson } 1676d4ce7aaSDoug Rabson cdevsw_remove(data->cdevsw); 168f7ea2f55SJulian Elischer return error; 169ecbb00a2SDoug Rabson } 170ecbb00a2SDoug Rabson 171ecbb00a2SDoug Rabson if (data->chainevh) 172ecbb00a2SDoug Rabson return data->chainevh(mod, what, data->chainarg); 173ecbb00a2SDoug Rabson else 174ecbb00a2SDoug Rabson return 0; 175ecbb00a2SDoug Rabson } 176bfbb9ce6SPoul-Henning Kamp 177bfbb9ce6SPoul-Henning Kamp /* 178bfbb9ce6SPoul-Henning Kamp * dev_t and u_dev_t primitives 179bfbb9ce6SPoul-Henning Kamp */ 180bfbb9ce6SPoul-Henning Kamp 181bfbb9ce6SPoul-Henning Kamp int 182bfbb9ce6SPoul-Henning Kamp major(dev_t x) 183bfbb9ce6SPoul-Henning Kamp { 184698bfad7SPoul-Henning Kamp if (x == NODEV) 185698bfad7SPoul-Henning Kamp return NOUDEV; 186698bfad7SPoul-Henning Kamp return((x->si_udev >> 8) & 0xff); 187bfbb9ce6SPoul-Henning Kamp } 188bfbb9ce6SPoul-Henning Kamp 189bfbb9ce6SPoul-Henning Kamp int 190bfbb9ce6SPoul-Henning Kamp minor(dev_t x) 191bfbb9ce6SPoul-Henning Kamp { 192698bfad7SPoul-Henning Kamp if (x == NODEV) 193698bfad7SPoul-Henning Kamp return NOUDEV; 194698bfad7SPoul-Henning Kamp return(x->si_udev & 0xffff00ff); 195bfbb9ce6SPoul-Henning Kamp } 196bfbb9ce6SPoul-Henning Kamp 1979a27d579SPoul-Henning Kamp int 1989a27d579SPoul-Henning Kamp lminor(dev_t x) 1999a27d579SPoul-Henning Kamp { 2009a27d579SPoul-Henning Kamp int i; 2019a27d579SPoul-Henning Kamp 2029a27d579SPoul-Henning Kamp if (x == NODEV) 2039a27d579SPoul-Henning Kamp return NOUDEV; 2049a27d579SPoul-Henning Kamp i = minor(x); 2059a27d579SPoul-Henning Kamp return ((i & 0xff) | (i >> 8)); 2069a27d579SPoul-Henning Kamp } 2079a27d579SPoul-Henning Kamp 208bfbb9ce6SPoul-Henning Kamp dev_t 2096fcd8a7cSPoul-Henning Kamp makebdev(int x, int y) 2106fcd8a7cSPoul-Henning Kamp { 2113de280c4SPoul-Henning Kamp return (makedev(bmaj2cmaj[x], y)); 2126fcd8a7cSPoul-Henning Kamp } 2136fcd8a7cSPoul-Henning Kamp 2146fcd8a7cSPoul-Henning Kamp dev_t 215bfbb9ce6SPoul-Henning Kamp makedev(int x, int y) 216bfbb9ce6SPoul-Henning Kamp { 217698bfad7SPoul-Henning Kamp struct specinfo *si; 218698bfad7SPoul-Henning Kamp udev_t udev; 219698bfad7SPoul-Henning Kamp int hash; 220698bfad7SPoul-Henning Kamp static int stashed; 221698bfad7SPoul-Henning Kamp 222698bfad7SPoul-Henning Kamp udev = (x << 8) | y; 223698bfad7SPoul-Henning Kamp hash = udev % DEVT_HASH; 224698bfad7SPoul-Henning Kamp SLIST_FOREACH(si, &dev_hash[hash], si_hash) { 225698bfad7SPoul-Henning Kamp if (si->si_udev == udev) 226698bfad7SPoul-Henning Kamp return (si); 227698bfad7SPoul-Henning Kamp } 228698bfad7SPoul-Henning Kamp if (stashed >= DEVT_STASH) { 229698bfad7SPoul-Henning Kamp MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT, 230698bfad7SPoul-Henning Kamp M_USE_RESERVE); 231698bfad7SPoul-Henning Kamp } else { 232698bfad7SPoul-Henning Kamp si = devt_stash + stashed++; 233698bfad7SPoul-Henning Kamp } 234698bfad7SPoul-Henning Kamp bzero(si, sizeof(*si)); 235698bfad7SPoul-Henning Kamp si->si_udev = udev; 236698bfad7SPoul-Henning Kamp si->si_bsize_phys = DEV_BSIZE; 237698bfad7SPoul-Henning Kamp si->si_bsize_best = BLKDEV_IOSIZE; 238698bfad7SPoul-Henning Kamp si->si_bsize_max = MAXBSIZE; 2390ef1c826SPoul-Henning Kamp if (y > 256) 2400ef1c826SPoul-Henning Kamp sprintf(si->si_name, "#%d/0x%x", x, y); 2410ef1c826SPoul-Henning Kamp else 2420ef1c826SPoul-Henning Kamp sprintf(si->si_name, "#%d/%d", x, y); 243698bfad7SPoul-Henning Kamp SLIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); 244698bfad7SPoul-Henning Kamp return (si); 245bfbb9ce6SPoul-Henning Kamp } 246bfbb9ce6SPoul-Henning Kamp 247bfbb9ce6SPoul-Henning Kamp udev_t 248bfbb9ce6SPoul-Henning Kamp dev2udev(dev_t x) 249bfbb9ce6SPoul-Henning Kamp { 250698bfad7SPoul-Henning Kamp if (x == NODEV) 251698bfad7SPoul-Henning Kamp return NOUDEV; 252698bfad7SPoul-Henning Kamp return (x->si_udev); 253bfbb9ce6SPoul-Henning Kamp } 254bfbb9ce6SPoul-Henning Kamp 255fb30b5bdSBrian Feldman udev_t 256fb30b5bdSBrian Feldman dev2budev(dev_t x) 257fb30b5bdSBrian Feldman { 25857d86fc6SBrian Feldman if (x == NODEV) 259fb30b5bdSBrian Feldman return NOUDEV; 260fb30b5bdSBrian Feldman else 261fb30b5bdSBrian Feldman return makeudev(devsw(x)->d_bmaj, minor(x)); 262fb30b5bdSBrian Feldman } 263fb30b5bdSBrian Feldman 264bfbb9ce6SPoul-Henning Kamp dev_t 265bfbb9ce6SPoul-Henning Kamp udev2dev(udev_t x, int b) 266bfbb9ce6SPoul-Henning Kamp { 267d21c632cSPoul-Henning Kamp switch (b) { 268d21c632cSPoul-Henning Kamp case 0: 269bfbb9ce6SPoul-Henning Kamp return makedev(umajor(x), uminor(x)); 270d21c632cSPoul-Henning Kamp case 1: 271d21c632cSPoul-Henning Kamp return makebdev(umajor(x), uminor(x)); 272d21c632cSPoul-Henning Kamp default: 273d21c632cSPoul-Henning Kamp Debugger("udev2dev(...,X)"); 274d21c632cSPoul-Henning Kamp return NODEV; 275d21c632cSPoul-Henning Kamp } 276bfbb9ce6SPoul-Henning Kamp } 277bfbb9ce6SPoul-Henning Kamp 278bfbb9ce6SPoul-Henning Kamp int 279bfbb9ce6SPoul-Henning Kamp uminor(udev_t dev) 280bfbb9ce6SPoul-Henning Kamp { 281bfbb9ce6SPoul-Henning Kamp return(dev & 0xffff00ff); 282bfbb9ce6SPoul-Henning Kamp } 283bfbb9ce6SPoul-Henning Kamp 284bfbb9ce6SPoul-Henning Kamp int 285bfbb9ce6SPoul-Henning Kamp umajor(udev_t dev) 286bfbb9ce6SPoul-Henning Kamp { 287bfbb9ce6SPoul-Henning Kamp return((dev & 0xff00) >> 8); 288bfbb9ce6SPoul-Henning Kamp } 289bfbb9ce6SPoul-Henning Kamp 290bfbb9ce6SPoul-Henning Kamp udev_t 291f008cfccSPoul-Henning Kamp makeudev(int x, int y) 292bfbb9ce6SPoul-Henning Kamp { 293bfbb9ce6SPoul-Henning Kamp return ((x << 8) | y); 294bfbb9ce6SPoul-Henning Kamp } 295bfbb9ce6SPoul-Henning Kamp 2960ef1c826SPoul-Henning Kamp dev_t 2970ef1c826SPoul-Henning Kamp make_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, char *fmt, ...) 2980ef1c826SPoul-Henning Kamp { 2990ef1c826SPoul-Henning Kamp dev_t dev; 3000ef1c826SPoul-Henning Kamp va_list ap; 3010ef1c826SPoul-Henning Kamp int i; 3020ef1c826SPoul-Henning Kamp 3030ef1c826SPoul-Henning Kamp dev = makedev(devsw->d_maj, minor); 3040ef1c826SPoul-Henning Kamp va_start(ap, fmt); 3050ef1c826SPoul-Henning Kamp i = kvprintf(fmt, NULL, dev->si_name, 32, ap); 3060ef1c826SPoul-Henning Kamp dev->si_name[i] = '\0'; 3070ef1c826SPoul-Henning Kamp va_end(ap); 3080ef1c826SPoul-Henning Kamp dev->si_devsw = devsw; 3090ef1c826SPoul-Henning Kamp return (dev); 3100ef1c826SPoul-Henning Kamp } 3110ef1c826SPoul-Henning Kamp 312b8e49f68SBill Fumerola char * 313b8e49f68SBill Fumerola devtoname(dev_t dev) 314b8e49f68SBill Fumerola { 315b8e49f68SBill Fumerola 316b8e49f68SBill Fumerola return (dev->si_name); 317b8e49f68SBill Fumerola } 318b8e49f68SBill Fumerola 319