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