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.21 1997/09/21 22:20:12 julian Exp $ 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/conf.h> 39 #include <sys/vnode.h> 40 41 #define NUMBDEV 128 42 #define NUMCDEV 256 43 #define bdevsw_ALLOCSTART (NUMBDEV/2) 44 #define cdevsw_ALLOCSTART (NUMCDEV/2) 45 46 struct bdevsw *bdevsw[NUMBDEV]; 47 int nblkdev = NUMBDEV; 48 struct cdevsw *cdevsw[NUMCDEV]; 49 int nchrdev = NUMCDEV; 50 51 52 53 /* 54 * Routine to determine if a device is a disk. 55 * 56 * KLUDGE XXX add flags to cdevsw entries for disks XXX 57 * A minimal stub routine can always return 0. 58 */ 59 int 60 isdisk(dev, type) 61 dev_t dev; 62 int type; 63 { 64 65 switch (major(dev)) { 66 case 15: /* VBLK: vn, VCHR: cd */ 67 return (1); 68 case 0: /* wd */ 69 case 2: /* fd */ 70 case 4: /* sd */ 71 case 6: /* cd */ 72 case 7: /* mcd */ 73 case 16: /* scd */ 74 case 17: /* matcd */ 75 case 18: /* ata */ 76 case 19: /* wcd */ 77 case 20: /* od */ 78 case 22: /* gd */ 79 if (type == VBLK) 80 return (1); 81 return (0); 82 case 3: /* wd */ 83 case 9: /* fd */ 84 case 13: /* sd */ 85 case 29: /* mcd */ 86 case 43: /* vn */ 87 case 45: /* scd */ 88 case 46: /* matcd */ 89 case 69: /* wcd */ 90 case 70: /* od */ 91 case 78: /* gd */ 92 if (type == VCHR) 93 return (1); 94 /* fall through */ 95 default: 96 return (0); 97 } 98 /* NOTREACHED */ 99 } 100 101 102 /* 103 * Routine to convert from character to block device number. 104 * 105 * A minimal stub routine can always return NODEV. 106 */ 107 dev_t 108 chrtoblk(dev_t dev) 109 { 110 struct bdevsw *bd; 111 struct cdevsw *cd; 112 113 if(cd = cdevsw[major(dev)]) { 114 if ( (bd = cd->d_bdev) ) 115 return(makedev(bd->d_maj,minor(dev))); 116 } 117 return(NODEV); 118 } 119 120 /* 121 * (re)place an entry in the bdevsw or cdevsw table 122 * return the slot used in major(*descrip) 123 */ 124 #define ADDENTRY(TTYPE,NXXXDEV,ALLOCSTART) \ 125 int TTYPE##_add(dev_t *descrip, \ 126 struct TTYPE *newentry, \ 127 struct TTYPE **oldentry) \ 128 { \ 129 int i ; \ 130 if ( (int)*descrip == NODEV) { /* auto (0 is valid) */ \ 131 /* \ 132 * Search the table looking for a slot... \ 133 */ \ 134 for (i = ALLOCSTART; i < NXXXDEV; i++) \ 135 if (TTYPE[i] == NULL) \ 136 break; /* found one! */ \ 137 /* out of allocable slots? */ \ 138 if (i >= NXXXDEV) { \ 139 return ENFILE; \ 140 } \ 141 } else { /* assign */ \ 142 i = major(*descrip); \ 143 if (i < 0 || i >= NXXXDEV) { \ 144 return EINVAL; \ 145 } \ 146 } \ 147 \ 148 /* maybe save old */ \ 149 if (oldentry) { \ 150 *oldentry = TTYPE[i]; \ 151 } \ 152 if (newentry) \ 153 newentry->d_maj = i; \ 154 /* replace with new */ \ 155 TTYPE[i] = newentry; \ 156 \ 157 /* done! let them know where we put it */ \ 158 *descrip = makedev(i,0); \ 159 return 0; \ 160 } \ 161 162 ADDENTRY(bdevsw, nblkdev,bdevsw_ALLOCSTART) 163 ADDENTRY(cdevsw, nchrdev,cdevsw_ALLOCSTART) 164 165 /* 166 * Since the bdevsw struct for a disk contains all the information 167 * needed to create a cdevsw entry, these two routines do that, rather 168 * than specifying it by hand. 169 */ 170 171 void 172 cdevsw_make(struct bdevsw *from) 173 { 174 struct cdevsw *to = from->d_cdev; 175 176 if (!to) 177 panic("No target cdevsw in bdevsw"); 178 to->d_open = from->d_open; 179 to->d_close = from->d_close; 180 to->d_read = rawread; 181 to->d_write = rawwrite; 182 to->d_ioctl = from->d_ioctl; 183 to->d_stop = nostop; 184 to->d_reset = nullreset; 185 to->d_devtotty = nodevtotty; 186 to->d_poll = seltrue; 187 to->d_mmap = nommap; 188 to->d_strategy = from->d_strategy; 189 to->d_name = from->d_name; 190 to->d_bdev = from; 191 to->d_maj = -1; 192 } 193 194 void 195 bdevsw_add_generic(int bdev, int cdev, struct bdevsw *bdevsw) 196 { 197 dev_t dev; 198 /* 199 * XXX hack alert. 200 */ 201 if (isdisk(makedev(bdev, 0), VBLK) && 202 (bdevsw->d_flags & D_TYPEMASK) != D_DISK) { 203 printf("bdevsw_add_generic: adding D_DISK flag for device %d\n", 204 bdev); 205 bdevsw->d_flags &= ~D_TYPEMASK; 206 bdevsw->d_flags |= D_DISK; 207 } 208 cdevsw_make(bdevsw); 209 dev = makedev(cdev, 0); 210 cdevsw_add(&dev, bdevsw->d_cdev, NULL); 211 dev = makedev(bdev, 0); 212 bdevsw_add(&dev, bdevsw , NULL); 213 } 214