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