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