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 * 330ef1c826SPoul-Henning Kamp * $Id: kern_conf.c,v 1.54 1999/08/08 00:34:00 grog 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 { 812447bec8SPoul-Henning Kamp return(cdevsw[major(dev)]); 822447bec8SPoul-Henning Kamp } 832447bec8SPoul-Henning Kamp 842447bec8SPoul-Henning Kamp struct cdevsw * 852447bec8SPoul-Henning Kamp bdevsw(dev_t dev) 862447bec8SPoul-Henning Kamp { 873de280c4SPoul-Henning Kamp return(cdevsw[major(dev)]); 882447bec8SPoul-Henning Kamp } 892447bec8SPoul-Henning Kamp 902447bec8SPoul-Henning Kamp /* 912447bec8SPoul-Henning Kamp * Add a cdevsw entry 922447bec8SPoul-Henning Kamp */ 932447bec8SPoul-Henning Kamp 94f7ea2f55SJulian Elischer int 952447bec8SPoul-Henning Kamp cdevsw_add(struct cdevsw *newentry) 96f7ea2f55SJulian Elischer { 97f7ea2f55SJulian Elischer int i; 98bfbb9ce6SPoul-Henning Kamp static int setup; 99bfbb9ce6SPoul-Henning Kamp 100bfbb9ce6SPoul-Henning Kamp if (!setup) { 1012447bec8SPoul-Henning Kamp for (i = 0; i < NUMCDEVSW; i++) 102bfbb9ce6SPoul-Henning Kamp if (!bmaj2cmaj[i]) 103698bfad7SPoul-Henning Kamp bmaj2cmaj[i] = 254; 104bfbb9ce6SPoul-Henning Kamp setup++; 105bfbb9ce6SPoul-Henning Kamp } 106f7ea2f55SJulian Elischer 1072447bec8SPoul-Henning Kamp if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) { 1082447bec8SPoul-Henning Kamp printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 1092447bec8SPoul-Henning Kamp newentry->d_name, newentry->d_maj); 110f7ea2f55SJulian Elischer return EINVAL; 111f7ea2f55SJulian Elischer } 112f7ea2f55SJulian Elischer 113c31558b2SPoul-Henning Kamp if (cdevsw[newentry->d_maj]) { 114c31558b2SPoul-Henning Kamp printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n", 115c31558b2SPoul-Henning Kamp newentry->d_name, cdevsw[newentry->d_maj]->d_name); 116c31558b2SPoul-Henning Kamp } 1172447bec8SPoul-Henning Kamp cdevsw[newentry->d_maj] = newentry; 118f7ea2f55SJulian Elischer 119c31558b2SPoul-Henning Kamp if (newentry->d_bmaj >= 0 && newentry->d_bmaj < NUMCDEVSW) { 120698bfad7SPoul-Henning Kamp if (bmaj2cmaj[newentry->d_bmaj] != 254) { 121c31558b2SPoul-Henning Kamp printf("WARNING: \"%s\" is usurping \"%s\"'s bmaj\n", 122c31558b2SPoul-Henning Kamp newentry->d_name, 123c31558b2SPoul-Henning Kamp cdevsw[bmaj2cmaj[newentry->d_bmaj]]->d_name); 124c31558b2SPoul-Henning Kamp } 1252447bec8SPoul-Henning Kamp bmaj2cmaj[newentry->d_bmaj] = newentry->d_maj; 126c31558b2SPoul-Henning Kamp } 1272447bec8SPoul-Henning Kamp 128f7ea2f55SJulian Elischer return 0; 129f7ea2f55SJulian Elischer } 130f7ea2f55SJulian Elischer 1319a9eb2b9SGreg Lehey /* 1329a9eb2b9SGreg Lehey * Remove a cdevsw entry 1339a9eb2b9SGreg Lehey */ 1349a9eb2b9SGreg Lehey 1359a9eb2b9SGreg Lehey int 1369a9eb2b9SGreg Lehey cdevsw_remove(struct cdevsw *oldentry) 1379a9eb2b9SGreg Lehey { 1389a9eb2b9SGreg Lehey if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) { 1399a9eb2b9SGreg Lehey printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 1409a9eb2b9SGreg Lehey oldentry->d_name, oldentry->d_maj); 1419a9eb2b9SGreg Lehey return EINVAL; 1429a9eb2b9SGreg Lehey } 1439a9eb2b9SGreg Lehey 1449a9eb2b9SGreg Lehey cdevsw[oldentry->d_maj] = NULL; 1459a9eb2b9SGreg Lehey 1469a9eb2b9SGreg Lehey if (oldentry->d_bmaj >= 0 && oldentry->d_bmaj < NUMCDEVSW) 14732c0c324SGreg Lehey bmaj2cmaj[oldentry->d_bmaj] = 254; 1489a9eb2b9SGreg Lehey 1499a9eb2b9SGreg Lehey return 0; 1509a9eb2b9SGreg Lehey } 1519a9eb2b9SGreg Lehey 152ecbb00a2SDoug Rabson int 15346eede00SPoul-Henning Kamp devsw_module_handler(module_t mod, int what, void* arg) 154ecbb00a2SDoug Rabson { 15546eede00SPoul-Henning Kamp struct devsw_module_data* data = (struct devsw_module_data*) arg; 1566d4ce7aaSDoug Rabson int error = 0; 157ecbb00a2SDoug Rabson 158ecbb00a2SDoug Rabson switch (what) { 159ecbb00a2SDoug Rabson case MOD_LOAD: 1602447bec8SPoul-Henning Kamp error = cdevsw_add(data->cdevsw); 1616ca34d85SDoug Rabson if (!error && data->chainevh) 1626ca34d85SDoug Rabson error = data->chainevh(mod, what, data->chainarg); 163ecbb00a2SDoug Rabson return error; 164ecbb00a2SDoug Rabson 165ecbb00a2SDoug Rabson case MOD_UNLOAD: 1666ca34d85SDoug Rabson if (data->chainevh) { 1676ca34d85SDoug Rabson error = data->chainevh(mod, what, data->chainarg); 1686ca34d85SDoug Rabson if (error) 169ecbb00a2SDoug Rabson return error; 1706ca34d85SDoug Rabson } 1716d4ce7aaSDoug Rabson cdevsw_remove(data->cdevsw); 172f7ea2f55SJulian Elischer return error; 173ecbb00a2SDoug Rabson } 174ecbb00a2SDoug Rabson 175ecbb00a2SDoug Rabson if (data->chainevh) 176ecbb00a2SDoug Rabson return data->chainevh(mod, what, data->chainarg); 177ecbb00a2SDoug Rabson else 178ecbb00a2SDoug Rabson return 0; 179ecbb00a2SDoug Rabson } 180bfbb9ce6SPoul-Henning Kamp 181bfbb9ce6SPoul-Henning Kamp /* 182bfbb9ce6SPoul-Henning Kamp * dev_t and u_dev_t primitives 183bfbb9ce6SPoul-Henning Kamp */ 184bfbb9ce6SPoul-Henning Kamp 185bfbb9ce6SPoul-Henning Kamp int 186bfbb9ce6SPoul-Henning Kamp major(dev_t x) 187bfbb9ce6SPoul-Henning Kamp { 188698bfad7SPoul-Henning Kamp if (x == NODEV) 189698bfad7SPoul-Henning Kamp return NOUDEV; 190698bfad7SPoul-Henning Kamp return((x->si_udev >> 8) & 0xff); 191bfbb9ce6SPoul-Henning Kamp } 192bfbb9ce6SPoul-Henning Kamp 193bfbb9ce6SPoul-Henning Kamp int 194bfbb9ce6SPoul-Henning Kamp minor(dev_t x) 195bfbb9ce6SPoul-Henning Kamp { 196698bfad7SPoul-Henning Kamp if (x == NODEV) 197698bfad7SPoul-Henning Kamp return NOUDEV; 198698bfad7SPoul-Henning Kamp return(x->si_udev & 0xffff00ff); 199bfbb9ce6SPoul-Henning Kamp } 200bfbb9ce6SPoul-Henning Kamp 201bfbb9ce6SPoul-Henning Kamp dev_t 2026fcd8a7cSPoul-Henning Kamp makebdev(int x, int y) 2036fcd8a7cSPoul-Henning Kamp { 2043de280c4SPoul-Henning Kamp return (makedev(bmaj2cmaj[x], y)); 2056fcd8a7cSPoul-Henning Kamp } 2066fcd8a7cSPoul-Henning Kamp 2076fcd8a7cSPoul-Henning Kamp dev_t 208bfbb9ce6SPoul-Henning Kamp makedev(int x, int y) 209bfbb9ce6SPoul-Henning Kamp { 210698bfad7SPoul-Henning Kamp struct specinfo *si; 211698bfad7SPoul-Henning Kamp udev_t udev; 212698bfad7SPoul-Henning Kamp int hash; 213698bfad7SPoul-Henning Kamp static int stashed; 214698bfad7SPoul-Henning Kamp 215698bfad7SPoul-Henning Kamp udev = (x << 8) | y; 216698bfad7SPoul-Henning Kamp hash = udev % DEVT_HASH; 217698bfad7SPoul-Henning Kamp SLIST_FOREACH(si, &dev_hash[hash], si_hash) { 218698bfad7SPoul-Henning Kamp if (si->si_udev == udev) 219698bfad7SPoul-Henning Kamp return (si); 220698bfad7SPoul-Henning Kamp } 221698bfad7SPoul-Henning Kamp if (stashed >= DEVT_STASH) { 222698bfad7SPoul-Henning Kamp MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT, 223698bfad7SPoul-Henning Kamp M_USE_RESERVE); 224698bfad7SPoul-Henning Kamp } else { 225698bfad7SPoul-Henning Kamp si = devt_stash + stashed++; 226698bfad7SPoul-Henning Kamp } 227698bfad7SPoul-Henning Kamp bzero(si, sizeof(*si)); 228698bfad7SPoul-Henning Kamp si->si_udev = udev; 229698bfad7SPoul-Henning Kamp si->si_bsize_phys = DEV_BSIZE; 230698bfad7SPoul-Henning Kamp si->si_bsize_best = BLKDEV_IOSIZE; 231698bfad7SPoul-Henning Kamp si->si_bsize_max = MAXBSIZE; 2320ef1c826SPoul-Henning Kamp if (y > 256) 2330ef1c826SPoul-Henning Kamp sprintf(si->si_name, "#%d/0x%x", x, y); 2340ef1c826SPoul-Henning Kamp else 2350ef1c826SPoul-Henning Kamp sprintf(si->si_name, "#%d/%d", x, y); 236698bfad7SPoul-Henning Kamp SLIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); 237698bfad7SPoul-Henning Kamp return (si); 238bfbb9ce6SPoul-Henning Kamp } 239bfbb9ce6SPoul-Henning Kamp 240bfbb9ce6SPoul-Henning Kamp udev_t 241bfbb9ce6SPoul-Henning Kamp dev2udev(dev_t x) 242bfbb9ce6SPoul-Henning Kamp { 243698bfad7SPoul-Henning Kamp if (x == NODEV) 244698bfad7SPoul-Henning Kamp return NOUDEV; 245698bfad7SPoul-Henning Kamp return (x->si_udev); 246bfbb9ce6SPoul-Henning Kamp } 247bfbb9ce6SPoul-Henning Kamp 248fb30b5bdSBrian Feldman udev_t 249fb30b5bdSBrian Feldman dev2budev(dev_t x) 250fb30b5bdSBrian Feldman { 25157d86fc6SBrian Feldman if (x == NODEV) 252fb30b5bdSBrian Feldman return NOUDEV; 253fb30b5bdSBrian Feldman else 254fb30b5bdSBrian Feldman return makeudev(devsw(x)->d_bmaj, minor(x)); 255fb30b5bdSBrian Feldman } 256fb30b5bdSBrian Feldman 257bfbb9ce6SPoul-Henning Kamp dev_t 258bfbb9ce6SPoul-Henning Kamp udev2dev(udev_t x, int b) 259bfbb9ce6SPoul-Henning Kamp { 260d21c632cSPoul-Henning Kamp switch (b) { 261d21c632cSPoul-Henning Kamp case 0: 262bfbb9ce6SPoul-Henning Kamp return makedev(umajor(x), uminor(x)); 263d21c632cSPoul-Henning Kamp case 1: 264d21c632cSPoul-Henning Kamp return makebdev(umajor(x), uminor(x)); 265d21c632cSPoul-Henning Kamp default: 266d21c632cSPoul-Henning Kamp Debugger("udev2dev(...,X)"); 267d21c632cSPoul-Henning Kamp return NODEV; 268d21c632cSPoul-Henning Kamp } 269bfbb9ce6SPoul-Henning Kamp } 270bfbb9ce6SPoul-Henning Kamp 271bfbb9ce6SPoul-Henning Kamp int 272bfbb9ce6SPoul-Henning Kamp uminor(udev_t dev) 273bfbb9ce6SPoul-Henning Kamp { 274bfbb9ce6SPoul-Henning Kamp return(dev & 0xffff00ff); 275bfbb9ce6SPoul-Henning Kamp } 276bfbb9ce6SPoul-Henning Kamp 277bfbb9ce6SPoul-Henning Kamp int 278bfbb9ce6SPoul-Henning Kamp umajor(udev_t dev) 279bfbb9ce6SPoul-Henning Kamp { 280bfbb9ce6SPoul-Henning Kamp return((dev & 0xff00) >> 8); 281bfbb9ce6SPoul-Henning Kamp } 282bfbb9ce6SPoul-Henning Kamp 283bfbb9ce6SPoul-Henning Kamp udev_t 284f008cfccSPoul-Henning Kamp makeudev(int x, int y) 285bfbb9ce6SPoul-Henning Kamp { 286bfbb9ce6SPoul-Henning Kamp return ((x << 8) | y); 287bfbb9ce6SPoul-Henning Kamp } 288bfbb9ce6SPoul-Henning Kamp 2890ef1c826SPoul-Henning Kamp dev_t 2900ef1c826SPoul-Henning Kamp make_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, char *fmt, ...) 2910ef1c826SPoul-Henning Kamp { 2920ef1c826SPoul-Henning Kamp dev_t dev; 2930ef1c826SPoul-Henning Kamp va_list ap; 2940ef1c826SPoul-Henning Kamp int i; 2950ef1c826SPoul-Henning Kamp 2960ef1c826SPoul-Henning Kamp dev = makedev(devsw->d_maj, minor); 2970ef1c826SPoul-Henning Kamp va_start(ap, fmt); 2980ef1c826SPoul-Henning Kamp i = kvprintf(fmt, NULL, dev->si_name, 32, ap); 2990ef1c826SPoul-Henning Kamp dev->si_name[i] = '\0'; 3000ef1c826SPoul-Henning Kamp va_end(ap); 3010ef1c826SPoul-Henning Kamp dev->si_devsw = devsw; 3020ef1c826SPoul-Henning Kamp return (dev); 3030ef1c826SPoul-Henning Kamp } 3040ef1c826SPoul-Henning Kamp 305