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