1 /* $OpenBSD: subr_autoconf.c,v 1.36 2003/06/02 23:28:06 millert Exp $ */ 2 /* $NetBSD: subr_autoconf.c,v 1.21 1996/04/04 06:06:18 cgd Exp $ */ 3 4 /* 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This software was developed by the Computer Systems Engineering group 9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 10 * contributed to Berkeley. 11 * 12 * All advertising materials mentioning features or use of this software 13 * must display the following acknowledgement: 14 * This product includes software developed by the University of 15 * California, Lawrence Berkeley Laboratories. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 3. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp (LBL) 42 * 43 * @(#)subr_autoconf.c 8.1 (Berkeley) 6/10/93 44 */ 45 46 #include <sys/param.h> 47 #include <sys/device.h> 48 #include <sys/limits.h> 49 #include <sys/malloc.h> 50 #include <sys/systm.h> 51 /* Extra stuff from Matthias Drochner <drochner@zelux6.zel.kfa-juelich.de> */ 52 #include <sys/queue.h> 53 54 /* 55 * Autoconfiguration subroutines. 56 */ 57 58 typedef int (*cond_predicate_t)(struct device *, void *); 59 60 /* 61 * ioconf.c exports exactly two names: cfdata and cfroots. All system 62 * devices and drivers are found via these tables. 63 */ 64 extern short cfroots[]; 65 66 #define ROOT ((struct device *)NULL) 67 68 struct matchinfo { 69 cfmatch_t fn; 70 struct device *parent; 71 void *match, *aux; 72 int indirect, pri; 73 }; 74 75 struct cftable_head allcftables; 76 77 static struct cftable staticcftable = { 78 cfdata 79 }; 80 81 #ifndef AUTOCONF_VERBOSE 82 #define AUTOCONF_VERBOSE 0 83 #endif /* AUTOCONF_VERBOSE */ 84 int autoconf_verbose = AUTOCONF_VERBOSE; /* trace probe calls */ 85 86 static void mapply(struct matchinfo *, struct cfdata *); 87 88 struct deferred_config { 89 TAILQ_ENTRY(deferred_config) dc_queue; 90 struct device *dc_dev; 91 void (*dc_func)(struct device *); 92 }; 93 94 TAILQ_HEAD(, deferred_config) deferred_config_queue; 95 96 void config_process_deferred_children(struct device *); 97 98 struct devicelist alldevs; /* list of all devices */ 99 struct evcntlist allevents; /* list of all event counters */ 100 101 /* 102 * Initialize autoconfiguration data structures. This occurs before console 103 * initialization as that might require use of this subsystem. Furthermore 104 * this means that malloc et al. isn't yet available. 105 */ 106 void 107 config_init() 108 { 109 TAILQ_INIT(&deferred_config_queue); 110 TAILQ_INIT(&alldevs); 111 TAILQ_INIT(&allevents); 112 TAILQ_INIT(&allcftables); 113 TAILQ_INSERT_TAIL(&allcftables, &staticcftable, list); 114 } 115 116 /* 117 * Apply the matching function and choose the best. This is used 118 * a few times and we want to keep the code small. 119 */ 120 void 121 mapply(m, cf) 122 register struct matchinfo *m; 123 register struct cfdata *cf; 124 { 125 register int pri; 126 void *match; 127 128 if (m->indirect) 129 match = config_make_softc(m->parent, cf); 130 else 131 match = cf; 132 133 if (autoconf_verbose) { 134 printf(">>> probing for %s", cf->cf_driver->cd_name); 135 if (cf->cf_fstate == FSTATE_STAR) 136 printf("*\n"); 137 else 138 printf("%d\n", cf->cf_unit); 139 } 140 if (m->fn != NULL) 141 pri = (*m->fn)(m->parent, match, m->aux); 142 else { 143 if (cf->cf_attach->ca_match == NULL) { 144 panic("mapply: no match function for '%s' device", 145 cf->cf_driver->cd_name); 146 } 147 pri = (*cf->cf_attach->ca_match)(m->parent, match, m->aux); 148 } 149 if (autoconf_verbose) 150 printf(">>> %s probe returned %d\n", cf->cf_driver->cd_name, 151 pri); 152 153 if (pri > m->pri) { 154 if (m->indirect && m->match) 155 free(m->match, M_DEVBUF); 156 m->match = match; 157 m->pri = pri; 158 } else { 159 if (m->indirect) 160 free(match, M_DEVBUF); 161 } 162 } 163 164 /* 165 * Iterate over all potential children of some device, calling the given 166 * function (default being the child's match function) for each one. 167 * Nonzero returns are matches; the highest value returned is considered 168 * the best match. Return the `found child' if we got a match, or NULL 169 * otherwise. The `aux' pointer is simply passed on through. 170 * 171 * Note that this function is designed so that it can be used to apply 172 * an arbitrary function to all potential children (its return value 173 * can be ignored). 174 */ 175 void * 176 config_search(fn, parent, aux) 177 cfmatch_t fn; 178 register struct device *parent; 179 void *aux; 180 { 181 register struct cfdata *cf; 182 register short *p; 183 struct matchinfo m; 184 struct cftable *t; 185 186 m.fn = fn; 187 m.parent = parent; 188 m.match = NULL; 189 m.aux = aux; 190 m.indirect = parent && parent->dv_cfdata->cf_driver->cd_indirect; 191 m.pri = 0; 192 for(t = allcftables.tqh_first; t; t = t->list.tqe_next) { 193 for (cf = t->tab; cf->cf_driver; cf++) { 194 /* 195 * Skip cf if no longer eligible, otherwise scan 196 * through parents for one matching `parent', 197 * and try match function. 198 */ 199 if (cf->cf_fstate == FSTATE_FOUND) 200 continue; 201 if (cf->cf_fstate == FSTATE_DNOTFOUND || 202 cf->cf_fstate == FSTATE_DSTAR) 203 continue; 204 for (p = cf->cf_parents; *p >= 0; p++) 205 if (parent->dv_cfdata == &(t->tab)[*p]) 206 mapply(&m, cf); 207 } 208 } 209 if (autoconf_verbose) { 210 if (m.match) 211 printf(">>> %s probe won\n", 212 ((struct cfdata *)m.match)->cf_driver->cd_name); 213 else 214 printf(">>> no winning probe\n"); 215 } 216 return (m.match); 217 } 218 219 /* 220 * Iterate over all potential children of some device, calling the given 221 * function for each one. 222 * 223 * Note that this function is designed so that it can be used to apply 224 * an arbitrary function to all potential children (its return value 225 * can be ignored). 226 */ 227 void 228 config_scan(fn, parent) 229 cfscan_t fn; 230 register struct device *parent; 231 { 232 register struct cfdata *cf; 233 register short *p; 234 void *match; 235 int indirect; 236 struct cftable *t; 237 238 indirect = parent && parent->dv_cfdata->cf_driver->cd_indirect; 239 for (t = allcftables.tqh_first; t; t = t->list.tqe_next) { 240 for (cf = t->tab; cf->cf_driver; cf++) { 241 /* 242 * Skip cf if no longer eligible, otherwise scan 243 * through parents for one matching `parent', 244 * and try match function. 245 */ 246 if (cf->cf_fstate == FSTATE_FOUND) 247 continue; 248 if (cf->cf_fstate == FSTATE_DNOTFOUND || 249 cf->cf_fstate == FSTATE_DSTAR) 250 continue; 251 for (p = cf->cf_parents; *p >= 0; p++) 252 if (parent->dv_cfdata == &(t->tab)[*p]) { 253 match = indirect? 254 config_make_softc(parent, cf) : 255 (void *)cf; 256 (*fn)(parent, match); 257 } 258 } 259 } 260 } 261 262 /* 263 * Find the given root device. 264 * This is much like config_search, but there is no parent. 265 */ 266 void * 267 config_rootsearch(fn, rootname, aux) 268 register cfmatch_t fn; 269 register char *rootname; 270 register void *aux; 271 { 272 register struct cfdata *cf; 273 register short *p; 274 struct matchinfo m; 275 276 m.fn = fn; 277 m.parent = ROOT; 278 m.match = NULL; 279 m.aux = aux; 280 m.indirect = 0; 281 m.pri = 0; 282 /* 283 * Look at root entries for matching name. We do not bother 284 * with found-state here since only one root should ever be 285 * searched (and it must be done first). 286 */ 287 for (p = cfroots; *p >= 0; p++) { 288 cf = &cfdata[*p]; 289 if (strcmp(cf->cf_driver->cd_name, rootname) == 0) 290 mapply(&m, cf); 291 } 292 return (m.match); 293 } 294 295 char *msgs[3] = { "", " not configured\n", " unsupported\n" }; 296 297 /* 298 * The given `aux' argument describes a device that has been found 299 * on the given parent, but not necessarily configured. Locate the 300 * configuration data for that device (using the submatch function 301 * provided, or using candidates' cd_match configuration driver 302 * functions) and attach it, and return true. If the device was 303 * not configured, call the given `print' function and return 0. 304 */ 305 struct device * 306 config_found_sm(parent, aux, print, submatch) 307 struct device *parent; 308 void *aux; 309 cfprint_t print; 310 cfmatch_t submatch; 311 { 312 void *match; 313 314 if ((match = config_search(submatch, parent, aux)) != NULL) 315 return (config_attach(parent, match, aux, print)); 316 if (print) 317 printf(msgs[(*print)(aux, parent->dv_xname)]); 318 return (NULL); 319 } 320 321 /* 322 * As above, but for root devices. 323 */ 324 struct device * 325 config_rootfound(rootname, aux) 326 char *rootname; 327 void *aux; 328 { 329 void *match; 330 331 if ((match = config_rootsearch((cfmatch_t)NULL, rootname, aux)) != NULL) 332 return (config_attach(ROOT, match, aux, (cfprint_t)NULL)); 333 printf("root device %s not configured\n", rootname); 334 return (NULL); 335 } 336 337 /* 338 * Attach a found device. Allocates memory for device variables. 339 */ 340 struct device * 341 config_attach(parent, match, aux, print) 342 register struct device *parent; 343 void *match; 344 register void *aux; 345 cfprint_t print; 346 { 347 register struct cfdata *cf; 348 register struct device *dev; 349 register struct cfdriver *cd; 350 register struct cfattach *ca; 351 struct cftable *t; 352 353 if (parent && parent->dv_cfdata->cf_driver->cd_indirect) { 354 dev = match; 355 cf = dev->dv_cfdata; 356 } else { 357 cf = match; 358 dev = config_make_softc(parent, cf); 359 } 360 361 cd = cf->cf_driver; 362 ca = cf->cf_attach; 363 364 cd->cd_devs[dev->dv_unit] = dev; 365 366 /* 367 * If this is a "STAR" device and we used the last unit, prepare for 368 * another one. 369 */ 370 if (cf->cf_fstate == FSTATE_STAR) { 371 if (dev->dv_unit == cf->cf_unit) 372 cf->cf_unit++; 373 } else 374 cf->cf_fstate = FSTATE_FOUND; 375 376 TAILQ_INSERT_TAIL(&alldevs, dev, dv_list); 377 device_ref(dev); 378 379 if (parent == ROOT) 380 printf("%s (root)", dev->dv_xname); 381 else { 382 printf("%s at %s", dev->dv_xname, parent->dv_xname); 383 if (print) 384 (void) (*print)(aux, (char *)0); 385 } 386 387 /* 388 * Before attaching, clobber any unfound devices that are 389 * otherwise identical, or bump the unit number on all starred 390 * cfdata for this device. 391 */ 392 for (t = allcftables.tqh_first; t; t = t->list.tqe_next) { 393 for (cf = t->tab; cf->cf_driver; cf++) 394 if (cf->cf_driver == cd && 395 cf->cf_unit == dev->dv_unit) { 396 if (cf->cf_fstate == FSTATE_NOTFOUND) 397 cf->cf_fstate = FSTATE_FOUND; 398 if (cf->cf_fstate == FSTATE_STAR) 399 cf->cf_unit++; 400 } 401 } 402 #ifdef __HAVE_DEVICE_REGISTER 403 device_register(dev, aux); 404 #endif 405 (*ca->ca_attach)(parent, dev, aux); 406 config_process_deferred_children(dev); 407 return (dev); 408 } 409 410 struct device * 411 config_make_softc(parent, cf) 412 struct device *parent; 413 struct cfdata *cf; 414 { 415 register struct device *dev; 416 register struct cfdriver *cd; 417 register struct cfattach *ca; 418 419 cd = cf->cf_driver; 420 ca = cf->cf_attach; 421 if (ca->ca_devsize < sizeof(struct device)) 422 panic("config_make_softc"); 423 424 /* get memory for all device vars */ 425 dev = (struct device *)malloc(ca->ca_devsize, M_DEVBUF, M_NOWAIT); 426 if (!dev) 427 panic("config_make_softc: allocation for device softc failed"); 428 bzero(dev, ca->ca_devsize); 429 dev->dv_class = cd->cd_class; 430 dev->dv_cfdata = cf; 431 dev->dv_flags = DVF_ACTIVE; /* always initially active */ 432 433 /* If this is a STAR device, search for a free unit number */ 434 if (cf->cf_fstate == FSTATE_STAR) { 435 for (dev->dv_unit = cf->cf_starunit1; 436 dev->dv_unit < cf->cf_unit; dev->dv_unit++) 437 if (cd->cd_ndevs == 0 || 438 cd->cd_devs[dev->dv_unit] == NULL) 439 break; 440 } else 441 dev->dv_unit = cf->cf_unit; 442 443 /* Build the device name into dv_xname. */ 444 if (snprintf(dev->dv_xname, sizeof(dev->dv_xname), "%s%d", 445 cd->cd_name, dev->dv_unit) >= sizeof(dev->dv_xname)) 446 panic("config_make_softc: device name too long"); 447 dev->dv_parent = parent; 448 449 /* put this device in the devices array */ 450 if (dev->dv_unit >= cd->cd_ndevs) { 451 /* 452 * Need to expand the array. 453 */ 454 int old = cd->cd_ndevs, new; 455 void **nsp; 456 457 if (old == 0) 458 new = MINALLOCSIZE / sizeof(void *); 459 else 460 new = old * 2; 461 while (new <= dev->dv_unit) 462 new *= 2; 463 cd->cd_ndevs = new; 464 nsp = malloc(new * sizeof(void *), M_DEVBUF, M_NOWAIT); 465 if (nsp == 0) 466 panic("config_make_softc: %sing dev array", 467 old != 0 ? "expand" : "creat"); 468 bzero(nsp + old, (new - old) * sizeof(void *)); 469 if (old != 0) { 470 bcopy(cd->cd_devs, nsp, old * sizeof(void *)); 471 free(cd->cd_devs, M_DEVBUF); 472 } 473 cd->cd_devs = nsp; 474 } 475 if (cd->cd_devs[dev->dv_unit]) 476 panic("config_make_softc: duplicate %s", dev->dv_xname); 477 478 dev->dv_ref = 1; 479 480 return (dev); 481 } 482 483 /* 484 * Detach a device. Optionally forced (e.g. because of hardware 485 * removal) and quiet. Returns zero if successful, non-zero 486 * (an error code) otherwise. 487 * 488 * Note that this code wants to be run from a process context, so 489 * that the detach can sleep to allow processes which have a device 490 * open to run and unwind their stacks. 491 */ 492 int 493 config_detach(dev, flags) 494 struct device *dev; 495 int flags; 496 { 497 struct cfdata *cf; 498 struct cfattach *ca; 499 struct cfdriver *cd; 500 #ifdef DIAGNOSTIC 501 struct device *d; 502 #endif 503 int rv = 0, i; 504 505 cf = dev->dv_cfdata; 506 #ifdef DIAGNOSTIC 507 if (cf->cf_fstate != FSTATE_FOUND && cf->cf_fstate != FSTATE_STAR) 508 panic("config_detach: bad device fstate"); 509 #endif 510 ca = cf->cf_attach; 511 cd = cf->cf_driver; 512 513 /* 514 * Ensure the device is deactivated. If the device doesn't 515 * have an activation entry point, we allow DVF_ACTIVE to 516 * remain set. Otherwise, if DVF_ACTIVE is still set, the 517 * device is busy, and the detach fails. 518 */ 519 if (ca->ca_activate != NULL) 520 rv = config_deactivate(dev); 521 522 /* 523 * Try to detach the device. If that's not possible, then 524 * we either panic() (for the forced but failed case), or 525 * return an error. 526 */ 527 if (rv == 0) { 528 if (ca->ca_detach != NULL) 529 rv = (*ca->ca_detach)(dev, flags); 530 else 531 rv = EOPNOTSUPP; 532 } 533 if (rv != 0) { 534 if ((flags & DETACH_FORCE) == 0) 535 return (rv); 536 else 537 panic("config_detach: forced detach of %s failed (%d)", 538 dev->dv_xname, rv); 539 } 540 541 /* 542 * The device has now been successfully detached. 543 */ 544 545 #ifdef DIAGNOSTIC 546 /* 547 * Sanity: If you're successfully detached, you should have no 548 * children. (Note that because children must be attached 549 * after parents, we only need to search the latter part of 550 * the list.) 551 */ 552 for (d = TAILQ_NEXT(dev, dv_list); d != NULL; 553 d = TAILQ_NEXT(d, dv_list)) { 554 if (d->dv_parent == dev) 555 panic("config_detach: detached device has children"); 556 } 557 #endif 558 559 /* 560 * Mark cfdata to show that the unit can be reused, if possible. 561 * Note that we can only re-use a starred unit number if the unit 562 * being detached had the last assigned unit number. 563 */ 564 for (cf = cfdata; cf->cf_driver; cf++) { 565 if (cf->cf_driver == cd) { 566 if (cf->cf_fstate == FSTATE_FOUND && 567 cf->cf_unit == dev->dv_unit) 568 cf->cf_fstate = FSTATE_NOTFOUND; 569 if (cf->cf_fstate == FSTATE_STAR && 570 cf->cf_unit == dev->dv_unit + 1) 571 cf->cf_unit--; 572 } 573 } 574 575 /* 576 * Unlink from device list. 577 */ 578 TAILQ_REMOVE(&alldevs, dev, dv_list); 579 device_unref(dev); 580 581 /* 582 * Remove from cfdriver's array, tell the world, and free softc. 583 */ 584 cd->cd_devs[dev->dv_unit] = NULL; 585 if ((flags & DETACH_QUIET) == 0) 586 printf("%s detached\n", dev->dv_xname); 587 588 device_unref(dev); 589 /* 590 * If the device now has no units in use, deallocate its softc array. 591 */ 592 for (i = 0; i < cd->cd_ndevs; i++) 593 if (cd->cd_devs[i] != NULL) 594 break; 595 if (i == cd->cd_ndevs) { /* nothing found; deallocate */ 596 free(cd->cd_devs, M_DEVBUF); 597 cd->cd_devs = NULL; 598 cd->cd_ndevs = 0; 599 } 600 601 /* 602 * Return success. 603 */ 604 return (0); 605 } 606 607 int 608 config_activate(dev) 609 struct device *dev; 610 { 611 struct cfattach *ca = dev->dv_cfdata->cf_attach; 612 int rv = 0, oflags = dev->dv_flags; 613 614 if (ca->ca_activate == NULL) 615 return (EOPNOTSUPP); 616 617 if ((dev->dv_flags & DVF_ACTIVE) == 0) { 618 dev->dv_flags |= DVF_ACTIVE; 619 rv = (*ca->ca_activate)(dev, DVACT_ACTIVATE); 620 if (rv) 621 dev->dv_flags = oflags; 622 } 623 return (rv); 624 } 625 626 int 627 config_deactivate(dev) 628 struct device *dev; 629 { 630 struct cfattach *ca = dev->dv_cfdata->cf_attach; 631 int rv = 0, oflags = dev->dv_flags; 632 633 if (ca->ca_activate == NULL) 634 return (EOPNOTSUPP); 635 636 if (dev->dv_flags & DVF_ACTIVE) { 637 dev->dv_flags &= ~DVF_ACTIVE; 638 rv = (*ca->ca_activate)(dev, DVACT_DEACTIVATE); 639 if (rv) 640 dev->dv_flags = oflags; 641 } 642 return (rv); 643 } 644 645 /* 646 * Defer the configuration of the specified device until all 647 * of its parent's devices have been attached. 648 */ 649 void 650 config_defer(dev, func) 651 struct device *dev; 652 void (*func)(struct device *); 653 { 654 struct deferred_config *dc; 655 656 if (dev->dv_parent == NULL) 657 panic("config_defer: can't defer config of a root device"); 658 659 #ifdef DIAGNOSTIC 660 for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL; 661 dc = TAILQ_NEXT(dc, dc_queue)) { 662 if (dc->dc_dev == dev) 663 panic("config_defer: deferred twice"); 664 } 665 #endif 666 667 if ((dc = malloc(sizeof(*dc), M_DEVBUF, M_NOWAIT)) == NULL) 668 panic("config_defer: can't allocate defer structure"); 669 670 dc->dc_dev = dev; 671 dc->dc_func = func; 672 TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue); 673 } 674 675 /* 676 * Process the deferred configuration queue for a device. 677 */ 678 void 679 config_process_deferred_children(parent) 680 struct device *parent; 681 { 682 struct deferred_config *dc, *ndc; 683 684 for (dc = TAILQ_FIRST(&deferred_config_queue); 685 dc != NULL; dc = ndc) { 686 ndc = TAILQ_NEXT(dc, dc_queue); 687 if (dc->dc_dev->dv_parent == parent) { 688 TAILQ_REMOVE(&deferred_config_queue, dc, dc_queue); 689 (*dc->dc_func)(dc->dc_dev); 690 free(dc, M_DEVBUF); 691 } 692 } 693 } 694 695 int 696 config_detach_children(parent, flags) 697 struct device *parent; 698 int flags; 699 { 700 struct device *dev, *next_dev; 701 int rv = 0; 702 703 /* The config_detach routine may sleep, meaning devices 704 may be added to the queue. However, all devices will 705 be added to the tail of the queue, the queue won't 706 be re-organized, and the subtree of parent here should be locked 707 for purposes of adding/removing children. 708 */ 709 for (dev = TAILQ_FIRST(&alldevs); 710 dev != NULL; dev = next_dev) { 711 next_dev = TAILQ_NEXT(dev, dv_list); 712 if (dev->dv_parent == parent && 713 (rv = config_detach(dev, flags))) 714 return (rv); 715 } 716 717 return (rv); 718 } 719 720 int 721 config_activate_children(parent, act) 722 struct device *parent; 723 enum devact act; 724 { 725 struct device *dev, *next_dev; 726 int rv = 0; 727 728 /* The config_deactivate routine may sleep, meaning devices 729 may be added to the queue. However, all devices will 730 be added to the tail of the queue, the queue won't 731 be re-organized, and the subtree of parent here should be locked 732 for purposes of adding/removing children. 733 */ 734 for (dev = TAILQ_FIRST(&alldevs); 735 dev != NULL; dev = next_dev) { 736 next_dev = TAILQ_NEXT(dev, dv_list); 737 if (dev->dv_parent == parent) { 738 switch (act) { 739 case DVACT_ACTIVATE: 740 rv = config_activate(dev); 741 break; 742 case DVACT_DEACTIVATE: 743 rv = config_deactivate(dev); 744 break; 745 default: 746 #ifdef DIAGNOSTIC 747 printf ("config_activate_children: shouldn't get here"); 748 #endif 749 rv = EOPNOTSUPP; 750 break; 751 752 } 753 754 if (rv) 755 break; 756 } 757 } 758 759 return (rv); 760 } 761 762 /* 763 * Lookup a device in the cfdriver device array. Does not return a 764 * device if it is not active. 765 * 766 * Increments ref count on the device by one, reflecting the 767 * new reference created on the stack. 768 * 769 * Context: process only 770 */ 771 struct device * 772 device_lookup(cd, unit) 773 struct cfdriver *cd; 774 int unit; 775 { 776 struct device *dv = NULL; 777 778 if (unit >= 0 && unit < cd->cd_ndevs) 779 dv = (struct device *)(cd->cd_devs[unit]); 780 781 if (!dv) 782 return (NULL); 783 784 if (!(dv->dv_flags & DVF_ACTIVE)) 785 dv = NULL; 786 787 if (dv != NULL) 788 device_ref(dv); 789 790 return (dv); 791 } 792 793 794 /* 795 * Increments the ref count on the device structure. The device 796 * structure is freed when the ref count hits 0. 797 * 798 * Context: process or interrupt 799 */ 800 void 801 device_ref(dv) 802 struct device *dv; 803 { 804 dv->dv_ref++; 805 } 806 807 /* 808 * Decrement the ref count on the device structure. 809 * 810 * free's the structure when the ref count hits zero and calls the zeroref 811 * function. 812 * 813 * Context: process or interrupt 814 */ 815 void 816 device_unref(dv) 817 struct device *dv; 818 { 819 dv->dv_ref--; 820 if (dv->dv_ref == 0) { 821 if (dv->dv_cfdata->cf_attach->ca_zeroref) 822 (*dv->dv_cfdata->cf_attach->ca_zeroref)(dv); 823 824 free(dv, M_DEVBUF); 825 } 826 } 827 828 /* 829 * Attach an event. These must come from initially-zero space (see 830 * commented-out assignments below), but that occurs naturally for 831 * device instance variables. 832 */ 833 void 834 evcnt_attach(dev, name, ev) 835 struct device *dev; 836 const char *name; 837 struct evcnt *ev; 838 { 839 840 #ifdef DIAGNOSTIC 841 if (strlen(name) >= sizeof(ev->ev_name)) 842 panic("evcnt_attach"); 843 #endif 844 /* ev->ev_next = NULL; */ 845 ev->ev_dev = dev; 846 /* ev->ev_count = 0; */ 847 strlcpy(ev->ev_name, name, sizeof ev->ev_name); 848 TAILQ_INSERT_TAIL(&allevents, ev, ev_list); 849 } 850