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