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