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.2 2003/06/17 04:28:41 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 void 1033 device_busy(device_t dev) 1034 { 1035 if (dev->state < DS_ATTACHED) 1036 panic("device_busy: called for unattached device"); 1037 if (dev->busy == 0 && dev->parent) 1038 device_busy(dev->parent); 1039 dev->busy++; 1040 dev->state = DS_BUSY; 1041 } 1042 1043 void 1044 device_unbusy(device_t dev) 1045 { 1046 if (dev->state != DS_BUSY) 1047 panic("device_unbusy: called for non-busy device"); 1048 dev->busy--; 1049 if (dev->busy == 0) { 1050 if (dev->parent) 1051 device_unbusy(dev->parent); 1052 dev->state = DS_ATTACHED; 1053 } 1054 } 1055 1056 void 1057 device_quiet(device_t dev) 1058 { 1059 dev->flags |= DF_QUIET; 1060 } 1061 1062 void 1063 device_verbose(device_t dev) 1064 { 1065 dev->flags &= ~DF_QUIET; 1066 } 1067 1068 int 1069 device_is_quiet(device_t dev) 1070 { 1071 return (dev->flags & DF_QUIET) != 0; 1072 } 1073 1074 int 1075 device_is_enabled(device_t dev) 1076 { 1077 return (dev->flags & DF_ENABLED) != 0; 1078 } 1079 1080 int 1081 device_is_alive(device_t dev) 1082 { 1083 return dev->state >= DS_ALIVE; 1084 } 1085 1086 int 1087 device_set_devclass(device_t dev, const char *classname) 1088 { 1089 devclass_t dc; 1090 1091 if (!classname) { 1092 if (dev->devclass) 1093 devclass_delete_device(dev->devclass, dev); 1094 return 0; 1095 } 1096 1097 if (dev->devclass) { 1098 printf("device_set_devclass: device class already set\n"); 1099 return EINVAL; 1100 } 1101 1102 dc = devclass_find_internal(classname, TRUE); 1103 if (!dc) 1104 return ENOMEM; 1105 1106 return devclass_add_device(dc, dev); 1107 } 1108 1109 int 1110 device_set_driver(device_t dev, driver_t *driver) 1111 { 1112 if (dev->state >= DS_ATTACHED) 1113 return EBUSY; 1114 1115 if (dev->driver == driver) 1116 return 0; 1117 1118 if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) { 1119 free(dev->softc, M_BUS); 1120 dev->softc = NULL; 1121 } 1122 dev->ops = &null_ops; 1123 dev->driver = driver; 1124 if (driver) { 1125 dev->ops = driver->ops; 1126 if (!(dev->flags & DF_EXTERNALSOFTC)) { 1127 dev->softc = malloc(driver->softc, M_BUS, M_NOWAIT); 1128 if (!dev->softc) { 1129 dev->ops = &null_ops; 1130 dev->driver = NULL; 1131 return ENOMEM; 1132 } 1133 bzero(dev->softc, driver->softc); 1134 } 1135 } 1136 return 0; 1137 } 1138 1139 int 1140 device_probe_and_attach(device_t dev) 1141 { 1142 device_t bus = dev->parent; 1143 int error = 0; 1144 int hasclass = (dev->devclass != 0); 1145 1146 if (dev->state >= DS_ALIVE) 1147 return 0; 1148 1149 if (dev->flags & DF_ENABLED) { 1150 error = device_probe_child(bus, dev); 1151 if (!error) { 1152 if (!device_is_quiet(dev)) 1153 device_print_child(bus, dev); 1154 error = DEVICE_ATTACH(dev); 1155 if (!error) 1156 dev->state = DS_ATTACHED; 1157 else { 1158 printf("device_probe_and_attach: %s%d attach returned %d\n", 1159 dev->driver->name, dev->unit, error); 1160 /* Unset the class that was set in device_probe_child */ 1161 if (!hasclass) 1162 device_set_devclass(dev, 0); 1163 device_set_driver(dev, NULL); 1164 dev->state = DS_NOTPRESENT; 1165 } 1166 } else { 1167 if (!(dev->flags & DF_DONENOMATCH)) { 1168 BUS_PROBE_NOMATCH(bus, dev); 1169 dev->flags |= DF_DONENOMATCH; 1170 } 1171 } 1172 } else { 1173 if (bootverbose) { 1174 device_print_prettyname(dev); 1175 printf("not probed (disabled)\n"); 1176 } 1177 } 1178 1179 return error; 1180 } 1181 1182 int 1183 device_detach(device_t dev) 1184 { 1185 int error; 1186 1187 PDEBUG(("%s", DEVICENAME(dev))); 1188 if (dev->state == DS_BUSY) 1189 return EBUSY; 1190 if (dev->state != DS_ATTACHED) 1191 return 0; 1192 1193 if ((error = DEVICE_DETACH(dev)) != 0) 1194 return error; 1195 device_printf(dev, "detached\n"); 1196 if (dev->parent) 1197 BUS_CHILD_DETACHED(dev->parent, dev); 1198 1199 if (!(dev->flags & DF_FIXEDCLASS)) 1200 devclass_delete_device(dev->devclass, dev); 1201 1202 dev->state = DS_NOTPRESENT; 1203 device_set_driver(dev, NULL); 1204 1205 return 0; 1206 } 1207 1208 int 1209 device_shutdown(device_t dev) 1210 { 1211 if (dev->state < DS_ATTACHED) 1212 return 0; 1213 return DEVICE_SHUTDOWN(dev); 1214 } 1215 1216 int 1217 device_set_unit(device_t dev, int unit) 1218 { 1219 devclass_t dc; 1220 int err; 1221 1222 dc = device_get_devclass(dev); 1223 if (unit < dc->maxunit && dc->devices[unit]) 1224 return EBUSY; 1225 err = devclass_delete_device(dc, dev); 1226 if (err) 1227 return err; 1228 dev->unit = unit; 1229 err = devclass_add_device(dc, dev); 1230 if (err) 1231 return err; 1232 return 0; 1233 } 1234 1235 #ifdef DEVICE_SYSCTLS 1236 1237 /* 1238 * Sysctl nodes for devices. 1239 */ 1240 1241 SYSCTL_NODE(_hw, OID_AUTO, devices, CTLFLAG_RW, 0, "A list of all devices"); 1242 1243 static int 1244 sysctl_handle_children(SYSCTL_HANDLER_ARGS) 1245 { 1246 device_t dev = arg1; 1247 device_t child; 1248 int first = 1, error = 0; 1249 1250 for (child = TAILQ_FIRST(&dev->children); child; 1251 child = TAILQ_NEXT(child, link)) { 1252 if (child->nameunit) { 1253 if (!first) { 1254 error = SYSCTL_OUT(req, ",", 1); 1255 if (error) return error; 1256 } else { 1257 first = 0; 1258 } 1259 error = SYSCTL_OUT(req, child->nameunit, strlen(child->nameunit)); 1260 if (error) return error; 1261 } 1262 } 1263 1264 error = SYSCTL_OUT(req, "", 1); 1265 1266 return error; 1267 } 1268 1269 static int 1270 sysctl_handle_state(SYSCTL_HANDLER_ARGS) 1271 { 1272 device_t dev = arg1; 1273 1274 switch (dev->state) { 1275 case DS_NOTPRESENT: 1276 return SYSCTL_OUT(req, "notpresent", sizeof("notpresent")); 1277 case DS_ALIVE: 1278 return SYSCTL_OUT(req, "alive", sizeof("alive")); 1279 case DS_ATTACHED: 1280 return SYSCTL_OUT(req, "attached", sizeof("attached")); 1281 case DS_BUSY: 1282 return SYSCTL_OUT(req, "busy", sizeof("busy")); 1283 } 1284 1285 return 0; 1286 } 1287 1288 static void 1289 device_register_oids(device_t dev) 1290 { 1291 struct sysctl_oid* oid; 1292 1293 oid = &dev->oid[0]; 1294 bzero(oid, sizeof(*oid)); 1295 oid->oid_parent = &sysctl__hw_devices_children; 1296 oid->oid_number = OID_AUTO; 1297 oid->oid_kind = CTLTYPE_NODE | CTLFLAG_RW; 1298 oid->oid_arg1 = &dev->oidlist[0]; 1299 oid->oid_arg2 = 0; 1300 oid->oid_name = dev->nameunit; 1301 oid->oid_handler = 0; 1302 oid->oid_fmt = "N"; 1303 SLIST_INIT(&dev->oidlist[0]); 1304 sysctl_register_oid(oid); 1305 1306 oid = &dev->oid[1]; 1307 bzero(oid, sizeof(*oid)); 1308 oid->oid_parent = &dev->oidlist[0]; 1309 oid->oid_number = OID_AUTO; 1310 oid->oid_kind = CTLTYPE_STRING | CTLFLAG_RD; 1311 oid->oid_arg1 = dev->desc ? dev->desc : ""; 1312 oid->oid_arg2 = dev->desc ? strlen(dev->desc) : 0; 1313 oid->oid_name = "desc"; 1314 oid->oid_handler = sysctl_handle_string; 1315 oid->oid_fmt = "A"; 1316 sysctl_register_oid(oid); 1317 1318 oid = &dev->oid[2]; 1319 bzero(oid, sizeof(*oid)); 1320 oid->oid_parent = &dev->oidlist[0]; 1321 oid->oid_number = OID_AUTO; 1322 oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD; 1323 oid->oid_arg1 = dev; 1324 oid->oid_arg2 = 0; 1325 oid->oid_name = "children"; 1326 oid->oid_handler = sysctl_handle_children; 1327 oid->oid_fmt = "A"; 1328 sysctl_register_oid(oid); 1329 1330 oid = &dev->oid[3]; 1331 bzero(oid, sizeof(*oid)); 1332 oid->oid_parent = &dev->oidlist[0]; 1333 oid->oid_number = OID_AUTO; 1334 oid->oid_kind = CTLTYPE_INT | CTLFLAG_RD; 1335 oid->oid_arg1 = dev; 1336 oid->oid_arg2 = 0; 1337 oid->oid_name = "state"; 1338 oid->oid_handler = sysctl_handle_state; 1339 oid->oid_fmt = "A"; 1340 sysctl_register_oid(oid); 1341 } 1342 1343 static void 1344 device_unregister_oids(device_t dev) 1345 { 1346 sysctl_unregister_oid(&dev->oid[0]); 1347 sysctl_unregister_oid(&dev->oid[1]); 1348 sysctl_unregister_oid(&dev->oid[2]); 1349 } 1350 1351 #endif 1352 1353 /*======================================*/ 1354 /* 1355 * Access functions for device resources. 1356 */ 1357 1358 /* Supplied by config(8) in ioconf.c */ 1359 extern struct config_device config_devtab[]; 1360 extern int devtab_count; 1361 1362 /* Runtime version */ 1363 struct config_device *devtab = config_devtab; 1364 1365 static int 1366 resource_new_name(const char *name, int unit) 1367 { 1368 struct config_device *new; 1369 1370 new = malloc((devtab_count + 1) * sizeof(*new), M_TEMP, M_NOWAIT); 1371 if (new == NULL) 1372 return -1; 1373 if (devtab && devtab_count > 0) 1374 bcopy(devtab, new, devtab_count * sizeof(*new)); 1375 bzero(&new[devtab_count], sizeof(*new)); 1376 new[devtab_count].name = malloc(strlen(name) + 1, M_TEMP, M_NOWAIT); 1377 if (new[devtab_count].name == NULL) { 1378 free(new, M_TEMP); 1379 return -1; 1380 } 1381 strcpy(new[devtab_count].name, name); 1382 new[devtab_count].unit = unit; 1383 new[devtab_count].resource_count = 0; 1384 new[devtab_count].resources = NULL; 1385 devtab = new; 1386 return devtab_count++; 1387 } 1388 1389 static int 1390 resource_new_resname(int j, const char *resname, resource_type type) 1391 { 1392 struct config_resource *new; 1393 int i; 1394 1395 i = devtab[j].resource_count; 1396 new = malloc((i + 1) * sizeof(*new), M_TEMP, M_NOWAIT); 1397 if (new == NULL) 1398 return -1; 1399 if (devtab[j].resources && i > 0) 1400 bcopy(devtab[j].resources, new, i * sizeof(*new)); 1401 bzero(&new[i], sizeof(*new)); 1402 new[i].name = malloc(strlen(resname) + 1, M_TEMP, M_NOWAIT); 1403 if (new[i].name == NULL) { 1404 free(new, M_TEMP); 1405 return -1; 1406 } 1407 strcpy(new[i].name, resname); 1408 new[i].type = type; 1409 if (devtab[j].resources) 1410 free(devtab[j].resources, M_TEMP); 1411 devtab[j].resources = new; 1412 devtab[j].resource_count = i + 1; 1413 return i; 1414 } 1415 1416 static int 1417 resource_match_string(int i, const char *resname, const char *value) 1418 { 1419 int j; 1420 struct config_resource *res; 1421 1422 for (j = 0, res = devtab[i].resources; 1423 j < devtab[i].resource_count; j++, res++) 1424 if (!strcmp(res->name, resname) 1425 && res->type == RES_STRING 1426 && !strcmp(res->u.stringval, value)) 1427 return j; 1428 return -1; 1429 } 1430 1431 static int 1432 resource_find(const char *name, int unit, const char *resname, 1433 struct config_resource **result) 1434 { 1435 int i, j; 1436 struct config_resource *res; 1437 1438 /* 1439 * First check specific instances, then generic. 1440 */ 1441 for (i = 0; i < devtab_count; i++) { 1442 if (devtab[i].unit < 0) 1443 continue; 1444 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { 1445 res = devtab[i].resources; 1446 for (j = 0; j < devtab[i].resource_count; j++, res++) 1447 if (!strcmp(res->name, resname)) { 1448 *result = res; 1449 return 0; 1450 } 1451 } 1452 } 1453 for (i = 0; i < devtab_count; i++) { 1454 if (devtab[i].unit >= 0) 1455 continue; 1456 /* XXX should this `&& devtab[i].unit == unit' be here? */ 1457 /* XXX if so, then the generic match does nothing */ 1458 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { 1459 res = devtab[i].resources; 1460 for (j = 0; j < devtab[i].resource_count; j++, res++) 1461 if (!strcmp(res->name, resname)) { 1462 *result = res; 1463 return 0; 1464 } 1465 } 1466 } 1467 return ENOENT; 1468 } 1469 1470 int 1471 resource_int_value(const char *name, int unit, const char *resname, int *result) 1472 { 1473 int error; 1474 struct config_resource *res; 1475 1476 if ((error = resource_find(name, unit, resname, &res)) != 0) 1477 return error; 1478 if (res->type != RES_INT) 1479 return EFTYPE; 1480 *result = res->u.intval; 1481 return 0; 1482 } 1483 1484 int 1485 resource_long_value(const char *name, int unit, const char *resname, 1486 long *result) 1487 { 1488 int error; 1489 struct config_resource *res; 1490 1491 if ((error = resource_find(name, unit, resname, &res)) != 0) 1492 return error; 1493 if (res->type != RES_LONG) 1494 return EFTYPE; 1495 *result = res->u.longval; 1496 return 0; 1497 } 1498 1499 int 1500 resource_string_value(const char *name, int unit, const char *resname, 1501 char **result) 1502 { 1503 int error; 1504 struct config_resource *res; 1505 1506 if ((error = resource_find(name, unit, resname, &res)) != 0) 1507 return error; 1508 if (res->type != RES_STRING) 1509 return EFTYPE; 1510 *result = res->u.stringval; 1511 return 0; 1512 } 1513 1514 int 1515 resource_query_string(int i, const char *resname, const char *value) 1516 { 1517 if (i < 0) 1518 i = 0; 1519 else 1520 i = i + 1; 1521 for (; i < devtab_count; i++) 1522 if (resource_match_string(i, resname, value) >= 0) 1523 return i; 1524 return -1; 1525 } 1526 1527 int 1528 resource_locate(int i, const char *resname) 1529 { 1530 if (i < 0) 1531 i = 0; 1532 else 1533 i = i + 1; 1534 for (; i < devtab_count; i++) 1535 if (!strcmp(devtab[i].name, resname)) 1536 return i; 1537 return -1; 1538 } 1539 1540 int 1541 resource_count(void) 1542 { 1543 return devtab_count; 1544 } 1545 1546 char * 1547 resource_query_name(int i) 1548 { 1549 return devtab[i].name; 1550 } 1551 1552 int 1553 resource_query_unit(int i) 1554 { 1555 return devtab[i].unit; 1556 } 1557 1558 static int 1559 resource_create(const char *name, int unit, const char *resname, 1560 resource_type type, struct config_resource **result) 1561 { 1562 int i, j; 1563 struct config_resource *res = NULL; 1564 1565 for (i = 0; i < devtab_count; i++) { 1566 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { 1567 res = devtab[i].resources; 1568 break; 1569 } 1570 } 1571 if (res == NULL) { 1572 i = resource_new_name(name, unit); 1573 if (i < 0) 1574 return ENOMEM; 1575 res = devtab[i].resources; 1576 } 1577 for (j = 0; j < devtab[i].resource_count; j++, res++) { 1578 if (!strcmp(res->name, resname)) { 1579 *result = res; 1580 return 0; 1581 } 1582 } 1583 j = resource_new_resname(i, resname, type); 1584 if (j < 0) 1585 return ENOMEM; 1586 res = &devtab[i].resources[j]; 1587 *result = res; 1588 return 0; 1589 } 1590 1591 int 1592 resource_set_int(const char *name, int unit, const char *resname, int value) 1593 { 1594 int error; 1595 struct config_resource *res; 1596 1597 error = resource_create(name, unit, resname, RES_INT, &res); 1598 if (error) 1599 return error; 1600 if (res->type != RES_INT) 1601 return EFTYPE; 1602 res->u.intval = value; 1603 return 0; 1604 } 1605 1606 int 1607 resource_set_long(const char *name, int unit, const char *resname, long value) 1608 { 1609 int error; 1610 struct config_resource *res; 1611 1612 error = resource_create(name, unit, resname, RES_LONG, &res); 1613 if (error) 1614 return error; 1615 if (res->type != RES_LONG) 1616 return EFTYPE; 1617 res->u.longval = value; 1618 return 0; 1619 } 1620 1621 int 1622 resource_set_string(const char *name, int unit, const char *resname, 1623 const char *value) 1624 { 1625 int error; 1626 struct config_resource *res; 1627 1628 error = resource_create(name, unit, resname, RES_STRING, &res); 1629 if (error) 1630 return error; 1631 if (res->type != RES_STRING) 1632 return EFTYPE; 1633 if (res->u.stringval) 1634 free(res->u.stringval, M_TEMP); 1635 res->u.stringval = malloc(strlen(value) + 1, M_TEMP, M_NOWAIT); 1636 if (res->u.stringval == NULL) 1637 return ENOMEM; 1638 strcpy(res->u.stringval, value); 1639 return 0; 1640 } 1641 1642 1643 static void 1644 resource_cfgload(void *dummy __unused) 1645 { 1646 struct config_resource *res, *cfgres; 1647 int i, j; 1648 int error; 1649 char *name, *resname; 1650 int unit; 1651 resource_type type; 1652 char *stringval; 1653 int config_devtab_count; 1654 1655 config_devtab_count = devtab_count; 1656 devtab = NULL; 1657 devtab_count = 0; 1658 1659 for (i = 0; i < config_devtab_count; i++) { 1660 name = config_devtab[i].name; 1661 unit = config_devtab[i].unit; 1662 1663 for (j = 0; j < config_devtab[i].resource_count; j++) { 1664 cfgres = config_devtab[i].resources; 1665 resname = cfgres[j].name; 1666 type = cfgres[j].type; 1667 error = resource_create(name, unit, resname, type, 1668 &res); 1669 if (error) { 1670 printf("create resource %s%d: error %d\n", 1671 name, unit, error); 1672 continue; 1673 } 1674 if (res->type != type) { 1675 printf("type mismatch %s%d: %d != %d\n", 1676 name, unit, res->type, type); 1677 continue; 1678 } 1679 switch (type) { 1680 case RES_INT: 1681 res->u.intval = cfgres[j].u.intval; 1682 break; 1683 case RES_LONG: 1684 res->u.longval = cfgres[j].u.longval; 1685 break; 1686 case RES_STRING: 1687 if (res->u.stringval) 1688 free(res->u.stringval, M_TEMP); 1689 stringval = cfgres[j].u.stringval; 1690 res->u.stringval = malloc(strlen(stringval) + 1, 1691 M_TEMP, M_NOWAIT); 1692 if (res->u.stringval == NULL) 1693 break; 1694 strcpy(res->u.stringval, stringval); 1695 break; 1696 default: 1697 panic("unknown resource type %d\n", type); 1698 } 1699 } 1700 } 1701 } 1702 SYSINIT(cfgload, SI_SUB_KMEM, SI_ORDER_ANY + 50, resource_cfgload, 0) 1703 1704 1705 /*======================================*/ 1706 /* 1707 * Some useful method implementations to make life easier for bus drivers. 1708 */ 1709 1710 void 1711 resource_list_init(struct resource_list *rl) 1712 { 1713 SLIST_INIT(rl); 1714 } 1715 1716 void 1717 resource_list_free(struct resource_list *rl) 1718 { 1719 struct resource_list_entry *rle; 1720 1721 while ((rle = SLIST_FIRST(rl)) != NULL) { 1722 if (rle->res) 1723 panic("resource_list_free: resource entry is busy"); 1724 SLIST_REMOVE_HEAD(rl, link); 1725 free(rle, M_BUS); 1726 } 1727 } 1728 1729 void 1730 resource_list_add(struct resource_list *rl, 1731 int type, int rid, 1732 u_long start, u_long end, u_long count) 1733 { 1734 struct resource_list_entry *rle; 1735 1736 rle = resource_list_find(rl, type, rid); 1737 if (!rle) { 1738 rle = malloc(sizeof(struct resource_list_entry), M_BUS, M_NOWAIT); 1739 if (!rle) 1740 panic("resource_list_add: can't record entry"); 1741 SLIST_INSERT_HEAD(rl, rle, link); 1742 rle->type = type; 1743 rle->rid = rid; 1744 rle->res = NULL; 1745 } 1746 1747 if (rle->res) 1748 panic("resource_list_add: resource entry is busy"); 1749 1750 rle->start = start; 1751 rle->end = end; 1752 rle->count = count; 1753 } 1754 1755 struct resource_list_entry* 1756 resource_list_find(struct resource_list *rl, 1757 int type, int rid) 1758 { 1759 struct resource_list_entry *rle; 1760 1761 SLIST_FOREACH(rle, rl, link) 1762 if (rle->type == type && rle->rid == rid) 1763 return rle; 1764 return NULL; 1765 } 1766 1767 void 1768 resource_list_delete(struct resource_list *rl, 1769 int type, int rid) 1770 { 1771 struct resource_list_entry *rle = resource_list_find(rl, type, rid); 1772 1773 if (rle) { 1774 SLIST_REMOVE(rl, rle, resource_list_entry, link); 1775 free(rle, M_BUS); 1776 } 1777 } 1778 1779 struct resource * 1780 resource_list_alloc(struct resource_list *rl, 1781 device_t bus, device_t child, 1782 int type, int *rid, 1783 u_long start, u_long end, 1784 u_long count, u_int flags) 1785 { 1786 struct resource_list_entry *rle = 0; 1787 int passthrough = (device_get_parent(child) != bus); 1788 int isdefault = (start == 0UL && end == ~0UL); 1789 1790 if (passthrough) { 1791 return BUS_ALLOC_RESOURCE(device_get_parent(bus), child, 1792 type, rid, 1793 start, end, count, flags); 1794 } 1795 1796 rle = resource_list_find(rl, type, *rid); 1797 1798 if (!rle) 1799 return 0; /* no resource of that type/rid */ 1800 if (rle->res) 1801 panic("resource_list_alloc: resource entry is busy"); 1802 1803 if (isdefault) { 1804 start = rle->start; 1805 count = max(count, rle->count); 1806 end = max(rle->end, start + count - 1); 1807 } 1808 1809 rle->res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child, 1810 type, rid, start, end, count, flags); 1811 1812 /* 1813 * Record the new range. 1814 */ 1815 if (rle->res) { 1816 rle->start = rman_get_start(rle->res); 1817 rle->end = rman_get_end(rle->res); 1818 rle->count = count; 1819 } 1820 1821 return rle->res; 1822 } 1823 1824 int 1825 resource_list_release(struct resource_list *rl, 1826 device_t bus, device_t child, 1827 int type, int rid, struct resource *res) 1828 { 1829 struct resource_list_entry *rle = 0; 1830 int passthrough = (device_get_parent(child) != bus); 1831 int error; 1832 1833 if (passthrough) { 1834 return BUS_RELEASE_RESOURCE(device_get_parent(bus), child, 1835 type, rid, res); 1836 } 1837 1838 rle = resource_list_find(rl, type, rid); 1839 1840 if (!rle) 1841 panic("resource_list_release: can't find resource"); 1842 if (!rle->res) 1843 panic("resource_list_release: resource entry is not busy"); 1844 1845 error = BUS_RELEASE_RESOURCE(device_get_parent(bus), child, 1846 type, rid, res); 1847 if (error) 1848 return error; 1849 1850 rle->res = NULL; 1851 return 0; 1852 } 1853 1854 int 1855 resource_list_print_type(struct resource_list *rl, const char *name, int type, 1856 const char *format) 1857 { 1858 struct resource_list_entry *rle; 1859 int printed, retval; 1860 1861 printed = 0; 1862 retval = 0; 1863 /* Yes, this is kinda cheating */ 1864 SLIST_FOREACH(rle, rl, link) { 1865 if (rle->type == type) { 1866 if (printed == 0) 1867 retval += printf(" %s ", name); 1868 else 1869 retval += printf(","); 1870 printed++; 1871 retval += printf(format, rle->start); 1872 if (rle->count > 1) { 1873 retval += printf("-"); 1874 retval += printf(format, rle->start + 1875 rle->count - 1); 1876 } 1877 } 1878 } 1879 return (retval); 1880 } 1881 1882 /* 1883 * Call DEVICE_IDENTIFY for each driver. 1884 */ 1885 int 1886 bus_generic_probe(device_t dev) 1887 { 1888 devclass_t dc = dev->devclass; 1889 driverlink_t dl; 1890 1891 for (dl = TAILQ_FIRST(&dc->drivers); dl; dl = TAILQ_NEXT(dl, link)) 1892 DEVICE_IDENTIFY(dl->driver, dev); 1893 1894 return 0; 1895 } 1896 1897 int 1898 bus_generic_attach(device_t dev) 1899 { 1900 device_t child; 1901 1902 for (child = TAILQ_FIRST(&dev->children); 1903 child; child = TAILQ_NEXT(child, link)) 1904 device_probe_and_attach(child); 1905 1906 return 0; 1907 } 1908 1909 int 1910 bus_generic_detach(device_t dev) 1911 { 1912 device_t child; 1913 int error; 1914 1915 if (dev->state != DS_ATTACHED) 1916 return EBUSY; 1917 1918 for (child = TAILQ_FIRST(&dev->children); 1919 child; child = TAILQ_NEXT(child, link)) 1920 if ((error = device_detach(child)) != 0) 1921 return error; 1922 1923 return 0; 1924 } 1925 1926 int 1927 bus_generic_shutdown(device_t dev) 1928 { 1929 device_t child; 1930 1931 for (child = TAILQ_FIRST(&dev->children); 1932 child; child = TAILQ_NEXT(child, link)) 1933 device_shutdown(child); 1934 1935 return 0; 1936 } 1937 1938 int 1939 bus_generic_suspend(device_t dev) 1940 { 1941 int error; 1942 device_t child, child2; 1943 1944 for (child = TAILQ_FIRST(&dev->children); 1945 child; child = TAILQ_NEXT(child, link)) { 1946 error = DEVICE_SUSPEND(child); 1947 if (error) { 1948 for (child2 = TAILQ_FIRST(&dev->children); 1949 child2 && child2 != child; 1950 child2 = TAILQ_NEXT(child2, link)) 1951 DEVICE_RESUME(child2); 1952 return (error); 1953 } 1954 } 1955 return 0; 1956 } 1957 1958 int 1959 bus_generic_resume(device_t dev) 1960 { 1961 device_t child; 1962 1963 for (child = TAILQ_FIRST(&dev->children); 1964 child; child = TAILQ_NEXT(child, link)) { 1965 DEVICE_RESUME(child); 1966 /* if resume fails, there's nothing we can usefully do... */ 1967 } 1968 return 0; 1969 } 1970 1971 int 1972 bus_print_child_header (device_t dev, device_t child) 1973 { 1974 int retval = 0; 1975 1976 if (device_get_desc(child)) { 1977 retval += device_printf(child, "<%s>", 1978 device_get_desc(child)); 1979 } else { 1980 retval += printf("%s", device_get_nameunit(child)); 1981 } 1982 1983 return (retval); 1984 } 1985 1986 int 1987 bus_print_child_footer (device_t dev, device_t child) 1988 { 1989 return(printf(" on %s\n", device_get_nameunit(dev))); 1990 } 1991 1992 int 1993 bus_generic_print_child(device_t dev, device_t child) 1994 { 1995 int retval = 0; 1996 1997 retval += bus_print_child_header(dev, child); 1998 retval += bus_print_child_footer(dev, child); 1999 2000 return (retval); 2001 } 2002 2003 int 2004 bus_generic_read_ivar(device_t dev, device_t child, int index, 2005 uintptr_t * result) 2006 { 2007 return ENOENT; 2008 } 2009 2010 int 2011 bus_generic_write_ivar(device_t dev, device_t child, int index, 2012 uintptr_t value) 2013 { 2014 return ENOENT; 2015 } 2016 2017 void 2018 bus_generic_driver_added(device_t dev, driver_t *driver) 2019 { 2020 device_t child; 2021 2022 DEVICE_IDENTIFY(driver, dev); 2023 for (child = TAILQ_FIRST(&dev->children); 2024 child; child = TAILQ_NEXT(child, link)) 2025 if (child->state == DS_NOTPRESENT) 2026 device_probe_and_attach(child); 2027 } 2028 2029 int 2030 bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq, 2031 int flags, driver_intr_t *intr, void *arg, 2032 void **cookiep) 2033 { 2034 /* Propagate up the bus hierarchy until someone handles it. */ 2035 if (dev->parent) 2036 return (BUS_SETUP_INTR(dev->parent, child, irq, flags, 2037 intr, arg, cookiep)); 2038 else 2039 return (EINVAL); 2040 } 2041 2042 int 2043 bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq, 2044 void *cookie) 2045 { 2046 /* Propagate up the bus hierarchy until someone handles it. */ 2047 if (dev->parent) 2048 return (BUS_TEARDOWN_INTR(dev->parent, child, irq, cookie)); 2049 else 2050 return (EINVAL); 2051 } 2052 2053 struct resource * 2054 bus_generic_alloc_resource(device_t dev, device_t child, int type, int *rid, 2055 u_long start, u_long end, u_long count, u_int flags) 2056 { 2057 /* Propagate up the bus hierarchy until someone handles it. */ 2058 if (dev->parent) 2059 return (BUS_ALLOC_RESOURCE(dev->parent, child, type, rid, 2060 start, end, count, flags)); 2061 else 2062 return (NULL); 2063 } 2064 2065 int 2066 bus_generic_release_resource(device_t dev, device_t child, int type, int rid, 2067 struct resource *r) 2068 { 2069 /* Propagate up the bus hierarchy until someone handles it. */ 2070 if (dev->parent) 2071 return (BUS_RELEASE_RESOURCE(dev->parent, child, type, rid, 2072 r)); 2073 else 2074 return (EINVAL); 2075 } 2076 2077 int 2078 bus_generic_activate_resource(device_t dev, device_t child, int type, int rid, 2079 struct resource *r) 2080 { 2081 /* Propagate up the bus hierarchy until someone handles it. */ 2082 if (dev->parent) 2083 return (BUS_ACTIVATE_RESOURCE(dev->parent, child, type, rid, 2084 r)); 2085 else 2086 return (EINVAL); 2087 } 2088 2089 int 2090 bus_generic_deactivate_resource(device_t dev, device_t child, int type, 2091 int rid, struct resource *r) 2092 { 2093 /* Propagate up the bus hierarchy until someone handles it. */ 2094 if (dev->parent) 2095 return (BUS_DEACTIVATE_RESOURCE(dev->parent, child, type, rid, 2096 r)); 2097 else 2098 return (EINVAL); 2099 } 2100 2101 /* 2102 * Some convenience functions to make it easier for drivers to use the 2103 * resource-management functions. All these really do is hide the 2104 * indirection through the parent's method table, making for slightly 2105 * less-wordy code. In the future, it might make sense for this code 2106 * to maintain some sort of a list of resources allocated by each device. 2107 */ 2108 struct resource * 2109 bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end, 2110 u_long count, u_int flags) 2111 { 2112 if (dev->parent == 0) 2113 return (0); 2114 return (BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end, 2115 count, flags)); 2116 } 2117 2118 int 2119 bus_activate_resource(device_t dev, int type, int rid, struct resource *r) 2120 { 2121 if (dev->parent == 0) 2122 return (EINVAL); 2123 return (BUS_ACTIVATE_RESOURCE(dev->parent, dev, type, rid, r)); 2124 } 2125 2126 int 2127 bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r) 2128 { 2129 if (dev->parent == 0) 2130 return (EINVAL); 2131 return (BUS_DEACTIVATE_RESOURCE(dev->parent, dev, type, rid, r)); 2132 } 2133 2134 int 2135 bus_release_resource(device_t dev, int type, int rid, struct resource *r) 2136 { 2137 if (dev->parent == 0) 2138 return (EINVAL); 2139 return (BUS_RELEASE_RESOURCE(dev->parent, dev, 2140 type, rid, r)); 2141 } 2142 2143 int 2144 bus_setup_intr(device_t dev, struct resource *r, int flags, 2145 driver_intr_t handler, void *arg, void **cookiep) 2146 { 2147 if (dev->parent == 0) 2148 return (EINVAL); 2149 return (BUS_SETUP_INTR(dev->parent, dev, r, flags, 2150 handler, arg, cookiep)); 2151 } 2152 2153 int 2154 bus_teardown_intr(device_t dev, struct resource *r, void *cookie) 2155 { 2156 if (dev->parent == 0) 2157 return (EINVAL); 2158 return (BUS_TEARDOWN_INTR(dev->parent, dev, r, cookie)); 2159 } 2160 2161 int 2162 bus_set_resource(device_t dev, int type, int rid, 2163 u_long start, u_long count) 2164 { 2165 return BUS_SET_RESOURCE(device_get_parent(dev), dev, type, rid, 2166 start, count); 2167 } 2168 2169 int 2170 bus_get_resource(device_t dev, int type, int rid, 2171 u_long *startp, u_long *countp) 2172 { 2173 return BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid, 2174 startp, countp); 2175 } 2176 2177 u_long 2178 bus_get_resource_start(device_t dev, int type, int rid) 2179 { 2180 u_long start, count; 2181 int error; 2182 2183 error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid, 2184 &start, &count); 2185 if (error) 2186 return 0; 2187 return start; 2188 } 2189 2190 u_long 2191 bus_get_resource_count(device_t dev, int type, int rid) 2192 { 2193 u_long start, count; 2194 int error; 2195 2196 error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid, 2197 &start, &count); 2198 if (error) 2199 return 0; 2200 return count; 2201 } 2202 2203 void 2204 bus_delete_resource(device_t dev, int type, int rid) 2205 { 2206 BUS_DELETE_RESOURCE(device_get_parent(dev), dev, type, rid); 2207 } 2208 2209 static int 2210 root_print_child(device_t dev, device_t child) 2211 { 2212 return (0); 2213 } 2214 2215 static int 2216 root_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg, 2217 void **cookiep) 2218 { 2219 /* 2220 * If an interrupt mapping gets to here something bad has happened. 2221 */ 2222 panic("root_setup_intr"); 2223 } 2224 2225 static device_method_t root_methods[] = { 2226 /* Device interface */ 2227 DEVMETHOD(device_shutdown, bus_generic_shutdown), 2228 DEVMETHOD(device_suspend, bus_generic_suspend), 2229 DEVMETHOD(device_resume, bus_generic_resume), 2230 2231 /* Bus interface */ 2232 DEVMETHOD(bus_print_child, root_print_child), 2233 DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), 2234 DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), 2235 DEVMETHOD(bus_setup_intr, root_setup_intr), 2236 2237 { 0, 0 } 2238 }; 2239 2240 static driver_t root_driver = { 2241 "root", 2242 root_methods, 2243 1, /* no softc */ 2244 }; 2245 2246 device_t root_bus; 2247 devclass_t root_devclass; 2248 2249 static int 2250 root_bus_module_handler(module_t mod, int what, void* arg) 2251 { 2252 switch (what) { 2253 case MOD_LOAD: 2254 compile_methods(&root_driver); 2255 root_bus = make_device(NULL, "root", 0); 2256 root_bus->desc = "System root bus"; 2257 root_bus->ops = root_driver.ops; 2258 root_bus->driver = &root_driver; 2259 root_bus->state = DS_ATTACHED; 2260 root_devclass = devclass_find_internal("root", FALSE); 2261 return 0; 2262 2263 case MOD_SHUTDOWN: 2264 device_shutdown(root_bus); 2265 return 0; 2266 } 2267 2268 return 0; 2269 } 2270 2271 static moduledata_t root_bus_mod = { 2272 "rootbus", 2273 root_bus_module_handler, 2274 0 2275 }; 2276 DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 2277 2278 void 2279 root_bus_configure(void) 2280 { 2281 device_t dev; 2282 2283 PDEBUG((".")); 2284 2285 for (dev = TAILQ_FIRST(&root_bus->children); dev; 2286 dev = TAILQ_NEXT(dev, link)) { 2287 device_probe_and_attach(dev); 2288 } 2289 } 2290 2291 int 2292 driver_module_handler(module_t mod, int what, void *arg) 2293 { 2294 int error, i; 2295 struct driver_module_data *dmd; 2296 devclass_t bus_devclass; 2297 2298 dmd = (struct driver_module_data *)arg; 2299 bus_devclass = devclass_find_internal(dmd->dmd_busname, TRUE); 2300 error = 0; 2301 2302 switch (what) { 2303 case MOD_LOAD: 2304 if (dmd->dmd_chainevh) 2305 error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); 2306 2307 for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { 2308 PDEBUG(("Loading module: driver %s on bus %s", 2309 DRIVERNAME(dmd->dmd_drivers[i]), 2310 dmd->dmd_busname)); 2311 error = devclass_add_driver(bus_devclass, 2312 dmd->dmd_drivers[i]); 2313 } 2314 if (error) 2315 break; 2316 2317 /* 2318 * The drivers loaded in this way are assumed to all 2319 * implement the same devclass. 2320 */ 2321 *dmd->dmd_devclass = 2322 devclass_find_internal(dmd->dmd_drivers[0]->name, 2323 TRUE); 2324 break; 2325 2326 case MOD_UNLOAD: 2327 for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { 2328 PDEBUG(("Unloading module: driver %s from bus %s", 2329 DRIVERNAME(dmd->dmd_drivers[i]), 2330 dmd->dmd_busname)); 2331 error = devclass_delete_driver(bus_devclass, 2332 dmd->dmd_drivers[i]); 2333 } 2334 2335 if (!error && dmd->dmd_chainevh) 2336 error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); 2337 break; 2338 } 2339 2340 return (error); 2341 } 2342 2343 #ifdef BUS_DEBUG 2344 2345 /* the _short versions avoid iteration by not calling anything that prints 2346 * more than oneliners. I love oneliners. 2347 */ 2348 2349 static void 2350 print_method_list(device_method_t *m, int indent) 2351 { 2352 int i; 2353 2354 if (!m) 2355 return; 2356 2357 for (i = 0; m->desc; i++, m++) 2358 indentprintf(("method %d: %s, offset=%d\n", 2359 i, m->desc->name, m->desc->offset)); 2360 } 2361 2362 static void 2363 print_device_ops(device_ops_t ops, int indent) 2364 { 2365 int i; 2366 int count = 0; 2367 2368 if (!ops) 2369 return; 2370 2371 /* we present a list of the methods that are pointing to the 2372 * error_method, but ignore the 0'th elements; it is always 2373 * error_method. 2374 */ 2375 for (i = 1; i < ops->maxoffset; i++) { 2376 if (ops->methods[i] == error_method) { 2377 if (count == 0) 2378 indentprintf(("error_method:")); 2379 printf(" %d", i); 2380 count++; 2381 } 2382 } 2383 if (count) 2384 printf("\n"); 2385 2386 indentprintf(("(%d method%s, %d valid, %d error_method%s)\n", 2387 ops->maxoffset-1, (ops->maxoffset-1 == 1? "":"s"), 2388 ops->maxoffset-1-count, 2389 count, (count == 1? "":"'s"))); 2390 } 2391 2392 static void 2393 print_device_short(device_t dev, int indent) 2394 { 2395 if (!dev) 2396 return; 2397 2398 indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%s,%sivars,%ssoftc,busy=%d\n", 2399 dev->unit, dev->desc, 2400 (dev->parent? "":"no "), 2401 (TAILQ_EMPTY(&dev->children)? "no ":""), 2402 (dev->flags&DF_ENABLED? "enabled,":"disabled,"), 2403 (dev->flags&DF_FIXEDCLASS? "fixed,":""), 2404 (dev->flags&DF_WILDCARD? "wildcard,":""), 2405 (dev->flags&DF_DESCMALLOCED? "descmalloced,":""), 2406 (dev->ivars? "":"no "), 2407 (dev->softc? "":"no "), 2408 dev->busy)); 2409 } 2410 2411 static void 2412 print_device(device_t dev, int indent) 2413 { 2414 if (!dev) 2415 return; 2416 2417 print_device_short(dev, indent); 2418 2419 indentprintf(("Parent:\n")); 2420 print_device_short(dev->parent, indent+1); 2421 indentprintf(("Methods:\n")); 2422 print_device_ops(dev->ops, indent+1); 2423 indentprintf(("Driver:\n")); 2424 print_driver_short(dev->driver, indent+1); 2425 indentprintf(("Devclass:\n")); 2426 print_devclass_short(dev->devclass, indent+1); 2427 } 2428 2429 void 2430 print_device_tree_short(device_t dev, int indent) 2431 /* print the device and all its children (indented) */ 2432 { 2433 device_t child; 2434 2435 if (!dev) 2436 return; 2437 2438 print_device_short(dev, indent); 2439 2440 for (child = TAILQ_FIRST(&dev->children); child; 2441 child = TAILQ_NEXT(child, link)) 2442 print_device_tree_short(child, indent+1); 2443 } 2444 2445 void 2446 print_device_tree(device_t dev, int indent) 2447 /* print the device and all its children (indented) */ 2448 { 2449 device_t child; 2450 2451 if (!dev) 2452 return; 2453 2454 print_device(dev, indent); 2455 2456 for (child = TAILQ_FIRST(&dev->children); child; 2457 child = TAILQ_NEXT(child, link)) 2458 print_device_tree(child, indent+1); 2459 } 2460 2461 static void 2462 print_driver_short(driver_t *driver, int indent) 2463 { 2464 if (!driver) 2465 return; 2466 2467 indentprintf(("driver %s: softc size = %d\n", 2468 driver->name, driver->softc)); 2469 } 2470 2471 static void 2472 print_driver(driver_t *driver, int indent) 2473 { 2474 if (!driver) 2475 return; 2476 2477 print_driver_short(driver, indent); 2478 indentprintf(("Methods:\n")); 2479 print_method_list(driver->methods, indent+1); 2480 indentprintf(("Operations:\n")); 2481 print_device_ops(driver->ops, indent+1); 2482 } 2483 2484 2485 static void 2486 print_driver_list(driver_list_t drivers, int indent) 2487 { 2488 driverlink_t driver; 2489 2490 for (driver = TAILQ_FIRST(&drivers); driver; 2491 driver = TAILQ_NEXT(driver, link)) 2492 print_driver(driver->driver, indent); 2493 } 2494 2495 static void 2496 print_devclass_short(devclass_t dc, int indent) 2497 { 2498 if ( !dc ) 2499 return; 2500 2501 indentprintf(("devclass %s: max units = %d\n", 2502 dc->name, dc->maxunit)); 2503 } 2504 2505 static void 2506 print_devclass(devclass_t dc, int indent) 2507 { 2508 int i; 2509 2510 if ( !dc ) 2511 return; 2512 2513 print_devclass_short(dc, indent); 2514 indentprintf(("Drivers:\n")); 2515 print_driver_list(dc->drivers, indent+1); 2516 2517 indentprintf(("Devices:\n")); 2518 for (i = 0; i < dc->maxunit; i++) 2519 if (dc->devices[i]) 2520 print_device(dc->devices[i], indent+1); 2521 } 2522 2523 void 2524 print_devclass_list_short(void) 2525 { 2526 devclass_t dc; 2527 2528 printf("Short listing of devclasses, drivers & devices:\n"); 2529 for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link)) 2530 print_devclass_short(dc, 0); 2531 } 2532 2533 void 2534 print_devclass_list(void) 2535 { 2536 devclass_t dc; 2537 2538 printf("Full listing of devclasses, drivers & devices:\n"); 2539 for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link)) 2540 print_devclass(dc, 0); 2541 } 2542 2543 #endif 2544