kern_conf.c revision 47069
1/*- 2 * Parts Copyright (c) 1995 Terrence R. Lambert 3 * Copyright (c) 1995 Julian R. Elischer 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Terrence R. Lambert. 17 * 4. The name Terrence R. Lambert may not be used to endorse or promote 18 * products derived from this software without specific prior written 19 * permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY Julian R. Elischer ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * $Id: kern_conf.c,v 1.38 1999/05/12 11:06:45 phk Exp $ 34 */ 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/module.h> 39#include <sys/conf.h> 40#include <sys/vnode.h> 41 42#define NUMCDEV 256 43#define cdevsw_ALLOCSTART (NUMCDEV/2) 44 45struct cdevsw *cdevsw[NUMCDEV]; 46int nchrdev = NUMCDEV; 47 48int bmaj2cmaj[NUMCDEV]; 49int nblkdev = NUMCDEV; 50 51/* 52 * Routine to convert from character to block device number. 53 * 54 * A minimal stub routine can always return NODEV. 55 */ 56dev_t 57chrtoblk(dev_t dev) 58{ 59 struct cdevsw *cd; 60 61 if((cd = devsw(dev)) != NULL) { 62 if (cd->d_bmaj != -1) 63 return(makedev(cd->d_bmaj,minor(dev))); 64 } 65 return(NODEV); 66} 67 68int 69cdevsw_add(dev_t *descrip, 70 struct cdevsw *newentry, 71 struct cdevsw **oldentry) 72{ 73 int i; 74 static int setup; 75 76 if (!setup) { 77 for (i = 0; i < NUMCDEV; i++) 78 if (!bmaj2cmaj[i]) 79 bmaj2cmaj[i] = 254; 80 setup++; 81 } 82 83 if ( *descrip == NODEV) { /* auto (0 is valid) */ 84 /* 85 * Search the table looking for a slot... 86 */ 87 for (i = cdevsw_ALLOCSTART; i < nchrdev; i++) 88 if (cdevsw[i] == NULL) 89 break; /* found one! */ 90 /* out of allocable slots? */ 91 if (i >= nchrdev) { 92 return ENFILE; 93 } 94 } else { /* assign */ 95 i = major(*descrip); 96 if (i < 0 || i >= nchrdev) { 97 return EINVAL; 98 } 99 } 100 101 /* maybe save old */ 102 if (oldentry) { 103 *oldentry = cdevsw[i]; 104 } 105 if (newentry) { 106 newentry->d_bmaj = -1; 107 newentry->d_maj = i; 108 } 109 /* replace with new */ 110 cdevsw[i] = newentry; 111 112 /* done! let them know where we put it */ 113 *descrip = makedev(i,0); 114 return 0; 115} 116 117void 118cdevsw_add_generic(int bmaj, int cmaj, struct cdevsw *devsw) 119{ 120 dev_t dev; 121 122 dev = makedev(cmaj, 0); 123 cdevsw_add(&dev, devsw, NULL); 124 cdevsw[cmaj]->d_bmaj = bmaj; 125 bmaj2cmaj[bmaj] = cmaj; 126} 127 128int 129devsw_module_handler(module_t mod, int what, void* arg) 130{ 131 struct devsw_module_data* data = (struct devsw_module_data*) arg; 132 int error; 133 134 if (data->cmaj == NOMAJ) 135 data->cdev = NODEV; 136 else 137 data->cdev = makedev(data->cmaj, 0); 138 switch (what) { 139 case MOD_LOAD: 140 error = cdevsw_add(&data->cdev, data->cdevsw, NULL); 141 if (!error && data->cdevsw->d_strategy != nostrategy) { 142 if (data->bmaj == NOMAJ) { 143 data->bdev = data->cdev; 144 data->bmaj = data->cmaj; 145 } else { 146 data->bdev = makedev(data->bmaj, 0); 147 } 148 data->cdevsw->d_maj = data->bmaj; 149 bmaj2cmaj[major(data->bdev)] = major(data->cdev); 150 } 151 if (!error && data->chainevh) 152 error = data->chainevh(mod, what, data->chainarg); 153 return error; 154 155 case MOD_UNLOAD: 156 if (data->chainevh) { 157 error = data->chainevh(mod, what, data->chainarg); 158 if (error) 159 return error; 160 } 161 if (data->cdevsw->d_strategy != nostrategy) 162 bmaj2cmaj[major(data->bdev)] = 0; 163 error = cdevsw_add(&data->cdev, NULL, NULL); 164 return error; 165 } 166 167 if (data->chainevh) 168 return data->chainevh(mod, what, data->chainarg); 169 else 170 return 0; 171} 172 173/* 174 * dev_t and u_dev_t primitives 175 */ 176 177#define DEVT_FASCIST 1 178 179int 180major(dev_t x) 181{ 182 uintptr_t i = (uintptr_t)x; 183 184#ifdef DEVT_FASCIST 185 return(253 - ((i >> 8) & 0xff)); 186#else 187 return((i >> 8) & 0xff); 188#endif 189} 190 191int 192minor(dev_t x) 193{ 194 uintptr_t i = (uintptr_t)x; 195 196 return(i & 0xffff00ff); 197} 198 199dev_t 200makedev(int x, int y) 201{ 202#ifdef DEVT_FASCIST 203 return ((dev_t) (((253 - x) << 8) | y)); 204#else 205 return ((dev_t) ((x << 8) | y)); 206#endif 207} 208 209udev_t 210dev2udev(dev_t x) 211{ 212 return umakedev(major(x), minor(x)); 213} 214 215dev_t 216udev2dev(udev_t x, int b) 217{ 218 return makedev(umajor(x), uminor(x)); 219} 220 221int 222uminor(udev_t dev) 223{ 224 return(dev & 0xffff00ff); 225} 226 227int 228umajor(udev_t dev) 229{ 230 return((dev & 0xff00) >> 8); 231} 232 233udev_t 234umakedev(int x, int y) 235{ 236 return ((x << 8) | y); 237} 238 239