subr_bus.c revision 111815
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 111815 2003-03-03 12:15:54Z phk $ 27 */ 28 29#include "opt_bus.h" 30 31#include <sys/param.h> 32#include <sys/conf.h> 33#include <sys/filio.h> 34#include <sys/lock.h> 35#include <sys/kernel.h> 36#include <sys/kobj.h> 37#include <sys/malloc.h> 38#include <sys/module.h> 39#include <sys/mutex.h> 40#include <sys/poll.h> 41#include <sys/proc.h> 42#include <sys/condvar.h> 43#include <sys/queue.h> 44#include <machine/bus.h> 45#include <sys/rman.h> 46#include <sys/selinfo.h> 47#include <sys/signalvar.h> 48#include <sys/sysctl.h> 49#include <sys/systm.h> 50#include <sys/uio.h> 51#include <sys/bus.h> 52 53#include <machine/stdarg.h> 54 55#include <vm/uma.h> 56 57SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW, NULL, NULL); 58 59/* 60 * Used to attach drivers to devclasses. 61 */ 62typedef struct driverlink *driverlink_t; 63struct driverlink { 64 driver_t *driver; 65 TAILQ_ENTRY(driverlink) link; /* list of drivers in devclass */ 66}; 67 68/* 69 * Forward declarations 70 */ 71typedef TAILQ_HEAD(devclass_list, devclass) devclass_list_t; 72typedef TAILQ_HEAD(driver_list, driverlink) driver_list_t; 73typedef TAILQ_HEAD(device_list, device) device_list_t; 74 75struct devclass { 76 TAILQ_ENTRY(devclass) link; 77 driver_list_t drivers; /* bus devclasses store drivers for bus */ 78 char *name; 79 device_t *devices; /* array of devices indexed by unit */ 80 int maxunit; /* size of devices array */ 81}; 82 83/* 84 * Implementation of device. 85 */ 86struct device { 87 /* 88 * A device is a kernel object. The first field must be the 89 * current ops table for the object. 90 */ 91 KOBJ_FIELDS; 92 93 /* 94 * Device hierarchy. 95 */ 96 TAILQ_ENTRY(device) link; /* list of devices in parent */ 97 TAILQ_ENTRY(device) devlink; /* global device list membership */ 98 device_t parent; 99 device_list_t children; /* list of subordinate devices */ 100 101 /* 102 * Details of this device. 103 */ 104 driver_t *driver; 105 devclass_t devclass; /* device class which we are in */ 106 int unit; 107 char* nameunit; /* name+unit e.g. foodev0 */ 108 char* desc; /* driver specific description */ 109 int busy; /* count of calls to device_busy() */ 110 device_state_t state; 111 u_int32_t devflags; /* api level flags for device_get_flags() */ 112 u_short flags; 113#define DF_ENABLED 1 /* device should be probed/attached */ 114#define DF_FIXEDCLASS 2 /* devclass specified at create time */ 115#define DF_WILDCARD 4 /* unit was originally wildcard */ 116#define DF_DESCMALLOCED 8 /* description was malloced */ 117#define DF_QUIET 16 /* don't print verbose attach message */ 118#define DF_DONENOMATCH 32 /* don't execute DEVICE_NOMATCH again */ 119#define DF_EXTERNALSOFTC 64 /* softc not allocated by us */ 120 u_char order; /* order from device_add_child_ordered() */ 121 u_char pad; 122 void *ivars; 123 void *softc; 124}; 125 126struct device_op_desc { 127 unsigned int offset; /* offset in driver ops */ 128 struct method* method; /* internal method implementation */ 129 devop_t deflt; /* default implementation */ 130 const char* name; /* unique name (for registration) */ 131}; 132 133static MALLOC_DEFINE(M_BUS, "bus", "Bus data structures"); 134 135#ifdef BUS_DEBUG 136 137static int bus_debug = 1; 138TUNABLE_INT("bus.debug", &bus_debug); 139SYSCTL_INT(_debug, OID_AUTO, bus_debug, CTLFLAG_RW, &bus_debug, 0, 140 "Debug bus code"); 141 142#define PDEBUG(a) if (bus_debug) {printf("%s:%d: ", __func__, __LINE__), printf a; printf("\n");} 143#define DEVICENAME(d) ((d)? device_get_name(d): "no device") 144#define DRIVERNAME(d) ((d)? d->name : "no driver") 145#define DEVCLANAME(d) ((d)? d->name : "no devclass") 146 147/* Produce the indenting, indent*2 spaces plus a '.' ahead of that to 148 * prevent syslog from deleting initial spaces 149 */ 150#define indentprintf(p) do { int iJ; printf("."); for (iJ=0; iJ<indent; iJ++) printf(" "); printf p ; } while (0) 151 152static void print_device_short(device_t dev, int indent); 153static void print_device(device_t dev, int indent); 154void print_device_tree_short(device_t dev, int indent); 155void print_device_tree(device_t dev, int indent); 156static void print_driver_short(driver_t *driver, int indent); 157static void print_driver(driver_t *driver, int indent); 158static void print_driver_list(driver_list_t drivers, int indent); 159static void print_devclass_short(devclass_t dc, int indent); 160static void print_devclass(devclass_t dc, int indent); 161void print_devclass_list_short(void); 162void print_devclass_list(void); 163 164#else 165/* Make the compiler ignore the function calls */ 166#define PDEBUG(a) /* nop */ 167#define DEVICENAME(d) /* nop */ 168#define DRIVERNAME(d) /* nop */ 169#define DEVCLANAME(d) /* nop */ 170 171#define print_device_short(d,i) /* nop */ 172#define print_device(d,i) /* nop */ 173#define print_device_tree_short(d,i) /* nop */ 174#define print_device_tree(d,i) /* nop */ 175#define print_driver_short(d,i) /* nop */ 176#define print_driver(d,i) /* nop */ 177#define print_driver_list(d,i) /* nop */ 178#define print_devclass_short(d,i) /* nop */ 179#define print_devclass(d,i) /* nop */ 180#define print_devclass_list_short() /* nop */ 181#define print_devclass_list() /* nop */ 182#endif 183 184/* 185 * /dev/devctl implementation 186 */ 187 188/* 189 * This design allows only one reader for /dev/devctl. This is not desirable 190 * in the long run, but will get a lot of hair out of this implementation. 191 * Maybe we should make this device a clonable device. 192 * 193 * Also note: we specifically do not attach a device to the device_t tree 194 * to avoid potential chicken and egg problems. One could argue that all 195 * of this belongs to the root node. One could also further argue that the 196 * sysctl interface that we have not might more properly be an ioctl 197 * interface, but at this stage of the game, I'm not inclined to rock that 198 * boat. 199 * 200 * I'm also not sure that the SIGIO support is done correctly or not, as 201 * I copied it from a driver that had SIGIO support that likely hasn't been 202 * tested since 3.4 or 2.2.8! 203 */ 204 205static int sysctl_devctl_disable(SYSCTL_HANDLER_ARGS); 206static int devctl_disable = 0; 207TUNABLE_INT("hw.bus.devctl_disable", &devctl_disable); 208SYSCTL_PROC(_hw_bus, OID_AUTO, devctl_disable, 209 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0, sysctl_devctl_disable, 210 "I", "devctl disable"); 211 212static d_open_t devopen; 213static d_close_t devclose; 214static d_read_t devread; 215static d_ioctl_t devioctl; 216static d_poll_t devpoll; 217 218#define CDEV_MAJOR 173 219static struct cdevsw dev_cdevsw = { 220 .d_open = devopen, 221 .d_close = devclose, 222 .d_read = devread, 223 .d_ioctl = devioctl, 224 .d_poll = devpoll, 225 .d_name = "devctl", 226 .d_maj = CDEV_MAJOR, 227}; 228 229struct dev_event_info 230{ 231 char *dei_data; 232 TAILQ_ENTRY(dev_event_info) dei_link; 233}; 234 235TAILQ_HEAD(devq, dev_event_info); 236 237struct dev_softc 238{ 239 int inuse; 240 int nonblock; 241 struct mtx mtx; 242 struct cv cv; 243 struct selinfo sel; 244 struct devq devq; 245 struct proc *async_proc; 246} devsoftc; 247 248dev_t devctl_dev; 249 250static void 251devinit(void) 252{ 253 devctl_dev = make_dev(&dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, 254 "devctl"); 255 mtx_init(&devsoftc.mtx, "dev mtx", "devd", MTX_DEF); 256 cv_init(&devsoftc.cv, "dev cv"); 257 TAILQ_INIT(&devsoftc.devq); 258} 259 260static int 261devopen(dev_t dev, int oflags, int devtype, d_thread_t *td) 262{ 263 if (devsoftc.inuse) 264 return (EBUSY); 265 /* move to init */ 266 devsoftc.inuse = 1; 267 devsoftc.nonblock = 0; 268 devsoftc.async_proc = NULL; 269 return (0); 270} 271 272static int 273devclose(dev_t dev, int fflag, int devtype, d_thread_t *td) 274{ 275 devsoftc.inuse = 0; 276 mtx_lock(&devsoftc.mtx); 277 cv_broadcast(&devsoftc.cv); 278 mtx_unlock(&devsoftc.mtx); 279 280 return (0); 281} 282 283/* 284 * The read channel for this device is used to report changes to 285 * userland in realtime. We are required to free the data as well as 286 * the n1 object because we allocate them separately. Also note that 287 * we return one record at a time. If you try to read this device a 288 * character at a time, you will loose the rest of the data. Listening 289 * programs are expected to cope. 290 */ 291static int 292devread(dev_t dev, struct uio *uio, int ioflag) 293{ 294 struct dev_event_info *n1; 295 int rv; 296 297 mtx_lock(&devsoftc.mtx); 298 while (TAILQ_EMPTY(&devsoftc.devq)) { 299 if (devsoftc.nonblock) { 300 mtx_unlock(&devsoftc.mtx); 301 return (EAGAIN); 302 } 303 rv = cv_wait_sig(&devsoftc.cv, &devsoftc.mtx); 304 if (rv) { 305 /* 306 * Need to translate ERESTART to EINTR here? -- jake 307 */ 308 mtx_unlock(&devsoftc.mtx); 309 return (rv); 310 } 311 } 312 n1 = TAILQ_FIRST(&devsoftc.devq); 313 TAILQ_REMOVE(&devsoftc.devq, n1, dei_link); 314 mtx_unlock(&devsoftc.mtx); 315 rv = uiomove(n1->dei_data, strlen(n1->dei_data), uio); 316 free(n1->dei_data, M_BUS); 317 free(n1, M_BUS); 318 return (rv); 319} 320 321static int 322devioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, d_thread_t *td) 323{ 324 switch (cmd) { 325 326 case FIONBIO: 327 if (*(int*)data) 328 devsoftc.nonblock = 1; 329 else 330 devsoftc.nonblock = 0; 331 return (0); 332 case FIOASYNC: 333 if (*(int*)data) 334 devsoftc.async_proc = td->td_proc; 335 else 336 devsoftc.async_proc = NULL; 337 return (0); 338 339 /* (un)Support for other fcntl() calls. */ 340 case FIOCLEX: 341 case FIONCLEX: 342 case FIONREAD: 343 case FIOSETOWN: 344 case FIOGETOWN: 345 default: 346 break; 347 } 348 return (ENOTTY); 349} 350 351static int 352devpoll(dev_t dev, int events, d_thread_t *td) 353{ 354 int revents = 0; 355 356 if (events & (POLLIN | POLLRDNORM)) 357 revents |= events & (POLLIN | POLLRDNORM); 358 359 if (events & (POLLOUT | POLLWRNORM)) 360 revents |= events & (POLLOUT | POLLWRNORM); 361 362 mtx_lock(&devsoftc.mtx); 363 if (events & POLLRDBAND) 364 if (!TAILQ_EMPTY(&devsoftc.devq)) 365 revents |= POLLRDBAND; 366 mtx_unlock(&devsoftc.mtx); 367 368 if (revents == 0) 369 selrecord(td, &devsoftc.sel); 370 371 return (revents); 372} 373 374/* 375 * Common routine that tries to make sending messages as easy as possible. 376 * We allocate memory for the data, copy strings into that, but do not 377 * free it unless there's an error. The dequeue part of the driver should 378 * free the data. We don't send data when the device is disabled. We do 379 * send data, even when we have no listeners, because we wish to avoid 380 * races relating to startup and restart of listening applications. 381 */ 382static void 383devaddq(const char *type, const char *what, device_t dev) 384{ 385 struct dev_event_info *n1 = NULL; 386 char *data = NULL; 387 char *loc; 388 const char *parstr; 389 390 if (devctl_disable) 391 return; 392 n1 = malloc(sizeof(*n1), M_BUS, M_NOWAIT); 393 if (n1 == NULL) 394 goto bad; 395 data = malloc(1024, M_BUS, M_NOWAIT); 396 if (data == NULL) 397 goto bad; 398 loc = malloc(1024, M_BUS, M_NOWAIT); 399 if (loc == NULL) 400 goto bad; 401 *loc = '\0'; 402 bus_child_location_str(dev, loc, 1024); 403 if (device_get_parent(dev) == NULL) 404 parstr = "."; /* Or '/' ? */ 405 else 406 parstr = device_get_nameunit(device_get_parent(dev)); 407 snprintf(data, 1024, "%s%s at %s on %s\n", type, what, loc, parstr); 408 free(loc, M_BUS); 409 n1->dei_data = data; 410 mtx_lock(&devsoftc.mtx); 411 TAILQ_INSERT_TAIL(&devsoftc.devq, n1, dei_link); 412 cv_broadcast(&devsoftc.cv); 413 mtx_unlock(&devsoftc.mtx); 414 selwakeup(&devsoftc.sel); 415 if (devsoftc.async_proc) 416 psignal(devsoftc.async_proc, SIGIO); 417 return; 418bad:; 419 free(data, M_BUS); 420 free(n1, M_BUS); 421 return; 422} 423 424/* 425 * A device was added to the tree. We are called just after it successfully 426 * attaches (that is, probe and attach success for this device). No call 427 * is made if a device is merely parented into the tree. See devnomatch 428 * if probe fails. If attach fails, no notification is sent (but maybe 429 * we should have a different message for this). 430 */ 431static void 432devadded(device_t dev) 433{ 434 devaddq("+", device_get_nameunit(dev), dev); 435} 436 437/* 438 * A device was removed from the tree. We are called just before this 439 * happens. 440 */ 441static void 442devremoved(device_t dev) 443{ 444 devaddq("-", device_get_nameunit(dev), dev); 445} 446 447/* 448 * Called when there's no match for this device. This is only called 449 * the first time that no match happens, so we don't keep getitng this 450 * message. Should that prove to be undesirable, we can change it. 451 * This is called when all drivers that can attach to a given bus 452 * decline to accept this device. Other errrors may not be detected. 453 */ 454static void 455devnomatch(device_t dev) 456{ 457 char *pnp = NULL; 458 459 pnp = malloc(1024, M_BUS, M_NOWAIT); 460 if (pnp == NULL) 461 return; 462 *pnp = '\0'; 463 bus_child_pnpinfo_str(dev, pnp, 1024); 464 devaddq("?", pnp, dev); 465 free(pnp, M_BUS); 466 return; 467} 468 469static int 470sysctl_devctl_disable(SYSCTL_HANDLER_ARGS) 471{ 472 struct dev_event_info *n1; 473 int dis, error; 474 475 dis = devctl_disable; 476 error = sysctl_handle_int(oidp, &dis, 0, req); 477 if (error || !req->newptr) 478 return (error); 479 mtx_lock(&devsoftc.mtx); 480 devctl_disable = dis; 481 if (dis) { 482 while (!TAILQ_EMPTY(&devsoftc.devq)) { 483 n1 = TAILQ_FIRST(&devsoftc.devq); 484 TAILQ_REMOVE(&devsoftc.devq, n1, dei_link); 485 free(n1->dei_data, M_BUS); 486 free(n1, M_BUS); 487 } 488 } 489 mtx_unlock(&devsoftc.mtx); 490 return (0); 491} 492 493/* End of /dev/devctl code */ 494 495TAILQ_HEAD(,device) bus_data_devices; 496static int bus_data_generation = 1; 497 498kobj_method_t null_methods[] = { 499 { 0, 0 } 500}; 501 502DEFINE_CLASS(null, null_methods, 0); 503 504/* 505 * Devclass implementation 506 */ 507 508static devclass_list_t devclasses = TAILQ_HEAD_INITIALIZER(devclasses); 509 510static devclass_t 511devclass_find_internal(const char *classname, int create) 512{ 513 devclass_t dc; 514 515 PDEBUG(("looking for %s", classname)); 516 if (!classname) 517 return (NULL); 518 519 TAILQ_FOREACH(dc, &devclasses, link) { 520 if (!strcmp(dc->name, classname)) 521 return (dc); 522 } 523 524 PDEBUG(("%s not found%s", classname, (create? ", creating": ""))); 525 if (create) { 526 dc = malloc(sizeof(struct devclass) + strlen(classname) + 1, 527 M_BUS, M_NOWAIT|M_ZERO); 528 if (!dc) 529 return (NULL); 530 dc->name = (char*) (dc + 1); 531 strcpy(dc->name, classname); 532 TAILQ_INIT(&dc->drivers); 533 TAILQ_INSERT_TAIL(&devclasses, dc, link); 534 535 bus_data_generation_update(); 536 } 537 538 return (dc); 539} 540 541devclass_t 542devclass_create(const char *classname) 543{ 544 return (devclass_find_internal(classname, TRUE)); 545} 546 547devclass_t 548devclass_find(const char *classname) 549{ 550 return (devclass_find_internal(classname, FALSE)); 551} 552 553int 554devclass_add_driver(devclass_t dc, driver_t *driver) 555{ 556 driverlink_t dl; 557 int i; 558 559 PDEBUG(("%s", DRIVERNAME(driver))); 560 561 dl = malloc(sizeof *dl, M_BUS, M_NOWAIT|M_ZERO); 562 if (!dl) 563 return (ENOMEM); 564 565 /* 566 * Compile the driver's methods. Also increase the reference count 567 * so that the class doesn't get freed when the last instance 568 * goes. This means we can safely use static methods and avoids a 569 * double-free in devclass_delete_driver. 570 */ 571 kobj_class_compile((kobj_class_t) driver); 572 573 /* 574 * Make sure the devclass which the driver is implementing exists. 575 */ 576 devclass_find_internal(driver->name, TRUE); 577 578 dl->driver = driver; 579 TAILQ_INSERT_TAIL(&dc->drivers, dl, link); 580 driver->refs++; 581 582 /* 583 * Call BUS_DRIVER_ADDED for any existing busses in this class. 584 */ 585 for (i = 0; i < dc->maxunit; i++) 586 if (dc->devices[i]) 587 BUS_DRIVER_ADDED(dc->devices[i], driver); 588 589 bus_data_generation_update(); 590 return (0); 591} 592 593int 594devclass_delete_driver(devclass_t busclass, driver_t *driver) 595{ 596 devclass_t dc = devclass_find(driver->name); 597 driverlink_t dl; 598 device_t dev; 599 int i; 600 int error; 601 602 PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass))); 603 604 if (!dc) 605 return (0); 606 607 /* 608 * Find the link structure in the bus' list of drivers. 609 */ 610 TAILQ_FOREACH(dl, &busclass->drivers, link) { 611 if (dl->driver == driver) 612 break; 613 } 614 615 if (!dl) { 616 PDEBUG(("%s not found in %s list", driver->name, 617 busclass->name)); 618 return (ENOENT); 619 } 620 621 /* 622 * Disassociate from any devices. We iterate through all the 623 * devices in the devclass of the driver and detach any which are 624 * using the driver and which have a parent in the devclass which 625 * we are deleting from. 626 * 627 * Note that since a driver can be in multiple devclasses, we 628 * should not detach devices which are not children of devices in 629 * the affected devclass. 630 */ 631 for (i = 0; i < dc->maxunit; i++) { 632 if (dc->devices[i]) { 633 dev = dc->devices[i]; 634 if (dev->driver == driver && dev->parent && 635 dev->parent->devclass == busclass) { 636 if ((error = device_detach(dev)) != 0) 637 return (error); 638 device_set_driver(dev, NULL); 639 } 640 } 641 } 642 643 TAILQ_REMOVE(&busclass->drivers, dl, link); 644 free(dl, M_BUS); 645 646 driver->refs--; 647 if (driver->refs == 0) 648 kobj_class_free((kobj_class_t) driver); 649 650 bus_data_generation_update(); 651 return (0); 652} 653 654static driverlink_t 655devclass_find_driver_internal(devclass_t dc, const char *classname) 656{ 657 driverlink_t dl; 658 659 PDEBUG(("%s in devclass %s", classname, DEVCLANAME(dc))); 660 661 TAILQ_FOREACH(dl, &dc->drivers, link) { 662 if (!strcmp(dl->driver->name, classname)) 663 return (dl); 664 } 665 666 PDEBUG(("not found")); 667 return (NULL); 668} 669 670driver_t * 671devclass_find_driver(devclass_t dc, const char *classname) 672{ 673 driverlink_t dl; 674 675 dl = devclass_find_driver_internal(dc, classname); 676 if (dl) 677 return (dl->driver); 678 return (NULL); 679} 680 681const char * 682devclass_get_name(devclass_t dc) 683{ 684 return (dc->name); 685} 686 687device_t 688devclass_get_device(devclass_t dc, int unit) 689{ 690 if (dc == NULL || unit < 0 || unit >= dc->maxunit) 691 return (NULL); 692 return (dc->devices[unit]); 693} 694 695void * 696devclass_get_softc(devclass_t dc, int unit) 697{ 698 device_t dev; 699 700 dev = devclass_get_device(dc, unit); 701 if (!dev) 702 return (NULL); 703 704 return (device_get_softc(dev)); 705} 706 707int 708devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp) 709{ 710 int i; 711 int count; 712 device_t *list; 713 714 count = 0; 715 for (i = 0; i < dc->maxunit; i++) 716 if (dc->devices[i]) 717 count++; 718 719 list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT|M_ZERO); 720 if (!list) 721 return (ENOMEM); 722 723 count = 0; 724 for (i = 0; i < dc->maxunit; i++) { 725 if (dc->devices[i]) { 726 list[count] = dc->devices[i]; 727 count++; 728 } 729 } 730 731 *devlistp = list; 732 *devcountp = count; 733 734 return (0); 735} 736 737int 738devclass_get_maxunit(devclass_t dc) 739{ 740 return (dc->maxunit); 741} 742 743int 744devclass_find_free_unit(devclass_t dc, int unit) 745{ 746 if (dc == NULL) 747 return (unit); 748 while (unit < dc->maxunit && dc->devices[unit] != NULL) 749 unit++; 750 return (unit); 751} 752 753static int 754devclass_alloc_unit(devclass_t dc, int *unitp) 755{ 756 int unit = *unitp; 757 758 PDEBUG(("unit %d in devclass %s", unit, DEVCLANAME(dc))); 759 760 /* If we were given a wired unit number, check for existing device */ 761 /* XXX imp XXX */ 762 if (unit != -1) { 763 if (unit >= 0 && unit < dc->maxunit && 764 dc->devices[unit] != NULL) { 765 if (bootverbose) 766 printf("%s: %s%d already exists; skipping it\n", 767 dc->name, dc->name, *unitp); 768 return (EEXIST); 769 } 770 } else { 771 /* Unwired device, find the next available slot for it */ 772 unit = 0; 773 while (unit < dc->maxunit && dc->devices[unit] != NULL) 774 unit++; 775 } 776 777 /* 778 * We've selected a unit beyond the length of the table, so let's 779 * extend the table to make room for all units up to and including 780 * this one. 781 */ 782 if (unit >= dc->maxunit) { 783 device_t *newlist; 784 int newsize; 785 786 newsize = roundup((unit + 1), MINALLOCSIZE / sizeof(device_t)); 787 newlist = malloc(sizeof(device_t) * newsize, M_BUS, M_NOWAIT); 788 if (!newlist) 789 return (ENOMEM); 790 bcopy(dc->devices, newlist, sizeof(device_t) * dc->maxunit); 791 bzero(newlist + dc->maxunit, 792 sizeof(device_t) * (newsize - dc->maxunit)); 793 if (dc->devices) 794 free(dc->devices, M_BUS); 795 dc->devices = newlist; 796 dc->maxunit = newsize; 797 } 798 PDEBUG(("now: unit %d in devclass %s", unit, DEVCLANAME(dc))); 799 800 *unitp = unit; 801 return (0); 802} 803 804static int 805devclass_add_device(devclass_t dc, device_t dev) 806{ 807 int buflen, error; 808 809 PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc))); 810 811 buflen = snprintf(NULL, 0, "%s%d$", dc->name, dev->unit); 812 if (buflen < 0) 813 return (ENOMEM); 814 dev->nameunit = malloc(buflen, M_BUS, M_NOWAIT|M_ZERO); 815 if (!dev->nameunit) 816 return (ENOMEM); 817 818 if ((error = devclass_alloc_unit(dc, &dev->unit)) != 0) { 819 free(dev->nameunit, M_BUS); 820 dev->nameunit = NULL; 821 return (error); 822 } 823 dc->devices[dev->unit] = dev; 824 dev->devclass = dc; 825 snprintf(dev->nameunit, buflen, "%s%d", dc->name, dev->unit); 826 827 return (0); 828} 829 830static int 831devclass_delete_device(devclass_t dc, device_t dev) 832{ 833 if (!dc || !dev) 834 return (0); 835 836 PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc))); 837 838 if (dev->devclass != dc || dc->devices[dev->unit] != dev) 839 panic("devclass_delete_device: inconsistent device class"); 840 dc->devices[dev->unit] = NULL; 841 if (dev->flags & DF_WILDCARD) 842 dev->unit = -1; 843 dev->devclass = NULL; 844 free(dev->nameunit, M_BUS); 845 dev->nameunit = NULL; 846 847 return (0); 848} 849 850static device_t 851make_device(device_t parent, const char *name, int unit) 852{ 853 device_t dev; 854 devclass_t dc; 855 856 PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit)); 857 858 if (name) { 859 dc = devclass_find_internal(name, TRUE); 860 if (!dc) { 861 printf("make_device: can't find device class %s\n", 862 name); 863 return (NULL); 864 } 865 } else { 866 dc = NULL; 867 } 868 869 dev = malloc(sizeof(struct device), M_BUS, M_NOWAIT|M_ZERO); 870 if (!dev) 871 return (NULL); 872 873 dev->parent = parent; 874 TAILQ_INIT(&dev->children); 875 kobj_init((kobj_t) dev, &null_class); 876 dev->driver = NULL; 877 dev->devclass = NULL; 878 dev->unit = unit; 879 dev->nameunit = NULL; 880 dev->desc = NULL; 881 dev->busy = 0; 882 dev->devflags = 0; 883 dev->flags = DF_ENABLED; 884 dev->order = 0; 885 if (unit == -1) 886 dev->flags |= DF_WILDCARD; 887 if (name) { 888 dev->flags |= DF_FIXEDCLASS; 889 if (devclass_add_device(dc, dev)) { 890 kobj_delete((kobj_t) dev, M_BUS); 891 return (NULL); 892 } 893 } 894 dev->ivars = NULL; 895 dev->softc = NULL; 896 897 dev->state = DS_NOTPRESENT; 898 899 TAILQ_INSERT_TAIL(&bus_data_devices, dev, devlink); 900 bus_data_generation_update(); 901 902 return (dev); 903} 904 905static int 906device_print_child(device_t dev, device_t child) 907{ 908 int retval = 0; 909 910 if (device_is_alive(child)) 911 retval += BUS_PRINT_CHILD(dev, child); 912 else 913 retval += device_printf(child, " not found\n"); 914 915 return (retval); 916} 917 918device_t 919device_add_child(device_t dev, const char *name, int unit) 920{ 921 return (device_add_child_ordered(dev, 0, name, unit)); 922} 923 924device_t 925device_add_child_ordered(device_t dev, int order, const char *name, int unit) 926{ 927 device_t child; 928 device_t place; 929 930 PDEBUG(("%s at %s with order %d as unit %d", 931 name, DEVICENAME(dev), order, unit)); 932 933 child = make_device(dev, name, unit); 934 if (child == NULL) 935 return (child); 936 child->order = order; 937 938 TAILQ_FOREACH(place, &dev->children, link) { 939 if (place->order > order) 940 break; 941 } 942 943 if (place) { 944 /* 945 * The device 'place' is the first device whose order is 946 * greater than the new child. 947 */ 948 TAILQ_INSERT_BEFORE(place, child, link); 949 } else { 950 /* 951 * The new child's order is greater or equal to the order of 952 * any existing device. Add the child to the tail of the list. 953 */ 954 TAILQ_INSERT_TAIL(&dev->children, child, link); 955 } 956 957 bus_data_generation_update(); 958 return (child); 959} 960 961int 962device_delete_child(device_t dev, device_t child) 963{ 964 int error; 965 device_t grandchild; 966 967 PDEBUG(("%s from %s", DEVICENAME(child), DEVICENAME(dev))); 968 969 /* remove children first */ 970 while ( (grandchild = TAILQ_FIRST(&child->children)) ) { 971 error = device_delete_child(child, grandchild); 972 if (error) 973 return (error); 974 } 975 976 if ((error = device_detach(child)) != 0) 977 return (error); 978 if (child->devclass) 979 devclass_delete_device(child->devclass, child); 980 TAILQ_REMOVE(&dev->children, child, link); 981 TAILQ_REMOVE(&bus_data_devices, child, devlink); 982 device_set_desc(child, NULL); 983 kobj_delete((kobj_t) child, M_BUS); 984 985 bus_data_generation_update(); 986 return (0); 987} 988 989/* 990 * Find only devices attached to this bus. 991 */ 992device_t 993device_find_child(device_t dev, const char *classname, int unit) 994{ 995 devclass_t dc; 996 device_t child; 997 998 dc = devclass_find(classname); 999 if (!dc) 1000 return (NULL); 1001 1002 child = devclass_get_device(dc, unit); 1003 if (child && child->parent == dev) 1004 return (child); 1005 return (NULL); 1006} 1007 1008static driverlink_t 1009first_matching_driver(devclass_t dc, device_t dev) 1010{ 1011 if (dev->devclass) 1012 return (devclass_find_driver_internal(dc, dev->devclass->name)); 1013 return (TAILQ_FIRST(&dc->drivers)); 1014} 1015 1016static driverlink_t 1017next_matching_driver(devclass_t dc, device_t dev, driverlink_t last) 1018{ 1019 if (dev->devclass) { 1020 driverlink_t dl; 1021 for (dl = TAILQ_NEXT(last, link); dl; dl = TAILQ_NEXT(dl, link)) 1022 if (!strcmp(dev->devclass->name, dl->driver->name)) 1023 return (dl); 1024 return (NULL); 1025 } 1026 return (TAILQ_NEXT(last, link)); 1027} 1028 1029static int 1030device_probe_child(device_t dev, device_t child) 1031{ 1032 devclass_t dc; 1033 driverlink_t best = 0; 1034 driverlink_t dl; 1035 int result, pri = 0; 1036 int hasclass = (child->devclass != 0); 1037 1038 dc = dev->devclass; 1039 if (!dc) 1040 panic("device_probe_child: parent device has no devclass"); 1041 1042 if (child->state == DS_ALIVE) 1043 return (0); 1044 1045 for (dl = first_matching_driver(dc, child); 1046 dl; 1047 dl = next_matching_driver(dc, child, dl)) { 1048 PDEBUG(("Trying %s", DRIVERNAME(dl->driver))); 1049 device_set_driver(child, dl->driver); 1050 if (!hasclass) 1051 device_set_devclass(child, dl->driver->name); 1052 result = DEVICE_PROBE(child); 1053 if (!hasclass) 1054 device_set_devclass(child, 0); 1055 1056 /* 1057 * If the driver returns SUCCESS, there can be no higher match 1058 * for this device. 1059 */ 1060 if (result == 0) { 1061 best = dl; 1062 pri = 0; 1063 break; 1064 } 1065 1066 /* 1067 * The driver returned an error so it certainly doesn't match. 1068 */ 1069 if (result > 0) { 1070 device_set_driver(child, 0); 1071 continue; 1072 } 1073 1074 /* 1075 * A priority lower than SUCCESS, remember the best matching 1076 * driver. Initialise the value of pri for the first match. 1077 */ 1078 if (best == 0 || result > pri) { 1079 best = dl; 1080 pri = result; 1081 continue; 1082 } 1083 } 1084 1085 /* 1086 * If we found a driver, change state and initialise the devclass. 1087 */ 1088 if (best) { 1089 if (!child->devclass) 1090 device_set_devclass(child, best->driver->name); 1091 device_set_driver(child, best->driver); 1092 if (pri < 0) { 1093 /* 1094 * A bit bogus. Call the probe method again to make 1095 * sure that we have the right description. 1096 */ 1097 DEVICE_PROBE(child); 1098 } 1099 child->state = DS_ALIVE; 1100 1101 bus_data_generation_update(); 1102 return (0); 1103 } 1104 1105 return (ENXIO); 1106} 1107 1108device_t 1109device_get_parent(device_t dev) 1110{ 1111 return (dev->parent); 1112} 1113 1114int 1115device_get_children(device_t dev, device_t **devlistp, int *devcountp) 1116{ 1117 int count; 1118 device_t child; 1119 device_t *list; 1120 1121 count = 0; 1122 TAILQ_FOREACH(child, &dev->children, link) { 1123 count++; 1124 } 1125 1126 list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT|M_ZERO); 1127 if (!list) 1128 return (ENOMEM); 1129 1130 count = 0; 1131 TAILQ_FOREACH(child, &dev->children, link) { 1132 list[count] = child; 1133 count++; 1134 } 1135 1136 *devlistp = list; 1137 *devcountp = count; 1138 1139 return (0); 1140} 1141 1142driver_t * 1143device_get_driver(device_t dev) 1144{ 1145 return (dev->driver); 1146} 1147 1148devclass_t 1149device_get_devclass(device_t dev) 1150{ 1151 return (dev->devclass); 1152} 1153 1154const char * 1155device_get_name(device_t dev) 1156{ 1157 if (dev->devclass) 1158 return (devclass_get_name(dev->devclass)); 1159 return (NULL); 1160} 1161 1162const char * 1163device_get_nameunit(device_t dev) 1164{ 1165 return (dev->nameunit); 1166} 1167 1168int 1169device_get_unit(device_t dev) 1170{ 1171 return (dev->unit); 1172} 1173 1174const char * 1175device_get_desc(device_t dev) 1176{ 1177 return (dev->desc); 1178} 1179 1180u_int32_t 1181device_get_flags(device_t dev) 1182{ 1183 return (dev->devflags); 1184} 1185 1186int 1187device_print_prettyname(device_t dev) 1188{ 1189 const char *name = device_get_name(dev); 1190 1191 if (name == 0) 1192 return (printf("unknown: ")); 1193 return (printf("%s%d: ", name, device_get_unit(dev))); 1194} 1195 1196int 1197device_printf(device_t dev, const char * fmt, ...) 1198{ 1199 va_list ap; 1200 int retval; 1201 1202 retval = device_print_prettyname(dev); 1203 va_start(ap, fmt); 1204 retval += vprintf(fmt, ap); 1205 va_end(ap); 1206 return (retval); 1207} 1208 1209static void 1210device_set_desc_internal(device_t dev, const char* desc, int copy) 1211{ 1212 if (dev->desc && (dev->flags & DF_DESCMALLOCED)) { 1213 free(dev->desc, M_BUS); 1214 dev->flags &= ~DF_DESCMALLOCED; 1215 dev->desc = NULL; 1216 } 1217 1218 if (copy && desc) { 1219 dev->desc = malloc(strlen(desc) + 1, M_BUS, M_NOWAIT); 1220 if (dev->desc) { 1221 strcpy(dev->desc, desc); 1222 dev->flags |= DF_DESCMALLOCED; 1223 } 1224 } else { 1225 /* Avoid a -Wcast-qual warning */ 1226 dev->desc = (char *)(uintptr_t) desc; 1227 } 1228 1229 bus_data_generation_update(); 1230} 1231 1232void 1233device_set_desc(device_t dev, const char* desc) 1234{ 1235 device_set_desc_internal(dev, desc, FALSE); 1236} 1237 1238void 1239device_set_desc_copy(device_t dev, const char* desc) 1240{ 1241 device_set_desc_internal(dev, desc, TRUE); 1242} 1243 1244void 1245device_set_flags(device_t dev, u_int32_t flags) 1246{ 1247 dev->devflags = flags; 1248} 1249 1250void * 1251device_get_softc(device_t dev) 1252{ 1253 return (dev->softc); 1254} 1255 1256void 1257device_set_softc(device_t dev, void *softc) 1258{ 1259 if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) 1260 free(dev->softc, M_BUS); 1261 dev->softc = softc; 1262 if (dev->softc) 1263 dev->flags |= DF_EXTERNALSOFTC; 1264 else 1265 dev->flags &= ~DF_EXTERNALSOFTC; 1266} 1267 1268void * 1269device_get_ivars(device_t dev) 1270{ 1271 1272 KASSERT(dev != NULL, ("device_get_ivars(NULL, ...)")); 1273 return (dev->ivars); 1274} 1275 1276void 1277device_set_ivars(device_t dev, void * ivars) 1278{ 1279 1280 KASSERT(dev != NULL, ("device_set_ivars(NULL, ...)")); 1281 dev->ivars = ivars; 1282} 1283 1284device_state_t 1285device_get_state(device_t dev) 1286{ 1287 return (dev->state); 1288} 1289 1290void 1291device_enable(device_t dev) 1292{ 1293 dev->flags |= DF_ENABLED; 1294} 1295 1296void 1297device_disable(device_t dev) 1298{ 1299 dev->flags &= ~DF_ENABLED; 1300} 1301 1302void 1303device_busy(device_t dev) 1304{ 1305 if (dev->state < DS_ATTACHED) 1306 panic("device_busy: called for unattached device"); 1307 if (dev->busy == 0 && dev->parent) 1308 device_busy(dev->parent); 1309 dev->busy++; 1310 dev->state = DS_BUSY; 1311} 1312 1313void 1314device_unbusy(device_t dev) 1315{ 1316 if (dev->state != DS_BUSY) 1317 panic("device_unbusy: called for non-busy device"); 1318 dev->busy--; 1319 if (dev->busy == 0) { 1320 if (dev->parent) 1321 device_unbusy(dev->parent); 1322 dev->state = DS_ATTACHED; 1323 } 1324} 1325 1326void 1327device_quiet(device_t dev) 1328{ 1329 dev->flags |= DF_QUIET; 1330} 1331 1332void 1333device_verbose(device_t dev) 1334{ 1335 dev->flags &= ~DF_QUIET; 1336} 1337 1338int 1339device_is_quiet(device_t dev) 1340{ 1341 return ((dev->flags & DF_QUIET) != 0); 1342} 1343 1344int 1345device_is_enabled(device_t dev) 1346{ 1347 return ((dev->flags & DF_ENABLED) != 0); 1348} 1349 1350int 1351device_is_alive(device_t dev) 1352{ 1353 return (dev->state >= DS_ALIVE); 1354} 1355 1356int 1357device_set_devclass(device_t dev, const char *classname) 1358{ 1359 devclass_t dc; 1360 int error; 1361 1362 if (!classname) { 1363 if (dev->devclass) 1364 devclass_delete_device(dev->devclass, dev); 1365 return (0); 1366 } 1367 1368 if (dev->devclass) { 1369 printf("device_set_devclass: device class already set\n"); 1370 return (EINVAL); 1371 } 1372 1373 dc = devclass_find_internal(classname, TRUE); 1374 if (!dc) 1375 return (ENOMEM); 1376 1377 error = devclass_add_device(dc, dev); 1378 1379 bus_data_generation_update(); 1380 return (error); 1381} 1382 1383int 1384device_set_driver(device_t dev, driver_t *driver) 1385{ 1386 if (dev->state >= DS_ATTACHED) 1387 return (EBUSY); 1388 1389 if (dev->driver == driver) 1390 return (0); 1391 1392 if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) { 1393 free(dev->softc, M_BUS); 1394 dev->softc = NULL; 1395 } 1396 kobj_delete((kobj_t) dev, 0); 1397 dev->driver = driver; 1398 if (driver) { 1399 kobj_init((kobj_t) dev, (kobj_class_t) driver); 1400 if (!(dev->flags & DF_EXTERNALSOFTC) && driver->size > 0) { 1401 dev->softc = malloc(driver->size, M_BUS, 1402 M_NOWAIT | M_ZERO); 1403 if (!dev->softc) { 1404 kobj_delete((kobj_t) dev, 0); 1405 kobj_init((kobj_t) dev, &null_class); 1406 dev->driver = NULL; 1407 return (ENOMEM); 1408 } 1409 } 1410 } else { 1411 kobj_init((kobj_t) dev, &null_class); 1412 } 1413 1414 bus_data_generation_update(); 1415 return (0); 1416} 1417 1418int 1419device_probe_and_attach(device_t dev) 1420{ 1421 device_t bus = dev->parent; 1422 int error = 0; 1423 int hasclass = (dev->devclass != 0); 1424 1425 if (dev->state >= DS_ALIVE) 1426 return (0); 1427 1428 if (dev->flags & DF_ENABLED) { 1429 error = device_probe_child(bus, dev); 1430 if (!error) { 1431 if (!device_is_quiet(dev)) 1432 device_print_child(bus, dev); 1433 error = DEVICE_ATTACH(dev); 1434 if (!error) { 1435 dev->state = DS_ATTACHED; 1436 devadded(dev); 1437 } else { 1438 printf("device_probe_and_attach: %s%d attach returned %d\n", 1439 dev->driver->name, dev->unit, error); 1440 /* Unset the class; set in device_probe_child */ 1441 if (!hasclass) 1442 device_set_devclass(dev, 0); 1443 device_set_driver(dev, NULL); 1444 dev->state = DS_NOTPRESENT; 1445 } 1446 } else { 1447 if (!(dev->flags & DF_DONENOMATCH)) { 1448 BUS_PROBE_NOMATCH(bus, dev); 1449 devnomatch(dev); 1450 dev->flags |= DF_DONENOMATCH; 1451 } 1452 } 1453 } else { 1454 if (bootverbose) { 1455 device_print_prettyname(dev); 1456 printf("not probed (disabled)\n"); 1457 } 1458 } 1459 1460 return (error); 1461} 1462 1463int 1464device_detach(device_t dev) 1465{ 1466 int error; 1467 1468 PDEBUG(("%s", DEVICENAME(dev))); 1469 if (dev->state == DS_BUSY) 1470 return (EBUSY); 1471 if (dev->state != DS_ATTACHED) 1472 return (0); 1473 1474 if ((error = DEVICE_DETACH(dev)) != 0) 1475 return (error); 1476 devremoved(dev); 1477 device_printf(dev, "detached\n"); 1478 if (dev->parent) 1479 BUS_CHILD_DETACHED(dev->parent, dev); 1480 1481 if (!(dev->flags & DF_FIXEDCLASS)) 1482 devclass_delete_device(dev->devclass, dev); 1483 1484 dev->state = DS_NOTPRESENT; 1485 device_set_driver(dev, NULL); 1486 1487 return (0); 1488} 1489 1490int 1491device_shutdown(device_t dev) 1492{ 1493 if (dev->state < DS_ATTACHED) 1494 return (0); 1495 return (DEVICE_SHUTDOWN(dev)); 1496} 1497 1498int 1499device_set_unit(device_t dev, int unit) 1500{ 1501 devclass_t dc; 1502 int err; 1503 1504 dc = device_get_devclass(dev); 1505 if (unit < dc->maxunit && dc->devices[unit]) 1506 return (EBUSY); 1507 err = devclass_delete_device(dc, dev); 1508 if (err) 1509 return (err); 1510 dev->unit = unit; 1511 err = devclass_add_device(dc, dev); 1512 if (err) 1513 return (err); 1514 1515 bus_data_generation_update(); 1516 return (0); 1517} 1518 1519/*======================================*/ 1520/* 1521 * Some useful method implementations to make life easier for bus drivers. 1522 */ 1523 1524void 1525resource_list_init(struct resource_list *rl) 1526{ 1527 SLIST_INIT(rl); 1528} 1529 1530void 1531resource_list_free(struct resource_list *rl) 1532{ 1533 struct resource_list_entry *rle; 1534 1535 while ((rle = SLIST_FIRST(rl)) != NULL) { 1536 if (rle->res) 1537 panic("resource_list_free: resource entry is busy"); 1538 SLIST_REMOVE_HEAD(rl, link); 1539 free(rle, M_BUS); 1540 } 1541} 1542 1543int 1544resource_list_add_next(struct resource_list *rl, int type, u_long start, 1545 u_long end, u_long count) 1546{ 1547 int rid; 1548 1549 rid = 0; 1550 while (resource_list_find(rl, type, rid) != NULL) 1551 rid++; 1552 resource_list_add(rl, type, rid, start, end, count); 1553 return (rid); 1554} 1555 1556void 1557resource_list_add(struct resource_list *rl, int type, int rid, 1558 u_long start, u_long end, u_long count) 1559{ 1560 struct resource_list_entry *rle; 1561 1562 rle = resource_list_find(rl, type, rid); 1563 if (!rle) { 1564 rle = malloc(sizeof(struct resource_list_entry), M_BUS, 1565 M_NOWAIT); 1566 if (!rle) 1567 panic("resource_list_add: can't record entry"); 1568 SLIST_INSERT_HEAD(rl, rle, link); 1569 rle->type = type; 1570 rle->rid = rid; 1571 rle->res = NULL; 1572 } 1573 1574 if (rle->res) 1575 panic("resource_list_add: resource entry is busy"); 1576 1577 rle->start = start; 1578 rle->end = end; 1579 rle->count = count; 1580} 1581 1582struct resource_list_entry * 1583resource_list_find(struct resource_list *rl, int type, int rid) 1584{ 1585 struct resource_list_entry *rle; 1586 1587 SLIST_FOREACH(rle, rl, link) { 1588 if (rle->type == type && rle->rid == rid) 1589 return (rle); 1590 } 1591 return (NULL); 1592} 1593 1594void 1595resource_list_delete(struct resource_list *rl, int type, int rid) 1596{ 1597 struct resource_list_entry *rle = resource_list_find(rl, type, rid); 1598 1599 if (rle) { 1600 if (rle->res != NULL) 1601 panic("resource_list_delete: resource has not been released"); 1602 SLIST_REMOVE(rl, rle, resource_list_entry, link); 1603 free(rle, M_BUS); 1604 } 1605} 1606 1607struct resource * 1608resource_list_alloc(struct resource_list *rl, device_t bus, device_t child, 1609 int type, int *rid, u_long start, u_long end, u_long count, u_int flags) 1610{ 1611 struct resource_list_entry *rle = 0; 1612 int passthrough = (device_get_parent(child) != bus); 1613 int isdefault = (start == 0UL && end == ~0UL); 1614 1615 if (passthrough) { 1616 return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, 1617 type, rid, start, end, count, flags)); 1618 } 1619 1620 rle = resource_list_find(rl, type, *rid); 1621 1622 if (!rle) 1623 return (NULL); /* no resource of that type/rid */ 1624 1625 if (rle->res) 1626 panic("resource_list_alloc: resource entry is busy"); 1627 1628 if (isdefault) { 1629 start = rle->start; 1630 count = ulmax(count, rle->count); 1631 end = ulmax(rle->end, start + count - 1); 1632 } 1633 1634 rle->res = BUS_ALLOC_RESOURCE(device_get_parent(bus), child, 1635 type, rid, start, end, count, flags); 1636 1637 /* 1638 * Record the new range. 1639 */ 1640 if (rle->res) { 1641 rle->start = rman_get_start(rle->res); 1642 rle->end = rman_get_end(rle->res); 1643 rle->count = count; 1644 } 1645 1646 return (rle->res); 1647} 1648 1649int 1650resource_list_release(struct resource_list *rl, device_t bus, device_t child, 1651 int type, int rid, struct resource *res) 1652{ 1653 struct resource_list_entry *rle = 0; 1654 int passthrough = (device_get_parent(child) != bus); 1655 int error; 1656 1657 if (passthrough) { 1658 return (BUS_RELEASE_RESOURCE(device_get_parent(bus), child, 1659 type, rid, res)); 1660 } 1661 1662 rle = resource_list_find(rl, type, rid); 1663 1664 if (!rle) 1665 panic("resource_list_release: can't find resource"); 1666 if (!rle->res) 1667 panic("resource_list_release: resource entry is not busy"); 1668 1669 error = BUS_RELEASE_RESOURCE(device_get_parent(bus), child, 1670 type, rid, res); 1671 if (error) 1672 return (error); 1673 1674 rle->res = NULL; 1675 return (0); 1676} 1677 1678int 1679resource_list_print_type(struct resource_list *rl, const char *name, int type, 1680 const char *format) 1681{ 1682 struct resource_list_entry *rle; 1683 int printed, retval; 1684 1685 printed = 0; 1686 retval = 0; 1687 /* Yes, this is kinda cheating */ 1688 SLIST_FOREACH(rle, rl, link) { 1689 if (rle->type == type) { 1690 if (printed == 0) 1691 retval += printf(" %s ", name); 1692 else 1693 retval += printf(","); 1694 printed++; 1695 retval += printf(format, rle->start); 1696 if (rle->count > 1) { 1697 retval += printf("-"); 1698 retval += printf(format, rle->start + 1699 rle->count - 1); 1700 } 1701 } 1702 } 1703 return (retval); 1704} 1705 1706/* 1707 * Call DEVICE_IDENTIFY for each driver. 1708 */ 1709int 1710bus_generic_probe(device_t dev) 1711{ 1712 devclass_t dc = dev->devclass; 1713 driverlink_t dl; 1714 1715 TAILQ_FOREACH(dl, &dc->drivers, link) { 1716 DEVICE_IDENTIFY(dl->driver, dev); 1717 } 1718 1719 return (0); 1720} 1721 1722int 1723bus_generic_attach(device_t dev) 1724{ 1725 device_t child; 1726 1727 TAILQ_FOREACH(child, &dev->children, link) { 1728 device_probe_and_attach(child); 1729 } 1730 1731 return (0); 1732} 1733 1734int 1735bus_generic_detach(device_t dev) 1736{ 1737 device_t child; 1738 int error; 1739 1740 if (dev->state != DS_ATTACHED) 1741 return (EBUSY); 1742 1743 TAILQ_FOREACH(child, &dev->children, link) { 1744 if ((error = device_detach(child)) != 0) 1745 return (error); 1746 } 1747 1748 return (0); 1749} 1750 1751int 1752bus_generic_shutdown(device_t dev) 1753{ 1754 device_t child; 1755 1756 TAILQ_FOREACH(child, &dev->children, link) { 1757 device_shutdown(child); 1758 } 1759 1760 return (0); 1761} 1762 1763int 1764bus_generic_suspend(device_t dev) 1765{ 1766 int error; 1767 device_t child, child2; 1768 1769 TAILQ_FOREACH(child, &dev->children, link) { 1770 error = DEVICE_SUSPEND(child); 1771 if (error) { 1772 for (child2 = TAILQ_FIRST(&dev->children); 1773 child2 && child2 != child; 1774 child2 = TAILQ_NEXT(child2, link)) 1775 DEVICE_RESUME(child2); 1776 return (error); 1777 } 1778 } 1779 return (0); 1780} 1781 1782int 1783bus_generic_resume(device_t dev) 1784{ 1785 device_t child; 1786 1787 TAILQ_FOREACH(child, &dev->children, 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>", device_get_desc(child)); 1801 } else { 1802 retval += printf("%s", device_get_nameunit(child)); 1803 } 1804 1805 return (retval); 1806} 1807 1808int 1809bus_print_child_footer (device_t dev, device_t child) 1810{ 1811 return (printf(" on %s\n", device_get_nameunit(dev))); 1812} 1813 1814int 1815bus_generic_print_child(device_t dev, device_t child) 1816{ 1817 int retval = 0; 1818 1819 retval += bus_print_child_header(dev, child); 1820 retval += bus_print_child_footer(dev, child); 1821 1822 return (retval); 1823} 1824 1825int 1826bus_generic_read_ivar(device_t dev, device_t child, int index, 1827 uintptr_t * result) 1828{ 1829 return (ENOENT); 1830} 1831 1832int 1833bus_generic_write_ivar(device_t dev, device_t child, int index, 1834 uintptr_t value) 1835{ 1836 return (ENOENT); 1837} 1838 1839struct resource_list * 1840bus_generic_get_resource_list (device_t dev, device_t child) 1841{ 1842 return (NULL); 1843} 1844 1845void 1846bus_generic_driver_added(device_t dev, driver_t *driver) 1847{ 1848 device_t child; 1849 1850 DEVICE_IDENTIFY(driver, dev); 1851 TAILQ_FOREACH(child, &dev->children, link) { 1852 if (child->state == DS_NOTPRESENT) 1853 device_probe_and_attach(child); 1854 } 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, void **cookiep) 1860{ 1861 /* Propagate up the bus hierarchy until someone handles it. */ 1862 if (dev->parent) 1863 return (BUS_SETUP_INTR(dev->parent, child, irq, flags, 1864 intr, arg, cookiep)); 1865 return (EINVAL); 1866} 1867 1868int 1869bus_generic_teardown_intr(device_t dev, device_t child, struct resource *irq, 1870 void *cookie) 1871{ 1872 /* Propagate up the bus hierarchy until someone handles it. */ 1873 if (dev->parent) 1874 return (BUS_TEARDOWN_INTR(dev->parent, child, irq, cookie)); 1875 return (EINVAL); 1876} 1877 1878struct resource * 1879bus_generic_alloc_resource(device_t dev, device_t child, int type, int *rid, 1880 u_long start, u_long end, u_long count, u_int flags) 1881{ 1882 /* Propagate up the bus hierarchy until someone handles it. */ 1883 if (dev->parent) 1884 return (BUS_ALLOC_RESOURCE(dev->parent, child, type, rid, 1885 start, end, count, flags)); 1886 return (NULL); 1887} 1888 1889int 1890bus_generic_release_resource(device_t dev, device_t child, int type, int rid, 1891 struct resource *r) 1892{ 1893 /* Propagate up the bus hierarchy until someone handles it. */ 1894 if (dev->parent) 1895 return (BUS_RELEASE_RESOURCE(dev->parent, child, type, rid, 1896 r)); 1897 return (EINVAL); 1898} 1899 1900int 1901bus_generic_activate_resource(device_t dev, device_t child, int type, int rid, 1902 struct resource *r) 1903{ 1904 /* Propagate up the bus hierarchy until someone handles it. */ 1905 if (dev->parent) 1906 return (BUS_ACTIVATE_RESOURCE(dev->parent, child, type, rid, 1907 r)); 1908 return (EINVAL); 1909} 1910 1911int 1912bus_generic_deactivate_resource(device_t dev, device_t child, int type, 1913 int rid, struct resource *r) 1914{ 1915 /* Propagate up the bus hierarchy until someone handles it. */ 1916 if (dev->parent) 1917 return (BUS_DEACTIVATE_RESOURCE(dev->parent, child, type, rid, 1918 r)); 1919 return (EINVAL); 1920} 1921 1922int 1923bus_generic_rl_get_resource (device_t dev, device_t child, int type, int rid, 1924 u_long *startp, u_long *countp) 1925{ 1926 struct resource_list * rl = NULL; 1927 struct resource_list_entry * rle = NULL; 1928 1929 rl = BUS_GET_RESOURCE_LIST(dev, child); 1930 if (!rl) 1931 return (EINVAL); 1932 1933 rle = resource_list_find(rl, type, rid); 1934 if (!rle) 1935 return (ENOENT); 1936 1937 if (startp) 1938 *startp = rle->start; 1939 if (countp) 1940 *countp = rle->count; 1941 1942 return (0); 1943} 1944 1945int 1946bus_generic_rl_set_resource (device_t dev, device_t child, int type, int rid, 1947 u_long start, u_long count) 1948{ 1949 struct resource_list * rl = NULL; 1950 1951 rl = BUS_GET_RESOURCE_LIST(dev, child); 1952 if (!rl) 1953 return (EINVAL); 1954 1955 resource_list_add(rl, type, rid, start, (start + count - 1), count); 1956 1957 return (0); 1958} 1959 1960void 1961bus_generic_rl_delete_resource (device_t dev, device_t child, int type, int rid) 1962{ 1963 struct resource_list * rl = NULL; 1964 1965 rl = BUS_GET_RESOURCE_LIST(dev, child); 1966 if (!rl) 1967 return; 1968 1969 resource_list_delete(rl, type, rid); 1970 1971 return; 1972} 1973 1974int 1975bus_generic_rl_release_resource (device_t dev, device_t child, int type, 1976 int rid, struct resource *r) 1977{ 1978 struct resource_list * rl = NULL; 1979 1980 rl = BUS_GET_RESOURCE_LIST(dev, child); 1981 if (!rl) 1982 return (EINVAL); 1983 1984 return (resource_list_release(rl, dev, child, type, rid, r)); 1985} 1986 1987struct resource * 1988bus_generic_rl_alloc_resource (device_t dev, device_t child, int type, 1989 int *rid, u_long start, u_long end, u_long count, u_int flags) 1990{ 1991 struct resource_list * rl = NULL; 1992 1993 rl = BUS_GET_RESOURCE_LIST(dev, child); 1994 if (!rl) 1995 return (NULL); 1996 1997 return (resource_list_alloc(rl, dev, child, type, rid, 1998 start, end, count, flags)); 1999} 2000 2001int 2002bus_generic_child_present(device_t bus, device_t child) 2003{ 2004 return (BUS_CHILD_PRESENT(device_get_parent(bus), bus)); 2005} 2006 2007/* 2008 * Some convenience functions to make it easier for drivers to use the 2009 * resource-management functions. All these really do is hide the 2010 * indirection through the parent's method table, making for slightly 2011 * less-wordy code. In the future, it might make sense for this code 2012 * to maintain some sort of a list of resources allocated by each device. 2013 */ 2014struct resource * 2015bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end, 2016 u_long count, u_int flags) 2017{ 2018 if (dev->parent == 0) 2019 return (0); 2020 return (BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end, 2021 count, flags)); 2022} 2023 2024int 2025bus_activate_resource(device_t dev, int type, int rid, struct resource *r) 2026{ 2027 if (dev->parent == 0) 2028 return (EINVAL); 2029 return (BUS_ACTIVATE_RESOURCE(dev->parent, dev, type, rid, r)); 2030} 2031 2032int 2033bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r) 2034{ 2035 if (dev->parent == 0) 2036 return (EINVAL); 2037 return (BUS_DEACTIVATE_RESOURCE(dev->parent, dev, type, rid, r)); 2038} 2039 2040int 2041bus_release_resource(device_t dev, int type, int rid, struct resource *r) 2042{ 2043 if (dev->parent == 0) 2044 return (EINVAL); 2045 return (BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r)); 2046} 2047 2048int 2049bus_setup_intr(device_t dev, struct resource *r, int flags, 2050 driver_intr_t handler, void *arg, void **cookiep) 2051{ 2052 if (dev->parent == 0) 2053 return (EINVAL); 2054 return (BUS_SETUP_INTR(dev->parent, dev, r, flags, 2055 handler, arg, cookiep)); 2056} 2057 2058int 2059bus_teardown_intr(device_t dev, struct resource *r, void *cookie) 2060{ 2061 if (dev->parent == 0) 2062 return (EINVAL); 2063 return (BUS_TEARDOWN_INTR(dev->parent, dev, r, cookie)); 2064} 2065 2066int 2067bus_set_resource(device_t dev, int type, int rid, 2068 u_long start, u_long count) 2069{ 2070 return (BUS_SET_RESOURCE(device_get_parent(dev), dev, type, rid, 2071 start, count)); 2072} 2073 2074int 2075bus_get_resource(device_t dev, int type, int rid, 2076 u_long *startp, u_long *countp) 2077{ 2078 return (BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid, 2079 startp, countp)); 2080} 2081 2082u_long 2083bus_get_resource_start(device_t dev, int type, int rid) 2084{ 2085 u_long start, count; 2086 int error; 2087 2088 error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid, 2089 &start, &count); 2090 if (error) 2091 return (0); 2092 return (start); 2093} 2094 2095u_long 2096bus_get_resource_count(device_t dev, int type, int rid) 2097{ 2098 u_long start, count; 2099 int error; 2100 2101 error = BUS_GET_RESOURCE(device_get_parent(dev), dev, type, rid, 2102 &start, &count); 2103 if (error) 2104 return (0); 2105 return (count); 2106} 2107 2108void 2109bus_delete_resource(device_t dev, int type, int rid) 2110{ 2111 BUS_DELETE_RESOURCE(device_get_parent(dev), dev, type, rid); 2112} 2113 2114int 2115bus_child_present(device_t child) 2116{ 2117 return (BUS_CHILD_PRESENT(device_get_parent(child), child)); 2118} 2119 2120int 2121bus_child_pnpinfo_str(device_t child, char *buf, size_t buflen) 2122{ 2123 device_t parent; 2124 2125 parent = device_get_parent(child); 2126 if (parent == NULL) { 2127 *buf = '\0'; 2128 return (0); 2129 } 2130 return (BUS_CHILD_PNPINFO_STR(parent, child, buf, buflen)); 2131} 2132 2133int 2134bus_child_location_str(device_t child, char *buf, size_t buflen) 2135{ 2136 device_t parent; 2137 2138 parent = device_get_parent(child); 2139 if (parent == NULL) { 2140 *buf = '\0'; 2141 return (0); 2142 } 2143 return (BUS_CHILD_LOCATION_STR(parent, child, buf, buflen)); 2144} 2145 2146static int 2147root_print_child(device_t dev, device_t child) 2148{ 2149 int retval = 0; 2150 2151 retval += bus_print_child_header(dev, child); 2152 retval += printf("\n"); 2153 2154 return (retval); 2155} 2156 2157static int 2158root_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg, 2159 void **cookiep) 2160{ 2161 /* 2162 * If an interrupt mapping gets to here something bad has happened. 2163 */ 2164 panic("root_setup_intr"); 2165} 2166 2167/* 2168 * If we get here, assume that the device is permanant and really is 2169 * present in the system. Removable bus drivers are expected to intercept 2170 * this call long before it gets here. We return -1 so that drivers that 2171 * really care can check vs -1 or some ERRNO returned higher in the food 2172 * chain. 2173 */ 2174static int 2175root_child_present(device_t dev, device_t child) 2176{ 2177 return (-1); 2178} 2179 2180static kobj_method_t root_methods[] = { 2181 /* Device interface */ 2182 KOBJMETHOD(device_shutdown, bus_generic_shutdown), 2183 KOBJMETHOD(device_suspend, bus_generic_suspend), 2184 KOBJMETHOD(device_resume, bus_generic_resume), 2185 2186 /* Bus interface */ 2187 KOBJMETHOD(bus_print_child, root_print_child), 2188 KOBJMETHOD(bus_read_ivar, bus_generic_read_ivar), 2189 KOBJMETHOD(bus_write_ivar, bus_generic_write_ivar), 2190 KOBJMETHOD(bus_setup_intr, root_setup_intr), 2191 KOBJMETHOD(bus_child_present, root_child_present), 2192 2193 { 0, 0 } 2194}; 2195 2196static driver_t root_driver = { 2197 "root", 2198 root_methods, 2199 1, /* no softc */ 2200}; 2201 2202device_t root_bus; 2203devclass_t root_devclass; 2204 2205static int 2206root_bus_module_handler(module_t mod, int what, void* arg) 2207{ 2208 switch (what) { 2209 case MOD_LOAD: 2210 TAILQ_INIT(&bus_data_devices); 2211 kobj_class_compile((kobj_class_t) &root_driver); 2212 root_bus = make_device(NULL, "root", 0); 2213 root_bus->desc = "System root bus"; 2214 kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver); 2215 root_bus->driver = &root_driver; 2216 root_bus->state = DS_ATTACHED; 2217 root_devclass = devclass_find_internal("root", FALSE); 2218 devinit(); 2219 return (0); 2220 2221 case MOD_SHUTDOWN: 2222 device_shutdown(root_bus); 2223 return (0); 2224 } 2225 2226 return (0); 2227} 2228 2229static moduledata_t root_bus_mod = { 2230 "rootbus", 2231 root_bus_module_handler, 2232 0 2233}; 2234DECLARE_MODULE(rootbus, root_bus_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 2235 2236void 2237root_bus_configure(void) 2238{ 2239 device_t dev; 2240 2241 PDEBUG((".")); 2242 2243 TAILQ_FOREACH(dev, &root_bus->children, link) { 2244 device_probe_and_attach(dev); 2245 } 2246} 2247 2248int 2249driver_module_handler(module_t mod, int what, void *arg) 2250{ 2251 int error, i; 2252 struct driver_module_data *dmd; 2253 devclass_t bus_devclass; 2254 2255 dmd = (struct driver_module_data *)arg; 2256 bus_devclass = devclass_find_internal(dmd->dmd_busname, TRUE); 2257 error = 0; 2258 2259 switch (what) { 2260 case MOD_LOAD: 2261 if (dmd->dmd_chainevh) 2262 error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); 2263 2264 for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { 2265 PDEBUG(("Loading module: driver %s on bus %s", 2266 DRIVERNAME(dmd->dmd_drivers[i]), dmd->dmd_busname)); 2267 error = devclass_add_driver(bus_devclass, 2268 dmd->dmd_drivers[i]); 2269 } 2270 if (error) 2271 break; 2272 2273 /* 2274 * The drivers loaded in this way are assumed to all 2275 * implement the same devclass. 2276 */ 2277 *dmd->dmd_devclass = 2278 devclass_find_internal(dmd->dmd_drivers[0]->name, TRUE); 2279 break; 2280 2281 case MOD_UNLOAD: 2282 for (i = 0; !error && i < dmd->dmd_ndrivers; i++) { 2283 PDEBUG(("Unloading module: driver %s from bus %s", 2284 DRIVERNAME(dmd->dmd_drivers[i]), 2285 dmd->dmd_busname)); 2286 error = devclass_delete_driver(bus_devclass, 2287 dmd->dmd_drivers[i]); 2288 } 2289 2290 if (!error && dmd->dmd_chainevh) 2291 error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg); 2292 break; 2293 } 2294 2295 return (error); 2296} 2297 2298#ifdef BUS_DEBUG 2299 2300/* the _short versions avoid iteration by not calling anything that prints 2301 * more than oneliners. I love oneliners. 2302 */ 2303 2304static void 2305print_device_short(device_t dev, int indent) 2306{ 2307 if (!dev) 2308 return; 2309 2310 indentprintf(("device %d: <%s> %sparent,%schildren,%s%s%s%s,%sivars,%ssoftc,busy=%d\n", 2311 dev->unit, dev->desc, 2312 (dev->parent? "":"no "), 2313 (TAILQ_EMPTY(&dev->children)? "no ":""), 2314 (dev->flags&DF_ENABLED? "enabled,":"disabled,"), 2315 (dev->flags&DF_FIXEDCLASS? "fixed,":""), 2316 (dev->flags&DF_WILDCARD? "wildcard,":""), 2317 (dev->flags&DF_DESCMALLOCED? "descmalloced,":""), 2318 (dev->ivars? "":"no "), 2319 (dev->softc? "":"no "), 2320 dev->busy)); 2321} 2322 2323static void 2324print_device(device_t dev, int indent) 2325{ 2326 if (!dev) 2327 return; 2328 2329 print_device_short(dev, indent); 2330 2331 indentprintf(("Parent:\n")); 2332 print_device_short(dev->parent, indent+1); 2333 indentprintf(("Driver:\n")); 2334 print_driver_short(dev->driver, indent+1); 2335 indentprintf(("Devclass:\n")); 2336 print_devclass_short(dev->devclass, indent+1); 2337} 2338 2339void 2340print_device_tree_short(device_t dev, int indent) 2341/* print the device and all its children (indented) */ 2342{ 2343 device_t child; 2344 2345 if (!dev) 2346 return; 2347 2348 print_device_short(dev, indent); 2349 2350 TAILQ_FOREACH(child, &dev->children, link) { 2351 print_device_tree_short(child, indent+1); 2352 } 2353} 2354 2355void 2356print_device_tree(device_t dev, int indent) 2357/* print the device and all its children (indented) */ 2358{ 2359 device_t child; 2360 2361 if (!dev) 2362 return; 2363 2364 print_device(dev, indent); 2365 2366 TAILQ_FOREACH(child, &dev->children, link) { 2367 print_device_tree(child, indent+1); 2368 } 2369} 2370 2371static void 2372print_driver_short(driver_t *driver, int indent) 2373{ 2374 if (!driver) 2375 return; 2376 2377 indentprintf(("driver %s: softc size = %zd\n", 2378 driver->name, driver->size)); 2379} 2380 2381static void 2382print_driver(driver_t *driver, int indent) 2383{ 2384 if (!driver) 2385 return; 2386 2387 print_driver_short(driver, indent); 2388} 2389 2390 2391static void 2392print_driver_list(driver_list_t drivers, int indent) 2393{ 2394 driverlink_t driver; 2395 2396 TAILQ_FOREACH(driver, &drivers, link) { 2397 print_driver(driver->driver, indent); 2398 } 2399} 2400 2401static void 2402print_devclass_short(devclass_t dc, int indent) 2403{ 2404 if ( !dc ) 2405 return; 2406 2407 indentprintf(("devclass %s: max units = %d\n", dc->name, dc->maxunit)); 2408} 2409 2410static void 2411print_devclass(devclass_t dc, int indent) 2412{ 2413 int i; 2414 2415 if ( !dc ) 2416 return; 2417 2418 print_devclass_short(dc, indent); 2419 indentprintf(("Drivers:\n")); 2420 print_driver_list(dc->drivers, indent+1); 2421 2422 indentprintf(("Devices:\n")); 2423 for (i = 0; i < dc->maxunit; i++) 2424 if (dc->devices[i]) 2425 print_device(dc->devices[i], indent+1); 2426} 2427 2428void 2429print_devclass_list_short(void) 2430{ 2431 devclass_t dc; 2432 2433 printf("Short listing of devclasses, drivers & devices:\n"); 2434 TAILQ_FOREACH(dc, &devclasses, link) { 2435 print_devclass_short(dc, 0); 2436 } 2437} 2438 2439void 2440print_devclass_list(void) 2441{ 2442 devclass_t dc; 2443 2444 printf("Full listing of devclasses, drivers & devices:\n"); 2445 TAILQ_FOREACH(dc, &devclasses, link) { 2446 print_devclass(dc, 0); 2447 } 2448} 2449 2450#endif 2451 2452/* 2453 * User-space access to the device tree. 2454 * 2455 * We implement a small set of nodes: 2456 * 2457 * hw.bus Single integer read method to obtain the 2458 * current generation count. 2459 * hw.bus.devices Reads the entire device tree in flat space. 2460 * hw.bus.rman Resource manager interface 2461 * 2462 * We might like to add the ability to scan devclasses and/or drivers to 2463 * determine what else is currently loaded/available. 2464 */ 2465 2466static int 2467sysctl_bus(SYSCTL_HANDLER_ARGS) 2468{ 2469 struct u_businfo ubus; 2470 2471 ubus.ub_version = BUS_USER_VERSION; 2472 ubus.ub_generation = bus_data_generation; 2473 2474 return (SYSCTL_OUT(req, &ubus, sizeof(ubus))); 2475} 2476SYSCTL_NODE(_hw_bus, OID_AUTO, info, CTLFLAG_RW, sysctl_bus, 2477 "bus-related data"); 2478 2479static int 2480sysctl_devices(SYSCTL_HANDLER_ARGS) 2481{ 2482 int *name = (int *)arg1; 2483 u_int namelen = arg2; 2484 int index; 2485 struct device *dev; 2486 struct u_device udev; /* XXX this is a bit big */ 2487 int error; 2488 2489 if (namelen != 2) 2490 return (EINVAL); 2491 2492 if (bus_data_generation_check(name[0])) 2493 return (EINVAL); 2494 2495 index = name[1]; 2496 2497 /* 2498 * Scan the list of devices, looking for the requested index. 2499 */ 2500 TAILQ_FOREACH(dev, &bus_data_devices, devlink) { 2501 if (index-- == 0) 2502 break; 2503 } 2504 if (dev == NULL) 2505 return (ENOENT); 2506 2507 /* 2508 * Populate the return array. 2509 */ 2510 udev.dv_handle = (uintptr_t)dev; 2511 udev.dv_parent = (uintptr_t)dev->parent; 2512 if (dev->nameunit == NULL) 2513 udev.dv_name[0] = '\0'; 2514 else 2515 strlcpy(udev.dv_name, dev->nameunit, sizeof(udev.dv_name)); 2516 2517 if (dev->desc == NULL) 2518 udev.dv_desc[0] = '\0'; 2519 else 2520 strlcpy(udev.dv_desc, dev->desc, sizeof(udev.dv_desc)); 2521 if (dev->driver == NULL || dev->driver->name == NULL) 2522 udev.dv_drivername[0] = '\0'; 2523 else 2524 strlcpy(udev.dv_drivername, dev->driver->name, 2525 sizeof(udev.dv_drivername)); 2526 udev.dv_pnpinfo[0] = '\0'; 2527 udev.dv_location[0] = '\0'; 2528 bus_child_pnpinfo_str(dev, udev.dv_pnpinfo, sizeof(udev.dv_pnpinfo)); 2529 bus_child_location_str(dev, udev.dv_location, sizeof(udev.dv_location)); 2530 udev.dv_devflags = dev->devflags; 2531 udev.dv_flags = dev->flags; 2532 udev.dv_state = dev->state; 2533 error = SYSCTL_OUT(req, &udev, sizeof(udev)); 2534 return (error); 2535} 2536 2537SYSCTL_NODE(_hw_bus, OID_AUTO, devices, CTLFLAG_RD, sysctl_devices, 2538 "system device tree"); 2539 2540/* 2541 * Sysctl interface for scanning the resource lists. 2542 * 2543 * We take two input parameters; the index into the list of resource 2544 * managers, and the resource offset into the list. 2545 */ 2546static int 2547sysctl_rman(SYSCTL_HANDLER_ARGS) 2548{ 2549 int *name = (int *)arg1; 2550 u_int namelen = arg2; 2551 int rman_idx, res_idx; 2552 struct rman *rm; 2553 struct resource *res; 2554 struct u_rman urm; 2555 struct u_resource ures; 2556 int error; 2557 2558 if (namelen != 3) 2559 return (EINVAL); 2560 2561 if (bus_data_generation_check(name[0])) 2562 return (EINVAL); 2563 rman_idx = name[1]; 2564 res_idx = name[2]; 2565 2566 /* 2567 * Find the indexed resource manager 2568 */ 2569 TAILQ_FOREACH(rm, &rman_head, rm_link) { 2570 if (rman_idx-- == 0) 2571 break; 2572 } 2573 if (rm == NULL) 2574 return (ENOENT); 2575 2576 /* 2577 * If the resource index is -1, we want details on the 2578 * resource manager. 2579 */ 2580 if (res_idx == -1) { 2581 urm.rm_handle = (uintptr_t)rm; 2582 strlcpy(urm.rm_descr, rm->rm_descr, RM_TEXTLEN); 2583 urm.rm_start = rm->rm_start; 2584 urm.rm_size = rm->rm_end - rm->rm_start + 1; 2585 urm.rm_type = rm->rm_type; 2586 2587 error = SYSCTL_OUT(req, &urm, sizeof(urm)); 2588 return (error); 2589 } 2590 2591 /* 2592 * Find the indexed resource and return it. 2593 */ 2594 TAILQ_FOREACH(res, &rm->rm_list, r_link) { 2595 if (res_idx-- == 0) { 2596 ures.r_handle = (uintptr_t)res; 2597 ures.r_parent = (uintptr_t)res->r_rm; 2598 ures.r_device = (uintptr_t)res->r_dev; 2599 if (res->r_dev != NULL) { 2600 if (device_get_name(res->r_dev) != NULL) { 2601 snprintf(ures.r_devname, RM_TEXTLEN, 2602 "%s%d", 2603 device_get_name(res->r_dev), 2604 device_get_unit(res->r_dev)); 2605 } else { 2606 strlcpy(ures.r_devname, "nomatch", 2607 RM_TEXTLEN); 2608 } 2609 } else { 2610 ures.r_devname[0] = '\0'; 2611 } 2612 ures.r_start = res->r_start; 2613 ures.r_size = res->r_end - res->r_start + 1; 2614 ures.r_flags = res->r_flags; 2615 2616 error = SYSCTL_OUT(req, &ures, sizeof(ures)); 2617 return (error); 2618 } 2619 } 2620 return (ENOENT); 2621} 2622 2623SYSCTL_NODE(_hw_bus, OID_AUTO, rman, CTLFLAG_RD, sysctl_rman, 2624 "kernel resource manager"); 2625 2626int 2627bus_data_generation_check(int generation) 2628{ 2629 if (generation != bus_data_generation) 2630 return (1); 2631 2632 /* XXX generate optimised lists here? */ 2633 return (0); 2634} 2635 2636void 2637bus_data_generation_update(void) 2638{ 2639 bus_data_generation++; 2640} 2641