kern_conf.c revision 37153
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.24 1998/06/07 17:11:32 dfr 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 47struct bdevsw *bdevsw[NUMBDEV]; 48int nblkdev = NUMBDEV; 49struct cdevsw *cdevsw[NUMCDEV]; 50int nchrdev = NUMCDEV; 51 52static void cdevsw_make __P((struct bdevsw *from)); 53static int isdisk __P((dev_t dev, int type)); 54 55/* 56 * Routine to determine if a device is a disk. 57 * 58 * KLUDGE XXX add flags to cdevsw entries for disks XXX 59 * A minimal stub routine can always return 0. 60 */ 61static int 62isdisk(dev, type) 63 dev_t dev; 64 int type; 65{ 66 67 switch (major(dev)) { 68 case 15: /* VBLK: vn, VCHR: cd */ 69 return (1); 70 case 0: /* wd */ 71 case 2: /* fd */ 72 case 4: /* sd */ 73 case 6: /* cd */ 74 case 7: /* mcd */ 75 case 16: /* scd */ 76 case 17: /* matcd */ 77 case 18: /* ata */ 78 case 19: /* wcd */ 79 case 20: /* od */ 80 case 22: /* gd */ 81 if (type == VBLK) 82 return (1); 83 return (0); 84 case 3: /* wd */ 85 case 9: /* fd */ 86 case 13: /* sd */ 87 case 29: /* mcd */ 88 case 43: /* vn */ 89 case 45: /* scd */ 90 case 46: /* matcd */ 91 case 69: /* wcd */ 92 case 70: /* od */ 93 case 78: /* gd */ 94 if (type == VCHR) 95 return (1); 96 /* fall through */ 97 default: 98 return (0); 99 } 100 /* NOTREACHED */ 101} 102 103 104/* 105 * Routine to convert from character to block device number. 106 * 107 * A minimal stub routine can always return NODEV. 108 */ 109dev_t 110chrtoblk(dev_t dev) 111{ 112 struct bdevsw *bd; 113 struct cdevsw *cd; 114 115 if(cd = cdevsw[major(dev)]) { 116 if ( (bd = cd->d_bdev) ) 117 return(makedev(bd->d_maj,minor(dev))); 118 } 119 return(NODEV); 120} 121 122/* 123 * (re)place an entry in the bdevsw or cdevsw table 124 * return the slot used in major(*descrip) 125 */ 126#define ADDENTRY(TTYPE,NXXXDEV,ALLOCSTART) \ 127int TTYPE##_add(dev_t *descrip, \ 128 struct TTYPE *newentry, \ 129 struct TTYPE **oldentry) \ 130{ \ 131 int i ; \ 132 if ( (int)*descrip == NODEV) { /* auto (0 is valid) */ \ 133 /* \ 134 * Search the table looking for a slot... \ 135 */ \ 136 for (i = ALLOCSTART; i < NXXXDEV; i++) \ 137 if (TTYPE[i] == NULL) \ 138 break; /* found one! */ \ 139 /* out of allocable slots? */ \ 140 if (i >= NXXXDEV) { \ 141 return ENFILE; \ 142 } \ 143 } else { /* assign */ \ 144 i = major(*descrip); \ 145 if (i < 0 || i >= NXXXDEV) { \ 146 return EINVAL; \ 147 } \ 148 } \ 149 \ 150 /* maybe save old */ \ 151 if (oldentry) { \ 152 *oldentry = TTYPE[i]; \ 153 } \ 154 if (newentry) \ 155 newentry->d_maj = i; \ 156 /* replace with new */ \ 157 TTYPE[i] = newentry; \ 158 \ 159 /* done! let them know where we put it */ \ 160 *descrip = makedev(i,0); \ 161 return 0; \ 162} \ 163 164static ADDENTRY(bdevsw, nblkdev,bdevsw_ALLOCSTART) 165ADDENTRY(cdevsw, nchrdev,cdevsw_ALLOCSTART) 166 167/* 168 * Since the bdevsw struct for a disk contains all the information 169 * needed to create a cdevsw entry, these two routines do that, rather 170 * than specifying it by hand. 171 */ 172 173static void 174cdevsw_make(struct bdevsw *from) 175{ 176 struct cdevsw *to = from->d_cdev; 177 178 if (!to) 179 panic("No target cdevsw in bdevsw"); 180 to->d_open = from->d_open; 181 to->d_close = from->d_close; 182 to->d_read = rawread; 183 to->d_write = rawwrite; 184 to->d_ioctl = from->d_ioctl; 185 to->d_stop = nostop; 186 to->d_reset = nullreset; 187 to->d_devtotty = nodevtotty; 188 to->d_poll = seltrue; 189 to->d_mmap = nommap; 190 to->d_strategy = from->d_strategy; 191 to->d_name = from->d_name; 192 to->d_bdev = from; 193 to->d_maj = -1; 194 to->d_bmaj = from->d_maj; 195 to->d_maxio = from->d_maxio; 196 to->d_dump = from->d_dump; 197 to->d_psize = from->d_psize; 198 to->d_flags = from->d_flags; 199} 200 201void 202bdevsw_add_generic(int bdev, int cdev, struct bdevsw *bdevsw) 203{ 204 dev_t dev; 205 /* 206 * XXX hack alert. 207 */ 208 if (isdisk(makedev(bdev, 0), VBLK) && 209 (bdevsw->d_flags & D_TYPEMASK) != D_DISK) { 210 printf("bdevsw_add_generic: adding D_DISK flag for device %d\n", 211 bdev); 212 bdevsw->d_flags &= ~D_TYPEMASK; 213 bdevsw->d_flags |= D_DISK; 214 } 215 cdevsw_make(bdevsw); 216 dev = makedev(cdev, 0); 217 cdevsw_add(&dev, bdevsw->d_cdev, NULL); 218 dev = makedev(bdev, 0); 219 bdevsw_add(&dev, bdevsw , NULL); 220} 221 222int 223cdevsw_module_handler(module_t mod, modeventtype_t what, void* arg) 224{ 225 struct cdevsw_module_data* data = (struct cdevsw_module_data*) arg; 226 int error; 227 228 switch (what) { 229 case MOD_LOAD: 230 if (error = cdevsw_add(&data->dev, data->cdevsw, NULL)) 231 return error; 232 break; 233 234 case MOD_UNLOAD: 235 if (error = cdevsw_add(&data->dev, NULL, NULL)) 236 return error; 237 break; 238 } 239 240 if (data->chainevh) 241 return data->chainevh(mod, what, data->chainarg); 242 else 243 return 0; 244} 245 246int 247bdevsw_module_handler(module_t mod, modeventtype_t what, void* arg) 248{ 249 struct bdevsw_module_data* data = (struct bdevsw_module_data*) arg; 250 int error; 251 252 switch (what) { 253 case MOD_LOAD: 254 /* 255 * XXX hack alert. 256 */ 257 if (isdisk(data->bdev, VBLK) && data->bdevsw->d_flags != D_DISK) { 258 printf("bdevsw_module_handler: adding D_DISK flag for device %d\n", 259 major(data->bdev)); 260 data->bdevsw->d_flags = D_DISK; 261 } 262 cdevsw_make(data->bdevsw); 263 if (error = cdevsw_add(&data->cdev, data->bdevsw->d_cdev, NULL)) 264 return error; 265 if (error = bdevsw_add(&data->bdev, data->bdevsw, NULL)) 266 return error; 267 break; 268 269 case MOD_UNLOAD: 270 if (error = cdevsw_add(&data->cdev, NULL, NULL)) 271 return error; 272 if (error = cdevsw_add(&data->bdev, NULL, NULL)) 273 return error; 274 break; 275 } 276 277 if (data->chainevh) 278 return data->chainevh(mod, what, data->chainarg); 279 else 280 return 0; 281} 282