xref: /netbsd/sys/dev/ofisa/ofisa.c (revision c4a72b64)
1 /*	$NetBSD: ofisa.c,v 1.12 2002/10/02 16:34:30 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.12 2002/10/02 16:34:30 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 		printf("%s at %s", name, pnp);
75 	else
76 		printf(" (%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 }
413