kern_conf.c revision 49982
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 * 3349982Sbillf * $Id: kern_conf.c,v 1.57 1999/08/15 09:32:47 phk 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> 4449535Sphk#include <machine/stdarg.h> 4511126Sjulian 4647640Sphk#define cdevsw_ALLOCSTART (NUMCDEVSW/2) 4712954Sjulian 4847640Sphkstruct cdevsw *cdevsw[NUMCDEVSW]; 4912954Sjulian 5048936Sphkstatic int bmaj2cmaj[NUMCDEVSW]; 5146635Sphk 5248936SphkMALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage"); 5348936Sphk 5448936Sphk#define DEVT_HASH 83 5548936Sphk#define DEVT_STASH 50 5648936Sphk 5748936Sphkstatic struct specinfo devt_stash[DEVT_STASH]; 5848936Sphk 5948936Sphkstatic SLIST_HEAD(devt_hash_head, specinfo) dev_hash[DEVT_HASH]; 6048936Sphk 6111126Sjulian/* 6212954Sjulian * Routine to convert from character to block device number. 6312954Sjulian * 6412954Sjulian * A minimal stub routine can always return NODEV. 6512954Sjulian */ 6612954Sjuliandev_t 6712954Sjulianchrtoblk(dev_t dev) 6812954Sjulian{ 6912954Sjulian struct cdevsw *cd; 7012954Sjulian 7146676Sphk if((cd = devsw(dev)) != NULL) { 7237389Sjulian if (cd->d_bmaj != -1) 7348864Sphk return(makebdev(cd->d_bmaj,minor(dev))); 7412954Sjulian } 7512954Sjulian return(NODEV); 7612954Sjulian} 7712954Sjulian 7847640Sphkstruct cdevsw * 7947640Sphkdevsw(dev_t dev) 8047640Sphk{ 8149679Sphk if (dev->si_devsw) 8249679Sphk return (dev->si_devsw); 8347640Sphk return(cdevsw[major(dev)]); 8447640Sphk} 8547640Sphk 8647640Sphk/* 8747640Sphk * Add a cdevsw entry 8847640Sphk */ 8947640Sphk 9037389Sjulianint 9147640Sphkcdevsw_add(struct cdevsw *newentry) 9217264Sphk{ 9347028Sphk int i; 9447028Sphk static int setup; 9517264Sphk 9647028Sphk if (!setup) { 9747640Sphk for (i = 0; i < NUMCDEVSW; i++) 9847028Sphk if (!bmaj2cmaj[i]) 9948936Sphk bmaj2cmaj[i] = 254; 10047028Sphk setup++; 10147028Sphk } 10247028Sphk 10347640Sphk if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) { 10447640Sphk printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 10547640Sphk newentry->d_name, newentry->d_maj); 10647640Sphk return EINVAL; 10737389Sjulian } 10817264Sphk 10948510Sphk if (cdevsw[newentry->d_maj]) { 11048510Sphk printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n", 11148510Sphk newentry->d_name, cdevsw[newentry->d_maj]->d_name); 11248510Sphk } 11347640Sphk cdevsw[newentry->d_maj] = newentry; 11437389Sjulian 11548510Sphk if (newentry->d_bmaj >= 0 && newentry->d_bmaj < NUMCDEVSW) { 11648936Sphk if (bmaj2cmaj[newentry->d_bmaj] != 254) { 11748510Sphk printf("WARNING: \"%s\" is usurping \"%s\"'s bmaj\n", 11848510Sphk newentry->d_name, 11948510Sphk cdevsw[bmaj2cmaj[newentry->d_bmaj]]->d_name); 12048510Sphk } 12147640Sphk bmaj2cmaj[newentry->d_bmaj] = newentry->d_maj; 12248510Sphk } 12347640Sphk 12437389Sjulian return 0; 12537389Sjulian} 12637389Sjulian 12748211Sgrog/* 12848211Sgrog * Remove a cdevsw entry 12948211Sgrog */ 13048211Sgrog 13136735Sdfrint 13248211Sgrogcdevsw_remove(struct cdevsw *oldentry) 13348211Sgrog{ 13448211Sgrog if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) { 13548211Sgrog printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 13648211Sgrog oldentry->d_name, oldentry->d_maj); 13748211Sgrog return EINVAL; 13848211Sgrog } 13948211Sgrog 14048211Sgrog cdevsw[oldentry->d_maj] = NULL; 14148211Sgrog 14248211Sgrog if (oldentry->d_bmaj >= 0 && oldentry->d_bmaj < NUMCDEVSW) 14349504Sgrog bmaj2cmaj[oldentry->d_bmaj] = 254; 14448211Sgrog 14548211Sgrog return 0; 14648211Sgrog} 14748211Sgrog 14848211Sgrogint 14946635Sphkdevsw_module_handler(module_t mod, int what, void* arg) 15036735Sdfr{ 15146635Sphk struct devsw_module_data* data = (struct devsw_module_data*) arg; 15248240Sdfr int error = 0; 15336735Sdfr 15436735Sdfr switch (what) { 15536735Sdfr case MOD_LOAD: 15647640Sphk error = cdevsw_add(data->cdevsw); 15744975Sdfr if (!error && data->chainevh) 15844975Sdfr error = data->chainevh(mod, what, data->chainarg); 15944975Sdfr return error; 16036735Sdfr 16136735Sdfr case MOD_UNLOAD: 16244975Sdfr if (data->chainevh) { 16344975Sdfr error = data->chainevh(mod, what, data->chainarg); 16444975Sdfr if (error) 16544975Sdfr return error; 16644975Sdfr } 16748240Sdfr cdevsw_remove(data->cdevsw); 16844975Sdfr return error; 16936735Sdfr } 17036735Sdfr 17136735Sdfr if (data->chainevh) 17236735Sdfr return data->chainevh(mod, what, data->chainarg); 17336735Sdfr else 17436735Sdfr return 0; 17536735Sdfr} 17647028Sphk 17747028Sphk/* 17847028Sphk * dev_t and u_dev_t primitives 17947028Sphk */ 18047028Sphk 18147028Sphkint 18247028Sphkmajor(dev_t x) 18347028Sphk{ 18448936Sphk if (x == NODEV) 18548936Sphk return NOUDEV; 18648936Sphk return((x->si_udev >> 8) & 0xff); 18747028Sphk} 18847028Sphk 18947028Sphkint 19047028Sphkminor(dev_t x) 19147028Sphk{ 19248936Sphk if (x == NODEV) 19348936Sphk return NOUDEV; 19448936Sphk return(x->si_udev & 0xffff00ff); 19547028Sphk} 19647028Sphk 19749826Sphkint 19849826Sphklminor(dev_t x) 19949826Sphk{ 20049826Sphk int i; 20149826Sphk 20249826Sphk if (x == NODEV) 20349826Sphk return NOUDEV; 20449826Sphk i = minor(x); 20549826Sphk return ((i & 0xff) | (i >> 8)); 20649826Sphk} 20749826Sphk 20847028Sphkdev_t 20947680Sphkmakebdev(int x, int y) 21047680Sphk{ 21148892Sphk return (makedev(bmaj2cmaj[x], y)); 21247680Sphk} 21347680Sphk 21447680Sphkdev_t 21547028Sphkmakedev(int x, int y) 21647028Sphk{ 21748936Sphk struct specinfo *si; 21848936Sphk udev_t udev; 21948936Sphk int hash; 22048936Sphk static int stashed; 22148936Sphk 22248936Sphk udev = (x << 8) | y; 22348936Sphk hash = udev % DEVT_HASH; 22448936Sphk SLIST_FOREACH(si, &dev_hash[hash], si_hash) { 22548936Sphk if (si->si_udev == udev) 22648936Sphk return (si); 22748936Sphk } 22848936Sphk if (stashed >= DEVT_STASH) { 22948936Sphk MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT, 23048936Sphk M_USE_RESERVE); 23148936Sphk } else { 23248936Sphk si = devt_stash + stashed++; 23348936Sphk } 23448936Sphk bzero(si, sizeof(*si)); 23548936Sphk si->si_udev = udev; 23648936Sphk si->si_bsize_phys = DEV_BSIZE; 23748936Sphk si->si_bsize_best = BLKDEV_IOSIZE; 23848936Sphk si->si_bsize_max = MAXBSIZE; 23949535Sphk if (y > 256) 24049535Sphk sprintf(si->si_name, "#%d/0x%x", x, y); 24149535Sphk else 24249535Sphk sprintf(si->si_name, "#%d/%d", x, y); 24348936Sphk SLIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); 24448936Sphk return (si); 24547028Sphk} 24647028Sphk 24747028Sphkudev_t 24847028Sphkdev2udev(dev_t x) 24947028Sphk{ 25048936Sphk if (x == NODEV) 25148936Sphk return NOUDEV; 25248936Sphk return (x->si_udev); 25347028Sphk} 25447028Sphk 25548948Sgreenudev_t 25648948Sgreendev2budev(dev_t x) 25748948Sgreen{ 25848949Sgreen if (x == NODEV) 25948948Sgreen return NOUDEV; 26048948Sgreen else 26148948Sgreen return makeudev(devsw(x)->d_bmaj, minor(x)); 26248948Sgreen} 26348948Sgreen 26447028Sphkdev_t 26547028Sphkudev2dev(udev_t x, int b) 26647028Sphk{ 26748864Sphk switch (b) { 26848864Sphk case 0: 26948864Sphk return makedev(umajor(x), uminor(x)); 27048864Sphk case 1: 27148864Sphk return makebdev(umajor(x), uminor(x)); 27248864Sphk default: 27348864Sphk Debugger("udev2dev(...,X)"); 27448864Sphk return NODEV; 27548864Sphk } 27647028Sphk} 27747028Sphk 27847028Sphkint 27947028Sphkuminor(udev_t dev) 28047028Sphk{ 28147028Sphk return(dev & 0xffff00ff); 28247028Sphk} 28347028Sphk 28447028Sphkint 28547028Sphkumajor(udev_t dev) 28647028Sphk{ 28747028Sphk return((dev & 0xff00) >> 8); 28847028Sphk} 28947028Sphk 29047028Sphkudev_t 29148859Sphkmakeudev(int x, int y) 29247028Sphk{ 29347028Sphk return ((x << 8) | y); 29447028Sphk} 29547028Sphk 29649535Sphkdev_t 29749535Sphkmake_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, char *fmt, ...) 29849535Sphk{ 29949535Sphk dev_t dev; 30049535Sphk va_list ap; 30149535Sphk int i; 30249535Sphk 30349535Sphk dev = makedev(devsw->d_maj, minor); 30449535Sphk va_start(ap, fmt); 30549535Sphk i = kvprintf(fmt, NULL, dev->si_name, 32, ap); 30649535Sphk dev->si_name[i] = '\0'; 30749535Sphk va_end(ap); 30849535Sphk dev->si_devsw = devsw; 30949535Sphk return (dev); 31049535Sphk} 31149535Sphk 31249982Sbillfchar * 31349982Sbillfdevtoname(dev_t dev) 31449982Sbillf{ 31549982Sbillf 31649982Sbillf return (dev->si_name); 31749982Sbillf} 31849982Sbillf 319