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