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