subr_bus.c revision 40648
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.6 1998/10/03 08:55:29 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 *list; 262 263 count = 0; 264 for (i = 0; i < dc->maxunit; i++) 265 if (dc->devices[i]) 266 count++; 267 268 list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT); 269 if (!list) 270 return ENOMEM; 271 272 count = 0; 273 for (i = 0; i < dc->maxunit; i++) 274 if (dc->devices[i]) { 275 list[count] = dc->devices[i]; 276 count++; 277 } 278 279 *devlistp = list; 280 *devcountp = count; 281 282 return 0; 283} 284 285int 286devclass_get_maxunit(devclass_t dc) 287{ 288 return dc->maxunit; 289} 290 291static int 292devclass_alloc_unit(devclass_t dc, int *unitp) 293{ 294 int unit = *unitp; 295 296 /* 297 * If we have been given a wired unit number, check for existing 298 * device. 299 */ 300 if (unit != -1) { 301 device_t dev; 302 dev = devclass_get_device(dc, unit); 303 if (dev) { 304 printf("devclass_alloc_unit: %s%d already exists, using next available unit number\n", dc->name, unit); 305 unit = -1; 306 } 307 } 308 309 if (unit == -1) { 310 unit = dc->nextunit; 311 dc->nextunit++; 312 } else if (dc->nextunit <= unit) 313 dc->nextunit = unit + 1; 314 315 if (unit >= dc->maxunit) { 316 device_t *newlist; 317 int newsize; 318 319 newsize = (dc->maxunit ? 2 * dc->maxunit 320 : MINALLOCSIZE / sizeof(device_t)); 321 newlist = malloc(sizeof(device_t) * newsize, M_DEVBUF, M_NOWAIT); 322 if (!newlist) 323 return ENOMEM; 324 bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit); 325 bzero(newlist + dc->maxunit, 326 sizeof(device_t) * (newsize - dc->maxunit)); 327 if (dc->devices) 328 free(dc->devices, M_DEVBUF); 329 dc->devices = newlist; 330 dc->maxunit = newsize; 331 } 332 333 *unitp = unit; 334 return 0; 335} 336 337static int 338devclass_add_device(devclass_t dc, device_t dev) 339{ 340 int error; 341 342 if (error = devclass_alloc_unit(dc, &dev->unit)) 343 return error; 344 dc->devices[dev->unit] = dev; 345 dev->devclass = dc; 346 return 0; 347} 348 349static int 350devclass_delete_device(devclass_t dc, device_t dev) 351{ 352 if (dev->devclass != dc 353 || dc->devices[dev->unit] != dev) 354 panic("devclass_delete_device: inconsistent device class"); 355 dc->devices[dev->unit] = NULL; 356 if (dev->flags & DF_WILDCARD) 357 dev->unit = -1; 358 dev->devclass = NULL; 359 while (dc->nextunit > 0 && dc->devices[dc->nextunit - 1] == NULL) 360 dc->nextunit--; 361 return 0; 362} 363 364static device_t 365make_device(device_t parent, const char *name, 366 int unit, void *ivars) 367{ 368 device_t dev; 369 devclass_t dc; 370 int error; 371 372 if (name) { 373 dc = devclass_find_internal(name, TRUE); 374 if (!dc) { 375 printf("make_device: can't find device class %s\n", name); 376 return NULL; 377 } 378 379 if (error = devclass_alloc_unit(dc, &unit)) 380 return NULL; 381 } else 382 dc = NULL; 383 384 dev = malloc(sizeof(struct device), M_DEVBUF, M_NOWAIT); 385 if (!dev) 386 return 0; 387 388 dev->parent = parent; 389 TAILQ_INIT(&dev->children); 390 dev->ops = &null_ops; 391 dev->driver = NULL; 392 dev->devclass = dc; 393 dev->unit = unit; 394 dev->desc = NULL; 395 dev->busy = 0; 396 dev->flags = DF_ENABLED; 397 if (unit == -1) 398 dev->flags |= DF_WILDCARD; 399 if (name) 400 dev->flags |= DF_FIXEDCLASS; 401 dev->ivars = ivars; 402 dev->softc = NULL; 403 404 if (dc) 405 dc->devices[unit] = dev; 406 407 dev->state = DS_NOTPRESENT; 408 409 return dev; 410} 411 412static void 413device_print_child(device_t dev, device_t child) 414{ 415 printf("%s%d", device_get_name(child), device_get_unit(child)); 416 if (device_is_alive(child)) { 417 if (device_get_desc(child)) 418 printf(": <%s>", device_get_desc(child)); 419 BUS_PRINT_CHILD(dev, child); 420 } else 421 printf(" not found"); 422 printf("\n"); 423} 424 425device_t 426device_add_child(device_t dev, const char *name, int unit, void *ivars) 427{ 428 device_t child; 429 430 child = make_device(dev, name, unit, ivars); 431 432 TAILQ_INSERT_TAIL(&dev->children, child, link); 433 434 return child; 435} 436 437device_t 438device_add_child_after(device_t dev, device_t place, const char *name, 439 int unit, void *ivars) 440{ 441 device_t child; 442 443 child = make_device(dev, name, unit, ivars); 444 445 if (place) { 446 TAILQ_INSERT_AFTER(&dev->children, place, dev, link); 447 } else { 448 TAILQ_INSERT_HEAD(&dev->children, dev, link); 449 } 450 451 return child; 452} 453 454int 455device_delete_child(device_t dev, device_t child) 456{ 457 int error; 458 459 if (error = device_detach(child)) 460 return error; 461 if (child->devclass) 462 devclass_delete_device(child->devclass, child); 463 TAILQ_REMOVE(&dev->children, child, link); 464 free(dev, M_DEVBUF); 465 466 return 0; 467} 468 469/* 470 * Find only devices attached to this bus. 471 */ 472device_t 473device_find_child(device_t dev, const char *classname, int unit) 474{ 475 devclass_t dc; 476 device_t child; 477 478 dc = devclass_find(classname); 479 if (!dc) 480 return NULL; 481 482 child = devclass_get_device(dc, unit); 483 if (child && child->parent == dev) 484 return child; 485 return NULL; 486} 487 488static driver_t * 489first_matching_driver(devclass_t dc, device_t dev) 490{ 491 if (dev->devclass) 492 return devclass_find_driver(dc, dev->devclass->name); 493 else 494 return TAILQ_FIRST(&dc->drivers); 495} 496 497static driver_t * 498next_matching_driver(devclass_t dc, device_t dev, driver_t *last) 499{ 500 if (dev->devclass) { 501 driver_t *driver; 502 for (driver = TAILQ_NEXT(last, link); driver; 503 driver = TAILQ_NEXT(driver, link)) 504 if (!strcmp(dev->devclass->name, driver->name)) 505 return driver; 506 return NULL; 507 } else 508 return TAILQ_NEXT(last, link); 509} 510 511static int 512device_probe_child(device_t dev, device_t child) 513{ 514 devclass_t dc; 515 driver_t *driver; 516 517 dc = dev->devclass; 518 if (dc == NULL) 519 panic("device_probe_child: parent device has no devclass"); 520 521 if (child->state == DS_ALIVE) 522 return 0; 523 524 for (driver = first_matching_driver(dc, child); 525 driver; 526 driver = next_matching_driver(dc, child, driver)) { 527 device_set_driver(child, driver); 528 if (DEVICE_PROBE(child) == 0) { 529 if (!child->devclass) 530 device_set_devclass(child, driver->name); 531 child->state = DS_ALIVE; 532 return 0; 533 } 534 } 535 536 return ENXIO; 537} 538 539device_t 540device_get_parent(device_t dev) 541{ 542 return dev->parent; 543} 544 545driver_t * 546device_get_driver(device_t dev) 547{ 548 return dev->driver; 549} 550 551devclass_t 552device_get_devclass(device_t dev) 553{ 554 return dev->devclass; 555} 556 557const char * 558device_get_name(device_t dev) 559{ 560 if (dev->devclass) 561 return devclass_get_name(dev->devclass); 562 return NULL; 563} 564 565int 566device_get_unit(device_t dev) 567{ 568 return dev->unit; 569} 570 571const char * 572device_get_desc(device_t dev) 573{ 574 return dev->desc; 575} 576 577void 578device_set_desc(device_t dev, const char* desc) 579{ 580 dev->desc = desc; 581} 582 583void * 584device_get_softc(device_t dev) 585{ 586 return dev->softc; 587} 588 589void * 590device_get_ivars(device_t dev) 591{ 592 return dev->ivars; 593} 594 595device_state_t 596device_get_state(device_t dev) 597{ 598 return dev->state; 599} 600 601void 602device_enable(device_t dev) 603{ 604 dev->flags |= DF_ENABLED; 605} 606 607void 608device_disable(device_t dev) 609{ 610 dev->flags &= ~DF_ENABLED; 611} 612 613void 614device_busy(device_t dev) 615{ 616 if (dev->state < DS_ATTACHED) 617 panic("device_busy: called for unattached device"); 618 if (dev->busy == 0 && dev->parent) 619 device_busy(dev->parent); 620 dev->busy++; 621 dev->state = DS_BUSY; 622} 623 624void 625device_unbusy(device_t dev) 626{ 627 if (dev->state != DS_BUSY) 628 panic("device_unbusy: called for non-busy device"); 629 dev->busy--; 630 if (dev->busy == 0) { 631 if (dev->parent) 632 device_unbusy(dev->parent); 633 dev->state = DS_ATTACHED; 634 } 635} 636 637int 638device_is_enabled(device_t dev) 639{ 640 return (dev->flags & DF_ENABLED) != 0; 641} 642 643int 644device_is_alive(device_t dev) 645{ 646 return dev->state >= DS_ALIVE; 647} 648 649int 650device_set_devclass(device_t dev, const char *classname) 651{ 652 devclass_t dc; 653 654 if (dev->devclass) { 655 printf("device_set_devclass: device class already set\n"); 656 return EINVAL; 657 } 658 659 dc = devclass_find_internal(classname, TRUE); 660 if (!dc) 661 return ENOMEM; 662 663 return devclass_add_device(dc, dev); 664} 665 666int 667device_set_driver(device_t dev, driver_t *driver) 668{ 669 if (dev->state >= DS_ATTACHED) 670 return EBUSY; 671 672 if (dev->driver == driver) 673 return 0; 674 675 if (dev->softc) { 676 free(dev->softc, M_DEVBUF); 677 dev->softc = NULL; 678 } 679 dev->ops = &null_ops; 680 dev->driver = driver; 681 if (driver) { 682 dev->ops = driver->ops; 683 dev->softc = malloc(driver->softc, M_DEVBUF, M_NOWAIT); 684 bzero(dev->softc, driver->softc); 685 } 686 return 0; 687} 688 689int 690device_probe_and_attach(device_t dev) 691{ 692 device_t bus = dev->parent; 693 int error; 694 695 if (dev->state >= DS_ALIVE) 696 return 0; 697 698 if (dev->flags & DF_ENABLED) { 699 device_probe_child(bus, dev); 700 device_print_child(bus, dev); 701 if (dev->state == DS_ALIVE) { 702 error = DEVICE_ATTACH(dev); 703 if (!error) 704 dev->state = DS_ATTACHED; 705 else { 706 printf("device_probe_and_attach: %s%d attach returned %d\n", 707 dev->driver->name, dev->unit, error); 708 device_set_driver(dev, NULL); 709 dev->state = DS_NOTPRESENT; 710 } 711 } 712 } else 713 printf("%s%d: disabled, not probed.\n", 714 dev->devclass->name, dev->unit); 715 716 return 0; 717} 718 719int 720device_detach(device_t dev) 721{ 722 int error; 723 724 if (dev->state == DS_BUSY) 725 return EBUSY; 726 if (dev->state != DS_ATTACHED) 727 return 0; 728 729 if (error = DEVICE_DETACH(dev)) 730 return error; 731 732 if (!(dev->flags & DF_FIXEDCLASS)) 733 devclass_delete_device(dev->devclass, dev); 734 735 dev->state = DS_NOTPRESENT; 736 device_set_driver(dev, NULL); 737 738 return 0; 739} 740 741int 742device_shutdown(device_t dev) 743{ 744 if (dev->state < DS_ATTACHED) 745 return 0; 746 return DEVICE_SHUTDOWN(dev); 747} 748 749/* 750 * Access functions for device resources. 751 */ 752extern struct config_device devtab[]; 753extern int devtab_count; 754 755static int 756resource_match_string(int i, char *resname, char *value) 757{ 758 int j; 759 struct resource *res; 760 761 for (j = 0, res = devtab[i].resources; 762 j < devtab[i].resource_count; j++, res++) 763 if (!strcmp(res->name, resname) 764 && res->type == RES_STRING 765 && !strcmp(res->u.stringval, value)) 766 return TRUE; 767 return FALSE; 768} 769 770static int 771resource_find(const char *name, int unit, char *resname, struct resource **result) 772{ 773 int i, j; 774 struct resource *res; 775 776 /* 777 * First check specific instances, then generic. 778 */ 779 for (i = 0; i < devtab_count; i++) { 780 if (devtab[i].unit < 0) 781 continue; 782 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { 783 res = devtab[i].resources; 784 for (j = 0; j < devtab[i].resource_count; j++, res++) 785 if (!strcmp(res->name, resname)) { 786 *result = res; 787 return 0; 788 } 789 } 790 } 791 for (i = 0; i < devtab_count; i++) { 792 if (devtab[i].unit >= 0) 793 continue; 794 if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { 795 res = devtab[i].resources; 796 for (j = 0; j < devtab[i].resource_count; j++, res++) 797 if (!strcmp(res->name, resname)) { 798 *result = res; 799 return 0; 800 } 801 } 802 } 803 return ENOENT; 804} 805 806int 807resource_int_value(const char *name, int unit, char *resname, int *result) 808{ 809 int error; 810 struct resource *res; 811 if ((error = resource_find(name, unit, resname, &res)) != 0) 812 return error; 813 if (res->type != RES_INT) 814 return EFTYPE; 815 *result = res->u.intval; 816 return 0; 817} 818 819int 820resource_long_value(const char *name, int unit, char *resname, long *result) 821{ 822 int error; 823 struct resource *res; 824 if ((error = resource_find(name, unit, resname, &res)) != 0) 825 return error; 826 if (res->type != RES_LONG) 827 return EFTYPE; 828 *result = res->u.longval; 829 return 0; 830} 831 832int 833resource_string_value(const char *name, int unit, char *resname, char **result) 834{ 835 int error; 836 struct resource *res; 837 if ((error = resource_find(name, unit, resname, &res)) != 0) 838 return error; 839 if (res->type != RES_STRING) 840 return EFTYPE; 841 *result = res->u.stringval; 842 return 0; 843} 844 845int 846resource_query_string(int i, char *resname, char *value) 847{ 848 if (i < 0) 849 i = 0; 850 else 851 i = i + 1; 852 for (; i < devtab_count; i++) 853 if (resource_match_string(i, resname, value)) 854 return i; 855 return -1; 856} 857 858char * 859resource_query_name(int i) 860{ 861 return devtab[i].name; 862} 863 864int 865resource_query_unit(int i) 866{ 867 return devtab[i].unit; 868} 869 870 871/* 872 * Some useful method implementations to make life easier for bus drivers. 873 */ 874int 875bus_generic_attach(device_t dev) 876{ 877 device_t child; 878 879 for (child = TAILQ_FIRST(&dev->children); 880 child; child = TAILQ_NEXT(child, link)) 881 device_probe_and_attach(child); 882 883 return 0; 884} 885 886int 887bus_generic_detach(device_t dev) 888{ 889 device_t child; 890 891 if (dev->state != DS_ATTACHED) 892 return EBUSY; 893 894 for (child = TAILQ_FIRST(&dev->children); 895 child; child = TAILQ_NEXT(child, link)) 896 device_detach(child); 897 898 return 0; 899} 900 901int 902bus_generic_shutdown(device_t dev) 903{ 904 device_t child; 905 906 for (child = TAILQ_FIRST(&dev->children); 907 child; child = TAILQ_NEXT(child, link)) 908 DEVICE_SHUTDOWN(child); 909 910 return 0; 911} 912 913void 914bus_generic_print_child(device_t dev, device_t child) 915{ 916} 917 918int 919bus_generic_read_ivar(device_t dev, device_t child, int index, u_long* result) 920{ 921 return ENOENT; 922} 923 924int 925bus_generic_write_ivar(device_t dev, device_t child, int index, u_long value) 926{ 927 return ENOENT; 928} 929 930void * 931bus_generic_create_intr(device_t dev, device_t child, int irq, driver_intr_t *intr, void *arg) 932{ 933 /* Propagate up the bus hierarchy until someone handles it. */ 934 if (dev->parent) 935 return BUS_CREATE_INTR(dev->parent, dev, irq, intr, arg); 936 else 937 return NULL; 938} 939 940int 941bus_generic_connect_intr(device_t dev, void *ih) 942{ 943 /* Propagate up the bus hierarchy until someone handles it. */ 944 if (dev->parent) 945 return BUS_CONNECT_INTR(dev->parent, ih); 946 else 947 return EINVAL; 948} 949 950static int root_create_intr(device_t dev, device_t child, 951 driver_intr_t *intr, void *arg) 952{ 953 /* 954 * If an interrupt mapping gets to here something bad has happened. 955 * Should probably panic. 956 */ 957 return EINVAL; 958} 959 960static device_method_t root_methods[] = { 961 /* Bus interface */ 962 DEVMETHOD(bus_print_child, bus_generic_print_child), 963 DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), 964 DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), 965 DEVMETHOD(bus_create_intr, root_create_intr), 966 967 { 0, 0 } 968}; 969 970static driver_t root_driver = { 971 "root", 972 root_methods, 973 DRIVER_TYPE_MISC, 974 1, /* no softc */ 975}; 976 977device_t root_bus; 978devclass_t root_devclass; 979 980static int 981root_bus_module_handler(module_t mod, modeventtype_t what, void* arg) 982{ 983 switch (what) { 984 case MOD_LOAD: 985 devclass_init(); 986 compile_methods(&root_driver); 987 root_bus = make_device(NULL, "root", 0, NULL); 988 root_bus->ops = root_driver.ops; 989 root_bus->driver = &root_driver; 990 root_bus->state = DS_ATTACHED; 991 root_devclass = devclass_find("root"); 992 return 0; 993 } 994 995 return 0; 996} 997 998static moduledata_t root_bus_mod = { 999 "rootbus", 1000 root_bus_module_handler, 1001 0 1002}; 1003DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 1004 1005void 1006root_bus_configure() 1007{ 1008 device_t dev; 1009 1010 for (dev = TAILQ_FIRST(&root_bus->children); dev; 1011 dev = TAILQ_NEXT(dev, link)) { 1012 device_probe_and_attach(dev); 1013 } 1014} 1015 1016int 1017driver_module_handler(module_t mod, modeventtype_t what, void* arg) 1018{ 1019 struct driver_module_data* data = (struct driver_module_data*) arg; 1020 devclass_t bus_devclass = devclass_find_internal(data->busname, TRUE); 1021 int error; 1022 1023 switch (what) { 1024 case MOD_LOAD: 1025 if (error = devclass_add_driver(bus_devclass, 1026 data->driver)) 1027 return error; 1028 *data->devclass = 1029 devclass_find_internal(data->driver->name, TRUE); 1030 break; 1031 1032 case MOD_UNLOAD: 1033 if (error = devclass_delete_driver(bus_devclass, 1034 data->driver)) 1035 return error; 1036 break; 1037 } 1038 1039 if (data->chainevh) 1040 return data->chainevh(mod, what, data->chainarg); 1041 else 1042 return 0; 1043} 1044