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.42 1999/06/01 18:56:24 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 cdevsw_ALLOCSTART (NUMCDEVSW/2) 43 44 struct cdevsw *cdevsw[NUMCDEVSW]; 45 46 int bmaj2cmaj[NUMCDEVSW]; 47 48 /* 49 * Routine to convert from character to block device number. 50 * 51 * A minimal stub routine can always return NODEV. 52 */ 53 dev_t 54 chrtoblk(dev_t dev) 55 { 56 struct cdevsw *cd; 57 58 if((cd = devsw(dev)) != NULL) { 59 if (cd->d_bmaj != -1) 60 return(makedev(cd->d_bmaj,minor(dev))); 61 } 62 return(NODEV); 63 } 64 65 struct cdevsw * 66 devsw(dev_t dev) 67 { 68 return(cdevsw[major(dev)]); 69 } 70 71 struct cdevsw * 72 bdevsw(dev_t dev) 73 { 74 struct cdevsw *c; 75 int i = major(dev); 76 77 if (bmaj2cmaj[i] == 254) 78 return 0; 79 80 c = cdevsw[bmaj2cmaj[major(dev)]]; 81 if (!c) { 82 printf("bogus bdev dev_t %p, no cdev\n", (void *)dev); 83 Debugger("Bummer"); 84 return 0; 85 } 86 /* CMAJ zero is the console, which has no strategy so this works */ 87 if (c->d_strategy) 88 return (c); 89 return (0); 90 } 91 92 /* 93 * Add a cdevsw entry 94 */ 95 96 int 97 cdevsw_add(struct cdevsw *newentry) 98 { 99 int i; 100 static int setup; 101 102 if (!setup) { 103 for (i = 0; i < NUMCDEVSW; i++) 104 if (!bmaj2cmaj[i]) 105 bmaj2cmaj[i] = 254; 106 setup++; 107 } 108 109 if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) { 110 printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n", 111 newentry->d_name, newentry->d_maj); 112 return EINVAL; 113 } 114 115 cdevsw[newentry->d_maj] = newentry; 116 117 if (newentry->d_bmaj >= 0 && newentry->d_bmaj < NUMCDEVSW) 118 bmaj2cmaj[newentry->d_bmaj] = newentry->d_maj; 119 120 return 0; 121 } 122 123 int 124 devsw_module_handler(module_t mod, int what, void* arg) 125 { 126 struct devsw_module_data* data = (struct devsw_module_data*) arg; 127 int error; 128 129 if (data->cmaj == NOMAJ) 130 data->cdev = NODEV; 131 else 132 data->cdev = makedev(data->cmaj, 0); 133 switch (what) { 134 case MOD_LOAD: 135 error = cdevsw_add(data->cdevsw); 136 if (!error && data->cdevsw->d_strategy != nostrategy) { 137 if (data->bmaj == NOMAJ) { 138 data->bdev = data->cdev; 139 data->bmaj = data->cmaj; 140 } else { 141 data->bdev = makedev(data->bmaj, 0); 142 } 143 data->cdevsw->d_maj = data->bmaj; 144 bmaj2cmaj[major(data->bdev)] = major(data->cdev); 145 } 146 if (!error && data->chainevh) 147 error = data->chainevh(mod, what, data->chainarg); 148 return error; 149 150 case MOD_UNLOAD: 151 if (data->chainevh) { 152 error = data->chainevh(mod, what, data->chainarg); 153 if (error) 154 return error; 155 } 156 if (data->cdevsw->d_strategy != nostrategy) 157 bmaj2cmaj[major(data->bdev)] = 0; 158 return error; 159 } 160 161 if (data->chainevh) 162 return data->chainevh(mod, what, data->chainarg); 163 else 164 return 0; 165 } 166 167 /* 168 * dev_t and u_dev_t primitives 169 */ 170 171 #define DEVT_FASCIST 1 172 173 int 174 major(dev_t x) 175 { 176 uintptr_t i = (uintptr_t)x; 177 178 #ifdef DEVT_FASCIST 179 return(255 - ((i >> 8) & 0xff)); 180 #else 181 return((i >> 8) & 0xff); 182 #endif 183 } 184 185 int 186 minor(dev_t x) 187 { 188 uintptr_t i = (uintptr_t)x; 189 190 return(i & 0xffff00ff); 191 } 192 193 dev_t 194 makebdev(int x, int y) 195 { 196 return (makedev(x, y)); 197 } 198 199 dev_t 200 makedev(int x, int y) 201 { 202 #ifdef DEVT_FASCIST 203 return ((dev_t) (((255 - x) << 8) | y)); 204 #else 205 return ((dev_t) ((x << 8) | y)); 206 #endif 207 } 208 209 udev_t 210 dev2udev(dev_t x) 211 { 212 return umakedev(major(x), minor(x)); 213 } 214 215 dev_t 216 udev2dev(udev_t x, int b) 217 { 218 return makedev(umajor(x), uminor(x)); 219 } 220 221 int 222 uminor(udev_t dev) 223 { 224 return(dev & 0xffff00ff); 225 } 226 227 int 228 umajor(udev_t dev) 229 { 230 return((dev & 0xff00) >> 8); 231 } 232 233 udev_t 234 umakedev(int x, int y) 235 { 236 return ((x << 8) | y); 237 } 238 239