1 /* 2 * Copyright (c) 1997,1998 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: src/sys/kern/subr_bus.c,v 1.54.2.9 2002/10/10 15:13:32 jhb Exp $ 27 * $DragonFly: src/sys/kern/subr_bus.c,v 1.14 2004/03/13 14:38:22 joerg Exp $ 28 */ 29 30 #include "opt_bus.h" 31 32 #include <sys/param.h> 33 #include <sys/queue.h> 34 #include <sys/malloc.h> 35 #include <sys/kernel.h> 36 #include <sys/module.h> 37 #ifdef DEVICE_SYSCTLS 38 #include <sys/sysctl.h> 39 #endif 40 #include <sys/kobj.h> 41 #include <sys/bus_private.h> 42 #include <sys/systm.h> 43 #include <machine/bus.h> 44 #include <sys/rman.h> 45 #include <machine/stdarg.h> /* for device_printf() */ 46 47 MALLOC_DEFINE(M_BUS, "bus", "Bus data structures"); 48 49 #ifdef BUS_DEBUG 50 #define PDEBUG(a) (printf(__FUNCTION__ ":%d: ", __LINE__), printf a, printf("\n")) 51 #define DEVICENAME(d) ((d)? device_get_name(d): "no device") 52 #define DRIVERNAME(d) ((d)? d->name : "no driver") 53 #define DEVCLANAME(d) ((d)? d->name : "no devclass") 54 55 /* Produce the indenting, indent*2 spaces plus a '.' ahead of that to 56 * prevent syslog from deleting initial spaces 57 */ 58 #define indentprintf(p) do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf(" "); printf p ; } while(0) 59 60 static void print_device_short(device_t dev, int indent); 61 static void print_device(device_t dev, int indent); 62 void print_device_tree_short(device_t dev, int indent); 63 void print_device_tree(device_t dev, int indent); 64 static void print_driver_short(driver_t *driver, int indent); 65 static void print_driver(driver_t *driver, int indent); 66 static void print_driver_list(driver_list_t drivers, int indent); 67 static void print_devclass_short(devclass_t dc, int indent); 68 static void print_devclass(devclass_t dc, int indent); 69 void print_devclass_list_short(void); 70 void print_devclass_list(void); 71 72 #else 73 /* Make the compiler ignore the function calls */ 74 #define PDEBUG(a) /* nop */ 75 #define DEVICENAME(d) /* nop */ 76 #define DRIVERNAME(d) /* nop */ 77 #define DEVCLANAME(d) /* nop */ 78 79 #define print_device_short(d,i) /* nop */ 80 #define print_device(d,i) /* nop */ 81 #define print_device_tree_short(d,i) /* nop */ 82 #define print_device_tree(d,i) /* nop */ 83 #define print_driver_short(d,i) /* nop */ 84 #define print_driver(d,i) /* nop */ 85 #define print_driver_list(d,i) /* nop */ 86 #define print_devclass_short(d,i) /* nop */ 87 #define print_devclass(d,i) /* nop */ 88 #define print_devclass_list_short() /* nop */ 89 #define print_devclass_list() /* nop */ 90 #endif 91 92 #ifdef DEVICE_SYSCTLS 93 static void device_register_oids(device_t dev); 94 static void device_unregister_oids(device_t dev); 95 #endif 96 97 kobj_method_t null_methods[] = { 98 { 0, 0 } 99 }; 100 101 DEFINE_CLASS(null, null_methods, 0); 102 103 /* 104 * Devclass implementation 105 */ 106 107 static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses); 108 109 static devclass_t 110 devclass_find_internal(const char *classname, int create) 111 { 112 devclass_t dc; 113 114 PDEBUG(("looking for %s", classname)); 115 if (classname == NULL) 116 return(NULL); 117 118 TAILQ_FOREACH(dc, &devclasses, link) 119 if (!strcmp(dc->name, classname)) 120 return(dc); 121 122 PDEBUG(("%s not found%s", classname, (create? ", creating": ""))); 123 if (create) { 124 dc = malloc(sizeof(struct devclass) + strlen(classname) + 1, 125 M_BUS, M_NOWAIT | M_ZERO); 126 if (!dc) 127 return NULL; 128 dc->name = (char*) (dc + 1); 129 strcpy(dc->name, classname); 130 dc->devices = NULL; 131 dc->maxunit = 0; 132 TAILQ_INIT(&dc->drivers); 133 TAILQ_INSERT_TAIL(&devclasses, dc, link); 134 } 135 136 return(dc); 137 } 138 139 devclass_t 140 devclass_create(const char *classname) 141 { 142 return(devclass_find_internal(classname, TRUE)); 143 } 144 145 devclass_t 146 devclass_find(const char *classname) 147 { 148 return(devclass_find_internal(classname, FALSE)); 149 } 150 151 int 152 devclass_add_driver(devclass_t dc, driver_t *driver) 153 { 154 driverlink_t dl; 155 int i; 156 157 PDEBUG(("%s", DRIVERNAME(driver))); 158 159 dl = malloc(sizeof *dl, M_BUS, M_NOWAIT | M_ZERO); 160 if (!dl) 161 return(ENOMEM); 162 163 /* 164 * Compile the driver's methods. Also increase the reference count 165 * so that the class doesn't get freed when the last instance 166 * goes. This means we can safely use static methods and avoids a 167 * double-free in devclass_delete_driver. 168 */ 169 kobj_class_compile((kobj_class_t) driver); 170 171 /* 172 * Make sure the devclass which the driver is implementing exists. 173 */ 174 devclass_find_internal(driver->name, TRUE); 175 176 dl->driver = driver; 177 TAILQ_INSERT_TAIL(&dc->drivers, dl, link); 178 driver->refs++; 179 180 /* 181 * Call BUS_DRIVER_ADDED for any existing busses in this class. 182 */ 183 for (i = 0; i < dc->maxunit; i++) 184 if (dc->devices[i]) 185 BUS_DRIVER_ADDED(dc->devices[i], driver); 186 187 return(0); 188 } 189 190 int 191 devclass_delete_driver(devclass_t busclass, driver_t *driver) 192 { 193 devclass_t dc = devclass_find(driver->name); 194 driverlink_t dl; 195 device_t dev; 196 int i; 197 int error; 198 199 PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass))); 200 201 if (!dc) 202 return(0); 203 204 /* 205 * Find the link structure in the bus' list of drivers. 206 */ 207 TAILQ_FOREACH(dl, &busclass->drivers, link) 208 if (dl->driver == driver) 209 break; 210 211 if (!dl) { 212 PDEBUG(("%s not found in %s list", driver->name, busclass->name)); 213 return(ENOENT); 214 } 215 216 /* 217 * Disassociate from any devices. We iterate through all the 218 * devices in the devclass of the driver and detach any which are 219 * using the driver and which have a parent in the devclass which 220 * we are deleting from. 221 * 222 * Note that since a driver can be in multiple devclasses, we 223 * should not detach devices which are not children of devices in 224 * the affected devclass. 225 */ 226 for (i = 0; i < dc->maxunit; i++) 227 if (dc->devices[i]) { 228 dev = dc->devices[i]; 229 if (dev->driver == driver && dev->parent && 230 dev->parent->devclass == busclass) { 231 if ((error = device_detach(dev)) != 0) 232 return(error); 233 device_set_driver(dev, NULL); 234 } 235 } 236 237 TAILQ_REMOVE(&busclass->drivers, dl, link); 238 free(dl, M_BUS); 239 240 driver->refs--; 241 if (driver->refs == 0) 242 kobj_class_free((kobj_class_t) driver); 243 244 return(0); 245 } 246 247 static driverlink_t 248 devclass_find_driver_internal(devclass_t dc, const char *classname) 249 { 250 driverlink_t dl; 251 252 PDEBUG(("%s in devclass %s", classname, DEVCLANAME(dc))); 253 254 TAILQ_FOREACH(dl, &dc->drivers, link) 255 if (!strcmp(dl->driver->name, classname)) 256 return(dl); 257 258 PDEBUG(("not found")); 259 return(NULL); 260 } 261 262 driver_t * 263 devclass_find_driver(devclass_t dc, const char *classname) 264 { 265 driverlink_t dl; 266 267 dl = devclass_find_driver_internal(dc, classname); 268 if (dl) 269 return(dl->driver); 270 else 271 return(NULL); 272 } 273 274 const char * 275 devclass_get_name(devclass_t dc) 276 { 277 return(dc->name); 278 } 279 280 device_t 281 devclass_get_device(devclass_t dc, int unit) 282 { 283 if (dc == NULL || unit < 0 || unit >= dc->maxunit) 284 return(NULL); 285 return(dc->devices[unit]); 286 } 287 288 void * 289 devclass_get_softc(devclass_t dc, int unit) 290 { 291 device_t dev; 292 293 dev = devclass_get_device(dc, unit); 294 if (!dev) 295 return(NULL); 296 297 return(device_get_softc(dev)); 298 } 299 300 int 301 devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp) 302 { 303 int i; 304 int count; 305 device_t *list; 306 307 count = 0; 308 for (i = 0; i < dc->maxunit; i++) 309 if (dc->devices[i]) 310 count++; 311 312 list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT | M_ZERO); 313 if (list == NULL) 314 return(ENOMEM); 315 316 count = 0; 317 for (i = 0; i < dc->maxunit; i++) 318 if (dc->devices[i]) { 319 list[count] = dc->devices[i]; 320 count++; 321 } 322 323 *devlistp = list; 324 *devcountp = count; 325 326 return(0); 327 } 328 329 int 330 devclass_get_maxunit(devclass_t dc) 331 { 332 return(dc->maxunit); 333 } 334 335 static int 336 devclass_alloc_unit(devclass_t dc, int *unitp) 337 { 338 int unit = *unitp; 339 340 PDEBUG(("unit %d in devclass %s", unit, DEVCLANAME(dc))); 341 342 /* If we have been given a wired unit number, check for existing device */ 343 if (unit != -1) { 344 if (unit >= 0 && unit < dc->maxunit && 345 dc->devices[unit] != NULL) { 346 if (bootverbose) 347 printf("%s-: %s%d exists, using next available unit number\n", 348 dc->name, dc->name, unit); 349 /* find the next available slot */ 350 while (++unit < dc->maxunit && dc->devices[unit] != NULL) 351 ; 352 } 353 } else { 354 /* Unwired device, find the next available slot for it */ 355 unit = 0; 356 while (unit < dc->maxunit && dc->devices[unit] != NULL) 357 unit++; 358 } 359 360 /* 361 * We've selected a unit beyond the length of the table, so let's 362 * extend the table to make room for all units up to and including 363 * this one. 364 */ 365 if (unit >= dc->maxunit) { 366 device_t *newlist; 367 int newsize; 368 369 newsize = roundup((unit + 1), MINALLOCSIZE / sizeof(device_t)); 370 newlist = malloc(sizeof(device_t) * newsize, M_BUS, M_NOWAIT | M_ZERO); 371 if (newlist == NULL) 372 return(ENOMEM); 373 bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit); 374 if (dc->devices) 375 free(dc->devices, M_BUS); 376 dc->devices = newlist; 377 dc->maxunit = newsize; 378 } 379 PDEBUG(("now: unit %d in devclass %s", unit, DEVCLANAME(dc))); 380 381 *unitp = unit; 382 return(0); 383 } 384 385 static int 386 devclass_add_device(devclass_t dc, device_t dev) 387 { 388 int buflen, error; 389 390 PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc))); 391 392 buflen = strlen(dc->name) + 5; 393 dev->nameunit = malloc(buflen, M_BUS, M_NOWAIT | M_ZERO); 394 if (!dev->nameunit) 395 return(ENOMEM); 396 397 if ((error = devclass_alloc_unit(dc, &dev->unit)) != 0) { 398 free(dev->nameunit, M_BUS); 399 dev->nameunit = NULL; 400 return(error); 401 } 402 dc->devices[dev->unit] = dev; 403 dev->devclass = dc; 404 snprintf(dev->nameunit, buflen, "%s%d", dc->name, dev->unit); 405 406 #ifdef DEVICE_SYSCTLS 407 device_register_oids(dev); 408 #endif 409 410 return(0); 411 } 412 413 static int 414 devclass_delete_device(devclass_t dc, device_t dev) 415 { 416 if (!dc || !dev) 417 return(0); 418 419 PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc))); 420 421 if (dev->devclass != dc || dc->devices[dev->unit] != dev) 422 panic("devclass_delete_device: inconsistent device class"); 423 dc->devices[dev->unit] = NULL; 424 if (dev->flags & DF_WILDCARD) 425 dev->unit = -1; 426 dev->devclass = NULL; 427 free(dev->nameunit, M_BUS); 428 dev->nameunit = NULL; 429 430 #ifdef DEVICE_SYSCTLS 431 device_unregister_oids(dev); 432 #endif 433 434 return(0); 435 } 436 437 static device_t 438 make_device(device_t parent, const char *name, int unit) 439 { 440 device_t dev; 441 devclass_t dc; 442 443 PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit)); 444 445 if (name != NULL) { 446 dc = devclass_find_internal(name, TRUE); 447 if (!dc) { 448 printf("make_device: can't find device class %s\n", name); 449 return(NULL); 450 } 451 } else 452 dc = NULL; 453 454 dev = malloc(sizeof(struct device), M_BUS, M_NOWAIT | M_ZERO); 455 if (!dev) 456 return(0); 457 458 dev->parent = parent; 459 TAILQ_INIT(&dev->children); 460 kobj_init((kobj_t) dev, &null_class); 461 dev->driver = NULL; 462 dev->devclass = NULL; 463 dev->unit = unit; 464 dev->nameunit = NULL; 465 dev->desc = NULL; 466 dev->busy = 0; 467 dev->devflags = 0; 468 dev->flags = DF_ENABLED; 469 dev->order = 0; 470 if (unit == -1) 471 dev->flags |= DF_WILDCARD; 472 if (name) { 473 dev->flags |= DF_FIXEDCLASS; 474 if (devclass_add_device(dc, dev) != 0) { 475 kobj_delete((kobj_t)dev, M_BUS); 476 return(NULL); 477 } 478 } 479 dev->ivars = NULL; 480 dev->softc = NULL; 481 482 dev->state = DS_NOTPRESENT; 483 484 return(dev); 485 } 486 487 static int 488 device_print_child(device_t dev, device_t child) 489 { 490 int retval = 0; 491 492 if (device_is_alive(child)) 493 retval += BUS_PRINT_CHILD(dev, child); 494 else 495 retval += device_printf(child, " not found\n"); 496 497 return(retval); 498 } 499 500 device_t 501 device_add_child(device_t dev, const char *name, int unit) 502 { 503 return device_add_child_ordered(dev, 0, name, unit); 504 } 505 506 device_t 507 device_add_child_ordered(device_t dev, int order, const char *name, int unit) 508 { 509 device_t child; 510 device_t place; 511 512 PDEBUG(("%s at %s with order %d as unit %d", name, DEVICENAME(dev), 513 order, unit)); 514 515 child = make_device(dev, name, unit); 516 if (child == NULL) 517 return child; 518 child->order = order; 519 520 TAILQ_FOREACH(place, &dev->children, link) 521 if (place->order > order) 522 break; 523 524 if (place) { 525 /* 526 * The device 'place' is the first device whose order is 527 * greater than the new child. 528 */ 529 TAILQ_INSERT_BEFORE(place, child, link); 530 } else { 531 /* 532 * The new child's order is greater or equal to the order of 533 * any existing device. Add the child to the tail of the list. 534 */ 535 TAILQ_INSERT_TAIL(&dev->children, child, link); 536 } 537 538 return(child); 539 } 540 541 int 542 device_delete_child(device_t dev, device_t child) 543 { 544 int error; 545 device_t grandchild; 546 547 PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev))); 548 549 /* remove children first */ 550 while ( (grandchild = TAILQ_FIRST(&child->children)) ) { 551 error = device_delete_child(child, grandchild); 552 if (error) 553 return(error); 554 } 555 556 if ((error = device_detach(child)) != 0) 557 return(error); 558 if (child->devclass) 559 devclass_delete_device(child->devclass, child); 560 TAILQ_REMOVE(&dev->children, child, link); 561 device_set_desc(child, NULL); 562 kobj_delete((kobj_t)child, M_BUS); 563 564 return(0); 565 } 566 567 /* 568 * Find only devices attached to this bus. 569 */ 570 device_t 571 device_find_child(device_t dev, const char *classname, int unit) 572 { 573 devclass_t dc; 574 device_t child; 575 576 dc = devclass_find(classname); 577 if (!dc) 578 return(NULL); 579 580 child = devclass_get_device(dc, unit); 581 if (child && child->parent == dev) 582 return(child); 583 return(NULL); 584 } 585 586 static driverlink_t 587 first_matching_driver(devclass_t dc, device_t dev) 588 { 589 if (dev->devclass) 590 return(devclass_find_driver_internal(dc, dev->devclass->name)); 591 else 592 return(TAILQ_FIRST(&dc->drivers)); 593 } 594 595 static driverlink_t 596 next_matching_driver(devclass_t dc, device_t dev, driverlink_t last) 597 { 598 if (dev->devclass) { 599 driverlink_t dl; 600 for (dl = TAILQ_NEXT(last, link); dl; dl = TAILQ_NEXT(dl, link)) 601 if (!strcmp(dev->devclass->name, dl->driver->name)) 602 return(dl); 603 return(NULL); 604 } else 605 return(TAILQ_NEXT(last, link)); 606 } 607 608 static int 609 device_probe_child(device_t dev, device_t child) 610 { 611 devclass_t dc; 612 driverlink_t best = 0; 613 driverlink_t dl; 614 int result, pri = 0; 615 int hasclass = (child->devclass != 0); 616 617 dc = dev->devclass; 618 if (!dc) 619 panic("device_probe_child: parent device has no devclass"); 620 621 if (child->state == DS_ALIVE) 622 return(0); 623 624 for (dl = first_matching_driver(dc, child); dl; 625 dl = next_matching_driver(dc, child, dl)) { 626 PDEBUG(("Trying %s", DRIVERNAME(dl->driver))); 627 device_set_driver(child, dl->driver); 628 if (!hasclass) 629 device_set_devclass(child, dl->driver->name); 630 result = DEVICE_PROBE(child); 631 if (!hasclass) 632 device_set_devclass(child, 0); 633 634 /* 635 * If the driver returns SUCCESS, there can be no higher match 636 * for this device. 637 */ 638 if (result == 0) { 639 best = dl; 640 pri = 0; 641 break; 642 } 643 644 /* 645 * The driver returned an error so it certainly doesn't match. 646 */ 647 if (result > 0) { 648 device_set_driver(child, 0); 649 continue; 650 } 651 652 /* 653 * A priority lower than SUCCESS, remember the best matching 654 * driver. Initialise the value of pri for the first match. 655 */ 656 if (best == 0 || result > pri) { 657 best = dl; 658 pri = result; 659 continue; 660 } 661 } 662 663 /* 664 * If we found a driver, change state and initialise the devclass. 665 */ 666 if (best) { 667 if (!child->devclass) 668 device_set_devclass(child, best->driver->name); 669 device_set_driver(child, best->driver); 670 if (pri < 0) { 671 /* 672 * A bit bogus. Call the probe method again to make 673 * sure that we have the right description. 674 */ 675 DEVICE_PROBE(child); 676 } 677 child->state = DS_ALIVE; 678 return(0); 679 } 680 681 return(ENXIO); 682 } 683 684 device_t 685 device_get_parent(device_t dev) 686 { 687 return dev->parent; 688 } 689 690 int 691 device_get_children(device_t dev, device_t **devlistp, int *devcountp) 692 { 693 int count; 694 device_t child; 695 device_t *list; 696 697 count = 0; 698 TAILQ_FOREACH(child, &dev->children, link) 699 count++; 700 701 list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT | M_ZERO); 702 if (!list) 703 return(ENOMEM); 704 705 count = 0; 706 TAILQ_FOREACH(child, &dev->children, link) { 707 list[count] = child; 708 count++; 709 } 710 711 *devlistp = list; 712 *devcountp = count; 713 714 return(0); 715 } 716 717 driver_t * 718 device_get_driver(device_t dev) 719 { 720 return(dev->driver); 721 } 722 723 devclass_t 724 device_get_devclass(device_t dev) 725 { 726 return(dev->devclass); 727 } 728 729 const char * 730 device_get_name(device_t dev) 731 { 732 if (dev->devclass) 733 return devclass_get_name(dev->devclass); 734 return(NULL); 735 } 736 737 const char * 738 device_get_nameunit(device_t dev) 739 { 740 return(dev->nameunit); 741 } 742 743 int 744 device_get_unit(device_t dev) 745 { 746 return(dev->unit); 747 } 748 749 const char * 750 device_get_desc(device_t dev) 751 { 752 return(dev->desc); 753 } 754 755 uint32_t 756 device_get_flags(device_t dev) 757 { 758 return(dev->devflags); 759 } 760 761 int 762 device_print_prettyname(device_t dev) 763 { 764 const char *name = device_get_name(dev); 765 766 if (name == 0) 767 return printf("unknown: "); 768 else 769 return printf("%s%d: ", name, device_get_unit(dev)); 770 } 771 772 int 773 device_printf(device_t dev, const char * fmt, ...) 774 { 775 __va_list ap; 776 int retval; 777 778 retval = device_print_prettyname(dev); 779 __va_start(ap, fmt); 780 retval += vprintf(fmt, ap); 781 __va_end(ap); 782 return retval; 783 } 784 785 static void 786 device_set_desc_internal(device_t dev, const char* desc, int copy) 787 { 788 if (dev->desc && (dev->flags & DF_DESCMALLOCED)) { 789 free(dev->desc, M_BUS); 790 dev->flags &= ~DF_DESCMALLOCED; 791 dev->desc = NULL; 792 } 793 794 if (copy && desc) { 795 dev->desc = malloc(strlen(desc) + 1, M_BUS, M_NOWAIT); 796 if (dev->desc) { 797 strcpy(dev->desc, desc); 798 dev->flags |= DF_DESCMALLOCED; 799 } 800 } else 801 /* Avoid a -Wcast-qual warning */ 802 dev->desc = (char *)(uintptr_t) desc; 803 804 #ifdef DEVICE_SYSCTLS 805 { 806 struct sysctl_oid *oid = &dev->oid[1]; 807 oid->oid_arg1 = dev->desc ? dev->desc : ""; 808 oid->oid_arg2 = dev->desc ? strlen(dev->desc) : 0; 809 } 810 #endif 811 } 812 813 void 814 device_set_desc(device_t dev, const char* desc) 815 { 816 device_set_desc_internal(dev, desc, FALSE); 817 } 818 819 void 820 device_set_desc_copy(device_t dev, const char* desc) 821 { 822 device_set_desc_internal(dev, desc, TRUE); 823 } 824 825 void 826 device_set_flags(device_t dev, uint32_t flags) 827 { 828 dev->devflags = flags; 829 } 830 831 void * 832 device_get_softc(device_t dev) 833 { 834 return dev->softc; 835 } 836 837 void 838 device_set_softc(device_t dev, void *softc) 839 { 840 if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) 841 free(dev->softc, M_BUS); 842 dev->softc = softc; 843 if (dev->softc) 844 dev->flags |= DF_EXTERNALSOFTC; 845 else 846 dev->flags &= ~DF_EXTERNALSOFTC; 847 } 848 849 void * 850 device_get_ivars(device_t dev) 851 { 852 return dev->ivars; 853 } 854 855 void 856 device_set_ivars(device_t dev, void * ivars) 857 { 858 if (!dev) 859 return; 860 861 dev->ivars = ivars; 862 } 863 864 device_state_t 865 device_get_state(device_t dev) 866 { 867 return(dev->state); 868 } 869 870 void 871 device_enable(device_t dev) 872 { 873 dev->flags |= DF_ENABLED; 874 } 875 876 void 877 device_disable(device_t dev) 878 { 879 dev->flags &= ~DF_ENABLED; 880 } 881 882 /* 883 * YYY cannot block 884 */ 885 void 886 device_busy(device_t dev) 887 { 888 if (dev->state < DS_ATTACHED) 889 panic("device_busy: called for unattached device"); 890 if (dev->busy == 0 && dev->parent) 891 device_busy(dev->parent); 892 dev->busy++; 893 dev->state = DS_BUSY; 894 } 895 896 /* 897 * YYY cannot block 898 */ 899 void 900 device_unbusy(device_t dev) 901 { 902 if (dev->state != DS_BUSY) 903 panic("device_unbusy: called for non-busy device"); 904 dev->busy--; 905 if (dev->busy == 0) { 906 if (dev->parent) 907 device_unbusy(dev->parent); 908 dev->state = DS_ATTACHED; 909 } 910 } 911 912 void 913 device_quiet(device_t dev) 914 { 915 dev->flags |= DF_QUIET; 916 } 917 918 void 919 device_verbose(device_t dev) 920 { 921 dev->flags &= ~DF_QUIET; 922 } 923 924 int 925 device_is_quiet(device_t dev) 926 { 927 return((dev->flags & DF_QUIET) != 0); 928 } 929 930 int 931 device_is_enabled(device_t dev) 932 { 933 return((dev->flags & DF_ENABLED) != 0); 934 } 935 936 int 937 device_is_alive(device_t dev) 938 { 939 return(dev->state >= DS_ALIVE); 940 } 941 942 int 943 device_is_attached(device_t dev) 944 { 945 return(dev->state >= DS_ATTACHED); 946 } 947 948 int 949 device_set_devclass(device_t dev, const char *classname) 950 { 951 devclass_t dc; 952 953 if (!classname) { 954 if (dev->devclass) 955 devclass_delete_device(dev->devclass, dev); 956 return(0); 957 } 958 959 if (dev->devclass) { 960 printf("device_set_devclass: device class already set\n"); 961 return(EINVAL); 962 } 963 964 dc = devclass_find_internal(classname, TRUE); 965 if (!dc) 966 return(ENOMEM); 967 968 return(devclass_add_device(dc, dev)); 969 } 970 971 int 972 device_set_driver(device_t dev, driver_t *driver) 973 { 974 if (dev->state >= DS_ATTACHED) 975 return(EBUSY); 976 977 if (dev->driver == driver) 978 return(0); 979 980 if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) { 981 free(dev->softc, M_BUS); 982 dev->softc = NULL; 983 } 984 kobj_delete((kobj_t) dev, 0); 985 dev->driver = driver; 986 if (driver) { 987 kobj_init((kobj_t) dev, (kobj_class_t) driver); 988 if (!(dev->flags & DF_EXTERNALSOFTC)) { 989 dev->softc = malloc(driver->size, M_BUS, 990 M_NOWAIT | M_ZERO); 991 if (!dev->softc) { 992 kobj_delete((kobj_t)dev, 0); 993 kobj_init((kobj_t) dev, &null_class); 994 dev->driver = NULL; 995 return(ENOMEM); 996 } 997 } 998 } else 999 kobj_init((kobj_t) dev, &null_class); 1000 return(0); 1001 } 1002 1003 int 1004 device_probe_and_attach(device_t dev) 1005 { 1006 device_t bus = dev->parent; 1007 int error = 0; 1008 int hasclass = (dev->devclass != 0); 1009 1010 if (dev->state >= DS_ALIVE) 1011 return(0); 1012 1013 if ((dev->flags & DF_ENABLED) == 0) { 1014 if (bootverbose) { 1015 device_print_prettyname(dev); 1016 printf("not probed (disabled)\n"); 1017 } 1018 return(0); 1019 } 1020 1021 error = device_probe_child(bus, dev); 1022 if (error) { 1023 if (!(dev->flags & DF_DONENOMATCH)) { 1024 BUS_PROBE_NOMATCH(bus, dev); 1025 dev->flags |= DF_DONENOMATCH; 1026 } 1027 return(error); 1028 } 1029 1030 if (!device_is_quiet(dev)) 1031 device_print_child(bus, dev); 1032 error = DEVICE_ATTACH(dev); 1033 if (!error) 1034 dev->state = DS_ATTACHED; 1035 else { 1036 printf("device_probe_and_attach: %s%d attach returned %d\n", 1037 dev->driver->name, dev->unit, error); 1038 /* Unset the class that was set in device_probe_child */ 1039 if (!hasclass) 1040 device_set_devclass(dev, 0); 1041 device_set_driver(dev, NULL); 1042 dev->state = DS_NOTPRESENT; 1043 } 1044 1045 return(error); 1046 } 1047 1048 int 1049 device_detach(device_t dev) 1050 { 1051 int error; 1052 1053 PDEBUG(("%s", DEVICENAME(dev))); 1054 if (dev->state == DS_BUSY) 1055 return(EBUSY); 1056 if (dev->state != DS_ATTACHED) 1057 return(0); 1058 1059 if ((error = DEVICE_DETACH(dev)) != 0) 1060 return(error); 1061 device_printf(dev, "detached\n"); 1062 if (dev->parent) 1063 BUS_CHILD_DETACHED(dev->parent, dev); 1064 1065 if (!(dev->flags & DF_FIXEDCLASS)) 1066 devclass_delete_device(dev->devclass, dev); 1067 1068 dev->state = DS_NOTPRESENT; 1069 device_set_driver(dev, NULL); 1070 1071 return(0); 1072 } 1073 1074 int 1075 device_shutdown(device_t dev) 1076 { 1077 if (dev->state < DS_ATTACHED) 1078 return 0; 1079 return DEVICE_SHUTDOWN(dev); 1080 } 1081 1082 int 1083 device_set_unit(device_t dev, int unit) 1084 { 1085 devclass_t dc; 1086 int err; 1087 1088 dc = device_get_devclass(dev); 1089 if (unit < dc->maxunit && dc->devices[unit]) 1090 return(EBUSY); 1091 err = devclass_delete_device(dc, dev); 1092 if (err) 1093 return(err); 1094 dev->unit = unit; 1095 err = devclass_add_device(dc, dev); 1096 return(err); 1097 } 1098 1099 #ifdef DEVICE_SYSCTLS 1100 1101 /* 1102 * Sysctl nodes for devices. 1103 */ 1104 1105 SYSCTL_NODE(_hw, OID_AUTO, devices, CTLFLAG_RW, 0, "A list of all devices"); 1106 1107 static int 1108 sysctl_handle_children(SYSCTL_HANDLER_ARGS) 1109 { 1110 device_t dev = arg1; 1111 device_t child; 1112 int first = 1, error = 0; 1113 1114 TAILQ_FOREACH(child, &dev->children, link) 1115 if (child->nameunit) { 1116 if (!first) { 1117 error = SYSCTL_OUT(req, ",", 1); 1118 if (error) 1119 return error; 1120 } else 1121 first = 0; 1122 error = SYSCTL_OUT(req, child->nameunit, 1123 strlen(child->nameunit)); 1124 if (error) 1125 return(error); 1126 } 1127 1128 error = SYSCTL_OUT(req, "", 1); 1129 1130 return(error); 1131 } 1132 1133 static int 1134 sysctl_handle_state(SYSCTL_HANDLER_ARGS) 1135 { 1136 device_t dev = arg1; 1137 1138 switch (dev->state) { 1139 case DS_NOTPRESENT: 1140 return SYSCTL_OUT(req, "notpresent", sizeof("notpresent")); 1141 case DS_ALIVE: 1142 return SYSCTL_OUT(req, "alive", sizeof("alive")); 1143 case DS_ATTACHED: 1144 return SYSCTL_OUT(req, "attached", sizeof("attached")); 1145 case DS_BUSY: 1146 return SYSCTL_OUT(req, "busy", sizeof("busy")); 1147 default: 1148 return (0); 1149 } 1150 } 1151 1152 static void 1153 device_register_oids(device_t dev) 1154 { 1155 struct sysctl_oid* oid; 1156 1157 oid = &dev->oid[0]; 1158 bzero(oid, sizeof(*oid)); 1159 oid->oid_parent = &sysctl__hw_devices_children; 1160 oid->oid_number = OID_AUTO; 1161 oid->oid_kind = CTLTYPE_NODE | CTLFLAG_RW; 1162 oid->oid_arg1 = &dev->oidlist[0]; 1163 oid->oid_arg2 = 0; 1164 oid->oid_name = dev->nameunit; 1165 oid->oid_handler = 0; 1166 oid->oid_fmt = "N"; 1167 SLIST_INIT(&dev->oidlist[0]); 1168 sysctl_register_oid(oid); 1169 1170 oid = &dev->oid[1]; 1171 bzero(oid, sizeof(*oid)); 1172 oid->oid_parent = &dev->oidlist[0]; 1173 oid->oid_number = OID_AUTO; 1174 oid->oid_kind = CTLTYPE_STRING | CTLFLAG_RD; 1175 oid->oid_arg1 = dev->desc ? dev->desc : ""; 1176 oid->oid_arg2 = dev->desc ? strlen(dev->desc) : 0; 1177 oid->oid_name = "desc"; 1178 oid->oid_handler = sysctl_handle_string; 1179 oid->oid_fmt = "A"; 1180 sysctl_register_oid(oid); 1181 1182 oid = &dev->oid[2]; 1183 bzero(oid, sizeof(*oid)); 1184 oid->oid_parent = &dev->oidlist[0]; 1185 oid->oid_number = OID_AUTO; 1186 oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD; 1187 oid->oid_arg1 = dev; 1188 oid->oid_arg2 = 0; 1189 oid->oid_name = "children"; 1190 oid->oid_handler = sysctl_handle_children; 1191 oid->oid_fmt = "A"; 1192 sysctl_register_oid(oid); 1193 1194 oid = &dev->oid[3]; 1195 bzero(oid, sizeof(*oid)); 1196 oid->oid_parent = &dev->oidlist[0]; 1197 oid->oid_number = OID_AUTO; 1198 oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD; 1199 oid->oid_arg1 = dev; 1200 oid->oid_arg2 = 0; 1201 oid->oid_name = "state"; 1202 oid->oid_handler = sysctl_handle_state; 1203 oid->oid_fmt = "A"; 1204 sysctl_register_oid(oid); 1205 } 1206 1207 static void 1208 device_unregister_oids(device_t dev) 1209 { 1210 sysctl_unregister_oid(&dev->oid[0]); 1211 sysctl_unregister_oid(&dev->oid[1]); 1212 sysctl_unregister_oid(&dev->oid[2]); 1213 } 1214 1215 #endif 1216 1217 /*======================================*/ 1218 /* 1219 * Access functions for device resources. 1220 */ 1221 1222 /* Supplied by config(8) in ioconf.c */ 1223 extern struct config_device config_devtab[]; 1224 extern int devtab_count; 1225 1226 /* Runtime version */ 1227 struct config_device *devtab = config_devtab; 1228 1229 static int 1230 resource_new_name(const char *name, int unit) 1231 { 1232 struct config_device *new; 1233 1234 new = malloc((devtab_count + 1) * sizeof(*new), M_TEMP, 1235 M_NOWAIT | M_ZERO); 1236 if (new == NULL) 1237 return(-1); 1238 if (devtab && devtab_count > 0) 1239 bcopy(devtab, new, devtab_count * sizeof(*new)); 1240 new[devtab_count].name = malloc(strlen(name) + 1, M_TEMP, M_NOWAIT); 1241 if (new[devtab_count].name == NULL) { 1242 free(new, M_TEMP); 1243 return(-1); 1244 } 1245 strcpy(new[devtab_count].name, name); 1246 new[devtab_count].unit = unit; 1247 new[devtab_count].resource_count = 0; 1248 new[devtab_count].resources = NULL; 1249 devtab = new; 1250 return devtab_count++; 1251 } 1252 1253 static int 1254 resource_new_resname(int j, const char *resname, resource_type type) 1255 { 1256 struct config_resource *new; 1257 int i; 1258 1259 i = devtab[j].resource_count; 1260 new = malloc((i + 1) * sizeof(*new), M_TEMP, M_NOWAIT | M_ZERO); 1261 if (new == NULL) 1262 return(-1); 1263 if (devtab[j].resources && i > 0) 1264 bcopy(devtab[j].resources, new, i * sizeof(*new)); 1265 new[i].name = malloc(strlen(resname) + 1, M_TEMP, M_NOWAIT); 1266 if (new[i].name == NULL) { 1267 free(new, M_TEMP); 1268 return(-1); 1269 } 1270 strcpy(new[i].name, resname); 1271 new[i].type = type; 1272 if (devtab[j].resources) 1273 free(devtab[j].resources, M_TEMP); 1274 devtab[j].resources = new; 1275 devtab[j].resource_count = i + 1; 1276 return(i); 1277 } 1278 1279 static int 1280 resource_match_string(int i, const char *resname, const char *value) 1281 { 1282 int j; 1283 struct config_resource *res; 1284 1285 for (j = 0, res = devtab[i].resources; 1286 j < devtab[i].resource_count; j++, res++) 1287 if (!strcmp(res->name, resname) 1288 && res->type == RES_STRING 1289 && !strcmp(res->u.stringval, value)) 1290 return(j); 1291 return(-1); 1292 } 1293 1294 static int 1295 resource_find(const char *name, int unit, const char *resname, 1296 struct config_resource **result) 1297 { 1298 int i, j; 1299 struct config_resource *res; 1300 1301 /* 1302 * First check specific instances, then generic. 1303 */ 1304 for (i = 0; i < devtab_count; i++) { 1305 if (devtab[i].unit < 0) 1306 continue; 1307 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { 1308 res = devtab[i].resources; 1309 for (j = 0; j < devtab[i].resource_count; j++, res++) 1310 if (!strcmp(res->name, resname)) { 1311 *result = res; 1312 return(0); 1313 } 1314 } 1315 } 1316 for (i = 0; i < devtab_count; i++) { 1317 if (devtab[i].unit >= 0) 1318 continue; 1319 /* XXX should this `&& devtab[i].unit == unit' be here? */ 1320 /* XXX if so, then the generic match does nothing */ 1321 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { 1322 res = devtab[i].resources; 1323 for (j = 0; j < devtab[i].resource_count; j++, res++) 1324 if (!strcmp(res->name, resname)) { 1325 *result = res; 1326 return(0); 1327 } 1328 } 1329 } 1330 return(ENOENT); 1331 } 1332 1333 int 1334 resource_int_value(const char *name, int unit, const char *resname, int *result) 1335 { 1336 int error; 1337 struct config_resource *res; 1338 1339 if ((error = resource_find(name, unit, resname, &res)) != 0) 1340 return(error); 1341 if (res->type != RES_INT) 1342 return(EFTYPE); 1343 *result = res->u.intval; 1344 return(0); 1345 } 1346 1347 int 1348 resource_long_value(const char *name, int unit, const char *resname, 1349 long *result) 1350 { 1351 int error; 1352 struct config_resource *res; 1353 1354 if ((error = resource_find(name, unit, resname, &res)) != 0) 1355 return(error); 1356 if (res->type != RES_LONG) 1357 return(EFTYPE); 1358 *result = res->u.longval; 1359 return(0); 1360 } 1361 1362 int 1363 resource_string_value(const char *name, int unit, const char *resname, 1364 char **result) 1365 { 1366 int error; 1367 struct config_resource *res; 1368 1369 if ((error = resource_find(name, unit, resname, &res)) != 0) 1370 return(error); 1371 if (res->type != RES_STRING) 1372 return(EFTYPE); 1373 *result = res->u.stringval; 1374 return(0); 1375 } 1376 1377 int 1378 resource_query_string(int i, const char *resname, const char *value) 1379 { 1380 if (i < 0) 1381 i = 0; 1382 else 1383 i = i + 1; 1384 for (; i < devtab_count; i++) 1385 if (resource_match_string(i, resname, value) >= 0) 1386 return(i); 1387 return(-1); 1388 } 1389 1390 int 1391 resource_locate(int i, const char *resname) 1392 { 1393 if (i < 0) 1394 i = 0; 1395 else 1396 i = i + 1; 1397 for (; i < devtab_count; i++) 1398 if (!strcmp(devtab[i].name, resname)) 1399 return(i); 1400 return(-1); 1401 } 1402 1403 int 1404 resource_count(void) 1405 { 1406 return(devtab_count); 1407 } 1408 1409 char * 1410 resource_query_name(int i) 1411 { 1412 return(devtab[i].name); 1413 } 1414 1415 int 1416 resource_query_unit(int i) 1417 { 1418 return(devtab[i].unit); 1419 } 1420 1421 static int 1422 resource_create(const char *name, int unit, const char *resname, 1423 resource_type type, struct config_resource **result) 1424 { 1425 int i, j; 1426 struct config_resource *res = NULL; 1427 1428 for (i = 0; i < devtab_count; i++) 1429 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { 1430 res = devtab[i].resources; 1431 break; 1432 } 1433 if (res == NULL) { 1434 i = resource_new_name(name, unit); 1435 if (i < 0) 1436 return(ENOMEM); 1437 res = devtab[i].resources; 1438 } 1439 for (j = 0; j < devtab[i].resource_count; j++, res++) 1440 if (!strcmp(res->name, resname)) { 1441 *result = res; 1442 return(0); 1443 } 1444 j = resource_new_resname(i, resname, type); 1445 if (j < 0) 1446 return(ENOMEM); 1447 res = &devtab[i].resources[j]; 1448 *result = res; 1449 return(0); 1450 } 1451 1452 int 1453 resource_set_int(const char *name, int unit, const char *resname, int value) 1454 { 1455 int error; 1456 struct config_resource *res; 1457 1458 error = resource_create(name, unit, resname, RES_INT, &res); 1459 if (error) 1460 return(error); 1461 if (res->type != RES_INT) 1462 return(EFTYPE); 1463 res->u.intval = value; 1464 return(0); 1465 } 1466 1467 int 1468 resource_set_long(const char *name, int unit, const char *resname, long value) 1469 { 1470 int error; 1471 struct config_resource *res; 1472 1473 error = resource_create(name, unit, resname, RES_LONG, &res); 1474 if (error) 1475 return(error); 1476 if (res->type != RES_LONG) 1477 return(EFTYPE); 1478 res->u.longval = value; 1479 return(0); 1480 } 1481 1482 int 1483 resource_set_string(const char *name, int unit, const char *resname, 1484 const char *value) 1485 { 1486 int error; 1487 struct config_resource *res; 1488 1489 error = resource_create(name, unit, resname, RES_STRING, &res); 1490 if (error) 1491 return(error); 1492 if (res->type != RES_STRING) 1493 return(EFTYPE); 1494 if (res->u.stringval) 1495 free(res->u.stringval, M_TEMP); 1496 res->u.stringval = malloc(strlen(value) + 1, M_TEMP, M_NOWAIT); 1497 if (res->u.stringval == NULL) 1498 return(ENOMEM); 1499 strcpy(res->u.stringval, value); 1500 return(0); 1501 } 1502 1503 static void 1504 resource_cfgload(void *dummy __unused) 1505 { 1506 struct config_resource *res, *cfgres; 1507 int i, j; 1508 int error; 1509 char *name, *resname; 1510 int unit; 1511 resource_type type; 1512 char *stringval; 1513 int config_devtab_count; 1514 1515 config_devtab_count = devtab_count; 1516 devtab = NULL; 1517 devtab_count = 0; 1518 1519 for (i = 0; i < config_devtab_count; i++) { 1520 name = config_devtab[i].name; 1521 unit = config_devtab[i].unit; 1522 1523 for (j = 0; j < config_devtab[i].resource_count; j++) { 1524 cfgres = config_devtab[i].resources; 1525 resname = cfgres[j].name; 1526 type = cfgres[j].type; 1527 error = resource_create(name, unit, resname, type, 1528 &res); 1529 if (error) { 1530 printf("create resource %s%d: error %d\n", 1531 name, unit, error); 1532 continue; 1533 } 1534 if (res->type != type) { 1535 printf("type mismatch %s%d: %d != %d\n", 1536 name, unit, res->type, type); 1537 continue; 1538 } 1539 switch (type) { 1540 case RES_INT: 1541 res->u.intval = cfgres[j].u.intval; 1542 break; 1543 case RES_LONG: 1544 res->u.longval = cfgres[j].u.longval; 1545 break; 1546 case RES_STRING: 1547 if (res->u.stringval) 1548 free(res->u.stringval, M_TEMP); 1549 stringval = cfgres[j].u.stringval; 1550 res->u.stringval = malloc(strlen(stringval) + 1, 1551 M_TEMP, M_NOWAIT); 1552 if (res->u.stringval == NULL) 1553 break; 1554 strcpy(res->u.stringval, stringval); 1555 break; 1556 default: 1557 panic("unknown resource type %d\n", type); 1558 } 1559 } 1560 } 1561 } 1562 SYSINIT(cfgload, SI_SUB_KMEM, SI_ORDER_ANY + 50, resource_cfgload, 0) 1563 1564 1565 /*======================================*/ 1566 /* 1567 * Some useful method implementations to make life easier for bus drivers. 1568 */ 1569 1570 void 1571 resource_list_init(struct resource_list *rl) 1572 { 1573 SLIST_INIT(rl); 1574 } 1575 1576 void 1577 resource_list_free(struct resource_list *rl) 1578 { 1579 struct resource_list_entry *rle; 1580 1581 while ((rle = SLIST_FIRST(rl)) != NULL) { 1582 if (rle->res) 1583 panic("resource_list_free: resource entry is busy"); 1584 SLIST_REMOVE_HEAD(rl, link); 1585 free(rle, M_BUS); 1586 } 1587 } 1588 1589 void 1590 resource_list_add(struct resource_list *rl, 1591 int type, int rid, 1592 u_long start, u_long end, u_long count) 1593 { 1594 struct resource_list_entry *rle; 1595 1596 rle = resource_list_find(rl, type, rid); 1597 if (rle == NULL) { 1598 rle = malloc(sizeof(struct resource_list_entry), M_BUS, M_NOWAIT); 1599 if (!rle) 1600 panic("resource_list_add: can't record entry"); 1601 SLIST_INSERT_HEAD(rl, rle, link); 1602 rle->type = type; 1603 rle->rid = rid; 1604 rle->res = NULL; 1605 } 1606 1607 if (rle->res) 1608 panic("resource_list_add: resource entry is busy"); 1609 1610 rle->start = start; 1611 rle->end = end; 1612 rle->count = count; 1613 } 1614 1615 struct resource_list_entry* 1616 resource_list_find(struct resource_list *rl, 1617 int type, int rid) 1618 { 1619 struct resource_list_entry *rle; 1620 1621 SLIST_FOREACH(rle, rl, link) 1622 if (rle->type == type && rle->rid == rid) 1623 return(rle); 1624 return(NULL); 1625 } 1626 1627 void 1628 resource_list_delete(struct resource_list *rl, 1629 int type, int rid) 1630 { 1631 struct resource_list_entry *rle = resource_list_find(rl, type, rid); 1632 1633 if (rle) { 1634 SLIST_REMOVE(rl, rle, resource_list_entry, link); 1635 free(rle, M_BUS); 1636 } 1637 } 1638 1639 struct resource * 1640 resource_list_alloc(struct resource_list *rl, 1641 device_t bus, device_t child, 1642 int type, int *rid, 1643 u_long start, u_long end, 1644 u_long count, u_int flags) 1645 { 1646 struct resource_list_entry *rle = 0; 1647 int passthrough = (device_get_parent(child) != bus); 1648 int isdefault = (start == 0UL && end == ~0UL); 1649 1650 if (passthrough) { 1651 return(BUS_ALLOC_RESOURCE(device_get_parent(bus), child, 1652 type, rid, 1653 start, end, count, flags)); 1654 } 1655 1656 rle = resource_list_find(rl, type, *rid); 1657 1658 if (!rle) 1659 return(0); /* no resource of that type/rid */ 1660 if (rle->res) 1661 panic("resource_list_alloc: resource entry is busy"); 1662 1663 if (isdefault) { 1664 start = rle->start; 1665 count = max(count, rle->count); 1666 end = max(rle->end, start + count - 1); 1667 } 1668 1669 rle->res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child, 1670 type, rid, start, end, count, flags); 1671 1672 /* 1673 * Record the new range. 1674 */ 1675 if (rle->res) { 1676 rle->start = rman_get_start(rle->res); 1677 rle->end = rman_get_end(rle->res); 1678 rle->count = count; 1679 } 1680 1681 return(rle->res); 1682 } 1683 1684 int 1685 resource_list_release(struct resource_list *rl, 1686 device_t bus, device_t child, 1687 int type, int rid, struct resource *res) 1688 { 1689 struct resource_list_entry *rle = 0; 1690 int passthrough = (device_get_parent(child) != bus); 1691 int error; 1692 1693 if (passthrough) { 1694 return(BUS_RELEASE_RESOURCE(device_get_parent(bus), child, 1695 type, rid, res)); 1696 } 1697 1698 rle = resource_list_find(rl, type, rid); 1699 1700 if (!rle) 1701 panic("resource_list_release: can't find resource"); 1702 if (!rle->res) 1703 panic("resource_list_release: resource entry is not busy"); 1704 1705 error = BUS_RELEASE_RESOURCE(device_get_parent(bus), child, 1706 type, rid, res); 1707 if (error) 1708 return(error); 1709 1710 rle->res = NULL; 1711 return(0); 1712 } 1713 1714 int 1715 resource_list_print_type(struct resource_list *rl, const char *name, int type, 1716 const char *format) 1717 { 1718 struct resource_list_entry *rle; 1719 int printed, retval; 1720 1721 printed = 0; 1722 retval = 0; 1723 /* Yes, this is kinda cheating */ 1724 SLIST_FOREACH(rle, rl, link) { 1725 if (rle->type == type) { 1726 if (printed == 0) 1727 retval += printf(" %s ", name); 1728 else 1729 retval += printf(","); 1730 printed++; 1731 retval += printf(format, rle->start); 1732 if (rle->count > 1) { 1733 retval += printf("-"); 1734 retval += printf(format, rle->start + 1735 rle->count - 1); 1736 } 1737 } 1738 } 1739 return(retval); 1740 } 1741 1742 /* 1743 * Call DEVICE_IDENTIFY for each driver. 1744 */ 1745 int 1746 bus_generic_probe(device_t dev) 1747 { 1748 devclass_t dc = dev->devclass; 1749 driverlink_t dl; 1750 1751 TAILQ_FOREACH(dl, &dc->drivers, link) 1752 DEVICE_IDENTIFY(dl->driver, dev); 1753 1754 return(0); 1755 } 1756 1757 int 1758 bus_generic_attach(device_t dev) 1759 { 1760 device_t child; 1761 1762 TAILQ_FOREACH(child, &dev->children, link) 1763 device_probe_and_attach(child); 1764 1765 return(0); 1766 } 1767 1768 int 1769 bus_generic_detach(device_t dev) 1770 { 1771 device_t child; 1772 int error; 1773 1774 if (dev->state != DS_ATTACHED) 1775 return(EBUSY); 1776 1777 TAILQ_FOREACH(child, &dev->children, link) 1778 if ((error = device_detach(child)) != 0) 1779 return(error); 1780 1781 return 0; 1782 } 1783 1784 int 1785 bus_generic_shutdown(device_t dev) 1786 { 1787 device_t child; 1788 1789 TAILQ_FOREACH(child, &dev->children, link) 1790 device_shutdown(child); 1791 1792 return(0); 1793 } 1794 1795 int 1796 bus_generic_suspend(device_t dev) 1797 { 1798 int error; 1799 device_t child, child2; 1800 1801 TAILQ_FOREACH(child, &dev->children, link) { 1802 error = DEVICE_SUSPEND(child); 1803 if (error) { 1804 for (child2 = TAILQ_FIRST(&dev->children); 1805 child2 && child2 != child; 1806 child2 = TAILQ_NEXT(child2, link)) 1807 DEVICE_RESUME(child2); 1808 return(error); 1809 } 1810 } 1811 return(0); 1812 } 1813 1814 int 1815 bus_generic_resume(device_t dev) 1816 { 1817 device_t child; 1818 1819 TAILQ_FOREACH(child, &dev->children, link) 1820 DEVICE_RESUME(child); 1821 /* if resume fails, there's nothing we can usefully do... */ 1822 1823 return(0); 1824 } 1825 1826 int 1827 bus_print_child_header(device_t dev, device_t child) 1828 { 1829 int retval = 0; 1830 1831 if (device_get_desc(child)) 1832 retval += device_printf(child, "<%s>", device_get_desc(child)); 1833 else 1834 retval += printf("%s", device_get_nameunit(child)); 1835 1836 return(retval); 1837 } 1838 1839 int 1840 bus_print_child_footer(device_t dev, device_t child) 1841 { 1842 return(printf(" on %s\n", device_get_nameunit(dev))); 1843 } 1844 1845 int 1846 bus_generic_print_child(device_t dev, device_t child) 1847 { 1848 int retval = 0; 1849 1850 retval += bus_print_child_header(dev, child); 1851 retval += bus_print_child_footer(dev, child); 1852 1853 return(retval); 1854 } 1855 1856 int 1857 bus_generic_read_ivar(device_t dev, device_t child, int index, 1858 uintptr_t * result) 1859 { 1860 return(ENOENT); 1861 } 1862 1863 int 1864 bus_generic_write_ivar(device_t dev, device_t child, int index, 1865 uintptr_t value) 1866 { 1867 return(ENOENT); 1868 } 1869 1870 struct resource_list * 1871 bus_generic_get_resource_list(device_t dev, device_t child) 1872 { 1873 return(NULL); 1874 } 1875 1876 void 1877 bus_generic_driver_added(device_t dev, driver_t *driver) 1878 { 1879 device_t child; 1880 1881 DEVICE_IDENTIFY(driver, dev); 1882 TAILQ_FOREACH(child, &dev->children, link) 1883 if (child->state == DS_NOTPRESENT) 1884 device_probe_and_attach(child); 1885 } 1886 1887 int 1888 bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq, 1889 int flags, driver_intr_t *intr, void *arg, 1890 void **cookiep) 1891 { 1892 /* Propagate up the bus hierarchy until someone handles it. */ 1893 if (dev->parent) 1894 return(BUS_SETUP_INTR(dev->parent, child, irq, flags, 1895 intr, arg, cookiep)); 1896 else 1897 return(EINVAL); 1898 } 1899 1900 int 1901 bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq, 1902 void *cookie) 1903 { 1904 /* Propagate up the bus hierarchy until someone handles it. */ 1905 if (dev->parent) 1906 return(BUS_TEARDOWN_INTR(dev->parent, child, irq, cookie)); 1907 else 1908 return(EINVAL); 1909 } 1910 1911 struct resource * 1912 bus_generic_alloc_resource(device_t dev, device_t child, int type, int *rid, 1913 u_long start, u_long end, u_long count, u_int flags) 1914 { 1915 /* Propagate up the bus hierarchy until someone handles it. */ 1916 if (dev->parent) 1917 return(BUS_ALLOC_RESOURCE(dev->parent, child, type, rid, 1918 start, end, count, flags)); 1919 else 1920 return(NULL); 1921 } 1922 1923 int 1924 bus_generic_release_resource(device_t dev, device_t child, int type, int rid, 1925 struct resource *r) 1926 { 1927 /* Propagate up the bus hierarchy until someone handles it. */ 1928 if (dev->parent) 1929 return(BUS_RELEASE_RESOURCE(dev->parent, child, type, rid, r)); 1930 else 1931 return(EINVAL); 1932 } 1933 1934 int 1935 bus_generic_activate_resource(device_t dev, device_t child, int type, int rid, 1936 struct resource *r) 1937 { 1938 /* Propagate up the bus hierarchy until someone handles it. */ 1939 if (dev->parent) 1940 return(BUS_ACTIVATE_RESOURCE(dev->parent, child, type, rid, r)); 1941 else 1942 return(EINVAL); 1943 } 1944 1945 int 1946 bus_generic_deactivate_resource(device_t dev, device_t child, int type, 1947 int rid, struct resource *r) 1948 { 1949 /* Propagate up the bus hierarchy until someone handles it. */ 1950 if (dev->parent) 1951 return(BUS_DEACTIVATE_RESOURCE(dev->parent, child, type, rid, 1952 r)); 1953 else 1954 return(EINVAL); 1955 } 1956 1957 int 1958 bus_generic_config_intr(device_t dev, int irq, enum intr_trigger trig, 1959 enum intr_polarity pol) 1960 { 1961 /* Propagate up the bus hierarchy until someone handles it. */ 1962 if (dev->parent) 1963 return(BUS_CONFIG_INTR(dev->parent, irq, trig, pol)); 1964 else 1965 return(EINVAL); 1966 } 1967 1968 int 1969 bus_generic_rl_get_resource(device_t dev, device_t child, int type, int rid, 1970 u_long *startp, u_long *countp) 1971 { 1972 struct resource_list *rl = NULL; 1973 struct resource_list_entry *rle = NULL; 1974 1975 rl = BUS_GET_RESOURCE_LIST(dev, child); 1976 if (!rl) 1977 return(EINVAL); 1978 1979 rle = resource_list_find(rl, type, rid); 1980 if (!rle) 1981 return(ENOENT); 1982 1983 if (startp) 1984 *startp = rle->start; 1985 if (countp) 1986 *countp = rle->count; 1987 1988 return(0); 1989 } 1990 1991 int 1992 bus_generic_rl_set_resource(device_t dev, device_t child, int type, int rid, 1993 u_long start, u_long count) 1994 { 1995 struct resource_list *rl = NULL; 1996 1997 rl = BUS_GET_RESOURCE_LIST(dev, child); 1998 if (!rl) 1999 return(EINVAL); 2000 2001 resource_list_add(rl, type, rid, start, (start + count - 1), count); 2002 2003 return(0); 2004 } 2005 2006 void 2007 bus_generic_rl_delete_resource(device_t dev, device_t child, int type, int rid) 2008 { 2009 struct resource_list *rl = NULL; 2010 2011 rl = BUS_GET_RESOURCE_LIST(dev, child); 2012 if (!rl) 2013 return; 2014 2015 resource_list_delete(rl, type, rid); 2016 } 2017 2018 int 2019 bus_generic_rl_release_resource(device_t dev, device_t child, int type, 2020 int rid, struct resource *r) 2021 { 2022 struct resource_list *rl = NULL; 2023 2024 rl = BUS_GET_RESOURCE_LIST(dev, child); 2025 if (!rl) 2026 return(EINVAL); 2027 2028 return(resource_list_release(rl, dev, child, type, rid, r)); 2029 } 2030 2031 struct resource * 2032 bus_generic_rl_alloc_resource(device_t dev, device_t child, int type, 2033 int *rid, u_long start, u_long end, u_long count, u_int flags) 2034 { 2035 struct resource_list *rl = NULL; 2036 2037 rl = BUS_GET_RESOURCE_LIST(dev, child); 2038 if (!rl) 2039 return(NULL); 2040 2041 return(resource_list_alloc(rl, dev, child, type, rid, 2042 start, end, count, flags)); 2043 } 2044 2045 int 2046 bus_generic_child_present(device_t bus, device_t child) 2047 { 2048 return(BUS_CHILD_PRESENT(device_get_parent(bus), bus)); 2049 } 2050 2051 2052 /* 2053 * Some convenience functions to make it easier for drivers to use the 2054 * resource-management functions. All these really do is hide the 2055 * indirection through the parent's method table, making for slightly 2056 * less-wordy code. In the future, it might make sense for this code 2057 * to maintain some sort of a list of resources allocated by each device. 2058 */ 2059 struct resource * 2060 bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end, 2061 u_long count, u_int flags) 2062 { 2063 if (dev->parent == 0) 2064 return(0); 2065 return(BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end, 2066 count, flags)); 2067 } 2068 2069 int 2070 bus_activate_resource(device_t dev, int type, int rid, struct resource *r) 2071 { 2072 if (dev->parent == 0) 2073 return(EINVAL); 2074 return(BUS_ACTIVATE_RESOURCE(dev->parent, dev, type, rid, r)); 2075 } 2076 2077 int 2078 bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r) 2079 { 2080 if (dev->parent == 0) 2081 return(EINVAL); 2082 return(BUS_DEACTIVATE_RESOURCE(dev->parent, dev, type, rid, r)); 2083 } 2084 2085 int 2086 bus_release_resource(device_t dev, int type, int rid, struct resource *r) 2087 { 2088 if (dev->parent == 0) 2089 return(EINVAL); 2090 return(BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r)); 2091 } 2092 2093 int 2094 bus_setup_intr(device_t dev, struct resource *r, int flags, 2095 driver_intr_t handler, void *arg, void **cookiep) 2096 { 2097 if (dev->parent == 0) 2098 return(EINVAL); 2099 return(BUS_SETUP_INTR(dev->parent, dev, r, flags, handler, arg, 2100 cookiep)); 2101 } 2102 2103 int 2104 bus_teardown_intr(device_t dev, struct resource *r, void *cookie) 2105 { 2106 if (dev->parent == 0) 2107 return(EINVAL); 2108 return(BUS_TEARDOWN_INTR(dev->parent, dev, r, cookie)); 2109 } 2110 2111 int 2112 bus_set_resource(device_t dev, int type, int rid, 2113 u_long start, u_long count) 2114 { 2115 return(BUS_SET_RESOURCE(device_get_parent(dev), dev, type, rid, 2116 start, count)); 2117 } 2118 2119 int 2120 bus_get_resource(device_t dev, int type, int rid, 2121 u_long *startp, u_long *countp) 2122 { 2123 return(BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid, 2124 startp, countp)); 2125 } 2126 2127 u_long 2128 bus_get_resource_start(device_t dev, int type, int rid) 2129 { 2130 u_long start, count; 2131 int error; 2132 2133 error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid, 2134 &start, &count); 2135 if (error) 2136 return(0); 2137 return(start); 2138 } 2139 2140 u_long 2141 bus_get_resource_count(device_t dev, int type, int rid) 2142 { 2143 u_long start, count; 2144 int error; 2145 2146 error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid, 2147 &start, &count); 2148 if (error) 2149 return(0); 2150 return(count); 2151 } 2152 2153 void 2154 bus_delete_resource(device_t dev, int type, int rid) 2155 { 2156 BUS_DELETE_RESOURCE(device_get_parent(dev), dev, type, rid); 2157 } 2158 2159 int 2160 bus_child_present(device_t child) 2161 { 2162 return (BUS_CHILD_PRESENT(device_get_parent(child), child)); 2163 } 2164 2165 int 2166 bus_child_pnpinfo_str(device_t child, char *buf, size_t buflen) 2167 { 2168 device_t parent; 2169 2170 parent = device_get_parent(child); 2171 if (parent == NULL) { 2172 *buf = '\0'; 2173 return (0); 2174 } 2175 return (BUS_CHILD_PNPINFO_STR(parent, child, buf, buflen)); 2176 } 2177 2178 int 2179 bus_child_location_str(device_t child, char *buf, size_t buflen) 2180 { 2181 device_t parent; 2182 2183 parent = device_get_parent(child); 2184 if (parent == NULL) { 2185 *buf = '\0'; 2186 return (0); 2187 } 2188 return (BUS_CHILD_LOCATION_STR(parent, child, buf, buflen)); 2189 } 2190 2191 static int 2192 root_print_child(device_t dev, device_t child) 2193 { 2194 return(0); 2195 } 2196 2197 static int 2198 root_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg, 2199 void **cookiep) 2200 { 2201 /* 2202 * If an interrupt mapping gets to here something bad has happened. 2203 */ 2204 panic("root_setup_intr"); 2205 } 2206 2207 /* 2208 * If we get here, assume that the device is permanant and really is 2209 * present in the system. Removable bus drivers are expected to intercept 2210 * this call long before it gets here. We return -1 so that drivers that 2211 * really care can check vs -1 or some ERRNO returned higher in the food 2212 * chain. 2213 */ 2214 static int 2215 root_child_present(device_t dev, device_t child) 2216 { 2217 return(-1); 2218 } 2219 2220 /* 2221 * XXX NOTE! other defaults may be set in bus_if.m 2222 */ 2223 static kobj_method_t root_methods[] = { 2224 /* Device interface */ 2225 KOBJMETHOD(device_shutdown, bus_generic_shutdown), 2226 KOBJMETHOD(device_suspend, bus_generic_suspend), 2227 KOBJMETHOD(device_resume, bus_generic_resume), 2228 2229 /* Bus interface */ 2230 KOBJMETHOD(bus_print_child, root_print_child), 2231 KOBJMETHOD(bus_read_ivar, bus_generic_read_ivar), 2232 KOBJMETHOD(bus_write_ivar, bus_generic_write_ivar), 2233 KOBJMETHOD(bus_setup_intr, root_setup_intr), 2234 KOBJMETHOD(bus_child_present, root_child_present), 2235 2236 { 0, 0 } 2237 }; 2238 2239 static driver_t root_driver = { 2240 "root", 2241 root_methods, 2242 1, /* no softc */ 2243 }; 2244 2245 device_t root_bus; 2246 devclass_t root_devclass; 2247 2248 static int 2249 root_bus_module_handler(module_t mod, int what, void* arg) 2250 { 2251 switch (what) { 2252 case MOD_LOAD: 2253 kobj_class_compile((kobj_class_t) &root_driver); 2254 root_bus = make_device(NULL, "root", 0); 2255 root_bus->desc = "System root bus"; 2256 kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver); 2257 root_bus->driver = &root_driver; 2258 root_bus->state = DS_ATTACHED; 2259 root_devclass = devclass_find_internal("root", FALSE); 2260 return(0); 2261 2262 case MOD_SHUTDOWN: 2263 device_shutdown(root_bus); 2264 return(0); 2265 default: 2266 return(0); 2267 } 2268 } 2269 2270 static moduledata_t root_bus_mod = { 2271 "rootbus", 2272 root_bus_module_handler, 2273 0 2274 }; 2275 DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 2276 2277 void 2278 root_bus_configure(void) 2279 { 2280 device_t dev; 2281 2282 PDEBUG((".")); 2283 2284 TAILQ_FOREACH(dev, &root_bus->children, link) 2285 device_probe_and_attach(dev); 2286 } 2287 2288 int 2289 driver_module_handler(module_t mod, int what, void *arg) 2290 { 2291 int error, i; 2292 struct driver_module_data *dmd; 2293 devclass_t bus_devclass; 2294 2295 dmd = (struct driver_module_data *)arg; 2296 bus_devclass = devclass_find_internal(dmd->dmd_busname, TRUE); 2297 error = 0; 2298 2299 switch (what) { 2300 case MOD_LOAD: 2301 if (dmd->dmd_chainevh) 2302 error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); 2303 2304 for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { 2305 PDEBUG(("Loading module: driver %s on bus %s", 2306 DRIVERNAME(dmd->dmd_drivers[i]), 2307 dmd->dmd_busname)); 2308 error = devclass_add_driver(bus_devclass, 2309 dmd->dmd_drivers[i]); 2310 } 2311 if (error) 2312 break; 2313 2314 /* 2315 * The drivers loaded in this way are assumed to all 2316 * implement the same devclass. 2317 */ 2318 *dmd->dmd_devclass = 2319 devclass_find_internal(dmd->dmd_drivers[0]->name, 2320 TRUE); 2321 break; 2322 2323 case MOD_UNLOAD: 2324 for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { 2325 PDEBUG(("Unloading module: driver %s from bus %s", 2326 DRIVERNAME(dmd->dmd_drivers[i]), 2327 dmd->dmd_busname)); 2328 error = devclass_delete_driver(bus_devclass, 2329 dmd->dmd_drivers[i]); 2330 } 2331 2332 if (!error && dmd->dmd_chainevh) 2333 error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); 2334 break; 2335 } 2336 2337 return (error); 2338 } 2339 2340 #ifdef BUS_DEBUG 2341 2342 /* 2343 * The _short versions avoid iteration by not calling anything that prints 2344 * more than oneliners. I love oneliners. 2345 */ 2346 2347 static void 2348 print_device_short(device_t dev, int indent) 2349 { 2350 if (!dev) 2351 return; 2352 2353 indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%s,%sivars,%ssoftc,busy=%d\n", 2354 dev->unit, dev->desc, 2355 (dev->parent? "":"no "), 2356 (TAILQ_EMPTY(&dev->children)? "no ":""), 2357 (dev->flags&DF_ENABLED? "enabled,":"disabled,"), 2358 (dev->flags&DF_FIXEDCLASS? "fixed,":""), 2359 (dev->flags&DF_WILDCARD? "wildcard,":""), 2360 (dev->flags&DF_DESCMALLOCED? "descmalloced,":""), 2361 (dev->ivars? "":"no "), 2362 (dev->softc? "":"no "), 2363 dev->busy)); 2364 } 2365 2366 static void 2367 print_device(device_t dev, int indent) 2368 { 2369 if (!dev) 2370 return; 2371 2372 print_device_short(dev, indent); 2373 2374 indentprintf(("Parent:\n")); 2375 print_device_short(dev->parent, indent+1); 2376 indentprintf(("Driver:\n")); 2377 print_driver_short(dev->driver, indent+1); 2378 indentprintf(("Devclass:\n")); 2379 print_devclass_short(dev->devclass, indent+1); 2380 } 2381 2382 /* 2383 * Print the device and all its children (indented). 2384 */ 2385 void 2386 print_device_tree_short(device_t dev, int indent) 2387 { 2388 device_t child; 2389 2390 if (!dev) 2391 return; 2392 2393 print_device_short(dev, indent); 2394 2395 TAILQ_FOREACH(child, &dev->children, link) 2396 print_device_tree_short(child, indent+1); 2397 } 2398 2399 /* 2400 * Print the device and all its children (indented). 2401 */ 2402 void 2403 print_device_tree(device_t dev, int indent) 2404 { 2405 device_t child; 2406 2407 if (!dev) 2408 return; 2409 2410 print_device(dev, indent); 2411 2412 TAILQ_FOREACH(child, &dev->children, link) 2413 print_device_tree(child, indent+1); 2414 } 2415 2416 static void 2417 print_driver_short(driver_t *driver, int indent) 2418 { 2419 if (!driver) 2420 return; 2421 2422 indentprintf(("driver %s: softc size = %d\n", 2423 driver->name, driver->size)); 2424 } 2425 2426 static void 2427 print_driver(driver_t *driver, int indent) 2428 { 2429 if (!driver) 2430 return; 2431 2432 print_driver_short(driver, indent); 2433 } 2434 2435 2436 static void 2437 print_driver_list(driver_list_t drivers, int indent) 2438 { 2439 driverlink_t driver; 2440 2441 TAILQ_FOREACH(driver, &drivers, link) 2442 print_driver(driver->driver, indent); 2443 } 2444 2445 static void 2446 print_devclass_short(devclass_t dc, int indent) 2447 { 2448 if (!dc) 2449 return; 2450 2451 indentprintf(("devclass %s: max units = %d\n", dc->name, dc->maxunit)); 2452 } 2453 2454 static void 2455 print_devclass(devclass_t dc, int indent) 2456 { 2457 int i; 2458 2459 if (!dc) 2460 return; 2461 2462 print_devclass_short(dc, indent); 2463 indentprintf(("Drivers:\n")); 2464 print_driver_list(dc->drivers, indent+1); 2465 2466 indentprintf(("Devices:\n")); 2467 for (i = 0; i < dc->maxunit; i++) 2468 if (dc->devices[i]) 2469 print_device(dc->devices[i], indent+1); 2470 } 2471 2472 void 2473 print_devclass_list_short(void) 2474 { 2475 devclass_t dc; 2476 2477 printf("Short listing of devclasses, drivers & devices:\n"); 2478 TAILQ_FOREACH(dc, &devclasses, link) { 2479 print_devclass_short(dc, 0); 2480 } 2481 } 2482 2483 void 2484 print_devclass_list(void) 2485 { 2486 devclass_t dc; 2487 2488 printf("Full listing of devclasses, drivers & devices:\n"); 2489 TAILQ_FOREACH(dc, &devclasses, link) { 2490 print_devclass(dc, 0); 2491 } 2492 } 2493 2494 #endif 2495 2496 /* 2497 * Check to see if a device is disabled via a disabled hint. 2498 */ 2499 int 2500 resource_disabled(const char *name, int unit) 2501 { 2502 int error, value; 2503 2504 error = resource_int_value(name, unit, "disabled", &value); 2505 if (error) 2506 return(0); 2507 return(value); 2508 } 2509