xref: /freebsd/sys/powerpc/ofw/ofw_real.c (revision b49db827)
18446b206SNathan Whitehorn /*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $	*/
28446b206SNathan Whitehorn 
38446b206SNathan Whitehorn /*-
471e3c308SPedro F. Giffuni  * SPDX-License-Identifier:BSD-4-Clause AND BSD-2-Clause-FreeBSD
571e3c308SPedro F. Giffuni  *
68446b206SNathan Whitehorn  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
78446b206SNathan Whitehorn  * Copyright (C) 1995, 1996 TooLs GmbH.
88446b206SNathan Whitehorn  * All rights reserved.
98446b206SNathan Whitehorn  *
108446b206SNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
118446b206SNathan Whitehorn  * modification, are permitted provided that the following conditions
128446b206SNathan Whitehorn  * are met:
138446b206SNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
148446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
158446b206SNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
168446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
178446b206SNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
188446b206SNathan Whitehorn  * 3. All advertising materials mentioning features or use of this software
198446b206SNathan Whitehorn  *    must display the following acknowledgement:
208446b206SNathan Whitehorn  *	This product includes software developed by TooLs GmbH.
218446b206SNathan Whitehorn  * 4. The name of TooLs GmbH may not be used to endorse or promote products
228446b206SNathan Whitehorn  *    derived from this software without specific prior written permission.
238446b206SNathan Whitehorn  *
248446b206SNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
258446b206SNathan Whitehorn  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
268446b206SNathan Whitehorn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
278446b206SNathan Whitehorn  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
288446b206SNathan Whitehorn  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
298446b206SNathan Whitehorn  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
308446b206SNathan Whitehorn  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
318446b206SNathan Whitehorn  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
328446b206SNathan Whitehorn  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
338446b206SNathan Whitehorn  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
348446b206SNathan Whitehorn  */
358446b206SNathan Whitehorn /*-
368446b206SNathan Whitehorn  * Copyright (C) 2000 Benno Rice.
378446b206SNathan Whitehorn  * All rights reserved.
388446b206SNathan Whitehorn  *
398446b206SNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
408446b206SNathan Whitehorn  * modification, are permitted provided that the following conditions
418446b206SNathan Whitehorn  * are met:
428446b206SNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
438446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
448446b206SNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
458446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
468446b206SNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
478446b206SNathan Whitehorn  *
488446b206SNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
498446b206SNathan Whitehorn  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
508446b206SNathan Whitehorn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
518446b206SNathan Whitehorn  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
528446b206SNathan Whitehorn  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
538446b206SNathan Whitehorn  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
548446b206SNathan Whitehorn  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
558446b206SNathan Whitehorn  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
568446b206SNathan Whitehorn  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
578446b206SNathan Whitehorn  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
588446b206SNathan Whitehorn  */
598446b206SNathan Whitehorn 
608446b206SNathan Whitehorn #include <sys/cdefs.h>
618446b206SNathan Whitehorn __FBSDID("$FreeBSD$");
628446b206SNathan Whitehorn 
63b49db827SBrandon Bergren #include <sys/endian.h>
648446b206SNathan Whitehorn #include <sys/param.h>
658446b206SNathan Whitehorn #include <sys/kernel.h>
668446b206SNathan Whitehorn #include <sys/lock.h>
678446b206SNathan Whitehorn #include <sys/mutex.h>
688446b206SNathan Whitehorn #include <sys/systm.h>
698446b206SNathan Whitehorn 
708446b206SNathan Whitehorn #include <vm/vm.h>
7170d75337SNathan Whitehorn #include <vm/vm_page.h>
728446b206SNathan Whitehorn #include <vm/pmap.h>
738446b206SNathan Whitehorn 
748446b206SNathan Whitehorn #include <machine/bus.h>
7570d75337SNathan Whitehorn #include <machine/md_var.h>
768446b206SNathan Whitehorn #include <machine/ofw_machdep.h>
7770d75337SNathan Whitehorn #include <machine/stdarg.h>
788446b206SNathan Whitehorn 
798446b206SNathan Whitehorn #include <dev/ofw/openfirm.h>
808446b206SNathan Whitehorn #include <dev/ofw/ofwvar.h>
818446b206SNathan Whitehorn #include "ofw_if.h"
828446b206SNathan Whitehorn 
838297758aSRafal Jaworowski static int ofw_real_init(ofw_t, void *openfirm);
848446b206SNathan Whitehorn static int ofw_real_test(ofw_t, const char *name);
858446b206SNathan Whitehorn static phandle_t ofw_real_peer(ofw_t, phandle_t node);
868446b206SNathan Whitehorn static phandle_t ofw_real_child(ofw_t, phandle_t node);
878446b206SNathan Whitehorn static phandle_t ofw_real_parent(ofw_t, phandle_t node);
888446b206SNathan Whitehorn static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
898446b206SNathan Whitehorn static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
908446b206SNathan Whitehorn     const char *propname);
918446b206SNathan Whitehorn static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
928446b206SNathan Whitehorn     void *buf, size_t buflen);
938446b206SNathan Whitehorn static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
948446b206SNathan Whitehorn     char *buf, size_t);
954fc23012SAndriy Gapon static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
964fc23012SAndriy Gapon     const void *buf, size_t len);
978446b206SNathan Whitehorn static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
988446b206SNathan Whitehorn static phandle_t ofw_real_finddevice(ofw_t, const char *device);
998446b206SNathan Whitehorn static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
1008446b206SNathan Whitehorn     size_t len);
1018446b206SNathan Whitehorn static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
1028446b206SNathan Whitehorn     size_t len);
1038446b206SNathan Whitehorn static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
104054e5dcbSNathan Whitehorn     int nargs, int nreturns, cell_t *args_and_returns);
10570d75337SNathan Whitehorn static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns,
106cdb25d82SMarius Strobl     cell_t *returns);
1078446b206SNathan Whitehorn static ihandle_t ofw_real_open(ofw_t, const char *device);
1088446b206SNathan Whitehorn static void ofw_real_close(ofw_t, ihandle_t instance);
1098446b206SNathan Whitehorn static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
1108446b206SNathan Whitehorn static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
1118446b206SNathan Whitehorn     size_t len);
1128446b206SNathan Whitehorn static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
1138446b206SNathan Whitehorn static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
1148446b206SNathan Whitehorn static void ofw_real_release(ofw_t, void *virt, size_t size);
1158446b206SNathan Whitehorn static void ofw_real_enter(ofw_t);
1168446b206SNathan Whitehorn static void ofw_real_exit(ofw_t);
1178446b206SNathan Whitehorn 
1188446b206SNathan Whitehorn static ofw_method_t ofw_real_methods[] = {
1198446b206SNathan Whitehorn 	OFWMETHOD(ofw_init,			ofw_real_init),
1208446b206SNathan Whitehorn 	OFWMETHOD(ofw_peer,			ofw_real_peer),
1218446b206SNathan Whitehorn 	OFWMETHOD(ofw_child,			ofw_real_child),
1228446b206SNathan Whitehorn 	OFWMETHOD(ofw_parent,			ofw_real_parent),
1238446b206SNathan Whitehorn 	OFWMETHOD(ofw_instance_to_package,	ofw_real_instance_to_package),
1248446b206SNathan Whitehorn 	OFWMETHOD(ofw_getproplen,		ofw_real_getproplen),
1258446b206SNathan Whitehorn 	OFWMETHOD(ofw_getprop,			ofw_real_getprop),
1268446b206SNathan Whitehorn 	OFWMETHOD(ofw_nextprop,			ofw_real_nextprop),
1278446b206SNathan Whitehorn 	OFWMETHOD(ofw_setprop,			ofw_real_setprop),
1288446b206SNathan Whitehorn 	OFWMETHOD(ofw_canon,			ofw_real_canon),
1298446b206SNathan Whitehorn 	OFWMETHOD(ofw_finddevice,		ofw_real_finddevice),
1308446b206SNathan Whitehorn 	OFWMETHOD(ofw_instance_to_path,		ofw_real_instance_to_path),
1318446b206SNathan Whitehorn 	OFWMETHOD(ofw_package_to_path,		ofw_real_package_to_path),
1328446b206SNathan Whitehorn 
1338446b206SNathan Whitehorn 	OFWMETHOD(ofw_test,			ofw_real_test),
1348446b206SNathan Whitehorn 	OFWMETHOD(ofw_call_method,		ofw_real_call_method),
13570d75337SNathan Whitehorn 	OFWMETHOD(ofw_interpret,		ofw_real_interpret),
1368446b206SNathan Whitehorn 	OFWMETHOD(ofw_open,			ofw_real_open),
1378446b206SNathan Whitehorn 	OFWMETHOD(ofw_close,			ofw_real_close),
1388446b206SNathan Whitehorn 	OFWMETHOD(ofw_read,			ofw_real_read),
1398446b206SNathan Whitehorn 	OFWMETHOD(ofw_write,			ofw_real_write),
1408446b206SNathan Whitehorn 	OFWMETHOD(ofw_seek,			ofw_real_seek),
1418446b206SNathan Whitehorn 	OFWMETHOD(ofw_claim,			ofw_real_claim),
1428446b206SNathan Whitehorn 	OFWMETHOD(ofw_release,			ofw_real_release),
1438446b206SNathan Whitehorn 	OFWMETHOD(ofw_enter,			ofw_real_enter),
1448446b206SNathan Whitehorn 	OFWMETHOD(ofw_exit,			ofw_real_exit),
1458446b206SNathan Whitehorn 	{ 0, 0 }
1468446b206SNathan Whitehorn };
1478446b206SNathan Whitehorn 
1488446b206SNathan Whitehorn static ofw_def_t ofw_real = {
1498446b206SNathan Whitehorn 	OFW_STD_REAL,
1508446b206SNathan Whitehorn 	ofw_real_methods,
1518446b206SNathan Whitehorn 	0
1528446b206SNathan Whitehorn };
1538446b206SNathan Whitehorn OFW_DEF(ofw_real);
1548446b206SNathan Whitehorn 
15570d75337SNathan Whitehorn static ofw_def_t ofw_32bit = {
15670d75337SNathan Whitehorn 	OFW_STD_32BIT,
15770d75337SNathan Whitehorn 	ofw_real_methods,
15870d75337SNathan Whitehorn 	0
15970d75337SNathan Whitehorn };
16070d75337SNathan Whitehorn OFW_DEF(ofw_32bit);
16170d75337SNathan Whitehorn 
162d745c852SEd Schouten static MALLOC_DEFINE(M_OFWREAL, "ofwreal",
163d745c852SEd Schouten     "Open Firmware Real Mode Bounce Page");
1648446b206SNathan Whitehorn 
1658446b206SNathan Whitehorn static int (*openfirmware)(void *);
1668446b206SNathan Whitehorn 
1678446b206SNathan Whitehorn static vm_offset_t	of_bounce_phys;
1688446b206SNathan Whitehorn static caddr_t		of_bounce_virt;
1698446b206SNathan Whitehorn static off_t		of_bounce_offset;
1708446b206SNathan Whitehorn static size_t		of_bounce_size;
17135f29427SLeandro Lupori 
172b49db827SBrandon Bergren #define IN(x) htobe32(x)
173b49db827SBrandon Bergren #define OUT(x) be32toh(x)
174b49db827SBrandon Bergren 
17535f29427SLeandro Lupori /*
17635f29427SLeandro Lupori  * To be able to use OFW console on PPC, that requires real mode OFW,
17735f29427SLeandro Lupori  * the mutex that guards the mapping/unmapping of virtual to physical
17835f29427SLeandro Lupori  * buffers (of_real_mtx) must be of SPIN type. This is needed because
17935f29427SLeandro Lupori  * kernel console first locks a SPIN mutex before calling OFW real.
18035f29427SLeandro Lupori  * By default, of_real_mtx is a sleepable mutex. To make it of SPIN
18135f29427SLeandro Lupori  * type, use the following tunnable:
18235f29427SLeandro Lupori  * machdep.ofw.mtx_spin=1
18335f29427SLeandro Lupori  *
18435f29427SLeandro Lupori  * Besides that, a few more tunables are needed to select and use the
18535f29427SLeandro Lupori  * OFW console with real mode OFW.
18635f29427SLeandro Lupori  *
18735f29427SLeandro Lupori  * In order to disable the use of OFW FrameBuffer and fallback to the
18835f29427SLeandro Lupori  * OFW console, use:
18935f29427SLeandro Lupori  * hw.ofwfb.disable=1
19035f29427SLeandro Lupori  *
19135f29427SLeandro Lupori  * To disable the use of FDT (that doesn't support OFW read/write methods)
19235f29427SLeandro Lupori  * and use real OFW instead, unset the following loader variable:
19335f29427SLeandro Lupori  * unset usefdt
19435f29427SLeandro Lupori  *
19535f29427SLeandro Lupori  * OFW is put in quiesce state in early kernel boot, which usually disables
19635f29427SLeandro Lupori  * OFW read/write capabilities (in QEMU write continue to work, but
19735f29427SLeandro Lupori  * read doesn't). To avoid OFW quiesce, use:
19835f29427SLeandro Lupori  * debug.quiesce_ofw=0
19935f29427SLeandro Lupori  *
20035f29427SLeandro Lupori  * Note that disabling OFW quiesce can cause conflicts between kernel and
20135f29427SLeandro Lupori  * OFW trying to control the same hardware. Thus, it must be used with care.
20235f29427SLeandro Lupori  * Some conflicts can be avoided by disabling kernel drivers with hints.
20335f29427SLeandro Lupori  * For instance, to disable a xhci controller and an USB keyboard connected
20435f29427SLeandro Lupori  * to it, that may be already being used for input by OFW, use:
20535f29427SLeandro Lupori  * hint.xhci.0.disabled=1
20635f29427SLeandro Lupori  */
20735f29427SLeandro Lupori 
2088446b206SNathan Whitehorn static struct mtx	of_bounce_mtx;
20935f29427SLeandro Lupori static struct mtx	of_spin_mtx;
21035f29427SLeandro Lupori static struct mtx	*of_real_mtx;
21135f29427SLeandro Lupori static void		(*of_mtx_lock)(void);
21235f29427SLeandro Lupori static void		(*of_mtx_unlock)(void);
2138446b206SNathan Whitehorn 
21470d75337SNathan Whitehorn extern int		ofw_real_mode;
21570d75337SNathan Whitehorn 
2168446b206SNathan Whitehorn /*
2178446b206SNathan Whitehorn  * After the VM is up, allocate a wired, low memory bounce page.
2188446b206SNathan Whitehorn  */
2198446b206SNathan Whitehorn 
2208446b206SNathan Whitehorn static void ofw_real_bounce_alloc(void *);
2218446b206SNathan Whitehorn 
22270d75337SNathan Whitehorn SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY,
2238446b206SNathan Whitehorn     ofw_real_bounce_alloc, NULL);
2248446b206SNathan Whitehorn 
2258446b206SNathan Whitehorn static void
22635f29427SLeandro Lupori ofw_real_mtx_lock_spin(void)
22735f29427SLeandro Lupori {
22835f29427SLeandro Lupori 	mtx_lock_spin(of_real_mtx);
22935f29427SLeandro Lupori }
23035f29427SLeandro Lupori 
23135f29427SLeandro Lupori static void
23235f29427SLeandro Lupori ofw_real_mtx_lock(void)
23335f29427SLeandro Lupori {
23435f29427SLeandro Lupori 	mtx_lock(of_real_mtx);
23535f29427SLeandro Lupori }
23635f29427SLeandro Lupori 
23735f29427SLeandro Lupori static void
23835f29427SLeandro Lupori ofw_real_mtx_unlock_spin(void)
23935f29427SLeandro Lupori {
24035f29427SLeandro Lupori 	mtx_unlock_spin(of_real_mtx);
24135f29427SLeandro Lupori }
24235f29427SLeandro Lupori 
24335f29427SLeandro Lupori static void
24435f29427SLeandro Lupori ofw_real_mtx_unlock(void)
24535f29427SLeandro Lupori {
24635f29427SLeandro Lupori 	mtx_unlock(of_real_mtx);
24735f29427SLeandro Lupori }
24835f29427SLeandro Lupori 
24935f29427SLeandro Lupori static void
2508446b206SNathan Whitehorn ofw_real_start(void)
2518446b206SNathan Whitehorn {
25235f29427SLeandro Lupori 	(*of_mtx_lock)();
2538446b206SNathan Whitehorn 	of_bounce_offset = 0;
2548446b206SNathan Whitehorn }
2558446b206SNathan Whitehorn 
2568446b206SNathan Whitehorn static void
2578446b206SNathan Whitehorn ofw_real_stop(void)
2588446b206SNathan Whitehorn {
25935f29427SLeandro Lupori 	(*of_mtx_unlock)();
2608446b206SNathan Whitehorn }
2618446b206SNathan Whitehorn 
2628446b206SNathan Whitehorn static void
2638446b206SNathan Whitehorn ofw_real_bounce_alloc(void *junk)
2648446b206SNathan Whitehorn {
265d6d06708SJustin Hibbits 	caddr_t temp;
266d6d06708SJustin Hibbits 
2678446b206SNathan Whitehorn 	/*
2688446b206SNathan Whitehorn 	 * Check that ofw_real is actually in use before allocating wads
2698446b206SNathan Whitehorn 	 * of memory. Do this by checking if our mutex has been set up.
2708446b206SNathan Whitehorn 	 */
2718446b206SNathan Whitehorn 	if (!mtx_initialized(&of_bounce_mtx))
2728446b206SNathan Whitehorn 		return;
2738446b206SNathan Whitehorn 
2748446b206SNathan Whitehorn 	/*
2758446b206SNathan Whitehorn 	 * Allocate a page of contiguous, wired physical memory that can
27617879090SNathan Whitehorn 	 * fit into a 32-bit address space and accessed from real mode.
2778446b206SNathan Whitehorn 	 */
278d6d06708SJustin Hibbits 	temp = contigmalloc(4 * PAGE_SIZE, M_OFWREAL, 0, 0,
279d6d06708SJustin Hibbits 	    ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
280d6d06708SJustin Hibbits 	    4 * PAGE_SIZE);
281d6d06708SJustin Hibbits 	if (temp == NULL)
282d6d06708SJustin Hibbits 		panic("%s: Not able to allocated contiguous memory\n", __func__);
2838446b206SNathan Whitehorn 
2848446b206SNathan Whitehorn 	mtx_lock(&of_bounce_mtx);
2858446b206SNathan Whitehorn 
286d6d06708SJustin Hibbits 	of_bounce_virt = temp;
28770d75337SNathan Whitehorn 
2888446b206SNathan Whitehorn 	of_bounce_phys = vtophys(of_bounce_virt);
28915b5b0acSJustin Hibbits 	of_bounce_size = 4 * PAGE_SIZE;
2908446b206SNathan Whitehorn 
29170d75337SNathan Whitehorn 	/*
29270d75337SNathan Whitehorn 	 * For virtual-mode OF, direct map this physical address so that
29370d75337SNathan Whitehorn 	 * we have a 32-bit virtual address to give OF.
29470d75337SNathan Whitehorn 	 */
29570d75337SNathan Whitehorn 
296f9edb09dSNathan Whitehorn 	if (!ofw_real_mode && (!hw_direct_map || DMAP_BASE_ADDRESS != 0))
29770d75337SNathan Whitehorn 		pmap_kenter(of_bounce_phys, of_bounce_phys);
29870d75337SNathan Whitehorn 
2998446b206SNathan Whitehorn 	mtx_unlock(&of_bounce_mtx);
3008446b206SNathan Whitehorn }
3018446b206SNathan Whitehorn 
3028446b206SNathan Whitehorn static cell_t
3038446b206SNathan Whitehorn ofw_real_map(const void *buf, size_t len)
3048446b206SNathan Whitehorn {
30570d75337SNathan Whitehorn 	static char emergency_buffer[255];
3068446b206SNathan Whitehorn 	cell_t phys;
3078446b206SNathan Whitehorn 
30835f29427SLeandro Lupori 	mtx_assert(of_real_mtx, MA_OWNED);
3098446b206SNathan Whitehorn 
3108446b206SNathan Whitehorn 	if (of_bounce_virt == NULL) {
31170d75337SNathan Whitehorn 		/*
31270d75337SNathan Whitehorn 		 * If we haven't set up the MMU, then buf is guaranteed
31370d75337SNathan Whitehorn 		 * to be accessible to OF, because the only memory we
31470d75337SNathan Whitehorn 		 * can use right now is memory mapped by firmware.
31570d75337SNathan Whitehorn 		 */
3168446b206SNathan Whitehorn 		if (!pmap_bootstrapped)
317f9edb09dSNathan Whitehorn 			return (cell_t)((uintptr_t)buf & ~DMAP_BASE_ADDRESS);
3188446b206SNathan Whitehorn 
3198446b206SNathan Whitehorn 		/*
3208446b206SNathan Whitehorn 		 * XXX: It is possible for us to get called before the VM has
3218446b206SNathan Whitehorn 		 * come online, but after the MMU is up. We don't have the
3228446b206SNathan Whitehorn 		 * bounce buffer yet, but can no longer presume a 1:1 mapping.
32370d75337SNathan Whitehorn 		 * Copy into the emergency buffer, and reset at the end.
3248446b206SNathan Whitehorn 		 */
32570d75337SNathan Whitehorn 		of_bounce_virt = emergency_buffer;
326f9edb09dSNathan Whitehorn 		of_bounce_phys = (vm_offset_t)of_bounce_virt &
327f9edb09dSNathan Whitehorn 		    ~DMAP_BASE_ADDRESS;
32870d75337SNathan Whitehorn 		of_bounce_size = sizeof(emergency_buffer);
3298446b206SNathan Whitehorn 	}
3308446b206SNathan Whitehorn 
3318446b206SNathan Whitehorn 	/*
3328446b206SNathan Whitehorn 	 * Make sure the bounce page offset satisfies any reasonable
3338446b206SNathan Whitehorn 	 * alignment constraint.
3348446b206SNathan Whitehorn 	 */
335f9edb09dSNathan Whitehorn 	of_bounce_offset += sizeof(register_t) -
336f9edb09dSNathan Whitehorn 	    (of_bounce_offset % sizeof(register_t));
3378446b206SNathan Whitehorn 
3388446b206SNathan Whitehorn 	if (of_bounce_offset + len > of_bounce_size) {
3398446b206SNathan Whitehorn 		panic("Oversize Open Firmware call!");
3408446b206SNathan Whitehorn 		return 0;
3418446b206SNathan Whitehorn 	}
3428446b206SNathan Whitehorn 
343ec664c11SAndreas Tobler 	if (buf != NULL)
3448446b206SNathan Whitehorn 		memcpy(of_bounce_virt + of_bounce_offset, buf, len);
345ec664c11SAndreas Tobler 	else
346ec664c11SAndreas Tobler 		return (0);
347ec664c11SAndreas Tobler 
3488446b206SNathan Whitehorn 	phys = of_bounce_phys + of_bounce_offset;
3498446b206SNathan Whitehorn 
3508446b206SNathan Whitehorn 	of_bounce_offset += len;
3518446b206SNathan Whitehorn 
35270d75337SNathan Whitehorn 	return (phys);
3538446b206SNathan Whitehorn }
3548446b206SNathan Whitehorn 
3558446b206SNathan Whitehorn static void
3568446b206SNathan Whitehorn ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
3578446b206SNathan Whitehorn {
35835f29427SLeandro Lupori 	mtx_assert(of_real_mtx, MA_OWNED);
3598446b206SNathan Whitehorn 
3608446b206SNathan Whitehorn 	if (of_bounce_virt == NULL)
3618446b206SNathan Whitehorn 		return;
3628446b206SNathan Whitehorn 
363ec664c11SAndreas Tobler 	if (physaddr == 0)
364ec664c11SAndreas Tobler 		return;
365ec664c11SAndreas Tobler 
3668446b206SNathan Whitehorn 	memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
3678446b206SNathan Whitehorn }
3688446b206SNathan Whitehorn 
3698446b206SNathan Whitehorn /* Initialiser */
3708446b206SNathan Whitehorn 
3718297758aSRafal Jaworowski static int
3728446b206SNathan Whitehorn ofw_real_init(ofw_t ofw, void *openfirm)
3738446b206SNathan Whitehorn {
37435f29427SLeandro Lupori 	int mtx_spin;
3758446b206SNathan Whitehorn 
37635f29427SLeandro Lupori 	openfirmware = (int (*)(void *))openfirm;
377d01195e3SChristian Brueffer 	mtx_init(&of_bounce_mtx, "OF Bounce Page", NULL, MTX_DEF);
37835f29427SLeandro Lupori 
37935f29427SLeandro Lupori 	mtx_spin = 0;
38035f29427SLeandro Lupori 	TUNABLE_INT_FETCH("machdep.ofw.mtx_spin", &mtx_spin);
38135f29427SLeandro Lupori 	if (mtx_spin) {
38235f29427SLeandro Lupori 		mtx_init(&of_spin_mtx, "OF Real", NULL, MTX_SPIN);
38335f29427SLeandro Lupori 		of_real_mtx = &of_spin_mtx;
38435f29427SLeandro Lupori 		of_mtx_lock = ofw_real_mtx_lock_spin;
38535f29427SLeandro Lupori 		of_mtx_unlock = ofw_real_mtx_unlock_spin;
38635f29427SLeandro Lupori 	} else {
38735f29427SLeandro Lupori 		of_real_mtx = &of_bounce_mtx;
38835f29427SLeandro Lupori 		of_mtx_lock = ofw_real_mtx_lock;
38935f29427SLeandro Lupori 		of_mtx_unlock = ofw_real_mtx_unlock;
39035f29427SLeandro Lupori 	}
39135f29427SLeandro Lupori 
3928446b206SNathan Whitehorn 	of_bounce_virt = NULL;
3938297758aSRafal Jaworowski 	return (0);
3948446b206SNathan Whitehorn }
3958446b206SNathan Whitehorn 
3968446b206SNathan Whitehorn /*
3978446b206SNathan Whitehorn  * Generic functions
3988446b206SNathan Whitehorn  */
3998446b206SNathan Whitehorn 
4008446b206SNathan Whitehorn /* Test to see if a service exists. */
4018446b206SNathan Whitehorn static int
4028446b206SNathan Whitehorn ofw_real_test(ofw_t ofw, const char *name)
4038446b206SNathan Whitehorn {
40470d75337SNathan Whitehorn 	vm_offset_t argsptr;
405d4bccd63SNathan Whitehorn 	struct {
4068446b206SNathan Whitehorn 		cell_t name;
4078446b206SNathan Whitehorn 		cell_t nargs;
4088446b206SNathan Whitehorn 		cell_t nreturns;
4098446b206SNathan Whitehorn 		cell_t service;
4108446b206SNathan Whitehorn 		cell_t missing;
41170d75337SNathan Whitehorn 	} args;
41270d75337SNathan Whitehorn 
413b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"test");
414b49db827SBrandon Bergren 	args.nargs = IN(1);
415b49db827SBrandon Bergren 	args.nreturns = IN(1);
4168446b206SNathan Whitehorn 
4178446b206SNathan Whitehorn 	ofw_real_start();
4188446b206SNathan Whitehorn 
419b49db827SBrandon Bergren 	args.service = IN(ofw_real_map(name, strlen(name) + 1));
42070d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
42170d75337SNathan Whitehorn 	if (args.service == 0 || openfirmware((void *)argsptr) == -1) {
4228446b206SNathan Whitehorn 		ofw_real_stop();
4238446b206SNathan Whitehorn 		return (-1);
4248446b206SNathan Whitehorn 	}
42570d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
4268446b206SNathan Whitehorn 	ofw_real_stop();
427b49db827SBrandon Bergren 	return (OUT(args.missing));
4288446b206SNathan Whitehorn }
4298446b206SNathan Whitehorn 
4308446b206SNathan Whitehorn /*
4318446b206SNathan Whitehorn  * Device tree functions
4328446b206SNathan Whitehorn  */
4338446b206SNathan Whitehorn 
4348446b206SNathan Whitehorn /* Return the next sibling of this node or 0. */
4358446b206SNathan Whitehorn static phandle_t
4368446b206SNathan Whitehorn ofw_real_peer(ofw_t ofw, phandle_t node)
4378446b206SNathan Whitehorn {
43870d75337SNathan Whitehorn 	vm_offset_t argsptr;
439d4bccd63SNathan Whitehorn 	struct {
4408446b206SNathan Whitehorn 		cell_t name;
4418446b206SNathan Whitehorn 		cell_t nargs;
4428446b206SNathan Whitehorn 		cell_t nreturns;
4438446b206SNathan Whitehorn 		cell_t node;
4448446b206SNathan Whitehorn 		cell_t next;
44570d75337SNathan Whitehorn 	} args;
44670d75337SNathan Whitehorn 
447b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"peer");
448b49db827SBrandon Bergren 	args.nargs = IN(1);
449b49db827SBrandon Bergren 	args.nreturns = IN(1);
4508446b206SNathan Whitehorn 
451b49db827SBrandon Bergren 	args.node = IN(node);
45270d75337SNathan Whitehorn 	ofw_real_start();
45370d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
45470d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
45570d75337SNathan Whitehorn 		ofw_real_stop();
45665184f89SNathan Whitehorn 		return (0);
45770d75337SNathan Whitehorn 	}
45870d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
45970d75337SNathan Whitehorn 	ofw_real_stop();
460b49db827SBrandon Bergren 	return (OUT(args.next));
4618446b206SNathan Whitehorn }
4628446b206SNathan Whitehorn 
4638446b206SNathan Whitehorn /* Return the first child of this node or 0. */
4648446b206SNathan Whitehorn static phandle_t
4658446b206SNathan Whitehorn ofw_real_child(ofw_t ofw, phandle_t node)
4668446b206SNathan Whitehorn {
46770d75337SNathan Whitehorn 	vm_offset_t argsptr;
468d4bccd63SNathan Whitehorn 	struct {
4698446b206SNathan Whitehorn 		cell_t name;
4708446b206SNathan Whitehorn 		cell_t nargs;
4718446b206SNathan Whitehorn 		cell_t nreturns;
4728446b206SNathan Whitehorn 		cell_t node;
4738446b206SNathan Whitehorn 		cell_t child;
47470d75337SNathan Whitehorn 	} args;
47570d75337SNathan Whitehorn 
476b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"child");
477b49db827SBrandon Bergren 	args.nargs = IN(1);
478b49db827SBrandon Bergren 	args.nreturns = IN(1);
4798446b206SNathan Whitehorn 
480b49db827SBrandon Bergren 	args.node = IN(node);
48170d75337SNathan Whitehorn 	ofw_real_start();
48270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
48370d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
48470d75337SNathan Whitehorn 		ofw_real_stop();
48565184f89SNathan Whitehorn 		return (0);
48670d75337SNathan Whitehorn 	}
48770d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
48870d75337SNathan Whitehorn 	ofw_real_stop();
489b49db827SBrandon Bergren 	return (OUT(args.child));
4908446b206SNathan Whitehorn }
4918446b206SNathan Whitehorn 
4928446b206SNathan Whitehorn /* Return the parent of this node or 0. */
4938446b206SNathan Whitehorn static phandle_t
4948446b206SNathan Whitehorn ofw_real_parent(ofw_t ofw, phandle_t node)
4958446b206SNathan Whitehorn {
49670d75337SNathan Whitehorn 	vm_offset_t argsptr;
497d4bccd63SNathan Whitehorn 	struct {
4988446b206SNathan Whitehorn 		cell_t name;
4998446b206SNathan Whitehorn 		cell_t nargs;
5008446b206SNathan Whitehorn 		cell_t nreturns;
5018446b206SNathan Whitehorn 		cell_t node;
5028446b206SNathan Whitehorn 		cell_t parent;
50370d75337SNathan Whitehorn 	} args;
50470d75337SNathan Whitehorn 
505b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"parent");
506b49db827SBrandon Bergren 	args.nargs = IN(1);
507b49db827SBrandon Bergren 	args.nreturns = IN(1);
5088446b206SNathan Whitehorn 
509b49db827SBrandon Bergren 	args.node = IN(node);
51070d75337SNathan Whitehorn 	ofw_real_start();
51170d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
51270d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
51370d75337SNathan Whitehorn 		ofw_real_stop();
51465184f89SNathan Whitehorn 		return (0);
51570d75337SNathan Whitehorn 	}
51670d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
51770d75337SNathan Whitehorn 	ofw_real_stop();
518b49db827SBrandon Bergren 	return (OUT(args.parent));
5198446b206SNathan Whitehorn }
5208446b206SNathan Whitehorn 
5218446b206SNathan Whitehorn /* Return the package handle that corresponds to an instance handle. */
5228446b206SNathan Whitehorn static phandle_t
5238446b206SNathan Whitehorn ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
5248446b206SNathan Whitehorn {
52570d75337SNathan Whitehorn 	vm_offset_t argsptr;
526d4bccd63SNathan Whitehorn 	struct {
5278446b206SNathan Whitehorn 		cell_t name;
5288446b206SNathan Whitehorn 		cell_t nargs;
5298446b206SNathan Whitehorn 		cell_t nreturns;
5308446b206SNathan Whitehorn 		cell_t instance;
5318446b206SNathan Whitehorn 		cell_t package;
53270d75337SNathan Whitehorn 	} args;
53370d75337SNathan Whitehorn 
534b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"instance-to-package");
535b49db827SBrandon Bergren 	args.nargs = IN(1);
536b49db827SBrandon Bergren 	args.nreturns = IN(1);
5378446b206SNathan Whitehorn 
538b49db827SBrandon Bergren 	args.instance = IN(instance);
53970d75337SNathan Whitehorn 	ofw_real_start();
54070d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
54170d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
54270d75337SNathan Whitehorn 		ofw_real_stop();
5438446b206SNathan Whitehorn 		return (-1);
54470d75337SNathan Whitehorn 	}
54570d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
54670d75337SNathan Whitehorn 	ofw_real_stop();
547b49db827SBrandon Bergren 	return (OUT(args.package));
5488446b206SNathan Whitehorn }
5498446b206SNathan Whitehorn 
5508446b206SNathan Whitehorn /* Get the length of a property of a package. */
5518446b206SNathan Whitehorn static ssize_t
5528446b206SNathan Whitehorn ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
5538446b206SNathan Whitehorn {
55470d75337SNathan Whitehorn 	vm_offset_t argsptr;
555d4bccd63SNathan Whitehorn 	struct {
5568446b206SNathan Whitehorn 		cell_t name;
5578446b206SNathan Whitehorn 		cell_t nargs;
5588446b206SNathan Whitehorn 		cell_t nreturns;
5598446b206SNathan Whitehorn 		cell_t package;
5608446b206SNathan Whitehorn 		cell_t propname;
56170d75337SNathan Whitehorn 		int32_t proplen;
56270d75337SNathan Whitehorn 	} args;
56370d75337SNathan Whitehorn 
564b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"getproplen");
565b49db827SBrandon Bergren 	args.nargs = IN(2);
566b49db827SBrandon Bergren 	args.nreturns = IN(1);
5678446b206SNathan Whitehorn 
5688446b206SNathan Whitehorn 	ofw_real_start();
5698446b206SNathan Whitehorn 
570b49db827SBrandon Bergren 	args.package = IN(package);
571b49db827SBrandon Bergren 	args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
57270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
57370d75337SNathan Whitehorn 	if (args.propname == 0 || openfirmware((void *)argsptr) == -1) {
5748446b206SNathan Whitehorn 		ofw_real_stop();
5758446b206SNathan Whitehorn 		return (-1);
5768446b206SNathan Whitehorn 	}
57770d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
5788446b206SNathan Whitehorn 	ofw_real_stop();
579b49db827SBrandon Bergren 	return ((ssize_t)(int32_t)OUT(args.proplen));
5808446b206SNathan Whitehorn }
5818446b206SNathan Whitehorn 
5828446b206SNathan Whitehorn /* Get the value of a property of a package. */
5838446b206SNathan Whitehorn static ssize_t
5848446b206SNathan Whitehorn ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
5858446b206SNathan Whitehorn     size_t buflen)
5868446b206SNathan Whitehorn {
58770d75337SNathan Whitehorn 	vm_offset_t argsptr;
588d4bccd63SNathan Whitehorn 	struct {
5898446b206SNathan Whitehorn 		cell_t name;
5908446b206SNathan Whitehorn 		cell_t nargs;
5918446b206SNathan Whitehorn 		cell_t nreturns;
5928446b206SNathan Whitehorn 		cell_t package;
5938446b206SNathan Whitehorn 		cell_t propname;
5948446b206SNathan Whitehorn 		cell_t buf;
5958446b206SNathan Whitehorn 		cell_t buflen;
59670d75337SNathan Whitehorn 		int32_t size;
59770d75337SNathan Whitehorn 	} args;
59870d75337SNathan Whitehorn 
599b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"getprop");
600b49db827SBrandon Bergren 	args.nargs = IN(4);
601b49db827SBrandon Bergren 	args.nreturns = IN(1);
6028446b206SNathan Whitehorn 
6038446b206SNathan Whitehorn 	ofw_real_start();
6048446b206SNathan Whitehorn 
605b49db827SBrandon Bergren 	args.package = IN(package);
606b49db827SBrandon Bergren 	args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
607b49db827SBrandon Bergren 	args.buf = IN(ofw_real_map(buf, buflen));
608b49db827SBrandon Bergren 	args.buflen = IN(buflen);
60970d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
61070d75337SNathan Whitehorn 	if (args.propname == 0 || args.buf == 0 ||
61170d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
6128446b206SNathan Whitehorn 		ofw_real_stop();
6138446b206SNathan Whitehorn 		return (-1);
6148446b206SNathan Whitehorn 	}
61570d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
616b49db827SBrandon Bergren 	ofw_real_unmap(OUT(args.buf), buf, buflen);
6178446b206SNathan Whitehorn 
6188446b206SNathan Whitehorn 	ofw_real_stop();
619b49db827SBrandon Bergren 	return ((ssize_t)(int32_t)OUT(args.size));
6208446b206SNathan Whitehorn }
6218446b206SNathan Whitehorn 
6228446b206SNathan Whitehorn /* Get the next property of a package. */
6238446b206SNathan Whitehorn static int
6248446b206SNathan Whitehorn ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
6258446b206SNathan Whitehorn     char *buf, size_t size)
6268446b206SNathan Whitehorn {
62770d75337SNathan Whitehorn 	vm_offset_t argsptr;
628d4bccd63SNathan Whitehorn 	struct {
6298446b206SNathan Whitehorn 		cell_t name;
6308446b206SNathan Whitehorn 		cell_t nargs;
6318446b206SNathan Whitehorn 		cell_t nreturns;
6328446b206SNathan Whitehorn 		cell_t package;
6338446b206SNathan Whitehorn 		cell_t previous;
6348446b206SNathan Whitehorn 		cell_t buf;
6358446b206SNathan Whitehorn 		cell_t flag;
63670d75337SNathan Whitehorn 	} args;
63770d75337SNathan Whitehorn 
638b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"nextprop");
639b49db827SBrandon Bergren 	args.nargs = IN(3);
640b49db827SBrandon Bergren 	args.nreturns = IN(1);
6418446b206SNathan Whitehorn 
6428446b206SNathan Whitehorn 	ofw_real_start();
6438446b206SNathan Whitehorn 
644b49db827SBrandon Bergren 	args.package = IN(package);
645b49db827SBrandon Bergren 	args.previous = IN(ofw_real_map(previous, (previous != NULL) ? (strlen(previous) + 1) : 0));
646b49db827SBrandon Bergren 	args.buf = IN(ofw_real_map(buf, size));
64770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
648ec664c11SAndreas Tobler 	if (args.buf == 0 || openfirmware((void *)argsptr) == -1) {
6498446b206SNathan Whitehorn 		ofw_real_stop();
6508446b206SNathan Whitehorn 		return (-1);
6518446b206SNathan Whitehorn 	}
65270d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
653b49db827SBrandon Bergren 	ofw_real_unmap(OUT(args.buf), buf, size);
6548446b206SNathan Whitehorn 
6558446b206SNathan Whitehorn 	ofw_real_stop();
656b49db827SBrandon Bergren 	return (OUT(args.flag));
6578446b206SNathan Whitehorn }
6588446b206SNathan Whitehorn 
6598446b206SNathan Whitehorn /* Set the value of a property of a package. */
6608446b206SNathan Whitehorn /* XXX Has a bug on FirePower */
6618446b206SNathan Whitehorn static int
6624fc23012SAndriy Gapon ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
6634fc23012SAndriy Gapon     const void *buf, size_t len)
6648446b206SNathan Whitehorn {
66570d75337SNathan Whitehorn 	vm_offset_t argsptr;
666d4bccd63SNathan Whitehorn 	struct {
6678446b206SNathan Whitehorn 		cell_t name;
6688446b206SNathan Whitehorn 		cell_t nargs;
6698446b206SNathan Whitehorn 		cell_t nreturns;
6708446b206SNathan Whitehorn 		cell_t package;
6718446b206SNathan Whitehorn 		cell_t propname;
6728446b206SNathan Whitehorn 		cell_t buf;
6738446b206SNathan Whitehorn 		cell_t len;
6748446b206SNathan Whitehorn 		cell_t size;
67570d75337SNathan Whitehorn 	} args;
67670d75337SNathan Whitehorn 
677b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"setprop");
678b49db827SBrandon Bergren 	args.nargs = IN(4);
679b49db827SBrandon Bergren 	args.nreturns = IN(1);
6808446b206SNathan Whitehorn 
6818446b206SNathan Whitehorn 	ofw_real_start();
6828446b206SNathan Whitehorn 
683b49db827SBrandon Bergren 	args.package = IN(package);
684b49db827SBrandon Bergren 	args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
685b49db827SBrandon Bergren 	args.buf = IN(ofw_real_map(buf, len));
686b49db827SBrandon Bergren 	args.len = IN(len);
68770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
68870d75337SNathan Whitehorn 	if (args.propname == 0 || args.buf == 0 ||
68970d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
6908446b206SNathan Whitehorn 		ofw_real_stop();
6918446b206SNathan Whitehorn 		return (-1);
6928446b206SNathan Whitehorn 	}
69370d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
6948446b206SNathan Whitehorn 	ofw_real_stop();
695b49db827SBrandon Bergren 	return (OUT(args.size));
6968446b206SNathan Whitehorn }
6978446b206SNathan Whitehorn 
6988446b206SNathan Whitehorn /* Convert a device specifier to a fully qualified pathname. */
6998446b206SNathan Whitehorn static ssize_t
7008446b206SNathan Whitehorn ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
7018446b206SNathan Whitehorn {
70270d75337SNathan Whitehorn 	vm_offset_t argsptr;
703d4bccd63SNathan Whitehorn 	struct {
7048446b206SNathan Whitehorn 		cell_t name;
7058446b206SNathan Whitehorn 		cell_t nargs;
7068446b206SNathan Whitehorn 		cell_t nreturns;
7078446b206SNathan Whitehorn 		cell_t device;
7088446b206SNathan Whitehorn 		cell_t buf;
7098446b206SNathan Whitehorn 		cell_t len;
71070d75337SNathan Whitehorn 		int32_t size;
71170d75337SNathan Whitehorn 	} args;
71270d75337SNathan Whitehorn 
713b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"canon");
714b49db827SBrandon Bergren 	args.nargs = IN(3);
715b49db827SBrandon Bergren 	args.nreturns = IN(1);
7168446b206SNathan Whitehorn 
7178446b206SNathan Whitehorn 	ofw_real_start();
7188446b206SNathan Whitehorn 
719b49db827SBrandon Bergren 	args.device = IN(ofw_real_map(device, strlen(device) + 1));
720b49db827SBrandon Bergren 	args.buf = IN(ofw_real_map(buf, len));
721b49db827SBrandon Bergren 	args.len = IN(len);
72270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
72370d75337SNathan Whitehorn 	if (args.device == 0 || args.buf == 0 ||
72470d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
7258446b206SNathan Whitehorn 		ofw_real_stop();
7268446b206SNathan Whitehorn 		return (-1);
7278446b206SNathan Whitehorn 	}
72870d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
729b49db827SBrandon Bergren 	ofw_real_unmap(OUT(args.buf), buf, len);
7308446b206SNathan Whitehorn 
7318446b206SNathan Whitehorn 	ofw_real_stop();
732b49db827SBrandon Bergren 	return ((ssize_t)(int32_t)OUT(args.size));
7338446b206SNathan Whitehorn }
7348446b206SNathan Whitehorn 
7358446b206SNathan Whitehorn /* Return a package handle for the specified device. */
7368446b206SNathan Whitehorn static phandle_t
7378446b206SNathan Whitehorn ofw_real_finddevice(ofw_t ofw, const char *device)
7388446b206SNathan Whitehorn {
73970d75337SNathan Whitehorn 	vm_offset_t argsptr;
740d4bccd63SNathan Whitehorn 	struct {
7418446b206SNathan Whitehorn 		cell_t name;
7428446b206SNathan Whitehorn 		cell_t nargs;
7438446b206SNathan Whitehorn 		cell_t nreturns;
7448446b206SNathan Whitehorn 		cell_t device;
7458446b206SNathan Whitehorn 		cell_t package;
74670d75337SNathan Whitehorn 	} args;
74770d75337SNathan Whitehorn 
748b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"finddevice");
749b49db827SBrandon Bergren 	args.nargs = IN(1);
750b49db827SBrandon Bergren 	args.nreturns = IN(1);
7518446b206SNathan Whitehorn 
7528446b206SNathan Whitehorn 	ofw_real_start();
7538446b206SNathan Whitehorn 
754b49db827SBrandon Bergren 	args.device = IN(ofw_real_map(device, strlen(device) + 1));
75570d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
75670d75337SNathan Whitehorn 	if (args.device == 0 ||
75770d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
7588446b206SNathan Whitehorn 		ofw_real_stop();
7598446b206SNathan Whitehorn 		return (-1);
7608446b206SNathan Whitehorn 	}
76170d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
7628446b206SNathan Whitehorn 	ofw_real_stop();
763b49db827SBrandon Bergren 	return (OUT(args.package));
7648446b206SNathan Whitehorn }
7658446b206SNathan Whitehorn 
7668446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to an instance. */
7678446b206SNathan Whitehorn static ssize_t
7688446b206SNathan Whitehorn ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
7698446b206SNathan Whitehorn {
77070d75337SNathan Whitehorn 	vm_offset_t argsptr;
771d4bccd63SNathan Whitehorn 	struct {
7728446b206SNathan Whitehorn 		cell_t name;
7738446b206SNathan Whitehorn 		cell_t nargs;
7748446b206SNathan Whitehorn 		cell_t nreturns;
7758446b206SNathan Whitehorn 		cell_t instance;
7768446b206SNathan Whitehorn 		cell_t buf;
7778446b206SNathan Whitehorn 		cell_t len;
77870d75337SNathan Whitehorn 		int32_t size;
77970d75337SNathan Whitehorn 	} args;
78070d75337SNathan Whitehorn 
781b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"instance-to-path");
782b49db827SBrandon Bergren 	args.nargs = IN(3);
783b49db827SBrandon Bergren 	args.nreturns = IN(1);
7848446b206SNathan Whitehorn 
7858446b206SNathan Whitehorn 	ofw_real_start();
7868446b206SNathan Whitehorn 
787b49db827SBrandon Bergren 	args.instance = IN(instance);
788b49db827SBrandon Bergren 	args.buf = IN(ofw_real_map(buf, len));
789b49db827SBrandon Bergren 	args.len = IN(len);
79070d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
79170d75337SNathan Whitehorn 	if (args.buf == 0 ||
79270d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
7938446b206SNathan Whitehorn 		ofw_real_stop();
7948446b206SNathan Whitehorn 		return (-1);
7958446b206SNathan Whitehorn 	}
79670d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
797b49db827SBrandon Bergren 	ofw_real_unmap(OUT(args.buf), buf, len);
7988446b206SNathan Whitehorn 
7998446b206SNathan Whitehorn 	ofw_real_stop();
800b49db827SBrandon Bergren 	return ((ssize_t)(int32_t)OUT(args.size));
8018446b206SNathan Whitehorn }
8028446b206SNathan Whitehorn 
8038446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to a package. */
8048446b206SNathan Whitehorn static ssize_t
8058446b206SNathan Whitehorn ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
8068446b206SNathan Whitehorn {
80770d75337SNathan Whitehorn 	vm_offset_t argsptr;
808d4bccd63SNathan Whitehorn 	struct {
8098446b206SNathan Whitehorn 		cell_t name;
8108446b206SNathan Whitehorn 		cell_t nargs;
8118446b206SNathan Whitehorn 		cell_t nreturns;
8128446b206SNathan Whitehorn 		cell_t package;
8138446b206SNathan Whitehorn 		cell_t buf;
8148446b206SNathan Whitehorn 		cell_t len;
81570d75337SNathan Whitehorn 		int32_t size;
81670d75337SNathan Whitehorn 	} args;
81770d75337SNathan Whitehorn 
818b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"package-to-path");
819b49db827SBrandon Bergren 	args.nargs = IN(3);
820b49db827SBrandon Bergren 	args.nreturns = IN(1);
8218446b206SNathan Whitehorn 
8228446b206SNathan Whitehorn 	ofw_real_start();
8238446b206SNathan Whitehorn 
824b49db827SBrandon Bergren 	args.package = IN(package);
825b49db827SBrandon Bergren 	args.buf = IN(ofw_real_map(buf, len));
826b49db827SBrandon Bergren 	args.len = IN(len);
82770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
82870d75337SNathan Whitehorn 	if (args.buf == 0 ||
82970d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
8308446b206SNathan Whitehorn 		ofw_real_stop();
8318446b206SNathan Whitehorn 		return (-1);
8328446b206SNathan Whitehorn 	}
83370d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
834b49db827SBrandon Bergren 	ofw_real_unmap(OUT(args.buf), buf, len);
8358446b206SNathan Whitehorn 
8368446b206SNathan Whitehorn 	ofw_real_stop();
837b49db827SBrandon Bergren 	return ((ssize_t)(int32_t)OUT(args.size));
8388446b206SNathan Whitehorn }
8398446b206SNathan Whitehorn 
8408446b206SNathan Whitehorn /*  Call the method in the scope of a given instance. */
8418446b206SNathan Whitehorn static int
8428446b206SNathan Whitehorn ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
843054e5dcbSNathan Whitehorn     int nargs, int nreturns, cell_t *args_and_returns)
8448446b206SNathan Whitehorn {
84570d75337SNathan Whitehorn 	vm_offset_t argsptr;
846d4bccd63SNathan Whitehorn 	struct {
8478446b206SNathan Whitehorn 		cell_t name;
8488446b206SNathan Whitehorn 		cell_t nargs;
8498446b206SNathan Whitehorn 		cell_t nreturns;
8508446b206SNathan Whitehorn 		cell_t method;
8518446b206SNathan Whitehorn 		cell_t instance;
8528446b206SNathan Whitehorn 		cell_t args_n_results[12];
85370d75337SNathan Whitehorn 	} args;
854cdb25d82SMarius Strobl 	cell_t *ap, *cp;
8558446b206SNathan Whitehorn 	int n;
8568446b206SNathan Whitehorn 
857b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"call-method");
858b49db827SBrandon Bergren 	args.nargs = IN(2);
859b49db827SBrandon Bergren 	args.nreturns = IN(1);
86070d75337SNathan Whitehorn 
8618446b206SNathan Whitehorn 	if (nargs > 6)
8628446b206SNathan Whitehorn 		return (-1);
8638446b206SNathan Whitehorn 
8648446b206SNathan Whitehorn 	ofw_real_start();
865b49db827SBrandon Bergren 	args.nargs = IN(nargs + 2);
866b49db827SBrandon Bergren 	args.nreturns = IN(nreturns + 1);
867b49db827SBrandon Bergren 	args.method = IN(ofw_real_map(method, strlen(method) + 1));
868b49db827SBrandon Bergren 	args.instance = IN(instance);
8698446b206SNathan Whitehorn 
8708446b206SNathan Whitehorn 	ap = args_and_returns;
8718446b206SNathan Whitehorn 	for (cp = args.args_n_results + (n = nargs); --n >= 0;)
872b49db827SBrandon Bergren 		*--cp = IN(*(ap++));
87370d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
87470d75337SNathan Whitehorn 	if (args.method == 0 ||
87570d75337SNathan Whitehorn 	    openfirmware((void *)argsptr) == -1) {
8768446b206SNathan Whitehorn 		ofw_real_stop();
8778446b206SNathan Whitehorn 		return (-1);
8788446b206SNathan Whitehorn 	}
87970d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
8808446b206SNathan Whitehorn 	ofw_real_stop();
881b49db827SBrandon Bergren 	if (OUT(args.args_n_results[nargs]))
882b49db827SBrandon Bergren 		return (OUT(args.args_n_results[nargs]));
883b49db827SBrandon Bergren 	for (cp = args.args_n_results + nargs + (n = OUT(args.nreturns)); --n > 0;)
884b49db827SBrandon Bergren 		*(ap++) = OUT(*--cp);
8858446b206SNathan Whitehorn 	return (0);
8868446b206SNathan Whitehorn }
8878446b206SNathan Whitehorn 
88870d75337SNathan Whitehorn static int
889cdb25d82SMarius Strobl ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
89070d75337SNathan Whitehorn {
89170d75337SNathan Whitehorn 	vm_offset_t argsptr;
89270d75337SNathan Whitehorn 	struct {
89370d75337SNathan Whitehorn 		cell_t name;
89470d75337SNathan Whitehorn 		cell_t nargs;
89570d75337SNathan Whitehorn 		cell_t nreturns;
89670d75337SNathan Whitehorn 		cell_t slot[16];
89770d75337SNathan Whitehorn 	} args;
89870d75337SNathan Whitehorn 	cell_t status;
89970d75337SNathan Whitehorn 	int i = 0, j = 0;
90070d75337SNathan Whitehorn 
901b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"interpret");
902b49db827SBrandon Bergren 	args.nargs = IN(1);
90370d75337SNathan Whitehorn 
90470d75337SNathan Whitehorn 	ofw_real_start();
905b49db827SBrandon Bergren 	args.nreturns = IN(++nreturns);
906b49db827SBrandon Bergren 	args.slot[i++] = IN(ofw_real_map(cmd, strlen(cmd) + 1));
90770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
90870d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
90970d75337SNathan Whitehorn 		ofw_real_stop();
91070d75337SNathan Whitehorn 		return (-1);
91170d75337SNathan Whitehorn 	}
91270d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
91370d75337SNathan Whitehorn 	ofw_real_stop();
914b49db827SBrandon Bergren 	status = OUT(args.slot[i++]);
91570d75337SNathan Whitehorn 	while (i < 1 + nreturns)
916b49db827SBrandon Bergren 		returns[j++] = OUT(args.slot[i++]);
91770d75337SNathan Whitehorn 	return (status);
91870d75337SNathan Whitehorn }
91970d75337SNathan Whitehorn 
9208446b206SNathan Whitehorn /*
9218446b206SNathan Whitehorn  * Device I/O functions
9228446b206SNathan Whitehorn  */
9238446b206SNathan Whitehorn 
9248446b206SNathan Whitehorn /* Open an instance for a device. */
9258446b206SNathan Whitehorn static ihandle_t
9268446b206SNathan Whitehorn ofw_real_open(ofw_t ofw, const char *device)
9278446b206SNathan Whitehorn {
92870d75337SNathan Whitehorn 	vm_offset_t argsptr;
929d4bccd63SNathan Whitehorn 	struct {
9308446b206SNathan Whitehorn 		cell_t name;
9318446b206SNathan Whitehorn 		cell_t nargs;
9328446b206SNathan Whitehorn 		cell_t nreturns;
9338446b206SNathan Whitehorn 		cell_t device;
9348446b206SNathan Whitehorn 		cell_t instance;
93570d75337SNathan Whitehorn 	} args;
93670d75337SNathan Whitehorn 
937b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"open");
938b49db827SBrandon Bergren 	args.nargs = IN(1);
939b49db827SBrandon Bergren 	args.nreturns = IN(1);
9408446b206SNathan Whitehorn 
9418446b206SNathan Whitehorn 	ofw_real_start();
9428446b206SNathan Whitehorn 
943b49db827SBrandon Bergren 	args.device = IN(ofw_real_map(device, strlen(device) + 1));
94470d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
94570d75337SNathan Whitehorn 	if (args.device == 0 || openfirmware((void *)argsptr) == -1
9468446b206SNathan Whitehorn 	    || args.instance == 0) {
9478446b206SNathan Whitehorn 		ofw_real_stop();
9488446b206SNathan Whitehorn 		return (-1);
9498446b206SNathan Whitehorn 	}
95070d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
9518446b206SNathan Whitehorn 	ofw_real_stop();
952b49db827SBrandon Bergren 	return (OUT(args.instance));
9538446b206SNathan Whitehorn }
9548446b206SNathan Whitehorn 
9558446b206SNathan Whitehorn /* Close an instance. */
9568446b206SNathan Whitehorn static void
9578446b206SNathan Whitehorn ofw_real_close(ofw_t ofw, ihandle_t instance)
9588446b206SNathan Whitehorn {
95970d75337SNathan Whitehorn 	vm_offset_t argsptr;
960d4bccd63SNathan Whitehorn 	struct {
9618446b206SNathan Whitehorn 		cell_t name;
9628446b206SNathan Whitehorn 		cell_t nargs;
9638446b206SNathan Whitehorn 		cell_t nreturns;
9648446b206SNathan Whitehorn 		cell_t instance;
96570d75337SNathan Whitehorn 	} args;
9668446b206SNathan Whitehorn 
967b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"close");
968b49db827SBrandon Bergren 	args.nargs = IN(1);
969b49db827SBrandon Bergren 	args.nreturns = IN(0);
970b49db827SBrandon Bergren 	args.instance = IN(instance);
97170d75337SNathan Whitehorn 	ofw_real_start();
97270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
97370d75337SNathan Whitehorn 	openfirmware((void *)argsptr);
97470d75337SNathan Whitehorn 	ofw_real_stop();
9758446b206SNathan Whitehorn }
9768446b206SNathan Whitehorn 
9778446b206SNathan Whitehorn /* Read from an instance. */
9788446b206SNathan Whitehorn static ssize_t
9798446b206SNathan Whitehorn ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
9808446b206SNathan Whitehorn {
98170d75337SNathan Whitehorn 	vm_offset_t argsptr;
982d4bccd63SNathan Whitehorn 	struct {
9838446b206SNathan Whitehorn 		cell_t name;
9848446b206SNathan Whitehorn 		cell_t nargs;
9858446b206SNathan Whitehorn 		cell_t nreturns;
9868446b206SNathan Whitehorn 		cell_t instance;
9878446b206SNathan Whitehorn 		cell_t addr;
9888446b206SNathan Whitehorn 		cell_t len;
98970d75337SNathan Whitehorn 		int32_t actual;
99070d75337SNathan Whitehorn 	} args;
99170d75337SNathan Whitehorn 
992b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"read");
993b49db827SBrandon Bergren 	args.nargs = IN(3);
994b49db827SBrandon Bergren 	args.nreturns = IN(1);
9958446b206SNathan Whitehorn 
9968446b206SNathan Whitehorn 	ofw_real_start();
9978446b206SNathan Whitehorn 
998b49db827SBrandon Bergren 	args.instance = IN(instance);
999b49db827SBrandon Bergren 	args.addr = IN(ofw_real_map(addr, len));
1000b49db827SBrandon Bergren 	args.len = IN(len);
100170d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
100270d75337SNathan Whitehorn 	if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
10038446b206SNathan Whitehorn 		ofw_real_stop();
10048446b206SNathan Whitehorn 		return (-1);
10058446b206SNathan Whitehorn 	}
100670d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
1007b49db827SBrandon Bergren 	ofw_real_unmap(OUT(args.addr), addr, len);
10088446b206SNathan Whitehorn 
10098446b206SNathan Whitehorn 	ofw_real_stop();
1010b49db827SBrandon Bergren 	return ((ssize_t)(int32_t)OUT(args.actual));
10118446b206SNathan Whitehorn }
10128446b206SNathan Whitehorn 
10138446b206SNathan Whitehorn /* Write to an instance. */
10148446b206SNathan Whitehorn static ssize_t
10158446b206SNathan Whitehorn ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
10168446b206SNathan Whitehorn {
101770d75337SNathan Whitehorn 	vm_offset_t argsptr;
1018d4bccd63SNathan Whitehorn 	struct {
10198446b206SNathan Whitehorn 		cell_t name;
10208446b206SNathan Whitehorn 		cell_t nargs;
10218446b206SNathan Whitehorn 		cell_t nreturns;
10228446b206SNathan Whitehorn 		cell_t instance;
10238446b206SNathan Whitehorn 		cell_t addr;
10248446b206SNathan Whitehorn 		cell_t len;
102570d75337SNathan Whitehorn 		int32_t actual;
102670d75337SNathan Whitehorn 	} args;
102770d75337SNathan Whitehorn 
1028b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"write");
1029b49db827SBrandon Bergren 	args.nargs = IN(3);
1030b49db827SBrandon Bergren 	args.nreturns = IN(1);
10318446b206SNathan Whitehorn 
10328446b206SNathan Whitehorn 	ofw_real_start();
10338446b206SNathan Whitehorn 
1034b49db827SBrandon Bergren 	args.instance = IN(instance);
1035b49db827SBrandon Bergren 	args.addr = IN(ofw_real_map(addr, len));
1036b49db827SBrandon Bergren 	args.len = IN(len);
103770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
103870d75337SNathan Whitehorn 	if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
10398446b206SNathan Whitehorn 		ofw_real_stop();
10408446b206SNathan Whitehorn 		return (-1);
10418446b206SNathan Whitehorn 	}
104270d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
10438446b206SNathan Whitehorn 	ofw_real_stop();
1044b49db827SBrandon Bergren 	return ((ssize_t)(int32_t)OUT(args.actual));
10458446b206SNathan Whitehorn }
10468446b206SNathan Whitehorn 
10478446b206SNathan Whitehorn /* Seek to a position. */
10488446b206SNathan Whitehorn static int
10498446b206SNathan Whitehorn ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
10508446b206SNathan Whitehorn {
105170d75337SNathan Whitehorn 	vm_offset_t argsptr;
1052d4bccd63SNathan Whitehorn 	struct {
10538446b206SNathan Whitehorn 		cell_t name;
10548446b206SNathan Whitehorn 		cell_t nargs;
10558446b206SNathan Whitehorn 		cell_t nreturns;
10568446b206SNathan Whitehorn 		cell_t instance;
10578446b206SNathan Whitehorn 		cell_t poshi;
10588446b206SNathan Whitehorn 		cell_t poslo;
10598446b206SNathan Whitehorn 		cell_t status;
106070d75337SNathan Whitehorn 	} args;
106170d75337SNathan Whitehorn 
1062b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"seek");
1063b49db827SBrandon Bergren 	args.nargs = IN(3);
1064b49db827SBrandon Bergren 	args.nreturns = IN(1);
10658446b206SNathan Whitehorn 
1066b49db827SBrandon Bergren 	args.instance = IN(instance);
1067b49db827SBrandon Bergren 	args.poshi = IN(pos >> 32);
1068b49db827SBrandon Bergren 	args.poslo = IN(pos);
106970d75337SNathan Whitehorn 	ofw_real_start();
107070d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
107170d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
107270d75337SNathan Whitehorn 		ofw_real_stop();
10738446b206SNathan Whitehorn 		return (-1);
107470d75337SNathan Whitehorn 	}
107570d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
107670d75337SNathan Whitehorn 	ofw_real_stop();
1077b49db827SBrandon Bergren 	return (OUT(args.status));
10788446b206SNathan Whitehorn }
10798446b206SNathan Whitehorn 
10808446b206SNathan Whitehorn /*
10818446b206SNathan Whitehorn  * Memory functions
10828446b206SNathan Whitehorn  */
10838446b206SNathan Whitehorn 
10848446b206SNathan Whitehorn /* Claim an area of memory. */
10858446b206SNathan Whitehorn static caddr_t
10868446b206SNathan Whitehorn ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
10878446b206SNathan Whitehorn {
108870d75337SNathan Whitehorn 	vm_offset_t argsptr;
1089d4bccd63SNathan Whitehorn 	struct {
10908446b206SNathan Whitehorn 		cell_t name;
10918446b206SNathan Whitehorn 		cell_t nargs;
10928446b206SNathan Whitehorn 		cell_t nreturns;
10938446b206SNathan Whitehorn 		cell_t virt;
10948446b206SNathan Whitehorn 		cell_t size;
10958446b206SNathan Whitehorn 		cell_t align;
10968446b206SNathan Whitehorn 		cell_t baseaddr;
109770d75337SNathan Whitehorn 	} args;
10988446b206SNathan Whitehorn 
1099b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"claim");
1100b49db827SBrandon Bergren 	args.nargs = IN(3);
1101b49db827SBrandon Bergren 	args.nreturns = IN(1);
110270d75337SNathan Whitehorn 
1103b49db827SBrandon Bergren 	args.virt = IN((cell_t)(uintptr_t)virt);
1104b49db827SBrandon Bergren 	args.size = IN(size);
1105b49db827SBrandon Bergren 	args.align = IN(align);
110670d75337SNathan Whitehorn 	ofw_real_start();
110770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
110870d75337SNathan Whitehorn 	if (openfirmware((void *)argsptr) == -1) {
110970d75337SNathan Whitehorn 		ofw_real_stop();
11108446b206SNathan Whitehorn 		return ((void *)-1);
111170d75337SNathan Whitehorn 	}
111270d75337SNathan Whitehorn 	ofw_real_unmap(argsptr, &args, sizeof(args));
111370d75337SNathan Whitehorn 	ofw_real_stop();
1114b49db827SBrandon Bergren 	return ((void *)(uintptr_t)(OUT(args.baseaddr)));
11158446b206SNathan Whitehorn }
11168446b206SNathan Whitehorn 
11178446b206SNathan Whitehorn /* Release an area of memory. */
11188446b206SNathan Whitehorn static void
11198446b206SNathan Whitehorn ofw_real_release(ofw_t ofw, void *virt, size_t size)
11208446b206SNathan Whitehorn {
112170d75337SNathan Whitehorn 	vm_offset_t argsptr;
1122d4bccd63SNathan Whitehorn 	struct {
11238446b206SNathan Whitehorn 		cell_t name;
11248446b206SNathan Whitehorn 		cell_t nargs;
11258446b206SNathan Whitehorn 		cell_t nreturns;
11268446b206SNathan Whitehorn 		cell_t virt;
11278446b206SNathan Whitehorn 		cell_t size;
112870d75337SNathan Whitehorn 	} args;
11298446b206SNathan Whitehorn 
1130b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"release");
1131b49db827SBrandon Bergren 	args.nargs = IN(2);
1132b49db827SBrandon Bergren 	args.nreturns = IN(0);
113370d75337SNathan Whitehorn 
1134b49db827SBrandon Bergren 	args.virt = IN((cell_t)(uintptr_t)virt);
1135b49db827SBrandon Bergren 	args.size = IN(size);
113670d75337SNathan Whitehorn 	ofw_real_start();
113770d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
113870d75337SNathan Whitehorn 	openfirmware((void *)argsptr);
113970d75337SNathan Whitehorn 	ofw_real_stop();
11408446b206SNathan Whitehorn }
11418446b206SNathan Whitehorn 
11428446b206SNathan Whitehorn /*
11438446b206SNathan Whitehorn  * Control transfer functions
11448446b206SNathan Whitehorn  */
11458446b206SNathan Whitehorn 
11468446b206SNathan Whitehorn /* Suspend and drop back to the Open Firmware interface. */
11478446b206SNathan Whitehorn static void
11488446b206SNathan Whitehorn ofw_real_enter(ofw_t ofw)
11498446b206SNathan Whitehorn {
115070d75337SNathan Whitehorn 	vm_offset_t argsptr;
1151d4bccd63SNathan Whitehorn 	struct {
11528446b206SNathan Whitehorn 		cell_t name;
11538446b206SNathan Whitehorn 		cell_t nargs;
11548446b206SNathan Whitehorn 		cell_t nreturns;
115570d75337SNathan Whitehorn 	} args;
11568446b206SNathan Whitehorn 
1157b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"enter");
1158b49db827SBrandon Bergren 	args.nargs = IN(0);
1159b49db827SBrandon Bergren 	args.nreturns = IN(0);
116070d75337SNathan Whitehorn 
116170d75337SNathan Whitehorn 	ofw_real_start();
116270d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
116370d75337SNathan Whitehorn 	openfirmware((void *)argsptr);
11648446b206SNathan Whitehorn 	/* We may come back. */
116570d75337SNathan Whitehorn 	ofw_real_stop();
11668446b206SNathan Whitehorn }
11678446b206SNathan Whitehorn 
11688446b206SNathan Whitehorn /* Shut down and drop back to the Open Firmware interface. */
11698446b206SNathan Whitehorn static void
11708446b206SNathan Whitehorn ofw_real_exit(ofw_t ofw)
11718446b206SNathan Whitehorn {
117270d75337SNathan Whitehorn 	vm_offset_t argsptr;
1173d4bccd63SNathan Whitehorn 	struct {
11748446b206SNathan Whitehorn 		cell_t name;
11758446b206SNathan Whitehorn 		cell_t nargs;
11768446b206SNathan Whitehorn 		cell_t nreturns;
117770d75337SNathan Whitehorn 	} args;
11788446b206SNathan Whitehorn 
1179b49db827SBrandon Bergren 	args.name = IN((cell_t)(uintptr_t)"exit");
1180b49db827SBrandon Bergren 	args.nargs = IN(0);
1181b49db827SBrandon Bergren 	args.nreturns = IN(0);
118270d75337SNathan Whitehorn 
118370d75337SNathan Whitehorn 	ofw_real_start();
118470d75337SNathan Whitehorn 	argsptr = ofw_real_map(&args, sizeof(args));
118570d75337SNathan Whitehorn 	openfirmware((void *)argsptr);
11868446b206SNathan Whitehorn 	for (;;)			/* just in case */
11878446b206SNathan Whitehorn 		;
118870d75337SNathan Whitehorn 	ofw_real_stop();
11898446b206SNathan Whitehorn }
1190