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