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