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