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