kern_conf.c revision 50092
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 * 3350092Sjulian * $Id: kern_conf.c,v 1.58 1999/08/17 20:25:50 billf Exp $ 3411126Sjulian */ 3511126Sjulian 3650092Sjulian#include "opt_devfs.h" 3750092Sjulian 3811126Sjulian#include <sys/param.h> 3948936Sphk#include <sys/kernel.h> 4011127Sjulian#include <sys/systm.h> 4136735Sdfr#include <sys/module.h> 4248936Sphk#include <sys/malloc.h> 4311126Sjulian#include <sys/conf.h> 4412954Sjulian#include <sys/vnode.h> 4548936Sphk#include <sys/queue.h> 4649535Sphk#include <machine/stdarg.h> 4750092Sjulian#ifdef DEVFS 4850092Sjulian#include <sys/devfsext.h> 4950092Sjulian#endif /* DEVFS */ 5011126Sjulian 5150092Sjulian 5247640Sphk#define cdevsw_ALLOCSTART (NUMCDEVSW/2) 5312954Sjulian 5447640Sphkstruct cdevsw *cdevsw[NUMCDEVSW]; 5512954Sjulian 5648936Sphkstatic int bmaj2cmaj[NUMCDEVSW]; 5746635Sphk 5848936SphkMALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage"); 5948936Sphk 6048936Sphk#define DEVT_HASH 83 6148936Sphk#define DEVT_STASH 50 6248936Sphk 6348936Sphkstatic struct specinfo devt_stash[DEVT_STASH]; 6448936Sphk 6548936Sphkstatic SLIST_HEAD(devt_hash_head, specinfo) dev_hash[DEVT_HASH]; 6648936Sphk 6711126Sjulian/* 6812954Sjulian * Routine to convert from character to block device number. 6912954Sjulian * 7012954Sjulian * A minimal stub routine can always return NODEV. 7112954Sjulian */ 7212954Sjuliandev_t 7312954Sjulianchrtoblk(dev_t dev) 7412954Sjulian{ 7512954Sjulian struct cdevsw *cd; 7612954Sjulian 7746676Sphk if((cd = devsw(dev)) != NULL) { 7837389Sjulian if (cd->d_bmaj != -1) 7948864Sphk return(makebdev(cd->d_bmaj,minor(dev))); 8012954Sjulian } 8112954Sjulian return(NODEV); 8212954Sjulian} 8312954Sjulian 8447640Sphkstruct cdevsw * 8547640Sphkdevsw(dev_t dev) 8647640Sphk{ 8749679Sphk if (dev->si_devsw) 8849679Sphk return (dev->si_devsw); 8947640Sphk return(cdevsw[major(dev)]); 9047640Sphk} 9147640Sphk 9247640Sphk/* 9347640Sphk * Add a cdevsw entry 9447640Sphk */ 9547640Sphk 9637389Sjulianint 9747640Sphkcdevsw_add(struct cdevsw *newentry) 9817264Sphk{ 9947028Sphk int i; 10047028Sphk static int setup; 10117264Sphk 10247028Sphk if (!setup) { 10347640Sphk for (i = 0; i < NUMCDEVSW; i++) 10447028Sphk if (!bmaj2cmaj[i]) 10548936Sphk bmaj2cmaj[i] = 254; 10647028Sphk setup++; 10747028Sphk } 10847028Sphk 10947640Sphk if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) { 11047640Sphk printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 11147640Sphk newentry->d_name, newentry->d_maj); 11247640Sphk return EINVAL; 11337389Sjulian } 11417264Sphk 11548510Sphk if (cdevsw[newentry->d_maj]) { 11648510Sphk printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n", 11748510Sphk newentry->d_name, cdevsw[newentry->d_maj]->d_name); 11848510Sphk } 11947640Sphk cdevsw[newentry->d_maj] = newentry; 12037389Sjulian 12148510Sphk if (newentry->d_bmaj >= 0 && newentry->d_bmaj < NUMCDEVSW) { 12248936Sphk if (bmaj2cmaj[newentry->d_bmaj] != 254) { 12348510Sphk printf("WARNING: \"%s\" is usurping \"%s\"'s bmaj\n", 12448510Sphk newentry->d_name, 12548510Sphk cdevsw[bmaj2cmaj[newentry->d_bmaj]]->d_name); 12648510Sphk } 12747640Sphk bmaj2cmaj[newentry->d_bmaj] = newentry->d_maj; 12848510Sphk } 12947640Sphk 13037389Sjulian return 0; 13137389Sjulian} 13237389Sjulian 13348211Sgrog/* 13448211Sgrog * Remove a cdevsw entry 13548211Sgrog */ 13648211Sgrog 13736735Sdfrint 13848211Sgrogcdevsw_remove(struct cdevsw *oldentry) 13948211Sgrog{ 14048211Sgrog if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) { 14148211Sgrog printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 14248211Sgrog oldentry->d_name, oldentry->d_maj); 14348211Sgrog return EINVAL; 14448211Sgrog } 14548211Sgrog 14648211Sgrog cdevsw[oldentry->d_maj] = NULL; 14748211Sgrog 14848211Sgrog if (oldentry->d_bmaj >= 0 && oldentry->d_bmaj < NUMCDEVSW) 14949504Sgrog bmaj2cmaj[oldentry->d_bmaj] = 254; 15048211Sgrog 15148211Sgrog return 0; 15248211Sgrog} 15348211Sgrog 15448211Sgrogint 15546635Sphkdevsw_module_handler(module_t mod, int what, void* arg) 15636735Sdfr{ 15746635Sphk struct devsw_module_data* data = (struct devsw_module_data*) arg; 15848240Sdfr int error = 0; 15936735Sdfr 16036735Sdfr switch (what) { 16136735Sdfr case MOD_LOAD: 16247640Sphk error = cdevsw_add(data->cdevsw); 16344975Sdfr if (!error && data->chainevh) 16444975Sdfr error = data->chainevh(mod, what, data->chainarg); 16544975Sdfr return error; 16636735Sdfr 16736735Sdfr case MOD_UNLOAD: 16844975Sdfr if (data->chainevh) { 16944975Sdfr error = data->chainevh(mod, what, data->chainarg); 17044975Sdfr if (error) 17144975Sdfr return error; 17244975Sdfr } 17348240Sdfr cdevsw_remove(data->cdevsw); 17444975Sdfr return error; 17536735Sdfr } 17636735Sdfr 17736735Sdfr if (data->chainevh) 17836735Sdfr return data->chainevh(mod, what, data->chainarg); 17936735Sdfr else 18036735Sdfr return 0; 18136735Sdfr} 18247028Sphk 18347028Sphk/* 18447028Sphk * dev_t and u_dev_t primitives 18547028Sphk */ 18647028Sphk 18747028Sphkint 18847028Sphkmajor(dev_t x) 18947028Sphk{ 19048936Sphk if (x == NODEV) 19148936Sphk return NOUDEV; 19248936Sphk return((x->si_udev >> 8) & 0xff); 19347028Sphk} 19447028Sphk 19547028Sphkint 19647028Sphkminor(dev_t x) 19747028Sphk{ 19848936Sphk if (x == NODEV) 19948936Sphk return NOUDEV; 20048936Sphk return(x->si_udev & 0xffff00ff); 20147028Sphk} 20247028Sphk 20349826Sphkint 20449826Sphklminor(dev_t x) 20549826Sphk{ 20649826Sphk int i; 20749826Sphk 20849826Sphk if (x == NODEV) 20949826Sphk return NOUDEV; 21049826Sphk i = minor(x); 21149826Sphk return ((i & 0xff) | (i >> 8)); 21249826Sphk} 21349826Sphk 21447028Sphkdev_t 21547680Sphkmakebdev(int x, int y) 21647680Sphk{ 21748892Sphk return (makedev(bmaj2cmaj[x], y)); 21847680Sphk} 21947680Sphk 22047680Sphkdev_t 22147028Sphkmakedev(int x, int y) 22247028Sphk{ 22348936Sphk struct specinfo *si; 22448936Sphk udev_t udev; 22548936Sphk int hash; 22648936Sphk static int stashed; 22748936Sphk 22848936Sphk udev = (x << 8) | y; 22948936Sphk hash = udev % DEVT_HASH; 23048936Sphk SLIST_FOREACH(si, &dev_hash[hash], si_hash) { 23148936Sphk if (si->si_udev == udev) 23248936Sphk return (si); 23348936Sphk } 23448936Sphk if (stashed >= DEVT_STASH) { 23548936Sphk MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT, 23648936Sphk M_USE_RESERVE); 23748936Sphk } else { 23848936Sphk si = devt_stash + stashed++; 23948936Sphk } 24048936Sphk bzero(si, sizeof(*si)); 24148936Sphk si->si_udev = udev; 24248936Sphk si->si_bsize_phys = DEV_BSIZE; 24348936Sphk si->si_bsize_best = BLKDEV_IOSIZE; 24448936Sphk si->si_bsize_max = MAXBSIZE; 24549535Sphk if (y > 256) 24649535Sphk sprintf(si->si_name, "#%d/0x%x", x, y); 24749535Sphk else 24849535Sphk sprintf(si->si_name, "#%d/%d", x, y); 24948936Sphk SLIST_INSERT_HEAD(&dev_hash[hash], si, si_hash); 25048936Sphk return (si); 25147028Sphk} 25247028Sphk 25347028Sphkudev_t 25447028Sphkdev2udev(dev_t x) 25547028Sphk{ 25648936Sphk if (x == NODEV) 25748936Sphk return NOUDEV; 25848936Sphk return (x->si_udev); 25947028Sphk} 26047028Sphk 26148948Sgreenudev_t 26248948Sgreendev2budev(dev_t x) 26348948Sgreen{ 26448949Sgreen if (x == NODEV) 26548948Sgreen return NOUDEV; 26648948Sgreen else 26748948Sgreen return makeudev(devsw(x)->d_bmaj, minor(x)); 26848948Sgreen} 26948948Sgreen 27047028Sphkdev_t 27147028Sphkudev2dev(udev_t x, int b) 27247028Sphk{ 27348864Sphk switch (b) { 27448864Sphk case 0: 27548864Sphk return makedev(umajor(x), uminor(x)); 27648864Sphk case 1: 27748864Sphk return makebdev(umajor(x), uminor(x)); 27848864Sphk default: 27948864Sphk Debugger("udev2dev(...,X)"); 28048864Sphk return NODEV; 28148864Sphk } 28247028Sphk} 28347028Sphk 28447028Sphkint 28547028Sphkuminor(udev_t dev) 28647028Sphk{ 28747028Sphk return(dev & 0xffff00ff); 28847028Sphk} 28947028Sphk 29047028Sphkint 29147028Sphkumajor(udev_t dev) 29247028Sphk{ 29347028Sphk return((dev & 0xff00) >> 8); 29447028Sphk} 29547028Sphk 29647028Sphkudev_t 29748859Sphkmakeudev(int x, int y) 29847028Sphk{ 29947028Sphk return ((x << 8) | y); 30047028Sphk} 30147028Sphk 30249535Sphkdev_t 30349535Sphkmake_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, char *fmt, ...) 30449535Sphk{ 30549535Sphk dev_t dev; 30649535Sphk va_list ap; 30749535Sphk int i; 30849535Sphk 30949535Sphk dev = makedev(devsw->d_maj, minor); 31049535Sphk va_start(ap, fmt); 31149535Sphk i = kvprintf(fmt, NULL, dev->si_name, 32, ap); 31249535Sphk dev->si_name[i] = '\0'; 31349535Sphk va_end(ap); 31449535Sphk dev->si_devsw = devsw; 31550092Sjulian 31650092Sjulian#ifdef DEVFS 31750092Sjulian dev->si_devfs = devfs_add_devswf(devsw, minor, DV_CHR, 31850092Sjulian uid, gid, perms, dev->si_name); 31950092Sjulian /* XXX HACK .. name may not start in 'r' */ 32050092Sjulian if ((devsw->d_bmaj != -1) 32150092Sjulian && (*dev->si_name == 'r') 32250092Sjulian && ((devsw->d_flags & D_TYPEMASK) == D_DISK)) { 32350092Sjulian dev->si_devfs = devfs_add_devswf(devsw, minor, DV_BLK, 32450092Sjulian uid, gid, perms, dev->si_name + 1); 32550092Sjulian } 32650092Sjulian#endif /* DEVFS */ 32749535Sphk return (dev); 32849535Sphk} 32949535Sphk 33049982Sbillfchar * 33149982Sbillfdevtoname(dev_t dev) 33249982Sbillf{ 33349982Sbillf 33449982Sbillf return (dev->si_name); 33549982Sbillf} 33649982Sbillf 337