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