Home | History | Annotate | Line # | Download | only in isa
isa.c revision 1.110.6.1
      1 /*	$NetBSD: isa.c,v 1.110.6.1 2002/04/06 16:12:08 eeh Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Charles M. Hannum; by Jason R. Thorpe of Wasabi Systems, Inc.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 #include <sys/cdefs.h>
     40 __KERNEL_RCSID(0, "$NetBSD: isa.c,v 1.110.6.1 2002/04/06 16:12:08 eeh Exp $");
     41 
     42 #include <sys/param.h>
     43 #include <sys/systm.h>
     44 #include <sys/kernel.h>
     45 #include <sys/malloc.h>
     46 #include <sys/device.h>
     47 #include <sys/properties.h>
     48 
     49 #include <machine/intr.h>
     50 
     51 #include <dev/isa/isareg.h>
     52 #include <dev/isa/isavar.h>
     53 #include <dev/isa/isadmareg.h>
     54 
     55 #include "isadma.h"
     56 
     57 #include "isapnp.h"
     58 #if NISAPNP > 0
     59 #include <dev/isapnp/isapnpreg.h>
     60 #include <dev/isapnp/isapnpvar.h>
     61 #endif
     62 
     63 int	isamatch(struct device *, struct cfdata *, void *);
     64 void	isaattach(struct device *, struct device *, void *);
     65 int	isaprint(void *, const char *);
     66 
     67 struct cfattach isa_ca = {
     68 	sizeof(struct isa_softc), isamatch, isaattach
     69 };
     70 
     71 void	isa_attach_knowndevs(struct isa_softc *);
     72 void	isa_free_knowndevs(struct isa_softc *);
     73 
     74 int	isasubmatch(struct device *, struct cfdata *, void *);
     75 int	isasearch(struct device *, struct cfdata *, void *);
     76 
     77 int
     78 isamatch(struct device *parent, struct cfdata *cf, void *aux)
     79 {
     80 	struct isabus_attach_args *iba = aux;
     81 
     82 	if (strcmp(iba->iba_busname, cf->cf_driver->cd_name))
     83 		return (0);
     84 
     85 	/* XXX check other indicators */
     86 
     87         return (1);
     88 }
     89 
     90 void
     91 isaattach(struct device *parent, struct device *self, void *aux)
     92 {
     93 	struct isa_softc *sc = (struct isa_softc *)DEV_PRIVATE(self);
     94 	struct isabus_attach_args *iba = aux;
     95 
     96 	sc->sc_devp = self;
     97 
     98 	TAILQ_INIT(&sc->sc_knowndevs);
     99 	sc->sc_dynamicdevs = 0;
    100 
    101 	isa_attach_hook(parent, self, iba);
    102 	printf("\n");
    103 
    104 	/* XXX Add code to fetch known-devices. */
    105 
    106 	sc->sc_iot = iba->iba_iot;
    107 	dev_setprop(self, "io-tag", &sc->sc_iot, sizeof(sc->sc_iot),
    108 		PROP_INT, 0);
    109 	sc->sc_memt = iba->iba_memt;
    110 	dev_setprop(self, "mem-tag", &sc->sc_memt, sizeof(sc->sc_memt),
    111 		PROP_INT, 0);
    112 	sc->sc_dmat = iba->iba_dmat;
    113 	dev_setprop(self, "dma-tag", &sc->sc_dmat, sizeof(sc->sc_dmat),
    114 		PROP_INT, 0);
    115 	sc->sc_ic = iba->iba_ic;
    116 	dev_setprop(self, "chipset-tag", &sc->sc_ic, sizeof(sc->sc_ic),
    117 		PROP_INT, 0);
    118 
    119 #if NISAPNP > 0
    120 	/*
    121 	 * Reset isapnp cards that the bios configured for us
    122 	 */
    123 	isapnp_isa_attach_hook(sc);
    124 #endif
    125 
    126 #if NISADMA > 0
    127 	/*
    128 	 * Initialize our DMA state.
    129 	 */
    130 	isa_dmainit(sc->sc_ic, sc->sc_iot, sc->sc_dmat, self);
    131 #endif
    132 
    133 	/* Attach all direct-config children. */
    134 	isa_attach_knowndevs(sc);
    135 
    136 	/*
    137 	 * If we don't support dynamic hello/goodbye of devices,
    138 	 * then free the knowndevs info now.
    139 	 */
    140 	if (sc->sc_dynamicdevs == 0)
    141 		isa_free_knowndevs(sc);
    142 
    143 	/* Attach all indrect-config children. */
    144 	config_search(isasearch, self, NULL);
    145 }
    146 
    147 void
    148 isa_attach_knowndevs(struct isa_softc *sc)
    149 {
    150 	struct isa_attach_args ia;
    151 	struct isa_knowndev *ik;
    152 	struct device *child;
    153 
    154 	if (TAILQ_EMPTY(&sc->sc_knowndevs))
    155 		return;
    156 
    157 	TAILQ_FOREACH(ik, &sc->sc_knowndevs, ik_list) {
    158 		if (ik->ik_claimed != NULL)
    159 			continue;
    160 
    161 		if ((child = dev_config_create(sc->sc_devp, 0)) == NULL)
    162 			panic("isa_attach_knowndevs: cannot allocate dev");
    163 
    164 		ia.ia_iot = sc->sc_iot;
    165 		ia.ia_memt = sc->sc_memt;
    166 		ia.ia_dmat = sc->sc_dmat;
    167 		ia.ia_ic = sc->sc_ic;
    168 
    169 		ia.ia_pnpname = ik->ik_pnpname;
    170 		if (ik->ik_pnpname) {
    171 			dev_setprop(child, "PNP-name", ik->ik_pnpname,
    172 				strlen(ik->ik_pnpname), PROP_STRING, 0);
    173 		}
    174 		ia.ia_pnpcompatnames = ik->ik_pnpcompatnames;
    175 		if (ik->ik_pnpcompatnames) {
    176 			struct isa_pnpname *ipn;
    177 			char buf[256];
    178 			int i = 0;
    179 
    180 			/*
    181 			 * Yeech.  We need to concatenate all these
    182 			 * annoying strings into one big one and then
    183 			 * create a property with it.  Good thing nothing
    184 			 * currently uses this feature.  Hope 255 bytes is
    185 			 * enough.
    186 			 */
    187 
    188 			for (ipn = ik->ik_pnpcompatnames; ipn != NULL;
    189 			     ipn = ipn->ipn_next) {
    190 				strcpy(&buf[i], ipn->ipn_name);
    191 				i += strlen(ipn->ipn_name);
    192 				buf[i++] = 0;
    193 				if (i > 256)
    194 					panic("isa_attach_knowndevs: compat");
    195 			}
    196 			dev_setprop(child, "PNP-compat", buf, i, PROP_STRING,
    197 				0);
    198 		}
    199 
    200 		ia.ia_io = ik->ik_io;
    201 		ia.ia_nio = ik->ik_nio;
    202 		if (ik->ik_nio) {
    203 			if (ik->ik_io[0].ir_addr != ISACF_PORT_DEFAULT) {
    204 				dev_setprop(child, "port",
    205 					&ik->ik_io[0].ir_addr, sizeof(int),
    206 					PROP_INT, 0);
    207 			}
    208 			if (ik->ik_io[0].ir_size != ISACF_SIZE_DEFAULT) {
    209 				dev_setprop(child, "size",
    210 					&ik->ik_io[0].ir_size, sizeof(int),
    211 					PROP_INT, 0);
    212 			}
    213 		}
    214 
    215 		ia.ia_iomem = ik->ik_iomem;
    216 		ia.ia_niomem = ik->ik_niomem;
    217 		if (ik->ik_niomem) {
    218 			if (ik->ik_iomem[0].ir_addr != ISACF_IOMEM_DEFAULT) {
    219 				dev_setprop(child, "iomem",
    220 					&ik->ik_iomem[0].ir_addr, sizeof(int),
    221 					PROP_INT, 0);
    222 			}
    223 			if (ik->ik_iomem[0].ir_size != ISACF_IOSIZ_DEFAULT) {
    224 				dev_setprop(child, "iosiz",
    225 					&ik->ik_iomem[0].ir_size, sizeof(int),
    226 					PROP_INT, 0);
    227 			}
    228 		}
    229 
    230 		ia.ia_irq = ik->ik_irq;
    231 		ia.ia_nirq = ik->ik_nirq;
    232 		if (ik->ik_nirq) {
    233 			if (ik->ik_irq[0].ir_irq != ISACF_IRQ_DEFAULT) {
    234 				dev_setprop(child, "irq",
    235 					&ik->ik_irq[0].ir_irq, sizeof(int),
    236 					PROP_INT, 0);
    237 			}
    238 		}
    239 
    240 		ia.ia_drq = ik->ik_drq;
    241 		ia.ia_ndrq = ik->ik_ndrq;
    242 		if (ik->ik_ndrq > 0 &&
    243 			ik->ik_drq[0].ir_drq != ISACF_DRQ_DEFAULT) {
    244 			dev_setprop(child, "drq",
    245 				&ik->ik_drq[0].ir_drq, sizeof(int),
    246 				PROP_INT, 0);
    247 		}
    248 		if (ik->ik_ndrq > 1 &&
    249 			ik->ik_drq[1].ir_drq != ISACF_DRQ2_DEFAULT) {
    250 			dev_setprop(child, "drq2",
    251 				&ik->ik_drq[1].ir_drq, sizeof(int),
    252 				PROP_INT, 0);
    253 		}
    254 
    255 		ia.ia_aux = NULL;
    256 
    257 		ik->ik_claimed = config_found_sad(sc->sc_devp, &ia,
    258 		    isaprint, isasubmatch, child);
    259 	}
    260 }
    261 
    262 void
    263 isa_free_knowndevs(struct isa_softc *sc)
    264 {
    265 	struct isa_knowndev *ik;
    266 	struct isa_pnpname *ipn;
    267 
    268 #define	FREEIT(x)	if (x != NULL) free(x, M_DEVBUF)
    269 
    270 	while ((ik = TAILQ_FIRST(&sc->sc_knowndevs)) != NULL) {
    271 		TAILQ_REMOVE(&sc->sc_knowndevs, ik, ik_list);
    272 		FREEIT(ik->ik_pnpname);
    273 		while ((ipn = ik->ik_pnpcompatnames) != NULL) {
    274 			ik->ik_pnpcompatnames = ipn->ipn_next;
    275 			free(ipn->ipn_name, M_DEVBUF);
    276 			free(ipn, M_DEVBUF);
    277 		}
    278 		FREEIT(ik->ik_io);
    279 		FREEIT(ik->ik_iomem);
    280 		FREEIT(ik->ik_irq);
    281 		FREEIT(ik->ik_drq);
    282 		free(ik, M_DEVBUF);
    283 	}
    284 
    285 #undef FREEIT
    286 }
    287 
    288 int
    289 isasubmatch(struct device *parent, struct cfdata *cf, void *aux)
    290 {
    291 	struct isa_attach_args *ia = aux;
    292 	int i;
    293 
    294 	if (ia->ia_nio == 0) {
    295 		if (cf->cf_iobase != ISACF_PORT_DEFAULT)
    296 			return (0);
    297 	} else {
    298 		if (cf->cf_iobase != ISACF_PORT_DEFAULT &&
    299 		    cf->cf_iobase != ia->ia_io[0].ir_addr)
    300 			return (0);
    301 	}
    302 
    303 	if (ia->ia_niomem == 0) {
    304 		if (cf->cf_maddr != ISACF_IOMEM_DEFAULT)
    305 			return (0);
    306 	} else {
    307 		if (cf->cf_maddr != ISACF_IOMEM_DEFAULT &&
    308 		    cf->cf_maddr != ia->ia_iomem[0].ir_addr)
    309 			return (0);
    310 	}
    311 
    312 	if (ia->ia_nirq == 0) {
    313 		if (cf->cf_irq != ISACF_IRQ_DEFAULT)
    314 			return (0);
    315 	} else {
    316 		if (cf->cf_irq != ISACF_IRQ_DEFAULT &&
    317 		    cf->cf_irq != ia->ia_irq[0].ir_irq)
    318 			return (0);
    319 	}
    320 
    321 	if (ia->ia_ndrq == 0) {
    322 		if (cf->cf_drq != ISACF_DRQ_DEFAULT)
    323 			return (0);
    324 		if (cf->cf_drq2 != ISACF_DRQ_DEFAULT)
    325 			return (0);
    326 	} else {
    327 		for (i = 0; i < 2; i++) {
    328 			if (i == ia->ia_ndrq)
    329 				break;
    330 			if (cf->cf_loc[ISACF_DRQ + i] != ISACF_DRQ_DEFAULT &&
    331 			    cf->cf_loc[ISACF_DRQ + i] != ia->ia_drq[i].ir_drq)
    332 				return (0);
    333 		}
    334 		for (; i < 2; i++) {
    335 			if (cf->cf_loc[ISACF_DRQ + i] != ISACF_DRQ_DEFAULT)
    336 				return (0);
    337 		}
    338 	}
    339 
    340 	return ((*cf->cf_attach->ca_match)(parent, cf, aux));
    341 }
    342 
    343 int
    344 isaprint(void *aux, const char *isa)
    345 {
    346 	struct isa_attach_args *ia = aux;
    347 	const char *sep;
    348 	int i;
    349 
    350 	/*
    351 	 * This block of code only fires if we have a direct-config'd
    352 	 * device for which there is no driver match.
    353 	 */
    354 	if (isa != NULL) {
    355 		struct isa_pnpname *ipn;
    356 
    357 		if (ia->ia_pnpname != NULL)
    358 			printf("%s", ia->ia_pnpname);
    359 		if ((ipn = ia->ia_pnpcompatnames) != NULL) {
    360 			printf(" (");	/* ) */
    361 			for (sep = ""; ipn != NULL;
    362 			     ipn = ipn->ipn_next, sep = " ") {
    363 				printf("%s%s", sep, ipn->ipn_name);
    364 			}
    365 	/* ( */		printf(")");
    366 		}
    367 		printf(" at %s", isa);
    368 	}
    369 
    370 	if (ia->ia_nio) {
    371 		sep = "";
    372 		printf(" port ");
    373 		for (i = 0; i < ia->ia_nio; i++) {
    374 			if (ia->ia_io[i].ir_size == 0)
    375 				continue;
    376 			printf("%s0x%x", sep, ia->ia_io[i].ir_addr);
    377 			if (ia->ia_io[i].ir_size > 1)
    378 				printf("-0x%x", ia->ia_io[i].ir_addr +
    379 				    ia->ia_io[i].ir_size - 1);
    380 			sep = ",";
    381 		}
    382 	}
    383 
    384 	if (ia->ia_niomem) {
    385 		sep = "";
    386 		printf(" iomem ");
    387 		for (i = 0; i < ia->ia_niomem; i++) {
    388 			if (ia->ia_iomem[i].ir_size == 0)
    389 				continue;
    390 			printf("%s0x%x", sep, ia->ia_iomem[i].ir_addr);
    391 			if (ia->ia_iomem[i].ir_size > 1)
    392 				printf("-0x%x", ia->ia_iomem[i].ir_addr +
    393 				    ia->ia_iomem[i].ir_size - 1);
    394 			sep = ",";
    395 		}
    396 	}
    397 
    398 	if (ia->ia_nirq) {
    399 		sep = "";
    400 		printf(" irq ");
    401 		for (i = 0; i < ia->ia_nirq; i++) {
    402 			if (ia->ia_irq[i].ir_irq == ISACF_IRQ_DEFAULT)
    403 				continue;
    404 			printf("%s%d", sep, ia->ia_irq[i].ir_irq);
    405 			sep = ",";
    406 		}
    407 	}
    408 
    409 	if (ia->ia_ndrq) {
    410 		sep = "";
    411 		printf(" drq ");
    412 		for (i = 0; i < ia->ia_ndrq; i++) {
    413 			if (ia->ia_drq[i].ir_drq == ISACF_DRQ_DEFAULT)
    414 				continue;
    415 			printf("%s%d", sep, ia->ia_drq[i].ir_drq);
    416 			sep = ",";
    417 		}
    418 	}
    419 
    420 	return (UNCONF);
    421 }
    422 
    423 int
    424 isasearch(struct device *parent, struct cfdata *cf, void *aux)
    425 {
    426 	struct device *child;
    427 	struct isa_io res_io[1];
    428 	struct isa_iomem res_mem[1];
    429 	struct isa_irq res_irq[1];
    430 	struct isa_drq res_drq[2];
    431 	struct isa_softc *sc = (struct isa_softc *)DEV_PRIVATE(parent);
    432 	struct isa_attach_args ia;
    433 	int tryagain = 1;
    434 
    435 	while (tryagain && (child = dev_config_create(parent, 0))) {
    436 		ia.ia_pnpname = NULL;
    437 		ia.ia_pnpcompatnames = NULL;
    438 
    439 		dev_setprop(child, "cd-name", cf->cf_driver->cd_name,
    440 			strlen(cf->cf_driver->cd_name) + 1, PROP_STRING, 0);
    441 
    442 		/*
    443 		 * ISA uses a slightly different property protocol for
    444 		 * locators.  Instead of instantiating "loc-foo" properties
    445 		 * for each locator, we will attach a "foo" property, but
    446 		 * only if the locator is not wildcarded.  When the device
    447 		 * attaches, if it wants to record or override locator
    448 		 * information, it creates appropriate properties, overriding
    449 		 * existing properties created here.
    450 		 */
    451 		res_io[0].ir_addr = cf->cf_loc[ISACF_PORT];
    452 		res_io[0].ir_size = 0;
    453 		if (cf->cf_loc[ISACF_PORT] != ISACF_PORT_DEFAULT) {
    454 			dev_setprop(child, cf->cf_locnames[ISACF_PORT],
    455 				&cf->cf_loc[ISACF_PORT], sizeof(int),
    456 				PROP_CONST|PROP_INT, 0);
    457 		}
    458 
    459 		res_mem[0].ir_addr = cf->cf_loc[ISACF_IOMEM];
    460 		if (cf->cf_loc[ISACF_IOMEM] != ISACF_IOMEM_DEFAULT) {
    461 			dev_setprop(child, cf->cf_locnames[ISACF_IOMEM],
    462 				&cf->cf_loc[ISACF_IOMEM], sizeof(int),
    463 				PROP_CONST|PROP_INT, 0);
    464 		}
    465 		res_mem[0].ir_size = cf->cf_loc[ISACF_IOSIZ];
    466 		if (cf->cf_loc[ISACF_IOSIZ] != ISACF_IOSIZ_DEFAULT) {
    467 			dev_setprop(child, cf->cf_locnames[ISACF_IOSIZ],
    468 				&cf->cf_loc[ISACF_IOSIZ], sizeof(int),
    469 				PROP_CONST|PROP_INT, 0);
    470 		}
    471 
    472 		res_irq[0].ir_irq =
    473 		    cf->cf_loc[ISACF_IRQ] == 2 ? 9 : cf->cf_loc[ISACF_IRQ];
    474 		if (res_irq[0].ir_irq != ISACF_IRQ_DEFAULT) {
    475 			dev_setprop(child, cf->cf_locnames[ISACF_IRQ],
    476 				&res_irq[0].ir_irq, sizeof(int),
    477 				PROP_INT, 0);
    478 		}
    479 
    480 		res_drq[0].ir_drq = cf->cf_loc[ISACF_DRQ];
    481 		if (cf->cf_loc[ISACF_DRQ] != ISACF_DRQ_DEFAULT) {
    482 			dev_setprop(child, cf->cf_locnames[ISACF_DRQ],
    483 				&cf->cf_loc[ISACF_DRQ], sizeof(int),
    484 				PROP_CONST|PROP_INT, 0);
    485 		}
    486 		res_drq[1].ir_drq = cf->cf_loc[ISACF_DRQ2];
    487 		if (cf->cf_loc[ISACF_DRQ2] != ISACF_DRQ2_DEFAULT) {
    488 			dev_setprop(child, cf->cf_locnames[ISACF_DRQ2],
    489 				&cf->cf_loc[ISACF_DRQ2], sizeof(int),
    490 				PROP_CONST|PROP_INT, 0);
    491 		}
    492 
    493 		ia.ia_iot = sc->sc_iot;
    494 		ia.ia_memt = sc->sc_memt;
    495 		ia.ia_dmat = sc->sc_dmat;
    496 		ia.ia_ic = sc->sc_ic;
    497 
    498 		ia.ia_io = res_io;
    499 		ia.ia_nio = 1;
    500 
    501 		ia.ia_iomem = res_mem;
    502 		ia.ia_niomem = 1;
    503 
    504 		ia.ia_irq = res_irq;
    505 		ia.ia_nirq = 1;
    506 
    507 		ia.ia_drq = res_drq;
    508 		ia.ia_ndrq = 2;
    509 
    510 		tryagain = 0;
    511 
    512 		/*
    513 		 * Find out if this is a new driver or old driver and call
    514 		 * the match function in the correct way.
    515 		 */
    516 		if ((ssize_t)cf->cf_attach->ca_devsize < 0) {
    517 			DEV_PRIVATE(child) = &ia;
    518 			if ((*cf->cf_attach->ca_match)(parent, cf, child) > 0) {
    519 				config_attach_ad(parent, cf, &ia,
    520 					isaprint, child);
    521 				tryagain = (cf->cf_fstate == FSTATE_STAR);
    522 			} else {
    523 				/* Destroy unused device node. */
    524 				config_detach(child, 0);
    525 			}
    526 		} else if ((*cf->cf_attach->ca_match)(parent, cf, &ia) > 0) {
    527 
    528 			/*
    529 			 * Old style devices do not update locator
    530 			 * properties, so we'll do that for them.
    531 			 */
    532 			if (res_io[0].ir_addr != cf->cf_loc[ISACF_PORT] &&
    533 				cf->cf_loc[ISACF_PORT] != ISACF_PORT_DEFAULT) {
    534 				dev_setprop(child, cf->cf_locnames[ISACF_PORT],
    535 					&res_io[0].ir_addr, sizeof(int),
    536 					PROP_INT, 0);
    537 			}
    538 			if (res_io[0].ir_size != 0) {
    539 				dev_setprop(child, cf->cf_locnames[ISACF_SIZE],
    540 					&res_io[0].ir_size, sizeof(int),
    541 					PROP_INT, 0);
    542 			}
    543 
    544 			if (res_mem[0].ir_addr != cf->cf_loc[ISACF_IOMEM] &&
    545 				cf->cf_loc[ISACF_IOMEM] !=
    546 				ISACF_IOMEM_DEFAULT) {
    547 				dev_setprop(child, cf->cf_locnames[ISACF_IOMEM],
    548 					&res_mem[0].ir_addr, sizeof(int),
    549 					PROP_INT, 0);
    550 			}
    551 
    552 			if (res_mem[0].ir_addr != cf->cf_loc[ISACF_IOSIZ] &&
    553 				cf->cf_loc[ISACF_IOSIZ] !=
    554 				ISACF_IOSIZ_DEFAULT) {
    555 				dev_setprop(child, cf->cf_locnames[ISACF_IOSIZ],
    556 					&res_mem[0].ir_size, sizeof(int),
    557 					PROP_INT, 0);
    558 			}
    559 
    560 			/*
    561 			 * Since this value may have been twiddled by us
    562 			 * earlier we cannot determine if the value was
    563 			 * untouched by our child.
    564 			 */
    565 			if (res_irq[0].ir_irq != cf->cf_loc[ISACF_IRQ]) {
    566 				dev_setprop(child, cf->cf_locnames[ISACF_IRQ],
    567 					&res_irq[0].ir_irq, sizeof(int),
    568 					PROP_INT, 0);
    569 			}
    570 
    571 			if (res_drq[0].ir_drq != cf->cf_loc[ISACF_DRQ] &&
    572 				cf->cf_loc[ISACF_DRQ] != ISACF_DRQ_DEFAULT) {
    573 				dev_setprop(child, cf->cf_locnames[ISACF_DRQ],
    574 					&res_drq[0].ir_drq, sizeof(int),
    575 					PROP_INT, 0);
    576 			}
    577 			if (res_drq[0].ir_drq != cf->cf_loc[ISACF_DRQ2] &&
    578 				cf->cf_loc[ISACF_DRQ2] != ISACF_DRQ2_DEFAULT) {
    579 				dev_setprop(child, cf->cf_locnames[ISACF_DRQ2],
    580 					&res_drq[0].ir_drq, sizeof(int),
    581 					PROP_INT, 0);
    582 			}
    583 
    584 			config_attach_ad(parent, cf, &ia, isaprint, child);
    585 			tryagain = (cf->cf_fstate == FSTATE_STAR);
    586 		} else {
    587 			/* Destroy unused device node. */
    588 			config_detach(child, 0);
    589 		}
    590 	}
    591 
    592 	return (0);
    593 }
    594 
    595 char *
    596 isa_intr_typename(int type)
    597 {
    598 
    599 	switch (type) {
    600         case IST_NONE :
    601 		return ("none");
    602         case IST_PULSE:
    603 		return ("pulsed");
    604         case IST_EDGE:
    605 		return ("edge-triggered");
    606         case IST_LEVEL:
    607 		return ("level-triggered");
    608 	default:
    609 		panic("isa_intr_typename: invalid type %d", type);
    610 	}
    611 }
    612