ofisa.c revision 1.6 1 /* $NetBSD: ofisa.c,v 1.6 1998/06/30 00:09:36 thorpej Exp $ */
2
3 /*
4 * Copyright 1997, 1998
5 * Digital Equipment Corporation. All rights reserved.
6 *
7 * This software is furnished under license and may be used and
8 * copied only in accordance with the following terms and conditions.
9 * Subject to these conditions, you may download, copy, install,
10 * use, modify and distribute this software in source and/or binary
11 * form. No title or ownership is transferred hereby.
12 *
13 * 1) Any source code used, modified or distributed must reproduce
14 * and retain this copyright notice and list of conditions as
15 * they appear in the source file.
16 *
17 * 2) No right is granted to use any trade name, trademark, or logo of
18 * Digital Equipment Corporation. Neither the "Digital Equipment
19 * Corporation" name nor any trademark or logo of Digital Equipment
20 * Corporation may be used to endorse or promote products derived
21 * from this software without the prior written permission of
22 * Digital Equipment Corporation.
23 *
24 * 3) This software is provided "AS-IS" and any express or implied
25 * warranties, including but not limited to, any implied warranties
26 * of merchantability, fitness for a particular purpose, or
27 * non-infringement are disclaimed. In no event shall DIGITAL be
28 * liable for any damages whatsoever, and in particular, DIGITAL
29 * shall not be liable for special, indirect, consequential, or
30 * incidental damages or damages for lost profits, loss of
31 * revenue or loss of use, whether such damages arise in contract,
32 * negligence, tort, under statute, in equity, at law or otherwise,
33 * even if advised of the possibility of such damage.
34 */
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/malloc.h>
40 #include <machine/bus.h>
41 #include <machine/intr.h>
42
43 #include <dev/ofw/openfirm.h>
44 #include <dev/isa/isavar.h>
45 #include <dev/ofisa/ofisavar.h>
46
47 #include "isadma.h"
48
49 #define OFW_MAX_STACK_BUF_SIZE 256
50
51 static int ofisamatch __P((struct device *, struct cfdata *, void *));
52 static void ofisaattach __P((struct device *, struct device *, void *));
53
54 struct cfattach ofisa_ca = {
55 sizeof(struct device), ofisamatch, ofisaattach
56 };
57
58 extern struct cfdriver ofisa_cd;
59
60 static int ofisaprint __P((void *, const char *));
61
62 static int
63 ofisaprint(aux, pnp)
64 void *aux;
65 const char *pnp;
66 {
67 struct ofbus_attach_args *oba = aux;
68 char name[64];
69
70 (void)of_packagename(oba->oba_phandle, name, sizeof name);
71 if (pnp)
72 printf("%s at %s", name, pnp);
73 else
74 printf(" (%s)", name);
75 return UNCONF;
76 }
77
78 int
79 ofisamatch(parent, cf, aux)
80 struct device *parent;
81 struct cfdata *cf;
82 void *aux;
83 {
84 struct ofbus_attach_args *oba = aux;
85 const char *compatible_strings[] = { "pnpPNP,a00", NULL };
86 int rv = 0;
87
88 if (of_compatible(oba->oba_phandle, compatible_strings) != -1)
89 rv = 5;
90
91 #ifdef _OFISA_MD_MATCH
92 if (!rv)
93 rv = ofisa_md_match(parent, cf, aux);
94 #endif
95
96 return (rv);
97 }
98
99 void
100 ofisaattach(parent, self, aux)
101 struct device *parent, *self;
102 void *aux;
103 {
104 struct ofbus_attach_args *oba = aux;
105 struct isabus_attach_args iba;
106 struct ofisa_attach_args aa;
107 int child;
108
109 if (ofisa_get_isabus_data(oba->oba_phandle, &iba) < 0) {
110 printf(": couldn't get essential bus data\n");
111 return;
112 }
113
114 printf("\n");
115
116 #if NISADMA > 0
117 /*
118 * Initialize our DMA state.
119 */
120 isa_dmainit(iba.iba_ic, iba.iba_iot, iba.iba_dmat, self);
121 #endif
122
123 for (child = OF_child(oba->oba_phandle); child;
124 child = OF_peer(child)) {
125 if (ofisa_ignore_child(oba->oba_phandle, child))
126 continue;
127
128 bzero(&aa, sizeof aa);
129
130 aa.oba.oba_busname = "ofw"; /* XXX */
131 aa.oba.oba_phandle = child;
132 aa.iot = iba.iba_iot;
133 aa.memt = iba.iba_memt;
134 aa.dmat = iba.iba_dmat;
135 aa.ic = iba.iba_ic;
136
137 config_found(self, &aa, ofisaprint);
138 }
139 }
140
141 int
142 ofisa_reg_count(phandle)
143 int phandle;
144 {
145 int len;
146
147 len = OF_getproplen(phandle, "reg");
148
149 /* nonexistant or obviously malformed "reg" property */
150 if (len < 0 || (len % 12) != 0)
151 return (-1);
152 return (len / 12);
153 }
154
155 int
156 ofisa_reg_get(phandle, descp, ndescs)
157 int phandle;
158 struct ofisa_reg_desc *descp;
159 int ndescs;
160 {
161 char *buf, *bp;
162 int i, proplen, allocated, rv;
163
164 i = ofisa_reg_count(phandle);
165 if (i < 0)
166 return (-1);
167 proplen = i * 12;
168 ndescs = min(ndescs, i);
169
170 i = ndescs * 12;
171 if (i > OFW_MAX_STACK_BUF_SIZE) {
172 buf = malloc(i, M_TEMP, M_WAITOK);
173 allocated = 1;
174 } else {
175 buf = alloca(i);
176 allocated = 0;
177 }
178
179 if (OF_getprop(phandle, "reg", buf, i) != proplen) {
180 rv = -1;
181 goto out;
182 }
183
184 for (i = 0, bp = buf; i < ndescs; i++, bp += 12) {
185 if (of_decode_int(&bp[0]) & 1)
186 descp[i].type = OFISA_REG_TYPE_IO;
187 else
188 descp[i].type = OFISA_REG_TYPE_MEM;
189 descp[i].addr = of_decode_int(&bp[4]);
190 descp[i].len = of_decode_int(&bp[8]);
191 }
192 rv = i; /* number of descriptors processed (== ndescs) */
193
194 out:
195 if (allocated)
196 free(buf, M_TEMP);
197 return (rv);
198 }
199
200 void
201 ofisa_reg_print(descp, ndescs)
202 struct ofisa_reg_desc *descp;
203 int ndescs;
204 {
205 int i;
206
207 if (ndescs == 0) {
208 printf("none");
209 return;
210 }
211
212 for (i = 0; i < ndescs; i++) {
213 printf("%s%s 0x%lx/%ld", i ? ", " : "",
214 descp[i].type == OFISA_REG_TYPE_IO ? "io" : "mem",
215 (long)descp[i].addr, (long)descp[i].len);
216 }
217 }
218
219 int
220 ofisa_intr_count(phandle)
221 int phandle;
222 {
223 int len;
224
225 len = OF_getproplen(phandle, "interrupts");
226
227 /* nonexistant or obviously malformed "reg" property */
228 if (len < 0 || (len % 8) != 0)
229 return (-1);
230 return (len / 8);
231 }
232
233 int
234 ofisa_intr_get(phandle, descp, ndescs)
235 int phandle;
236 struct ofisa_intr_desc *descp;
237 int ndescs;
238 {
239 char *buf, *bp;
240 int i, proplen, allocated, rv;
241
242 i = ofisa_intr_count(phandle);
243 if (i < 0)
244 return (-1);
245 proplen = i * 8;
246 ndescs = min(ndescs, i);
247
248 i = ndescs * 8;
249 if (i > OFW_MAX_STACK_BUF_SIZE) {
250 buf = malloc(i, M_TEMP, M_WAITOK);
251 allocated = 1;
252 } else {
253 buf = alloca(i);
254 allocated = 0;
255 }
256
257 if (OF_getprop(phandle, "interrupts", buf, i) != proplen) {
258 rv = -1;
259 goto out;
260 }
261
262 for (i = 0, bp = buf; i < ndescs; i++, bp += 8) {
263 descp[i].irq = of_decode_int(&bp[0]);
264 switch (of_decode_int(&bp[4])) {
265 case 0:
266 case 1:
267 descp[i].share = IST_LEVEL;
268 break;
269 case 2:
270 case 3:
271 descp[i].share = IST_EDGE;
272 break;
273 #ifdef DIAGNOSTIC
274 default:
275 /* Dunno what to do, so fail. */
276 printf("ofisa_intr_get: unknown intrerrupt type %d\n",
277 of_decode_int(&bp[4]));
278 rv = -1;
279 goto out;
280 #endif
281 }
282 }
283 rv = i; /* number of descriptors processed (== ndescs) */
284
285 out:
286 if (allocated)
287 free(buf, M_TEMP);
288 return (rv);
289 }
290
291 void
292 ofisa_intr_print(descp, ndescs)
293 struct ofisa_intr_desc *descp;
294 int ndescs;
295 {
296 int i;
297
298 if (ndescs == 0) {
299 printf("none");
300 return;
301 }
302
303 for (i = 0; i < ndescs; i++) {
304 printf("%s%d (%s)", i ? ", " : "", descp[i].irq,
305 descp[i].share == IST_LEVEL ? "level" : "edge");
306 }
307 }
308
309 int
310 ofisa_dma_count(phandle)
311 int phandle;
312 {
313 int len;
314
315 len = OF_getproplen(phandle, "dma");
316
317 /* nonexistant or obviously malformed "reg" property */
318 if (len < 0 || (len % 20) != 0)
319 return (-1);
320 return (len / 20);
321 }
322
323 int
324 ofisa_dma_get(phandle, descp, ndescs)
325 int phandle;
326 struct ofisa_dma_desc *descp;
327 int ndescs;
328 {
329 char *buf, *bp;
330 int i, proplen, allocated, rv;
331
332 i = ofisa_dma_count(phandle);
333 if (i < 0)
334 return (-1);
335 proplen = i * 20;
336 ndescs = min(ndescs, i);
337
338 i = ndescs * 20;
339 if (i > OFW_MAX_STACK_BUF_SIZE) {
340 buf = malloc(i, M_TEMP, M_WAITOK);
341 allocated = 1;
342 } else {
343 buf = alloca(i);
344 allocated = 0;
345 }
346
347 if (OF_getprop(phandle, "dma", buf, i) != proplen) {
348 rv = -1;
349 goto out;
350 }
351
352 for (i = 0, bp = buf; i < ndescs; i++, bp += 20) {
353 descp[i].drq = of_decode_int(&bp[0]);
354 descp[i].mode = of_decode_int(&bp[4]);
355 descp[i].width = of_decode_int(&bp[8]);
356 descp[i].countwidth = of_decode_int(&bp[12]);
357 descp[i].busmaster = of_decode_int(&bp[16]);
358 }
359 rv = i; /* number of descriptors processed (== ndescs) */
360
361 out:
362 if (allocated)
363 free(buf, M_TEMP);
364 return (rv);
365 }
366
367 void
368 ofisa_dma_print(descp, ndescs)
369 struct ofisa_dma_desc *descp;
370 int ndescs;
371 {
372 char unkmode[16];
373 const char *modestr;
374 int i;
375
376 if (ndescs == 0) {
377 printf("none");
378 return;
379 }
380
381 for (i = 0; i < ndescs; i++) {
382 switch (descp[i].mode) {
383 case OFISA_DMA_MODE_COMPAT:
384 modestr = "compat";
385 break;
386 case OFISA_DMA_MODE_A:
387 modestr = "A";
388 break;
389 case OFISA_DMA_MODE_B:
390 modestr = "B";
391 break;
392 case OFISA_DMA_MODE_F:
393 modestr = "F";
394 break;
395 case OFISA_DMA_MODE_C:
396 modestr = "C";
397 break;
398 default:
399 sprintf(unkmode, "??? (%d)", descp[i].mode);
400 modestr = unkmode;
401 break;
402 }
403
404 printf("%s%d %s mode %d-bit (%d-bit count)%s", i ? ", " : "",
405 descp[i].drq, modestr, descp[i].width,
406 descp[i].countwidth,
407 descp[i].busmaster ? " busmaster" : "");
408
409 }
410 }
411