Merge from vendor branch DIFFUTILS:
[dragonfly.git] / sys / boot / ofw / libofw / openfirm.c
1 /*
2  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
3  * Copyright (C) 1995, 1996 TooLs GmbH.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by TooLs GmbH.
17  * 4. The name of TooLs GmbH may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 /*
32  * Copyright (C) 2000 Benno Rice.
33  * All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  *
44  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
45  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
49  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
50  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
52  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
53  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54  *
55  * $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $
56  * $FreeBSD: src/sys/boot/ofw/libofw/openfirm.c,v 1.7 2002/07/18 12:39:02 benno Exp $
57  * $DragonFly: src/sys/boot/ofw/libofw/openfirm.c,v 1.1 2003/11/10 06:08:37 dillon Exp $
58  */
59
60 #include <machine/stdarg.h>
61
62 #include <stand.h>
63
64 #include "openfirm.h"
65
66 int (*openfirmware)(void *);
67
68 static ihandle_t stdin;
69 static ihandle_t stdout;
70
71 ihandle_t mmu;
72 ihandle_t memory;
73
74 /* Initialiaser */
75
76 void
77 OF_init(int (*openfirm)(void *))
78 {
79         phandle_t       chosen;
80
81         openfirmware = openfirm;
82
83         chosen = OF_finddevice("/chosen");
84         OF_getprop(chosen, "memory", &memory, sizeof(memory));
85         if (memory == 0)
86                 panic("failed to get memory ihandle");
87         OF_getprop(chosen, "mmu", &mmu, sizeof(mmu));
88         if (mmu == 0)
89                 panic("failed to get mmu ihandle");
90 }
91
92 /*
93  * Generic functions
94  */
95
96 /* Test to see if a service exists. */
97 int
98 OF_test(char *name)
99 {
100         static struct {
101                 cell_t  name;
102                 cell_t  nargs;
103                 cell_t  nreturns;
104                 cell_t  service;
105                 cell_t  missing;
106         } args = {
107                 (cell_t)"test",
108                 1,
109                 1,
110                 0,
111                 0
112         };
113
114         args.service = (cell_t)name;
115         if (openfirmware(&args) == -1)
116                 return -1;
117         return (int)args.missing;
118 }
119
120 /* Return firmware millisecond count. */
121 int
122 OF_milliseconds()
123 {
124         static struct {
125                 cell_t  name;
126                 cell_t  nargs;
127                 cell_t  nreturns;
128                 cell_t  ms;
129         } args = {
130                 (cell_t)"milliseconds",
131                 0,
132                 1,
133                 0
134         };
135         
136         openfirmware(&args);
137         return (int)args.ms;
138 }
139
140 /*
141  * Device tree functions
142  */
143
144 /* Return the next sibling of this node or 0. */
145 phandle_t
146 OF_peer(phandle_t node)
147 {
148         static struct {
149                 cell_t          name;
150                 cell_t          nargs;
151                 cell_t          nreturns;
152                 cell_t          node;
153                 cell_t          next;
154         } args = {
155                 (cell_t)"peer",
156                 1,
157                 1,
158                 0,
159                 0
160         };
161
162         args.node = (u_int)node;
163         if (openfirmware(&args) == -1)
164                 return -1;
165         return (phandle_t)args.next;
166 }
167
168 /* Return the first child of this node or 0. */
169 phandle_t
170 OF_child(phandle_t node)
171 {
172         static struct {
173                 cell_t          name;
174                 cell_t          nargs;
175                 cell_t          nreturns;
176                 cell_t          node;
177                 cell_t          child;
178         } args = {
179                 (cell_t)"child",
180                 1,
181                 1,
182                 0,
183                 0
184         };
185
186         args.node = (u_int)node;
187         if (openfirmware(&args) == -1)
188                 return -1;
189         return (phandle_t)args.child;
190 }
191
192 /* Return the parent of this node or 0. */
193 phandle_t
194 OF_parent(phandle_t node)
195 {
196         static struct {
197                 cell_t          name;
198                 cell_t          nargs;
199                 cell_t          nreturns;
200                 cell_t          node;
201                 cell_t          parent;
202         } args = {
203                 (cell_t)"parent",
204                 1,
205                 1,
206                 0,
207                 0
208         };
209
210         args.node = (u_int)node;
211         if (openfirmware(&args) == -1)
212                 return -1;
213         return (phandle_t)args.parent;
214 }
215
216 /* Return the package handle that corresponds to an instance handle. */
217 phandle_t
218 OF_instance_to_package(ihandle_t instance)
219 {
220         static struct {
221                 cell_t  name;
222                 cell_t  nargs;
223                 cell_t  nreturns;
224                 cell_t  instance;
225                 cell_t  package;
226         } args = {
227                 (cell_t)"instance-to-package",
228                 1,
229                 1,
230                 0,
231                 0
232         };
233         
234         args.instance = (u_int)instance;
235         if (openfirmware(&args) == -1)
236                 return -1;
237         return (phandle_t)args.package;
238 }
239
240 /* Get the length of a property of a package. */
241 int
242 OF_getproplen(phandle_t package, char *propname)
243 {
244         static struct {
245                 cell_t  name;
246                 cell_t  nargs;
247                 cell_t  nreturns;
248                 cell_t  package;
249                 cell_t  propname;
250                 cell_t  proplen;
251         } args = {
252                 (cell_t)"getproplen",
253                 2,
254                 1,
255                 0,
256                 0,
257                 0
258         };
259
260         args.package = (u_int)package;
261         args.propname = (cell_t)propname;
262         if (openfirmware(&args) == -1)
263                 return -1;
264         return (int)args.proplen;
265 }
266
267 /* Get the value of a property of a package. */
268 int
269 OF_getprop(phandle_t package, char *propname, void *buf, int buflen)
270 {
271         static struct {
272                 cell_t          name;
273                 cell_t          nargs;
274                 cell_t          nreturns;
275                 cell_t          package;
276                 cell_t          propname;
277                 cell_t          buf;
278                 cell_t          buflen;
279                 cell_t          size;
280         } args = {
281                 (cell_t)"getprop",
282                 4,
283                 1,
284                 0,
285                 0,
286                 0,
287                 0,
288                 0
289         };
290         
291         args.package = (u_int)package;
292         args.propname = (cell_t)propname;
293         args.buf = (cell_t)buf;
294         args.buflen = (u_int)buflen;
295         if (openfirmware(&args) == -1)
296                 return -1;
297         return (int)args.size;
298 }
299
300 /* Get the next property of a package. */
301 int
302 OF_nextprop(phandle_t package, char *previous, char *buf)
303 {
304         static struct {
305                 cell_t          name;
306                 cell_t          nargs;
307                 cell_t          nreturns;
308                 cell_t          package;
309                 cell_t          previous;
310                 cell_t          buf;
311                 cell_t          flag;
312         } args = {
313                 (cell_t)"nextprop",
314                 3,
315                 1,
316                 0,
317                 0,
318                 0,
319                 0
320         };
321
322         args.package = (u_int)package;
323         args.previous = (cell_t)previous;
324         args.buf = (cell_t)buf;
325         if (openfirmware(&args) == -1)
326                 return -1;
327         return (int)args.flag;
328 }
329
330 /* Set the value of a property of a package. */
331 /* XXX Has a bug on FirePower */
332 int
333 OF_setprop(phandle_t package, char *propname, void *buf, int len)
334 {
335         static struct {
336                 cell_t          name;
337                 cell_t          nargs;
338                 cell_t          nreturns;
339                 cell_t          package;
340                 cell_t          propname;
341                 cell_t          buf;
342                 cell_t          len;
343                 cell_t          size;
344         } args = {
345                 (cell_t)"setprop",
346                 4,
347                 1,
348                 0,
349                 0,
350                 0,
351                 0,
352                 0
353         };
354         
355         args.package = (u_int)package;
356         args.propname = (cell_t)propname;
357         args.buf = (cell_t)buf;
358         args.len = (u_int)len;
359         if (openfirmware(&args) == -1)
360                 return -1;
361         return (int)args.size;
362 }
363
364 /* Convert a device specifier to a fully qualified pathname. */
365 int
366 OF_canon(const char *device, char *buf, int len)
367 {
368         static struct {
369                 cell_t  name;
370                 cell_t  nargs;
371                 cell_t  nreturns;
372                 cell_t  device;
373                 cell_t  buf;
374                 cell_t  len;
375                 cell_t  size;
376         } args = {
377                 (cell_t)"canon",
378                 3,
379                 1,
380                 0,
381                 0,
382                 0,
383                 0
384         };
385         
386         args.device = (cell_t)device;
387         args.buf = (cell_t)buf;
388         args.len = (cell_t)len;
389         if (openfirmware(&args) == -1)
390                 return -1;
391         return (int)args.size;
392 }
393
394 /* Return a package handle for the specified device. */
395 phandle_t
396 OF_finddevice(const char *device)
397 {
398         int i;
399         static struct {
400                 cell_t          name;
401                 cell_t          nargs;
402                 cell_t          nreturns;
403                 cell_t          device;
404                 cell_t          package;
405         } args = {
406                 (cell_t)"finddevice",
407                 1,
408                 1,
409                 0,
410                 0
411         };      
412         
413         args.device = (cell_t)device;
414         if (openfirmware(&args) == -1)
415                 return -1;
416
417         return (phandle_t)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                 0,
437                 0,
438                 0,
439                 0
440         };
441
442         args.instance = (u_int)instance;
443         args.buf = (cell_t)buf;
444         args.len = (u_int)len;
445         if (openfirmware(&args) == -1)
446                 return -1;
447         return (int)args.size;
448 }
449
450 /* Return the fully qualified pathname corresponding to a package. */
451 int
452 OF_package_to_path(phandle_t package, char *buf, int len)
453 {
454         static struct {
455                 cell_t          name;
456                 cell_t          nargs;
457                 cell_t          nreturns;
458                 cell_t          package;
459                 cell_t          buf;
460                 cell_t          len;
461                 cell_t          size;
462         } args = {
463                 (cell_t)"package-to-path",
464                 3,
465                 1,
466                 0,
467                 0,
468                 0,
469                 0
470         };
471
472         args.package = (u_int)package;
473         args.buf = (cell_t)buf;
474         args.len = (u_int)len;
475         if (openfirmware(&args) == -1)
476                 return -1;
477         return (int)args.size;
478 }
479
480 /*  Call the method in the scope of a given instance. */
481 int
482 OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
483 {
484         va_list ap;
485         static struct {
486                 cell_t          name;
487                 cell_t          nargs;
488                 cell_t          nreturns;
489                 cell_t          method;
490                 cell_t          instance;
491                 cell_t          args_n_results[12];
492         } args = {
493                 (cell_t)"call-method",
494                 2,
495                 1,
496                 0,
497                 0,
498                 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
499         };
500         int *ip, n;
501
502         if (nargs > 6)
503                 return -1;
504         args.nargs = nargs + 2;
505         args.nreturns = nreturns + 1;
506         args.method = (cell_t)method;
507         args.instance = (u_int)instance;
508         va_start(ap, nreturns);
509         for (ip = (int *)(args.args_n_results + (n = nargs)); --n >= 0;)
510                 *--ip = va_arg(ap, int);
511
512         if (openfirmware(&args) == -1)
513                 return -1;
514         if (args.args_n_results[nargs])
515                 return (int)args.args_n_results[nargs];
516         for (ip = (int *)(args.args_n_results + nargs + (n = args.nreturns));
517             --n > 0;)
518                 *va_arg(ap, int *) = *--ip;
519         va_end(ap);
520         return 0;
521 }
522
523 /*
524  * Device I/O functions.
525  */
526
527 /* Open an instance for a device. */
528 ihandle_t
529 OF_open(char *device)
530 {
531         static struct {
532                 cell_t          name;
533                 cell_t          nargs;
534                 cell_t          nreturns;
535                 cell_t          device;
536                 cell_t          instance;
537         } args = {
538                 (cell_t)"open",
539                 1,
540                 1,
541                 0,
542                 0
543         };
544         
545         args.device = (cell_t)device;
546         if (openfirmware(&args) == -1 || args.instance == 0) {
547                 return -1;
548         }
549         return (ihandle_t)args.instance;
550 }
551
552 /* Close an instance. */
553 void
554 OF_close(ihandle_t instance)
555 {
556         static struct {
557                 cell_t          name;
558                 cell_t          nargs;
559                 cell_t          nreturns;
560                 cell_t          instance;
561         } args = {
562                 (cell_t)"close",
563                 1,
564                 0,
565                 0
566         };
567         
568         args.instance = (u_int)instance;
569         openfirmware(&args);
570 }
571
572 /* Read from an instance. */
573 int
574 OF_read(ihandle_t instance, void *addr, int len)
575 {
576         static struct {
577                 cell_t          name;
578                 cell_t          nargs;
579                 cell_t          nreturns;
580                 cell_t          instance;
581                 cell_t          addr;
582                 cell_t          len;
583                 cell_t          actual;
584         } args = {
585                 (cell_t)"read",
586                 3,
587                 1,
588                 0,
589                 0,
590                 0,
591                 0
592         };
593
594         args.instance = (u_int)instance;
595         args.addr = (cell_t)addr;
596         args.len = (u_int)len;
597
598 #if defined(OPENFIRM_DEBUG)
599         printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
600             args.instance, args.addr, args.len);
601 #endif
602
603         if (openfirmware(&args) == -1)
604                 return -1;
605
606 #if defined(OPENFIRM_DEBUG)
607         printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
608             args.instance, args.addr, args.len, args.actual);
609 #endif
610
611         return (int)args.actual;
612 }
613
614 /* Write to an instance. */
615 int
616 OF_write(ihandle_t instance, void *addr, int len)
617 {
618         static struct {
619                 cell_t          name;
620                 cell_t          nargs;
621                 cell_t          nreturns;
622                 cell_t          instance;
623                 cell_t          addr;
624                 cell_t          len;
625                 cell_t          actual;
626         } args = {
627                 (cell_t)"write",
628                 3,
629                 1,
630                 0,
631                 0,
632                 0,
633                 0
634         };
635
636         args.instance = (u_int)instance;
637         args.addr = (cell_t)addr;
638         args.len = (u_int)len;
639         if (openfirmware(&args) == -1)
640                 return -1;
641         return (int)args.actual;
642 }
643
644 /* Seek to a position. */
645 int
646 OF_seek(ihandle_t instance, u_int64_t pos)
647 {
648         static struct {
649                 cell_t          name;
650                 cell_t          nargs;
651                 cell_t          nreturns;
652                 cell_t          instance;
653                 cell_t          poshi;
654                 cell_t          poslo;
655                 cell_t          status;
656         } args = {
657                 (cell_t)"seek",
658                 3,
659                 1,
660                 0,
661                 0,
662                 0,
663                 0
664         };
665         
666         args.instance = (u_int)instance;
667         args.poshi = pos >> 32;
668         args.poslo = pos;
669         if (openfirmware(&args) == -1)
670                 return -1;
671         return (int)args.status;
672 }
673
674 /*
675  * Memory functions.
676  */
677
678 /* Claim an area of memory. */
679 void *
680 OF_claim(void *virt, u_int size, u_int align)
681 {
682         static struct {
683                 cell_t  name;
684                 cell_t  nargs;
685                 cell_t  nreturns;
686                 cell_t  virt;
687                 cell_t  size;
688                 cell_t  align;
689                 cell_t  baseaddr;
690         } args = {
691                 (cell_t)"claim",
692                 3,
693                 1,
694                 0,
695                 0,
696                 0,
697                 0
698         };
699
700         args.virt = (cell_t)virt;
701         args.size = size;
702         args.align = align;
703         if (openfirmware(&args) == -1)
704                 return (void *)-1;
705         return (void *)args.baseaddr;
706 }
707
708 /* Allocate an area of physical memory */
709 vm_offset_t
710 OF_claim_virt(vm_offset_t virt, size_t size, int align)
711 {
712         static struct {
713                 cell_t  name;
714                 cell_t  nargs;
715                 cell_t  nret;
716                 cell_t  method;
717                 cell_t  ihandle;
718                 cell_t  align;
719                 cell_t  size;
720                 cell_t  virt;
721                 cell_t  status;
722                 cell_t  ret;
723         } args = {
724                 (cell_t)"call-method",
725                 5,
726                 2,
727                 (cell_t)"claim",
728                 0,
729                 0,
730                 0,
731                 0,
732                 0,      /* ret */
733                 0,
734         };
735
736         args.ihandle = mmu;
737         args.align = align;
738         args.size = size;
739         args.virt = virt;
740
741         if (openfirmware(&args) == -1)
742                 return (vm_offset_t)-1;
743
744         return (vm_offset_t)args.ret;
745 }
746
747 /* Allocate an area of physical memory */
748 void *
749 OF_alloc_phys(size_t size, int align)
750 {
751         static struct {
752                 cell_t  name;
753                 cell_t  nargs;
754                 cell_t  nret;
755                 cell_t  method;
756                 cell_t  ihandle;
757                 cell_t  align;
758                 cell_t  size;
759                 cell_t  status;
760                 cell_t  phys_hi;
761                 cell_t  phys_low;
762         } args = {
763                 (cell_t)"call-method",
764                 4,
765                 3,
766                 (cell_t)"claim",
767                 0,
768                 0,
769                 0,
770                 0,      /* ret */
771                 0,
772                 0,
773         };
774
775         args.ihandle = memory;
776         args.size = size;
777         args.align = align;
778
779         if (openfirmware(&args) == -1)
780                 return (void *)-1;
781
782         return (void *)(args.phys_hi << 32 | args.phys_low);
783 }
784
785 /* Release an area of memory. */
786 void
787 OF_release(void *virt, u_int size)
788 {
789         static struct {
790                 cell_t  name;
791                 cell_t  nargs;
792                 cell_t  nreturns;
793                 cell_t  virt;
794                 cell_t  size;
795         } args = {
796                 (cell_t)"release",
797                 2,
798                 0,
799                 0,
800                 0
801         };
802         
803         args.virt = (cell_t)virt;
804         args.size = size;
805         openfirmware(&args);
806 }
807
808 /* Release an area of physical memory. */
809 void
810 OF_release_phys(vm_offset_t phys, u_int size)
811 {
812         static struct {
813                 cell_t  name;
814                 cell_t  nargs;
815                 cell_t  nret;
816                 cell_t  method;
817                 cell_t  ihandle;
818                 cell_t  size;
819                 cell_t  phys_hi;
820                 cell_t  phys_lo;
821         } args = {
822                 (cell_t)"call-method",
823                 5,
824                 0,
825                 (cell_t)"release",
826                 0,
827                 0,
828                 0,
829                 0
830         };
831
832         args.ihandle = memory;
833         args.phys_hi = (u_int32_t)(phys >> 32);
834         args.phys_lo = (u_int32_t)phys;
835         args.size = size;
836         openfirmware(&args);
837 }
838
839 /*
840  * Control transfer functions.
841  */
842
843 /* Reset the system and call "boot <bootspec>". */
844 void
845 OF_boot(char *bootspec)
846 {
847         static struct {
848                 cell_t  name;
849                 cell_t  nargs;
850                 cell_t  nreturns;
851                 cell_t  bootspec;
852         } args = {
853                 (cell_t)"boot",
854                 1,
855                 0,
856                 0
857         };
858
859         args.bootspec = (cell_t)bootspec;
860         openfirmware(&args);
861         for (;;);                       /* just in case */
862 }
863
864 /* Suspend and drop back to the OpenFirmware interface. */
865 void
866 OF_enter()
867 {
868         static struct {
869                 cell_t  name;
870                 cell_t  nargs;
871                 cell_t  nreturns;
872         } args = {
873                 (cell_t)"enter",
874                 0,
875                 0
876         };
877
878         openfirmware(&args);
879 }
880
881 /* Shut down and drop back to the OpenFirmware interface. */
882 void
883 OF_exit()
884 {
885         static struct {
886                 cell_t  name;
887                 cell_t  nargs;
888                 cell_t  nreturns;
889         } args = {
890                 (cell_t)"exit",
891                 0,
892                 0
893         };
894
895         openfirmware(&args);
896         for (;;);                       /* just in case */
897 }
898
899 /* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
900 #ifdef  __notyet__
901 void
902 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
903 {
904         static struct {
905                 cell_t  name;
906                 cell_t  nargs;
907                 cell_t  nreturns;
908                 cell_t  virt;
909                 cell_t  size;
910                 cell_t  entry;
911                 cell_t  arg;
912                 cell_t  len;
913         } args = {
914                 (cell_t)"chain",
915                 5,
916                 0,
917                 0,
918                 0,
919                 0,
920                 0,
921                 0
922         };
923
924         args.virt = (cell_t)virt;
925         args.size = size;
926         args.entry = (cell_t)entry;
927         args.arg = (cell_t)arg;
928         args.len = len;
929         openfirmware(&args);
930 }
931 #else
932 void
933 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
934 {
935         /*
936          * This is a REALLY dirty hack till the firmware gets this going
937          */
938         if (size > 0)
939                 OF_release(virt, size);
940
941         entry(0, 0, openfirmware, arg, len);
942 }
943 #endif