isa_machdep.c revision 1.20 1 /* $NetBSD: isa_machdep.c,v 1.20 2001/01/07 21:17:32 leo Exp $ */
2
3 /*
4 * Copyright (c) 1997 Leo Weppelman. All rights reserved.
5 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
6 * Copyright (c) 1994 Charles M. Hannum. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Charles M. Hannum.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/time.h>
37 #include <sys/systm.h>
38 #include <sys/errno.h>
39 #include <sys/device.h>
40
41 #include <uvm/uvm_extern.h>
42
43 #include <dev/isa/isavar.h>
44 #include <dev/isa/isareg.h>
45
46 #include <m68k/asm_single.h>
47
48 #include <machine/bus.h>
49 #include <machine/cpu.h>
50 #include <machine/iomap.h>
51 #include <machine/mfp.h>
52 #include <atari/atari/device.h>
53
54 static int isabusprint __P((void *auxp, const char *));
55 static int isabusmatch __P((struct device *, struct cfdata *, void *));
56 static void isabusattach __P((struct device *, struct device *, void *));
57
58 struct isabus_softc {
59 struct device sc_dev;
60 struct atari_isa_chipset sc_chipset;
61 };
62
63 struct cfattach isabus_ca = {
64 sizeof(struct isabus_softc), isabusmatch, isabusattach
65 };
66
67 int
68 isabusmatch(pdp, cfp, auxp)
69 struct device *pdp;
70 struct cfdata *cfp;
71 void *auxp;
72 {
73 static int nmatched = 0;
74
75 if (strcmp((char *)auxp, "isabus"))
76 return (0); /* Wrong number... */
77
78 if(atari_realconfig == 0)
79 return (0);
80
81 if (machineid & (ATARI_HADES|ATARI_MILAN)) {
82 /*
83 * The Hades and Milan have only one pci bus
84 */
85 if (nmatched)
86 return (0);
87 nmatched++;
88 return (1);
89 }
90 return(0);
91 }
92
93 void
94 isabusattach(pdp, dp, auxp)
95 struct device *pdp, *dp;
96 void *auxp;
97 {
98 struct isabus_softc *sc = (struct isabus_softc *)dp;
99 struct isabus_attach_args iba;
100
101 iba.iba_busname = "isa";
102 iba.iba_dmat = BUS_ISA_DMA_TAG;
103 iba.iba_iot = leb_alloc_bus_space_tag(NULL);
104 iba.iba_memt = leb_alloc_bus_space_tag(NULL);
105 iba.iba_ic = &sc->sc_chipset;
106 if ((iba.iba_iot == NULL) || (iba.iba_memt == NULL)) {
107 printf("leb_alloc_bus_space_tag failed!\n");
108 return;
109 }
110 iba.iba_iot->base = ISA_IOSTART;
111 iba.iba_memt->base = ISA_MEMSTART;
112
113 MFP->mf_aer |= (IO_ISA1|IO_ISA2); /* ISA interrupts: LOW->HIGH */
114
115 printf("\n");
116 config_found(dp, &iba, isabusprint);
117 }
118
119 int
120 isabusprint(auxp, name)
121 void *auxp;
122 const char *name;
123 {
124 if(name == NULL)
125 return(UNCONF);
126 return(QUIET);
127 }
128
129 void
130 isa_attach_hook(parent, self, iba)
131 struct device *parent, *self;
132 struct isabus_attach_args *iba;
133 {
134 }
135
136 /*
137 * The interrupt stuff is rather ugly. On the Hades, all interrupt lines
138 * for a slot are wired together and connected to either IO3 (slot1) or
139 * IO7 (slot2). Since no info can be obtained about the slot position
140 * at isa_intr_establish() time, the following assumption is made:
141 * - irq <= 6 -> slot 1
142 * - irq > 6 -> slot 2
143 */
144
145 #define SLOTNR(irq) ((irq <= 6) ? 0 : 1)
146
147 static isa_intr_info_t iinfo[2] = { { -1 }, { -1 } };
148
149 static int iifun __P((int, int));
150
151 static int
152 iifun(slot, sr)
153 int slot;
154 int sr;
155 {
156 isa_intr_info_t *iinfo_p;
157 int s;
158
159 iinfo_p = &iinfo[slot];
160
161 /*
162 * Disable the interrupts
163 */
164 if (slot == 0) {
165 single_inst_bclr_b(MFP->mf_imrb, IB_ISA1);
166 }
167 else {
168 single_inst_bclr_b(MFP->mf_imra, IA_ISA2);
169 }
170
171 if ((sr & PSL_IPL) >= (iinfo_p->ipl & PSL_IPL)) {
172 /*
173 * We're running at a too high priority now.
174 */
175 add_sicallback((si_farg)iifun, (void*)slot, 0);
176 }
177 else {
178 s = splx(iinfo_p->ipl);
179 if (slot == 0) {
180 do {
181 MFP->mf_iprb = (u_int8_t)~IB_ISA1;
182 (void) (iinfo_p->ifunc)(iinfo_p->iarg);
183 } while (MFP->mf_iprb & IB_ISA1);
184 single_inst_bset_b(MFP->mf_imrb, IB_ISA1);
185 }
186 else {
187 do {
188 MFP->mf_ipra = (u_int8_t)~IA_ISA2;
189 (void) (iinfo_p->ifunc)(iinfo_p->iarg);
190 } while (MFP->mf_ipra & IA_ISA2);
191 single_inst_bset_b(MFP->mf_imra, IA_ISA2);
192 }
193 splx(s);
194 }
195 return 1;
196 }
197
198
199 /*
200 * XXXX
201 * XXXX Note that this function is not really working yet! The big problem is
202 * XXXX to only generate interrupts for the slot the card is in...
203 */
204 int
205 isa_intr_alloc(ic, mask, type, irq)
206 isa_chipset_tag_t ic;
207 int mask;
208 int type;
209 int *irq;
210 {
211 isa_intr_info_t *iinfo_p;
212 int slot, i;
213
214
215 /*
216 * The Hades only supports edge triggered interrupts!
217 */
218 if (type != IST_EDGE)
219 return 1;
220
221 #define MAXIRQ 10 /* XXX: Pure fiction */
222 for (i = 0; i < MAXIRQ; i++) {
223 if (mask & (1<<i)) {
224 slot = SLOTNR(i);
225 iinfo_p = &iinfo[slot];
226
227 if (iinfo_p->slot < 0) {
228 *irq = i;
229 printf("WARNING: isa_intr_alloc is not yet ready!\n"
230 " make sure the card is in slot %d!\n",
231 slot);
232 return 0;
233 }
234 }
235 }
236 return (1);
237 }
238
239 const struct evcnt *
240 isa_intr_evcnt(isa_chipset_tag_t ic, int irq)
241 {
242
243 /* XXX for now, no evcnt parent reported */
244 return NULL;
245 }
246
247 void *
248 isa_intr_establish(ic, irq, type, level, ih_fun, ih_arg)
249 isa_chipset_tag_t ic;
250 int irq, type, level;
251 int (*ih_fun) __P((void *));
252 void *ih_arg;
253 {
254 isa_intr_info_t *iinfo_p;
255 struct intrhand *ihand;
256 int slot;
257
258 /*
259 * The Hades only supports edge triggered interrupts!
260 */
261 if (type != IST_EDGE)
262 return NULL;
263
264 slot = SLOTNR(irq);
265 iinfo_p = &iinfo[slot];
266
267 if (iinfo_p->slot >= 0)
268 panic("isa_intr_establish: interrupt was already established\n");
269
270 ihand = intr_establish((slot == 0) ? 3 : 15, USER_VEC, 0,
271 (hw_ifun_t)iifun, (void *)slot);
272 if (ihand != NULL) {
273 iinfo_p->slot = slot;
274 iinfo_p->ipl = level;
275 iinfo_p->ifunc = ih_fun;
276 iinfo_p->iarg = ih_arg;
277 iinfo_p->ihand = ihand;
278
279 /*
280 * Enable (unmask) the interrupt
281 */
282 if (slot == 0) {
283 single_inst_bset_b(MFP->mf_imrb, IB_ISA1);
284 single_inst_bset_b(MFP->mf_ierb, IB_ISA1);
285 }
286 else {
287 single_inst_bset_b(MFP->mf_imra, IA_ISA2);
288 single_inst_bset_b(MFP->mf_iera, IA_ISA2);
289 }
290 return(iinfo_p);
291 }
292 return NULL;
293 }
294
295 void
296 isa_intr_disestablish(ic, handler)
297 isa_chipset_tag_t ic;
298 void *handler;
299 {
300 isa_intr_info_t *iinfo_p = (isa_intr_info_t *)handler;
301
302 if (iinfo_p->slot < 0)
303 panic("isa_intr_disestablish: interrupt was not established\n");
304
305 (void) intr_disestablish(iinfo_p->ihand);
306 iinfo_p->slot = -1;
307 }
308