diff --git a/sys/dev/isa/isa.c b/sys/dev/isa/isa.c index c348f15a9c0f2..30a5791451817 100644 --- a/sys/dev/isa/isa.c +++ b/sys/dev/isa/isa.c @@ -1,4 +1,4 @@ -/* $NetBSD: isa.c,v 1.110 2002/01/07 21:47:09 thorpej Exp $ */ +/* $NetBSD: isa.c,v 1.110.6.1 2002/04/06 16:12:08 eeh Exp $ */ /*- * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. @@ -37,13 +37,14 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: isa.c,v 1.110 2002/01/07 21:47:09 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: isa.c,v 1.110.6.1 2002/04/06 16:12:08 eeh Exp $"); #include #include #include #include #include +#include #include @@ -89,9 +90,11 @@ isamatch(struct device *parent, struct cfdata *cf, void *aux) void isaattach(struct device *parent, struct device *self, void *aux) { - struct isa_softc *sc = (struct isa_softc *)self; + struct isa_softc *sc = (struct isa_softc *)DEV_PRIVATE(self); struct isabus_attach_args *iba = aux; + sc->sc_devp = self; + TAILQ_INIT(&sc->sc_knowndevs); sc->sc_dynamicdevs = 0; @@ -101,9 +104,17 @@ isaattach(struct device *parent, struct device *self, void *aux) /* XXX Add code to fetch known-devices. */ sc->sc_iot = iba->iba_iot; + dev_setprop(self, "io-tag", &sc->sc_iot, sizeof(sc->sc_iot), + PROP_INT, 0); sc->sc_memt = iba->iba_memt; + dev_setprop(self, "mem-tag", &sc->sc_memt, sizeof(sc->sc_memt), + PROP_INT, 0); sc->sc_dmat = iba->iba_dmat; + dev_setprop(self, "dma-tag", &sc->sc_dmat, sizeof(sc->sc_dmat), + PROP_INT, 0); sc->sc_ic = iba->iba_ic; + dev_setprop(self, "chipset-tag", &sc->sc_ic, sizeof(sc->sc_ic), + PROP_INT, 0); #if NISAPNP > 0 /* @@ -138,6 +149,7 @@ isa_attach_knowndevs(struct isa_softc *sc) { struct isa_attach_args ia; struct isa_knowndev *ik; + struct device *child; if (TAILQ_EMPTY(&sc->sc_knowndevs)) return; @@ -146,30 +158,104 @@ isa_attach_knowndevs(struct isa_softc *sc) if (ik->ik_claimed != NULL) continue; + if ((child = dev_config_create(sc->sc_devp, 0)) == NULL) + panic("isa_attach_knowndevs: cannot allocate dev"); + ia.ia_iot = sc->sc_iot; ia.ia_memt = sc->sc_memt; ia.ia_dmat = sc->sc_dmat; ia.ia_ic = sc->sc_ic; ia.ia_pnpname = ik->ik_pnpname; + if (ik->ik_pnpname) { + dev_setprop(child, "PNP-name", ik->ik_pnpname, + strlen(ik->ik_pnpname), PROP_STRING, 0); + } ia.ia_pnpcompatnames = ik->ik_pnpcompatnames; + if (ik->ik_pnpcompatnames) { + struct isa_pnpname *ipn; + char buf[256]; + int i = 0; + + /* + * Yeech. We need to concatenate all these + * annoying strings into one big one and then + * create a property with it. Good thing nothing + * currently uses this feature. Hope 255 bytes is + * enough. + */ + + for (ipn = ik->ik_pnpcompatnames; ipn != NULL; + ipn = ipn->ipn_next) { + strcpy(&buf[i], ipn->ipn_name); + i += strlen(ipn->ipn_name); + buf[i++] = 0; + if (i > 256) + panic("isa_attach_knowndevs: compat"); + } + dev_setprop(child, "PNP-compat", buf, i, PROP_STRING, + 0); + } ia.ia_io = ik->ik_io; ia.ia_nio = ik->ik_nio; + if (ik->ik_nio) { + if (ik->ik_io[0].ir_addr != ISACF_PORT_DEFAULT) { + dev_setprop(child, "port", + &ik->ik_io[0].ir_addr, sizeof(int), + PROP_INT, 0); + } + if (ik->ik_io[0].ir_size != ISACF_SIZE_DEFAULT) { + dev_setprop(child, "size", + &ik->ik_io[0].ir_size, sizeof(int), + PROP_INT, 0); + } + } ia.ia_iomem = ik->ik_iomem; ia.ia_niomem = ik->ik_niomem; + if (ik->ik_niomem) { + if (ik->ik_iomem[0].ir_addr != ISACF_IOMEM_DEFAULT) { + dev_setprop(child, "iomem", + &ik->ik_iomem[0].ir_addr, sizeof(int), + PROP_INT, 0); + } + if (ik->ik_iomem[0].ir_size != ISACF_IOSIZ_DEFAULT) { + dev_setprop(child, "iosiz", + &ik->ik_iomem[0].ir_size, sizeof(int), + PROP_INT, 0); + } + } ia.ia_irq = ik->ik_irq; ia.ia_nirq = ik->ik_nirq; + if (ik->ik_nirq) { + if (ik->ik_irq[0].ir_irq != ISACF_IRQ_DEFAULT) { + dev_setprop(child, "irq", + &ik->ik_irq[0].ir_irq, sizeof(int), + PROP_INT, 0); + } + } ia.ia_drq = ik->ik_drq; ia.ia_ndrq = ik->ik_ndrq; + if (ik->ik_ndrq > 0 && + ik->ik_drq[0].ir_drq != ISACF_DRQ_DEFAULT) { + dev_setprop(child, "drq", + &ik->ik_drq[0].ir_drq, sizeof(int), + PROP_INT, 0); + } + if (ik->ik_ndrq > 1 && + ik->ik_drq[1].ir_drq != ISACF_DRQ2_DEFAULT) { + dev_setprop(child, "drq2", + &ik->ik_drq[1].ir_drq, sizeof(int), + PROP_INT, 0); + } ia.ia_aux = NULL; - ik->ik_claimed = config_found_sm(&sc->sc_dev, &ia, - isaprint, isasubmatch); + ik->ik_claimed = config_found_sad(sc->sc_devp, &ia, + isaprint, isasubmatch, child); } } @@ -337,29 +423,72 @@ isaprint(void *aux, const char *isa) int isasearch(struct device *parent, struct cfdata *cf, void *aux) { + struct device *child; struct isa_io res_io[1]; struct isa_iomem res_mem[1]; struct isa_irq res_irq[1]; struct isa_drq res_drq[2]; - struct isa_softc *sc = (struct isa_softc *)parent; + struct isa_softc *sc = (struct isa_softc *)DEV_PRIVATE(parent); struct isa_attach_args ia; - int tryagain; + int tryagain = 1; - do { + while (tryagain && (child = dev_config_create(parent, 0))) { ia.ia_pnpname = NULL; ia.ia_pnpcompatnames = NULL; + dev_setprop(child, "cd-name", cf->cf_driver->cd_name, + strlen(cf->cf_driver->cd_name) + 1, PROP_STRING, 0); + + /* + * ISA uses a slightly different property protocol for + * locators. Instead of instantiating "loc-foo" properties + * for each locator, we will attach a "foo" property, but + * only if the locator is not wildcarded. When the device + * attaches, if it wants to record or override locator + * information, it creates appropriate properties, overriding + * existing properties created here. + */ res_io[0].ir_addr = cf->cf_loc[ISACF_PORT]; res_io[0].ir_size = 0; + if (cf->cf_loc[ISACF_PORT] != ISACF_PORT_DEFAULT) { + dev_setprop(child, cf->cf_locnames[ISACF_PORT], + &cf->cf_loc[ISACF_PORT], sizeof(int), + PROP_CONST|PROP_INT, 0); + } res_mem[0].ir_addr = cf->cf_loc[ISACF_IOMEM]; + if (cf->cf_loc[ISACF_IOMEM] != ISACF_IOMEM_DEFAULT) { + dev_setprop(child, cf->cf_locnames[ISACF_IOMEM], + &cf->cf_loc[ISACF_IOMEM], sizeof(int), + PROP_CONST|PROP_INT, 0); + } res_mem[0].ir_size = cf->cf_loc[ISACF_IOSIZ]; + if (cf->cf_loc[ISACF_IOSIZ] != ISACF_IOSIZ_DEFAULT) { + dev_setprop(child, cf->cf_locnames[ISACF_IOSIZ], + &cf->cf_loc[ISACF_IOSIZ], sizeof(int), + PROP_CONST|PROP_INT, 0); + } res_irq[0].ir_irq = cf->cf_loc[ISACF_IRQ] == 2 ? 9 : cf->cf_loc[ISACF_IRQ]; + if (res_irq[0].ir_irq != ISACF_IRQ_DEFAULT) { + dev_setprop(child, cf->cf_locnames[ISACF_IRQ], + &res_irq[0].ir_irq, sizeof(int), + PROP_INT, 0); + } res_drq[0].ir_drq = cf->cf_loc[ISACF_DRQ]; + if (cf->cf_loc[ISACF_DRQ] != ISACF_DRQ_DEFAULT) { + dev_setprop(child, cf->cf_locnames[ISACF_DRQ], + &cf->cf_loc[ISACF_DRQ], sizeof(int), + PROP_CONST|PROP_INT, 0); + } res_drq[1].ir_drq = cf->cf_loc[ISACF_DRQ2]; + if (cf->cf_loc[ISACF_DRQ2] != ISACF_DRQ2_DEFAULT) { + dev_setprop(child, cf->cf_locnames[ISACF_DRQ2], + &cf->cf_loc[ISACF_DRQ2], sizeof(int), + PROP_CONST|PROP_INT, 0); + } ia.ia_iot = sc->sc_iot; ia.ia_memt = sc->sc_memt; @@ -379,11 +508,86 @@ isasearch(struct device *parent, struct cfdata *cf, void *aux) ia.ia_ndrq = 2; tryagain = 0; - if ((*cf->cf_attach->ca_match)(parent, cf, &ia) > 0) { - config_attach(parent, cf, &ia, isaprint); + + /* + * Find out if this is a new driver or old driver and call + * the match function in the correct way. + */ + if ((ssize_t)cf->cf_attach->ca_devsize < 0) { + DEV_PRIVATE(child) = &ia; + if ((*cf->cf_attach->ca_match)(parent, cf, child) > 0) { + config_attach_ad(parent, cf, &ia, + isaprint, child); + tryagain = (cf->cf_fstate == FSTATE_STAR); + } else { + /* Destroy unused device node. */ + config_detach(child, 0); + } + } else if ((*cf->cf_attach->ca_match)(parent, cf, &ia) > 0) { + + /* + * Old style devices do not update locator + * properties, so we'll do that for them. + */ + if (res_io[0].ir_addr != cf->cf_loc[ISACF_PORT] && + cf->cf_loc[ISACF_PORT] != ISACF_PORT_DEFAULT) { + dev_setprop(child, cf->cf_locnames[ISACF_PORT], + &res_io[0].ir_addr, sizeof(int), + PROP_INT, 0); + } + if (res_io[0].ir_size != 0) { + dev_setprop(child, cf->cf_locnames[ISACF_SIZE], + &res_io[0].ir_size, sizeof(int), + PROP_INT, 0); + } + + if (res_mem[0].ir_addr != cf->cf_loc[ISACF_IOMEM] && + cf->cf_loc[ISACF_IOMEM] != + ISACF_IOMEM_DEFAULT) { + dev_setprop(child, cf->cf_locnames[ISACF_IOMEM], + &res_mem[0].ir_addr, sizeof(int), + PROP_INT, 0); + } + + if (res_mem[0].ir_addr != cf->cf_loc[ISACF_IOSIZ] && + cf->cf_loc[ISACF_IOSIZ] != + ISACF_IOSIZ_DEFAULT) { + dev_setprop(child, cf->cf_locnames[ISACF_IOSIZ], + &res_mem[0].ir_size, sizeof(int), + PROP_INT, 0); + } + + /* + * Since this value may have been twiddled by us + * earlier we cannot determine if the value was + * untouched by our child. + */ + if (res_irq[0].ir_irq != cf->cf_loc[ISACF_IRQ]) { + dev_setprop(child, cf->cf_locnames[ISACF_IRQ], + &res_irq[0].ir_irq, sizeof(int), + PROP_INT, 0); + } + + if (res_drq[0].ir_drq != cf->cf_loc[ISACF_DRQ] && + cf->cf_loc[ISACF_DRQ] != ISACF_DRQ_DEFAULT) { + dev_setprop(child, cf->cf_locnames[ISACF_DRQ], + &res_drq[0].ir_drq, sizeof(int), + PROP_INT, 0); + } + if (res_drq[0].ir_drq != cf->cf_loc[ISACF_DRQ2] && + cf->cf_loc[ISACF_DRQ2] != ISACF_DRQ2_DEFAULT) { + dev_setprop(child, cf->cf_locnames[ISACF_DRQ2], + &res_drq[0].ir_drq, sizeof(int), + PROP_INT, 0); + } + + config_attach_ad(parent, cf, &ia, isaprint, child); tryagain = (cf->cf_fstate == FSTATE_STAR); + } else { + /* Destroy unused device node. */ + config_detach(child, 0); } - } while (tryagain); + } return (0); } diff --git a/sys/dev/isa/isavar.h b/sys/dev/isa/isavar.h index fdb084acd7866..48262f0db5014 100644 --- a/sys/dev/isa/isavar.h +++ b/sys/dev/isa/isavar.h @@ -1,4 +1,4 @@ -/* $NetBSD: isavar.h,v 1.39 2002/01/07 21:47:10 thorpej Exp $ */ +/* $NetBSD: isavar.h,v 1.39.6.1 2002/04/06 16:12:08 eeh Exp $ */ /*- * Copyright (c) 1997, 2001 The NetBSD Foundation, Inc. @@ -218,6 +218,7 @@ struct isa_attach_args { */ struct isa_softc { struct device sc_dev; /* base device */ + struct device *sc_devp; bus_space_tag_t sc_iot; /* isa io space tag */ bus_space_tag_t sc_memt; /* isa mem space tag */