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 * 33698bfad7SPoul-Henning Kamp * $Id: kern_conf.c,v 1.50 1999/07/19 09:37:59 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> 44698bfad7SPoul-Henning Kamp 45698bfad7SPoul-Henning Kamp #include <miscfs/specfs/specdev.h> 461dfcbb0cSJulian Elischer 472447bec8SPoul-Henning Kamp #define cdevsw_ALLOCSTART (NUMCDEVSW/2) 481dfcbb0cSJulian Elischer 492447bec8SPoul-Henning Kamp struct cdevsw *cdevsw[NUMCDEVSW]; 501dfcbb0cSJulian Elischer 51698bfad7SPoul-Henning Kamp static int bmaj2cmaj[NUMCDEVSW]; 52698bfad7SPoul-Henning Kamp 53698bfad7SPoul-Henning Kamp MALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage"); 54698bfad7SPoul-Henning Kamp 55698bfad7SPoul-Henning Kamp #define DEVT_HASH 83 56698bfad7SPoul-Henning Kamp #define DEVT_STASH 50 57698bfad7SPoul-Henning Kamp 58698bfad7SPoul-Henning Kamp static struct specinfo devt_stash[DEVT_STASH]; 59698bfad7SPoul-Henning Kamp 60698bfad7SPoul-Henning Kamp static SLIST_HEAD(devt_hash_head, specinfo) dev_hash[DEVT_HASH]; 6146eede00SPoul-Henning Kamp 621dfcbb0cSJulian Elischer /* 631dfcbb0cSJulian Elischer * Routine to convert from character to block device number. 641dfcbb0cSJulian Elischer * 651dfcbb0cSJulian Elischer * A minimal stub routine can always return NODEV. 661dfcbb0cSJulian Elischer */ 671dfcbb0cSJulian Elischer dev_t 681dfcbb0cSJulian Elischer chrtoblk(dev_t dev) 691dfcbb0cSJulian Elischer { 701dfcbb0cSJulian Elischer struct cdevsw *cd; 711dfcbb0cSJulian Elischer 724be2eb8cSPoul-Henning Kamp if((cd = devsw(dev)) != NULL) { 73f7ea2f55SJulian Elischer if (cd->d_bmaj != -1) 74d21c632cSPoul-Henning Kamp return(makebdev(cd->d_bmaj,minor(dev))); 751dfcbb0cSJulian Elischer } 761dfcbb0cSJulian Elischer return(NODEV); 771dfcbb0cSJulian Elischer } 7826453f35SJulian Elischer 792447bec8SPoul-Henning Kamp struct cdevsw * 802447bec8SPoul-Henning Kamp devsw(dev_t dev) 812447bec8SPoul-Henning Kamp { 822447bec8SPoul-Henning Kamp return(cdevsw[major(dev)]); 832447bec8SPoul-Henning Kamp } 842447bec8SPoul-Henning Kamp 852447bec8SPoul-Henning Kamp struct cdevsw * 862447bec8SPoul-Henning Kamp bdevsw(dev_t dev) 872447bec8SPoul-Henning Kamp { 883de280c4SPoul-Henning Kamp return(cdevsw[major(dev)]); 892447bec8SPoul-Henning Kamp } 902447bec8SPoul-Henning Kamp 912447bec8SPoul-Henning Kamp /* 922447bec8SPoul-Henning Kamp * Add a cdevsw entry 932447bec8SPoul-Henning Kamp */ 942447bec8SPoul-Henning Kamp 95f7ea2f55SJulian Elischer int 962447bec8SPoul-Henning Kamp cdevsw_add(struct cdevsw *newentry) 97f7ea2f55SJulian Elischer { 98f7ea2f55SJulian Elischer int i; 99bfbb9ce6SPoul-Henning Kamp static int setup; 100bfbb9ce6SPoul-Henning Kamp 101bfbb9ce6SPoul-Henning Kamp if (!setup) { 1022447bec8SPoul-Henning Kamp for (i = 0; i < NUMCDEVSW; i++) 103bfbb9ce6SPoul-Henning Kamp if (!bmaj2cmaj[i]) 104698bfad7SPoul-Henning Kamp bmaj2cmaj[i] = 254; 105bfbb9ce6SPoul-Henning Kamp setup++; 106bfbb9ce6SPoul-Henning Kamp } 107f7ea2f55SJulian Elischer 1082447bec8SPoul-Henning Kamp if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) { 1092447bec8SPoul-Henning Kamp printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 1102447bec8SPoul-Henning Kamp newentry->d_name, newentry->d_maj); 111f7ea2f55SJulian Elischer return EINVAL; 112f7ea2f55SJulian Elischer } 113f7ea2f55SJulian Elischer 114c31558b2SPoul-Henning Kamp if (cdevsw[newentry->d_maj]) { 115c31558b2SPoul-Henning Kamp printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n", 116c31558b2SPoul-Henning Kamp newentry->d_name, cdevsw[newentry->d_maj]->d_name); 117c31558b2SPoul-Henning Kamp } 1182447bec8SPoul-Henning Kamp cdevsw[newentry->d_maj] = newentry; 119f7ea2f55SJulian Elischer 120c31558b2SPoul-Henning Kamp if (newentry->d_bmaj >= 0 && newentry->d_bmaj < NUMCDEVSW) { 121698bfad7SPoul-Henning Kamp if (bmaj2cmaj[newentry->d_bmaj] != 254) { 122c31558b2SPoul-Henning Kamp printf("WARNING: \"%s\" is usurping \"%s\"'s bmaj\n", 123c31558b2SPoul-Henning Kamp newentry->d_name, 124c31558b2SPoul-Henning Kamp cdevsw[bmaj2cmaj[newentry->d_bmaj]]->d_name); 125c31558b2SPoul-Henning Kamp } 1262447bec8SPoul-Henning Kamp bmaj2cmaj[newentry->d_bmaj] = newentry->d_maj; 127c31558b2SPoul-Henning Kamp } 1282447bec8SPoul-Henning Kamp 129f7ea2f55SJulian Elischer return 0; 130f7ea2f55SJulian Elischer } 131f7ea2f55SJulian Elischer 1329a9eb2b9SGreg Lehey /* 1339a9eb2b9SGreg Lehey * Remove a cdevsw entry 1349a9eb2b9SGreg Lehey */ 1359a9eb2b9SGreg Lehey 1369a9eb2b9SGreg Lehey int 1379a9eb2b9SGreg Lehey cdevsw_remove(struct cdevsw *oldentry) 1389a9eb2b9SGreg Lehey { 1399a9eb2b9SGreg Lehey if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) { 1409a9eb2b9SGreg Lehey printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 1419a9eb2b9SGreg Lehey oldentry->d_name, oldentry->d_maj); 1429a9eb2b9SGreg Lehey return EINVAL; 1439a9eb2b9SGreg Lehey } 1449a9eb2b9SGreg Lehey 1459a9eb2b9SGreg Lehey cdevsw[oldentry->d_maj] = NULL; 1469a9eb2b9SGreg Lehey 1479a9eb2b9SGreg Lehey if (oldentry->d_bmaj >= 0 && oldentry->d_bmaj < NUMCDEVSW) 1489a9eb2b9SGreg Lehey bmaj2cmaj[oldentry->d_bmaj] = NULL; 1499a9eb2b9SGreg Lehey 1509a9eb2b9SGreg Lehey return 0; 1519a9eb2b9SGreg Lehey } 1529a9eb2b9SGreg Lehey 153ecbb00a2SDoug Rabson int 15446eede00SPoul-Henning Kamp devsw_module_handler(module_t mod, int what, void* arg) 155ecbb00a2SDoug Rabson { 15646eede00SPoul-Henning Kamp struct devsw_module_data* data = (struct devsw_module_data*) arg; 1576d4ce7aaSDoug Rabson int error = 0; 158ecbb00a2SDoug Rabson 159ecbb00a2SDoug Rabson switch (what) { 160ecbb00a2SDoug Rabson case MOD_LOAD: 1612447bec8SPoul-Henning Kamp error = cdevsw_add(data->cdevsw); 1626ca34d85SDoug Rabson if (!error && data->chainevh) 1636ca34d85SDoug Rabson error = data->chainevh(mod, what, data->chainarg); 164ecbb00a2SDoug Rabson return error; 165ecbb00a2SDoug Rabson 166ecbb00a2SDoug Rabson case MOD_UNLOAD: 1676ca34d85SDoug Rabson if (data->chainevh) { 1686ca34d85SDoug Rabson error = data->chainevh(mod, what, data->chainarg); 1696ca34d85SDoug Rabson if (error) 170ecbb00a2SDoug Rabson return error; 1716ca34d85SDoug Rabson } 1726d4ce7aaSDoug Rabson cdevsw_remove(data->cdevsw); 173f7ea2f55SJulian Elischer return error; 174ecbb00a2SDoug Rabson } 175ecbb00a2SDoug Rabson 176ecbb00a2SDoug Rabson if (data->chainevh) 177ecbb00a2SDoug Rabson return data->chainevh(mod, what, data->chainarg); 178ecbb00a2SDoug Rabson else 179ecbb00a2SDoug Rabson return 0; 180ecbb00a2SDoug Rabson } 181bfbb9ce6SPoul-Henning Kamp 182bfbb9ce6SPoul-Henning Kamp /* 183bfbb9ce6SPoul-Henning Kamp * dev_t and u_dev_t primitives 184bfbb9ce6SPoul-Henning Kamp */ 185bfbb9ce6SPoul-Henning Kamp 186bfbb9ce6SPoul-Henning Kamp int 187bfbb9ce6SPoul-Henning Kamp major(dev_t x) 188bfbb9ce6SPoul-Henning Kamp { 189698bfad7SPoul-Henning Kamp if (x == NODEV) 190698bfad7SPoul-Henning Kamp return NOUDEV; 191698bfad7SPoul-Henning Kamp return((x->si_udev >> 8) & 0xff); 192bfbb9ce6SPoul-Henning Kamp } 193bfbb9ce6SPoul-Henning Kamp 194bfbb9ce6SPoul-Henning Kamp int 195bfbb9ce6SPoul-Henning Kamp minor(dev_t x) 196bfbb9ce6SPoul-Henning Kamp { 197698bfad7SPoul-Henning Kamp if (x == NODEV) 198698bfad7SPoul-Henning Kamp return NOUDEV; 199698bfad7SPoul-Henning Kamp return(x->si_udev & 0xffff00ff); 200bfbb9ce6SPoul-Henning Kamp } 201bfbb9ce6SPoul-Henning Kamp 202bfbb9ce6SPoul-Henning Kamp dev_t 2036fcd8a7cSPoul-Henning Kamp makebdev(int x, int y) 2046fcd8a7cSPoul-Henning Kamp { 2053de280c4SPoul-Henning Kamp return (makedev(bmaj2cmaj[x], y)); 2066fcd8a7cSPoul-Henning Kamp } 2076fcd8a7cSPoul-Henning Kamp 2086fcd8a7cSPoul-Henning Kamp dev_t 209bfbb9ce6SPoul-Henning Kamp makedev(int x, int y) 210bfbb9ce6SPoul-Henning Kamp { 211698bfad7SPoul-Henning Kamp struct specinfo *si; 212698bfad7SPoul-Henning Kamp udev_t udev; 213698bfad7SPoul-Henning Kamp int hash; 214698bfad7SPoul-Henning Kamp static int stashed; 215698bfad7SPoul-Henning Kamp 216698bfad7SPoul-Henning Kamp udev = (x << 8) | y; 217698bfad7SPoul-Henning Kamp hash = udev % DEVT_HASH; 218698bfad7SPoul-Henning Kamp SLIST_FOREACH(si, &dev_hash[hash], si_hash) { 219698bfad7SPoul-Henning Kamp if (si->si_udev == udev) 220698bfad7SPoul-Henning Kamp return (si); 221698bfad7SPoul-Henning Kamp } 222698bfad7SPoul-Henning Kamp if (stashed >= DEVT_STASH) { 223698bfad7SPoul-Henning Kamp MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT, 224698bfad7SPoul-Henning Kamp M_USE_RESERVE); 225698bfad7SPoul-Henning Kamp } else { 226698bfad7SPoul-Henning Kamp si = devt_stash + stashed++; 227698bfad7SPoul-Henning Kamp } 228698bfad7SPoul-Henning Kamp bzero(si, sizeof(*si)); 229698bfad7SPoul-Henning Kamp si->si_udev = udev; 230698bfad7SPoul-Henning Kamp si->si_bsize_phys = DEV_BSIZE; 231698bfad7SPoul-Henning Kamp si->si_bsize_best = BLKDEV_IOSIZE; 232698bfad7SPoul-Henning Kamp si->si_bsize_max = MAXBSIZE; 233698bfad7SPoul-Henning Kamp SLIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); 234698bfad7SPoul-Henning Kamp return (si); 235bfbb9ce6SPoul-Henning Kamp } 236bfbb9ce6SPoul-Henning Kamp 237bfbb9ce6SPoul-Henning Kamp udev_t 238bfbb9ce6SPoul-Henning Kamp dev2udev(dev_t x) 239bfbb9ce6SPoul-Henning Kamp { 240698bfad7SPoul-Henning Kamp if (x == NODEV) 241698bfad7SPoul-Henning Kamp return NOUDEV; 242698bfad7SPoul-Henning Kamp return (x->si_udev); 243bfbb9ce6SPoul-Henning Kamp } 244bfbb9ce6SPoul-Henning Kamp 245bfbb9ce6SPoul-Henning Kamp dev_t 246bfbb9ce6SPoul-Henning Kamp udev2dev(udev_t x, int b) 247bfbb9ce6SPoul-Henning Kamp { 248d21c632cSPoul-Henning Kamp switch (b) { 249d21c632cSPoul-Henning Kamp case 0: 250bfbb9ce6SPoul-Henning Kamp return makedev(umajor(x), uminor(x)); 251d21c632cSPoul-Henning Kamp case 1: 252d21c632cSPoul-Henning Kamp return makebdev(umajor(x), uminor(x)); 253d21c632cSPoul-Henning Kamp default: 254d21c632cSPoul-Henning Kamp Debugger("udev2dev(...,X)"); 255d21c632cSPoul-Henning Kamp return NODEV; 256d21c632cSPoul-Henning Kamp } 257bfbb9ce6SPoul-Henning Kamp } 258bfbb9ce6SPoul-Henning Kamp 259bfbb9ce6SPoul-Henning Kamp int 260bfbb9ce6SPoul-Henning Kamp uminor(udev_t dev) 261bfbb9ce6SPoul-Henning Kamp { 262bfbb9ce6SPoul-Henning Kamp return(dev & 0xffff00ff); 263bfbb9ce6SPoul-Henning Kamp } 264bfbb9ce6SPoul-Henning Kamp 265bfbb9ce6SPoul-Henning Kamp int 266bfbb9ce6SPoul-Henning Kamp umajor(udev_t dev) 267bfbb9ce6SPoul-Henning Kamp { 268bfbb9ce6SPoul-Henning Kamp return((dev & 0xff00) >> 8); 269bfbb9ce6SPoul-Henning Kamp } 270bfbb9ce6SPoul-Henning Kamp 271bfbb9ce6SPoul-Henning Kamp udev_t 272f008cfccSPoul-Henning Kamp makeudev(int x, int y) 273bfbb9ce6SPoul-Henning Kamp { 274bfbb9ce6SPoul-Henning Kamp return ((x << 8) | y); 275bfbb9ce6SPoul-Henning Kamp } 276bfbb9ce6SPoul-Henning Kamp 277