1 /* $OpenBSD: isa.c,v 1.39 2003/06/03 21:09:02 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
79 };
80
81 struct cfdriver isa_cd = {
82 NULL, "isa", DV_DULL, 1
83 };
84
85 int
86 isamatch(parent, match, aux)
87 struct device *parent;
88 void *match, *aux;
89 {
90 struct cfdata *cf = match;
91 struct isabus_attach_args *iba = aux;
92
93 if (strcmp(iba->iba_busname, cf->cf_driver->cd_name))
94 return (0);
95
96 /* XXX check other indicators */
97
98 return (1);
99 }
100
101 void
102 isaattach(parent, self, aux)
103 struct device *parent, *self;
104 void *aux;
105 {
106 struct isa_softc *sc = (struct isa_softc *)self;
107 struct isabus_attach_args *iba = aux;
108
109 isa_attach_hook(parent, self, iba);
110 printf("\n");
111
112 sc->sc_iot = iba->iba_iot;
113 sc->sc_memt = iba->iba_memt;
114 #if NISADMA > 0
115 sc->sc_dmat = iba->iba_dmat;
116 #endif /* NISADMA > 0 */
117 sc->sc_ic = iba->iba_ic;
118
119 #if NISAPNP > 0
120 isapnp_isa_attach_hook(sc);
121 #endif
122
123 #if NISADMA > 0
124 /*
125 * Map the registers used by the ISA DMA controller.
126 * XXX Should be done in the isadmaattach routine.. but the delay
127 * XXX port makes it troublesome. Note that these aren't really
128 * XXX valid on ISA busses without DMA.
129 */
130 if (bus_space_map(sc->sc_iot, IO_DMA1, DMA1_IOSIZE, 0, &sc->sc_dma1h))
131 panic("isaattach: can't map DMA controller #1");
132 if (bus_space_map(sc->sc_iot, IO_DMA2, DMA2_IOSIZE, 0, &sc->sc_dma2h))
133 panic("isaattach: can't map DMA controller #2");
134 if (bus_space_map(sc->sc_iot, IO_DMAPG, 0xf, 0, &sc->sc_dmapgh))
135 panic("isaattach: can't map DMA page registers");
136
137 /*
138 * Map port 0x84, which causes a 1.25us delay when read.
139 * We do this now, since several drivers need it.
140 * XXX this port doesn't exist on all ISA busses...
141 */
142 if (bus_space_subregion(sc->sc_iot, sc->sc_dmapgh, 0x04, 1,
143 &sc->sc_delaybah))
144 #else /* NISADMA > 0 */
145 if (bus_space_map(sc->sc_iot, IO_DMAPG + 0x4, 0x1, 0,
146 &sc->sc_delaybah))
147 #endif /* NISADMA > 0 */
148 panic("isaattach: can't map `delay port'"); /* XXX */
149
150 TAILQ_INIT(&sc->sc_subdevs);
151 config_scan(isascan, self);
152 }
153
154 int
155 isaprint(aux, isa)
156 void *aux;
157 const char *isa;
158 {
159 struct isa_attach_args *ia = aux;
160
161 if (ia->ia_iosize)
162 printf(" port 0x%x", ia->ia_iobase);
163 if (ia->ia_iosize > 1)
164 printf("/%d", ia->ia_iosize);
165 if (ia->ia_msize)
166 printf(" iomem 0x%x", ia->ia_maddr);
167 if (ia->ia_msize > 1)
168 printf("/%d", ia->ia_msize);
169 if (ia->ia_irq != IRQUNK)
170 printf(" irq %d", ia->ia_irq);
171 if (ia->ia_drq != DRQUNK)
172 printf(" drq %d", ia->ia_drq);
173 if (ia->ia_drq2 != DRQUNK)
174 printf(" drq2 %d", ia->ia_drq2);
175 return (UNCONF);
176 }
177
178 void
179 isascan(parent, match)
180 struct device *parent;
181 void *match;
182 {
183 struct isa_softc *sc = (struct isa_softc *)parent;
184 struct device *dev = match;
185 struct cfdata *cf = dev->dv_cfdata;
186 struct isa_attach_args ia;
187
188 ia.ia_iot = sc->sc_iot;
189 ia.ia_memt = sc->sc_memt;
190 #if NISADMA > 0
191 ia.ia_dmat = sc->sc_dmat;
192 #endif /* NISADMA > 0 */
193 ia.ia_ic = sc->sc_ic;
194 ia.ia_iobase = cf->cf_iobase;
195 ia.ia_iosize = 0x666;
196 ia.ia_maddr = cf->cf_maddr;
197 ia.ia_msize = cf->cf_msize;
198 ia.ia_irq = cf->cf_irq == 2 ? 9 : cf->cf_irq;
199 ia.ia_drq = cf->cf_drq;
200 ia.ia_drq2 = cf->cf_drq2;
201 ia.ia_delaybah = sc->sc_delaybah;
202
203 if (cf->cf_fstate == FSTATE_STAR) {
204 struct isa_attach_args ia2 = ia;
205
206 if (autoconf_verbose)
207 printf(">>> probing for %s*\n",
208 cf->cf_driver->cd_name);
209 while ((*cf->cf_attach->ca_match)(parent, dev, &ia2) > 0) {
210 #if !defined(__NO_ISA_INTR_CHECK)
211 if ((ia2.ia_irq != IRQUNK) &&
212 !isa_intr_check(sc->sc_ic, ia2.ia_irq, IST_EDGE)) {
213 printf("%s%d: irq %d already in use\n",
214 cf->cf_driver->cd_name, cf->cf_unit,
215 ia2.ia_irq);
216 ia2 = ia;
217 break;
218 }
219 #endif
220
221 if (autoconf_verbose)
222 printf(">>> probe for %s* clone into %s%d\n",
223 cf->cf_driver->cd_name,
224 cf->cf_driver->cd_name, cf->cf_unit);
225 if (ia2.ia_iosize == 0x666) {
226 printf("%s: iosize not repaired by driver\n",
227 sc->sc_dev.dv_xname);
228 ia2.ia_iosize = 0;
229 }
230 config_attach(parent, dev, &ia2, isaprint);
231 dev = config_make_softc(parent, cf);
232 #if NISADMA > 0
233 if (ia2.ia_drq != DRQUNK)
234 ISA_DRQ_ALLOC((struct device *)sc, ia2.ia_drq);
235 if (ia2.ia_drq2 != DRQUNK)
236 ISA_DRQ_ALLOC((struct device *)sc, ia2.ia_drq2);
237 #endif /* NISAMDA > 0 */
238 ia2 = ia;
239 }
240 if (autoconf_verbose)
241 printf(">>> probing for %s* finished\n",
242 cf->cf_driver->cd_name);
243 free(dev, M_DEVBUF);
244 return;
245 }
246
247 if (autoconf_verbose)
248 printf(">>> probing for %s%d\n", cf->cf_driver->cd_name,
249 cf->cf_unit);
250 if ((*cf->cf_attach->ca_match)(parent, dev, &ia) > 0) {
251 #if !defined(__NO_ISA_INTR_CHECK)
252 if ((ia.ia_irq != IRQUNK) &&
253 !isa_intr_check(sc->sc_ic, ia.ia_irq, IST_EDGE)) {
254 printf("%s%d: irq %d already in use\n",
255 cf->cf_driver->cd_name, cf->cf_unit, ia.ia_irq);
256 free(dev, M_DEVBUF);
257 } else {
258 #endif
259 if (autoconf_verbose)
260 printf(">>> probing for %s%d succeeded\n",
261 cf->cf_driver->cd_name, cf->cf_unit);
262 config_attach(parent, dev, &ia, isaprint);
263
264 #if NISADMA > 0
265 if (ia.ia_drq != DRQUNK)
266 ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq);
267 if (ia.ia_drq2 != DRQUNK)
268 ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq2);
269 #endif /* NISAMDA > 0 */
270 #if !defined(__NO_ISA_INTR_CHECK)
271 }
272 #endif
273 } else {
274 if (autoconf_verbose)
275 printf(">>> probing for %s%d failed\n",
276 cf->cf_driver->cd_name, cf->cf_unit);
277 free(dev, M_DEVBUF);
278 }
279 }
280
281 char *
282 isa_intr_typename(type)
283 int type;
284 {
285
286 switch (type) {
287 case IST_NONE:
288 return ("none");
289 case IST_PULSE:
290 return ("pulsed");
291 case IST_EDGE:
292 return ("edge-triggered");
293 case IST_LEVEL:
294 return ("level-triggered");
295 default:
296 panic("isa_intr_typename: invalid type %d", type);
297 }
298 }