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