kern_conf.c revision 49504
111126Sjulian/*- 211126Sjulian * Parts Copyright (c) 1995 Terrence R. Lambert 311126Sjulian * Copyright (c) 1995 Julian R. Elischer 411126Sjulian * All rights reserved. 511126Sjulian * 611126Sjulian * Redistribution and use in source and binary forms, with or without 711126Sjulian * modification, are permitted provided that the following conditions 811126Sjulian * are met: 911126Sjulian * 1. Redistributions of source code must retain the above copyright 1011126Sjulian * notice, this list of conditions and the following disclaimer. 1111126Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1211126Sjulian * notice, this list of conditions and the following disclaimer in the 1311126Sjulian * documentation and/or other materials provided with the distribution. 1411126Sjulian * 3. All advertising materials mentioning features or use of this software 1511126Sjulian * must display the following acknowledgement: 1611126Sjulian * This product includes software developed by Terrence R. Lambert. 1711126Sjulian * 4. The name Terrence R. Lambert may not be used to endorse or promote 1811126Sjulian * products derived from this software without specific prior written 1911126Sjulian * permission. 2011126Sjulian * 2111126Sjulian * THIS SOFTWARE IS PROVIDED BY Julian R. Elischer ``AS IS'' AND ANY 2211126Sjulian * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2311126Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2411126Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE 2511126Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2611126Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2711126Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2811126Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2911126Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3011126Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3111126Sjulian * SUCH DAMAGE. 3211126Sjulian * 3349504Sgrog * $Id: kern_conf.c,v 1.53 1999/07/20 21:51:12 green Exp $ 3411126Sjulian */ 3511126Sjulian 3611126Sjulian#include <sys/param.h> 3748936Sphk#include <sys/kernel.h> 3811127Sjulian#include <sys/systm.h> 3936735Sdfr#include <sys/module.h> 4048936Sphk#include <sys/malloc.h> 4111126Sjulian#include <sys/conf.h> 4212954Sjulian#include <sys/vnode.h> 4348936Sphk#include <sys/queue.h> 4411126Sjulian 4548936Sphk#include <miscfs/specfs/specdev.h> 4648936Sphk 4747640Sphk#define cdevsw_ALLOCSTART (NUMCDEVSW/2) 4812954Sjulian 4947640Sphkstruct cdevsw *cdevsw[NUMCDEVSW]; 5012954Sjulian 5148936Sphkstatic int bmaj2cmaj[NUMCDEVSW]; 5246635Sphk 5348936SphkMALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage"); 5448936Sphk 5548936Sphk#define DEVT_HASH 83 5648936Sphk#define DEVT_STASH 50 5748936Sphk 5848936Sphkstatic struct specinfo devt_stash[DEVT_STASH]; 5948936Sphk 6048936Sphkstatic SLIST_HEAD(devt_hash_head, specinfo) dev_hash[DEVT_HASH]; 6148936Sphk 6211126Sjulian/* 6312954Sjulian * Routine to convert from character to block device number. 6412954Sjulian * 6512954Sjulian * A minimal stub routine can always return NODEV. 6612954Sjulian */ 6712954Sjuliandev_t 6812954Sjulianchrtoblk(dev_t dev) 6912954Sjulian{ 7012954Sjulian struct cdevsw *cd; 7112954Sjulian 7246676Sphk if((cd = devsw(dev)) != NULL) { 7337389Sjulian if (cd->d_bmaj != -1) 7448864Sphk return(makebdev(cd->d_bmaj,minor(dev))); 7512954Sjulian } 7612954Sjulian return(NODEV); 7712954Sjulian} 7812954Sjulian 7947640Sphkstruct cdevsw * 8047640Sphkdevsw(dev_t dev) 8147640Sphk{ 8247640Sphk return(cdevsw[major(dev)]); 8347640Sphk} 8447640Sphk 8547640Sphkstruct cdevsw * 8647640Sphkbdevsw(dev_t dev) 8747640Sphk{ 8848892Sphk return(cdevsw[major(dev)]); 8947640Sphk} 9047640Sphk 9147640Sphk/* 9247640Sphk * Add a cdevsw entry 9347640Sphk */ 9447640Sphk 9537389Sjulianint 9647640Sphkcdevsw_add(struct cdevsw *newentry) 9717264Sphk{ 9847028Sphk int i; 9947028Sphk static int setup; 10017264Sphk 10147028Sphk if (!setup) { 10247640Sphk for (i = 0; i < NUMCDEVSW; i++) 10347028Sphk if (!bmaj2cmaj[i]) 10448936Sphk bmaj2cmaj[i] = 254; 10547028Sphk setup++; 10647028Sphk } 10747028Sphk 10847640Sphk if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) { 10947640Sphk printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 11047640Sphk newentry->d_name, newentry->d_maj); 11147640Sphk return EINVAL; 11237389Sjulian } 11317264Sphk 11448510Sphk if (cdevsw[newentry->d_maj]) { 11548510Sphk printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n", 11648510Sphk newentry->d_name, cdevsw[newentry->d_maj]->d_name); 11748510Sphk } 11847640Sphk cdevsw[newentry->d_maj] = newentry; 11937389Sjulian 12048510Sphk if (newentry->d_bmaj >= 0 && newentry->d_bmaj < NUMCDEVSW) { 12148936Sphk if (bmaj2cmaj[newentry->d_bmaj] != 254) { 12248510Sphk printf("WARNING: \"%s\" is usurping \"%s\"'s bmaj\n", 12348510Sphk newentry->d_name, 12448510Sphk cdevsw[bmaj2cmaj[newentry->d_bmaj]]->d_name); 12548510Sphk } 12647640Sphk bmaj2cmaj[newentry->d_bmaj] = newentry->d_maj; 12748510Sphk } 12847640Sphk 12937389Sjulian return 0; 13037389Sjulian} 13137389Sjulian 13248211Sgrog/* 13348211Sgrog * Remove a cdevsw entry 13448211Sgrog */ 13548211Sgrog 13636735Sdfrint 13748211Sgrogcdevsw_remove(struct cdevsw *oldentry) 13848211Sgrog{ 13948211Sgrog if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) { 14048211Sgrog printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 14148211Sgrog oldentry->d_name, oldentry->d_maj); 14248211Sgrog return EINVAL; 14348211Sgrog } 14448211Sgrog 14548211Sgrog cdevsw[oldentry->d_maj] = NULL; 14648211Sgrog 14748211Sgrog if (oldentry->d_bmaj >= 0 && oldentry->d_bmaj < NUMCDEVSW) 14849504Sgrog bmaj2cmaj[oldentry->d_bmaj] = 254; 14948211Sgrog 15048211Sgrog return 0; 15148211Sgrog} 15248211Sgrog 15348211Sgrogint 15446635Sphkdevsw_module_handler(module_t mod, int what, void* arg) 15536735Sdfr{ 15646635Sphk struct devsw_module_data* data = (struct devsw_module_data*) arg; 15748240Sdfr int error = 0; 15836735Sdfr 15936735Sdfr switch (what) { 16036735Sdfr case MOD_LOAD: 16147640Sphk error = cdevsw_add(data->cdevsw); 16244975Sdfr if (!error && data->chainevh) 16344975Sdfr error = data->chainevh(mod, what, data->chainarg); 16444975Sdfr return error; 16536735Sdfr 16636735Sdfr case MOD_UNLOAD: 16744975Sdfr if (data->chainevh) { 16844975Sdfr error = data->chainevh(mod, what, data->chainarg); 16944975Sdfr if (error) 17044975Sdfr return error; 17144975Sdfr } 17248240Sdfr cdevsw_remove(data->cdevsw); 17344975Sdfr return error; 17436735Sdfr } 17536735Sdfr 17636735Sdfr if (data->chainevh) 17736735Sdfr return data->chainevh(mod, what, data->chainarg); 17836735Sdfr else 17936735Sdfr return 0; 18036735Sdfr} 18147028Sphk 18247028Sphk/* 18347028Sphk * dev_t and u_dev_t primitives 18447028Sphk */ 18547028Sphk 18647028Sphkint 18747028Sphkmajor(dev_t x) 18847028Sphk{ 18948936Sphk if (x == NODEV) 19048936Sphk return NOUDEV; 19148936Sphk return((x->si_udev >> 8) & 0xff); 19247028Sphk} 19347028Sphk 19447028Sphkint 19547028Sphkminor(dev_t x) 19647028Sphk{ 19748936Sphk if (x == NODEV) 19848936Sphk return NOUDEV; 19948936Sphk return(x->si_udev & 0xffff00ff); 20047028Sphk} 20147028Sphk 20247028Sphkdev_t 20347680Sphkmakebdev(int x, int y) 20447680Sphk{ 20548892Sphk return (makedev(bmaj2cmaj[x], y)); 20647680Sphk} 20747680Sphk 20847680Sphkdev_t 20947028Sphkmakedev(int x, int y) 21047028Sphk{ 21148936Sphk struct specinfo *si; 21248936Sphk udev_t udev; 21348936Sphk int hash; 21448936Sphk static int stashed; 21548936Sphk 21648936Sphk udev = (x << 8) | y; 21748936Sphk hash = udev % DEVT_HASH; 21848936Sphk SLIST_FOREACH(si, &dev_hash[hash], si_hash) { 21948936Sphk if (si->si_udev == udev) 22048936Sphk return (si); 22148936Sphk } 22248936Sphk if (stashed >= DEVT_STASH) { 22348936Sphk MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT, 22448936Sphk M_USE_RESERVE); 22548936Sphk } else { 22648936Sphk si = devt_stash + stashed++; 22748936Sphk } 22848936Sphk bzero(si, sizeof(*si)); 22948936Sphk si->si_udev = udev; 23048936Sphk si->si_bsize_phys = DEV_BSIZE; 23148936Sphk si->si_bsize_best = BLKDEV_IOSIZE; 23248936Sphk si->si_bsize_max = MAXBSIZE; 23348936Sphk SLIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); 23448936Sphk return (si); 23547028Sphk} 23647028Sphk 23747028Sphkudev_t 23847028Sphkdev2udev(dev_t x) 23947028Sphk{ 24048936Sphk if (x == NODEV) 24148936Sphk return NOUDEV; 24248936Sphk return (x->si_udev); 24347028Sphk} 24447028Sphk 24548948Sgreenudev_t 24648948Sgreendev2budev(dev_t x) 24748948Sgreen{ 24848949Sgreen if (x == NODEV) 24948948Sgreen return NOUDEV; 25048948Sgreen else 25148948Sgreen return makeudev(devsw(x)->d_bmaj, minor(x)); 25248948Sgreen} 25348948Sgreen 25447028Sphkdev_t 25547028Sphkudev2dev(udev_t x, int b) 25647028Sphk{ 25748864Sphk switch (b) { 25848864Sphk case 0: 25948864Sphk return makedev(umajor(x), uminor(x)); 26048864Sphk case 1: 26148864Sphk return makebdev(umajor(x), uminor(x)); 26248864Sphk default: 26348864Sphk Debugger("udev2dev(...,X)"); 26448864Sphk return NODEV; 26548864Sphk } 26647028Sphk} 26747028Sphk 26847028Sphkint 26947028Sphkuminor(udev_t dev) 27047028Sphk{ 27147028Sphk return(dev & 0xffff00ff); 27247028Sphk} 27347028Sphk 27447028Sphkint 27547028Sphkumajor(udev_t dev) 27647028Sphk{ 27747028Sphk return((dev & 0xff00) >> 8); 27847028Sphk} 27947028Sphk 28047028Sphkudev_t 28148859Sphkmakeudev(int x, int y) 28247028Sphk{ 28347028Sphk return ((x << 8) | y); 28447028Sphk} 28547028Sphk 286