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