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