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