FreeBSD/Linux Kernel Cross Reference
sys/dev/ofisa/ofisa.c
1 /* $NetBSD: ofisa.c,v 1.13 2003/01/01 00:10:22 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/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: ofisa.c,v 1.13 2003/01/01 00:10:22 thorpej Exp $");
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/device.h>
42 #include <sys/malloc.h>
43 #include <machine/bus.h>
44 #include <machine/intr.h>
45
46 #include <dev/ofw/openfirm.h>
47 #include <dev/isa/isavar.h>
48 #include <dev/ofisa/ofisavar.h>
49
50 #include "isadma.h"
51
52 #define OFW_MAX_STACK_BUF_SIZE 256
53
54 static int ofisamatch __P((struct device *, struct cfdata *, void *));
55 static void ofisaattach __P((struct device *, struct device *, void *));
56
57 CFATTACH_DECL(ofisa, sizeof(struct device),
58 ofisamatch, ofisaattach, NULL, NULL);
59
60 extern struct cfdriver ofisa_cd;
61
62 static int ofisaprint __P((void *, const char *));
63
64 static int
65 ofisaprint(aux, pnp)
66 void *aux;
67 const char *pnp;
68 {
69 struct ofbus_attach_args *oba = aux;
70 char name[64];
71
72 (void)of_packagename(oba->oba_phandle, name, sizeof name);
73 if (pnp)
74 aprint_normal("%s at %s", name, pnp);
75 else
76 aprint_normal(" (%s)", name);
77 return UNCONF;
78 }
79
80 int
81 ofisamatch(parent, cf, aux)
82 struct device *parent;
83 struct cfdata *cf;
84 void *aux;
85 {
86 struct ofbus_attach_args *oba = aux;
87 static const char *const compatible_strings[] = { "pnpPNP,a00", NULL };
88 int rv = 0;
89
90 if (of_compatible(oba->oba_phandle, compatible_strings) != -1)
91 rv = 5;
92
93 #ifdef _OFISA_MD_MATCH
94 if (!rv)
95 rv = ofisa_md_match(parent, cf, aux);
96 #endif
97
98 return (rv);
99 }
100
101 void
102 ofisaattach(parent, self, aux)
103 struct device *parent, *self;
104 void *aux;
105 {
106 struct ofbus_attach_args *oba = aux;
107 struct isabus_attach_args iba;
108 struct ofisa_attach_args aa;
109 int child;
110
111 if (ofisa_get_isabus_data(oba->oba_phandle, &iba) < 0) {
112 printf(": couldn't get essential bus data\n");
113 return;
114 }
115
116 printf("\n");
117
118 #if NISADMA > 0
119 /*
120 * Initialize our DMA state.
121 */
122 isa_dmainit(iba.iba_ic, iba.iba_iot, iba.iba_dmat, self);
123 #endif
124
125 for (child = OF_child(oba->oba_phandle); child;
126 child = OF_peer(child)) {
127 if (ofisa_ignore_child(oba->oba_phandle, child))
128 continue;
129
130 bzero(&aa, sizeof aa);
131
132 aa.oba.oba_busname = "ofw"; /* XXX */
133 aa.oba.oba_phandle = child;
134 aa.iot = iba.iba_iot;
135 aa.memt = iba.iba_memt;
136 aa.dmat = iba.iba_dmat;
137 aa.ic = iba.iba_ic;
138
139 config_found(self, &aa, ofisaprint);
140 }
141 }
142
143 int
144 ofisa_reg_count(phandle)
145 int phandle;
146 {
147 int len;
148
149 len = OF_getproplen(phandle, "reg");
150
151 /* nonexistent or obviously malformed "reg" property */
152 if (len < 0 || (len % 12) != 0)
153 return (-1);
154 return (len / 12);
155 }
156
157 int
158 ofisa_reg_get(phandle, descp, ndescs)
159 int phandle;
160 struct ofisa_reg_desc *descp;
161 int ndescs;
162 {
163 char *buf, *bp;
164 int i, proplen, allocated, rv;
165
166 i = ofisa_reg_count(phandle);
167 if (i < 0)
168 return (-1);
169 proplen = i * 12;
170 ndescs = min(ndescs, i);
171
172 i = ndescs * 12;
173 if (i > OFW_MAX_STACK_BUF_SIZE) {
174 buf = malloc(i, M_TEMP, M_WAITOK);
175 allocated = 1;
176 } else {
177 buf = alloca(i);
178 allocated = 0;
179 }
180
181 if (OF_getprop(phandle, "reg", buf, i) != proplen) {
182 rv = -1;
183 goto out;
184 }
185
186 for (i = 0, bp = buf; i < ndescs; i++, bp += 12) {
187 if (of_decode_int(&bp[0]) & 1)
188 descp[i].type = OFISA_REG_TYPE_IO;
189 else
190 descp[i].type = OFISA_REG_TYPE_MEM;
191 descp[i].addr = of_decode_int(&bp[4]);
192 descp[i].len = of_decode_int(&bp[8]);
193 }
194 rv = i; /* number of descriptors processed (== ndescs) */
195
196 out:
197 if (allocated)
198 free(buf, M_TEMP);
199 return (rv);
200 }
201
202 void
203 ofisa_reg_print(descp, ndescs)
204 struct ofisa_reg_desc *descp;
205 int ndescs;
206 {
207 int i;
208
209 if (ndescs == 0) {
210 printf("none");
211 return;
212 }
213
214 for (i = 0; i < ndescs; i++) {
215 printf("%s%s 0x%lx/%ld", i ? ", " : "",
216 descp[i].type == OFISA_REG_TYPE_IO ? "io" : "mem",
217 (long)descp[i].addr, (long)descp[i].len);
218 }
219 }
220
221 int
222 ofisa_intr_count(phandle)
223 int phandle;
224 {
225 int len;
226
227 len = OF_getproplen(phandle, "interrupts");
228
229 /* nonexistent or obviously malformed "reg" property */
230 if (len < 0 || (len % 8) != 0)
231 return (-1);
232 return (len / 8);
233 }
234
235 int
236 ofisa_intr_get(phandle, descp, ndescs)
237 int phandle;
238 struct ofisa_intr_desc *descp;
239 int ndescs;
240 {
241 char *buf, *bp;
242 int i, proplen, allocated, rv;
243
244 i = ofisa_intr_count(phandle);
245 if (i < 0)
246 return (-1);
247 proplen = i * 8;
248 ndescs = min(ndescs, i);
249
250 i = ndescs * 8;
251 if (i > OFW_MAX_STACK_BUF_SIZE) {
252 buf = malloc(i, M_TEMP, M_WAITOK);
253 allocated = 1;
254 } else {
255 buf = alloca(i);
256 allocated = 0;
257 }
258
259 if (OF_getprop(phandle, "interrupts", buf, i) != proplen) {
260 rv = -1;
261 goto out;
262 }
263
264 for (i = 0, bp = buf; i < ndescs; i++, bp += 8) {
265 descp[i].irq = of_decode_int(&bp[0]);
266 switch (of_decode_int(&bp[4])) {
267 case 0:
268 case 1:
269 descp[i].share = IST_LEVEL;
270 break;
271 case 2:
272 case 3:
273 descp[i].share = IST_EDGE;
274 break;
275 #ifdef DIAGNOSTIC
276 default:
277 /* Dunno what to do, so fail. */
278 printf("ofisa_intr_get: unknown intrerrupt type %d\n",
279 of_decode_int(&bp[4]));
280 rv = -1;
281 goto out;
282 #endif
283 }
284 }
285 rv = i; /* number of descriptors processed (== ndescs) */
286
287 out:
288 if (allocated)
289 free(buf, M_TEMP);
290 return (rv);
291 }
292
293 void
294 ofisa_intr_print(descp, ndescs)
295 struct ofisa_intr_desc *descp;
296 int ndescs;
297 {
298 int i;
299
300 if (ndescs == 0) {
301 printf("none");
302 return;
303 }
304
305 for (i = 0; i < ndescs; i++) {
306 printf("%s%d (%s)", i ? ", " : "", descp[i].irq,
307 descp[i].share == IST_LEVEL ? "level" : "edge");
308 }
309 }
310
311 int
312 ofisa_dma_count(phandle)
313 int phandle;
314 {
315 int len;
316
317 len = OF_getproplen(phandle, "dma");
318
319 /* nonexistent or obviously malformed "reg" property */
320 if (len < 0 || (len % 20) != 0)
321 return (-1);
322 return (len / 20);
323 }
324
325 int
326 ofisa_dma_get(phandle, descp, ndescs)
327 int phandle;
328 struct ofisa_dma_desc *descp;
329 int ndescs;
330 {
331 char *buf, *bp;
332 int i, proplen, allocated, rv;
333
334 i = ofisa_dma_count(phandle);
335 if (i < 0)
336 return (-1);
337 proplen = i * 20;
338 ndescs = min(ndescs, i);
339
340 i = ndescs * 20;
341 if (i > OFW_MAX_STACK_BUF_SIZE) {
342 buf = malloc(i, M_TEMP, M_WAITOK);
343 allocated = 1;
344 } else {
345 buf = alloca(i);
346 allocated = 0;
347 }
348
349 if (OF_getprop(phandle, "dma", buf, i) != proplen) {
350 rv = -1;
351 goto out;
352 }
353
354 for (i = 0, bp = buf; i < ndescs; i++, bp += 20) {
355 descp[i].drq = of_decode_int(&bp[0]);
356 descp[i].mode = of_decode_int(&bp[4]);
357 descp[i].width = of_decode_int(&bp[8]);
358 descp[i].countwidth = of_decode_int(&bp[12]);
359 descp[i].busmaster = of_decode_int(&bp[16]);
360 }
361 rv = i; /* number of descriptors processed (== ndescs) */
362
363 out:
364 if (allocated)
365 free(buf, M_TEMP);
366 return (rv);
367 }
368
369 void
370 ofisa_dma_print(descp, ndescs)
371 struct ofisa_dma_desc *descp;
372 int ndescs;
373 {
374 char unkmode[16];
375 const char *modestr;
376 int i;
377
378 if (ndescs == 0) {
379 printf("none");
380 return;
381 }
382
383 for (i = 0; i < ndescs; i++) {
384 switch (descp[i].mode) {
385 case OFISA_DMA_MODE_COMPAT:
386 modestr = "compat";
387 break;
388 case OFISA_DMA_MODE_A:
389 modestr = "A";
390 break;
391 case OFISA_DMA_MODE_B:
392 modestr = "B";
393 break;
394 case OFISA_DMA_MODE_F:
395 modestr = "F";
396 break;
397 case OFISA_DMA_MODE_C:
398 modestr = "C";
399 break;
400 default:
401 sprintf(unkmode, "??? (%d)", descp[i].mode);
402 modestr = unkmode;
403 break;
404 }
405
406 printf("%s%d %s mode %d-bit (%d-bit count)%s", i ? ", " : "",
407 descp[i].drq, modestr, descp[i].width,
408 descp[i].countwidth,
409 descp[i].busmaster ? " busmaster" : "");
410
411 }
412 }
Cache object: eab996399849fe657fea2d2160502427
|