Deleted Added
full compact
openfirm.c (124140) openfirm.c (131783)
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
58#include <sys/cdefs.h>
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
58#include <sys/cdefs.h>
59__FBSDID("$FreeBSD: head/sys/boot/ofw/libofw/openfirm.c 124140 2004-01-04 23:30:47Z obrien $");
59__FBSDID("$FreeBSD: head/sys/boot/ofw/libofw/openfirm.c 131783 2004-07-08 06:09:22Z grehan $");
60
61#include <machine/stdarg.h>
62
63#include <stand.h>
64
65#include "openfirm.h"
66
67int (*openfirmware)(void *);
68
69static ihandle_t stdin;
70static ihandle_t stdout;
71
72ihandle_t mmu;
73ihandle_t memory;
74
75/* Initialiaser */
76
77void
78OF_init(int (*openfirm)(void *))
79{
80 phandle_t chosen;
81
82 openfirmware = openfirm;
83
84 chosen = OF_finddevice("/chosen");
85 OF_getprop(chosen, "memory", &memory, sizeof(memory));
86 if (memory == 0)
87 panic("failed to get memory ihandle");
88 OF_getprop(chosen, "mmu", &mmu, sizeof(mmu));
89 if (mmu == 0)
90 panic("failed to get mmu ihandle");
91}
92
93/*
94 * Generic functions
95 */
96
97/* Test to see if a service exists. */
98int
99OF_test(char *name)
100{
101 static struct {
102 cell_t name;
103 cell_t nargs;
104 cell_t nreturns;
105 cell_t service;
106 cell_t missing;
107 } args = {
108 (cell_t)"test",
109 1,
110 1,
111 0,
112 0
113 };
114
115 args.service = (cell_t)name;
116 if (openfirmware(&args) == -1)
117 return -1;
118 return (int)args.missing;
119}
120
121/* Return firmware millisecond count. */
122int
123OF_milliseconds()
124{
125 static struct {
126 cell_t name;
127 cell_t nargs;
128 cell_t nreturns;
129 cell_t ms;
130 } args = {
131 (cell_t)"milliseconds",
132 0,
133 1,
134 0
135 };
136
137 openfirmware(&args);
138 return (int)args.ms;
139}
140
141/*
142 * Device tree functions
143 */
144
145/* Return the next sibling of this node or 0. */
146phandle_t
147OF_peer(phandle_t node)
148{
149 static struct {
150 cell_t name;
151 cell_t nargs;
152 cell_t nreturns;
153 cell_t node;
154 cell_t next;
155 } args = {
156 (cell_t)"peer",
157 1,
158 1,
159 0,
160 0
161 };
162
163 args.node = (u_int)node;
164 if (openfirmware(&args) == -1)
165 return -1;
166 return (phandle_t)args.next;
167}
168
169/* Return the first child of this node or 0. */
170phandle_t
171OF_child(phandle_t node)
172{
173 static struct {
174 cell_t name;
175 cell_t nargs;
176 cell_t nreturns;
177 cell_t node;
178 cell_t child;
179 } args = {
180 (cell_t)"child",
181 1,
182 1,
183 0,
184 0
185 };
186
187 args.node = (u_int)node;
188 if (openfirmware(&args) == -1)
189 return -1;
190 return (phandle_t)args.child;
191}
192
193/* Return the parent of this node or 0. */
194phandle_t
195OF_parent(phandle_t node)
196{
197 static struct {
198 cell_t name;
199 cell_t nargs;
200 cell_t nreturns;
201 cell_t node;
202 cell_t parent;
203 } args = {
204 (cell_t)"parent",
205 1,
206 1,
207 0,
208 0
209 };
210
211 args.node = (u_int)node;
212 if (openfirmware(&args) == -1)
213 return -1;
214 return (phandle_t)args.parent;
215}
216
217/* Return the package handle that corresponds to an instance handle. */
218phandle_t
219OF_instance_to_package(ihandle_t instance)
220{
221 static struct {
222 cell_t name;
223 cell_t nargs;
224 cell_t nreturns;
225 cell_t instance;
226 cell_t package;
227 } args = {
228 (cell_t)"instance-to-package",
229 1,
230 1,
231 0,
232 0
233 };
234
235 args.instance = (u_int)instance;
236 if (openfirmware(&args) == -1)
237 return -1;
238 return (phandle_t)args.package;
239}
240
241/* Get the length of a property of a package. */
242int
243OF_getproplen(phandle_t package, char *propname)
244{
245 static struct {
246 cell_t name;
247 cell_t nargs;
248 cell_t nreturns;
249 cell_t package;
250 cell_t propname;
251 cell_t proplen;
252 } args = {
253 (cell_t)"getproplen",
254 2,
255 1,
256 0,
257 0,
258 0
259 };
260
261 args.package = (u_int)package;
262 args.propname = (cell_t)propname;
263 if (openfirmware(&args) == -1)
264 return -1;
265 return (int)args.proplen;
266}
267
268/* Get the value of a property of a package. */
269int
270OF_getprop(phandle_t package, char *propname, void *buf, int buflen)
271{
272 static struct {
273 cell_t name;
274 cell_t nargs;
275 cell_t nreturns;
276 cell_t package;
277 cell_t propname;
278 cell_t buf;
279 cell_t buflen;
280 cell_t size;
281 } args = {
282 (cell_t)"getprop",
283 4,
284 1,
285 0,
286 0,
287 0,
288 0,
289 0
290 };
291
292 args.package = (u_int)package;
293 args.propname = (cell_t)propname;
294 args.buf = (cell_t)buf;
295 args.buflen = (u_int)buflen;
296 if (openfirmware(&args) == -1)
297 return -1;
298 return (int)args.size;
299}
300
301/* Get the next property of a package. */
302int
303OF_nextprop(phandle_t package, char *previous, char *buf)
304{
305 static struct {
306 cell_t name;
307 cell_t nargs;
308 cell_t nreturns;
309 cell_t package;
310 cell_t previous;
311 cell_t buf;
312 cell_t flag;
313 } args = {
314 (cell_t)"nextprop",
315 3,
316 1,
317 0,
318 0,
319 0,
320 0
321 };
322
323 args.package = (u_int)package;
324 args.previous = (cell_t)previous;
325 args.buf = (cell_t)buf;
326 if (openfirmware(&args) == -1)
327 return -1;
328 return (int)args.flag;
329}
330
331/* Set the value of a property of a package. */
332/* XXX Has a bug on FirePower */
333int
334OF_setprop(phandle_t package, char *propname, void *buf, int len)
335{
336 static struct {
337 cell_t name;
338 cell_t nargs;
339 cell_t nreturns;
340 cell_t package;
341 cell_t propname;
342 cell_t buf;
343 cell_t len;
344 cell_t size;
345 } args = {
346 (cell_t)"setprop",
347 4,
348 1,
349 0,
350 0,
351 0,
352 0,
353 0
354 };
355
356 args.package = (u_int)package;
357 args.propname = (cell_t)propname;
358 args.buf = (cell_t)buf;
359 args.len = (u_int)len;
360 if (openfirmware(&args) == -1)
361 return -1;
362 return (int)args.size;
363}
364
365/* Convert a device specifier to a fully qualified pathname. */
366int
367OF_canon(const char *device, char *buf, int len)
368{
369 static struct {
370 cell_t name;
371 cell_t nargs;
372 cell_t nreturns;
373 cell_t device;
374 cell_t buf;
375 cell_t len;
376 cell_t size;
377 } args = {
378 (cell_t)"canon",
379 3,
380 1,
381 0,
382 0,
383 0,
384 0
385 };
386
387 args.device = (cell_t)device;
388 args.buf = (cell_t)buf;
389 args.len = (cell_t)len;
390 if (openfirmware(&args) == -1)
391 return -1;
392 return (int)args.size;
393}
394
395/* Return a package handle for the specified device. */
396phandle_t
397OF_finddevice(const char *device)
398{
399 int i;
400 static struct {
401 cell_t name;
402 cell_t nargs;
403 cell_t nreturns;
404 cell_t device;
405 cell_t package;
406 } args = {
407 (cell_t)"finddevice",
408 1,
409 1,
410 0,
411 0
412 };
413
414 args.device = (cell_t)device;
415 if (openfirmware(&args) == -1)
416 return -1;
417
418 return (phandle_t)args.package;
419}
420
421/* Return the fully qualified pathname corresponding to an instance. */
422int
423OF_instance_to_path(ihandle_t instance, char *buf, int len)
424{
425 static struct {
426 cell_t name;
427 cell_t nargs;
428 cell_t nreturns;
429 cell_t instance;
430 cell_t buf;
431 cell_t len;
432 cell_t size;
433 } args = {
434 (cell_t)"instance-to-path",
435 3,
436 1,
437 0,
438 0,
439 0,
440 0
441 };
442
443 args.instance = (u_int)instance;
444 args.buf = (cell_t)buf;
445 args.len = (u_int)len;
446 if (openfirmware(&args) == -1)
447 return -1;
448 return (int)args.size;
449}
450
451/* Return the fully qualified pathname corresponding to a package. */
452int
453OF_package_to_path(phandle_t package, char *buf, int len)
454{
455 static struct {
456 cell_t name;
457 cell_t nargs;
458 cell_t nreturns;
459 cell_t package;
460 cell_t buf;
461 cell_t len;
462 cell_t size;
463 } args = {
464 (cell_t)"package-to-path",
465 3,
466 1,
467 0,
468 0,
469 0,
470 0
471 };
472
473 args.package = (u_int)package;
474 args.buf = (cell_t)buf;
475 args.len = (u_int)len;
476 if (openfirmware(&args) == -1)
477 return -1;
478 return (int)args.size;
479}
480
481/* Call the method in the scope of a given instance. */
482int
483OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
484{
485 va_list ap;
486 static struct {
487 cell_t name;
488 cell_t nargs;
489 cell_t nreturns;
490 cell_t method;
491 cell_t instance;
492 cell_t args_n_results[12];
493 } args = {
494 (cell_t)"call-method",
495 2,
496 1,
497 0,
498 0,
499 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
500 };
501 int *ip, n;
502
503 if (nargs > 6)
504 return -1;
505 args.nargs = nargs + 2;
506 args.nreturns = nreturns + 1;
507 args.method = (cell_t)method;
508 args.instance = (u_int)instance;
509 va_start(ap, nreturns);
510 for (ip = (int *)(args.args_n_results + (n = nargs)); --n >= 0;)
511 *--ip = va_arg(ap, int);
512
513 if (openfirmware(&args) == -1)
514 return -1;
515 if (args.args_n_results[nargs])
516 return (int)args.args_n_results[nargs];
517 for (ip = (int *)(args.args_n_results + nargs + (n = args.nreturns));
518 --n > 0;)
519 *va_arg(ap, int *) = *--ip;
520 va_end(ap);
521 return 0;
522}
523
524/*
525 * Device I/O functions.
526 */
527
528/* Open an instance for a device. */
529ihandle_t
530OF_open(char *device)
531{
532 static struct {
533 cell_t name;
534 cell_t nargs;
535 cell_t nreturns;
536 cell_t device;
537 cell_t instance;
538 } args = {
539 (cell_t)"open",
540 1,
541 1,
542 0,
543 0
544 };
545
546 args.device = (cell_t)device;
547 if (openfirmware(&args) == -1 || args.instance == 0) {
548 return -1;
549 }
550 return (ihandle_t)args.instance;
551}
552
553/* Close an instance. */
554void
555OF_close(ihandle_t instance)
556{
557 static struct {
558 cell_t name;
559 cell_t nargs;
560 cell_t nreturns;
561 cell_t instance;
562 } args = {
563 (cell_t)"close",
564 1,
565 0,
566 0
567 };
568
569 args.instance = (u_int)instance;
570 openfirmware(&args);
571}
572
573/* Read from an instance. */
574int
575OF_read(ihandle_t instance, void *addr, int len)
576{
577 static struct {
578 cell_t name;
579 cell_t nargs;
580 cell_t nreturns;
581 cell_t instance;
582 cell_t addr;
583 cell_t len;
584 cell_t actual;
585 } args = {
586 (cell_t)"read",
587 3,
588 1,
589 0,
590 0,
591 0,
592 0
593 };
594
595 args.instance = (u_int)instance;
596 args.addr = (cell_t)addr;
597 args.len = (u_int)len;
598
599#if defined(OPENFIRM_DEBUG)
600 printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
601 args.instance, args.addr, args.len);
602#endif
603
604 if (openfirmware(&args) == -1)
605 return -1;
606
607#if defined(OPENFIRM_DEBUG)
608 printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
609 args.instance, args.addr, args.len, args.actual);
610#endif
611
612 return (int)args.actual;
613}
614
615/* Write to an instance. */
616int
617OF_write(ihandle_t instance, void *addr, int len)
618{
619 static struct {
620 cell_t name;
621 cell_t nargs;
622 cell_t nreturns;
623 cell_t instance;
624 cell_t addr;
625 cell_t len;
626 cell_t actual;
627 } args = {
628 (cell_t)"write",
629 3,
630 1,
631 0,
632 0,
633 0,
634 0
635 };
636
637 args.instance = (u_int)instance;
638 args.addr = (cell_t)addr;
639 args.len = (u_int)len;
640 if (openfirmware(&args) == -1)
641 return -1;
642 return (int)args.actual;
643}
644
645/* Seek to a position. */
646int
647OF_seek(ihandle_t instance, u_int64_t pos)
648{
649 static struct {
650 cell_t name;
651 cell_t nargs;
652 cell_t nreturns;
653 cell_t instance;
654 cell_t poshi;
655 cell_t poslo;
656 cell_t status;
657 } args = {
658 (cell_t)"seek",
659 3,
660 1,
661 0,
662 0,
663 0,
664 0
665 };
666
667 args.instance = (u_int)instance;
668 args.poshi = pos >> 32;
669 args.poslo = pos;
670 if (openfirmware(&args) == -1)
671 return -1;
672 return (int)args.status;
673}
674
675/*
676 * Memory functions.
677 */
678
679/* Claim an area of memory. */
680void *
681OF_claim(void *virt, u_int size, u_int align)
682{
683 static struct {
684 cell_t name;
685 cell_t nargs;
686 cell_t nreturns;
687 cell_t virt;
688 cell_t size;
689 cell_t align;
690 cell_t baseaddr;
691 } args = {
692 (cell_t)"claim",
693 3,
694 1,
695 0,
696 0,
697 0,
698 0
699 };
700
701 args.virt = (cell_t)virt;
702 args.size = size;
703 args.align = align;
704 if (openfirmware(&args) == -1)
705 return (void *)-1;
706 return (void *)args.baseaddr;
707}
708
709/* Allocate an area of physical memory */
710vm_offset_t
711OF_claim_virt(vm_offset_t virt, size_t size, int align)
712{
713 static struct {
714 cell_t name;
715 cell_t nargs;
716 cell_t nret;
717 cell_t method;
718 cell_t ihandle;
719 cell_t align;
720 cell_t size;
721 cell_t virt;
722 cell_t status;
723 cell_t ret;
724 } args = {
725 (cell_t)"call-method",
726 5,
727 2,
728 (cell_t)"claim",
729 0,
730 0,
731 0,
732 0,
733 0, /* ret */
734 0,
735 };
736
737 args.ihandle = mmu;
738 args.align = align;
739 args.size = size;
740 args.virt = virt;
741
742 if (openfirmware(&args) == -1)
743 return (vm_offset_t)-1;
744
745 return (vm_offset_t)args.ret;
746}
747
748/* Allocate an area of physical memory */
749void *
750OF_alloc_phys(size_t size, int align)
751{
752 static struct {
753 cell_t name;
754 cell_t nargs;
755 cell_t nret;
756 cell_t method;
757 cell_t ihandle;
758 cell_t align;
759 cell_t size;
760 cell_t status;
761 cell_t phys_hi;
762 cell_t phys_low;
763 } args = {
764 (cell_t)"call-method",
765 4,
766 3,
767 (cell_t)"claim",
768 0,
769 0,
770 0,
771 0, /* ret */
772 0,
773 0,
774 };
775
776 args.ihandle = memory;
777 args.size = size;
778 args.align = align;
779
780 if (openfirmware(&args) == -1)
781 return (void *)-1;
782
783 return (void *)(args.phys_hi << 32 | args.phys_low);
784}
785
786/* Release an area of memory. */
787void
788OF_release(void *virt, u_int size)
789{
790 static struct {
791 cell_t name;
792 cell_t nargs;
793 cell_t nreturns;
794 cell_t virt;
795 cell_t size;
796 } args = {
797 (cell_t)"release",
798 2,
799 0,
800 0,
801 0
802 };
803
804 args.virt = (cell_t)virt;
805 args.size = size;
806 openfirmware(&args);
807}
808
809/* Release an area of physical memory. */
810void
811OF_release_phys(vm_offset_t phys, u_int size)
812{
813 static struct {
814 cell_t name;
815 cell_t nargs;
816 cell_t nret;
817 cell_t method;
818 cell_t ihandle;
819 cell_t size;
820 cell_t phys_hi;
821 cell_t phys_lo;
822 } args = {
823 (cell_t)"call-method",
824 5,
825 0,
826 (cell_t)"release",
827 0,
828 0,
829 0,
830 0
831 };
832
833 args.ihandle = memory;
834 args.phys_hi = (u_int32_t)(phys >> 32);
835 args.phys_lo = (u_int32_t)phys;
836 args.size = size;
837 openfirmware(&args);
838}
839
840/*
841 * Control transfer functions.
842 */
843
844/* Reset the system and call "boot <bootspec>". */
845void
846OF_boot(char *bootspec)
847{
848 static struct {
849 cell_t name;
850 cell_t nargs;
851 cell_t nreturns;
852 cell_t bootspec;
853 } args = {
854 (cell_t)"boot",
855 1,
856 0,
857 0
858 };
859
860 args.bootspec = (cell_t)bootspec;
861 openfirmware(&args);
862 for (;;); /* just in case */
863}
864
865/* Suspend and drop back to the OpenFirmware interface. */
866void
867OF_enter()
868{
869 static struct {
870 cell_t name;
871 cell_t nargs;
872 cell_t nreturns;
873 } args = {
874 (cell_t)"enter",
875 0,
876 0
877 };
878
879 openfirmware(&args);
880}
881
882/* Shut down and drop back to the OpenFirmware interface. */
883void
884OF_exit()
885{
886 static struct {
887 cell_t name;
888 cell_t nargs;
889 cell_t nreturns;
890 } args = {
891 (cell_t)"exit",
892 0,
893 0
894 };
895
896 openfirmware(&args);
897 for (;;); /* just in case */
898}
899
900/* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
60
61#include <machine/stdarg.h>
62
63#include <stand.h>
64
65#include "openfirm.h"
66
67int (*openfirmware)(void *);
68
69static ihandle_t stdin;
70static ihandle_t stdout;
71
72ihandle_t mmu;
73ihandle_t memory;
74
75/* Initialiaser */
76
77void
78OF_init(int (*openfirm)(void *))
79{
80 phandle_t chosen;
81
82 openfirmware = openfirm;
83
84 chosen = OF_finddevice("/chosen");
85 OF_getprop(chosen, "memory", &memory, sizeof(memory));
86 if (memory == 0)
87 panic("failed to get memory ihandle");
88 OF_getprop(chosen, "mmu", &mmu, sizeof(mmu));
89 if (mmu == 0)
90 panic("failed to get mmu ihandle");
91}
92
93/*
94 * Generic functions
95 */
96
97/* Test to see if a service exists. */
98int
99OF_test(char *name)
100{
101 static struct {
102 cell_t name;
103 cell_t nargs;
104 cell_t nreturns;
105 cell_t service;
106 cell_t missing;
107 } args = {
108 (cell_t)"test",
109 1,
110 1,
111 0,
112 0
113 };
114
115 args.service = (cell_t)name;
116 if (openfirmware(&args) == -1)
117 return -1;
118 return (int)args.missing;
119}
120
121/* Return firmware millisecond count. */
122int
123OF_milliseconds()
124{
125 static struct {
126 cell_t name;
127 cell_t nargs;
128 cell_t nreturns;
129 cell_t ms;
130 } args = {
131 (cell_t)"milliseconds",
132 0,
133 1,
134 0
135 };
136
137 openfirmware(&args);
138 return (int)args.ms;
139}
140
141/*
142 * Device tree functions
143 */
144
145/* Return the next sibling of this node or 0. */
146phandle_t
147OF_peer(phandle_t node)
148{
149 static struct {
150 cell_t name;
151 cell_t nargs;
152 cell_t nreturns;
153 cell_t node;
154 cell_t next;
155 } args = {
156 (cell_t)"peer",
157 1,
158 1,
159 0,
160 0
161 };
162
163 args.node = (u_int)node;
164 if (openfirmware(&args) == -1)
165 return -1;
166 return (phandle_t)args.next;
167}
168
169/* Return the first child of this node or 0. */
170phandle_t
171OF_child(phandle_t node)
172{
173 static struct {
174 cell_t name;
175 cell_t nargs;
176 cell_t nreturns;
177 cell_t node;
178 cell_t child;
179 } args = {
180 (cell_t)"child",
181 1,
182 1,
183 0,
184 0
185 };
186
187 args.node = (u_int)node;
188 if (openfirmware(&args) == -1)
189 return -1;
190 return (phandle_t)args.child;
191}
192
193/* Return the parent of this node or 0. */
194phandle_t
195OF_parent(phandle_t node)
196{
197 static struct {
198 cell_t name;
199 cell_t nargs;
200 cell_t nreturns;
201 cell_t node;
202 cell_t parent;
203 } args = {
204 (cell_t)"parent",
205 1,
206 1,
207 0,
208 0
209 };
210
211 args.node = (u_int)node;
212 if (openfirmware(&args) == -1)
213 return -1;
214 return (phandle_t)args.parent;
215}
216
217/* Return the package handle that corresponds to an instance handle. */
218phandle_t
219OF_instance_to_package(ihandle_t instance)
220{
221 static struct {
222 cell_t name;
223 cell_t nargs;
224 cell_t nreturns;
225 cell_t instance;
226 cell_t package;
227 } args = {
228 (cell_t)"instance-to-package",
229 1,
230 1,
231 0,
232 0
233 };
234
235 args.instance = (u_int)instance;
236 if (openfirmware(&args) == -1)
237 return -1;
238 return (phandle_t)args.package;
239}
240
241/* Get the length of a property of a package. */
242int
243OF_getproplen(phandle_t package, char *propname)
244{
245 static struct {
246 cell_t name;
247 cell_t nargs;
248 cell_t nreturns;
249 cell_t package;
250 cell_t propname;
251 cell_t proplen;
252 } args = {
253 (cell_t)"getproplen",
254 2,
255 1,
256 0,
257 0,
258 0
259 };
260
261 args.package = (u_int)package;
262 args.propname = (cell_t)propname;
263 if (openfirmware(&args) == -1)
264 return -1;
265 return (int)args.proplen;
266}
267
268/* Get the value of a property of a package. */
269int
270OF_getprop(phandle_t package, char *propname, void *buf, int buflen)
271{
272 static struct {
273 cell_t name;
274 cell_t nargs;
275 cell_t nreturns;
276 cell_t package;
277 cell_t propname;
278 cell_t buf;
279 cell_t buflen;
280 cell_t size;
281 } args = {
282 (cell_t)"getprop",
283 4,
284 1,
285 0,
286 0,
287 0,
288 0,
289 0
290 };
291
292 args.package = (u_int)package;
293 args.propname = (cell_t)propname;
294 args.buf = (cell_t)buf;
295 args.buflen = (u_int)buflen;
296 if (openfirmware(&args) == -1)
297 return -1;
298 return (int)args.size;
299}
300
301/* Get the next property of a package. */
302int
303OF_nextprop(phandle_t package, char *previous, char *buf)
304{
305 static struct {
306 cell_t name;
307 cell_t nargs;
308 cell_t nreturns;
309 cell_t package;
310 cell_t previous;
311 cell_t buf;
312 cell_t flag;
313 } args = {
314 (cell_t)"nextprop",
315 3,
316 1,
317 0,
318 0,
319 0,
320 0
321 };
322
323 args.package = (u_int)package;
324 args.previous = (cell_t)previous;
325 args.buf = (cell_t)buf;
326 if (openfirmware(&args) == -1)
327 return -1;
328 return (int)args.flag;
329}
330
331/* Set the value of a property of a package. */
332/* XXX Has a bug on FirePower */
333int
334OF_setprop(phandle_t package, char *propname, void *buf, int len)
335{
336 static struct {
337 cell_t name;
338 cell_t nargs;
339 cell_t nreturns;
340 cell_t package;
341 cell_t propname;
342 cell_t buf;
343 cell_t len;
344 cell_t size;
345 } args = {
346 (cell_t)"setprop",
347 4,
348 1,
349 0,
350 0,
351 0,
352 0,
353 0
354 };
355
356 args.package = (u_int)package;
357 args.propname = (cell_t)propname;
358 args.buf = (cell_t)buf;
359 args.len = (u_int)len;
360 if (openfirmware(&args) == -1)
361 return -1;
362 return (int)args.size;
363}
364
365/* Convert a device specifier to a fully qualified pathname. */
366int
367OF_canon(const char *device, char *buf, int len)
368{
369 static struct {
370 cell_t name;
371 cell_t nargs;
372 cell_t nreturns;
373 cell_t device;
374 cell_t buf;
375 cell_t len;
376 cell_t size;
377 } args = {
378 (cell_t)"canon",
379 3,
380 1,
381 0,
382 0,
383 0,
384 0
385 };
386
387 args.device = (cell_t)device;
388 args.buf = (cell_t)buf;
389 args.len = (cell_t)len;
390 if (openfirmware(&args) == -1)
391 return -1;
392 return (int)args.size;
393}
394
395/* Return a package handle for the specified device. */
396phandle_t
397OF_finddevice(const char *device)
398{
399 int i;
400 static struct {
401 cell_t name;
402 cell_t nargs;
403 cell_t nreturns;
404 cell_t device;
405 cell_t package;
406 } args = {
407 (cell_t)"finddevice",
408 1,
409 1,
410 0,
411 0
412 };
413
414 args.device = (cell_t)device;
415 if (openfirmware(&args) == -1)
416 return -1;
417
418 return (phandle_t)args.package;
419}
420
421/* Return the fully qualified pathname corresponding to an instance. */
422int
423OF_instance_to_path(ihandle_t instance, char *buf, int len)
424{
425 static struct {
426 cell_t name;
427 cell_t nargs;
428 cell_t nreturns;
429 cell_t instance;
430 cell_t buf;
431 cell_t len;
432 cell_t size;
433 } args = {
434 (cell_t)"instance-to-path",
435 3,
436 1,
437 0,
438 0,
439 0,
440 0
441 };
442
443 args.instance = (u_int)instance;
444 args.buf = (cell_t)buf;
445 args.len = (u_int)len;
446 if (openfirmware(&args) == -1)
447 return -1;
448 return (int)args.size;
449}
450
451/* Return the fully qualified pathname corresponding to a package. */
452int
453OF_package_to_path(phandle_t package, char *buf, int len)
454{
455 static struct {
456 cell_t name;
457 cell_t nargs;
458 cell_t nreturns;
459 cell_t package;
460 cell_t buf;
461 cell_t len;
462 cell_t size;
463 } args = {
464 (cell_t)"package-to-path",
465 3,
466 1,
467 0,
468 0,
469 0,
470 0
471 };
472
473 args.package = (u_int)package;
474 args.buf = (cell_t)buf;
475 args.len = (u_int)len;
476 if (openfirmware(&args) == -1)
477 return -1;
478 return (int)args.size;
479}
480
481/* Call the method in the scope of a given instance. */
482int
483OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
484{
485 va_list ap;
486 static struct {
487 cell_t name;
488 cell_t nargs;
489 cell_t nreturns;
490 cell_t method;
491 cell_t instance;
492 cell_t args_n_results[12];
493 } args = {
494 (cell_t)"call-method",
495 2,
496 1,
497 0,
498 0,
499 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
500 };
501 int *ip, n;
502
503 if (nargs > 6)
504 return -1;
505 args.nargs = nargs + 2;
506 args.nreturns = nreturns + 1;
507 args.method = (cell_t)method;
508 args.instance = (u_int)instance;
509 va_start(ap, nreturns);
510 for (ip = (int *)(args.args_n_results + (n = nargs)); --n >= 0;)
511 *--ip = va_arg(ap, int);
512
513 if (openfirmware(&args) == -1)
514 return -1;
515 if (args.args_n_results[nargs])
516 return (int)args.args_n_results[nargs];
517 for (ip = (int *)(args.args_n_results + nargs + (n = args.nreturns));
518 --n > 0;)
519 *va_arg(ap, int *) = *--ip;
520 va_end(ap);
521 return 0;
522}
523
524/*
525 * Device I/O functions.
526 */
527
528/* Open an instance for a device. */
529ihandle_t
530OF_open(char *device)
531{
532 static struct {
533 cell_t name;
534 cell_t nargs;
535 cell_t nreturns;
536 cell_t device;
537 cell_t instance;
538 } args = {
539 (cell_t)"open",
540 1,
541 1,
542 0,
543 0
544 };
545
546 args.device = (cell_t)device;
547 if (openfirmware(&args) == -1 || args.instance == 0) {
548 return -1;
549 }
550 return (ihandle_t)args.instance;
551}
552
553/* Close an instance. */
554void
555OF_close(ihandle_t instance)
556{
557 static struct {
558 cell_t name;
559 cell_t nargs;
560 cell_t nreturns;
561 cell_t instance;
562 } args = {
563 (cell_t)"close",
564 1,
565 0,
566 0
567 };
568
569 args.instance = (u_int)instance;
570 openfirmware(&args);
571}
572
573/* Read from an instance. */
574int
575OF_read(ihandle_t instance, void *addr, int len)
576{
577 static struct {
578 cell_t name;
579 cell_t nargs;
580 cell_t nreturns;
581 cell_t instance;
582 cell_t addr;
583 cell_t len;
584 cell_t actual;
585 } args = {
586 (cell_t)"read",
587 3,
588 1,
589 0,
590 0,
591 0,
592 0
593 };
594
595 args.instance = (u_int)instance;
596 args.addr = (cell_t)addr;
597 args.len = (u_int)len;
598
599#if defined(OPENFIRM_DEBUG)
600 printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
601 args.instance, args.addr, args.len);
602#endif
603
604 if (openfirmware(&args) == -1)
605 return -1;
606
607#if defined(OPENFIRM_DEBUG)
608 printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
609 args.instance, args.addr, args.len, args.actual);
610#endif
611
612 return (int)args.actual;
613}
614
615/* Write to an instance. */
616int
617OF_write(ihandle_t instance, void *addr, int len)
618{
619 static struct {
620 cell_t name;
621 cell_t nargs;
622 cell_t nreturns;
623 cell_t instance;
624 cell_t addr;
625 cell_t len;
626 cell_t actual;
627 } args = {
628 (cell_t)"write",
629 3,
630 1,
631 0,
632 0,
633 0,
634 0
635 };
636
637 args.instance = (u_int)instance;
638 args.addr = (cell_t)addr;
639 args.len = (u_int)len;
640 if (openfirmware(&args) == -1)
641 return -1;
642 return (int)args.actual;
643}
644
645/* Seek to a position. */
646int
647OF_seek(ihandle_t instance, u_int64_t pos)
648{
649 static struct {
650 cell_t name;
651 cell_t nargs;
652 cell_t nreturns;
653 cell_t instance;
654 cell_t poshi;
655 cell_t poslo;
656 cell_t status;
657 } args = {
658 (cell_t)"seek",
659 3,
660 1,
661 0,
662 0,
663 0,
664 0
665 };
666
667 args.instance = (u_int)instance;
668 args.poshi = pos >> 32;
669 args.poslo = pos;
670 if (openfirmware(&args) == -1)
671 return -1;
672 return (int)args.status;
673}
674
675/*
676 * Memory functions.
677 */
678
679/* Claim an area of memory. */
680void *
681OF_claim(void *virt, u_int size, u_int align)
682{
683 static struct {
684 cell_t name;
685 cell_t nargs;
686 cell_t nreturns;
687 cell_t virt;
688 cell_t size;
689 cell_t align;
690 cell_t baseaddr;
691 } args = {
692 (cell_t)"claim",
693 3,
694 1,
695 0,
696 0,
697 0,
698 0
699 };
700
701 args.virt = (cell_t)virt;
702 args.size = size;
703 args.align = align;
704 if (openfirmware(&args) == -1)
705 return (void *)-1;
706 return (void *)args.baseaddr;
707}
708
709/* Allocate an area of physical memory */
710vm_offset_t
711OF_claim_virt(vm_offset_t virt, size_t size, int align)
712{
713 static struct {
714 cell_t name;
715 cell_t nargs;
716 cell_t nret;
717 cell_t method;
718 cell_t ihandle;
719 cell_t align;
720 cell_t size;
721 cell_t virt;
722 cell_t status;
723 cell_t ret;
724 } args = {
725 (cell_t)"call-method",
726 5,
727 2,
728 (cell_t)"claim",
729 0,
730 0,
731 0,
732 0,
733 0, /* ret */
734 0,
735 };
736
737 args.ihandle = mmu;
738 args.align = align;
739 args.size = size;
740 args.virt = virt;
741
742 if (openfirmware(&args) == -1)
743 return (vm_offset_t)-1;
744
745 return (vm_offset_t)args.ret;
746}
747
748/* Allocate an area of physical memory */
749void *
750OF_alloc_phys(size_t size, int align)
751{
752 static struct {
753 cell_t name;
754 cell_t nargs;
755 cell_t nret;
756 cell_t method;
757 cell_t ihandle;
758 cell_t align;
759 cell_t size;
760 cell_t status;
761 cell_t phys_hi;
762 cell_t phys_low;
763 } args = {
764 (cell_t)"call-method",
765 4,
766 3,
767 (cell_t)"claim",
768 0,
769 0,
770 0,
771 0, /* ret */
772 0,
773 0,
774 };
775
776 args.ihandle = memory;
777 args.size = size;
778 args.align = align;
779
780 if (openfirmware(&args) == -1)
781 return (void *)-1;
782
783 return (void *)(args.phys_hi << 32 | args.phys_low);
784}
785
786/* Release an area of memory. */
787void
788OF_release(void *virt, u_int size)
789{
790 static struct {
791 cell_t name;
792 cell_t nargs;
793 cell_t nreturns;
794 cell_t virt;
795 cell_t size;
796 } args = {
797 (cell_t)"release",
798 2,
799 0,
800 0,
801 0
802 };
803
804 args.virt = (cell_t)virt;
805 args.size = size;
806 openfirmware(&args);
807}
808
809/* Release an area of physical memory. */
810void
811OF_release_phys(vm_offset_t phys, u_int size)
812{
813 static struct {
814 cell_t name;
815 cell_t nargs;
816 cell_t nret;
817 cell_t method;
818 cell_t ihandle;
819 cell_t size;
820 cell_t phys_hi;
821 cell_t phys_lo;
822 } args = {
823 (cell_t)"call-method",
824 5,
825 0,
826 (cell_t)"release",
827 0,
828 0,
829 0,
830 0
831 };
832
833 args.ihandle = memory;
834 args.phys_hi = (u_int32_t)(phys >> 32);
835 args.phys_lo = (u_int32_t)phys;
836 args.size = size;
837 openfirmware(&args);
838}
839
840/*
841 * Control transfer functions.
842 */
843
844/* Reset the system and call "boot <bootspec>". */
845void
846OF_boot(char *bootspec)
847{
848 static struct {
849 cell_t name;
850 cell_t nargs;
851 cell_t nreturns;
852 cell_t bootspec;
853 } args = {
854 (cell_t)"boot",
855 1,
856 0,
857 0
858 };
859
860 args.bootspec = (cell_t)bootspec;
861 openfirmware(&args);
862 for (;;); /* just in case */
863}
864
865/* Suspend and drop back to the OpenFirmware interface. */
866void
867OF_enter()
868{
869 static struct {
870 cell_t name;
871 cell_t nargs;
872 cell_t nreturns;
873 } args = {
874 (cell_t)"enter",
875 0,
876 0
877 };
878
879 openfirmware(&args);
880}
881
882/* Shut down and drop back to the OpenFirmware interface. */
883void
884OF_exit()
885{
886 static struct {
887 cell_t name;
888 cell_t nargs;
889 cell_t nreturns;
890 } args = {
891 (cell_t)"exit",
892 0,
893 0
894 };
895
896 openfirmware(&args);
897 for (;;); /* just in case */
898}
899
900/* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
901#ifdef __notyet__
901#if 0
902void
903OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
904{
905 static struct {
906 cell_t name;
907 cell_t nargs;
908 cell_t nreturns;
909 cell_t virt;
910 cell_t size;
911 cell_t entry;
912 cell_t arg;
913 cell_t len;
914 } args = {
915 (cell_t)"chain",
916 5,
917 0,
918 0,
919 0,
920 0,
921 0,
922 0
923 };
924
925 args.virt = (cell_t)virt;
926 args.size = size;
927 args.entry = (cell_t)entry;
928 args.arg = (cell_t)arg;
929 args.len = len;
930 openfirmware(&args);
931}
932#else
933void
934OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
935{
936 /*
937 * This is a REALLY dirty hack till the firmware gets this going
938 */
902void
903OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
904{
905 static struct {
906 cell_t name;
907 cell_t nargs;
908 cell_t nreturns;
909 cell_t virt;
910 cell_t size;
911 cell_t entry;
912 cell_t arg;
913 cell_t len;
914 } args = {
915 (cell_t)"chain",
916 5,
917 0,
918 0,
919 0,
920 0,
921 0,
922 0
923 };
924
925 args.virt = (cell_t)virt;
926 args.size = size;
927 args.entry = (cell_t)entry;
928 args.arg = (cell_t)arg;
929 args.len = len;
930 openfirmware(&args);
931}
932#else
933void
934OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
935{
936 /*
937 * This is a REALLY dirty hack till the firmware gets this going
938 */
939#if 0
939 if (size > 0)
940 OF_release(virt, size);
940 if (size > 0)
941 OF_release(virt, size);
942#endif
941
942 entry(0, 0, openfirmware, arg, len);
943}
944#endif
943
944 entry(0, 0, openfirmware, arg, len);
945}
946#endif