1 /* $NetBSD: subr_devsw.c,v 1.36 2016/12/16 23:35:04 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 2001, 2002, 2007, 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by MAEKAWA Masahide <gehenna@NetBSD.org>, and by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Overview 34 * 35 * subr_devsw.c: registers device drivers by name and by major 36 * number, and provides wrapper methods for performing I/O and 37 * other tasks on device drivers, keying on the device number 38 * (dev_t). 39 * 40 * When the system is built, the config(8) command generates 41 * static tables of device drivers built into the kernel image 42 * along with their associated methods. These are recorded in 43 * the cdevsw0 and bdevsw0 tables. Drivers can also be added to 44 * and removed from the system dynamically. 45 * 46 * Allocation 47 * 48 * When the system initially boots only the statically allocated 49 * indexes (bdevsw0, cdevsw0) are used. If these overflow due to 50 * allocation, we allocate a fixed block of memory to hold the new, 51 * expanded index. This "fork" of the table is only ever performed 52 * once in order to guarantee that other threads may safely access 53 * the device tables: 54 * 55 * o Once a thread has a "reference" to the table via an earlier 56 * open() call, we know that the entry in the table must exist 57 * and so it is safe to access it. 58 * 59 * o Regardless of whether other threads see the old or new 60 * pointers, they will point to a correct device switch 61 * structure for the operation being performed. 62 * 63 * XXX Currently, the wrapper methods such as cdev_read() verify 64 * that a device driver does in fact exist before calling the 65 * associated driver method. This should be changed so that 66 * once the device is has been referenced by a vnode (opened), 67 * calling the other methods should be valid until that reference 68 * is dropped. 69 */ 70 71 #include <sys/cdefs.h> 72 __KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.36 2016/12/16 23:35:04 riastradh Exp $"); 73 74 #ifdef _KERNEL_OPT 75 #include "opt_dtrace.h" 76 #endif 77 78 #include <sys/param.h> 79 #include <sys/conf.h> 80 #include <sys/kmem.h> 81 #include <sys/systm.h> 82 #include <sys/poll.h> 83 #include <sys/tty.h> 84 #include <sys/cpu.h> 85 #include <sys/buf.h> 86 #include <sys/reboot.h> 87 #include <sys/sdt.h> 88 89 #ifdef DEVSW_DEBUG 90 #define DPRINTF(x) printf x 91 #else /* DEVSW_DEBUG */ 92 #define DPRINTF(x) 93 #endif /* DEVSW_DEBUG */ 94 95 #define MAXDEVSW 512 /* the maximum of major device number */ 96 #define BDEVSW_SIZE (sizeof(struct bdevsw *)) 97 #define CDEVSW_SIZE (sizeof(struct cdevsw *)) 98 #define DEVSWCONV_SIZE (sizeof(struct devsw_conv)) 99 100 extern const struct bdevsw **bdevsw, *bdevsw0[]; 101 extern const struct cdevsw **cdevsw, *cdevsw0[]; 102 extern struct devsw_conv *devsw_conv, devsw_conv0[]; 103 extern const int sys_bdevsws, sys_cdevsws; 104 extern int max_bdevsws, max_cdevsws, max_devsw_convs; 105 106 static int bdevsw_attach(const struct bdevsw *, devmajor_t *); 107 static int cdevsw_attach(const struct cdevsw *, devmajor_t *); 108 static void devsw_detach_locked(const struct bdevsw *, const struct cdevsw *); 109 110 kmutex_t device_lock; 111 112 void (*biodone_vfs)(buf_t *) = (void *)nullop; 113 114 void 115 devsw_init(void) 116 { 117 118 KASSERT(sys_bdevsws < MAXDEVSW - 1); 119 KASSERT(sys_cdevsws < MAXDEVSW - 1); 120 mutex_init(&device_lock, MUTEX_DEFAULT, IPL_NONE); 121 } 122 123 int 124 devsw_attach(const char *devname, 125 const struct bdevsw *bdev, devmajor_t *bmajor, 126 const struct cdevsw *cdev, devmajor_t *cmajor) 127 { 128 struct devsw_conv *conv; 129 char *name; 130 int error, i; 131 size_t len; 132 133 if (devname == NULL || cdev == NULL) 134 return (EINVAL); 135 136 mutex_enter(&device_lock); 137 138 for (i = 0 ; i < max_devsw_convs ; i++) { 139 conv = &devsw_conv[i]; 140 if (conv->d_name == NULL || strcmp(devname, conv->d_name) != 0) 141 continue; 142 143 if (*bmajor < 0) 144 *bmajor = conv->d_bmajor; 145 if (*cmajor < 0) 146 *cmajor = conv->d_cmajor; 147 148 if (*bmajor != conv->d_bmajor || *cmajor != conv->d_cmajor) { 149 error = EINVAL; 150 goto fail; 151 } 152 if ((*bmajor >= 0 && bdev == NULL) || *cmajor < 0) { 153 error = EINVAL; 154 goto fail; 155 } 156 157 if ((*bmajor >= 0 && bdevsw[*bmajor] != NULL) || 158 cdevsw[*cmajor] != NULL) { 159 error = EEXIST; 160 goto fail; 161 } 162 163 if (bdev != NULL) 164 bdevsw[*bmajor] = bdev; 165 cdevsw[*cmajor] = cdev; 166 167 mutex_exit(&device_lock); 168 return (0); 169 } 170 171 error = bdevsw_attach(bdev, bmajor); 172 if (error != 0) 173 goto fail; 174 error = cdevsw_attach(cdev, cmajor); 175 if (error != 0) { 176 devsw_detach_locked(bdev, NULL); 177 goto fail; 178 } 179 180 for (i = 0 ; i < max_devsw_convs ; i++) { 181 if (devsw_conv[i].d_name == NULL) 182 break; 183 } 184 if (i == max_devsw_convs) { 185 struct devsw_conv *newptr; 186 int old_convs, new_convs; 187 188 old_convs = max_devsw_convs; 189 new_convs = old_convs + 1; 190 191 newptr = kmem_zalloc(new_convs * DEVSWCONV_SIZE, KM_NOSLEEP); 192 if (newptr == NULL) { 193 devsw_detach_locked(bdev, cdev); 194 error = ENOMEM; 195 goto fail; 196 } 197 newptr[old_convs].d_name = NULL; 198 newptr[old_convs].d_bmajor = -1; 199 newptr[old_convs].d_cmajor = -1; 200 memcpy(newptr, devsw_conv, old_convs * DEVSWCONV_SIZE); 201 if (devsw_conv != devsw_conv0) 202 kmem_free(devsw_conv, old_convs * DEVSWCONV_SIZE); 203 devsw_conv = newptr; 204 max_devsw_convs = new_convs; 205 } 206 207 len = strlen(devname) + 1; 208 name = kmem_alloc(len, KM_NOSLEEP); 209 if (name == NULL) { 210 devsw_detach_locked(bdev, cdev); 211 error = ENOMEM; 212 goto fail; 213 } 214 strlcpy(name, devname, len); 215 216 devsw_conv[i].d_name = name; 217 devsw_conv[i].d_bmajor = *bmajor; 218 devsw_conv[i].d_cmajor = *cmajor; 219 220 mutex_exit(&device_lock); 221 return (0); 222 fail: 223 mutex_exit(&device_lock); 224 return (error); 225 } 226 227 static int 228 bdevsw_attach(const struct bdevsw *devsw, devmajor_t *devmajor) 229 { 230 const struct bdevsw **newptr; 231 devmajor_t bmajor; 232 int i; 233 234 KASSERT(mutex_owned(&device_lock)); 235 236 if (devsw == NULL) 237 return (0); 238 239 if (*devmajor < 0) { 240 for (bmajor = sys_bdevsws ; bmajor < max_bdevsws ; bmajor++) { 241 if (bdevsw[bmajor] != NULL) 242 continue; 243 for (i = 0 ; i < max_devsw_convs ; i++) { 244 if (devsw_conv[i].d_bmajor == bmajor) 245 break; 246 } 247 if (i != max_devsw_convs) 248 continue; 249 break; 250 } 251 *devmajor = bmajor; 252 } 253 254 if (*devmajor >= MAXDEVSW) { 255 printf("bdevsw_attach: block majors exhausted"); 256 return (ENOMEM); 257 } 258 259 if (*devmajor >= max_bdevsws) { 260 KASSERT(bdevsw == bdevsw0); 261 newptr = kmem_zalloc(MAXDEVSW * BDEVSW_SIZE, KM_NOSLEEP); 262 if (newptr == NULL) 263 return (ENOMEM); 264 memcpy(newptr, bdevsw, max_bdevsws * BDEVSW_SIZE); 265 bdevsw = newptr; 266 max_bdevsws = MAXDEVSW; 267 } 268 269 if (bdevsw[*devmajor] != NULL) 270 return (EEXIST); 271 272 bdevsw[*devmajor] = devsw; 273 274 return (0); 275 } 276 277 static int 278 cdevsw_attach(const struct cdevsw *devsw, devmajor_t *devmajor) 279 { 280 const struct cdevsw **newptr; 281 devmajor_t cmajor; 282 int i; 283 284 KASSERT(mutex_owned(&device_lock)); 285 286 if (*devmajor < 0) { 287 for (cmajor = sys_cdevsws ; cmajor < max_cdevsws ; cmajor++) { 288 if (cdevsw[cmajor] != NULL) 289 continue; 290 for (i = 0 ; i < max_devsw_convs ; i++) { 291 if (devsw_conv[i].d_cmajor == cmajor) 292 break; 293 } 294 if (i != max_devsw_convs) 295 continue; 296 break; 297 } 298 *devmajor = cmajor; 299 } 300 301 if (*devmajor >= MAXDEVSW) { 302 printf("cdevsw_attach: character majors exhausted"); 303 return (ENOMEM); 304 } 305 306 if (*devmajor >= max_cdevsws) { 307 KASSERT(cdevsw == cdevsw0); 308 newptr = kmem_zalloc(MAXDEVSW * CDEVSW_SIZE, KM_NOSLEEP); 309 if (newptr == NULL) 310 return (ENOMEM); 311 memcpy(newptr, cdevsw, max_cdevsws * CDEVSW_SIZE); 312 cdevsw = newptr; 313 max_cdevsws = MAXDEVSW; 314 } 315 316 if (cdevsw[*devmajor] != NULL) 317 return (EEXIST); 318 319 cdevsw[*devmajor] = devsw; 320 321 return (0); 322 } 323 324 static void 325 devsw_detach_locked(const struct bdevsw *bdev, const struct cdevsw *cdev) 326 { 327 int i; 328 329 KASSERT(mutex_owned(&device_lock)); 330 331 if (bdev != NULL) { 332 for (i = 0 ; i < max_bdevsws ; i++) { 333 if (bdevsw[i] != bdev) 334 continue; 335 bdevsw[i] = NULL; 336 break; 337 } 338 } 339 if (cdev != NULL) { 340 for (i = 0 ; i < max_cdevsws ; i++) { 341 if (cdevsw[i] != cdev) 342 continue; 343 cdevsw[i] = NULL; 344 break; 345 } 346 } 347 } 348 349 int 350 devsw_detach(const struct bdevsw *bdev, const struct cdevsw *cdev) 351 { 352 353 mutex_enter(&device_lock); 354 devsw_detach_locked(bdev, cdev); 355 mutex_exit(&device_lock); 356 return 0; 357 } 358 359 /* 360 * Look up a block device by number. 361 * 362 * => Caller must ensure that the device is attached. 363 */ 364 const struct bdevsw * 365 bdevsw_lookup(dev_t dev) 366 { 367 devmajor_t bmajor; 368 369 if (dev == NODEV) 370 return (NULL); 371 bmajor = major(dev); 372 if (bmajor < 0 || bmajor >= max_bdevsws) 373 return (NULL); 374 375 return (bdevsw[bmajor]); 376 } 377 378 /* 379 * Look up a character device by number. 380 * 381 * => Caller must ensure that the device is attached. 382 */ 383 const struct cdevsw * 384 cdevsw_lookup(dev_t dev) 385 { 386 devmajor_t cmajor; 387 388 if (dev == NODEV) 389 return (NULL); 390 cmajor = major(dev); 391 if (cmajor < 0 || cmajor >= max_cdevsws) 392 return (NULL); 393 394 return (cdevsw[cmajor]); 395 } 396 397 /* 398 * Look up a block device by reference to its operations set. 399 * 400 * => Caller must ensure that the device is not detached, and therefore 401 * that the returned major is still valid when dereferenced. 402 */ 403 devmajor_t 404 bdevsw_lookup_major(const struct bdevsw *bdev) 405 { 406 devmajor_t bmajor; 407 408 for (bmajor = 0 ; bmajor < max_bdevsws ; bmajor++) { 409 if (bdevsw[bmajor] == bdev) 410 return (bmajor); 411 } 412 413 return (NODEVMAJOR); 414 } 415 416 /* 417 * Look up a character device by reference to its operations set. 418 * 419 * => Caller must ensure that the device is not detached, and therefore 420 * that the returned major is still valid when dereferenced. 421 */ 422 devmajor_t 423 cdevsw_lookup_major(const struct cdevsw *cdev) 424 { 425 devmajor_t cmajor; 426 427 for (cmajor = 0 ; cmajor < max_cdevsws ; cmajor++) { 428 if (cdevsw[cmajor] == cdev) 429 return (cmajor); 430 } 431 432 return (NODEVMAJOR); 433 } 434 435 /* 436 * Convert from block major number to name. 437 * 438 * => Caller must ensure that the device is not detached, and therefore 439 * that the name pointer is still valid when dereferenced. 440 */ 441 const char * 442 devsw_blk2name(devmajor_t bmajor) 443 { 444 const char *name; 445 devmajor_t cmajor; 446 int i; 447 448 name = NULL; 449 cmajor = -1; 450 451 mutex_enter(&device_lock); 452 if (bmajor < 0 || bmajor >= max_bdevsws || bdevsw[bmajor] == NULL) { 453 mutex_exit(&device_lock); 454 return (NULL); 455 } 456 for (i = 0 ; i < max_devsw_convs; i++) { 457 if (devsw_conv[i].d_bmajor == bmajor) { 458 cmajor = devsw_conv[i].d_cmajor; 459 break; 460 } 461 } 462 if (cmajor >= 0 && cmajor < max_cdevsws && cdevsw[cmajor] != NULL) 463 name = devsw_conv[i].d_name; 464 mutex_exit(&device_lock); 465 466 return (name); 467 } 468 469 /* 470 * Convert char major number to device driver name. 471 */ 472 const char * 473 cdevsw_getname(devmajor_t major) 474 { 475 const char *name; 476 int i; 477 478 name = NULL; 479 480 if (major < 0) 481 return (NULL); 482 483 mutex_enter(&device_lock); 484 for (i = 0 ; i < max_devsw_convs; i++) { 485 if (devsw_conv[i].d_cmajor == major) { 486 name = devsw_conv[i].d_name; 487 break; 488 } 489 } 490 mutex_exit(&device_lock); 491 return (name); 492 } 493 494 /* 495 * Convert block major number to device driver name. 496 */ 497 const char * 498 bdevsw_getname(devmajor_t major) 499 { 500 const char *name; 501 int i; 502 503 name = NULL; 504 505 if (major < 0) 506 return (NULL); 507 508 mutex_enter(&device_lock); 509 for (i = 0 ; i < max_devsw_convs; i++) { 510 if (devsw_conv[i].d_bmajor == major) { 511 name = devsw_conv[i].d_name; 512 break; 513 } 514 } 515 mutex_exit(&device_lock); 516 return (name); 517 } 518 519 /* 520 * Convert from device name to block major number. 521 * 522 * => Caller must ensure that the device is not detached, and therefore 523 * that the major number is still valid when dereferenced. 524 */ 525 devmajor_t 526 devsw_name2blk(const char *name, char *devname, size_t devnamelen) 527 { 528 struct devsw_conv *conv; 529 devmajor_t bmajor; 530 int i; 531 532 if (name == NULL) 533 return (NODEVMAJOR); 534 535 mutex_enter(&device_lock); 536 for (i = 0 ; i < max_devsw_convs ; i++) { 537 size_t len; 538 539 conv = &devsw_conv[i]; 540 if (conv->d_name == NULL) 541 continue; 542 len = strlen(conv->d_name); 543 if (strncmp(conv->d_name, name, len) != 0) 544 continue; 545 if (*(name +len) && !isdigit(*(name + len))) 546 continue; 547 bmajor = conv->d_bmajor; 548 if (bmajor < 0 || bmajor >= max_bdevsws || 549 bdevsw[bmajor] == NULL) 550 break; 551 if (devname != NULL) { 552 #ifdef DEVSW_DEBUG 553 if (strlen(conv->d_name) >= devnamelen) 554 printf("devsw_name2blk: too short buffer"); 555 #endif /* DEVSW_DEBUG */ 556 strncpy(devname, conv->d_name, devnamelen); 557 devname[devnamelen - 1] = '\0'; 558 } 559 mutex_exit(&device_lock); 560 return (bmajor); 561 } 562 563 mutex_exit(&device_lock); 564 return (NODEVMAJOR); 565 } 566 567 /* 568 * Convert from device name to char major number. 569 * 570 * => Caller must ensure that the device is not detached, and therefore 571 * that the major number is still valid when dereferenced. 572 */ 573 devmajor_t 574 devsw_name2chr(const char *name, char *devname, size_t devnamelen) 575 { 576 struct devsw_conv *conv; 577 devmajor_t cmajor; 578 int i; 579 580 if (name == NULL) 581 return (NODEVMAJOR); 582 583 mutex_enter(&device_lock); 584 for (i = 0 ; i < max_devsw_convs ; i++) { 585 size_t len; 586 587 conv = &devsw_conv[i]; 588 if (conv->d_name == NULL) 589 continue; 590 len = strlen(conv->d_name); 591 if (strncmp(conv->d_name, name, len) != 0) 592 continue; 593 if (*(name +len) && !isdigit(*(name + len))) 594 continue; 595 cmajor = conv->d_cmajor; 596 if (cmajor < 0 || cmajor >= max_cdevsws || 597 cdevsw[cmajor] == NULL) 598 break; 599 if (devname != NULL) { 600 #ifdef DEVSW_DEBUG 601 if (strlen(conv->d_name) >= devnamelen) 602 printf("devsw_name2chr: too short buffer"); 603 #endif /* DEVSW_DEBUG */ 604 strncpy(devname, conv->d_name, devnamelen); 605 devname[devnamelen - 1] = '\0'; 606 } 607 mutex_exit(&device_lock); 608 return (cmajor); 609 } 610 611 mutex_exit(&device_lock); 612 return (NODEVMAJOR); 613 } 614 615 /* 616 * Convert from character dev_t to block dev_t. 617 * 618 * => Caller must ensure that the device is not detached, and therefore 619 * that the major number is still valid when dereferenced. 620 */ 621 dev_t 622 devsw_chr2blk(dev_t cdev) 623 { 624 devmajor_t bmajor, cmajor; 625 int i; 626 dev_t rv; 627 628 cmajor = major(cdev); 629 bmajor = NODEVMAJOR; 630 rv = NODEV; 631 632 mutex_enter(&device_lock); 633 if (cmajor < 0 || cmajor >= max_cdevsws || cdevsw[cmajor] == NULL) { 634 mutex_exit(&device_lock); 635 return (NODEV); 636 } 637 for (i = 0 ; i < max_devsw_convs ; i++) { 638 if (devsw_conv[i].d_cmajor == cmajor) { 639 bmajor = devsw_conv[i].d_bmajor; 640 break; 641 } 642 } 643 if (bmajor >= 0 && bmajor < max_bdevsws && bdevsw[bmajor] != NULL) 644 rv = makedev(bmajor, minor(cdev)); 645 mutex_exit(&device_lock); 646 647 return (rv); 648 } 649 650 /* 651 * Convert from block dev_t to character dev_t. 652 * 653 * => Caller must ensure that the device is not detached, and therefore 654 * that the major number is still valid when dereferenced. 655 */ 656 dev_t 657 devsw_blk2chr(dev_t bdev) 658 { 659 devmajor_t bmajor, cmajor; 660 int i; 661 dev_t rv; 662 663 bmajor = major(bdev); 664 cmajor = NODEVMAJOR; 665 rv = NODEV; 666 667 mutex_enter(&device_lock); 668 if (bmajor < 0 || bmajor >= max_bdevsws || bdevsw[bmajor] == NULL) { 669 mutex_exit(&device_lock); 670 return (NODEV); 671 } 672 for (i = 0 ; i < max_devsw_convs ; i++) { 673 if (devsw_conv[i].d_bmajor == bmajor) { 674 cmajor = devsw_conv[i].d_cmajor; 675 break; 676 } 677 } 678 if (cmajor >= 0 && cmajor < max_cdevsws && cdevsw[cmajor] != NULL) 679 rv = makedev(cmajor, minor(bdev)); 680 mutex_exit(&device_lock); 681 682 return (rv); 683 } 684 685 /* 686 * Device access methods. 687 */ 688 689 #define DEV_LOCK(d) \ 690 if ((mpflag = (d->d_flag & D_MPSAFE)) == 0) { \ 691 KERNEL_LOCK(1, NULL); \ 692 } 693 694 #define DEV_UNLOCK(d) \ 695 if (mpflag == 0) { \ 696 KERNEL_UNLOCK_ONE(NULL); \ 697 } 698 699 int 700 bdev_open(dev_t dev, int flag, int devtype, lwp_t *l) 701 { 702 const struct bdevsw *d; 703 int rv, mpflag; 704 705 /* 706 * For open we need to lock, in order to synchronize 707 * with attach/detach. 708 */ 709 mutex_enter(&device_lock); 710 d = bdevsw_lookup(dev); 711 mutex_exit(&device_lock); 712 if (d == NULL) 713 return ENXIO; 714 715 DEV_LOCK(d); 716 rv = (*d->d_open)(dev, flag, devtype, l); 717 DEV_UNLOCK(d); 718 719 return rv; 720 } 721 722 int 723 bdev_close(dev_t dev, int flag, int devtype, lwp_t *l) 724 { 725 const struct bdevsw *d; 726 int rv, mpflag; 727 728 if ((d = bdevsw_lookup(dev)) == NULL) 729 return ENXIO; 730 731 DEV_LOCK(d); 732 rv = (*d->d_close)(dev, flag, devtype, l); 733 DEV_UNLOCK(d); 734 735 return rv; 736 } 737 738 SDT_PROVIDER_DECLARE(io); 739 SDT_PROBE_DEFINE1(io, kernel, , start, "struct buf *"/*bp*/); 740 741 void 742 bdev_strategy(struct buf *bp) 743 { 744 const struct bdevsw *d; 745 int mpflag; 746 747 SDT_PROBE1(io, kernel, , start, bp); 748 749 if ((d = bdevsw_lookup(bp->b_dev)) == NULL) { 750 bp->b_error = ENXIO; 751 bp->b_resid = bp->b_bcount; 752 biodone_vfs(bp); /* biodone() iff vfs present */ 753 return; 754 } 755 756 DEV_LOCK(d); 757 (*d->d_strategy)(bp); 758 DEV_UNLOCK(d); 759 } 760 761 int 762 bdev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l) 763 { 764 const struct bdevsw *d; 765 int rv, mpflag; 766 767 if ((d = bdevsw_lookup(dev)) == NULL) 768 return ENXIO; 769 770 DEV_LOCK(d); 771 rv = (*d->d_ioctl)(dev, cmd, data, flag, l); 772 DEV_UNLOCK(d); 773 774 return rv; 775 } 776 777 int 778 bdev_dump(dev_t dev, daddr_t addr, void *data, size_t sz) 779 { 780 const struct bdevsw *d; 781 int rv; 782 783 /* 784 * Dump can be called without the device open. Since it can 785 * currently only be called with the system paused (and in a 786 * potentially unstable state), we don't perform any locking. 787 */ 788 if ((d = bdevsw_lookup(dev)) == NULL) 789 return ENXIO; 790 791 /* DEV_LOCK(d); */ 792 rv = (*d->d_dump)(dev, addr, data, sz); 793 /* DEV_UNLOCK(d); */ 794 795 return rv; 796 } 797 798 int 799 bdev_flags(dev_t dev) 800 { 801 const struct bdevsw *d; 802 803 if ((d = bdevsw_lookup(dev)) == NULL) 804 return 0; 805 return d->d_flag & ~D_TYPEMASK; 806 } 807 808 int 809 bdev_type(dev_t dev) 810 { 811 const struct bdevsw *d; 812 813 if ((d = bdevsw_lookup(dev)) == NULL) 814 return D_OTHER; 815 return d->d_flag & D_TYPEMASK; 816 } 817 818 int 819 bdev_size(dev_t dev) 820 { 821 const struct bdevsw *d; 822 int rv, mpflag = 0; 823 824 if ((d = bdevsw_lookup(dev)) == NULL || 825 d->d_psize == NULL) 826 return -1; 827 828 /* 829 * Don't to try lock the device if we're dumping. 830 * XXX: is there a better way to test this? 831 */ 832 if ((boothowto & RB_DUMP) == 0) 833 DEV_LOCK(d); 834 rv = (*d->d_psize)(dev); 835 if ((boothowto & RB_DUMP) == 0) 836 DEV_UNLOCK(d); 837 838 return rv; 839 } 840 841 int 842 bdev_discard(dev_t dev, off_t pos, off_t len) 843 { 844 const struct bdevsw *d; 845 int rv, mpflag; 846 847 if ((d = bdevsw_lookup(dev)) == NULL) 848 return ENXIO; 849 850 DEV_LOCK(d); 851 rv = (*d->d_discard)(dev, pos, len); 852 DEV_UNLOCK(d); 853 854 return rv; 855 } 856 857 int 858 cdev_open(dev_t dev, int flag, int devtype, lwp_t *l) 859 { 860 const struct cdevsw *d; 861 int rv, mpflag; 862 863 /* 864 * For open we need to lock, in order to synchronize 865 * with attach/detach. 866 */ 867 mutex_enter(&device_lock); 868 d = cdevsw_lookup(dev); 869 mutex_exit(&device_lock); 870 if (d == NULL) 871 return ENXIO; 872 873 DEV_LOCK(d); 874 rv = (*d->d_open)(dev, flag, devtype, l); 875 DEV_UNLOCK(d); 876 877 return rv; 878 } 879 880 int 881 cdev_close(dev_t dev, int flag, int devtype, lwp_t *l) 882 { 883 const struct cdevsw *d; 884 int rv, mpflag; 885 886 if ((d = cdevsw_lookup(dev)) == NULL) 887 return ENXIO; 888 889 DEV_LOCK(d); 890 rv = (*d->d_close)(dev, flag, devtype, l); 891 DEV_UNLOCK(d); 892 893 return rv; 894 } 895 896 int 897 cdev_read(dev_t dev, struct uio *uio, int flag) 898 { 899 const struct cdevsw *d; 900 int rv, mpflag; 901 902 if ((d = cdevsw_lookup(dev)) == NULL) 903 return ENXIO; 904 905 DEV_LOCK(d); 906 rv = (*d->d_read)(dev, uio, flag); 907 DEV_UNLOCK(d); 908 909 return rv; 910 } 911 912 int 913 cdev_write(dev_t dev, struct uio *uio, int flag) 914 { 915 const struct cdevsw *d; 916 int rv, mpflag; 917 918 if ((d = cdevsw_lookup(dev)) == NULL) 919 return ENXIO; 920 921 DEV_LOCK(d); 922 rv = (*d->d_write)(dev, uio, flag); 923 DEV_UNLOCK(d); 924 925 return rv; 926 } 927 928 int 929 cdev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l) 930 { 931 const struct cdevsw *d; 932 int rv, mpflag; 933 934 if ((d = cdevsw_lookup(dev)) == NULL) 935 return ENXIO; 936 937 DEV_LOCK(d); 938 rv = (*d->d_ioctl)(dev, cmd, data, flag, l); 939 DEV_UNLOCK(d); 940 941 return rv; 942 } 943 944 void 945 cdev_stop(struct tty *tp, int flag) 946 { 947 const struct cdevsw *d; 948 int mpflag; 949 950 if ((d = cdevsw_lookup(tp->t_dev)) == NULL) 951 return; 952 953 DEV_LOCK(d); 954 (*d->d_stop)(tp, flag); 955 DEV_UNLOCK(d); 956 } 957 958 struct tty * 959 cdev_tty(dev_t dev) 960 { 961 const struct cdevsw *d; 962 963 if ((d = cdevsw_lookup(dev)) == NULL) 964 return NULL; 965 966 /* XXX Check if necessary. */ 967 if (d->d_tty == NULL) 968 return NULL; 969 970 return (*d->d_tty)(dev); 971 } 972 973 int 974 cdev_poll(dev_t dev, int flag, lwp_t *l) 975 { 976 const struct cdevsw *d; 977 int rv, mpflag; 978 979 if ((d = cdevsw_lookup(dev)) == NULL) 980 return POLLERR; 981 982 DEV_LOCK(d); 983 rv = (*d->d_poll)(dev, flag, l); 984 DEV_UNLOCK(d); 985 986 return rv; 987 } 988 989 paddr_t 990 cdev_mmap(dev_t dev, off_t off, int flag) 991 { 992 const struct cdevsw *d; 993 paddr_t rv; 994 int mpflag; 995 996 if ((d = cdevsw_lookup(dev)) == NULL) 997 return (paddr_t)-1LL; 998 999 DEV_LOCK(d); 1000 rv = (*d->d_mmap)(dev, off, flag); 1001 DEV_UNLOCK(d); 1002 1003 return rv; 1004 } 1005 1006 int 1007 cdev_kqfilter(dev_t dev, struct knote *kn) 1008 { 1009 const struct cdevsw *d; 1010 int rv, mpflag; 1011 1012 if ((d = cdevsw_lookup(dev)) == NULL) 1013 return ENXIO; 1014 1015 DEV_LOCK(d); 1016 rv = (*d->d_kqfilter)(dev, kn); 1017 DEV_UNLOCK(d); 1018 1019 return rv; 1020 } 1021 1022 int 1023 cdev_discard(dev_t dev, off_t pos, off_t len) 1024 { 1025 const struct cdevsw *d; 1026 int rv, mpflag; 1027 1028 if ((d = cdevsw_lookup(dev)) == NULL) 1029 return ENXIO; 1030 1031 DEV_LOCK(d); 1032 rv = (*d->d_discard)(dev, pos, len); 1033 DEV_UNLOCK(d); 1034 1035 return rv; 1036 } 1037 1038 int 1039 cdev_flags(dev_t dev) 1040 { 1041 const struct cdevsw *d; 1042 1043 if ((d = cdevsw_lookup(dev)) == NULL) 1044 return 0; 1045 return d->d_flag & ~D_TYPEMASK; 1046 } 1047 1048 int 1049 cdev_type(dev_t dev) 1050 { 1051 const struct cdevsw *d; 1052 1053 if ((d = cdevsw_lookup(dev)) == NULL) 1054 return D_OTHER; 1055 return d->d_flag & D_TYPEMASK; 1056 } 1057 1058 /* 1059 * nommap(dev, off, prot) 1060 * 1061 * mmap routine that always fails, for non-mmappable devices. 1062 */ 1063 paddr_t 1064 nommap(dev_t dev, off_t off, int prot) 1065 { 1066 1067 return (paddr_t)-1; 1068 } 1069