]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/powerpc/ofw/ofw_real.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / powerpc / ofw / ofw_real.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 <sys/param.h>
62 #include <sys/kernel.h>
63 #include <sys/lock.h>
64 #include <sys/mutex.h>
65 #include <sys/systm.h>
66
67 #include <vm/vm.h>
68 #include <vm/pmap.h>
69
70 #include <machine/stdarg.h>
71 #include <machine/bus.h>
72 #include <machine/pmap.h>
73 #include <machine/ofw_machdep.h>
74
75 #include <dev/ofw/openfirm.h>
76 #include <dev/ofw/ofwvar.h>
77 #include "ofw_if.h"
78
79 static void ofw_real_init(ofw_t, void *openfirm);
80 static int ofw_real_test(ofw_t, const char *name);
81 static phandle_t ofw_real_peer(ofw_t, phandle_t node);
82 static phandle_t ofw_real_child(ofw_t, phandle_t node);
83 static phandle_t ofw_real_parent(ofw_t, phandle_t node);
84 static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
85 static ssize_t ofw_real_getproplen(ofw_t, phandle_t package, 
86     const char *propname);
87 static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname, 
88     void *buf, size_t buflen);
89 static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous, 
90     char *buf, size_t);
91 static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
92     const void *buf, size_t len);
93 static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
94 static phandle_t ofw_real_finddevice(ofw_t, const char *device);
95 static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf, 
96     size_t len);
97 static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf, 
98     size_t len);
99 static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method, 
100     int nargs, int nreturns, unsigned long *args_and_returns);
101 static ihandle_t ofw_real_open(ofw_t, const char *device);
102 static void ofw_real_close(ofw_t, ihandle_t instance);
103 static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
104 static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr, 
105     size_t len);
106 static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
107 static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
108 static void ofw_real_release(ofw_t, void *virt, size_t size);
109 static void ofw_real_enter(ofw_t);
110 static void ofw_real_exit(ofw_t);
111
112 static ofw_method_t ofw_real_methods[] = {
113         OFWMETHOD(ofw_init,                     ofw_real_init),
114         OFWMETHOD(ofw_peer,                     ofw_real_peer),
115         OFWMETHOD(ofw_child,                    ofw_real_child),
116         OFWMETHOD(ofw_parent,                   ofw_real_parent),
117         OFWMETHOD(ofw_instance_to_package,      ofw_real_instance_to_package),
118         OFWMETHOD(ofw_getproplen,               ofw_real_getproplen),
119         OFWMETHOD(ofw_getprop,                  ofw_real_getprop),
120         OFWMETHOD(ofw_nextprop,                 ofw_real_nextprop),
121         OFWMETHOD(ofw_setprop,                  ofw_real_setprop),
122         OFWMETHOD(ofw_canon,                    ofw_real_canon),
123         OFWMETHOD(ofw_finddevice,               ofw_real_finddevice),
124         OFWMETHOD(ofw_instance_to_path,         ofw_real_instance_to_path),
125         OFWMETHOD(ofw_package_to_path,          ofw_real_package_to_path),
126
127         OFWMETHOD(ofw_test,                     ofw_real_test),
128         OFWMETHOD(ofw_call_method,              ofw_real_call_method),
129         OFWMETHOD(ofw_open,                     ofw_real_open),
130         OFWMETHOD(ofw_close,                    ofw_real_close),
131         OFWMETHOD(ofw_read,                     ofw_real_read),
132         OFWMETHOD(ofw_write,                    ofw_real_write),
133         OFWMETHOD(ofw_seek,                     ofw_real_seek),
134         OFWMETHOD(ofw_claim,                    ofw_real_claim),
135         OFWMETHOD(ofw_release,                  ofw_real_release),
136         OFWMETHOD(ofw_enter,                    ofw_real_enter),
137         OFWMETHOD(ofw_exit,                     ofw_real_exit),
138
139         { 0, 0 }
140 };
141
142 static ofw_def_t ofw_real = {
143         OFW_STD_REAL,
144         ofw_real_methods,
145         0
146 };
147 OFW_DEF(ofw_real);
148
149 MALLOC_DEFINE(M_OFWREAL, "ofwreal", "Open Firmware Real Mode Bounce Page");
150
151 static int (*openfirmware)(void *);
152
153 static vm_offset_t      of_bounce_phys;
154 static caddr_t          of_bounce_virt;
155 static off_t            of_bounce_offset;
156 static size_t           of_bounce_size;
157 static struct mtx       of_bounce_mtx;
158
159 /*
160  * After the VM is up, allocate a wired, low memory bounce page.
161  */
162
163 static void ofw_real_bounce_alloc(void *);
164
165 SYSINIT(ofw_real_bounce_alloc, SI_SUB_VM, SI_ORDER_ANY, 
166     ofw_real_bounce_alloc, NULL);
167
168 static void
169 ofw_real_start(void)
170 {
171         mtx_lock(&of_bounce_mtx);
172         of_bounce_offset = 0;
173 }
174         
175 static void
176 ofw_real_stop(void)
177 {
178         mtx_unlock(&of_bounce_mtx);
179 }
180
181 static void
182 ofw_real_bounce_alloc(void *junk)
183 {
184         /*
185          * Check that ofw_real is actually in use before allocating wads 
186          * of memory. Do this by checking if our mutex has been set up.
187          */
188         if (!mtx_initialized(&of_bounce_mtx))
189                 return;
190
191         /*
192          * Allocate a page of contiguous, wired physical memory that can
193          * fit into a 32-bit address space.
194          */
195
196         mtx_lock(&of_bounce_mtx);
197
198         of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0,
199                              0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE);
200         of_bounce_phys = vtophys(of_bounce_virt);
201         of_bounce_size = PAGE_SIZE;
202
203         mtx_unlock(&of_bounce_mtx);
204 }
205
206 static cell_t
207 ofw_real_map(const void *buf, size_t len)
208 {
209         cell_t phys;
210
211         mtx_assert(&of_bounce_mtx, MA_OWNED);
212
213         if (of_bounce_virt == NULL) {
214                 if (!pmap_bootstrapped)
215                         return (cell_t)buf;
216
217                 /*
218                  * XXX: It is possible for us to get called before the VM has
219                  * come online, but after the MMU is up. We don't have the
220                  * bounce buffer yet, but can no longer presume a 1:1 mapping.
221                  * Grab the physical address of the buffer, and hope it is
222                  * in range if this happens.
223                  */
224                 return (cell_t)vtophys(buf);
225         }
226
227         /*
228          * Make sure the bounce page offset satisfies any reasonable
229          * alignment constraint.
230          */
231         of_bounce_offset += of_bounce_offset % sizeof(register_t);
232
233         if (of_bounce_offset + len > of_bounce_size) {
234                 panic("Oversize Open Firmware call!");
235                 return 0;
236         }
237
238         memcpy(of_bounce_virt + of_bounce_offset, buf, len);
239         phys = of_bounce_phys + of_bounce_offset;
240
241         of_bounce_offset += len;
242
243         return phys;
244 }
245
246 static void
247 ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
248 {
249         mtx_assert(&of_bounce_mtx, MA_OWNED);
250
251         if (of_bounce_virt == NULL)
252                 return;
253
254         memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
255 }
256
257 /* Initialiser */
258
259 static void
260 ofw_real_init(ofw_t ofw, void *openfirm)
261 {
262         openfirmware = (int (*)(void *))openfirm;
263
264         mtx_init(&of_bounce_mtx, "OF Bounce Page", MTX_DEF, 0);
265         of_bounce_virt = NULL;
266 }
267
268 /*
269  * Generic functions
270  */
271
272 /* Test to see if a service exists. */
273 static int
274 ofw_real_test(ofw_t ofw, const char *name)
275 {
276         static struct {
277                 cell_t name;
278                 cell_t nargs;
279                 cell_t nreturns;
280                 cell_t service;
281                 cell_t missing;
282         } args = {
283                 (cell_t)"test",
284                 1,
285                 1,
286         };
287
288         ofw_real_start();
289
290         args.service = ofw_real_map(name, strlen(name) + 1);
291         if (args.service == 0 || openfirmware(&args) == -1) {
292                 ofw_real_stop();
293                 return (-1);
294         }
295         ofw_real_stop();
296         return (args.missing);
297 }
298
299 /*
300  * Device tree functions
301  */
302
303 /* Return the next sibling of this node or 0. */
304 static phandle_t
305 ofw_real_peer(ofw_t ofw, phandle_t node)
306 {
307         static struct {
308                 cell_t name;
309                 cell_t nargs;
310                 cell_t nreturns;
311                 cell_t node;
312                 cell_t next;
313         } args = {
314                 (cell_t)"peer",
315                 1,
316                 1,
317         };
318
319         args.node = node;
320         if (openfirmware(&args) == -1)
321                 return (-1);
322         return (args.next);
323 }
324
325 /* Return the first child of this node or 0. */
326 static phandle_t
327 ofw_real_child(ofw_t ofw, phandle_t node)
328 {
329         static struct {
330                 cell_t name;
331                 cell_t nargs;
332                 cell_t nreturns;
333                 cell_t node;
334                 cell_t child;
335         } args = {
336                 (cell_t)"child",
337                 1,
338                 1,
339         };
340
341         args.node = node;
342         if (openfirmware(&args) == -1)
343                 return (-1);
344         return (args.child);
345 }
346
347 /* Return the parent of this node or 0. */
348 static phandle_t
349 ofw_real_parent(ofw_t ofw, phandle_t node)
350 {
351         static struct {
352                 cell_t name;
353                 cell_t nargs;
354                 cell_t nreturns;
355                 cell_t node;
356                 cell_t parent;
357         } args = {
358                 (cell_t)"parent",
359                 1,
360                 1,
361         };
362
363         args.node = node;
364         if (openfirmware(&args) == -1)
365                 return (-1);
366         return (args.parent);
367 }
368
369 /* Return the package handle that corresponds to an instance handle. */
370 static phandle_t
371 ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
372 {
373         static struct {
374                 cell_t name;
375                 cell_t nargs;
376                 cell_t nreturns;
377                 cell_t instance;
378                 cell_t package;
379         } args = {
380                 (cell_t)"instance-to-package",
381                 1,
382                 1,
383         };
384
385         args.instance = instance;
386         if (openfirmware(&args) == -1)
387                 return (-1);
388         return (args.package);
389 }
390
391 /* Get the length of a property of a package. */
392 static ssize_t
393 ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
394 {
395         static struct {
396                 cell_t name;
397                 cell_t nargs;
398                 cell_t nreturns;
399                 cell_t package;
400                 cell_t propname;
401                 cell_t proplen;
402         } args = {
403                 (cell_t)"getproplen",
404                 2,
405                 1,
406         };
407
408         ofw_real_start();
409
410         args.package = package;
411         args.propname = ofw_real_map(propname, strlen(propname) + 1);
412         if (args.propname == 0 || openfirmware(&args) == -1) {
413                 ofw_real_stop();
414                 return (-1);
415         }
416         ofw_real_stop();
417         return (args.proplen);
418 }
419
420 /* Get the value of a property of a package. */
421 static ssize_t
422 ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, 
423     size_t buflen)
424 {
425         static struct {
426                 cell_t name;
427                 cell_t nargs;
428                 cell_t nreturns;
429                 cell_t package;
430                 cell_t propname;
431                 cell_t buf;
432                 cell_t buflen;
433                 cell_t size;
434         } args = {
435                 (cell_t)"getprop",
436                 4,
437                 1,
438         };
439
440         ofw_real_start();
441
442         args.package = package;
443         args.propname = ofw_real_map(propname, strlen(propname) + 1);
444         args.buf = ofw_real_map(buf, buflen);
445         args.buflen = buflen;
446         if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) {
447                 ofw_real_stop();
448                 return (-1);
449         }
450         ofw_real_unmap(args.buf, buf, buflen);
451
452         ofw_real_stop();
453         return (args.size);
454 }
455
456 /* Get the next property of a package. */
457 static int
458 ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous, 
459     char *buf, size_t size)
460 {
461         static struct {
462                 cell_t name;
463                 cell_t nargs;
464                 cell_t nreturns;
465                 cell_t package;
466                 cell_t previous;
467                 cell_t buf;
468                 cell_t flag;
469         } args = {
470                 (cell_t)"nextprop",
471                 3,
472                 1,
473         };
474
475         ofw_real_start();
476
477         args.package = package;
478         args.previous = ofw_real_map(previous, strlen(previous) + 1);
479         args.buf = ofw_real_map(buf, size);
480         if (args.previous == 0 || args.buf == 0 || openfirmware(&args) == -1) {
481                 ofw_real_stop();
482                 return (-1);
483         }
484         ofw_real_unmap(args.buf, buf, size);
485
486         ofw_real_stop();
487         return (args.flag);
488 }
489
490 /* Set the value of a property of a package. */
491 /* XXX Has a bug on FirePower */
492 static int
493 ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
494     const void *buf, size_t len)
495 {
496         static struct {
497                 cell_t name;
498                 cell_t nargs;
499                 cell_t nreturns;
500                 cell_t package;
501                 cell_t propname;
502                 cell_t buf;
503                 cell_t len;
504                 cell_t size;
505         } args = {
506                 (cell_t)"setprop",
507                 4,
508                 1,
509         };
510
511         ofw_real_start();
512
513         args.package = package;
514         args.propname = ofw_real_map(propname, strlen(propname) + 1);
515         args.buf = ofw_real_map(buf, len);
516         args.len = len;
517         if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) {
518                 ofw_real_stop();
519                 return (-1);
520         }
521         ofw_real_stop();
522         return (args.size);
523 }
524
525 /* Convert a device specifier to a fully qualified pathname. */
526 static ssize_t
527 ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
528 {
529         static struct {
530                 cell_t name;
531                 cell_t nargs;
532                 cell_t nreturns;
533                 cell_t device;
534                 cell_t buf;
535                 cell_t len;
536                 cell_t size;
537         } args = {
538                 (cell_t)"canon",
539                 3,
540                 1,
541         };
542
543         ofw_real_start();
544
545         args.device = ofw_real_map(device, strlen(device) + 1);
546         args.buf = ofw_real_map(buf, len);
547         args.len = len;
548         if (args.device == 0 || args.buf == 0 || openfirmware(&args) == -1) {
549                 ofw_real_stop();
550                 return (-1);
551         }
552         ofw_real_unmap(args.buf, buf, len);
553
554         ofw_real_stop();
555         return (args.size);
556 }
557
558 /* Return a package handle for the specified device. */
559 static phandle_t
560 ofw_real_finddevice(ofw_t ofw, const char *device)
561 {
562         static struct {
563                 cell_t name;
564                 cell_t nargs;
565                 cell_t nreturns;
566                 cell_t device;
567                 cell_t package;
568         } args = {
569                 (cell_t)"finddevice",
570                 1,
571                 1,
572         };
573
574         ofw_real_start();
575
576         args.device = ofw_real_map(device, strlen(device) + 1);
577         if (args.device == 0 || openfirmware(&args) == -1) {
578                 ofw_real_stop();
579                 return (-1);
580         }
581         ofw_real_stop();
582         return (args.package);
583 }
584
585 /* Return the fully qualified pathname corresponding to an instance. */
586 static ssize_t
587 ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
588 {
589         static struct {
590                 cell_t name;
591                 cell_t nargs;
592                 cell_t nreturns;
593                 cell_t instance;
594                 cell_t buf;
595                 cell_t len;
596                 cell_t size;
597         } args = {
598                 (cell_t)"instance-to-path",
599                 3,
600                 1,
601         };
602
603         ofw_real_start();
604
605         args.instance = instance;
606         args.buf = ofw_real_map(buf, len);
607         args.len = len;
608         if (args.buf == 0 || openfirmware(&args) == -1) {
609                 ofw_real_stop();
610                 return (-1);
611         }
612         ofw_real_unmap(args.buf, buf, len);
613
614         ofw_real_stop();
615         return (args.size);
616 }
617
618 /* Return the fully qualified pathname corresponding to a package. */
619 static ssize_t
620 ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
621 {
622         static struct {
623                 cell_t name;
624                 cell_t nargs;
625                 cell_t nreturns;
626                 cell_t package;
627                 cell_t buf;
628                 cell_t len;
629                 cell_t size;
630         } args = {
631                 (cell_t)"package-to-path",
632                 3,
633                 1,
634         };
635
636         ofw_real_start();
637
638         args.package = package;
639         args.buf = ofw_real_map(buf, len);
640         args.len = len;
641         if (args.buf == 0 || openfirmware(&args) == -1) {
642                 ofw_real_stop();
643                 return (-1);
644         }
645         ofw_real_unmap(args.buf, buf, len);
646
647         ofw_real_stop();
648         return (args.size);
649 }
650
651 /*  Call the method in the scope of a given instance. */
652 static int
653 ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, 
654     int nargs, int nreturns, unsigned long *args_and_returns)
655 {
656         static struct {
657                 cell_t name;
658                 cell_t nargs;
659                 cell_t nreturns;
660                 cell_t method;
661                 cell_t instance;
662                 cell_t args_n_results[12];
663         } args = {
664                 (cell_t)"call-method",
665                 2,
666                 1,
667         };
668         cell_t *cp;
669         unsigned long *ap;
670         int n;
671
672         if (nargs > 6)
673                 return (-1);
674
675         ofw_real_start();
676         args.nargs = nargs + 2;
677         args.nreturns = nreturns + 1;
678         args.method = ofw_real_map(method, strlen(method) + 1);
679         args.instance = instance;
680
681         ap = args_and_returns;
682         for (cp = args.args_n_results + (n = nargs); --n >= 0;)
683                 *--cp = *(ap++);
684         if (args.method == 0 || openfirmware(&args) == -1) {
685                 ofw_real_stop();
686                 return (-1);
687         }
688         ofw_real_stop();
689         if (args.args_n_results[nargs])
690                 return (args.args_n_results[nargs]);
691         for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
692                 *(ap++) = *--cp;
693         return (0);
694 }
695
696 /*
697  * Device I/O functions
698  */
699
700 /* Open an instance for a device. */
701 static ihandle_t
702 ofw_real_open(ofw_t ofw, const char *device)
703 {
704         static struct {
705                 cell_t name;
706                 cell_t nargs;
707                 cell_t nreturns;
708                 cell_t device;
709                 cell_t instance;
710         } args = {
711                 (cell_t)"open",
712                 1,
713                 1,
714         };
715
716         ofw_real_start();
717
718         args.device = ofw_real_map(device, strlen(device) + 1);
719         if (args.device == 0 || openfirmware(&args) == -1 
720             || args.instance == 0) {
721                 ofw_real_stop();
722                 return (-1);
723         }
724         ofw_real_stop();
725         return (args.instance);
726 }
727
728 /* Close an instance. */
729 static void
730 ofw_real_close(ofw_t ofw, ihandle_t instance)
731 {
732         static struct {
733                 cell_t name;
734                 cell_t nargs;
735                 cell_t nreturns;
736                 cell_t instance;
737         } args = {
738                 (cell_t)"close",
739                 1,
740         };
741
742         args.instance = instance;
743         openfirmware(&args);
744 }
745
746 /* Read from an instance. */
747 static ssize_t
748 ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
749 {
750         static struct {
751                 cell_t name;
752                 cell_t nargs;
753                 cell_t nreturns;
754                 cell_t instance;
755                 cell_t addr;
756                 cell_t len;
757                 cell_t actual;
758         } args = {
759                 (cell_t)"read",
760                 3,
761                 1,
762         };
763
764         ofw_real_start();
765
766         args.instance = instance;
767         args.addr = ofw_real_map(addr, len);
768         args.len = len;
769         if (args.addr == 0 || openfirmware(&args) == -1) {
770                 ofw_real_stop();
771                 return (-1);
772         }
773         ofw_real_unmap(args.addr, addr, len);
774
775         ofw_real_stop();
776         return (args.actual);
777 }
778
779 /* Write to an instance. */
780 static ssize_t
781 ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
782 {
783         static struct {
784                 cell_t name;
785                 cell_t nargs;
786                 cell_t nreturns;
787                 cell_t instance;
788                 cell_t addr;
789                 cell_t len;
790                 cell_t actual;
791         } args = {
792                 (cell_t)"write",
793                 3,
794                 1,
795         };
796
797         ofw_real_start();
798
799         args.instance = instance;
800         args.addr = ofw_real_map(addr, len);
801         args.len = len;
802         if (args.addr == 0 || openfirmware(&args) == -1) {
803                 ofw_real_stop();
804                 return (-1);
805         }
806         ofw_real_stop();
807         return (args.actual);
808 }
809
810 /* Seek to a position. */
811 static int
812 ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
813 {
814         static struct {
815                 cell_t name;
816                 cell_t nargs;
817                 cell_t nreturns;
818                 cell_t instance;
819                 cell_t poshi;
820                 cell_t poslo;
821                 cell_t status;
822         } args = {
823                 (cell_t)"seek",
824                 3,
825                 1,
826         };
827
828         args.instance = instance;
829         args.poshi = pos >> 32;
830         args.poslo = pos;
831         if (openfirmware(&args) == -1)
832                 return (-1);
833         return (args.status);
834 }
835
836 /*
837  * Memory functions
838  */
839
840 /* Claim an area of memory. */
841 static caddr_t
842 ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
843 {
844         static struct {
845                 cell_t name;
846                 cell_t nargs;
847                 cell_t nreturns;
848                 cell_t virt;
849                 cell_t size;
850                 cell_t align;
851                 cell_t baseaddr;
852         } args = {
853                 (cell_t)"claim",
854                 3,
855                 1,
856         };
857
858         args.virt = (cell_t)virt;
859         args.size = size;
860         args.align = align;
861         if (openfirmware(&args) == -1)
862                 return ((void *)-1);
863         return ((void *)args.baseaddr);
864 }
865
866 /* Release an area of memory. */
867 static void
868 ofw_real_release(ofw_t ofw, void *virt, size_t size)
869 {
870         static struct {
871                 cell_t name;
872                 cell_t nargs;
873                 cell_t nreturns;
874                 cell_t virt;
875                 cell_t size;
876         } args = {
877                 (cell_t)"release",
878                 2,
879         };
880
881         args.virt = (cell_t)virt;
882         args.size = size;
883         openfirmware(&args);
884 }
885
886 /*
887  * Control transfer functions
888  */
889
890 /* Suspend and drop back to the Open Firmware interface. */
891 static void
892 ofw_real_enter(ofw_t ofw)
893 {
894         static struct {
895                 cell_t name;
896                 cell_t nargs;
897                 cell_t nreturns;
898         } args = {
899                 (cell_t)"enter",
900         };
901
902         openfirmware(&args);
903         /* We may come back. */
904 }
905
906 /* Shut down and drop back to the Open Firmware interface. */
907 static void
908 ofw_real_exit(ofw_t ofw)
909 {
910         static struct {
911                 cell_t name;
912                 cell_t nargs;
913                 cell_t nreturns;
914         } args = {
915                 (cell_t)"exit",
916         };
917
918         openfirmware(&args);
919         for (;;)                        /* just in case */
920                 ;
921 }
922