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