xref: /openbsd-src/sys/dev/isa/isa.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
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