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.26 1998/06/26 18:14:25 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 NUMBDEV 128 43 #define NUMCDEV 256 44 #define bdevsw_ALLOCSTART (NUMBDEV/2) 45 #define cdevsw_ALLOCSTART (NUMCDEV/2) 46 47 struct cdevsw *bdevsw[NUMBDEV]; 48 int nblkdev = NUMBDEV; 49 struct cdevsw *cdevsw[NUMCDEV]; 50 int nchrdev = NUMCDEV; 51 52 /* 53 * Routine to convert from character to block device number. 54 * 55 * A minimal stub routine can always return NODEV. 56 */ 57 dev_t 58 chrtoblk(dev_t dev) 59 { 60 struct bdevsw *bd; 61 struct cdevsw *cd; 62 63 if(cd = cdevsw[major(dev)]) { 64 if (cd->d_bmaj != -1) 65 return(makedev(cd->d_bmaj,minor(dev))); 66 } 67 return(NODEV); 68 } 69 70 /* 71 * (re)place an entry in the bdevsw or cdevsw table 72 * return the slot used in major(*descrip) 73 */ 74 static int 75 bdevsw_add(dev_t *descrip, 76 struct cdevsw *newentry, 77 struct cdevsw **oldentry) 78 { 79 int i ; 80 81 if ( (int)*descrip == NODEV) { /* auto (0 is valid) */ 82 /* 83 * Search the table looking for a slot... 84 */ 85 for (i = bdevsw_ALLOCSTART; i < nblkdev; i++) 86 if (bdevsw[i] == NULL) 87 break; /* found one! */ 88 /* out of allocable slots? */ 89 if (i >= nblkdev) { 90 return ENFILE; 91 } 92 } else { /* assign */ 93 i = major(*descrip); 94 if (i < 0 || i >= nblkdev) { 95 return EINVAL; 96 } 97 } 98 99 /* maybe save old */ 100 if (oldentry) { 101 *oldentry = bdevsw[i]; 102 } 103 if (newentry) { 104 newentry->d_bmaj = i; 105 } 106 /* replace with new */ 107 bdevsw[i] = newentry; 108 109 /* done! let them know where we put it */ 110 *descrip = makedev(i,0); 111 return 0; 112 } 113 114 int 115 cdevsw_add(dev_t *descrip, 116 struct cdevsw *newentry, 117 struct cdevsw **oldentry) 118 { 119 int i ; 120 121 if ( (int)*descrip == NODEV) { /* auto (0 is valid) */ 122 /* 123 * Search the table looking for a slot... 124 */ 125 for (i = cdevsw_ALLOCSTART; i < nchrdev; i++) 126 if (cdevsw[i] == NULL) 127 break; /* found one! */ 128 /* out of allocable slots? */ 129 if (i >= nchrdev) { 130 return ENFILE; 131 } 132 } else { /* assign */ 133 i = major(*descrip); 134 if (i < 0 || i >= nchrdev) { 135 return EINVAL; 136 } 137 } 138 139 /* maybe save old */ 140 if (oldentry) { 141 *oldentry = cdevsw[i]; 142 } 143 if (newentry) { 144 newentry->d_bmaj = -1; 145 newentry->d_maj = i; 146 } 147 /* replace with new */ 148 cdevsw[i] = newentry; 149 150 /* done! let them know where we put it */ 151 *descrip = makedev(i,0); 152 return 0; 153 } 154 155 /* 156 * note must call cdevsw_add before bdevsw_add due to d_bmaj hack. 157 */ 158 void 159 cdevsw_add_generic(int bdev, int cdev, struct cdevsw *cdevsw) 160 { 161 dev_t dev; 162 163 dev = makedev(cdev, 0); 164 cdevsw_add(&dev, cdevsw, NULL); 165 dev = makedev(bdev, 0); 166 bdevsw_add(&dev, cdevsw, NULL); 167 } 168 169 int 170 cdevsw_module_handler(module_t mod, modeventtype_t what, void* arg) 171 { 172 struct cdevsw_module_data* data = (struct cdevsw_module_data*) arg; 173 int error; 174 175 switch (what) { 176 case MOD_LOAD: 177 if (error = cdevsw_add(&data->dev, data->cdevsw, NULL)) 178 return error; 179 break; 180 181 case MOD_UNLOAD: 182 if (error = cdevsw_add(&data->dev, NULL, NULL)) 183 return error; 184 break; 185 } 186 187 if (data->chainevh) 188 return data->chainevh(mod, what, data->chainarg); 189 else 190 return 0; 191 } 192 193 int 194 bdevsw_module_handler(module_t mod, modeventtype_t what, void* arg) 195 { 196 struct bdevsw_module_data* data = (struct bdevsw_module_data*) arg; 197 int error; 198 199 switch (what) { 200 case MOD_LOAD: 201 if (error = cdevsw_add(&data->cdev, data->cdevsw, NULL)) 202 return error; 203 if (error = bdevsw_add(&data->bdev, data->cdevsw, NULL)) { 204 cdevsw_add(&data->bdev, NULL, NULL); 205 return error; 206 } 207 break; 208 209 case MOD_UNLOAD: 210 if (error = bdevsw_add(&data->bdev, NULL, NULL)) 211 return error; 212 if (error = cdevsw_add(&data->cdev, NULL, NULL)) 213 return error; 214 break; 215 } 216 217 if (data->chainevh) 218 return data->chainevh(mod, what, data->chainarg); 219 else 220 return 0; 221 } 222