xref: /freebsd/sys/dev/ofw/openfirm.c (revision 817420dc8eac7df799c78f5309b75092b7f7cd40)
1 /*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai 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 /*
34  * Copyright (C) 2000 Benno Rice.
35  * All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  *
46  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
47  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
52  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
54  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
55  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56  *
57  * $FreeBSD$
58  */
59 
60 #include <machine/stdarg.h>
61 
62 #include <stand.h>
63 
64 #include "openfirm.h"
65 
66 static int (*openfirmware)(void *);
67 static ihandle_t stdin;
68 static ihandle_t stdout;
69 
70 /* Initialiaser */
71 
72 void
73 OF_init(int (*openfirm)(void *))
74 {
75 	openfirmware = openfirm;
76 }
77 
78 /*
79  * Generic functions
80  */
81 
82 /* Test to see if a service exists. */
83 int
84 OF_test(char *name)
85 {
86 	static struct {
87 		char	*name;
88 		int	nargs;
89 		int	nreturns;
90 		char	*service;
91 		int	missing;
92 	} args = {
93 		"test",
94 		1,
95 		1,
96 	};
97 
98 	args.service = name;
99 	if (openfirmware(&args) == -1)
100 		return -1;
101 	return args.missing;
102 }
103 
104 /* Return firmware millisecond count. */
105 int
106 OF_milliseconds()
107 {
108 	static struct {
109 		char	*name;
110 		int	nargs;
111 		int	nreturns;
112 		int	ms;
113 	} args = {
114 		"milliseconds",
115 		0,
116 		1,
117 	};
118 
119 	openfirmware(&args);
120 	return args.ms;
121 }
122 
123 /*
124  * Device tree functions
125  */
126 
127 /* Return the next sibling of this node or 0. */
128 phandle_t
129 OF_peer(phandle_t node)
130 {
131 	static struct {
132 		char		*name;
133 		int		nargs;
134 		int		nreturns;
135 		phandle_t	node;
136 		phandle_t	next;
137 	} args = {
138 		"peer",
139 		1,
140 		1,
141 	};
142 
143 	args.node = node;
144 	if (openfirmware(&args) == -1)
145 		return -1;
146 	return args.next;
147 }
148 
149 /* Return the first child of this node or 0. */
150 phandle_t
151 OF_child(phandle_t node)
152 {
153 	static struct {
154 		char		*name;
155 		int		nargs;
156 		int		nreturns;
157 		phandle_t	node;
158 		phandle_t	child;
159 	} args = {
160 		"child",
161 		1,
162 		1,
163 	};
164 
165 	args.node = node;
166 	if (openfirmware(&args) == -1)
167 		return -1;
168 	return args.child;
169 }
170 
171 /* Return the parent of this node or 0. */
172 phandle_t
173 OF_parent(phandle_t node)
174 {
175 	static struct {
176 		char		*name;
177 		int		nargs;
178 		int		nreturns;
179 		phandle_t	node;
180 		phandle_t	parent;
181 	} args = {
182 		"parent",
183 		1,
184 		1,
185 	};
186 
187 	args.node = node;
188 	if (openfirmware(&args) == -1)
189 		return -1;
190 	return args.parent;
191 }
192 
193 /* Return the package handle that corresponds to an instance handle. */
194 phandle_t
195 OF_instance_to_package(ihandle_t instance)
196 {
197 	static struct {
198 		char		*name;
199 		int		nargs;
200 		int		nreturns;
201 		ihandle_t	instance;
202 		phandle_t	package;
203 	} args = {
204 		"instance-to-package",
205 		1,
206 		1,
207 	};
208 
209 	args.instance = instance;
210 	if (openfirmware(&args) == -1)
211 		return -1;
212 	return args.package;
213 }
214 
215 /* Get the length of a property of a package. */
216 int
217 OF_getproplen(phandle_t package, char *propname)
218 {
219 	static struct {
220 		char		*name;
221 		int		nargs;
222 		int		nreturns;
223 		phandle_t	package;
224 		char 		*propname;
225 		int		proplen;
226 	} args = {
227 		"getproplen",
228 		2,
229 		1,
230 	};
231 
232 	args.package = package;
233 	args.propname = propname;
234 	if (openfirmware(&args) == -1)
235 		return -1;
236 	return args.proplen;
237 }
238 
239 /* Get the value of a property of a package. */
240 int
241 OF_getprop(phandle_t package, char *propname, void *buf, int buflen)
242 {
243 	static struct {
244 		char		*name;
245 		int		nargs;
246 		int		nreturns;
247 		phandle_t	package;
248 		char		*propname;
249 		void		*buf;
250 		int		buflen;
251 		int		size;
252 	} args = {
253 		"getprop",
254 		4,
255 		1,
256 	};
257 
258 	args.package = package;
259 	args.propname = propname;
260 	args.buf = buf;
261 	args.buflen = buflen;
262 	if (openfirmware(&args) == -1)
263 		return -1;
264 	return args.size;
265 }
266 
267 /* Get the next property of a package. */
268 int
269 OF_nextprop(phandle_t package, char *previous, char *buf)
270 {
271 	static struct {
272 		char		*name;
273 		int		nargs;
274 		int		nreturns;
275 		phandle_t	package;
276 		char 		*previous;
277 		char		*buf;
278 		int		flag;
279 	} args = {
280 		"nextprop",
281 		3,
282 		1,
283 	};
284 
285 	args.package = package;
286 	args.previous = previous;
287 	args.buf = buf;
288 	if (openfirmware(&args) == -1)
289 		return -1;
290 	return args.flag;
291 }
292 
293 /* Set the value of a property of a package. */
294 /* XXX Has a bug on FirePower */
295 int
296 OF_setprop(phandle_t package, char *propname, void *buf, int len)
297 {
298 	static struct {
299 		char		*name;
300 		int		nargs;
301 		int		nreturns;
302 		phandle_t	package;
303 		char		*propname;
304 		void		*buf;
305 		int		len;
306 		int		size;
307 	} args = {
308 		"setprop",
309 		4,
310 		1,
311 	};
312 
313 	args.package = package;
314 	args.propname = propname;
315 	args.buf = buf;
316 	args.len = len;
317 	if (openfirmware(&args) == -1)
318 		return -1;
319 	return args.size;
320 }
321 
322 /* Convert a device specifier to a fully qualified pathname. */
323 int
324 OF_canon(const char *device, char *buf, int len)
325 {
326 	static struct {
327 		char	*name;
328 		int	nargs;
329 		int	nreturns;
330 		char	*device;
331 		char	*buf;
332 		int	len;
333 		int	size;
334 	} args = {
335 		"canon",
336 		3,
337 		1,
338 	};
339 
340 	args.device = (char *)(uintptr_t *)device;
341 	args.buf = buf;
342 	args.len = len;
343 	if (openfirmware(&args) == -1)
344 		return -1;
345 	return args.size;
346 }
347 
348 /* Return a package handle for the specified device. */
349 phandle_t
350 OF_finddevice(const char *device)
351 {
352 	static struct {
353 		char		*name;
354 		int		nargs;
355 		int		nreturns;
356 		char		*device;
357 		phandle_t	package;
358 	} args = {
359 		"finddevice",
360 		1,
361 		1,
362 	};
363 
364 	args.device = (char *)(uintptr_t *)device;
365 	if (openfirmware(&args) == -1)
366 		return -1;
367 	return args.package;
368 }
369 
370 /* Return the fully qualified pathname corresponding to an instance. */
371 int
372 OF_instance_to_path(ihandle_t instance, char *buf, int len)
373 {
374 	static struct {
375 		char		*name;
376 		int		nargs;
377 		int		nreturns;
378 		ihandle_t	instance;
379 		char		*buf;
380 		int		len;
381 		int		size;
382 	} args = {
383 		"instance-to-path",
384 		3,
385 		1,
386 	};
387 
388 	args.instance = instance;
389 	args.buf = buf;
390 	args.len = len;
391 	if (openfirmware(&args) == -1)
392 		return -1;
393 	return(args.size);
394 }
395 
396 /* Return the fully qualified pathname corresponding to a package. */
397 int
398 OF_package_to_path(phandle_t package, char *buf, int len)
399 {
400 	static struct {
401 		char		*name;
402 		int		nargs;
403 		int		nreturns;
404 		phandle_t	package;
405 		char		*buf;
406 		int		len;
407 		int		size;
408 	} args = {
409 		"package-to-path",
410 		3,
411 		1,
412 	};
413 
414 	args.package = package;
415 	args.buf = buf;
416 	args.len = len;
417 	if (openfirmware(&args) == -1)
418 		return -1;
419 	return(args.size);
420 }
421 
422 /*  Call the method in the scope of a given instance. */
423 int
424 OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
425 {
426 	va_list ap;
427 	static struct {
428 		char		*name;
429 		int		nargs;
430 		int		nreturns;
431 		char		*method;
432 		ihandle_t	instance;
433 		int		args_n_results[12];
434 	} args = {
435 		"call-method",
436 		2,
437 		1,
438 	};
439 	int *ip, n;
440 
441 	if (nargs > 6)
442 		return -1;
443 	args.nargs = nargs + 2;
444 	args.nreturns = nreturns + 1;
445 	args.method = method;
446 	args.instance = instance;
447 	va_start(ap, nreturns);
448 	for (ip = args.args_n_results + (n = nargs); --n >= 0;)
449 		*--ip = va_arg(ap, int);
450 
451 	if (openfirmware(&args) == -1)
452 		return -1;
453 	if (args.args_n_results[nargs])
454 		return args.args_n_results[nargs];
455 	for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
456 		*va_arg(ap, int *) = *--ip;
457 	va_end(ap);
458 	return 0;
459 }
460 
461 /*
462  * Device I/O functions.
463  */
464 
465 /* Open an instance for a device. */
466 ihandle_t
467 OF_open(char *device)
468 {
469 	static struct {
470 		char		*name;
471 		int		nargs;
472 		int		nreturns;
473 		char		*device;
474 		ihandle_t	instance;
475 	} args = {
476 		"open",
477 		1,
478 		1,
479 	};
480 
481 	args.device = device;
482 	if (openfirmware(&args) == -1 || args.instance == 0) {
483 		return -1;
484 	}
485 	return args.instance;
486 }
487 
488 /* Close an instance. */
489 void
490 OF_close(ihandle_t instance)
491 {
492 	static struct {
493 		char		*name;
494 		int		nargs;
495 		int		nreturns;
496 		ihandle_t	instance;
497 	} args = {
498 		"close",
499 		1,
500 		0,
501 	};
502 
503 	args.instance = instance;
504 	openfirmware(&args);
505 }
506 
507 /* Read from an instance. */
508 int
509 OF_read(ihandle_t instance, void *addr, int len)
510 {
511 	static struct {
512 		char		*name;
513 		int		nargs;
514 		int		nreturns;
515 		ihandle_t	instance;
516 		void		*addr;
517 		int		len;
518 		int		actual;
519 	} args = {
520 		"read",
521 		3,
522 		1,
523 	};
524 
525 	args.instance = instance;
526 	args.addr = addr;
527 	args.len = len;
528 
529 #if defined(OPENFIRM_DEBUG)
530 	printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
531 	    args.instance, args.addr, args.len);
532 #endif
533 
534 	if (openfirmware(&args) == -1)
535 		return -1;
536 
537 #if defined(OPENFIRM_DEBUG)
538 	printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
539 	    args.instance, args.addr, args.len, args.actual);
540 #endif
541 
542 	return args.actual;
543 }
544 
545 /* Write to an instance. */
546 int
547 OF_write(ihandle_t instance, void *addr, int len)
548 {
549 	static struct {
550 		char		*name;
551 		int		nargs;
552 		int		nreturns;
553 		ihandle_t	instance;
554 		void		*addr;
555 		int		len;
556 		int		actual;
557 	} args = {
558 		"write",
559 		3,
560 		1,
561 	};
562 
563 	args.instance = instance;
564 	args.addr = addr;
565 	args.len = len;
566 	if (openfirmware(&args) == -1)
567 		return -1;
568 	return args.actual;
569 }
570 
571 /* Seek to a position. */
572 int
573 OF_seek(ihandle_t instance, u_int64_t pos)
574 {
575 	static struct {
576 		char		*name;
577 		int		nargs;
578 		int		nreturns;
579 		ihandle_t	instance;
580 		int		poshi;
581 		int		poslo;
582 		int		status;
583 	} args = {
584 		"seek",
585 		3,
586 		1,
587 	};
588 
589 	args.instance = instance;
590 	args.poshi = (int)(pos >> 32);
591 	args.poslo = (int)pos;
592 	if (openfirmware(&args) == -1)
593 		return -1;
594 	return args.status;
595 }
596 
597 /*
598  * Memory functions.
599  */
600 
601 /* Claim an area of memory. */
602 void *
603 OF_claim(void *virt, u_int size, u_int align)
604 {
605 	static struct {
606 		char	*name;
607 		int	 nargs;
608 		int	 nreturns;
609 		void	 *virt;
610 		u_int	 size;
611 		u_int	 align;
612 		void	 *baseaddr;
613 	} args = {
614 		"claim",
615 		3,
616 		1,
617 	};
618 
619 	args.virt = virt;
620 	args.size = size;
621 	args.align = align;
622 	if (openfirmware(&args) == -1)
623 		return (void *)-1;
624 	return args.baseaddr;
625 }
626 
627 /* Release an area of memory. */
628 void
629 OF_release(void *virt, u_int size)
630 {
631 	static struct {
632 		char	*name;
633 		int	nargs;
634 		int	nreturns;
635 		void	*virt;
636 		u_int	size;
637 	} args = {
638 		"release",
639 		2,
640 		0,
641 	};
642 
643 	args.virt = virt;
644 	args.size = size;
645 	openfirmware(&args);
646 }
647 
648 /*
649  * Control transfer functions.
650  */
651 
652 /* Reset the system and call "boot <bootspec>". */
653 void
654 OF_boot(char *bootspec)
655 {
656 	static struct {
657 		char	*name;
658 		int	nargs;
659 		int	nreturns;
660 		char	*bootspec;
661 	} args = {
662 		"boot",
663 		1,
664 		0,
665 	};
666 
667 	args.bootspec = bootspec;
668 	openfirmware(&args);
669 	for (;;);			/* just in case */
670 }
671 
672 /* Suspend and drop back to the OpenFirmware interface. */
673 void
674 OF_enter()
675 {
676 	static struct {
677 		char *name;
678 		int nargs;
679 		int nreturns;
680 	} args = {
681 		"enter",
682 		0,
683 		0
684 	};
685 
686 	openfirmware(&args);
687 	return;				/* We may come back. */
688 }
689 
690 /* Shut down and drop back to the OpenFirmware interface. */
691 void
692 OF_exit()
693 {
694 	static struct {
695 		char *name;
696 		int nargs;
697 		int nreturns;
698 	} args = {
699 		"exit",
700 		0,
701 		0
702 	};
703 
704 	openfirmware(&args);
705 	for (;;);			/* just in case */
706 }
707 
708 /* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
709 #ifdef	__notyet__
710 void
711 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
712 {
713 	static struct {
714 		char	*name;
715 		int	nargs;
716 		int	nreturns;
717 		void	*virt;
718 		u_int	size;
719 		void	(*entry)();
720 		void	*arg;
721 		u_int	len;
722 	} args = {
723 		"chain",
724 		5,
725 		0,
726 	};
727 
728 	args.virt = virt;
729 	args.size = size;
730 	args.entry = entry;
731 	args.arg = arg;
732 	args.len = len;
733 	openfirmware(&args);
734 }
735 #else
736 void
737 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
738 {
739 	/*
740 	 * This is a REALLY dirty hack till the firmware gets this going
741 	 */
742 #if 0
743 	OF_release(virt, size);
744 #endif
745 	entry(0, 0, openfirmware, arg, len);
746 }
747 #endif
748