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