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