1 /*- 2 * Copyright (c) 1992 OMRON Corporation. 3 * Copyright (c) 1991, 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 * 8 * from: hp300/hp300/conf.c 8.2 (Berkeley) 11/14/93 9 * 10 * @(#)conf.c 8.4 (Berkeley) 11/21/94 11 */ 12 13 #include <sys/param.h> 14 #include <sys/systm.h> 15 #include <sys/buf.h> 16 #include <sys/ioctl.h> 17 #include <sys/proc.h> 18 #include <sys/vnode.h> 19 #include <sys/tty.h> 20 #include <sys/conf.h> 21 22 int rawread __P((dev_t, struct uio *, int)); 23 int rawwrite __P((dev_t, struct uio *, int)); 24 int swstrategy __P((struct buf *)); 25 int ttselect __P((dev_t, int, struct proc *)); 26 27 #define dev_type_open(n) int n __P((dev_t, int, int, struct proc *)) 28 #define dev_type_close(n) int n __P((dev_t, int, int, struct proc *)) 29 #define dev_type_strategy(n) int n __P((struct buf *)) 30 #define dev_type_ioctl(n) \ 31 int n __P((dev_t, int, caddr_t, int, struct proc *)) 32 33 /* bdevsw-specific types */ 34 #define dev_type_dump(n) int n __P(()) 35 #define dev_type_size(n) int n __P((dev_t)) 36 37 #define dev_decl(n,t) __CONCAT(dev_type_,t)(__CONCAT(n,t)) 38 #define dev_init(c,n,t) \ 39 (c > 0 ? __CONCAT(n,t) : (__CONCAT(dev_type_,t)((*))) enxio) 40 41 /* bdevsw-specific initializations */ 42 #define dev_size_init(c,n) (c > 0 ? __CONCAT(n,size) : 0) 43 44 #define bdev_decl(n) \ 45 dev_decl(n,open); dev_decl(n,close); dev_decl(n,strategy); \ 46 dev_decl(n,ioctl); dev_decl(n,dump); dev_decl(n,size) 47 48 /* disk without close routine */ 49 #define bdev_disk_init(c,n) { \ 50 dev_init(c,n,open), (dev_type_close((*))) nullop, \ 51 dev_init(c,n,strategy), dev_init(c,n,ioctl), \ 52 dev_init(c,n,dump), dev_size_init(c,n), 0 } 53 54 /* disk with close routine */ 55 #define bdev_ldisk_init(c,n) { \ 56 dev_init(c,n,open), dev_init(c,n,close), \ 57 dev_init(c,n,strategy), dev_init(c,n,ioctl), \ 58 dev_init(c,n,dump), dev_size_init(c,n), 0 } 59 60 #define bdev_tape_init(c,n) { \ 61 dev_init(c,n,open), dev_init(c,n,close), \ 62 dev_init(c,n,strategy), dev_init(c,n,ioctl), \ 63 dev_init(c,n,dump), 0, B_TAPE } 64 65 #define bdev_swap_init() { \ 66 (dev_type_open((*))) enodev, (dev_type_close((*))) enodev, \ 67 swstrategy, (dev_type_ioctl((*))) enodev, \ 68 (dev_type_dump((*))) enodev, 0, 0 } 69 70 #define bdev_notdef() bdev_tape_init(0,no) 71 72 bdev_decl(no); /* dummy declarations */ 73 74 #include "st.h" 75 #include "sd.h" 76 #include "vn.h" 77 78 bdev_decl(st); 79 bdev_decl(sd); 80 bdev_decl(vn); 81 82 struct bdevsw bdevsw[] = 83 { 84 bdev_notdef(), /* 0 */ 85 bdev_notdef(), /* 1 */ 86 bdev_notdef(), /* 2 */ 87 bdev_swap_init(), /* 3: swap pseudo-device */ 88 bdev_ldisk_init(NSD,sd),/* 4: scsi disk */ 89 bdev_notdef(), /* 5 */ 90 bdev_disk_init(NVN,vn), /* 6: vnode disk driver (swap to files) */ 91 bdev_tape_init(NST,st), /* 7: scsi tape */ 92 }; 93 94 int nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]); 95 96 /* cdevsw-specific types */ 97 #define dev_type_read(n) int n __P((dev_t, struct uio *, int)) 98 #define dev_type_write(n) int n __P((dev_t, struct uio *, int)) 99 #define dev_type_stop(n) int n __P((struct tty *, int)) 100 #define dev_type_reset(n) int n __P((int)) 101 #define dev_type_select(n) int n __P((dev_t, int, struct proc *)) 102 #define dev_type_map(n) int n __P(()) 103 104 #define cdev_decl(n) \ 105 dev_decl(n,open); dev_decl(n,close); dev_decl(n,read); \ 106 dev_decl(n,write); dev_decl(n,ioctl); dev_decl(n,stop); \ 107 dev_decl(n,reset); dev_decl(n,select); dev_decl(n,map); \ 108 dev_decl(n,strategy); extern struct tty __CONCAT(n,_tty)[] 109 110 #define dev_tty_init(c,n) (c > 0 ? __CONCAT(n,_tty) : 0) 111 112 /* open, read, write, ioctl, strategy */ 113 #define cdev_disk_init(c,n) { \ 114 dev_init(c,n,open), (dev_type_close((*))) nullop, dev_init(c,n,read), \ 115 dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ 116 (dev_type_reset((*))) nullop, 0, seltrue, (dev_type_map((*))) enodev, \ 117 dev_init(c,n,strategy) } 118 119 /* open, close, read, write, ioctl, strategy */ 120 #define cdev_ldisk_init(c,n) { \ 121 dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ 122 dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ 123 (dev_type_reset((*))) nullop, 0, seltrue, (dev_type_map((*))) enodev, \ 124 dev_init(c,n,strategy) } 125 126 /* open, close, read, write, ioctl, strategy */ 127 #define cdev_tape_init(c,n) { \ 128 dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ 129 dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ 130 (dev_type_reset((*))) nullop, 0, seltrue, (dev_type_map((*))) enodev, \ 131 dev_init(c,n,strategy) } 132 133 /* open, close, read, write, ioctl, stop, tty */ 134 #define cdev_tty_init(c,n) { \ 135 dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ 136 dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \ 137 (dev_type_reset((*))) nullop, dev_tty_init(c,n), ttselect, \ 138 (dev_type_map((*))) enodev, 0 } 139 140 #define cdev_notdef() { \ 141 (dev_type_open((*))) enodev, (dev_type_close((*))) enodev, \ 142 (dev_type_read((*))) enodev, (dev_type_write((*))) enodev, \ 143 (dev_type_ioctl((*))) enodev, (dev_type_stop((*))) enodev, \ 144 (dev_type_reset((*))) nullop, 0, seltrue, \ 145 (dev_type_map((*))) enodev, 0 } 146 147 cdev_decl(no); /* dummy declarations */ 148 149 cdev_decl(cn); 150 /* open, close, read, write, ioctl, select -- XXX should be a tty */ 151 #define cdev_cn_init(c,n) { \ 152 dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ 153 dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \ 154 (dev_type_reset((*))) nullop, 0, dev_init(c,n,select), \ 155 (dev_type_map((*))) enodev, 0 } 156 157 cdev_decl(ctty); 158 /* open, read, write, ioctl, select -- XXX should be a tty */ 159 #define cdev_ctty_init(c,n) { \ 160 dev_init(c,n,open), (dev_type_close((*))) nullop, dev_init(c,n,read), \ 161 dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \ 162 (dev_type_reset((*))) nullop, 0, dev_init(c,n,select), \ 163 (dev_type_map((*))) enodev, 0 } 164 165 dev_type_read(mmrw); 166 dev_type_map(mmmap); 167 /* read, write, mmap */ 168 #define cdev_mm_init(c,n) { \ 169 (dev_type_open((*))) nullop, (dev_type_close((*))) nullop, mmrw, \ 170 mmrw, (dev_type_ioctl((*))) enodev, (dev_type_stop((*))) nullop, \ 171 (dev_type_reset((*))) nullop, 0, seltrue, mmmap, 0 } 172 173 /* read, write, strategy */ 174 #define cdev_swap_init(c,n) { \ 175 (dev_type_open((*))) nullop, (dev_type_close((*))) nullop, rawread, \ 176 rawwrite, (dev_type_ioctl((*))) enodev, (dev_type_stop((*))) enodev, \ 177 (dev_type_reset((*))) nullop, 0, (dev_type_select((*))) enodev, \ 178 (dev_type_map((*))) enodev, dev_init(c,n,strategy) } 179 180 #include "pty.h" 181 #define pts_tty pt_tty 182 #define ptsioctl ptyioctl 183 cdev_decl(pts); 184 #define ptc_tty pt_tty 185 #define ptcioctl ptyioctl 186 cdev_decl(ptc); 187 188 /* open, close, read, write, ioctl, tty, select */ 189 #define cdev_ptc_init(c,n) { \ 190 dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ 191 dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) nullop, \ 192 (dev_type_reset((*))) nullop, dev_tty_init(c,n), dev_init(c,n,select), \ 193 (dev_type_map((*))) enodev, 0 } 194 195 cdev_decl(log); 196 /* open, close, read, ioctl, select -- XXX should be a generic device */ 197 #define cdev_log_init(c,n) { \ 198 dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ 199 (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ 200 (dev_type_stop((*))) enodev, (dev_type_reset((*))) nullop, 0, \ 201 dev_init(c,n,select), (dev_type_map((*))) enodev, 0 } 202 203 cdev_decl(st); 204 cdev_decl(sd); 205 206 cdev_decl(fb); 207 /* open, close, ioctl, mmap */ 208 #define cdev_fb_init(c,n) { \ 209 dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) nullop, \ 210 (dev_type_write((*))) nullop, dev_init(c,n,ioctl), \ 211 (dev_type_stop((*))) enodev, (dev_type_reset((*))) nullop, 0, \ 212 dev_init(c,n,select), dev_init(c,n,map), 0 } 213 214 #include "sio.h" 215 cdev_decl(sio); 216 217 #include "bmc.h" 218 cdev_decl(bmc); 219 220 cdev_decl(kbd); 221 /* open, close, read, ioctl, select, map -- XXX should be a map device */ 222 #define cdev_kbd_init(c,n) { \ 223 dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ 224 (dev_type_write((*))) nullop, dev_init(c,n,ioctl), \ 225 (dev_type_stop((*))) enodev, (dev_type_reset((*))) nullop, 0, \ 226 ttselect, (dev_type_map((*))) nullop, 0 } 227 228 cdev_decl(cd); 229 230 cdev_decl(vn); 231 /* open, read, write, ioctl -- XXX should be a disk */ 232 #define cdev_vn_init(c,n) { \ 233 dev_init(c,n,open), (dev_type_close((*))) nullop, dev_init(c,n,read), \ 234 dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ 235 (dev_type_reset((*))) nullop, 0, seltrue, (dev_type_map((*))) enodev, \ 236 0 } 237 238 dev_type_open(fdopen); 239 /* open */ 240 #define cdev_fd_init(c,n) { \ 241 dev_init(c,n,open), (dev_type_close((*))) enodev, \ 242 (dev_type_read((*))) enodev, (dev_type_write((*))) enodev, \ 243 (dev_type_ioctl((*))) enodev, (dev_type_stop((*))) enodev, \ 244 (dev_type_reset((*))) enodev, 0, (dev_type_select((*))) enodev, \ 245 (dev_type_map((*))) enodev, 0 } 246 247 #include "bpfilter.h" 248 cdev_decl(bpf); 249 /* open, close, read, write, ioctl, select -- XXX should be generic device */ 250 #define cdev_bpf_init(c,n) { \ 251 dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \ 252 dev_init(c,n,write), dev_init(c,n,ioctl), (dev_type_stop((*))) enodev, \ 253 (dev_type_reset((*))) enodev, 0, dev_init(c,n,select), \ 254 (dev_type_map((*))) enodev, 0 } 255 256 struct cdevsw cdevsw[] = 257 { 258 cdev_cn_init(1,cn), /* 0: virtual console */ 259 cdev_ctty_init(1,ctty), /* 1: controlling terminal */ 260 cdev_mm_init(1,mm), /* 2: /dev/{null,mem,kmem,...} */ 261 cdev_swap_init(1,sw), /* 3: /dev/drum (swap pseudo-device) */ 262 cdev_tty_init(NPTY,pts), /* 4: pseudo-tty slave */ 263 cdev_ptc_init(NPTY,ptc), /* 5: pseudo-tty master */ 264 cdev_log_init(1,log), /* 6: /dev/klog */ 265 cdev_notdef(), /* 7 */ 266 cdev_ldisk_init(NSD,sd), /* 8: scsi disk */ 267 cdev_notdef(), /* 9 */ 268 cdev_fb_init(1,fb), /* 10: frame buffer */ 269 cdev_notdef(), /* 11 */ 270 cdev_tty_init(NSIO,sio), /* 12: built-in single-port serial */ 271 cdev_tty_init(NBMC,bmc), /* 13: console terminal emulator */ 272 cdev_kbd_init(2,kbd), /* 14: keyboard */ 273 cdev_notdef(), /* 15 */ 274 cdev_notdef(), /* 16 */ 275 cdev_notdef(), /* 17 */ 276 cdev_notdef(), /* 18 */ 277 cdev_vn_init(NVN,vn), /* 19: vnode disk */ 278 cdev_tape_init(NST,st), /* 20: scsi tape */ 279 cdev_fd_init(1,fd), /* 21: file descriptor pseudo-dev */ 280 cdev_bpf_init(NBPFILTER,bpf), /* 22: berkeley packet filter */ 281 }; 282 283 int nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]); 284 285 int mem_no = 2; /* major device number of memory special file */ 286 287 /* 288 * Swapdev is a fake device implemented 289 * in sw.c used only internally to get to swstrategy. 290 * It cannot be provided to the users, because the 291 * swstrategy routine munches the b_dev and b_blkno entries 292 * before calling the appropriate driver. This would horribly 293 * confuse, e.g. the hashing routines. Instead, /dev/drum is 294 * provided as a character (raw) device. 295 */ 296 dev_t swapdev = makedev(3, 0); 297 298 /* 299 * Routine that identifies /dev/mem and /dev/kmem. 300 * 301 * A minimal stub routine can always return 0. 302 */ 303 iskmemdev(dev) 304 dev_t dev; 305 { 306 307 return (major(dev) == 2 && minor(dev) < 2); 308 } 309 310 iszerodev(dev) 311 dev_t dev; 312 { 313 return (major(dev) == 2 && minor(dev) == 12); 314 } 315 316 /* 317 * Routine to determine if a device is a tty. 318 * 319 * A minimal stub routine can always return 0. 320 */ 321 istty(dev) 322 dev_t dev; 323 { 324 325 switch (major(dev)) { 326 case 0: 327 case 1: 328 case 4: 329 case 5: 330 case 12: 331 case 13: 332 case 14: 333 return (1); 334 default: 335 return (0); 336 } 337 } 338 339 /* 340 * Routine to determine if a device is a disk. 341 * 342 * A minimal stub routine can always return 0. 343 */ 344 isdisk(dev, type) 345 dev_t dev; 346 int type; 347 { 348 349 switch (major(dev)) { 350 case 4: 351 case 6: 352 if (type == VBLK) 353 return (1); 354 return (0); 355 case 8: 356 case 19: 357 if (type == VCHR) 358 return (1); 359 /* fall through */ 360 default: 361 return (0); 362 } 363 /* NOTREACHED */ 364 } 365 366 #define MAXDEV 21 367 static int chrtoblktbl[MAXDEV] = { 368 /* VCHR */ /* VBLK */ 369 /* 0 */ NODEV, 370 /* 1 */ NODEV, 371 /* 2 */ NODEV, 372 /* 3 */ NODEV, 373 /* 4 */ NODEV, 374 /* 5 */ NODEV, 375 /* 6 */ NODEV, 376 /* 7 */ NODEV, 377 /* 8 */ 4, 378 /* 9 */ NODEV, 379 /* 10 */ NODEV, 380 /* 11 */ NODEV, 381 /* 12 */ NODEV, 382 /* 13 */ NODEV, 383 /* 14 */ NODEV, 384 /* 15 */ NODEV, 385 /* 16 */ NODEV, 386 /* 17 */ NODEV, 387 /* 18 */ NODEV, 388 /* 19 */ 6, 389 /* 20 */ 7, 390 }; 391 /* 392 * Routine to convert from character to block device number. 393 * 394 * A minimal stub routine can always return NODEV. 395 */ 396 chrtoblk(dev) 397 dev_t dev; 398 { 399 int blkmaj; 400 401 if (major(dev) >= MAXDEV || (blkmaj = chrtoblktbl[major(dev)]) == NODEV) 402 return (NODEV); 403 return (makedev(blkmaj, minor(dev))); 404 } 405