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-FreeBSD
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 __FBSDID("$FreeBSD$");
63 #include <sys/endian.h>
64 #include <sys/param.h>
65 #include <sys/kernel.h>
67 #include <sys/mutex.h>
68 #include <sys/systm.h>
71 #include <vm/vm_page.h>
74 #include <machine/bus.h>
75 #include <machine/md_var.h>
76 #include <machine/ofw_machdep.h>
77 #include <machine/stdarg.h>
79 #include <dev/ofw/openfirm.h>
80 #include <dev/ofw/ofwvar.h>
83 static int ofw_real_init(ofw_t, void *openfirm);
84 static int ofw_real_test(ofw_t, const char *name);
85 static phandle_t ofw_real_peer(ofw_t, phandle_t node);
86 static phandle_t ofw_real_child(ofw_t, phandle_t node);
87 static phandle_t ofw_real_parent(ofw_t, phandle_t node);
88 static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
89 static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
90 const char *propname);
91 static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
92 void *buf, size_t buflen);
93 static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
95 static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
96 const void *buf, size_t len);
97 static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
98 static phandle_t ofw_real_finddevice(ofw_t, const char *device);
99 static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
101 static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
103 static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
104 int nargs, int nreturns, cell_t *args_and_returns);
105 static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns,
107 static ihandle_t ofw_real_open(ofw_t, const char *device);
108 static void ofw_real_close(ofw_t, ihandle_t instance);
109 static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
110 static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
112 static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
113 static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
114 static void ofw_real_release(ofw_t, void *virt, size_t size);
115 static void ofw_real_enter(ofw_t);
116 static void ofw_real_exit(ofw_t);
118 static ofw_method_t ofw_real_methods[] = {
119 OFWMETHOD(ofw_init, ofw_real_init),
120 OFWMETHOD(ofw_peer, ofw_real_peer),
121 OFWMETHOD(ofw_child, ofw_real_child),
122 OFWMETHOD(ofw_parent, ofw_real_parent),
123 OFWMETHOD(ofw_instance_to_package, ofw_real_instance_to_package),
124 OFWMETHOD(ofw_getproplen, ofw_real_getproplen),
125 OFWMETHOD(ofw_getprop, ofw_real_getprop),
126 OFWMETHOD(ofw_nextprop, ofw_real_nextprop),
127 OFWMETHOD(ofw_setprop, ofw_real_setprop),
128 OFWMETHOD(ofw_canon, ofw_real_canon),
129 OFWMETHOD(ofw_finddevice, ofw_real_finddevice),
130 OFWMETHOD(ofw_instance_to_path, ofw_real_instance_to_path),
131 OFWMETHOD(ofw_package_to_path, ofw_real_package_to_path),
133 OFWMETHOD(ofw_test, ofw_real_test),
134 OFWMETHOD(ofw_call_method, ofw_real_call_method),
135 OFWMETHOD(ofw_interpret, ofw_real_interpret),
136 OFWMETHOD(ofw_open, ofw_real_open),
137 OFWMETHOD(ofw_close, ofw_real_close),
138 OFWMETHOD(ofw_read, ofw_real_read),
139 OFWMETHOD(ofw_write, ofw_real_write),
140 OFWMETHOD(ofw_seek, ofw_real_seek),
141 OFWMETHOD(ofw_claim, ofw_real_claim),
142 OFWMETHOD(ofw_release, ofw_real_release),
143 OFWMETHOD(ofw_enter, ofw_real_enter),
144 OFWMETHOD(ofw_exit, ofw_real_exit),
148 static ofw_def_t ofw_real = {
155 static ofw_def_t ofw_32bit = {
162 static MALLOC_DEFINE(M_OFWREAL, "ofwreal",
163 "Open Firmware Real Mode Bounce Page");
165 static int (*openfirmware)(void *);
167 static vm_offset_t of_bounce_phys;
168 static caddr_t of_bounce_virt;
169 static off_t of_bounce_offset;
170 static size_t of_bounce_size;
172 #define IN(x) htobe32(x)
173 #define OUT(x) be32toh(x)
176 * To be able to use OFW console on PPC, that requires real mode OFW,
177 * the mutex that guards the mapping/unmapping of virtual to physical
178 * buffers (of_real_mtx) must be of SPIN type. This is needed because
179 * kernel console first locks a SPIN mutex before calling OFW real.
180 * By default, of_real_mtx is a sleepable mutex. To make it of SPIN
181 * type, use the following tunnable:
182 * machdep.ofw.mtx_spin=1
184 * Besides that, a few more tunables are needed to select and use the
185 * OFW console with real mode OFW.
187 * In order to disable the use of OFW FrameBuffer and fallback to the
191 * To disable the use of FDT (that doesn't support OFW read/write methods)
192 * and use real OFW instead, unset the following loader variable:
195 * OFW is put in quiesce state in early kernel boot, which usually disables
196 * OFW read/write capabilities (in QEMU write continue to work, but
197 * read doesn't). To avoid OFW quiesce, use:
198 * debug.quiesce_ofw=0
200 * Note that disabling OFW quiesce can cause conflicts between kernel and
201 * OFW trying to control the same hardware. Thus, it must be used with care.
202 * Some conflicts can be avoided by disabling kernel drivers with hints.
203 * For instance, to disable a xhci controller and an USB keyboard connected
204 * to it, that may be already being used for input by OFW, use:
205 * hint.xhci.0.disabled=1
208 static struct mtx of_bounce_mtx;
209 static struct mtx of_spin_mtx;
210 static struct mtx *of_real_mtx;
211 static void (*of_mtx_lock)(void);
212 static void (*of_mtx_unlock)(void);
214 extern int ofw_real_mode;
217 * After the VM is up, allocate a wired, low memory bounce page.
220 static void ofw_real_bounce_alloc(void *);
222 SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY,
223 ofw_real_bounce_alloc, NULL);
226 ofw_real_mtx_lock_spin(void)
228 mtx_lock_spin(of_real_mtx);
232 ofw_real_mtx_lock(void)
234 mtx_lock(of_real_mtx);
238 ofw_real_mtx_unlock_spin(void)
240 mtx_unlock_spin(of_real_mtx);
244 ofw_real_mtx_unlock(void)
246 mtx_unlock(of_real_mtx);
253 of_bounce_offset = 0;
263 ofw_real_bounce_alloc(void *junk)
268 * Check that ofw_real is actually in use before allocating wads
269 * of memory. Do this by checking if our mutex has been set up.
271 if (!mtx_initialized(&of_bounce_mtx))
275 * Allocate a page of contiguous, wired physical memory that can
276 * fit into a 32-bit address space and accessed from real mode.
278 temp = contigmalloc(4 * PAGE_SIZE, M_OFWREAL, 0, 0,
279 ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
282 panic("%s: Not able to allocated contiguous memory\n", __func__);
284 mtx_lock(&of_bounce_mtx);
286 of_bounce_virt = temp;
288 of_bounce_phys = vtophys(of_bounce_virt);
289 of_bounce_size = 4 * PAGE_SIZE;
292 * For virtual-mode OF, direct map this physical address so that
293 * we have a 32-bit virtual address to give OF.
296 if (!ofw_real_mode && (!hw_direct_map || DMAP_BASE_ADDRESS != 0))
297 pmap_kenter(of_bounce_phys, of_bounce_phys);
299 mtx_unlock(&of_bounce_mtx);
303 ofw_real_map(const void *buf, size_t len)
305 static char emergency_buffer[255];
308 mtx_assert(of_real_mtx, MA_OWNED);
310 if (of_bounce_virt == NULL) {
312 * If we haven't set up the MMU, then buf is guaranteed
313 * to be accessible to OF, because the only memory we
314 * can use right now is memory mapped by firmware.
316 if (!pmap_bootstrapped)
317 return (cell_t)((uintptr_t)buf & ~DMAP_BASE_ADDRESS);
320 * XXX: It is possible for us to get called before the VM has
321 * come online, but after the MMU is up. We don't have the
322 * bounce buffer yet, but can no longer presume a 1:1 mapping.
323 * Copy into the emergency buffer, and reset at the end.
325 of_bounce_virt = emergency_buffer;
326 of_bounce_phys = (vm_offset_t)of_bounce_virt &
328 of_bounce_size = sizeof(emergency_buffer);
332 * Make sure the bounce page offset satisfies any reasonable
333 * alignment constraint.
335 of_bounce_offset += sizeof(register_t) -
336 (of_bounce_offset % sizeof(register_t));
338 if (of_bounce_offset + len > of_bounce_size) {
339 panic("Oversize Open Firmware call!");
344 memcpy(of_bounce_virt + of_bounce_offset, buf, len);
348 phys = of_bounce_phys + of_bounce_offset;
350 of_bounce_offset += len;
356 ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
358 mtx_assert(of_real_mtx, MA_OWNED);
360 if (of_bounce_virt == NULL)
366 memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
372 ofw_real_init(ofw_t ofw, void *openfirm)
376 openfirmware = (int (*)(void *))openfirm;
377 mtx_init(&of_bounce_mtx, "OF Bounce Page", NULL, MTX_DEF);
380 TUNABLE_INT_FETCH("machdep.ofw.mtx_spin", &mtx_spin);
382 mtx_init(&of_spin_mtx, "OF Real", NULL, MTX_SPIN);
383 of_real_mtx = &of_spin_mtx;
384 of_mtx_lock = ofw_real_mtx_lock_spin;
385 of_mtx_unlock = ofw_real_mtx_unlock_spin;
387 of_real_mtx = &of_bounce_mtx;
388 of_mtx_lock = ofw_real_mtx_lock;
389 of_mtx_unlock = ofw_real_mtx_unlock;
392 of_bounce_virt = NULL;
400 /* Test to see if a service exists. */
402 ofw_real_test(ofw_t ofw, const char *name)
413 args.name = IN((cell_t)(uintptr_t)"test");
415 args.nreturns = IN(1);
419 args.service = IN(ofw_real_map(name, strlen(name) + 1));
420 argsptr = ofw_real_map(&args, sizeof(args));
421 if (args.service == 0 || openfirmware((void *)argsptr) == -1) {
425 ofw_real_unmap(argsptr, &args, sizeof(args));
427 return (OUT(args.missing));
431 * Device tree functions
434 /* Return the next sibling of this node or 0. */
436 ofw_real_peer(ofw_t ofw, phandle_t node)
447 args.name = IN((cell_t)(uintptr_t)"peer");
449 args.nreturns = IN(1);
451 args.node = IN(node);
453 argsptr = ofw_real_map(&args, sizeof(args));
454 if (openfirmware((void *)argsptr) == -1) {
458 ofw_real_unmap(argsptr, &args, sizeof(args));
460 return (OUT(args.next));
463 /* Return the first child of this node or 0. */
465 ofw_real_child(ofw_t ofw, phandle_t node)
476 args.name = IN((cell_t)(uintptr_t)"child");
478 args.nreturns = IN(1);
480 args.node = IN(node);
482 argsptr = ofw_real_map(&args, sizeof(args));
483 if (openfirmware((void *)argsptr) == -1) {
487 ofw_real_unmap(argsptr, &args, sizeof(args));
489 return (OUT(args.child));
492 /* Return the parent of this node or 0. */
494 ofw_real_parent(ofw_t ofw, phandle_t node)
505 args.name = IN((cell_t)(uintptr_t)"parent");
507 args.nreturns = IN(1);
509 args.node = IN(node);
511 argsptr = ofw_real_map(&args, sizeof(args));
512 if (openfirmware((void *)argsptr) == -1) {
516 ofw_real_unmap(argsptr, &args, sizeof(args));
518 return (OUT(args.parent));
521 /* Return the package handle that corresponds to an instance handle. */
523 ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
534 args.name = IN((cell_t)(uintptr_t)"instance-to-package");
536 args.nreturns = IN(1);
538 args.instance = IN(instance);
540 argsptr = ofw_real_map(&args, sizeof(args));
541 if (openfirmware((void *)argsptr) == -1) {
545 ofw_real_unmap(argsptr, &args, sizeof(args));
547 return (OUT(args.package));
550 /* Get the length of a property of a package. */
552 ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
564 args.name = IN((cell_t)(uintptr_t)"getproplen");
566 args.nreturns = IN(1);
570 args.package = IN(package);
571 args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
572 argsptr = ofw_real_map(&args, sizeof(args));
573 if (args.propname == 0 || openfirmware((void *)argsptr) == -1) {
577 ofw_real_unmap(argsptr, &args, sizeof(args));
579 return ((ssize_t)(int32_t)OUT(args.proplen));
582 /* Get the value of a property of a package. */
584 ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
599 args.name = IN((cell_t)(uintptr_t)"getprop");
601 args.nreturns = IN(1);
605 args.package = IN(package);
606 args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
607 args.buf = IN(ofw_real_map(buf, buflen));
608 args.buflen = IN(buflen);
609 argsptr = ofw_real_map(&args, sizeof(args));
610 if (args.propname == 0 || args.buf == 0 ||
611 openfirmware((void *)argsptr) == -1) {
615 ofw_real_unmap(argsptr, &args, sizeof(args));
616 ofw_real_unmap(OUT(args.buf), buf, buflen);
619 return ((ssize_t)(int32_t)OUT(args.size));
622 /* Get the next property of a package. */
624 ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
625 char *buf, size_t size)
638 args.name = IN((cell_t)(uintptr_t)"nextprop");
640 args.nreturns = IN(1);
644 args.package = IN(package);
645 args.previous = IN(ofw_real_map(previous, (previous != NULL) ? (strlen(previous) + 1) : 0));
646 args.buf = IN(ofw_real_map(buf, size));
647 argsptr = ofw_real_map(&args, sizeof(args));
648 if (args.buf == 0 || openfirmware((void *)argsptr) == -1) {
652 ofw_real_unmap(argsptr, &args, sizeof(args));
653 ofw_real_unmap(OUT(args.buf), buf, size);
656 return (OUT(args.flag));
659 /* Set the value of a property of a package. */
660 /* XXX Has a bug on FirePower */
662 ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
663 const void *buf, size_t len)
677 args.name = IN((cell_t)(uintptr_t)"setprop");
679 args.nreturns = IN(1);
683 args.package = IN(package);
684 args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
685 args.buf = IN(ofw_real_map(buf, len));
687 argsptr = ofw_real_map(&args, sizeof(args));
688 if (args.propname == 0 || args.buf == 0 ||
689 openfirmware((void *)argsptr) == -1) {
693 ofw_real_unmap(argsptr, &args, sizeof(args));
695 return (OUT(args.size));
698 /* Convert a device specifier to a fully qualified pathname. */
700 ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
713 args.name = IN((cell_t)(uintptr_t)"canon");
715 args.nreturns = IN(1);
719 args.device = IN(ofw_real_map(device, strlen(device) + 1));
720 args.buf = IN(ofw_real_map(buf, len));
722 argsptr = ofw_real_map(&args, sizeof(args));
723 if (args.device == 0 || args.buf == 0 ||
724 openfirmware((void *)argsptr) == -1) {
728 ofw_real_unmap(argsptr, &args, sizeof(args));
729 ofw_real_unmap(OUT(args.buf), buf, len);
732 return ((ssize_t)(int32_t)OUT(args.size));
735 /* Return a package handle for the specified device. */
737 ofw_real_finddevice(ofw_t ofw, const char *device)
748 args.name = IN((cell_t)(uintptr_t)"finddevice");
750 args.nreturns = IN(1);
754 args.device = IN(ofw_real_map(device, strlen(device) + 1));
755 argsptr = ofw_real_map(&args, sizeof(args));
756 if (args.device == 0 ||
757 openfirmware((void *)argsptr) == -1) {
761 ofw_real_unmap(argsptr, &args, sizeof(args));
763 return (OUT(args.package));
766 /* Return the fully qualified pathname corresponding to an instance. */
768 ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
781 args.name = IN((cell_t)(uintptr_t)"instance-to-path");
783 args.nreturns = IN(1);
787 args.instance = IN(instance);
788 args.buf = IN(ofw_real_map(buf, len));
790 argsptr = ofw_real_map(&args, sizeof(args));
792 openfirmware((void *)argsptr) == -1) {
796 ofw_real_unmap(argsptr, &args, sizeof(args));
797 ofw_real_unmap(OUT(args.buf), buf, len);
800 return ((ssize_t)(int32_t)OUT(args.size));
803 /* Return the fully qualified pathname corresponding to a package. */
805 ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
818 args.name = IN((cell_t)(uintptr_t)"package-to-path");
820 args.nreturns = IN(1);
824 args.package = IN(package);
825 args.buf = IN(ofw_real_map(buf, len));
827 argsptr = ofw_real_map(&args, sizeof(args));
829 openfirmware((void *)argsptr) == -1) {
833 ofw_real_unmap(argsptr, &args, sizeof(args));
834 ofw_real_unmap(OUT(args.buf), buf, len);
837 return ((ssize_t)(int32_t)OUT(args.size));
840 /* Call the method in the scope of a given instance. */
842 ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
843 int nargs, int nreturns, cell_t *args_and_returns)
852 cell_t args_n_results[12];
857 args.name = IN((cell_t)(uintptr_t)"call-method");
859 args.nreturns = IN(1);
865 args.nargs = IN(nargs + 2);
866 args.nreturns = IN(nreturns + 1);
867 args.method = IN(ofw_real_map(method, strlen(method) + 1));
868 args.instance = IN(instance);
870 ap = args_and_returns;
871 for (cp = args.args_n_results + (n = nargs); --n >= 0;)
873 argsptr = ofw_real_map(&args, sizeof(args));
874 if (args.method == 0 ||
875 openfirmware((void *)argsptr) == -1) {
879 ofw_real_unmap(argsptr, &args, sizeof(args));
881 if (OUT(args.args_n_results[nargs]))
882 return (OUT(args.args_n_results[nargs]));
883 for (cp = args.args_n_results + nargs + (n = OUT(args.nreturns)); --n > 0;)
884 *(ap++) = OUT(*--cp);
889 ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
901 args.name = IN((cell_t)(uintptr_t)"interpret");
905 args.nreturns = IN(++nreturns);
906 args.slot[i++] = IN(ofw_real_map(cmd, strlen(cmd) + 1));
907 argsptr = ofw_real_map(&args, sizeof(args));
908 if (openfirmware((void *)argsptr) == -1) {
912 ofw_real_unmap(argsptr, &args, sizeof(args));
914 status = OUT(args.slot[i++]);
915 while (i < 1 + nreturns)
916 returns[j++] = OUT(args.slot[i++]);
921 * Device I/O functions
924 /* Open an instance for a device. */
926 ofw_real_open(ofw_t ofw, const char *device)
937 args.name = IN((cell_t)(uintptr_t)"open");
939 args.nreturns = IN(1);
943 args.device = IN(ofw_real_map(device, strlen(device) + 1));
944 argsptr = ofw_real_map(&args, sizeof(args));
945 if (args.device == 0 || openfirmware((void *)argsptr) == -1
946 || args.instance == 0) {
950 ofw_real_unmap(argsptr, &args, sizeof(args));
952 return (OUT(args.instance));
955 /* Close an instance. */
957 ofw_real_close(ofw_t ofw, ihandle_t instance)
967 args.name = IN((cell_t)(uintptr_t)"close");
969 args.nreturns = IN(0);
970 args.instance = IN(instance);
972 argsptr = ofw_real_map(&args, sizeof(args));
973 openfirmware((void *)argsptr);
977 /* Read from an instance. */
979 ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
992 args.name = IN((cell_t)(uintptr_t)"read");
994 args.nreturns = IN(1);
998 args.instance = IN(instance);
999 args.addr = IN(ofw_real_map(addr, len));
1001 argsptr = ofw_real_map(&args, sizeof(args));
1002 if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
1006 ofw_real_unmap(argsptr, &args, sizeof(args));
1007 ofw_real_unmap(OUT(args.addr), addr, len);
1010 return ((ssize_t)(int32_t)OUT(args.actual));
1013 /* Write to an instance. */
1015 ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
1017 vm_offset_t argsptr;
1028 args.name = IN((cell_t)(uintptr_t)"write");
1030 args.nreturns = IN(1);
1034 args.instance = IN(instance);
1035 args.addr = IN(ofw_real_map(addr, len));
1037 argsptr = ofw_real_map(&args, sizeof(args));
1038 if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
1042 ofw_real_unmap(argsptr, &args, sizeof(args));
1044 return ((ssize_t)(int32_t)OUT(args.actual));
1047 /* Seek to a position. */
1049 ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
1051 vm_offset_t argsptr;
1062 args.name = IN((cell_t)(uintptr_t)"seek");
1064 args.nreturns = IN(1);
1066 args.instance = IN(instance);
1067 args.poshi = IN(pos >> 32);
1068 args.poslo = IN(pos);
1070 argsptr = ofw_real_map(&args, sizeof(args));
1071 if (openfirmware((void *)argsptr) == -1) {
1075 ofw_real_unmap(argsptr, &args, sizeof(args));
1077 return (OUT(args.status));
1084 /* Claim an area of memory. */
1086 ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
1088 vm_offset_t argsptr;
1099 args.name = IN((cell_t)(uintptr_t)"claim");
1101 args.nreturns = IN(1);
1103 args.virt = IN((cell_t)(uintptr_t)virt);
1104 args.size = IN(size);
1105 args.align = IN(align);
1107 argsptr = ofw_real_map(&args, sizeof(args));
1108 if (openfirmware((void *)argsptr) == -1) {
1110 return ((void *)-1);
1112 ofw_real_unmap(argsptr, &args, sizeof(args));
1114 return ((void *)(uintptr_t)(OUT(args.baseaddr)));
1117 /* Release an area of memory. */
1119 ofw_real_release(ofw_t ofw, void *virt, size_t size)
1121 vm_offset_t argsptr;
1130 args.name = IN((cell_t)(uintptr_t)"release");
1132 args.nreturns = IN(0);
1134 args.virt = IN((cell_t)(uintptr_t)virt);
1135 args.size = IN(size);
1137 argsptr = ofw_real_map(&args, sizeof(args));
1138 openfirmware((void *)argsptr);
1143 * Control transfer functions
1146 /* Suspend and drop back to the Open Firmware interface. */
1148 ofw_real_enter(ofw_t ofw)
1150 vm_offset_t argsptr;
1157 args.name = IN((cell_t)(uintptr_t)"enter");
1159 args.nreturns = IN(0);
1162 argsptr = ofw_real_map(&args, sizeof(args));
1163 openfirmware((void *)argsptr);
1164 /* We may come back. */
1168 /* Shut down and drop back to the Open Firmware interface. */
1170 ofw_real_exit(ofw_t ofw)
1172 vm_offset_t argsptr;
1179 args.name = IN((cell_t)(uintptr_t)"exit");
1181 args.nreturns = IN(0);
1184 argsptr = ofw_real_map(&args, sizeof(args));
1185 openfirmware((void *)argsptr);
1186 for (;;) /* just in case */