1 /* $OpenBSD: isa.c,v 1.40 2010/07/08 20:18:32 deraadt Exp $ */ 2 /* $NetBSD: isa.c,v 1.85 1996/05/14 00:31:04 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1997, Jason Downs. 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS 17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /*- 30 * Copyright (c) 1993, 1994 Charles Hannum. All rights reserved. 31 * 32 * Redistribution and use in source and binary forms, with or without 33 * modification, are permitted provided that the following conditions 34 * are met: 35 * 1. Redistributions of source code must retain the above copyright 36 * notice, this list of conditions and the following disclaimer. 37 * 2. Redistributions in binary form must reproduce the above copyright 38 * notice, this list of conditions and the following disclaimer in the 39 * documentation and/or other materials provided with the distribution. 40 * 3. All advertising materials mentioning features or use of this software 41 * must display the following acknowledgement: 42 * This product includes software developed by Charles Hannum. 43 * 4. The name of the author may not be used to endorse or promote products 44 * derived from this software without specific prior written permission. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 51 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 */ 57 58 #include <sys/param.h> 59 #include <sys/systm.h> 60 #include <sys/kernel.h> 61 #include <sys/conf.h> 62 #include <sys/malloc.h> 63 #include <sys/device.h> 64 #include <sys/extent.h> 65 66 #include <machine/intr.h> 67 68 #include <dev/isa/isareg.h> 69 #include <dev/isa/isavar.h> 70 #include <dev/isa/isadmareg.h> 71 72 int isamatch(struct device *, void *, void *); 73 void isaattach(struct device *, struct device *, void *); 74 75 extern int autoconf_verbose; 76 77 struct cfattach isa_ca = { 78 sizeof(struct isa_softc), isamatch, isaattach, NULL, 79 config_activate_children 80 }; 81 82 struct cfdriver isa_cd = { 83 NULL, "isa", DV_DULL, 1 84 }; 85 86 int 87 isamatch(parent, match, aux) 88 struct device *parent; 89 void *match, *aux; 90 { 91 struct cfdata *cf = match; 92 struct isabus_attach_args *iba = aux; 93 94 if (strcmp(iba->iba_busname, cf->cf_driver->cd_name)) 95 return (0); 96 97 /* XXX check other indicators */ 98 99 return (1); 100 } 101 102 void 103 isaattach(parent, self, aux) 104 struct device *parent, *self; 105 void *aux; 106 { 107 struct isa_softc *sc = (struct isa_softc *)self; 108 struct isabus_attach_args *iba = aux; 109 110 isa_attach_hook(parent, self, iba); 111 printf("\n"); 112 113 sc->sc_iot = iba->iba_iot; 114 sc->sc_memt = iba->iba_memt; 115 #if NISADMA > 0 116 sc->sc_dmat = iba->iba_dmat; 117 #endif /* NISADMA > 0 */ 118 sc->sc_ic = iba->iba_ic; 119 120 #if NISAPNP > 0 121 isapnp_isa_attach_hook(sc); 122 #endif 123 124 #if NISADMA > 0 125 /* 126 * Map the registers used by the ISA DMA controller. 127 * XXX Should be done in the isadmaattach routine.. but the delay 128 * XXX port makes it troublesome. Note that these aren't really 129 * XXX valid on ISA busses without DMA. 130 */ 131 if (bus_space_map(sc->sc_iot, IO_DMA1, DMA1_IOSIZE, 0, &sc->sc_dma1h)) 132 panic("isaattach: can't map DMA controller #1"); 133 if (bus_space_map(sc->sc_iot, IO_DMA2, DMA2_IOSIZE, 0, &sc->sc_dma2h)) 134 panic("isaattach: can't map DMA controller #2"); 135 if (bus_space_map(sc->sc_iot, IO_DMAPG, 0xf, 0, &sc->sc_dmapgh)) 136 panic("isaattach: can't map DMA page registers"); 137 138 /* 139 * Map port 0x84, which causes a 1.25us delay when read. 140 * We do this now, since several drivers need it. 141 * XXX this port doesn't exist on all ISA busses... 142 */ 143 if (bus_space_subregion(sc->sc_iot, sc->sc_dmapgh, 0x04, 1, 144 &sc->sc_delaybah)) 145 #else /* NISADMA > 0 */ 146 if (bus_space_map(sc->sc_iot, IO_DMAPG + 0x4, 0x1, 0, 147 &sc->sc_delaybah)) 148 #endif /* NISADMA > 0 */ 149 panic("isaattach: can't map `delay port'"); /* XXX */ 150 151 TAILQ_INIT(&sc->sc_subdevs); 152 config_scan(isascan, self); 153 } 154 155 int 156 isaprint(aux, isa) 157 void *aux; 158 const char *isa; 159 { 160 struct isa_attach_args *ia = aux; 161 162 if (ia->ia_iosize) 163 printf(" port 0x%x", ia->ia_iobase); 164 if (ia->ia_iosize > 1) 165 printf("/%d", ia->ia_iosize); 166 if (ia->ia_msize) 167 printf(" iomem 0x%x", ia->ia_maddr); 168 if (ia->ia_msize > 1) 169 printf("/%d", ia->ia_msize); 170 if (ia->ia_irq != IRQUNK) 171 printf(" irq %d", ia->ia_irq); 172 if (ia->ia_drq != DRQUNK) 173 printf(" drq %d", ia->ia_drq); 174 if (ia->ia_drq2 != DRQUNK) 175 printf(" drq2 %d", ia->ia_drq2); 176 return (UNCONF); 177 } 178 179 void 180 isascan(parent, match) 181 struct device *parent; 182 void *match; 183 { 184 struct isa_softc *sc = (struct isa_softc *)parent; 185 struct device *dev = match; 186 struct cfdata *cf = dev->dv_cfdata; 187 struct isa_attach_args ia; 188 189 ia.ia_iot = sc->sc_iot; 190 ia.ia_memt = sc->sc_memt; 191 #if NISADMA > 0 192 ia.ia_dmat = sc->sc_dmat; 193 #endif /* NISADMA > 0 */ 194 ia.ia_ic = sc->sc_ic; 195 ia.ia_iobase = cf->cf_iobase; 196 ia.ia_iosize = 0x666; 197 ia.ia_maddr = cf->cf_maddr; 198 ia.ia_msize = cf->cf_msize; 199 ia.ia_irq = cf->cf_irq == 2 ? 9 : cf->cf_irq; 200 ia.ia_drq = cf->cf_drq; 201 ia.ia_drq2 = cf->cf_drq2; 202 ia.ia_delaybah = sc->sc_delaybah; 203 204 if (cf->cf_fstate == FSTATE_STAR) { 205 struct isa_attach_args ia2 = ia; 206 207 if (autoconf_verbose) 208 printf(">>> probing for %s*\n", 209 cf->cf_driver->cd_name); 210 while ((*cf->cf_attach->ca_match)(parent, dev, &ia2) > 0) { 211 #if !defined(__NO_ISA_INTR_CHECK) 212 if ((ia2.ia_irq != IRQUNK) && 213 !isa_intr_check(sc->sc_ic, ia2.ia_irq, IST_EDGE)) { 214 printf("%s%d: irq %d already in use\n", 215 cf->cf_driver->cd_name, cf->cf_unit, 216 ia2.ia_irq); 217 ia2 = ia; 218 break; 219 } 220 #endif 221 222 if (autoconf_verbose) 223 printf(">>> probe for %s* clone into %s%d\n", 224 cf->cf_driver->cd_name, 225 cf->cf_driver->cd_name, cf->cf_unit); 226 if (ia2.ia_iosize == 0x666) { 227 printf("%s: iosize not repaired by driver\n", 228 sc->sc_dev.dv_xname); 229 ia2.ia_iosize = 0; 230 } 231 config_attach(parent, dev, &ia2, isaprint); 232 dev = config_make_softc(parent, cf); 233 #if NISADMA > 0 234 if (ia2.ia_drq != DRQUNK) 235 ISA_DRQ_ALLOC((struct device *)sc, ia2.ia_drq); 236 if (ia2.ia_drq2 != DRQUNK) 237 ISA_DRQ_ALLOC((struct device *)sc, ia2.ia_drq2); 238 #endif /* NISAMDA > 0 */ 239 ia2 = ia; 240 } 241 if (autoconf_verbose) 242 printf(">>> probing for %s* finished\n", 243 cf->cf_driver->cd_name); 244 free(dev, M_DEVBUF); 245 return; 246 } 247 248 if (autoconf_verbose) 249 printf(">>> probing for %s%d\n", cf->cf_driver->cd_name, 250 cf->cf_unit); 251 if ((*cf->cf_attach->ca_match)(parent, dev, &ia) > 0) { 252 #if !defined(__NO_ISA_INTR_CHECK) 253 if ((ia.ia_irq != IRQUNK) && 254 !isa_intr_check(sc->sc_ic, ia.ia_irq, IST_EDGE)) { 255 printf("%s%d: irq %d already in use\n", 256 cf->cf_driver->cd_name, cf->cf_unit, ia.ia_irq); 257 free(dev, M_DEVBUF); 258 } else { 259 #endif 260 if (autoconf_verbose) 261 printf(">>> probing for %s%d succeeded\n", 262 cf->cf_driver->cd_name, cf->cf_unit); 263 config_attach(parent, dev, &ia, isaprint); 264 265 #if NISADMA > 0 266 if (ia.ia_drq != DRQUNK) 267 ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq); 268 if (ia.ia_drq2 != DRQUNK) 269 ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq2); 270 #endif /* NISAMDA > 0 */ 271 #if !defined(__NO_ISA_INTR_CHECK) 272 } 273 #endif 274 } else { 275 if (autoconf_verbose) 276 printf(">>> probing for %s%d failed\n", 277 cf->cf_driver->cd_name, cf->cf_unit); 278 free(dev, M_DEVBUF); 279 } 280 } 281 282 char * 283 isa_intr_typename(type) 284 int type; 285 { 286 287 switch (type) { 288 case IST_NONE: 289 return ("none"); 290 case IST_PULSE: 291 return ("pulsed"); 292 case IST_EDGE: 293 return ("edge-triggered"); 294 case IST_LEVEL: 295 return ("level-triggered"); 296 default: 297 panic("isa_intr_typename: invalid type %d", type); 298 } 299 } 300