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 * $Id: subr_bus.c,v 1.12 1998/12/12 11:30:04 n_hibma Exp $ 27 */ 28 29 #include <sys/param.h> 30 #include <sys/queue.h> 31 #include <sys/malloc.h> 32 #include <sys/kernel.h> 33 #include <sys/module.h> 34 #include <sys/bus_private.h> 35 #include <sys/systm.h> 36 37 #include "opt_bus.h" 38 39 #ifdef BUS_DEBUG 40 #define PDEBUG(a) (printf(__FUNCTION__ ":%d: ", __LINE__), printf a, printf("\n")) 41 #define DEVICENAME(d) ((d)? device_get_name(d): "no device") 42 #define DRIVERNAME(d) ((d)? d->name : "no driver") 43 #define DEVCLANAME(d) ((d)? d->name : "no devclass") 44 45 /* Produce the indenting, indent*2 spaces plus a '.' ahead of that to 46 * prevent syslog from deleting initial spaces 47 */ 48 #define indentprintf(p) do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf(" "); printf p ; } while(0) 49 50 static void print_method_list(device_method_t *m, int indent); 51 static void print_device_ops(device_ops_t ops, int indent); 52 static void print_device_short(device_t dev, int indent); 53 static void print_device(device_t dev, int indent); 54 void print_device_tree_short(device_t dev, int indent); 55 void print_device_tree(device_t dev, int indent); 56 static void print_driver_short(driver_t *driver, int indent); 57 static void print_driver(driver_t *driver, int indent); 58 static void print_driver_list(driver_list_t drivers, int indent); 59 static void print_devclass_short(devclass_t dc, int indent); 60 static void print_devclass(devclass_t dc, int indent); 61 void print_devclass_list_short(void); 62 void print_devclass_list(void); 63 64 #else 65 /* Make the compiler ignore the function calls */ 66 #define PDEBUG(a) /* nop */ 67 #define DEVICENAME(d) /* nop */ 68 #define DRIVERNAME(d) /* nop */ 69 #define DEVCLANAME(d) /* nop */ 70 71 #define print_method_list(m,i) /* nop */ 72 #define print_device_ops(o,i) /* nop */ 73 #define print_device_short(d,i) /* nop */ 74 #define print_device(d,i) /* nop */ 75 #define print_device_tree_short(d,i) /* nop */ 76 #define print_device_tree(d,i) /* nop */ 77 #define print_driver_short(d,i) /* nop */ 78 #define print_driver(d,i) /* nop */ 79 #define print_driver_list(d,i) /* nop */ 80 #define print_devclass_short(d,i) /* nop */ 81 #define print_devclass(d,i) /* nop */ 82 #define print_devclass_list_short() /* nop */ 83 #define print_devclass_list() /* nop */ 84 #endif 85 86 87 /* 88 * Method table handling 89 */ 90 static int next_method_offset = 1; 91 static int methods_count = 0; 92 static int methods_size = 0; 93 94 struct method { 95 int offset; 96 char* name; 97 }; 98 99 static struct method *methods = 0; 100 101 static void 102 register_method(struct device_op_desc *desc) 103 { 104 int i; 105 struct method* m; 106 107 for (i = 0; i < methods_count; i++) 108 if (!strcmp(methods[i].name, desc->name)) { 109 desc->offset = methods[i].offset; 110 PDEBUG(("methods[%d] has the same name, %s, with offset %d", 111 i, desc->name, desc->offset)); 112 return; 113 } 114 115 if (methods_count == methods_size) { 116 struct method* p; 117 118 methods_size += 10; 119 p = (struct method*) malloc(methods_size * sizeof(struct method), 120 M_DEVBUF, M_NOWAIT); 121 if (!p) 122 panic("register_method: out of memory"); 123 if (methods) { 124 bcopy(methods, p, methods_count * sizeof(struct method)); 125 free(methods, M_DEVBUF); 126 } 127 methods = p; 128 } 129 m = &methods[methods_count++]; 130 m->name = malloc(strlen(desc->name) + 1, M_DEVBUF, M_NOWAIT); 131 if (!m->name) 132 panic("register_method: out of memory"); 133 strcpy(m->name, desc->name); 134 desc->offset = m->offset = next_method_offset++; 135 } 136 137 static int error_method(void) 138 { 139 return ENXIO; 140 } 141 142 static struct device_ops null_ops = { 143 1, 144 { error_method } 145 }; 146 147 static void 148 compile_methods(driver_t *driver) 149 { 150 device_ops_t ops; 151 struct device_method *m; 152 int i; 153 154 /* 155 * First register any methods which need it. 156 */ 157 for (i = 0, m = driver->methods; m->desc; i++, m++) 158 if (!m->desc->offset) 159 register_method(m->desc); 160 else 161 PDEBUG(("offset not equal to zero, method desc %d left as is", i)); 162 163 /* 164 * Then allocate the compiled op table. 165 */ 166 ops = malloc(sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t), 167 M_DEVBUF, M_NOWAIT); 168 if (!ops) 169 panic("compile_methods: out of memory"); 170 171 ops->maxoffset = next_method_offset; 172 for (i = 0; i < next_method_offset; i++) 173 ops->methods[i] = error_method; 174 for (i = 0, m = driver->methods; m->desc; i++, m++) 175 ops->methods[m->desc->offset] = m->func; 176 PDEBUG(("%s has %d method%s, wasting %d bytes", 177 DRIVERNAME(driver), i, (i==1?"":"s"), 178 (next_method_offset-i)*sizeof(devop_t))); 179 180 driver->ops = ops; 181 } 182 183 /* 184 * Devclass implementation 185 */ 186 187 static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses); 188 189 static devclass_t 190 devclass_find_internal(const char *classname, int create) 191 { 192 devclass_t dc; 193 194 PDEBUG(("looking for %s", classname)); 195 if (!classname) 196 return NULL; 197 198 for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link)) 199 if (!strcmp(dc->name, classname)) 200 return dc; 201 202 PDEBUG(("%s not found%s", classname, (create? ", creating": ""))); 203 if (create) { 204 dc = malloc(sizeof(struct devclass) + strlen(classname) + 1, 205 M_DEVBUF, M_NOWAIT); 206 if (!dc) 207 return NULL; 208 dc->name = (char*) (dc + 1); 209 strcpy(dc->name, classname); 210 dc->devices = NULL; 211 dc->maxunit = 0; 212 dc->nextunit = 0; 213 TAILQ_INIT(&dc->drivers); 214 TAILQ_INSERT_TAIL(&devclasses, dc, link); 215 } 216 217 return dc; 218 } 219 220 devclass_t 221 devclass_find(const char *classname) 222 { 223 return devclass_find_internal(classname, FALSE); 224 } 225 226 int 227 devclass_add_driver(devclass_t dc, driver_t *driver) 228 { 229 PDEBUG(("%s", DRIVERNAME(driver))); 230 /* 231 * Compile the drivers methods. 232 */ 233 compile_methods(driver); 234 235 /* 236 * Make sure the devclass which the driver is implementing exists. 237 */ 238 devclass_find_internal(driver->name, TRUE); 239 240 TAILQ_INSERT_TAIL(&dc->drivers, driver, link); 241 242 return 0; 243 } 244 245 int 246 devclass_delete_driver(devclass_t busclass, driver_t *driver) 247 { 248 devclass_t dc = devclass_find(driver->name); 249 device_t dev; 250 int i; 251 int error; 252 253 PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass))); 254 255 if (!dc) 256 return 0; 257 258 /* 259 * Disassociate from any devices. We iterate through all the 260 * devices in the devclass of the driver and detach any which are 261 * using the driver. 262 */ 263 for (i = 0; i < dc->maxunit; i++) { 264 if (dc->devices[i]) { 265 dev = dc->devices[i]; 266 if (dev->driver == driver) { 267 if (error = device_detach(dev)) 268 return error; 269 device_set_driver(dev, NULL); 270 } 271 } 272 } 273 274 TAILQ_REMOVE(&busclass->drivers, driver, link); 275 return 0; 276 } 277 278 driver_t * 279 devclass_find_driver(devclass_t dc, const char *classname) 280 { 281 driver_t *driver; 282 283 PDEBUG(("%s in devclass %s", classname, DEVCLANAME(dc))); 284 285 for (driver = TAILQ_FIRST(&dc->drivers); driver; 286 driver = TAILQ_NEXT(driver, link)) { 287 if (!strcmp(driver->name, classname)) 288 return driver; 289 } 290 291 PDEBUG(("not found")); 292 return NULL; 293 } 294 295 const char * 296 devclass_get_name(devclass_t dc) 297 { 298 return dc->name; 299 } 300 301 device_t 302 devclass_get_device(devclass_t dc, int unit) 303 { 304 if (unit < 0 || unit >= dc->maxunit) 305 return NULL; 306 return dc->devices[unit]; 307 } 308 309 void * 310 devclass_get_softc(devclass_t dc, int unit) 311 { 312 device_t dev; 313 314 if (unit < 0 || unit >= dc->maxunit) 315 return NULL; 316 dev = dc->devices[unit]; 317 if (!dev || dev->state < DS_ATTACHED) 318 return NULL; 319 return dev->softc; 320 } 321 322 int 323 devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp) 324 { 325 int i; 326 int count; 327 device_t *list; 328 329 count = 0; 330 for (i = 0; i < dc->maxunit; i++) 331 if (dc->devices[i]) 332 count++; 333 334 list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT); 335 if (!list) 336 return ENOMEM; 337 338 count = 0; 339 for (i = 0; i < dc->maxunit; i++) 340 if (dc->devices[i]) { 341 list[count] = dc->devices[i]; 342 count++; 343 } 344 345 *devlistp = list; 346 *devcountp = count; 347 348 return 0; 349 } 350 351 int 352 devclass_get_maxunit(devclass_t dc) 353 { 354 return dc->maxunit; 355 } 356 357 static int 358 devclass_alloc_unit(devclass_t dc, int *unitp) 359 { 360 int unit = *unitp; 361 362 PDEBUG(("unit %d in devclass %s", unit, DEVCLANAME(dc))); 363 364 /* 365 * If we have been given a wired unit number, check for existing 366 * device. 367 */ 368 if (unit != -1) { 369 device_t dev; 370 dev = devclass_get_device(dc, unit); 371 if (dev) { 372 printf("devclass_alloc_unit: %s%d already exists, using next available unit number\n", dc->name, unit); 373 unit = -1; 374 } 375 } 376 377 if (unit == -1) { 378 unit = dc->nextunit; 379 dc->nextunit++; 380 } else if (dc->nextunit <= unit) 381 dc->nextunit = unit + 1; 382 383 if (unit >= dc->maxunit) { 384 device_t *newlist; 385 int newsize; 386 387 newsize = (dc->maxunit ? 2 * dc->maxunit 388 : MINALLOCSIZE / sizeof(device_t)); 389 newlist = malloc(sizeof(device_t) * newsize, M_DEVBUF, M_NOWAIT); 390 if (!newlist) 391 return ENOMEM; 392 bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit); 393 bzero(newlist + dc->maxunit, 394 sizeof(device_t) * (newsize - dc->maxunit)); 395 if (dc->devices) 396 free(dc->devices, M_DEVBUF); 397 dc->devices = newlist; 398 dc->maxunit = newsize; 399 } 400 PDEBUG(("now: unit %d in devclass %s", unit, DEVCLANAME(dc))); 401 402 *unitp = unit; 403 return 0; 404 } 405 406 static int 407 devclass_add_device(devclass_t dc, device_t dev) 408 { 409 int error; 410 411 PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc))); 412 413 if (error = devclass_alloc_unit(dc, &dev->unit)) 414 return error; 415 dc->devices[dev->unit] = dev; 416 dev->devclass = dc; 417 return 0; 418 } 419 420 static int 421 devclass_delete_device(devclass_t dc, device_t dev) 422 { 423 if (!dc || !dev) 424 return 0; 425 426 PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc))); 427 428 if (dev->devclass != dc 429 || dc->devices[dev->unit] != dev) 430 panic("devclass_delete_device: inconsistent device class"); 431 dc->devices[dev->unit] = NULL; 432 if (dev->flags & DF_WILDCARD) 433 dev->unit = -1; 434 dev->devclass = NULL; 435 while (dc->nextunit > 0 && dc->devices[dc->nextunit - 1] == NULL) 436 dc->nextunit--; 437 return 0; 438 } 439 440 static device_t 441 make_device(device_t parent, const char *name, 442 int unit, void *ivars) 443 { 444 device_t dev; 445 devclass_t dc; 446 int error; 447 448 PDEBUG(("%s at %s as unit %d with%s ivars", 449 name, DEVICENAME(parent), unit, (ivars? "":"out"))); 450 451 if (name) { 452 dc = devclass_find_internal(name, TRUE); 453 if (!dc) { 454 printf("make_device: can't find device class %s\n", name); 455 return NULL; 456 } 457 458 if (error = devclass_alloc_unit(dc, &unit)) 459 return NULL; 460 } else 461 dc = NULL; 462 463 dev = malloc(sizeof(struct device), M_DEVBUF, M_NOWAIT); 464 if (!dev) 465 return 0; 466 467 dev->parent = parent; 468 TAILQ_INIT(&dev->children); 469 dev->ops = &null_ops; 470 dev->driver = NULL; 471 dev->devclass = dc; 472 dev->unit = unit; 473 dev->desc = NULL; 474 dev->busy = 0; 475 dev->flags = DF_ENABLED; 476 if (unit == -1) 477 dev->flags |= DF_WILDCARD; 478 if (name) 479 dev->flags |= DF_FIXEDCLASS; 480 dev->ivars = ivars; 481 dev->softc = NULL; 482 483 if (dc) 484 dc->devices[unit] = dev; 485 486 dev->state = DS_NOTPRESENT; 487 488 return dev; 489 } 490 491 static void 492 device_print_child(device_t dev, device_t child) 493 { 494 printf("%s%d", device_get_name(child), device_get_unit(child)); 495 if (device_is_alive(child)) { 496 if (device_get_desc(child)) 497 printf(": <%s>", device_get_desc(child)); 498 BUS_PRINT_CHILD(dev, child); 499 } else 500 printf(" not found"); 501 printf("\n"); 502 } 503 504 device_t 505 device_add_child(device_t dev, const char *name, int unit, void *ivars) 506 { 507 device_t child; 508 509 PDEBUG(("%s at %s as unit %d with%s ivars", 510 name, DEVICENAME(dev), unit, (ivars? "":"out"))); 511 512 child = make_device(dev, name, unit, ivars); 513 514 if (child) 515 TAILQ_INSERT_TAIL(&dev->children, child, link); 516 else 517 PDEBUG(("%s failed", name)); 518 519 return child; 520 } 521 522 device_t 523 device_add_child_after(device_t dev, device_t place, const char *name, 524 int unit, void *ivars) 525 { 526 device_t child; 527 528 PDEBUG(("%s at %s after %s as unit %d with%s ivars", 529 name, DEVICENAME(dev), DEVICENAME(place), unit, (ivars? "":"out"))); 530 531 child = make_device(dev, name, unit, ivars); 532 533 if (place) { 534 TAILQ_INSERT_AFTER(&dev->children, place, dev, link); 535 } else { 536 TAILQ_INSERT_HEAD(&dev->children, dev, link); 537 } 538 539 return child; 540 } 541 542 int 543 device_delete_child(device_t dev, device_t child) 544 { 545 int error; 546 device_t grandchild; 547 548 PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev))); 549 550 /* remove children first */ 551 while ( (grandchild = TAILQ_FIRST(&child->children)) ) { 552 error = device_delete_child(child, grandchild); 553 if (error) 554 return error; 555 } 556 557 if (error = device_detach(child)) 558 return error; 559 if (child->devclass) 560 devclass_delete_device(child->devclass, child); 561 TAILQ_REMOVE(&dev->children, child, link); 562 free(child, M_DEVBUF); 563 564 return 0; 565 } 566 567 /* 568 * Find only devices attached to this bus. 569 */ 570 device_t 571 device_find_child(device_t dev, const char *classname, int unit) 572 { 573 devclass_t dc; 574 device_t child; 575 576 dc = devclass_find(classname); 577 if (!dc) 578 return NULL; 579 580 child = devclass_get_device(dc, unit); 581 if (child && child->parent == dev) 582 return child; 583 return NULL; 584 } 585 586 static driver_t * 587 first_matching_driver(devclass_t dc, device_t dev) 588 { 589 if (dev->devclass) 590 return devclass_find_driver(dc, dev->devclass->name); 591 else 592 return TAILQ_FIRST(&dc->drivers); 593 } 594 595 static driver_t * 596 next_matching_driver(devclass_t dc, device_t dev, driver_t *last) 597 { 598 if (dev->devclass) { 599 driver_t *driver; 600 for (driver = TAILQ_NEXT(last, link); driver; 601 driver = TAILQ_NEXT(driver, link)) 602 if (!strcmp(dev->devclass->name, driver->name)) 603 return driver; 604 return NULL; 605 } else 606 return TAILQ_NEXT(last, link); 607 } 608 609 static int 610 device_probe_child(device_t dev, device_t child) 611 { 612 devclass_t dc; 613 driver_t *driver; 614 615 dc = dev->devclass; 616 if (dc == NULL) 617 panic("device_probe_child: parent device has no devclass"); 618 619 if (child->state == DS_ALIVE) 620 return 0; 621 622 for (driver = first_matching_driver(dc, child); 623 driver; 624 driver = next_matching_driver(dc, child, driver)) { 625 PDEBUG(("Trying %s", DRIVERNAME(driver))); 626 device_set_driver(child, driver); 627 if (DEVICE_PROBE(child) == 0) { 628 if (!child->devclass) 629 device_set_devclass(child, driver->name); 630 child->state = DS_ALIVE; 631 return 0; 632 } 633 } 634 635 return ENXIO; 636 } 637 638 device_t 639 device_get_parent(device_t dev) 640 { 641 return dev->parent; 642 } 643 644 driver_t * 645 device_get_driver(device_t dev) 646 { 647 return dev->driver; 648 } 649 650 devclass_t 651 device_get_devclass(device_t dev) 652 { 653 return dev->devclass; 654 } 655 656 const char * 657 device_get_name(device_t dev) 658 { 659 if (dev->devclass) 660 return devclass_get_name(dev->devclass); 661 return NULL; 662 } 663 664 int 665 device_get_unit(device_t dev) 666 { 667 return dev->unit; 668 } 669 670 const char * 671 device_get_desc(device_t dev) 672 { 673 return dev->desc; 674 } 675 676 void 677 device_print_prettyname(device_t dev) 678 { 679 const char *name = device_get_name(dev); 680 681 if (name == 0) 682 name = "(no driver assigned)"; 683 printf("%s%d: ", name, device_get_unit(dev)); 684 } 685 686 void 687 device_set_desc(device_t dev, const char* desc) 688 { 689 dev->desc = desc; 690 } 691 692 void * 693 device_get_softc(device_t dev) 694 { 695 return dev->softc; 696 } 697 698 void * 699 device_get_ivars(device_t dev) 700 { 701 return dev->ivars; 702 } 703 704 device_state_t 705 device_get_state(device_t dev) 706 { 707 return dev->state; 708 } 709 710 void 711 device_enable(device_t dev) 712 { 713 dev->flags |= DF_ENABLED; 714 } 715 716 void 717 device_disable(device_t dev) 718 { 719 dev->flags &= ~DF_ENABLED; 720 } 721 722 void 723 device_busy(device_t dev) 724 { 725 if (dev->state < DS_ATTACHED) 726 panic("device_busy: called for unattached device"); 727 if (dev->busy == 0 && dev->parent) 728 device_busy(dev->parent); 729 dev->busy++; 730 dev->state = DS_BUSY; 731 } 732 733 void 734 device_unbusy(device_t dev) 735 { 736 if (dev->state != DS_BUSY) 737 panic("device_unbusy: called for non-busy device"); 738 dev->busy--; 739 if (dev->busy == 0) { 740 if (dev->parent) 741 device_unbusy(dev->parent); 742 dev->state = DS_ATTACHED; 743 } 744 } 745 746 int 747 device_is_enabled(device_t dev) 748 { 749 return (dev->flags & DF_ENABLED) != 0; 750 } 751 752 int 753 device_is_alive(device_t dev) 754 { 755 return dev->state >= DS_ALIVE; 756 } 757 758 int 759 device_set_devclass(device_t dev, const char *classname) 760 { 761 devclass_t dc; 762 763 if (dev->devclass) { 764 printf("device_set_devclass: device class already set\n"); 765 return EINVAL; 766 } 767 768 dc = devclass_find_internal(classname, TRUE); 769 if (!dc) 770 return ENOMEM; 771 772 return devclass_add_device(dc, dev); 773 } 774 775 int 776 device_set_driver(device_t dev, driver_t *driver) 777 { 778 if (dev->state >= DS_ATTACHED) 779 return EBUSY; 780 781 if (dev->driver == driver) 782 return 0; 783 784 if (dev->softc) { 785 free(dev->softc, M_DEVBUF); 786 dev->softc = NULL; 787 } 788 dev->ops = &null_ops; 789 dev->driver = driver; 790 if (driver) { 791 dev->ops = driver->ops; 792 dev->softc = malloc(driver->softc, M_DEVBUF, M_NOWAIT); 793 if (!dev->softc) { 794 dev->ops = &null_ops; 795 dev->driver = NULL; 796 return ENOMEM; 797 } 798 bzero(dev->softc, driver->softc); 799 } 800 return 0; 801 } 802 803 int 804 device_probe_and_attach(device_t dev) 805 { 806 device_t bus = dev->parent; 807 int error = 0; 808 809 if (dev->state >= DS_ALIVE) 810 return 0; 811 812 if (dev->flags & DF_ENABLED) { 813 error = device_probe_child(bus, dev); 814 if (!error) { 815 device_print_child(bus, dev); 816 error = DEVICE_ATTACH(dev); 817 if (!error) 818 dev->state = DS_ATTACHED; 819 else { 820 printf("device_probe_and_attach: %s%d attach returned %d\n", 821 dev->driver->name, dev->unit, error); 822 device_set_driver(dev, NULL); 823 dev->state = DS_NOTPRESENT; 824 } 825 } 826 } else { 827 device_print_prettyname(dev); 828 printf("not probed (disabled)\n"); 829 } 830 831 return error; 832 } 833 834 int 835 device_detach(device_t dev) 836 { 837 int error; 838 839 PDEBUG(("%s", DEVICENAME(dev))); 840 if (dev->state == DS_BUSY) 841 return EBUSY; 842 if (dev->state != DS_ATTACHED) 843 return 0; 844 845 if (error = DEVICE_DETACH(dev)) 846 return error; 847 848 if (!(dev->flags & DF_FIXEDCLASS)) 849 devclass_delete_device(dev->devclass, dev); 850 851 dev->state = DS_NOTPRESENT; 852 device_set_driver(dev, NULL); 853 854 return 0; 855 } 856 857 int 858 device_shutdown(device_t dev) 859 { 860 if (dev->state < DS_ATTACHED) 861 return 0; 862 return DEVICE_SHUTDOWN(dev); 863 } 864 865 /* 866 * Access functions for device resources. 867 */ 868 extern struct config_device devtab[]; 869 extern int devtab_count; 870 871 static int 872 resource_match_string(int i, char *resname, char *value) 873 { 874 int j; 875 struct config_resource *res; 876 877 for (j = 0, res = devtab[i].resources; 878 j < devtab[i].resource_count; j++, res++) 879 if (!strcmp(res->name, resname) 880 && res->type == RES_STRING 881 && !strcmp(res->u.stringval, value)) 882 return TRUE; 883 return FALSE; 884 } 885 886 static int 887 resource_find(const char *name, int unit, char *resname, 888 struct config_resource **result) 889 { 890 int i, j; 891 struct config_resource *res; 892 893 /* 894 * First check specific instances, then generic. 895 */ 896 for (i = 0; i < devtab_count; i++) { 897 if (devtab[i].unit < 0) 898 continue; 899 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { 900 res = devtab[i].resources; 901 for (j = 0; j < devtab[i].resource_count; j++, res++) 902 if (!strcmp(res->name, resname)) { 903 *result = res; 904 return 0; 905 } 906 } 907 } 908 for (i = 0; i < devtab_count; i++) { 909 if (devtab[i].unit >= 0) 910 continue; 911 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { 912 res = devtab[i].resources; 913 for (j = 0; j < devtab[i].resource_count; j++, res++) 914 if (!strcmp(res->name, resname)) { 915 *result = res; 916 return 0; 917 } 918 } 919 } 920 return ENOENT; 921 } 922 923 int 924 resource_int_value(const char *name, int unit, char *resname, int *result) 925 { 926 int error; 927 struct config_resource *res; 928 if ((error = resource_find(name, unit, resname, &res)) != 0) 929 return error; 930 if (res->type != RES_INT) 931 return EFTYPE; 932 *result = res->u.intval; 933 return 0; 934 } 935 936 int 937 resource_long_value(const char *name, int unit, char *resname, long *result) 938 { 939 int error; 940 struct config_resource *res; 941 if ((error = resource_find(name, unit, resname, &res)) != 0) 942 return error; 943 if (res->type != RES_LONG) 944 return EFTYPE; 945 *result = res->u.longval; 946 return 0; 947 } 948 949 int 950 resource_string_value(const char *name, int unit, char *resname, char **result) 951 { 952 int error; 953 struct config_resource *res; 954 if ((error = resource_find(name, unit, resname, &res)) != 0) 955 return error; 956 if (res->type != RES_STRING) 957 return EFTYPE; 958 *result = res->u.stringval; 959 return 0; 960 } 961 962 int 963 resource_query_string(int i, char *resname, char *value) 964 { 965 if (i < 0) 966 i = 0; 967 else 968 i = i + 1; 969 for (; i < devtab_count; i++) 970 if (resource_match_string(i, resname, value)) 971 return i; 972 return -1; 973 } 974 975 char * 976 resource_query_name(int i) 977 { 978 return devtab[i].name; 979 } 980 981 int 982 resource_query_unit(int i) 983 { 984 return devtab[i].unit; 985 } 986 987 988 /* 989 * Some useful method implementations to make life easier for bus drivers. 990 */ 991 int 992 bus_generic_attach(device_t dev) 993 { 994 device_t child; 995 996 for (child = TAILQ_FIRST(&dev->children); 997 child; child = TAILQ_NEXT(child, link)) 998 device_probe_and_attach(child); 999 1000 return 0; 1001 } 1002 1003 int 1004 bus_generic_detach(device_t dev) 1005 { 1006 device_t child; 1007 int error; 1008 1009 if (dev->state != DS_ATTACHED) 1010 return EBUSY; 1011 1012 for (child = TAILQ_FIRST(&dev->children); 1013 child; child = TAILQ_NEXT(child, link)) 1014 if (error = device_detach(child)) 1015 return error; 1016 1017 return 0; 1018 } 1019 1020 int 1021 bus_generic_shutdown(device_t dev) 1022 { 1023 device_t child; 1024 1025 for (child = TAILQ_FIRST(&dev->children); 1026 child; child = TAILQ_NEXT(child, link)) 1027 DEVICE_SHUTDOWN(child); 1028 1029 return 0; 1030 } 1031 1032 int 1033 bus_generic_suspend(device_t dev) 1034 { 1035 int error; 1036 device_t child, child2; 1037 1038 for (child = TAILQ_FIRST(&dev->children); 1039 child; child = TAILQ_NEXT(child, link)) { 1040 error = DEVICE_SUSPEND(child); 1041 if (error) { 1042 for (child2 = TAILQ_FIRST(&dev->children); 1043 child2 && child2 != child; 1044 child2 = TAILQ_NEXT(child2, link)) 1045 DEVICE_RESUME(child2); 1046 return (error); 1047 } 1048 } 1049 return 0; 1050 } 1051 1052 int 1053 bus_generic_resume(device_t dev) 1054 { 1055 device_t child; 1056 1057 for (child = TAILQ_FIRST(&dev->children); 1058 child; child = TAILQ_NEXT(child, link)) { 1059 DEVICE_RESUME(child); 1060 /* if resume fails, there's nothing we can usefully do... */ 1061 } 1062 return 0; 1063 } 1064 1065 void 1066 bus_generic_print_child(device_t dev, device_t child) 1067 { 1068 } 1069 1070 int 1071 bus_generic_read_ivar(device_t dev, device_t child, int index, 1072 uintptr_t * result) 1073 { 1074 return ENOENT; 1075 } 1076 1077 int 1078 bus_generic_write_ivar(device_t dev, device_t child, int index, 1079 uintptr_t value) 1080 { 1081 return ENOENT; 1082 } 1083 1084 int 1085 bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq, 1086 driver_intr_t *intr, void *arg, void **cookiep) 1087 { 1088 /* Propagate up the bus hierarchy until someone handles it. */ 1089 if (dev->parent) 1090 return (BUS_SETUP_INTR(dev->parent, dev, irq, intr, arg, 1091 cookiep)); 1092 else 1093 return (EINVAL); 1094 } 1095 1096 int 1097 bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq, 1098 void *cookie) 1099 { 1100 /* Propagate up the bus hierarchy until someone handles it. */ 1101 if (dev->parent) 1102 return (BUS_TEARDOWN_INTR(dev->parent, dev, irq, cookie)); 1103 else 1104 return (EINVAL); 1105 } 1106 1107 int 1108 bus_generic_activate_resource(device_t dev, device_t child, int type, int rid, 1109 struct resource *r) 1110 { 1111 /* Propagate up the bus hierarchy until someone handles it. */ 1112 if (dev->parent) 1113 return (BUS_ACTIVATE_RESOURCE(dev->parent, child, type, rid, 1114 r)); 1115 else 1116 return (EINVAL); 1117 } 1118 1119 int 1120 bus_generic_deactivate_resource(device_t dev, device_t child, int type, 1121 int rid, struct resource *r) 1122 { 1123 /* Propagate up the bus hierarchy until someone handles it. */ 1124 if (dev->parent) 1125 return (BUS_DEACTIVATE_RESOURCE(dev->parent, child, type, rid, 1126 r)); 1127 else 1128 return (EINVAL); 1129 } 1130 1131 /* 1132 * Some convenience functions to make it easier for drivers to use the 1133 * resource-management functions. All these really do is hide the 1134 * indirection through the parent's method table, making for slightly 1135 * less-wordy code. In the future, it might make sense for this code 1136 * to maintain some sort of a list of resources allocated by each device. 1137 */ 1138 struct resource * 1139 bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end, 1140 u_long count, u_int flags) 1141 { 1142 if (dev->parent == 0) 1143 return (0); 1144 return (BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end, 1145 count, flags)); 1146 } 1147 1148 int 1149 bus_activate_resource(device_t dev, int type, int rid, struct resource *r) 1150 { 1151 if (dev->parent == 0) 1152 return (EINVAL); 1153 return (BUS_ACTIVATE_RESOURCE(dev->parent, dev, type, rid, r)); 1154 } 1155 1156 int 1157 bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r) 1158 { 1159 if (dev->parent == 0) 1160 return (EINVAL); 1161 return (BUS_DEACTIVATE_RESOURCE(dev->parent, dev, type, rid, r)); 1162 } 1163 1164 int 1165 bus_release_resource(device_t dev, int type, int rid, struct resource *r) 1166 { 1167 if (dev->parent == 0) 1168 return (EINVAL); 1169 return (BUS_RELEASE_RESOURCE(dev->parent, dev, 1170 type, rid, r)); 1171 } 1172 1173 static int 1174 root_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg, 1175 void **cookiep) 1176 { 1177 /* 1178 * If an interrupt mapping gets to here something bad has happened. 1179 */ 1180 panic("root_setup_intr"); 1181 } 1182 1183 static device_method_t root_methods[] = { 1184 /* Device interface */ 1185 DEVMETHOD(device_suspend, bus_generic_suspend), 1186 DEVMETHOD(device_resume, bus_generic_resume), 1187 1188 /* Bus interface */ 1189 DEVMETHOD(bus_print_child, bus_generic_print_child), 1190 DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), 1191 DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), 1192 DEVMETHOD(bus_setup_intr, root_setup_intr), 1193 1194 { 0, 0 } 1195 }; 1196 1197 static driver_t root_driver = { 1198 "root", 1199 root_methods, 1200 DRIVER_TYPE_MISC, 1201 1, /* no softc */ 1202 }; 1203 1204 device_t root_bus; 1205 devclass_t root_devclass; 1206 1207 static int 1208 root_bus_module_handler(module_t mod, int what, void* arg) 1209 { 1210 switch (what) { 1211 case MOD_LOAD: 1212 compile_methods(&root_driver); 1213 root_bus = make_device(NULL, "root", 0, NULL); 1214 root_bus->desc = "System root bus"; 1215 root_bus->ops = root_driver.ops; 1216 root_bus->driver = &root_driver; 1217 root_bus->state = DS_ATTACHED; 1218 root_devclass = devclass_find_internal("root", FALSE); 1219 return 0; 1220 } 1221 1222 return 0; 1223 } 1224 1225 static moduledata_t root_bus_mod = { 1226 "rootbus", 1227 root_bus_module_handler, 1228 0 1229 }; 1230 DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 1231 1232 void 1233 root_bus_configure(void) 1234 { 1235 device_t dev; 1236 1237 PDEBUG((".")); 1238 1239 for (dev = TAILQ_FIRST(&root_bus->children); dev; 1240 dev = TAILQ_NEXT(dev, link)) { 1241 device_probe_and_attach(dev); 1242 } 1243 } 1244 1245 int 1246 driver_module_handler(module_t mod, int what, void *arg) 1247 { 1248 int error, i; 1249 struct driver_module_data *dmd; 1250 devclass_t bus_devclass; 1251 1252 dmd = (struct driver_module_data *)arg; 1253 bus_devclass = devclass_find_internal(dmd->dmd_busname, TRUE); 1254 error = 0; 1255 1256 switch (what) { 1257 case MOD_LOAD: 1258 for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { 1259 PDEBUG(("Loading module: driver %s on bus %s", 1260 DRIVERNAME(dmd->dmd_drivers[i]), 1261 dmd->dmd_busname)); 1262 error = devclass_add_driver(bus_devclass, 1263 dmd->dmd_drivers[i]); 1264 } 1265 if (error) 1266 break; 1267 1268 /* 1269 * The drivers loaded in this way are assumed to all 1270 * implement the same devclass. 1271 */ 1272 *dmd->dmd_devclass = 1273 devclass_find_internal(dmd->dmd_drivers[0]->name, 1274 TRUE); 1275 break; 1276 1277 case MOD_UNLOAD: 1278 for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { 1279 PDEBUG(("Unloading module: driver %s from bus %s", 1280 DRIVERNAME(dmd->dmd_drivers[i]), 1281 dmd->dmd_busname)); 1282 error = devclass_delete_driver(bus_devclass, 1283 dmd->dmd_drivers[i]); 1284 } 1285 break; 1286 } 1287 1288 if (!error && dmd->dmd_chainevh) 1289 error = dmd->dmd_chainevh(mod, what, dmd->dmd_chainarg); 1290 return (error); 1291 } 1292 1293 #ifdef BUS_DEBUG 1294 1295 /* the _short versions avoid iteration by not calling anything that prints 1296 * more than oneliners. I love oneliners. 1297 */ 1298 1299 static void 1300 print_method_list(device_method_t *m, int indent) 1301 { 1302 int i; 1303 1304 if (!m) 1305 return; 1306 1307 for (i = 0; m->desc; i++, m++) 1308 indentprintf(("method %d: %s, offset=%d\n", 1309 i, m->desc->name, m->desc->offset)); 1310 } 1311 1312 static void 1313 print_device_ops(device_ops_t ops, int indent) 1314 { 1315 int i; 1316 int count = 0; 1317 1318 if (!ops) 1319 return; 1320 1321 /* we present a list of the methods that are pointing to the 1322 * error_method, but ignore the 0'th elements; it is always 1323 * error_method. 1324 */ 1325 for (i = 1; i < ops->maxoffset; i++) { 1326 if (ops->methods[i] == error_method) { 1327 if (count == 0) 1328 indentprintf(("error_method:")); 1329 printf(" %d", i); 1330 count++; 1331 } 1332 } 1333 if (count) 1334 printf("\n"); 1335 1336 indentprintf(("(%d method%s, %d valid, %d error_method%s)\n", 1337 ops->maxoffset-1, (ops->maxoffset-1 == 1? "":"s"), 1338 ops->maxoffset-1-count, 1339 count, (count == 1? "":"'s"))); 1340 } 1341 1342 static void 1343 print_device_short(device_t dev, int indent) 1344 { 1345 if (!dev) 1346 return; 1347 1348 indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%sivars,%ssoftc,busy=%d\n", 1349 dev->unit, dev->desc, 1350 (dev->parent? "":"no "), 1351 (TAILQ_EMPTY(&dev->children)? "no ":""), 1352 (dev->flags&DF_ENABLED? "enabled,":"disabled,"), 1353 (dev->flags&DF_FIXEDCLASS? "fixed,":""), 1354 (dev->flags&DF_WILDCARD? "wildcard,":""), 1355 (dev->ivars? "":"no "), 1356 (dev->softc? "":"no "), 1357 dev->busy)); 1358 } 1359 1360 static void 1361 print_device(device_t dev, int indent) 1362 { 1363 if (!dev) 1364 return; 1365 1366 print_device_short(dev, indent); 1367 1368 indentprintf(("Parent:\n")); 1369 print_device_short(dev->parent, indent+1); 1370 indentprintf(("Methods:\n")); 1371 print_device_ops(dev->ops, indent+1); 1372 indentprintf(("Driver:\n")); 1373 print_driver_short(dev->driver, indent+1); 1374 indentprintf(("Devclass:\n")); 1375 print_devclass_short(dev->devclass, indent+1); 1376 } 1377 1378 void 1379 print_device_tree_short(device_t dev, int indent) 1380 /* print the device and all its children (indented) */ 1381 { 1382 device_t child; 1383 1384 if (!dev) 1385 return; 1386 1387 print_device_short(dev, indent); 1388 1389 for (child = TAILQ_FIRST(&dev->children); child; 1390 child = TAILQ_NEXT(child, link)) 1391 print_device_tree_short(child, indent+1); 1392 } 1393 1394 void 1395 print_device_tree(device_t dev, int indent) 1396 /* print the device and all its children (indented) */ 1397 { 1398 device_t child; 1399 1400 if (!dev) 1401 return; 1402 1403 print_device(dev, indent); 1404 1405 for (child = TAILQ_FIRST(&dev->children); child; 1406 child = TAILQ_NEXT(child, link)) 1407 print_device_tree(child, indent+1); 1408 } 1409 1410 static void 1411 print_driver_short(driver_t *driver, int indent) 1412 { 1413 if (!driver) 1414 return; 1415 1416 indentprintf(("driver %s: type = %s%s%s%s, softc size = %d\n", 1417 driver->name, 1418 /* yes, I know this looks silly, but going to bed at 1419 * two o'clock and having to get up at 7:30 again is silly 1420 * as well. As is sticking your head in a bucket of water. 1421 */ 1422 (driver->type == DRIVER_TYPE_TTY? "tty":""), 1423 (driver->type == DRIVER_TYPE_BIO? "bio":""), 1424 (driver->type == DRIVER_TYPE_NET? "net":""), 1425 (driver->type == DRIVER_TYPE_MISC? "misc":""), 1426 driver->softc)); 1427 } 1428 1429 static void 1430 print_driver(driver_t *driver, int indent) 1431 { 1432 if (!driver) 1433 return; 1434 1435 print_driver_short(driver, indent); 1436 indentprintf(("Methods:\n")); 1437 print_method_list(driver->methods, indent+1); 1438 indentprintf(("Operations:\n")); 1439 print_device_ops(driver->ops, indent+1); 1440 } 1441 1442 1443 static void 1444 print_driver_list(driver_list_t drivers, int indent) 1445 { 1446 driver_t *driver; 1447 1448 for (driver = TAILQ_FIRST(&drivers); driver; 1449 driver = TAILQ_NEXT(driver, link)) 1450 print_driver(driver, indent); 1451 } 1452 1453 static void 1454 print_devclass_short(devclass_t dc, int indent) 1455 { 1456 if ( !dc ) 1457 return; 1458 1459 indentprintf(("devclass %s: max units = %d, next unit = %d\n", 1460 dc->name, dc->maxunit, dc->nextunit)); 1461 } 1462 1463 static void 1464 print_devclass(devclass_t dc, int indent) 1465 { 1466 int i; 1467 1468 if ( !dc ) 1469 return; 1470 1471 print_devclass_short(dc, indent); 1472 indentprintf(("Drivers:\n")); 1473 print_driver_list(dc->drivers, indent+1); 1474 1475 indentprintf(("Devices:\n")); 1476 for (i = 0; i < dc->maxunit; i++) 1477 if (dc->devices[i]) 1478 print_device(dc->devices[i], indent+1); 1479 } 1480 1481 void 1482 print_devclass_list_short(void) 1483 { 1484 devclass_t dc; 1485 1486 printf("Short listing of devclasses, drivers & devices:\n"); 1487 for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link)) 1488 print_devclass_short(dc, 0); 1489 } 1490 1491 void 1492 print_devclass_list(void) 1493 { 1494 devclass_t dc; 1495 1496 printf("Full listing of devclasses, drivers & devices:\n"); 1497 for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link)) 1498 print_devclass(dc, 0); 1499 } 1500 1501 #endif 1502