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