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