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