Home | History | Annotate | Line # | Download | only in kern
subr_autoconf.c revision 1.55.2.3
      1 /* $NetBSD: subr_autoconf.c,v 1.55.2.3 2001/11/14 19:16:39 nathanw Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1996, 2000 Christopher G. Demetriou
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *          This product includes software developed for the
     18  *          NetBSD Project.  See http://www.netbsd.org/ for
     19  *          information about NetBSD.
     20  * 4. The name of the author may not be used to endorse or promote products
     21  *    derived from this software without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33  *
     34  * --(license Id: LICENSE.proto,v 1.1 2000/06/13 21:40:26 cgd Exp )--
     35  */
     36 
     37 /*
     38  * Copyright (c) 1992, 1993
     39  *	The Regents of the University of California.  All rights reserved.
     40  *
     41  * This software was developed by the Computer Systems Engineering group
     42  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
     43  * contributed to Berkeley.
     44  *
     45  * All advertising materials mentioning features or use of this software
     46  * must display the following acknowledgement:
     47  *	This product includes software developed by the University of
     48  *	California, Lawrence Berkeley Laboratories.
     49  *
     50  * Redistribution and use in source and binary forms, with or without
     51  * modification, are permitted provided that the following conditions
     52  * are met:
     53  * 1. Redistributions of source code must retain the above copyright
     54  *    notice, this list of conditions and the following disclaimer.
     55  * 2. Redistributions in binary form must reproduce the above copyright
     56  *    notice, this list of conditions and the following disclaimer in the
     57  *    documentation and/or other materials provided with the distribution.
     58  * 3. All advertising materials mentioning features or use of this software
     59  *    must display the following acknowledgement:
     60  *	This product includes software developed by the University of
     61  *	California, Berkeley and its contributors.
     62  * 4. Neither the name of the University nor the names of its contributors
     63  *    may be used to endorse or promote products derived from this software
     64  *    without specific prior written permission.
     65  *
     66  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     67  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     68  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     69  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     70  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     71  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     72  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     73  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     74  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     75  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     76  * SUCH DAMAGE.
     77  *
     78  * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp  (LBL)
     79  *
     80  *	@(#)subr_autoconf.c	8.3 (Berkeley) 5/17/94
     81  */
     82 
     83 #include <sys/cdefs.h>
     84 __KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.55.2.3 2001/11/14 19:16:39 nathanw Exp $");
     85 
     86 #include <sys/param.h>
     87 #include <sys/device.h>
     88 #include <sys/malloc.h>
     89 #include <sys/systm.h>
     90 #include <sys/kernel.h>
     91 #include <sys/errno.h>
     92 #include <sys/proc.h>
     93 #include <machine/limits.h>
     94 
     95 #include "opt_userconf.h"
     96 #ifdef USERCONF
     97 #include <sys/userconf.h>
     98 #include <sys/reboot.h>
     99 #endif
    100 
    101 /*
    102  * Autoconfiguration subroutines.
    103  */
    104 
    105 /*
    106  * ioconf.c exports exactly two names: cfdata and cfroots.  All system
    107  * devices and drivers are found via these tables.
    108  */
    109 extern struct cfdata cfdata[];
    110 extern short cfroots[];
    111 
    112 #define	ROOT ((struct device *)NULL)
    113 
    114 struct matchinfo {
    115 	cfmatch_t fn;
    116 	struct	device *parent;
    117 	void	*aux;
    118 	struct	cfdata *match;
    119 	int	pri;
    120 };
    121 
    122 static char *number(char *, int);
    123 static void mapply(struct matchinfo *, struct cfdata *);
    124 
    125 struct deferred_config {
    126 	TAILQ_ENTRY(deferred_config) dc_queue;
    127 	struct device *dc_dev;
    128 	void (*dc_func)(struct device *);
    129 };
    130 
    131 TAILQ_HEAD(deferred_config_head, deferred_config);
    132 
    133 struct deferred_config_head deferred_config_queue;
    134 struct deferred_config_head interrupt_config_queue;
    135 
    136 static void config_process_deferred(struct deferred_config_head *,
    137 	struct device *);
    138 
    139 /* list of all devices */
    140 struct devicelist alldevs;
    141 
    142 /* list of all events */
    143 struct evcntlist allevents = TAILQ_HEAD_INITIALIZER(allevents);
    144 
    145 __volatile int config_pending;		/* semaphore for mountroot */
    146 
    147 /*
    148  * Configure the system's hardware.
    149  */
    150 void
    151 configure(void)
    152 {
    153 
    154 	TAILQ_INIT(&deferred_config_queue);
    155 	TAILQ_INIT(&interrupt_config_queue);
    156 	TAILQ_INIT(&alldevs);
    157 
    158 #ifdef USERCONF
    159 	if (boothowto & RB_USERCONF)
    160 		user_config();
    161 #endif
    162 
    163 	/*
    164 	 * Do the machine-dependent portion of autoconfiguration.  This
    165 	 * sets the configuration machinery here in motion by "finding"
    166 	 * the root bus.  When this function returns, we expect interrupts
    167 	 * to be enabled.
    168 	 */
    169 	cpu_configure();
    170 
    171 	/*
    172 	 * Now that we've found all the hardware, start the real time
    173 	 * and statistics clocks.
    174 	 */
    175 	initclocks();
    176 
    177 	cold = 0;	/* clocks are running, we're warm now! */
    178 
    179 	/*
    180 	 * Now callback to finish configuration for devices which want
    181 	 * to do this once interrupts are enabled.
    182 	 */
    183 	config_process_deferred(&interrupt_config_queue, NULL);
    184 }
    185 
    186 /*
    187  * Apply the matching function and choose the best.  This is used
    188  * a few times and we want to keep the code small.
    189  */
    190 static void
    191 mapply(struct matchinfo *m, struct cfdata *cf)
    192 {
    193 	int pri;
    194 
    195 	if (m->fn != NULL)
    196 		pri = (*m->fn)(m->parent, cf, m->aux);
    197 	else {
    198 	        if (cf->cf_attach->ca_match == NULL) {
    199 			panic("mapply: no match function for '%s' device\n",
    200 			    cf->cf_driver->cd_name);
    201 		}
    202 		pri = (*cf->cf_attach->ca_match)(m->parent, cf, m->aux);
    203 	}
    204 	if (pri > m->pri) {
    205 		m->match = cf;
    206 		m->pri = pri;
    207 	}
    208 }
    209 
    210 /*
    211  * Iterate over all potential children of some device, calling the given
    212  * function (default being the child's match function) for each one.
    213  * Nonzero returns are matches; the highest value returned is considered
    214  * the best match.  Return the `found child' if we got a match, or NULL
    215  * otherwise.  The `aux' pointer is simply passed on through.
    216  *
    217  * Note that this function is designed so that it can be used to apply
    218  * an arbitrary function to all potential children (its return value
    219  * can be ignored).
    220  */
    221 struct cfdata *
    222 config_search(cfmatch_t fn, struct device *parent, void *aux)
    223 {
    224 	struct cfdata *cf;
    225 	short *p;
    226 	struct matchinfo m;
    227 
    228 	m.fn = fn;
    229 	m.parent = parent;
    230 	m.aux = aux;
    231 	m.match = NULL;
    232 	m.pri = 0;
    233 	for (cf = cfdata; cf->cf_driver; cf++) {
    234 		/*
    235 		 * Skip cf if no longer eligible, otherwise scan through
    236 		 * parents for one matching `parent', and try match function.
    237 		 */
    238 		if (cf->cf_fstate == FSTATE_FOUND)
    239 			continue;
    240 		for (p = cf->cf_parents; *p >= 0; p++)
    241 			if (parent->dv_cfdata == &cfdata[*p])
    242 				mapply(&m, cf);
    243 	}
    244 	return (m.match);
    245 }
    246 
    247 /*
    248  * Find the given root device.
    249  * This is much like config_search, but there is no parent.
    250  */
    251 struct cfdata *
    252 config_rootsearch(cfmatch_t fn, const char *rootname, void *aux)
    253 {
    254 	struct cfdata *cf;
    255 	short *p;
    256 	struct matchinfo m;
    257 
    258 	m.fn = fn;
    259 	m.parent = ROOT;
    260 	m.aux = aux;
    261 	m.match = NULL;
    262 	m.pri = 0;
    263 	/*
    264 	 * Look at root entries for matching name.  We do not bother
    265 	 * with found-state here since only one root should ever be
    266 	 * searched (and it must be done first).
    267 	 */
    268 	for (p = cfroots; *p >= 0; p++) {
    269 		cf = &cfdata[*p];
    270 		if (strcmp(cf->cf_driver->cd_name, rootname) == 0)
    271 			mapply(&m, cf);
    272 	}
    273 	return (m.match);
    274 }
    275 
    276 static const char *msgs[3] = { "", " not configured\n", " unsupported\n" };
    277 
    278 /*
    279  * The given `aux' argument describes a device that has been found
    280  * on the given parent, but not necessarily configured.  Locate the
    281  * configuration data for that device (using the submatch function
    282  * provided, or using candidates' cd_match configuration driver
    283  * functions) and attach it, and return true.  If the device was
    284  * not configured, call the given `print' function and return 0.
    285  */
    286 struct device *
    287 config_found_sm(struct device *parent, void *aux, cfprint_t print,
    288     cfmatch_t submatch)
    289 {
    290 	struct cfdata *cf;
    291 
    292 	if ((cf = config_search(submatch, parent, aux)) != NULL)
    293 		return (config_attach(parent, cf, aux, print));
    294 	if (print)
    295 		printf("%s", msgs[(*print)(aux, parent->dv_xname)]);
    296 	return (NULL);
    297 }
    298 
    299 /*
    300  * As above, but for root devices.
    301  */
    302 struct device *
    303 config_rootfound(const char *rootname, void *aux)
    304 {
    305 	struct cfdata *cf;
    306 
    307 	if ((cf = config_rootsearch((cfmatch_t)NULL, rootname, aux)) != NULL)
    308 		return (config_attach(ROOT, cf, aux, (cfprint_t)NULL));
    309 	printf("root device %s not configured\n", rootname);
    310 	return (NULL);
    311 }
    312 
    313 /* just like sprintf(buf, "%d") except that it works from the end */
    314 static char *
    315 number(char *ep, int n)
    316 {
    317 
    318 	*--ep = 0;
    319 	while (n >= 10) {
    320 		*--ep = (n % 10) + '0';
    321 		n /= 10;
    322 	}
    323 	*--ep = n + '0';
    324 	return (ep);
    325 }
    326 
    327 /*
    328  * Attach a found device.  Allocates memory for device variables.
    329  */
    330 struct device *
    331 config_attach(struct device *parent, struct cfdata *cf, void *aux,
    332 	cfprint_t print)
    333 {
    334 	struct device *dev;
    335 	struct cfdriver *cd;
    336 	struct cfattach *ca;
    337 	size_t lname, lunit;
    338 	const char *xunit;
    339 	int myunit;
    340 	char num[10];
    341 
    342 	cd = cf->cf_driver;
    343 	ca = cf->cf_attach;
    344 	if (ca->ca_devsize < sizeof(struct device))
    345 		panic("config_attach");
    346 #ifndef __BROKEN_CONFIG_UNIT_USAGE
    347 	if (cf->cf_fstate == FSTATE_STAR) {
    348 		for (myunit = cf->cf_unit; myunit < cd->cd_ndevs; myunit++)
    349 			if (cd->cd_devs[myunit] == NULL)
    350 				break;
    351 		/*
    352 		 * myunit is now the unit of the first NULL device pointer,
    353 		 * or max(cd->cd_ndevs,cf->cf_unit).
    354 		 */
    355 	} else {
    356 		myunit = cf->cf_unit;
    357 #else /* __BROKEN_CONFIG_UNIT_USAGE */
    358 	myunit = cf->cf_unit;
    359 	if (cf->cf_fstate == FSTATE_STAR)
    360 		cf->cf_unit++;
    361 	else {
    362 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
    363 		KASSERT(cf->cf_fstate == FSTATE_NOTFOUND);
    364 		cf->cf_fstate = FSTATE_FOUND;
    365 	}
    366 
    367 	/* compute length of name and decimal expansion of unit number */
    368 	lname = strlen(cd->cd_name);
    369 	xunit = number(&num[sizeof(num)], myunit);
    370 	lunit = &num[sizeof(num)] - xunit;
    371 	if (lname + lunit >= sizeof(dev->dv_xname))
    372 		panic("config_attach: device name too long");
    373 
    374 	/* get memory for all device vars */
    375 	dev = (struct device *)malloc(ca->ca_devsize, M_DEVBUF,
    376 	    cold ? M_NOWAIT : M_WAITOK);
    377 	if (!dev)
    378 	    panic("config_attach: memory allocation for device softc failed");
    379 	memset(dev, 0, ca->ca_devsize);
    380 	TAILQ_INSERT_TAIL(&alldevs, dev, dv_list);	/* link up */
    381 	dev->dv_class = cd->cd_class;
    382 	dev->dv_cfdata = cf;
    383 	dev->dv_unit = myunit;
    384 	memcpy(dev->dv_xname, cd->cd_name, lname);
    385 	memcpy(dev->dv_xname + lname, xunit, lunit);
    386 	dev->dv_parent = parent;
    387 	dev->dv_flags = DVF_ACTIVE;	/* always initially active */
    388 
    389 	if (parent == ROOT)
    390 		printf("%s (root)", dev->dv_xname);
    391 	else {
    392 		printf("%s at %s", dev->dv_xname, parent->dv_xname);
    393 		if (print)
    394 			(void) (*print)(aux, NULL);
    395 	}
    396 
    397 	/* put this device in the devices array */
    398 	if (dev->dv_unit >= cd->cd_ndevs) {
    399 		/*
    400 		 * Need to expand the array.
    401 		 */
    402 		int old = cd->cd_ndevs, new;
    403 		void **nsp;
    404 
    405 		if (old == 0)
    406 			new = MINALLOCSIZE / sizeof(void *);
    407 		else
    408 			new = old * 2;
    409 		while (new <= dev->dv_unit)
    410 			new *= 2;
    411 		cd->cd_ndevs = new;
    412 		nsp = malloc(new * sizeof(void *), M_DEVBUF,
    413 		    cold ? M_NOWAIT : M_WAITOK);
    414 		if (nsp == 0)
    415 			panic("config_attach: %sing dev array",
    416 			    old != 0 ? "expand" : "creat");
    417 		memset(nsp + old, 0, (new - old) * sizeof(void *));
    418 		if (old != 0) {
    419 			memcpy(nsp, cd->cd_devs, old * sizeof(void *));
    420 			free(cd->cd_devs, M_DEVBUF);
    421 		}
    422 		cd->cd_devs = nsp;
    423 	}
    424 	if (cd->cd_devs[dev->dv_unit])
    425 		panic("config_attach: duplicate %s", dev->dv_xname);
    426 	cd->cd_devs[dev->dv_unit] = dev;
    427 
    428 	/*
    429 	 * Before attaching, clobber any unfound devices that are
    430 	 * otherwise identical.
    431 	 */
    432 #ifdef __BROKEN_CONFIG_UNIT_USAGE
    433 	/* bump the unit number on all starred cfdata for this device. */
    434 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
    435 	for (cf = cfdata; cf->cf_driver; cf++)
    436 		if (cf->cf_driver == cd && cf->cf_unit == dev->dv_unit) {
    437 			if (cf->cf_fstate == FSTATE_NOTFOUND)
    438 				cf->cf_fstate = FSTATE_FOUND;
    439 #ifdef __BROKEN_CONFIG_UNIT_USAGE
    440 			if (cf->cf_fstate == FSTATE_STAR)
    441 				cf->cf_unit++;
    442 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
    443 		}
    444 #ifdef __HAVE_DEVICE_REGISTER
    445 	device_register(dev, aux);
    446 #endif
    447 	(*ca->ca_attach)(parent, dev, aux);
    448 	config_process_deferred(&deferred_config_queue, dev);
    449 	return (dev);
    450 }
    451 
    452 /*
    453  * Detach a device.  Optionally forced (e.g. because of hardware
    454  * removal) and quiet.  Returns zero if successful, non-zero
    455  * (an error code) otherwise.
    456  *
    457  * Note that this code wants to be run from a process context, so
    458  * that the detach can sleep to allow processes which have a device
    459  * open to run and unwind their stacks.
    460  */
    461 int
    462 config_detach(struct device *dev, int flags)
    463 {
    464 	struct cfdata *cf;
    465 	struct cfattach *ca;
    466 	struct cfdriver *cd;
    467 #ifdef DIAGNOSTIC
    468 	struct device *d;
    469 #endif
    470 	int rv = 0, i;
    471 
    472 	cf = dev->dv_cfdata;
    473 #ifdef DIAGNOSTIC
    474 	if (cf->cf_fstate != FSTATE_FOUND && cf->cf_fstate != FSTATE_STAR)
    475 		panic("config_detach: bad device fstate");
    476 #endif
    477 	ca = cf->cf_attach;
    478 	cd = cf->cf_driver;
    479 
    480 	/*
    481 	 * Ensure the device is deactivated.  If the device doesn't
    482 	 * have an activation entry point, we allow DVF_ACTIVE to
    483 	 * remain set.  Otherwise, if DVF_ACTIVE is still set, the
    484 	 * device is busy, and the detach fails.
    485 	 */
    486 	if (ca->ca_activate != NULL)
    487 		rv = config_deactivate(dev);
    488 
    489 	/*
    490 	 * Try to detach the device.  If that's not possible, then
    491 	 * we either panic() (for the forced but failed case), or
    492 	 * return an error.
    493 	 */
    494 	if (rv == 0) {
    495 		if (ca->ca_detach != NULL)
    496 			rv = (*ca->ca_detach)(dev, flags);
    497 		else
    498 			rv = EOPNOTSUPP;
    499 	}
    500 	if (rv != 0) {
    501 		if ((flags & DETACH_FORCE) == 0)
    502 			return (rv);
    503 		else
    504 			panic("config_detach: forced detach of %s failed (%d)",
    505 			    dev->dv_xname, rv);
    506 	}
    507 
    508 	/*
    509 	 * The device has now been successfully detached.
    510 	 */
    511 
    512 #ifdef DIAGNOSTIC
    513 	/*
    514 	 * Sanity: If you're successfully detached, you should have no
    515 	 * children.  (Note that because children must be attached
    516 	 * after parents, we only need to search the latter part of
    517 	 * the list.)
    518 	 */
    519 	for (d = TAILQ_NEXT(dev, dv_list); d != NULL;
    520 	    d = TAILQ_NEXT(d, dv_list)) {
    521 		if (d->dv_parent == dev) {
    522 			printf("config_detach: detached device %s"
    523 			    " has children %s\n", dev->dv_xname, d->dv_xname);
    524 			panic("config_detach");
    525 		}
    526 	}
    527 #endif
    528 
    529 	/*
    530 	 * Mark cfdata to show that the unit can be reused, if possible.
    531 	 */
    532 #ifdef __BROKEN_CONFIG_UNIT_USAGE
    533 	/*
    534 	 * Note that we can only re-use a starred unit number if the unit
    535 	 * being detached had the last assigned unit number.
    536 	 */
    537 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
    538 	for (cf = cfdata; cf->cf_driver; cf++) {
    539 		if (cf->cf_driver == cd) {
    540 			if (cf->cf_fstate == FSTATE_FOUND &&
    541 			    cf->cf_unit == dev->dv_unit)
    542 				cf->cf_fstate = FSTATE_NOTFOUND;
    543 #ifdef __BROKEN_CONFIG_UNIT_USAGE
    544 			if (cf->cf_fstate == FSTATE_STAR &&
    545 			    cf->cf_unit == dev->dv_unit + 1)
    546 				cf->cf_unit--;
    547 #endif /* __BROKEN_CONFIG_UNIT_USAGE */
    548 		}
    549 	}
    550 
    551 	/*
    552 	 * Unlink from device list.
    553 	 */
    554 	TAILQ_REMOVE(&alldevs, dev, dv_list);
    555 
    556 	/*
    557 	 * Remove from cfdriver's array, tell the world, and free softc.
    558 	 */
    559 	cd->cd_devs[dev->dv_unit] = NULL;
    560 	if ((flags & DETACH_QUIET) == 0)
    561 		printf("%s detached\n", dev->dv_xname);
    562 	free(dev, M_DEVBUF);
    563 
    564 	/*
    565 	 * If the device now has no units in use, deallocate its softc array.
    566 	 */
    567 	for (i = 0; i < cd->cd_ndevs; i++)
    568 		if (cd->cd_devs[i] != NULL)
    569 			break;
    570 	if (i == cd->cd_ndevs) {		/* nothing found; deallocate */
    571 		free(cd->cd_devs, M_DEVBUF);
    572 		cd->cd_devs = NULL;
    573 		cd->cd_ndevs = 0;
    574 	}
    575 
    576 	/*
    577 	 * Return success.
    578 	 */
    579 	return (0);
    580 }
    581 
    582 int
    583 config_activate(struct device *dev)
    584 {
    585 	struct cfattach *ca = dev->dv_cfdata->cf_attach;
    586 	int rv = 0, oflags = dev->dv_flags;
    587 
    588 	if (ca->ca_activate == NULL)
    589 		return (EOPNOTSUPP);
    590 
    591 	if ((dev->dv_flags & DVF_ACTIVE) == 0) {
    592 		dev->dv_flags |= DVF_ACTIVE;
    593 		rv = (*ca->ca_activate)(dev, DVACT_ACTIVATE);
    594 		if (rv)
    595 			dev->dv_flags = oflags;
    596 	}
    597 	return (rv);
    598 }
    599 
    600 int
    601 config_deactivate(struct device *dev)
    602 {
    603 	struct cfattach *ca = dev->dv_cfdata->cf_attach;
    604 	int rv = 0, oflags = dev->dv_flags;
    605 
    606 	if (ca->ca_activate == NULL)
    607 		return (EOPNOTSUPP);
    608 
    609 	if (dev->dv_flags & DVF_ACTIVE) {
    610 		dev->dv_flags &= ~DVF_ACTIVE;
    611 		rv = (*ca->ca_activate)(dev, DVACT_DEACTIVATE);
    612 		if (rv)
    613 			dev->dv_flags = oflags;
    614 	}
    615 	return (rv);
    616 }
    617 
    618 /*
    619  * Defer the configuration of the specified device until all
    620  * of its parent's devices have been attached.
    621  */
    622 void
    623 config_defer(struct device *dev, void (*func)(struct device *))
    624 {
    625 	struct deferred_config *dc;
    626 
    627 	if (dev->dv_parent == NULL)
    628 		panic("config_defer: can't defer config of a root device");
    629 
    630 #ifdef DIAGNOSTIC
    631 	for (dc = TAILQ_FIRST(&deferred_config_queue); dc != NULL;
    632 	     dc = TAILQ_NEXT(dc, dc_queue)) {
    633 		if (dc->dc_dev == dev)
    634 			panic("config_defer: deferred twice");
    635 	}
    636 #endif
    637 
    638 	dc = malloc(sizeof(*dc), M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
    639 	if (dc == NULL)
    640 		panic("config_defer: unable to allocate callback");
    641 
    642 	dc->dc_dev = dev;
    643 	dc->dc_func = func;
    644 	TAILQ_INSERT_TAIL(&deferred_config_queue, dc, dc_queue);
    645 	config_pending_incr();
    646 }
    647 
    648 /*
    649  * Defer some autoconfiguration for a device until after interrupts
    650  * are enabled.
    651  */
    652 void
    653 config_interrupts(struct device *dev, void (*func)(struct device *))
    654 {
    655 	struct deferred_config *dc;
    656 
    657 	/*
    658 	 * If interrupts are enabled, callback now.
    659 	 */
    660 	if (cold == 0) {
    661 		(*func)(dev);
    662 		return;
    663 	}
    664 
    665 #ifdef DIAGNOSTIC
    666 	for (dc = TAILQ_FIRST(&interrupt_config_queue); dc != NULL;
    667 	     dc = TAILQ_NEXT(dc, dc_queue)) {
    668 		if (dc->dc_dev == dev)
    669 			panic("config_interrupts: deferred twice");
    670 	}
    671 #endif
    672 
    673 	dc = malloc(sizeof(*dc), M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
    674 	if (dc == NULL)
    675 		panic("config_interrupts: unable to allocate callback");
    676 
    677 	dc->dc_dev = dev;
    678 	dc->dc_func = func;
    679 	TAILQ_INSERT_TAIL(&interrupt_config_queue, dc, dc_queue);
    680 	config_pending_incr();
    681 }
    682 
    683 /*
    684  * Process a deferred configuration queue.
    685  */
    686 static void
    687 config_process_deferred(struct deferred_config_head *queue,
    688     struct device *parent)
    689 {
    690 	struct deferred_config *dc, *ndc;
    691 
    692 	for (dc = TAILQ_FIRST(queue); dc != NULL; dc = ndc) {
    693 		ndc = TAILQ_NEXT(dc, dc_queue);
    694 		if (parent == NULL || dc->dc_dev->dv_parent == parent) {
    695 			TAILQ_REMOVE(queue, dc, dc_queue);
    696 			(*dc->dc_func)(dc->dc_dev);
    697 			free(dc, M_DEVBUF);
    698 			config_pending_decr();
    699 		}
    700 	}
    701 }
    702 
    703 /*
    704  * Manipulate the config_pending semaphore.
    705  */
    706 void
    707 config_pending_incr(void)
    708 {
    709 
    710 	config_pending++;
    711 }
    712 
    713 void
    714 config_pending_decr(void)
    715 {
    716 
    717 #ifdef DIAGNOSTIC
    718 	if (config_pending == 0)
    719 		panic("config_pending_decr: config_pending == 0");
    720 #endif
    721 	config_pending--;
    722 	if (config_pending == 0)
    723 		wakeup((void *)&config_pending);
    724 }
    725 
    726 /*
    727  * Attach a statically-initialized event.  The type and string pointers
    728  * are already set up.
    729  */
    730 void
    731 evcnt_attach_static(struct evcnt *ev)
    732 {
    733 	int len;
    734 
    735 	len = strlen(ev->ev_group);
    736 #ifdef DIAGNOSTIC
    737 	if (len >= EVCNT_STRING_MAX)		/* ..._MAX includes NUL */
    738 		panic("evcnt_attach_static: group length (%s)", ev->ev_group);
    739 #endif
    740 	ev->ev_grouplen = len;
    741 
    742 	len = strlen(ev->ev_name);
    743 #ifdef DIAGNOSTIC
    744 	if (len >= EVCNT_STRING_MAX)		/* ..._MAX includes NUL */
    745 		panic("evcnt_attach_static: name length (%s)", ev->ev_name);
    746 #endif
    747 	ev->ev_namelen = len;
    748 
    749 	TAILQ_INSERT_TAIL(&allevents, ev, ev_list);
    750 }
    751 
    752 /*
    753  * Attach a dynamically-initialized event.  Zero it, set up the type
    754  * and string pointers and then act like it was statically initialized.
    755  */
    756 void
    757 evcnt_attach_dynamic(struct evcnt *ev, int type, const struct evcnt *parent,
    758     const char *group, const char *name)
    759 {
    760 
    761 	memset(ev, 0, sizeof *ev);
    762 	ev->ev_type = type;
    763 	ev->ev_parent = parent;
    764 	ev->ev_group = group;
    765 	ev->ev_name = name;
    766 	evcnt_attach_static(ev);
    767 }
    768 
    769 /*
    770  * Detach an event.
    771  */
    772 void
    773 evcnt_detach(struct evcnt *ev)
    774 {
    775 
    776 	TAILQ_REMOVE(&allevents, ev, ev_list);
    777 }
    778