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