xref: /netbsd/sys/arch/powerpc/powerpc/openfirm.c (revision bf9ec67e)
1 /*	$NetBSD: openfirm.c,v 1.11 2001/09/24 13:22:33 wiz Exp $	*/
2 
3 /*
4  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5  * Copyright (C) 1995, 1996 TooLs GmbH.
6  * 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 TooLs GmbH.
19  * 4. The name of TooLs GmbH 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 TOOLS GMBH ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 
36 #include <machine/psl.h>
37 #include <machine/stdarg.h>
38 
39 #include <dev/ofw/openfirm.h>
40 
41 char *OF_buf;
42 
43 void ofw_stack(void);
44 void ofbcopy(const void *, void *, size_t);
45 
46 int
47 OF_peer(phandle)
48 	int phandle;
49 {
50 	static struct {
51 		char *name;
52 		int nargs;
53 		int nreturns;
54 		int phandle;
55 		int sibling;
56 	} args = {
57 		"peer",
58 		1,
59 		1,
60 	};
61 
62 	ofw_stack();
63 	args.phandle = phandle;
64 	if (openfirmware(&args) == -1)
65 		return 0;
66 	return args.sibling;
67 }
68 
69 int
70 OF_child(phandle)
71 	int phandle;
72 {
73 	static struct {
74 		char *name;
75 		int nargs;
76 		int nreturns;
77 		int phandle;
78 		int child;
79 	} args = {
80 		"child",
81 		1,
82 		1,
83 	};
84 
85 	ofw_stack();
86 	args.phandle = phandle;
87 	if (openfirmware(&args) == -1)
88 		return 0;
89 	return args.child;
90 }
91 
92 int
93 OF_parent(phandle)
94 	int phandle;
95 {
96 	static struct {
97 		char *name;
98 		int nargs;
99 		int nreturns;
100 		int phandle;
101 		int parent;
102 	} args = {
103 		"parent",
104 		1,
105 		1,
106 	};
107 
108 	ofw_stack();
109 	args.phandle = phandle;
110 	if (openfirmware(&args) == -1)
111 		return 0;
112 	return args.parent;
113 }
114 
115 int
116 OF_instance_to_package(ihandle)
117 	int ihandle;
118 {
119 	static struct {
120 		char *name;
121 		int nargs;
122 		int nreturns;
123 		int ihandle;
124 		int phandle;
125 	} args = {
126 		"instance-to-package",
127 		1,
128 		1,
129 	};
130 
131 	ofw_stack();
132 	args.ihandle = ihandle;
133 	if (openfirmware(&args) == -1)
134 		return -1;
135 	return args.phandle;
136 }
137 
138 int
139 OF_getproplen(handle, prop)
140 	int handle;
141 	char *prop;
142 {
143 	static struct {
144 		char *name;
145 		int nargs;
146 		int nreturns;
147 		int phandle;
148 		char *prop;
149 		int proplen;
150 	} args = {
151 		"getproplen",
152 		2,
153 		1,
154 	};
155 
156 	ofw_stack();
157 	args.phandle = handle;
158 	args.prop = prop;
159 	if (openfirmware(&args) == -1)
160 		return -1;
161 	return args.proplen;
162 }
163 
164 int
165 OF_getprop(handle, prop, buf, buflen)
166 	int handle;
167 	char *prop;
168 	void *buf;
169 	int buflen;
170 {
171 	static struct {
172 		char *name;
173 		int nargs;
174 		int nreturns;
175 		int phandle;
176 		char *prop;
177 		void *buf;
178 		int buflen;
179 		int size;
180 	} args = {
181 		"getprop",
182 		4,
183 		1,
184 	};
185 
186 	ofw_stack();
187 	if (buflen > NBPG)
188 		return -1;
189 	args.phandle = handle;
190 	args.prop = prop;
191 	args.buf = OF_buf;
192 	args.buflen = buflen;
193 	if (openfirmware(&args) == -1)
194 		return -1;
195 	if (args.size > buflen)
196 		args.size = buflen;
197 	if (args.size > 0)
198 		ofbcopy(OF_buf, buf, args.size);
199 	return args.size;
200 }
201 
202 int
203 OF_nextprop(handle, prop, nextprop)
204 	int handle;
205 	char *prop;
206 	void *nextprop;
207 {
208 	static struct {
209 		char *name;
210 		int nargs;
211 		int nreturns;
212 		int phandle;
213 		char *prop;
214 		char *buf;
215 		int flag;
216 	} args = {
217 		"nextprop",
218 		3,
219 		1,
220 	};
221 
222 	ofw_stack();
223 	args.phandle = handle;
224 	args.prop = prop;
225 	args.buf = OF_buf;
226 	if (openfirmware(&args) == -1)
227 		return -1;
228 	strncpy(nextprop, OF_buf, 32);
229 	return args.flag;
230 }
231 
232 int
233 OF_finddevice(name)
234 	char *name;
235 {
236 	static struct {
237 		char *name;
238 		int nargs;
239 		int nreturns;
240 		char *device;
241 		int phandle;
242 	} args = {
243 		"finddevice",
244 		1,
245 		1,
246 	};
247 
248 	ofw_stack();
249 	args.device = name;
250 	if (openfirmware(&args) == -1)
251 		return -1;
252 	return args.phandle;
253 }
254 
255 int
256 OF_instance_to_path(ihandle, buf, buflen)
257 	int ihandle;
258 	char *buf;
259 	int buflen;
260 {
261 	static struct {
262 		char *name;
263 		int nargs;
264 		int nreturns;
265 		int ihandle;
266 		char *buf;
267 		int buflen;
268 		int length;
269 	} args = {
270 		"instance-to-path",
271 		3,
272 		1,
273 	};
274 
275 	if (buflen > NBPG)
276 		return -1;
277 	args.ihandle = ihandle;
278 	args.buf = OF_buf;
279 	args.buflen = buflen;
280 	if (openfirmware(&args) < 0)
281 		return -1;
282 	if (args.length > buflen)
283 		args.length = buflen;
284 	if (args.length > 0)
285 		ofbcopy(OF_buf, buf, args.length);
286 	return args.length;
287 }
288 
289 int
290 OF_package_to_path(phandle, buf, buflen)
291 	int phandle;
292 	char *buf;
293 	int buflen;
294 {
295 	static struct {
296 		char *name;
297 		int nargs;
298 		int nreturns;
299 		int phandle;
300 		char *buf;
301 		int buflen;
302 		int length;
303 	} args = {
304 		"package-to-path",
305 		3,
306 		1,
307 	};
308 
309 	ofw_stack();
310 	if (buflen > NBPG)
311 		return -1;
312 	args.phandle = phandle;
313 	args.buf = OF_buf;
314 	args.buflen = buflen;
315 	if (openfirmware(&args) < 0)
316 		return -1;
317 	if (args.length > buflen)
318 		args.length = buflen;
319 	if (args.length > 0)
320 		ofbcopy(OF_buf, buf, args.length);
321 	return args.length;
322 }
323 
324 int
325 #ifdef	__STDC__
326 OF_call_method(char *method, int ihandle, int nargs, int nreturns, ...)
327 #else
328 OF_call_method(method, ihandle, nargs, nreturns, va_alist)
329 	char *method;
330 	int ihandle;
331 	int nargs;
332 	int nreturns;
333 	va_dcl
334 #endif
335 {
336 	va_list ap;
337 	static struct {
338 		char *name;
339 		int nargs;
340 		int nreturns;
341 		char *method;
342 		int ihandle;
343 		int args_n_results[12];
344 	} args = {
345 		"call-method",
346 		2,
347 		1,
348 	};
349 	int *ip, n;
350 
351 	if (nargs > 6)
352 		return -1;
353 	args.nargs = nargs + 2;
354 	args.nreturns = nreturns + 1;
355 	args.method = method;
356 	args.ihandle = ihandle;
357 	va_start(ap, nreturns);
358 	for (ip = args.args_n_results + (n = nargs); --n >= 0;)
359 		*--ip = va_arg(ap, int);
360 	ofw_stack();
361 	if (openfirmware(&args) == -1) {
362 		va_end(ap);
363 		return -1;
364 	}
365 	if (args.args_n_results[nargs]) {
366 		va_end(ap);
367 		return args.args_n_results[nargs];
368 	}
369 	for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
370 		*va_arg(ap, int *) = *--ip;
371 	va_end(ap);
372 	return 0;
373 }
374 
375 int
376 #ifdef	__STDC__
377 OF_call_method_1(char *method, int ihandle, int nargs, ...)
378 #else
379 OF_call_method_1(method, ihandle, nargs, va_alist)
380 	char *method;
381 	int ihandle;
382 	int nargs;
383 	va_dcl
384 #endif
385 {
386 	va_list ap;
387 	static struct {
388 		char *name;
389 		int nargs;
390 		int nreturns;
391 		char *method;
392 		int ihandle;
393 		int args_n_results[8];
394 	} args = {
395 		"call-method",
396 		2,
397 		2,
398 	};
399 	int *ip, n;
400 
401 	if (nargs > 6)
402 		return -1;
403 	args.nargs = nargs + 2;
404 	args.method = method;
405 	args.ihandle = ihandle;
406 	va_start(ap, nargs);
407 	for (ip = args.args_n_results + (n = nargs); --n >= 0;)
408 		*--ip = va_arg(ap, int);
409 	va_end(ap);
410 	ofw_stack();
411 	if (openfirmware(&args) == -1)
412 		return -1;
413 	if (args.args_n_results[nargs])
414 		return -1;
415 	return args.args_n_results[nargs + 1];
416 }
417 
418 int
419 OF_open(dname)
420 	char *dname;
421 {
422 	static struct {
423 		char *name;
424 		int nargs;
425 		int nreturns;
426 		char *dname;
427 		int handle;
428 	} args = {
429 		"open",
430 		1,
431 		1,
432 	};
433 	int l;
434 
435 	ofw_stack();
436 	if ((l = strlen(dname)) >= NBPG)
437 		return -1;
438 	ofbcopy(dname, OF_buf, l + 1);
439 	args.dname = OF_buf;
440 	if (openfirmware(&args) == -1)
441 		return -1;
442 	return args.handle;
443 }
444 
445 void
446 OF_close(handle)
447 	int handle;
448 {
449 	static struct {
450 		char *name;
451 		int nargs;
452 		int nreturns;
453 		int handle;
454 	} args = {
455 		"close",
456 		1,
457 		0,
458 	};
459 
460 	ofw_stack();
461 	args.handle = handle;
462 	openfirmware(&args);
463 }
464 
465 /*
466  * This assumes that character devices don't read in multiples of NBPG.
467  */
468 int
469 OF_read(handle, addr, len)
470 	int handle;
471 	void *addr;
472 	int len;
473 {
474 	static struct {
475 		char *name;
476 		int nargs;
477 		int nreturns;
478 		int ihandle;
479 		void *addr;
480 		int len;
481 		int actual;
482 	} args = {
483 		"read",
484 		3,
485 		1,
486 	};
487 	int l, act = 0;
488 	char *p = addr;
489 
490 	ofw_stack();
491 	args.ihandle = handle;
492 	args.addr = OF_buf;
493 	for (; len > 0; len -= l, p += l) {
494 		l = min(NBPG, len);
495 		args.len = l;
496 		if (openfirmware(&args) == -1)
497 			return -1;
498 		if (args.actual > 0) {
499 			ofbcopy(OF_buf, p, args.actual);
500 			act += args.actual;
501 		}
502 		if (args.actual < l) {
503 			if (act)
504 				return act;
505 			else
506 				return args.actual;
507 		}
508 	}
509 	return act;
510 }
511 
512 int
513 OF_write(handle, addr, len)
514 	int handle;
515 	void *addr;
516 	int len;
517 {
518 	static struct {
519 		char *name;
520 		int nargs;
521 		int nreturns;
522 		int ihandle;
523 		void *addr;
524 		int len;
525 		int actual;
526 	} args = {
527 		"write",
528 		3,
529 		1,
530 	};
531 	int l, act = 0;
532 	char *p = addr;
533 
534 	ofw_stack();
535 	args.ihandle = handle;
536 	args.addr = OF_buf;
537 	for (; len > 0; len -= l, p += l) {
538 		l = min(NBPG, len);
539 		ofbcopy(p, OF_buf, l);
540 		args.len = l;
541 		if (openfirmware(&args) == -1)
542 			return -1;
543 		l = args.actual;
544 		act += l;
545 	}
546 	return act;
547 }
548 
549 int
550 OF_seek(handle, pos)
551 	int handle;
552 	u_quad_t pos;
553 {
554 	static struct {
555 		char *name;
556 		int nargs;
557 		int nreturns;
558 		int handle;
559 		int poshi;
560 		int poslo;
561 		int status;
562 	} args = {
563 		"seek",
564 		3,
565 		1,
566 	};
567 
568 	ofw_stack();
569 	args.handle = handle;
570 	args.poshi = (int)(pos >> 32);
571 	args.poslo = (int)pos;
572 	if (openfirmware(&args) == -1)
573 		return -1;
574 	return args.status;
575 }
576 
577 void
578 OF_boot(bootspec)
579 	char *bootspec;
580 {
581 	static struct {
582 		char *name;
583 		int nargs;
584 		int nreturns;
585 		char *bootspec;
586 	} args = {
587 		"boot",
588 		1,
589 		0,
590 	};
591 	int l;
592 
593 	if ((l = strlen(bootspec)) >= NBPG)
594 		panic("OF_boot");
595 	ofw_stack();
596 	ofbcopy(bootspec, OF_buf, l + 1);
597 	args.bootspec = OF_buf;
598 	openfirmware(&args);
599 	while (1);			/* just in case */
600 }
601 
602 void
603 OF_enter()
604 {
605 	static struct {
606 		char *name;
607 		int nargs;
608 		int nreturns;
609 	} args = {
610 		"enter",
611 		0,
612 		0,
613 	};
614 
615 	ofw_stack();
616 	openfirmware(&args);
617 }
618 
619 void
620 OF_exit()
621 {
622 	static struct {
623 		char *name;
624 		int nargs;
625 		int nreturns;
626 	} args = {
627 		"exit",
628 		0,
629 		0,
630 	};
631 
632 	ofw_stack();
633 	openfirmware(&args);
634 	while (1);			/* just in case */
635 }
636 
637 void
638 (*OF_set_callback (void (*newfunc)(void *))) (void *)
639 {
640 	static struct {
641 		char *name;
642 		int nargs;
643 		int nreturns;
644 		void (*newfunc)(void *);
645 		void (*oldfunc)(void *);
646 	} args = {
647 		"set-callback",
648 		1,
649 		1,
650 	};
651 
652 	ofw_stack();
653 	args.newfunc = newfunc;
654 	if (openfirmware(&args) == -1)
655 		return 0;
656 	return args.oldfunc;
657 }
658 
659 /*
660  * This version of bcopy doesn't work for overlapping regions!
661  */
662 void
663 ofbcopy(src, dst, len)
664 	const void *src;
665 	void *dst;
666 	size_t len;
667 {
668 	const char *sp = src;
669 	char *dp = dst;
670 
671 	if (src == dst)
672 		return;
673 
674 	/*
675 	 * Do some optimization?						XXX
676 	 */
677 	while (len-- > 0)
678 		*dp++ = *sp++;
679 }
680