xref: /openbsd/sys/dev/isa/isa.c (revision 09467b48)
1 /*	$OpenBSD: isa.c,v 1.47 2019/05/09 17:38:23 semarie 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 isamatch(parent, match, aux)
85 	struct device *parent;
86 	void *match, *aux;
87 {
88 	struct cfdata *cf = match;
89 	struct isabus_attach_args *iba = aux;
90 
91 	if (strcmp(iba->iba_busname, cf->cf_driver->cd_name))
92 		return (0);
93 
94 	/* XXX check other indicators */
95 
96         return (1);
97 }
98 
99 void
100 isaattach(parent, self, aux)
101 	struct device *parent, *self;
102 	void *aux;
103 {
104 	struct isa_softc *sc = (struct isa_softc *)self;
105 	struct isabus_attach_args *iba = aux;
106 
107 	isa_attach_hook(parent, self, iba);
108 	printf("\n");
109 
110 	sc->sc_iot = iba->iba_iot;
111 	sc->sc_memt = iba->iba_memt;
112 #if NISADMA > 0
113 	sc->sc_dmat = iba->iba_dmat;
114 #endif /* NISADMA > 0 */
115 	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 	if (bus_space_map(sc->sc_iot, IO_DMA1, DMA1_IOSIZE, 0, &sc->sc_dma1h))
129 		panic("isaattach: can't map DMA controller #1");
130 	if (bus_space_map(sc->sc_iot, IO_DMA2, DMA2_IOSIZE, 0, &sc->sc_dma2h))
131 		panic("isaattach: can't map DMA controller #2");
132 	if (bus_space_map(sc->sc_iot, IO_DMAPG, 0xf, 0, &sc->sc_dmapgh))
133 		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 	if (bus_space_subregion(sc->sc_iot, sc->sc_dmapgh, 0x04, 1,
141 	    &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 		panic("isaattach: can't map `delay port'");	/* XXX */
147 
148 	TAILQ_INIT(&sc->sc_subdevs);
149 	config_scan(isascan, self);
150 }
151 
152 int
153 isaprint(aux, isa)
154 	void *aux;
155 	const char *isa;
156 {
157 	struct isa_attach_args *ia = aux;
158 	int irq, nirq;
159 	int dma, ndma;
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 
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 
171 	nirq = ia->ipa_nirq;
172 	if (nirq < 0 || nirq > nitems(ia->ipa_irq))
173 		nirq = 1;
174 	for (irq = 0; irq < nirq; irq++)
175 		if (ia->ipa_irq[irq].num != IRQUNK)
176 			printf(" irq %d", ia->ipa_irq[irq].num);
177 
178 	ndma = ia->ipa_ndrq;
179 	if (ndma < 0 || ndma > nitems(ia->ipa_drq))
180 		ndma = 2;
181 	for (dma = 0; dma < ndma; dma++)
182 		if (ia->ipa_drq[dma].num != DRQUNK) {
183 			if (dma == 0)
184 				printf(" drq");
185 			else
186 				printf(" drq%d", dma + 1);
187 			printf(" %d", ia->ipa_drq[dma].num);
188 		}
189 
190 	return (UNCONF);
191 }
192 
193 void
194 isascan(parent, match)
195 	struct device *parent;
196 	void *match;
197 {
198 	struct isa_softc *sc = (struct isa_softc *)parent;
199 	struct device *dev = match;
200 	struct cfdata *cf = dev->dv_cfdata;
201 	struct isa_attach_args ia;
202 
203 	ia.ia_iot = sc->sc_iot;
204 	ia.ia_memt = sc->sc_memt;
205 #if NISADMA > 0
206 	ia.ia_dmat = sc->sc_dmat;
207 #endif /* NISADMA > 0 */
208 	ia.ia_ic = sc->sc_ic;
209 	ia.ia_iobase = cf->cf_iobase;
210 	ia.ia_iosize = 0x666;
211 	ia.ia_maddr = cf->cf_maddr;
212 	ia.ia_msize = cf->cf_msize;
213 	ia.ia_irq = cf->cf_irq == 2 ? 9 : cf->cf_irq;
214 	ia.ipa_nirq = ia.ia_irq == IRQUNK ? 0 : 1;
215 	ia.ia_drq = cf->cf_drq;
216 	ia.ia_drq2 = cf->cf_drq2;
217 	ia.ipa_ndrq = 2;
218 	ia.ia_delaybah = sc->sc_delaybah;
219 
220 	if (cf->cf_fstate == FSTATE_STAR) {
221 		struct isa_attach_args ia2 = ia;
222 
223 		if (autoconf_verbose)
224 			printf(">>> probing for %s*\n",
225 			    cf->cf_driver->cd_name);
226 		while ((*cf->cf_attach->ca_match)(parent, dev, &ia2) > 0) {
227 #if !defined(__NO_ISA_INTR_CHECK)
228 			if ((ia2.ia_irq != IRQUNK) &&
229 			    !isa_intr_check(sc->sc_ic, ia2.ia_irq, IST_EDGE)) {
230 				printf("%s%d: irq %d already in use\n",
231 				    cf->cf_driver->cd_name, cf->cf_unit,
232 				    ia2.ia_irq);
233 				ia2 = ia;
234 				break;
235 			}
236 #endif
237 
238 			if (autoconf_verbose)
239 				printf(">>> probe for %s* clone into %s%d\n",
240 				    cf->cf_driver->cd_name,
241 				    cf->cf_driver->cd_name, cf->cf_unit);
242 			if (ia2.ia_iosize == 0x666) {
243 				printf("%s: iosize not repaired by driver\n",
244 				    sc->sc_dev.dv_xname);
245 				ia2.ia_iosize = 0;
246 			}
247 			config_attach(parent, dev, &ia2, isaprint);
248 			dev = config_make_softc(parent, cf);
249 #if NISADMA > 0
250 			if (ia2.ia_drq != DRQUNK)
251 				ISA_DRQ_ALLOC((struct device *)sc, ia2.ia_drq);
252 			if (ia2.ia_drq2 != DRQUNK)
253 				ISA_DRQ_ALLOC((struct device *)sc, ia2.ia_drq2);
254 #endif /* NISAMDA > 0 */
255 			ia2 = ia;
256 		}
257 		if (autoconf_verbose)
258 			printf(">>> probing for %s* finished\n",
259 			    cf->cf_driver->cd_name);
260 		free(dev, M_DEVBUF, cf->cf_attach->ca_devsize);
261 		return;
262 	}
263 
264 	if (autoconf_verbose)
265 		printf(">>> probing for %s%d\n", cf->cf_driver->cd_name,
266 		    cf->cf_unit);
267 	if ((*cf->cf_attach->ca_match)(parent, dev, &ia) > 0) {
268 #if !defined(__NO_ISA_INTR_CHECK)
269 		if ((ia.ia_irq != IRQUNK) &&
270 		    !isa_intr_check(sc->sc_ic, ia.ia_irq, IST_EDGE)) {
271 			printf("%s%d: irq %d already in use\n",
272 			    cf->cf_driver->cd_name, cf->cf_unit, ia.ia_irq);
273 			free(dev, M_DEVBUF, cf->cf_attach->ca_devsize);
274 		} else {
275 #endif
276 			if (autoconf_verbose)
277 				printf(">>> probing for %s%d succeeded\n",
278 				    cf->cf_driver->cd_name, cf->cf_unit);
279 			config_attach(parent, dev, &ia, isaprint);
280 
281 #if NISADMA > 0
282 			if (ia.ia_drq != DRQUNK)
283 				ISA_DRQ_ALLOC((struct device *)sc, ia.ia_drq);
284 			if (ia.ia_drq2 != DRQUNK)
285 				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 		if (autoconf_verbose)
292 			printf(">>> probing for %s%d failed\n",
293 			    cf->cf_driver->cd_name, cf->cf_unit);
294 		free(dev, M_DEVBUF, cf->cf_attach->ca_devsize);
295 	}
296 }
297 
298 char *
299 isa_intr_typename(type)
300 	int type;
301 {
302 
303 	switch (type) {
304         case IST_NONE:
305 		return ("none");
306         case IST_PULSE:
307 		return ("pulsed");
308         case IST_EDGE:
309 		return ("edge-triggered");
310         case IST_LEVEL:
311 		return ("level-triggered");
312 	default:
313 		panic("isa_intr_typename: invalid type %d", type);
314 	}
315 }
316