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