1 /* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */
4 * SPDX-License-Identifier:BSD-4-Clause AND BSD-2-Clause
6 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
7 * Copyright (C) 1995, 1996 TooLs GmbH.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by TooLs GmbH.
21 * 4. The name of TooLs GmbH may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
30 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 * Copyright (C) 2000 Benno Rice.
37 * All rights reserved.
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
48 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
49 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
50 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
53 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
54 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
55 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
56 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
57 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 #include <sys/cdefs.h>
61 #include <sys/endian.h>
62 #include <sys/param.h>
63 #include <sys/kernel.h>
65 #include <sys/mutex.h>
66 #include <sys/systm.h>
69 #include <vm/vm_page.h>
72 #include <machine/bus.h>
73 #include <machine/md_var.h>
74 #include <machine/ofw_machdep.h>
75 #include <machine/stdarg.h>
77 #include <dev/ofw/openfirm.h>
78 #include <dev/ofw/ofwvar.h>
81 static int ofw_real_init(ofw_t, void *openfirm);
82 static int ofw_real_test(ofw_t, const char *name);
83 static phandle_t ofw_real_peer(ofw_t, phandle_t node);
84 static phandle_t ofw_real_child(ofw_t, phandle_t node);
85 static phandle_t ofw_real_parent(ofw_t, phandle_t node);
86 static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
87 static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
88 const char *propname);
89 static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
90 void *buf, size_t buflen);
91 static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
93 static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
94 const void *buf, size_t len);
95 static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
96 static phandle_t ofw_real_finddevice(ofw_t, const char *device);
97 static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
99 static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
101 static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
102 int nargs, int nreturns, cell_t *args_and_returns);
103 static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns,
105 static ihandle_t ofw_real_open(ofw_t, const char *device);
106 static void ofw_real_close(ofw_t, ihandle_t instance);
107 static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
108 static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
110 static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
111 static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
112 static void ofw_real_release(ofw_t, void *virt, size_t size);
113 static void ofw_real_enter(ofw_t);
114 static void ofw_real_exit(ofw_t);
116 static ofw_method_t ofw_real_methods[] = {
117 OFWMETHOD(ofw_init, ofw_real_init),
118 OFWMETHOD(ofw_peer, ofw_real_peer),
119 OFWMETHOD(ofw_child, ofw_real_child),
120 OFWMETHOD(ofw_parent, ofw_real_parent),
121 OFWMETHOD(ofw_instance_to_package, ofw_real_instance_to_package),
122 OFWMETHOD(ofw_getproplen, ofw_real_getproplen),
123 OFWMETHOD(ofw_getprop, ofw_real_getprop),
124 OFWMETHOD(ofw_nextprop, ofw_real_nextprop),
125 OFWMETHOD(ofw_setprop, ofw_real_setprop),
126 OFWMETHOD(ofw_canon, ofw_real_canon),
127 OFWMETHOD(ofw_finddevice, ofw_real_finddevice),
128 OFWMETHOD(ofw_instance_to_path, ofw_real_instance_to_path),
129 OFWMETHOD(ofw_package_to_path, ofw_real_package_to_path),
131 OFWMETHOD(ofw_test, ofw_real_test),
132 OFWMETHOD(ofw_call_method, ofw_real_call_method),
133 OFWMETHOD(ofw_interpret, ofw_real_interpret),
134 OFWMETHOD(ofw_open, ofw_real_open),
135 OFWMETHOD(ofw_close, ofw_real_close),
136 OFWMETHOD(ofw_read, ofw_real_read),
137 OFWMETHOD(ofw_write, ofw_real_write),
138 OFWMETHOD(ofw_seek, ofw_real_seek),
139 OFWMETHOD(ofw_claim, ofw_real_claim),
140 OFWMETHOD(ofw_release, ofw_real_release),
141 OFWMETHOD(ofw_enter, ofw_real_enter),
142 OFWMETHOD(ofw_exit, ofw_real_exit),
146 static ofw_def_t ofw_real = {
153 static ofw_def_t ofw_32bit = {
160 static MALLOC_DEFINE(M_OFWREAL, "ofwreal",
161 "Open Firmware Real Mode Bounce Page");
163 static int (*openfirmware)(void *);
165 static vm_offset_t of_bounce_phys;
166 static caddr_t of_bounce_virt;
167 static off_t of_bounce_offset;
168 static size_t of_bounce_size;
170 #define IN(x) htobe32(x)
171 #define OUT(x) be32toh(x)
174 * To be able to use OFW console on PPC, that requires real mode OFW,
175 * the mutex that guards the mapping/unmapping of virtual to physical
176 * buffers (of_real_mtx) must be of SPIN type. This is needed because
177 * kernel console first locks a SPIN mutex before calling OFW real.
178 * By default, of_real_mtx is a sleepable mutex. To make it of SPIN
179 * type, use the following tunnable:
180 * machdep.ofw.mtx_spin=1
182 * Besides that, a few more tunables are needed to select and use the
183 * OFW console with real mode OFW.
185 * In order to disable the use of OFW FrameBuffer and fallback to the
189 * To disable the use of FDT (that doesn't support OFW read/write methods)
190 * and use real OFW instead, unset the following loader variable:
193 * OFW is put in quiesce state in early kernel boot, which usually disables
194 * OFW read/write capabilities (in QEMU write continue to work, but
195 * read doesn't). To avoid OFW quiesce, use:
196 * debug.quiesce_ofw=0
198 * Note that disabling OFW quiesce can cause conflicts between kernel and
199 * OFW trying to control the same hardware. Thus, it must be used with care.
200 * Some conflicts can be avoided by disabling kernel drivers with hints.
201 * For instance, to disable a xhci controller and an USB keyboard connected
202 * to it, that may be already being used for input by OFW, use:
203 * hint.xhci.0.disabled=1
206 static struct mtx of_bounce_mtx;
207 static struct mtx of_spin_mtx;
208 static struct mtx *of_real_mtx;
209 static void (*of_mtx_lock)(void);
210 static void (*of_mtx_unlock)(void);
212 extern int ofw_real_mode;
215 * After the VM is up, allocate a wired, low memory bounce page.
218 static void ofw_real_bounce_alloc(void *);
220 SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY,
221 ofw_real_bounce_alloc, NULL);
224 ofw_real_mtx_lock_spin(void)
226 mtx_lock_spin(of_real_mtx);
230 ofw_real_mtx_lock(void)
232 mtx_lock(of_real_mtx);
236 ofw_real_mtx_unlock_spin(void)
238 mtx_unlock_spin(of_real_mtx);
242 ofw_real_mtx_unlock(void)
244 mtx_unlock(of_real_mtx);
251 of_bounce_offset = 0;
261 ofw_real_bounce_alloc(void *junk)
266 * Check that ofw_real is actually in use before allocating wads
267 * of memory. Do this by checking if our mutex has been set up.
269 if (!mtx_initialized(&of_bounce_mtx))
273 * Allocate a page of contiguous, wired physical memory that can
274 * fit into a 32-bit address space and accessed from real mode.
276 temp = contigmalloc(4 * PAGE_SIZE, M_OFWREAL, 0, 0,
277 ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
280 panic("%s: Not able to allocated contiguous memory\n", __func__);
282 mtx_lock(&of_bounce_mtx);
284 of_bounce_virt = temp;
286 of_bounce_phys = vtophys(of_bounce_virt);
287 of_bounce_size = 4 * PAGE_SIZE;
290 * For virtual-mode OF, direct map this physical address so that
291 * we have a 32-bit virtual address to give OF.
294 if (!ofw_real_mode && (!hw_direct_map || DMAP_BASE_ADDRESS != 0))
295 pmap_kenter(of_bounce_phys, of_bounce_phys);
297 mtx_unlock(&of_bounce_mtx);
301 ofw_real_map(const void *buf, size_t len)
303 static char emergency_buffer[255];
306 mtx_assert(of_real_mtx, MA_OWNED);
308 if (of_bounce_virt == NULL) {
310 * If we haven't set up the MMU, then buf is guaranteed
311 * to be accessible to OF, because the only memory we
312 * can use right now is memory mapped by firmware.
314 if (!pmap_bootstrapped)
315 return (cell_t)((uintptr_t)buf & ~DMAP_BASE_ADDRESS);
318 * XXX: It is possible for us to get called before the VM has
319 * come online, but after the MMU is up. We don't have the
320 * bounce buffer yet, but can no longer presume a 1:1 mapping.
321 * Copy into the emergency buffer, and reset at the end.
323 of_bounce_virt = emergency_buffer;
324 of_bounce_phys = (vm_offset_t)of_bounce_virt &
326 of_bounce_size = sizeof(emergency_buffer);
330 * Make sure the bounce page offset satisfies any reasonable
331 * alignment constraint.
333 of_bounce_offset += sizeof(register_t) -
334 (of_bounce_offset % sizeof(register_t));
336 if (of_bounce_offset + len > of_bounce_size) {
337 panic("Oversize Open Firmware call!");
342 memcpy(of_bounce_virt + of_bounce_offset, buf, len);
346 phys = of_bounce_phys + of_bounce_offset;
348 of_bounce_offset += len;
354 ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
356 mtx_assert(of_real_mtx, MA_OWNED);
358 if (of_bounce_virt == NULL)
364 memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
370 ofw_real_init(ofw_t ofw, void *openfirm)
374 openfirmware = (int (*)(void *))openfirm;
375 mtx_init(&of_bounce_mtx, "OF Bounce Page", NULL, MTX_DEF);
378 TUNABLE_INT_FETCH("machdep.ofw.mtx_spin", &mtx_spin);
380 mtx_init(&of_spin_mtx, "OF Real", NULL, MTX_SPIN);
381 of_real_mtx = &of_spin_mtx;
382 of_mtx_lock = ofw_real_mtx_lock_spin;
383 of_mtx_unlock = ofw_real_mtx_unlock_spin;
385 of_real_mtx = &of_bounce_mtx;
386 of_mtx_lock = ofw_real_mtx_lock;
387 of_mtx_unlock = ofw_real_mtx_unlock;
390 of_bounce_virt = NULL;
398 /* Test to see if a service exists. */
400 ofw_real_test(ofw_t ofw, const char *name)
411 args.name = IN((cell_t)(uintptr_t)"test");
413 args.nreturns = IN(1);
417 args.service = IN(ofw_real_map(name, strlen(name) + 1));
418 argsptr = ofw_real_map(&args, sizeof(args));
419 if (args.service == 0 || openfirmware((void *)argsptr) == -1) {
423 ofw_real_unmap(argsptr, &args, sizeof(args));
425 return (OUT(args.missing));
429 * Device tree functions
432 /* Return the next sibling of this node or 0. */
434 ofw_real_peer(ofw_t ofw, phandle_t node)
445 args.name = IN((cell_t)(uintptr_t)"peer");
447 args.nreturns = IN(1);
449 args.node = IN(node);
451 argsptr = ofw_real_map(&args, sizeof(args));
452 if (openfirmware((void *)argsptr) == -1) {
456 ofw_real_unmap(argsptr, &args, sizeof(args));
458 return (OUT(args.next));
461 /* Return the first child of this node or 0. */
463 ofw_real_child(ofw_t ofw, phandle_t node)
474 args.name = IN((cell_t)(uintptr_t)"child");
476 args.nreturns = IN(1);
478 args.node = IN(node);
480 argsptr = ofw_real_map(&args, sizeof(args));
481 if (openfirmware((void *)argsptr) == -1) {
485 ofw_real_unmap(argsptr, &args, sizeof(args));
487 return (OUT(args.child));
490 /* Return the parent of this node or 0. */
492 ofw_real_parent(ofw_t ofw, phandle_t node)
503 args.name = IN((cell_t)(uintptr_t)"parent");
505 args.nreturns = IN(1);
507 args.node = IN(node);
509 argsptr = ofw_real_map(&args, sizeof(args));
510 if (openfirmware((void *)argsptr) == -1) {
514 ofw_real_unmap(argsptr, &args, sizeof(args));
516 return (OUT(args.parent));
519 /* Return the package handle that corresponds to an instance handle. */
521 ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
532 args.name = IN((cell_t)(uintptr_t)"instance-to-package");
534 args.nreturns = IN(1);
536 args.instance = IN(instance);
538 argsptr = ofw_real_map(&args, sizeof(args));
539 if (openfirmware((void *)argsptr) == -1) {
543 ofw_real_unmap(argsptr, &args, sizeof(args));
545 return (OUT(args.package));
548 /* Get the length of a property of a package. */
550 ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
562 args.name = IN((cell_t)(uintptr_t)"getproplen");
564 args.nreturns = IN(1);
568 args.package = IN(package);
569 args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
570 argsptr = ofw_real_map(&args, sizeof(args));
571 if (args.propname == 0 || openfirmware((void *)argsptr) == -1) {
575 ofw_real_unmap(argsptr, &args, sizeof(args));
577 return ((ssize_t)(int32_t)OUT(args.proplen));
580 /* Get the value of a property of a package. */
582 ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
597 args.name = IN((cell_t)(uintptr_t)"getprop");
599 args.nreturns = IN(1);
603 args.package = IN(package);
604 args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
605 args.buf = IN(ofw_real_map(buf, buflen));
606 args.buflen = IN(buflen);
607 argsptr = ofw_real_map(&args, sizeof(args));
608 if (args.propname == 0 || args.buf == 0 ||
609 openfirmware((void *)argsptr) == -1) {
613 ofw_real_unmap(argsptr, &args, sizeof(args));
614 ofw_real_unmap(OUT(args.buf), buf, buflen);
617 return ((ssize_t)(int32_t)OUT(args.size));
620 /* Get the next property of a package. */
622 ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
623 char *buf, size_t size)
636 args.name = IN((cell_t)(uintptr_t)"nextprop");
638 args.nreturns = IN(1);
642 args.package = IN(package);
643 args.previous = IN(ofw_real_map(previous, (previous != NULL) ? (strlen(previous) + 1) : 0));
644 args.buf = IN(ofw_real_map(buf, size));
645 argsptr = ofw_real_map(&args, sizeof(args));
646 if (args.buf == 0 || openfirmware((void *)argsptr) == -1) {
650 ofw_real_unmap(argsptr, &args, sizeof(args));
651 ofw_real_unmap(OUT(args.buf), buf, size);
654 return (OUT(args.flag));
657 /* Set the value of a property of a package. */
658 /* XXX Has a bug on FirePower */
660 ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
661 const void *buf, size_t len)
675 args.name = IN((cell_t)(uintptr_t)"setprop");
677 args.nreturns = IN(1);
681 args.package = IN(package);
682 args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
683 args.buf = IN(ofw_real_map(buf, len));
685 argsptr = ofw_real_map(&args, sizeof(args));
686 if (args.propname == 0 || args.buf == 0 ||
687 openfirmware((void *)argsptr) == -1) {
691 ofw_real_unmap(argsptr, &args, sizeof(args));
693 return (OUT(args.size));
696 /* Convert a device specifier to a fully qualified pathname. */
698 ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
711 args.name = IN((cell_t)(uintptr_t)"canon");
713 args.nreturns = IN(1);
717 args.device = IN(ofw_real_map(device, strlen(device) + 1));
718 args.buf = IN(ofw_real_map(buf, len));
720 argsptr = ofw_real_map(&args, sizeof(args));
721 if (args.device == 0 || args.buf == 0 ||
722 openfirmware((void *)argsptr) == -1) {
726 ofw_real_unmap(argsptr, &args, sizeof(args));
727 ofw_real_unmap(OUT(args.buf), buf, len);
730 return ((ssize_t)(int32_t)OUT(args.size));
733 /* Return a package handle for the specified device. */
735 ofw_real_finddevice(ofw_t ofw, const char *device)
746 args.name = IN((cell_t)(uintptr_t)"finddevice");
748 args.nreturns = IN(1);
752 args.device = IN(ofw_real_map(device, strlen(device) + 1));
753 argsptr = ofw_real_map(&args, sizeof(args));
754 if (args.device == 0 ||
755 openfirmware((void *)argsptr) == -1) {
759 ofw_real_unmap(argsptr, &args, sizeof(args));
761 return (OUT(args.package));
764 /* Return the fully qualified pathname corresponding to an instance. */
766 ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
779 args.name = IN((cell_t)(uintptr_t)"instance-to-path");
781 args.nreturns = IN(1);
785 args.instance = IN(instance);
786 args.buf = IN(ofw_real_map(buf, len));
788 argsptr = ofw_real_map(&args, sizeof(args));
790 openfirmware((void *)argsptr) == -1) {
794 ofw_real_unmap(argsptr, &args, sizeof(args));
795 ofw_real_unmap(OUT(args.buf), buf, len);
798 return ((ssize_t)(int32_t)OUT(args.size));
801 /* Return the fully qualified pathname corresponding to a package. */
803 ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
816 args.name = IN((cell_t)(uintptr_t)"package-to-path");
818 args.nreturns = IN(1);
822 args.package = IN(package);
823 args.buf = IN(ofw_real_map(buf, len));
825 argsptr = ofw_real_map(&args, sizeof(args));
827 openfirmware((void *)argsptr) == -1) {
831 ofw_real_unmap(argsptr, &args, sizeof(args));
832 ofw_real_unmap(OUT(args.buf), buf, len);
835 return ((ssize_t)(int32_t)OUT(args.size));
838 /* Call the method in the scope of a given instance. */
840 ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
841 int nargs, int nreturns, cell_t *args_and_returns)
850 cell_t args_n_results[12];
855 args.name = IN((cell_t)(uintptr_t)"call-method");
857 args.nreturns = IN(1);
863 args.nargs = IN(nargs + 2);
864 args.nreturns = IN(nreturns + 1);
865 args.method = IN(ofw_real_map(method, strlen(method) + 1));
866 args.instance = IN(instance);
868 ap = args_and_returns;
869 for (cp = args.args_n_results + (n = nargs); --n >= 0;)
871 argsptr = ofw_real_map(&args, sizeof(args));
872 if (args.method == 0 ||
873 openfirmware((void *)argsptr) == -1) {
877 ofw_real_unmap(argsptr, &args, sizeof(args));
879 if (OUT(args.args_n_results[nargs]))
880 return (OUT(args.args_n_results[nargs]));
881 for (cp = args.args_n_results + nargs + (n = OUT(args.nreturns)); --n > 0;)
882 *(ap++) = OUT(*--cp);
887 ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
899 args.name = IN((cell_t)(uintptr_t)"interpret");
903 args.nreturns = IN(++nreturns);
904 args.slot[i++] = IN(ofw_real_map(cmd, strlen(cmd) + 1));
905 argsptr = ofw_real_map(&args, sizeof(args));
906 if (openfirmware((void *)argsptr) == -1) {
910 ofw_real_unmap(argsptr, &args, sizeof(args));
912 status = OUT(args.slot[i++]);
913 while (i < 1 + nreturns)
914 returns[j++] = OUT(args.slot[i++]);
919 * Device I/O functions
922 /* Open an instance for a device. */
924 ofw_real_open(ofw_t ofw, const char *device)
935 args.name = IN((cell_t)(uintptr_t)"open");
937 args.nreturns = IN(1);
941 args.device = IN(ofw_real_map(device, strlen(device) + 1));
942 argsptr = ofw_real_map(&args, sizeof(args));
943 if (args.device == 0 || openfirmware((void *)argsptr) == -1
944 || args.instance == 0) {
948 ofw_real_unmap(argsptr, &args, sizeof(args));
950 return (OUT(args.instance));
953 /* Close an instance. */
955 ofw_real_close(ofw_t ofw, ihandle_t instance)
965 args.name = IN((cell_t)(uintptr_t)"close");
967 args.nreturns = IN(0);
968 args.instance = IN(instance);
970 argsptr = ofw_real_map(&args, sizeof(args));
971 openfirmware((void *)argsptr);
975 /* Read from an instance. */
977 ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
990 args.name = IN((cell_t)(uintptr_t)"read");
992 args.nreturns = IN(1);
996 args.instance = IN(instance);
997 args.addr = IN(ofw_real_map(addr, len));
999 argsptr = ofw_real_map(&args, sizeof(args));
1000 if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
1004 ofw_real_unmap(argsptr, &args, sizeof(args));
1005 ofw_real_unmap(OUT(args.addr), addr, len);
1008 return ((ssize_t)(int32_t)OUT(args.actual));
1011 /* Write to an instance. */
1013 ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
1015 vm_offset_t argsptr;
1026 args.name = IN((cell_t)(uintptr_t)"write");
1028 args.nreturns = IN(1);
1032 args.instance = IN(instance);
1033 args.addr = IN(ofw_real_map(addr, len));
1035 argsptr = ofw_real_map(&args, sizeof(args));
1036 if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
1040 ofw_real_unmap(argsptr, &args, sizeof(args));
1042 return ((ssize_t)(int32_t)OUT(args.actual));
1045 /* Seek to a position. */
1047 ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
1049 vm_offset_t argsptr;
1060 args.name = IN((cell_t)(uintptr_t)"seek");
1062 args.nreturns = IN(1);
1064 args.instance = IN(instance);
1065 args.poshi = IN(pos >> 32);
1066 args.poslo = IN(pos);
1068 argsptr = ofw_real_map(&args, sizeof(args));
1069 if (openfirmware((void *)argsptr) == -1) {
1073 ofw_real_unmap(argsptr, &args, sizeof(args));
1075 return (OUT(args.status));
1082 /* Claim an area of memory. */
1084 ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
1086 vm_offset_t argsptr;
1097 args.name = IN((cell_t)(uintptr_t)"claim");
1099 args.nreturns = IN(1);
1101 args.virt = IN((cell_t)(uintptr_t)virt);
1102 args.size = IN(size);
1103 args.align = IN(align);
1105 argsptr = ofw_real_map(&args, sizeof(args));
1106 if (openfirmware((void *)argsptr) == -1) {
1108 return ((void *)-1);
1110 ofw_real_unmap(argsptr, &args, sizeof(args));
1112 return ((void *)(uintptr_t)(OUT(args.baseaddr)));
1115 /* Release an area of memory. */
1117 ofw_real_release(ofw_t ofw, void *virt, size_t size)
1119 vm_offset_t argsptr;
1128 args.name = IN((cell_t)(uintptr_t)"release");
1130 args.nreturns = IN(0);
1132 args.virt = IN((cell_t)(uintptr_t)virt);
1133 args.size = IN(size);
1135 argsptr = ofw_real_map(&args, sizeof(args));
1136 openfirmware((void *)argsptr);
1141 * Control transfer functions
1144 /* Suspend and drop back to the Open Firmware interface. */
1146 ofw_real_enter(ofw_t ofw)
1148 vm_offset_t argsptr;
1155 args.name = IN((cell_t)(uintptr_t)"enter");
1157 args.nreturns = IN(0);
1160 argsptr = ofw_real_map(&args, sizeof(args));
1161 openfirmware((void *)argsptr);
1162 /* We may come back. */
1166 /* Shut down and drop back to the Open Firmware interface. */
1168 ofw_real_exit(ofw_t ofw)
1170 vm_offset_t argsptr;
1177 args.name = IN((cell_t)(uintptr_t)"exit");
1179 args.nreturns = IN(0);
1182 argsptr = ofw_real_map(&args, sizeof(args));
1183 openfirmware((void *)argsptr);
1184 for (;;) /* just in case */