subr_bus.c revision 38860
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.4 1998/07/22 08:35:52 dfr 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/* 38 * Method table handling 39 */ 40 41static int next_method_offset = 1; 42static int methods_count = 0; 43static int methods_size = 0; 44 45struct method { 46 int offset; 47 char* name; 48}; 49 50static struct method *methods = 0; 51 52static void 53register_method(struct device_op_desc *desc) 54{ 55 int i; 56 struct method* m; 57 58 for (i = 0; i < methods_count; i++) 59 if (!strcmp(methods[i].name, desc->name)) { 60 desc->offset = methods[i].offset; 61 return; 62 } 63 64 if (methods_count == methods_size) { 65 struct method* p; 66 67 methods_size += 10; 68 p = (struct method*) malloc(methods_size * sizeof(struct method), 69 M_DEVBUF, M_NOWAIT); 70 if (!p) 71 panic("register_method: out of memory"); 72 if (methods) { 73 bcopy(methods, p, methods_count * sizeof(struct method)); 74 free(methods, M_DEVBUF); 75 } 76 methods = p; 77 } 78 m = &methods[methods_count++]; 79 m->name = malloc(strlen(desc->name) + 1, M_DEVBUF, M_NOWAIT); 80 if (!m->name) 81 panic("register_method: out of memory"); 82 strcpy(m->name, desc->name); 83 desc->offset = m->offset = next_method_offset++; 84} 85 86static int error_method(void) 87{ 88 return ENXIO; 89} 90 91static struct device_ops null_ops = { 92 1, 93 { error_method } 94}; 95 96static void 97compile_methods(driver_t *driver) 98{ 99 device_ops_t ops; 100 struct device_method *m; 101 int i; 102 103 /* 104 * First register any methods which need it. 105 */ 106 for (i = 0, m = driver->methods; m->desc; i++, m++) 107 if (!m->desc->offset) 108 register_method(m->desc); 109 110 /* 111 * Then allocate the compiled op table. 112 */ 113 ops = malloc(sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t), 114 M_DEVBUF, M_NOWAIT); 115 if (!ops) 116 panic("compile_methods: out of memory"); 117 ops->maxoffset = next_method_offset; 118 for (i = 0; i < next_method_offset; i++) 119 ops->methods[i] = error_method; 120 for (i = 0, m = driver->methods; m->desc; i++, m++) 121 ops->methods[m->desc->offset] = m->func; 122 driver->ops = ops; 123} 124 125/* 126 * Devclass implementation 127 */ 128 129static devclass_list_t devclasses; 130 131static void 132devclass_init(void) 133{ 134 TAILQ_INIT(&devclasses); 135} 136 137static devclass_t 138devclass_find_internal(const char *classname, int create) 139{ 140 devclass_t dc; 141 142 for (dc = TAILQ_FIRST(&devclasses); dc; dc = TAILQ_NEXT(dc, link)) 143 if (!strcmp(dc->name, classname)) 144 return dc; 145 146 if (create) { 147 dc = malloc(sizeof(struct devclass) + strlen(classname) + 1, 148 M_DEVBUF, M_NOWAIT); 149 if (!dc) 150 return NULL; 151 dc->name = (char*) (dc + 1); 152 strcpy(dc->name, classname); 153 dc->devices = NULL; 154 dc->maxunit = 0; 155 dc->nextunit = 0; 156 TAILQ_INIT(&dc->drivers); 157 TAILQ_INSERT_TAIL(&devclasses, dc, link); 158 } 159 160 return dc; 161} 162 163devclass_t 164devclass_find(const char *classname) 165{ 166 return devclass_find_internal(classname, FALSE); 167} 168 169int 170devclass_add_driver(devclass_t dc, driver_t *driver) 171{ 172 /* 173 * Compile the drivers methods. 174 */ 175 compile_methods(driver); 176 177 /* 178 * Make sure the devclass which the driver is implementing exists. 179 */ 180 devclass_find_internal(driver->name, TRUE); 181 182 TAILQ_INSERT_TAIL(&dc->drivers, driver, link); 183 184 return 0; 185} 186 187int 188devclass_delete_driver(devclass_t dc, driver_t *driver) 189{ 190 device_t bus; 191 device_t dev; 192 int i; 193 int error; 194 195 /* 196 * Disassociate from any devices. We iterate through all the 197 * devices attached to any bus in this class. 198 */ 199 for (i = 0; i < dc->maxunit; i++) { 200 if (dc->devices[i]) { 201 bus = dc->devices[i]->parent; 202 for (dev = TAILQ_FIRST(&bus->children); dev; 203 dev = TAILQ_NEXT(dev, link)) 204 if (dev->driver == driver) { 205 if (error = DEVICE_DETACH(dev)) 206 return error; 207 device_set_driver(dev, NULL); 208 } 209 } 210 } 211 212 TAILQ_REMOVE(&dc->drivers, driver, link); 213 return 0; 214} 215 216driver_t * 217devclass_find_driver(devclass_t dc, const char *classname) 218{ 219 driver_t *driver; 220 221 for (driver = TAILQ_FIRST(&dc->drivers); driver; 222 driver = TAILQ_NEXT(driver, link)) 223 if (!strcmp(driver->name, classname)) 224 return driver; 225 226 return NULL; 227} 228 229const char * 230devclass_get_name(devclass_t dc) 231{ 232 return dc->name; 233} 234 235device_t 236devclass_get_device(devclass_t dc, int unit) 237{ 238 if (unit < 0 || unit >= dc->maxunit) 239 return NULL; 240 return dc->devices[unit]; 241} 242 243void * 244devclass_get_softc(devclass_t dc, int unit) 245{ 246 device_t dev; 247 248 if (unit < 0 || unit >= dc->maxunit) 249 return NULL; 250 dev = dc->devices[unit]; 251 if (!dev || dev->state < DS_ATTACHED) 252 return NULL; 253 return dev->softc; 254} 255 256int 257devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp) 258{ 259 int i; 260 int count; 261 device_t dev; 262 device_t *list; 263 264 count = 0; 265 for (i = 0; i < dc->maxunit; i++) 266 if (dc->devices[i]) 267 count++; 268 269 list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT); 270 if (!list) 271 return ENOMEM; 272 273 count = 0; 274 for (i = 0; i < dc->maxunit; i++) 275 if (dc->devices[i]) { 276 list[count] = dc->devices[i]; 277 count++; 278 } 279 280 *devlistp = list; 281 *devcountp = count; 282 283 return 0; 284} 285 286int 287devclass_get_maxunit(devclass_t dc) 288{ 289 return dc->maxunit; 290} 291 292static int 293devclass_alloc_unit(devclass_t dc, int *unitp) 294{ 295 int unit = *unitp; 296 297 /* 298 * If we have been given a wired unit number, check for existing 299 * device. 300 */ 301 if (unit != -1) { 302 device_t dev; 303 dev = devclass_get_device(dc, unit); 304 if (dev) { 305 printf("devclass_alloc_unit: %s%d already exists, using next available unit number\n", dc->name, unit); 306 unit = -1; 307 } 308 } 309 310 if (unit == -1) { 311 unit = dc->nextunit; 312 dc->nextunit++; 313 } else if (dc->nextunit <= unit) 314 dc->nextunit = unit + 1; 315 316 if (unit >= dc->maxunit) { 317 device_t *newlist; 318 int newsize; 319 320 newsize = (dc->maxunit ? 2 * dc->maxunit 321 : MINALLOCSIZE / sizeof(device_t)); 322 newlist = malloc(sizeof(device_t) * newsize, M_DEVBUF, M_NOWAIT); 323 if (!newlist) 324 return ENOMEM; 325 bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit); 326 bzero(newlist + dc->maxunit, 327 sizeof(device_t) * (newsize - dc->maxunit)); 328 if (dc->devices) 329 free(dc->devices, M_DEVBUF); 330 dc->devices = newlist; 331 dc->maxunit = newsize; 332 } 333 334 *unitp = unit; 335 return 0; 336} 337 338static int 339devclass_add_device(devclass_t dc, device_t dev) 340{ 341 int error; 342 343 if (error = devclass_alloc_unit(dc, &dev->unit)) 344 return error; 345 dc->devices[dev->unit] = dev; 346 dev->devclass = dc; 347 return 0; 348} 349 350static int 351devclass_delete_device(devclass_t dc, device_t dev) 352{ 353 if (dev->devclass != dc 354 || dc->devices[dev->unit] != dev) 355 panic("devclass_delete_device: inconsistent device class"); 356 dc->devices[dev->unit] = NULL; 357 if (dev->flags & DF_WILDCARD) 358 dev->unit = -1; 359 dev->devclass = NULL; 360 while (dc->nextunit > 0 && dc->devices[dc->nextunit - 1] == NULL) 361 dc->nextunit--; 362 return 0; 363} 364 365static device_t 366make_device(device_t parent, const char *name, 367 int unit, void *ivars) 368{ 369 driver_t *driver; 370 device_t dev; 371 devclass_t dc; 372 int error; 373 374 if (name) { 375 dc = devclass_find_internal(name, TRUE); 376 if (!dc) { 377 printf("make_device: can't find device class %s\n", name); 378 return NULL; 379 } 380 381 if (error = devclass_alloc_unit(dc, &unit)) 382 return NULL; 383 } else 384 dc = NULL; 385 386 dev = malloc(sizeof(struct device), M_DEVBUF, M_NOWAIT); 387 if (!dev) 388 return 0; 389 390 dev->parent = parent; 391 TAILQ_INIT(&dev->children); 392 dev->ops = &null_ops; 393 dev->driver = NULL; 394 dev->devclass = dc; 395 dev->unit = unit; 396 dev->desc = NULL; 397 dev->busy = 0; 398 dev->flags = DF_ENABLED; 399 if (unit == -1) 400 dev->flags |= DF_WILDCARD; 401 if (name) 402 dev->flags |= DF_FIXEDCLASS; 403 dev->ivars = ivars; 404 dev->softc = NULL; 405 406 if (dc) 407 dc->devices[unit] = dev; 408 409 dev->state = DS_NOTPRESENT; 410 411 return dev; 412} 413 414static void 415device_print_child(device_t dev, device_t child) 416{ 417 printf("%s%d", device_get_name(child), device_get_unit(child)); 418 if (device_is_alive(child)) { 419 if (device_get_desc(child)) 420 printf(": <%s>", device_get_desc(child)); 421 BUS_PRINT_CHILD(dev, child); 422 } else 423 printf(" not found"); 424 printf("\n"); 425} 426 427device_t 428device_add_child(device_t dev, const char *name, int unit, void *ivars) 429{ 430 device_t child; 431 432 child = make_device(dev, name, unit, ivars); 433 434 TAILQ_INSERT_TAIL(&dev->children, child, link); 435 436 return child; 437} 438 439device_t 440device_add_child_after(device_t dev, device_t place, const char *name, 441 int unit, void *ivars) 442{ 443 device_t child; 444 445 child = make_device(dev, name, unit, ivars); 446 447 if (place) { 448 TAILQ_INSERT_AFTER(&dev->children, place, dev, link); 449 } else { 450 TAILQ_INSERT_HEAD(&dev->children, dev, link); 451 } 452 453 return child; 454} 455 456int 457device_delete_child(device_t dev, device_t child) 458{ 459 int error; 460 461 if (error = DEVICE_DETACH(child)) 462 return error; 463 if (child->devclass) 464 devclass_delete_device(child->devclass, child); 465 TAILQ_REMOVE(&dev->children, child, link); 466 free(dev, M_DEVBUF); 467 468 return 0; 469} 470 471/* 472 * Find only devices attached to this bus. 473 */ 474device_t 475device_find_child(device_t dev, const char *classname, int unit) 476{ 477 devclass_t dc; 478 device_t child; 479 480 dc = devclass_find(classname); 481 if (!dc) 482 return NULL; 483 484 child = devclass_get_device(dc, unit); 485 if (child && child->parent == dev) 486 return child; 487 return NULL; 488} 489 490static driver_t * 491first_matching_driver(devclass_t dc, device_t dev) 492{ 493 if (dev->devclass) 494 return devclass_find_driver(dc, dev->devclass->name); 495 else 496 return TAILQ_FIRST(&dc->drivers); 497} 498 499static driver_t * 500next_matching_driver(devclass_t dc, device_t dev, driver_t *last) 501{ 502 if (dev->devclass) { 503 driver_t *driver; 504 for (driver = TAILQ_NEXT(last, link); driver; 505 driver = TAILQ_NEXT(driver, link)) 506 if (!strcmp(dev->devclass->name, driver->name)) 507 return driver; 508 return NULL; 509 } else 510 return TAILQ_NEXT(last, link); 511} 512 513static int 514device_probe_child(device_t dev, device_t child) 515{ 516 devclass_t dc; 517 driver_t *driver; 518 void *softc; 519 520 dc = dev->devclass; 521 if (dc == NULL) 522 panic("device_probe_child: parent device has no devclass"); 523 524 if (child->state == DS_ALIVE) 525 return 0; 526 527 for (driver = first_matching_driver(dc, child); 528 driver; 529 driver = next_matching_driver(dc, child, driver)) { 530 device_set_driver(child, driver); 531 if (DEVICE_PROBE(child) == 0) { 532 if (!child->devclass) 533 device_set_devclass(child, driver->name); 534 child->state = DS_ALIVE; 535 return 0; 536 } 537 } 538 539 return ENXIO; 540} 541 542device_t 543device_get_parent(device_t dev) 544{ 545 return dev->parent; 546} 547 548driver_t * 549device_get_driver(device_t dev) 550{ 551 return dev->driver; 552} 553 554devclass_t 555device_get_devclass(device_t dev) 556{ 557 return dev->devclass; 558} 559 560const char * 561device_get_name(device_t dev) 562{ 563 if (dev->devclass) 564 return devclass_get_name(dev->devclass); 565 return NULL; 566} 567 568int 569device_get_unit(device_t dev) 570{ 571 return dev->unit; 572} 573 574const char * 575device_get_desc(device_t dev) 576{ 577 return dev->desc; 578} 579 580void 581device_set_desc(device_t dev, const char* desc) 582{ 583 dev->desc = desc; 584} 585 586void * 587device_get_softc(device_t dev) 588{ 589 return dev->softc; 590} 591 592void * 593device_get_ivars(device_t dev) 594{ 595 return dev->ivars; 596} 597 598device_state_t 599device_get_state(device_t dev) 600{ 601 return dev->state; 602} 603 604void 605device_enable(device_t dev) 606{ 607 dev->flags |= DF_ENABLED; 608} 609 610void 611device_disable(device_t dev) 612{ 613 dev->flags &= ~DF_ENABLED; 614} 615 616void 617device_busy(device_t dev) 618{ 619 if (dev->state < DS_ATTACHED) 620 panic("device_busy: called for unattached device"); 621 if (dev->busy == 0 && dev->parent) 622 device_busy(dev->parent); 623 dev->busy++; 624 dev->state = DS_BUSY; 625} 626 627void 628device_unbusy(device_t dev) 629{ 630 if (dev->state != DS_BUSY) 631 panic("device_unbusy: called for non-busy device"); 632 dev->busy--; 633 if (dev->busy == 0) { 634 if (dev->parent) 635 device_unbusy(dev->parent); 636 dev->state = DS_ATTACHED; 637 } 638} 639 640int 641device_is_enabled(device_t dev) 642{ 643 return (dev->flags & DF_ENABLED) != 0; 644} 645 646int 647device_is_alive(device_t dev) 648{ 649 return dev->state >= DS_ALIVE; 650} 651 652int 653device_set_devclass(device_t dev, const char *classname) 654{ 655 devclass_t dc; 656 657 if (dev->devclass) { 658 printf("device_set_devclass: device class already set\n"); 659 return EINVAL; 660 } 661 662 dc = devclass_find_internal(classname, TRUE); 663 if (!dc) 664 return ENOMEM; 665 666 return devclass_add_device(dc, dev); 667} 668 669int 670device_set_driver(device_t dev, driver_t *driver) 671{ 672 if (dev->state >= DS_ATTACHED) 673 return EBUSY; 674 675 if (dev->driver == driver) 676 return 0; 677 678 if (dev->softc) { 679 free(dev->softc, M_DEVBUF); 680 dev->softc = NULL; 681 } 682 dev->ops = &null_ops; 683 dev->driver = driver; 684 if (driver) { 685 dev->ops = driver->ops; 686 dev->softc = malloc(driver->softc, M_DEVBUF, M_NOWAIT); 687 bzero(dev->softc, driver->softc); 688 } 689 return 0; 690} 691 692int 693device_probe_and_attach(device_t dev) 694{ 695 device_t bus = dev->parent; 696 int error; 697 698 if (dev->state >= DS_ALIVE) 699 return 0; 700 701 if (dev->flags & DF_ENABLED) { 702 device_probe_child(bus, dev); 703 device_print_child(bus, dev); 704 if (dev->state == DS_ALIVE) { 705 error = DEVICE_ATTACH(dev); 706 if (!error) 707 dev->state = DS_ATTACHED; 708 else { 709 printf("device_probe_and_attach: %s%d attach returned %d\n", 710 dev->driver->name, dev->unit, error); 711 device_set_driver(dev, NULL); 712 dev->state = DS_NOTPRESENT; 713 } 714 } 715 } else 716 printf("%s%d: disabled, not probed.\n", 717 dev->devclass->name, dev->unit); 718 719 return 0; 720} 721 722int 723device_detach(device_t dev) 724{ 725 int error; 726 727 if (dev->state == DS_BUSY) 728 return EBUSY; 729 if (dev->state != DS_ATTACHED) 730 return 0; 731 732 if (error = DEVICE_DETACH(dev)) 733 return error; 734 735 if (!(dev->flags & DF_FIXEDCLASS)) 736 devclass_delete_device(dev->devclass, dev); 737 738 dev->state = DS_NOTPRESENT; 739 device_set_driver(dev, NULL); 740 741 return 0; 742} 743 744int 745device_shutdown(device_t dev) 746{ 747 if (dev->state < DS_ATTACHED) 748 return 0; 749 return DEVICE_SHUTDOWN(dev); 750} 751 752/* 753 * Access functions for device resources. 754 */ 755extern struct config_device devtab[]; 756extern int devtab_count; 757 758static int 759resource_match_string(int i, char *resname, char *value) 760{ 761 int j; 762 struct resource *res; 763 764 for (j = 0, res = devtab[i].resources; 765 j < devtab[i].resource_count; j++, res++) 766 if (!strcmp(res->name, resname) 767 && res->type == RES_STRING 768 && !strcmp(res->u.stringval, value)) 769 return TRUE; 770 return FALSE; 771} 772 773static int 774resource_find(const char *name, int unit, char *resname, struct resource **result) 775{ 776 int i, j; 777 struct resource *res; 778 779 /* 780 * First check specific instances, then generic. 781 */ 782 for (i = 0; i < devtab_count; i++) { 783 if (devtab[i].unit < 0) 784 continue; 785 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { 786 res = devtab[i].resources; 787 for (j = 0; j < devtab[i].resource_count; j++, res++) 788 if (!strcmp(res->name, resname)) { 789 *result = res; 790 return 0; 791 } 792 } 793 } 794 for (i = 0; i < devtab_count; i++) { 795 if (devtab[i].unit >= 0) 796 continue; 797 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { 798 res = devtab[i].resources; 799 for (j = 0; j < devtab[i].resource_count; j++, res++) 800 if (!strcmp(res->name, resname)) { 801 *result = res; 802 return 0; 803 } 804 } 805 } 806 return ENOENT; 807} 808 809int 810resource_int_value(const char *name, int unit, char *resname, int *result) 811{ 812 int error; 813 struct resource *res; 814 if ((error = resource_find(name, unit, resname, &res)) != 0) 815 return error; 816 if (res->type != RES_INT) 817 return EFTYPE; 818 *result = res->u.intval; 819 return 0; 820} 821 822int 823resource_long_value(const char *name, int unit, char *resname, long *result) 824{ 825 int error; 826 struct resource *res; 827 if ((error = resource_find(name, unit, resname, &res)) != 0) 828 return error; 829 if (res->type != RES_LONG) 830 return EFTYPE; 831 *result = res->u.longval; 832 return 0; 833} 834 835int 836resource_string_value(const char *name, int unit, char *resname, char **result) 837{ 838 int error; 839 struct resource *res; 840 if ((error = resource_find(name, unit, resname, &res)) != 0) 841 return error; 842 if (res->type != RES_STRING) 843 return EFTYPE; 844 *result = res->u.stringval; 845 return 0; 846} 847 848int 849resource_query_string(int i, char *resname, char *value) 850{ 851 if (i < 0) 852 i = 0; 853 else 854 i = i + 1; 855 for (; i < devtab_count; i++) 856 if (resource_match_string(i, resname, value)) 857 return i; 858 return -1; 859} 860 861char * 862resource_query_name(int i) 863{ 864 return devtab[i].name; 865} 866 867int 868resource_query_unit(int i) 869{ 870 return devtab[i].unit; 871} 872 873 874/* 875 * Some useful method implementations to make life easier for bus drivers. 876 */ 877int 878bus_generic_attach(device_t dev) 879{ 880 device_t child; 881 int error; 882 883 for (child = TAILQ_FIRST(&dev->children); 884 child; child = TAILQ_NEXT(child, link)) 885 device_probe_and_attach(child); 886 887 return 0; 888} 889 890int 891bus_generic_detach(device_t dev) 892{ 893 device_t child; 894 int error; 895 896 if (dev->state != DS_ATTACHED) 897 return EBUSY; 898 899 for (child = TAILQ_FIRST(&dev->children); 900 child; child = TAILQ_NEXT(child, link)) 901 DEVICE_DETACH(child); 902 903 return 0; 904} 905 906int 907bus_generic_shutdown(device_t dev) 908{ 909 device_t child; 910 911 for (child = TAILQ_FIRST(&dev->children); 912 child; child = TAILQ_NEXT(child, link)) 913 DEVICE_SHUTDOWN(child); 914 915 return 0; 916} 917 918void 919bus_generic_print_child(device_t dev, device_t child) 920{ 921} 922 923int 924bus_generic_read_ivar(device_t dev, device_t child, int index, u_long* result) 925{ 926 return ENOENT; 927} 928 929int 930bus_generic_write_ivar(device_t dev, device_t child, int index, u_long value) 931{ 932 return ENOENT; 933} 934 935void * 936bus_generic_create_intr(device_t dev, device_t child, int irq, driver_intr_t *intr, void *arg) 937{ 938 /* Propagate up the bus hierarchy until someone handles it. */ 939 if (dev->parent) 940 return BUS_CREATE_INTR(dev->parent, dev, irq, intr, arg); 941 else 942 return NULL; 943} 944 945int 946bus_generic_connect_intr(device_t dev, void *ih) 947{ 948 /* Propagate up the bus hierarchy until someone handles it. */ 949 if (dev->parent) 950 return BUS_CONNECT_INTR(dev->parent, ih); 951 else 952 return EINVAL; 953} 954 955static int root_create_intr(device_t dev, device_t child, 956 driver_intr_t *intr, void *arg) 957{ 958 /* 959 * If an interrupt mapping gets to here something bad has happened. 960 * Should probably panic. 961 */ 962 return EINVAL; 963} 964 965static device_method_t root_methods[] = { 966 /* Bus interface */ 967 DEVMETHOD(bus_print_child, bus_generic_print_child), 968 DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), 969 DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), 970 DEVMETHOD(bus_create_intr, root_create_intr), 971 972 { 0, 0 } 973}; 974 975static driver_t root_driver = { 976 "root", 977 root_methods, 978 DRIVER_TYPE_MISC, 979 1, /* no softc */ 980}; 981 982device_t root_bus; 983devclass_t root_devclass; 984 985static int 986root_bus_module_handler(module_t mod, modeventtype_t what, void* arg) 987{ 988 switch (what) { 989 case MOD_LOAD: 990 devclass_init(); 991 compile_methods(&root_driver); 992 root_bus = make_device(NULL, "root", 0, NULL); 993 root_bus->ops = root_driver.ops; 994 root_bus->driver = &root_driver; 995 root_bus->state = DS_ATTACHED; 996 root_devclass = devclass_find("root"); 997 return 0; 998 } 999 1000 return 0; 1001} 1002 1003static moduledata_t root_bus_mod = { 1004 "rootbus", 1005 root_bus_module_handler, 1006 0 1007}; 1008DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 1009 1010void 1011root_bus_configure() 1012{ 1013 device_t dev; 1014 int error; 1015 1016 for (dev = TAILQ_FIRST(&root_bus->children); dev; 1017 dev = TAILQ_NEXT(dev, link)) { 1018 device_probe_and_attach(dev); 1019 } 1020} 1021 1022int 1023driver_module_handler(module_t mod, modeventtype_t what, void* arg) 1024{ 1025 struct driver_module_data* data = (struct driver_module_data*) arg; 1026 devclass_t bus_devclass = devclass_find_internal(data->busname, TRUE); 1027 int error; 1028 1029 switch (what) { 1030 case MOD_LOAD: 1031 if (error = devclass_add_driver(bus_devclass, 1032 data->driver)) 1033 return error; 1034 *data->devclass = 1035 devclass_find_internal(data->driver->name, TRUE); 1036 break; 1037 1038 case MOD_UNLOAD: 1039 if (error = devclass_delete_driver(bus_devclass, 1040 data->driver)) 1041 return error; 1042 break; 1043 } 1044 1045 if (data->chainevh) 1046 return data->chainevh(mod, what, data->chainarg); 1047 else 1048 return 0; 1049} 1050