18446b206SNathan Whitehorn /* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */
28446b206SNathan Whitehorn
38446b206SNathan Whitehorn /*-
4*4d846d26SWarner Losh * SPDX-License-Identifier:BSD-4-Clause AND BSD-2-Clause
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>
61b49db827SBrandon Bergren #include <sys/endian.h>
628446b206SNathan Whitehorn #include <sys/param.h>
638446b206SNathan Whitehorn #include <sys/kernel.h>
648446b206SNathan Whitehorn #include <sys/lock.h>
658446b206SNathan Whitehorn #include <sys/mutex.h>
668446b206SNathan Whitehorn #include <sys/systm.h>
678446b206SNathan Whitehorn
688446b206SNathan Whitehorn #include <vm/vm.h>
6970d75337SNathan Whitehorn #include <vm/vm_page.h>
708446b206SNathan Whitehorn #include <vm/pmap.h>
718446b206SNathan Whitehorn
728446b206SNathan Whitehorn #include <machine/bus.h>
7370d75337SNathan Whitehorn #include <machine/md_var.h>
748446b206SNathan Whitehorn #include <machine/ofw_machdep.h>
7570d75337SNathan Whitehorn #include <machine/stdarg.h>
768446b206SNathan Whitehorn
778446b206SNathan Whitehorn #include <dev/ofw/openfirm.h>
788446b206SNathan Whitehorn #include <dev/ofw/ofwvar.h>
798446b206SNathan Whitehorn #include "ofw_if.h"
808446b206SNathan Whitehorn
818297758aSRafal Jaworowski static int ofw_real_init(ofw_t, void *openfirm);
828446b206SNathan Whitehorn static int ofw_real_test(ofw_t, const char *name);
838446b206SNathan Whitehorn static phandle_t ofw_real_peer(ofw_t, phandle_t node);
848446b206SNathan Whitehorn static phandle_t ofw_real_child(ofw_t, phandle_t node);
858446b206SNathan Whitehorn static phandle_t ofw_real_parent(ofw_t, phandle_t node);
868446b206SNathan Whitehorn static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
878446b206SNathan Whitehorn static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
888446b206SNathan Whitehorn const char *propname);
898446b206SNathan Whitehorn static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
908446b206SNathan Whitehorn void *buf, size_t buflen);
918446b206SNathan Whitehorn static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
928446b206SNathan Whitehorn char *buf, size_t);
934fc23012SAndriy Gapon static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
944fc23012SAndriy Gapon const void *buf, size_t len);
958446b206SNathan Whitehorn static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
968446b206SNathan Whitehorn static phandle_t ofw_real_finddevice(ofw_t, const char *device);
978446b206SNathan Whitehorn static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
988446b206SNathan Whitehorn size_t len);
998446b206SNathan Whitehorn static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
1008446b206SNathan Whitehorn size_t len);
1018446b206SNathan Whitehorn static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
102054e5dcbSNathan Whitehorn int nargs, int nreturns, cell_t *args_and_returns);
10370d75337SNathan Whitehorn static int ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns,
104cdb25d82SMarius Strobl cell_t *returns);
1058446b206SNathan Whitehorn static ihandle_t ofw_real_open(ofw_t, const char *device);
1068446b206SNathan Whitehorn static void ofw_real_close(ofw_t, ihandle_t instance);
1078446b206SNathan Whitehorn static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
1088446b206SNathan Whitehorn static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
1098446b206SNathan Whitehorn size_t len);
1108446b206SNathan Whitehorn static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
1118446b206SNathan Whitehorn static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
1128446b206SNathan Whitehorn static void ofw_real_release(ofw_t, void *virt, size_t size);
1138446b206SNathan Whitehorn static void ofw_real_enter(ofw_t);
1148446b206SNathan Whitehorn static void ofw_real_exit(ofw_t);
1158446b206SNathan Whitehorn
1168446b206SNathan Whitehorn static ofw_method_t ofw_real_methods[] = {
1178446b206SNathan Whitehorn OFWMETHOD(ofw_init, ofw_real_init),
1188446b206SNathan Whitehorn OFWMETHOD(ofw_peer, ofw_real_peer),
1198446b206SNathan Whitehorn OFWMETHOD(ofw_child, ofw_real_child),
1208446b206SNathan Whitehorn OFWMETHOD(ofw_parent, ofw_real_parent),
1218446b206SNathan Whitehorn OFWMETHOD(ofw_instance_to_package, ofw_real_instance_to_package),
1228446b206SNathan Whitehorn OFWMETHOD(ofw_getproplen, ofw_real_getproplen),
1238446b206SNathan Whitehorn OFWMETHOD(ofw_getprop, ofw_real_getprop),
1248446b206SNathan Whitehorn OFWMETHOD(ofw_nextprop, ofw_real_nextprop),
1258446b206SNathan Whitehorn OFWMETHOD(ofw_setprop, ofw_real_setprop),
1268446b206SNathan Whitehorn OFWMETHOD(ofw_canon, ofw_real_canon),
1278446b206SNathan Whitehorn OFWMETHOD(ofw_finddevice, ofw_real_finddevice),
1288446b206SNathan Whitehorn OFWMETHOD(ofw_instance_to_path, ofw_real_instance_to_path),
1298446b206SNathan Whitehorn OFWMETHOD(ofw_package_to_path, ofw_real_package_to_path),
1308446b206SNathan Whitehorn
1318446b206SNathan Whitehorn OFWMETHOD(ofw_test, ofw_real_test),
1328446b206SNathan Whitehorn OFWMETHOD(ofw_call_method, ofw_real_call_method),
13370d75337SNathan Whitehorn OFWMETHOD(ofw_interpret, ofw_real_interpret),
1348446b206SNathan Whitehorn OFWMETHOD(ofw_open, ofw_real_open),
1358446b206SNathan Whitehorn OFWMETHOD(ofw_close, ofw_real_close),
1368446b206SNathan Whitehorn OFWMETHOD(ofw_read, ofw_real_read),
1378446b206SNathan Whitehorn OFWMETHOD(ofw_write, ofw_real_write),
1388446b206SNathan Whitehorn OFWMETHOD(ofw_seek, ofw_real_seek),
1398446b206SNathan Whitehorn OFWMETHOD(ofw_claim, ofw_real_claim),
1408446b206SNathan Whitehorn OFWMETHOD(ofw_release, ofw_real_release),
1418446b206SNathan Whitehorn OFWMETHOD(ofw_enter, ofw_real_enter),
1428446b206SNathan Whitehorn OFWMETHOD(ofw_exit, ofw_real_exit),
1438446b206SNathan Whitehorn { 0, 0 }
1448446b206SNathan Whitehorn };
1458446b206SNathan Whitehorn
1468446b206SNathan Whitehorn static ofw_def_t ofw_real = {
1478446b206SNathan Whitehorn OFW_STD_REAL,
1488446b206SNathan Whitehorn ofw_real_methods,
1498446b206SNathan Whitehorn 0
1508446b206SNathan Whitehorn };
1518446b206SNathan Whitehorn OFW_DEF(ofw_real);
1528446b206SNathan Whitehorn
15370d75337SNathan Whitehorn static ofw_def_t ofw_32bit = {
15470d75337SNathan Whitehorn OFW_STD_32BIT,
15570d75337SNathan Whitehorn ofw_real_methods,
15670d75337SNathan Whitehorn 0
15770d75337SNathan Whitehorn };
15870d75337SNathan Whitehorn OFW_DEF(ofw_32bit);
15970d75337SNathan Whitehorn
160d745c852SEd Schouten static MALLOC_DEFINE(M_OFWREAL, "ofwreal",
161d745c852SEd Schouten "Open Firmware Real Mode Bounce Page");
1628446b206SNathan Whitehorn
1638446b206SNathan Whitehorn static int (*openfirmware)(void *);
1648446b206SNathan Whitehorn
1658446b206SNathan Whitehorn static vm_offset_t of_bounce_phys;
1668446b206SNathan Whitehorn static caddr_t of_bounce_virt;
1678446b206SNathan Whitehorn static off_t of_bounce_offset;
1688446b206SNathan Whitehorn static size_t of_bounce_size;
16935f29427SLeandro Lupori
170b49db827SBrandon Bergren #define IN(x) htobe32(x)
171b49db827SBrandon Bergren #define OUT(x) be32toh(x)
172b49db827SBrandon Bergren
17335f29427SLeandro Lupori /*
17435f29427SLeandro Lupori * To be able to use OFW console on PPC, that requires real mode OFW,
17535f29427SLeandro Lupori * the mutex that guards the mapping/unmapping of virtual to physical
17635f29427SLeandro Lupori * buffers (of_real_mtx) must be of SPIN type. This is needed because
17735f29427SLeandro Lupori * kernel console first locks a SPIN mutex before calling OFW real.
17835f29427SLeandro Lupori * By default, of_real_mtx is a sleepable mutex. To make it of SPIN
17935f29427SLeandro Lupori * type, use the following tunnable:
18035f29427SLeandro Lupori * machdep.ofw.mtx_spin=1
18135f29427SLeandro Lupori *
18235f29427SLeandro Lupori * Besides that, a few more tunables are needed to select and use the
18335f29427SLeandro Lupori * OFW console with real mode OFW.
18435f29427SLeandro Lupori *
18535f29427SLeandro Lupori * In order to disable the use of OFW FrameBuffer and fallback to the
18635f29427SLeandro Lupori * OFW console, use:
18735f29427SLeandro Lupori * hw.ofwfb.disable=1
18835f29427SLeandro Lupori *
18935f29427SLeandro Lupori * To disable the use of FDT (that doesn't support OFW read/write methods)
19035f29427SLeandro Lupori * and use real OFW instead, unset the following loader variable:
19135f29427SLeandro Lupori * unset usefdt
19235f29427SLeandro Lupori *
19335f29427SLeandro Lupori * OFW is put in quiesce state in early kernel boot, which usually disables
19435f29427SLeandro Lupori * OFW read/write capabilities (in QEMU write continue to work, but
19535f29427SLeandro Lupori * read doesn't). To avoid OFW quiesce, use:
19635f29427SLeandro Lupori * debug.quiesce_ofw=0
19735f29427SLeandro Lupori *
19835f29427SLeandro Lupori * Note that disabling OFW quiesce can cause conflicts between kernel and
19935f29427SLeandro Lupori * OFW trying to control the same hardware. Thus, it must be used with care.
20035f29427SLeandro Lupori * Some conflicts can be avoided by disabling kernel drivers with hints.
20135f29427SLeandro Lupori * For instance, to disable a xhci controller and an USB keyboard connected
20235f29427SLeandro Lupori * to it, that may be already being used for input by OFW, use:
20335f29427SLeandro Lupori * hint.xhci.0.disabled=1
20435f29427SLeandro Lupori */
20535f29427SLeandro Lupori
2068446b206SNathan Whitehorn static struct mtx of_bounce_mtx;
20735f29427SLeandro Lupori static struct mtx of_spin_mtx;
20835f29427SLeandro Lupori static struct mtx *of_real_mtx;
20935f29427SLeandro Lupori static void (*of_mtx_lock)(void);
21035f29427SLeandro Lupori static void (*of_mtx_unlock)(void);
2118446b206SNathan Whitehorn
21270d75337SNathan Whitehorn extern int ofw_real_mode;
21370d75337SNathan Whitehorn
2148446b206SNathan Whitehorn /*
2158446b206SNathan Whitehorn * After the VM is up, allocate a wired, low memory bounce page.
2168446b206SNathan Whitehorn */
2178446b206SNathan Whitehorn
2188446b206SNathan Whitehorn static void ofw_real_bounce_alloc(void *);
2198446b206SNathan Whitehorn
22070d75337SNathan Whitehorn SYSINIT(ofw_real_bounce_alloc, SI_SUB_KMEM, SI_ORDER_ANY,
2218446b206SNathan Whitehorn ofw_real_bounce_alloc, NULL);
2228446b206SNathan Whitehorn
2238446b206SNathan Whitehorn static void
ofw_real_mtx_lock_spin(void)22435f29427SLeandro Lupori ofw_real_mtx_lock_spin(void)
22535f29427SLeandro Lupori {
22635f29427SLeandro Lupori mtx_lock_spin(of_real_mtx);
22735f29427SLeandro Lupori }
22835f29427SLeandro Lupori
22935f29427SLeandro Lupori static void
ofw_real_mtx_lock(void)23035f29427SLeandro Lupori ofw_real_mtx_lock(void)
23135f29427SLeandro Lupori {
23235f29427SLeandro Lupori mtx_lock(of_real_mtx);
23335f29427SLeandro Lupori }
23435f29427SLeandro Lupori
23535f29427SLeandro Lupori static void
ofw_real_mtx_unlock_spin(void)23635f29427SLeandro Lupori ofw_real_mtx_unlock_spin(void)
23735f29427SLeandro Lupori {
23835f29427SLeandro Lupori mtx_unlock_spin(of_real_mtx);
23935f29427SLeandro Lupori }
24035f29427SLeandro Lupori
24135f29427SLeandro Lupori static void
ofw_real_mtx_unlock(void)24235f29427SLeandro Lupori ofw_real_mtx_unlock(void)
24335f29427SLeandro Lupori {
24435f29427SLeandro Lupori mtx_unlock(of_real_mtx);
24535f29427SLeandro Lupori }
24635f29427SLeandro Lupori
24735f29427SLeandro Lupori static void
ofw_real_start(void)2488446b206SNathan Whitehorn ofw_real_start(void)
2498446b206SNathan Whitehorn {
25035f29427SLeandro Lupori (*of_mtx_lock)();
2518446b206SNathan Whitehorn of_bounce_offset = 0;
2528446b206SNathan Whitehorn }
2538446b206SNathan Whitehorn
2548446b206SNathan Whitehorn static void
ofw_real_stop(void)2558446b206SNathan Whitehorn ofw_real_stop(void)
2568446b206SNathan Whitehorn {
25735f29427SLeandro Lupori (*of_mtx_unlock)();
2588446b206SNathan Whitehorn }
2598446b206SNathan Whitehorn
2608446b206SNathan Whitehorn static void
ofw_real_bounce_alloc(void * junk)2618446b206SNathan Whitehorn ofw_real_bounce_alloc(void *junk)
2628446b206SNathan Whitehorn {
263d6d06708SJustin Hibbits caddr_t temp;
264d6d06708SJustin Hibbits
2658446b206SNathan Whitehorn /*
2668446b206SNathan Whitehorn * Check that ofw_real is actually in use before allocating wads
2678446b206SNathan Whitehorn * of memory. Do this by checking if our mutex has been set up.
2688446b206SNathan Whitehorn */
2698446b206SNathan Whitehorn if (!mtx_initialized(&of_bounce_mtx))
2708446b206SNathan Whitehorn return;
2718446b206SNathan Whitehorn
2728446b206SNathan Whitehorn /*
2738446b206SNathan Whitehorn * Allocate a page of contiguous, wired physical memory that can
27417879090SNathan Whitehorn * fit into a 32-bit address space and accessed from real mode.
2758446b206SNathan Whitehorn */
276d6d06708SJustin Hibbits temp = contigmalloc(4 * PAGE_SIZE, M_OFWREAL, 0, 0,
277d6d06708SJustin Hibbits ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
278d6d06708SJustin Hibbits 4 * PAGE_SIZE);
279d6d06708SJustin Hibbits if (temp == NULL)
280d6d06708SJustin Hibbits panic("%s: Not able to allocated contiguous memory\n", __func__);
2818446b206SNathan Whitehorn
2828446b206SNathan Whitehorn mtx_lock(&of_bounce_mtx);
2838446b206SNathan Whitehorn
284d6d06708SJustin Hibbits of_bounce_virt = temp;
28570d75337SNathan Whitehorn
2868446b206SNathan Whitehorn of_bounce_phys = vtophys(of_bounce_virt);
28715b5b0acSJustin Hibbits of_bounce_size = 4 * PAGE_SIZE;
2888446b206SNathan Whitehorn
28970d75337SNathan Whitehorn /*
29070d75337SNathan Whitehorn * For virtual-mode OF, direct map this physical address so that
29170d75337SNathan Whitehorn * we have a 32-bit virtual address to give OF.
29270d75337SNathan Whitehorn */
29370d75337SNathan Whitehorn
294f9edb09dSNathan Whitehorn if (!ofw_real_mode && (!hw_direct_map || DMAP_BASE_ADDRESS != 0))
29570d75337SNathan Whitehorn pmap_kenter(of_bounce_phys, of_bounce_phys);
29670d75337SNathan Whitehorn
2978446b206SNathan Whitehorn mtx_unlock(&of_bounce_mtx);
2988446b206SNathan Whitehorn }
2998446b206SNathan Whitehorn
3008446b206SNathan Whitehorn static cell_t
ofw_real_map(const void * buf,size_t len)3018446b206SNathan Whitehorn ofw_real_map(const void *buf, size_t len)
3028446b206SNathan Whitehorn {
30370d75337SNathan Whitehorn static char emergency_buffer[255];
3048446b206SNathan Whitehorn cell_t phys;
3058446b206SNathan Whitehorn
30635f29427SLeandro Lupori mtx_assert(of_real_mtx, MA_OWNED);
3078446b206SNathan Whitehorn
3088446b206SNathan Whitehorn if (of_bounce_virt == NULL) {
30970d75337SNathan Whitehorn /*
31070d75337SNathan Whitehorn * If we haven't set up the MMU, then buf is guaranteed
31170d75337SNathan Whitehorn * to be accessible to OF, because the only memory we
31270d75337SNathan Whitehorn * can use right now is memory mapped by firmware.
31370d75337SNathan Whitehorn */
3148446b206SNathan Whitehorn if (!pmap_bootstrapped)
315f9edb09dSNathan Whitehorn return (cell_t)((uintptr_t)buf & ~DMAP_BASE_ADDRESS);
3168446b206SNathan Whitehorn
3178446b206SNathan Whitehorn /*
3188446b206SNathan Whitehorn * XXX: It is possible for us to get called before the VM has
3198446b206SNathan Whitehorn * come online, but after the MMU is up. We don't have the
3208446b206SNathan Whitehorn * bounce buffer yet, but can no longer presume a 1:1 mapping.
32170d75337SNathan Whitehorn * Copy into the emergency buffer, and reset at the end.
3228446b206SNathan Whitehorn */
32370d75337SNathan Whitehorn of_bounce_virt = emergency_buffer;
324f9edb09dSNathan Whitehorn of_bounce_phys = (vm_offset_t)of_bounce_virt &
325f9edb09dSNathan Whitehorn ~DMAP_BASE_ADDRESS;
32670d75337SNathan Whitehorn of_bounce_size = sizeof(emergency_buffer);
3278446b206SNathan Whitehorn }
3288446b206SNathan Whitehorn
3298446b206SNathan Whitehorn /*
3308446b206SNathan Whitehorn * Make sure the bounce page offset satisfies any reasonable
3318446b206SNathan Whitehorn * alignment constraint.
3328446b206SNathan Whitehorn */
333f9edb09dSNathan Whitehorn of_bounce_offset += sizeof(register_t) -
334f9edb09dSNathan Whitehorn (of_bounce_offset % sizeof(register_t));
3358446b206SNathan Whitehorn
3368446b206SNathan Whitehorn if (of_bounce_offset + len > of_bounce_size) {
3378446b206SNathan Whitehorn panic("Oversize Open Firmware call!");
3388446b206SNathan Whitehorn return 0;
3398446b206SNathan Whitehorn }
3408446b206SNathan Whitehorn
341ec664c11SAndreas Tobler if (buf != NULL)
3428446b206SNathan Whitehorn memcpy(of_bounce_virt + of_bounce_offset, buf, len);
343ec664c11SAndreas Tobler else
344ec664c11SAndreas Tobler return (0);
345ec664c11SAndreas Tobler
3468446b206SNathan Whitehorn phys = of_bounce_phys + of_bounce_offset;
3478446b206SNathan Whitehorn
3488446b206SNathan Whitehorn of_bounce_offset += len;
3498446b206SNathan Whitehorn
35070d75337SNathan Whitehorn return (phys);
3518446b206SNathan Whitehorn }
3528446b206SNathan Whitehorn
3538446b206SNathan Whitehorn static void
ofw_real_unmap(cell_t physaddr,void * buf,size_t len)3548446b206SNathan Whitehorn ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
3558446b206SNathan Whitehorn {
35635f29427SLeandro Lupori mtx_assert(of_real_mtx, MA_OWNED);
3578446b206SNathan Whitehorn
3588446b206SNathan Whitehorn if (of_bounce_virt == NULL)
3598446b206SNathan Whitehorn return;
3608446b206SNathan Whitehorn
361ec664c11SAndreas Tobler if (physaddr == 0)
362ec664c11SAndreas Tobler return;
363ec664c11SAndreas Tobler
3648446b206SNathan Whitehorn memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
3658446b206SNathan Whitehorn }
3668446b206SNathan Whitehorn
3678446b206SNathan Whitehorn /* Initialiser */
3688446b206SNathan Whitehorn
3698297758aSRafal Jaworowski static int
ofw_real_init(ofw_t ofw,void * openfirm)3708446b206SNathan Whitehorn ofw_real_init(ofw_t ofw, void *openfirm)
3718446b206SNathan Whitehorn {
37235f29427SLeandro Lupori int mtx_spin;
3738446b206SNathan Whitehorn
37435f29427SLeandro Lupori openfirmware = (int (*)(void *))openfirm;
375d01195e3SChristian Brueffer mtx_init(&of_bounce_mtx, "OF Bounce Page", NULL, MTX_DEF);
37635f29427SLeandro Lupori
37735f29427SLeandro Lupori mtx_spin = 0;
37835f29427SLeandro Lupori TUNABLE_INT_FETCH("machdep.ofw.mtx_spin", &mtx_spin);
37935f29427SLeandro Lupori if (mtx_spin) {
38035f29427SLeandro Lupori mtx_init(&of_spin_mtx, "OF Real", NULL, MTX_SPIN);
38135f29427SLeandro Lupori of_real_mtx = &of_spin_mtx;
38235f29427SLeandro Lupori of_mtx_lock = ofw_real_mtx_lock_spin;
38335f29427SLeandro Lupori of_mtx_unlock = ofw_real_mtx_unlock_spin;
38435f29427SLeandro Lupori } else {
38535f29427SLeandro Lupori of_real_mtx = &of_bounce_mtx;
38635f29427SLeandro Lupori of_mtx_lock = ofw_real_mtx_lock;
38735f29427SLeandro Lupori of_mtx_unlock = ofw_real_mtx_unlock;
38835f29427SLeandro Lupori }
38935f29427SLeandro Lupori
3908446b206SNathan Whitehorn of_bounce_virt = NULL;
3918297758aSRafal Jaworowski return (0);
3928446b206SNathan Whitehorn }
3938446b206SNathan Whitehorn
3948446b206SNathan Whitehorn /*
3958446b206SNathan Whitehorn * Generic functions
3968446b206SNathan Whitehorn */
3978446b206SNathan Whitehorn
3988446b206SNathan Whitehorn /* Test to see if a service exists. */
3998446b206SNathan Whitehorn static int
ofw_real_test(ofw_t ofw,const char * name)4008446b206SNathan Whitehorn ofw_real_test(ofw_t ofw, const char *name)
4018446b206SNathan Whitehorn {
40270d75337SNathan Whitehorn vm_offset_t argsptr;
403d4bccd63SNathan Whitehorn struct {
4048446b206SNathan Whitehorn cell_t name;
4058446b206SNathan Whitehorn cell_t nargs;
4068446b206SNathan Whitehorn cell_t nreturns;
4078446b206SNathan Whitehorn cell_t service;
4088446b206SNathan Whitehorn cell_t missing;
40970d75337SNathan Whitehorn } args;
41070d75337SNathan Whitehorn
411b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"test");
412b49db827SBrandon Bergren args.nargs = IN(1);
413b49db827SBrandon Bergren args.nreturns = IN(1);
4148446b206SNathan Whitehorn
4158446b206SNathan Whitehorn ofw_real_start();
4168446b206SNathan Whitehorn
417b49db827SBrandon Bergren args.service = IN(ofw_real_map(name, strlen(name) + 1));
41870d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
41970d75337SNathan Whitehorn if (args.service == 0 || openfirmware((void *)argsptr) == -1) {
4208446b206SNathan Whitehorn ofw_real_stop();
4218446b206SNathan Whitehorn return (-1);
4228446b206SNathan Whitehorn }
42370d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
4248446b206SNathan Whitehorn ofw_real_stop();
425b49db827SBrandon Bergren return (OUT(args.missing));
4268446b206SNathan Whitehorn }
4278446b206SNathan Whitehorn
4288446b206SNathan Whitehorn /*
4298446b206SNathan Whitehorn * Device tree functions
4308446b206SNathan Whitehorn */
4318446b206SNathan Whitehorn
4328446b206SNathan Whitehorn /* Return the next sibling of this node or 0. */
4338446b206SNathan Whitehorn static phandle_t
ofw_real_peer(ofw_t ofw,phandle_t node)4348446b206SNathan Whitehorn ofw_real_peer(ofw_t ofw, phandle_t node)
4358446b206SNathan Whitehorn {
43670d75337SNathan Whitehorn vm_offset_t argsptr;
437d4bccd63SNathan Whitehorn struct {
4388446b206SNathan Whitehorn cell_t name;
4398446b206SNathan Whitehorn cell_t nargs;
4408446b206SNathan Whitehorn cell_t nreturns;
4418446b206SNathan Whitehorn cell_t node;
4428446b206SNathan Whitehorn cell_t next;
44370d75337SNathan Whitehorn } args;
44470d75337SNathan Whitehorn
445b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"peer");
446b49db827SBrandon Bergren args.nargs = IN(1);
447b49db827SBrandon Bergren args.nreturns = IN(1);
4488446b206SNathan Whitehorn
449b49db827SBrandon Bergren args.node = IN(node);
45070d75337SNathan Whitehorn ofw_real_start();
45170d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
45270d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) {
45370d75337SNathan Whitehorn ofw_real_stop();
45465184f89SNathan Whitehorn return (0);
45570d75337SNathan Whitehorn }
45670d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
45770d75337SNathan Whitehorn ofw_real_stop();
458b49db827SBrandon Bergren return (OUT(args.next));
4598446b206SNathan Whitehorn }
4608446b206SNathan Whitehorn
4618446b206SNathan Whitehorn /* Return the first child of this node or 0. */
4628446b206SNathan Whitehorn static phandle_t
ofw_real_child(ofw_t ofw,phandle_t node)4638446b206SNathan Whitehorn ofw_real_child(ofw_t ofw, phandle_t node)
4648446b206SNathan Whitehorn {
46570d75337SNathan Whitehorn vm_offset_t argsptr;
466d4bccd63SNathan Whitehorn struct {
4678446b206SNathan Whitehorn cell_t name;
4688446b206SNathan Whitehorn cell_t nargs;
4698446b206SNathan Whitehorn cell_t nreturns;
4708446b206SNathan Whitehorn cell_t node;
4718446b206SNathan Whitehorn cell_t child;
47270d75337SNathan Whitehorn } args;
47370d75337SNathan Whitehorn
474b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"child");
475b49db827SBrandon Bergren args.nargs = IN(1);
476b49db827SBrandon Bergren args.nreturns = IN(1);
4778446b206SNathan Whitehorn
478b49db827SBrandon Bergren args.node = IN(node);
47970d75337SNathan Whitehorn ofw_real_start();
48070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
48170d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) {
48270d75337SNathan Whitehorn ofw_real_stop();
48365184f89SNathan Whitehorn return (0);
48470d75337SNathan Whitehorn }
48570d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
48670d75337SNathan Whitehorn ofw_real_stop();
487b49db827SBrandon Bergren return (OUT(args.child));
4888446b206SNathan Whitehorn }
4898446b206SNathan Whitehorn
4908446b206SNathan Whitehorn /* Return the parent of this node or 0. */
4918446b206SNathan Whitehorn static phandle_t
ofw_real_parent(ofw_t ofw,phandle_t node)4928446b206SNathan Whitehorn ofw_real_parent(ofw_t ofw, phandle_t node)
4938446b206SNathan Whitehorn {
49470d75337SNathan Whitehorn vm_offset_t argsptr;
495d4bccd63SNathan Whitehorn struct {
4968446b206SNathan Whitehorn cell_t name;
4978446b206SNathan Whitehorn cell_t nargs;
4988446b206SNathan Whitehorn cell_t nreturns;
4998446b206SNathan Whitehorn cell_t node;
5008446b206SNathan Whitehorn cell_t parent;
50170d75337SNathan Whitehorn } args;
50270d75337SNathan Whitehorn
503b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"parent");
504b49db827SBrandon Bergren args.nargs = IN(1);
505b49db827SBrandon Bergren args.nreturns = IN(1);
5068446b206SNathan Whitehorn
507b49db827SBrandon Bergren args.node = IN(node);
50870d75337SNathan Whitehorn ofw_real_start();
50970d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
51070d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) {
51170d75337SNathan Whitehorn ofw_real_stop();
51265184f89SNathan Whitehorn return (0);
51370d75337SNathan Whitehorn }
51470d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
51570d75337SNathan Whitehorn ofw_real_stop();
516b49db827SBrandon Bergren return (OUT(args.parent));
5178446b206SNathan Whitehorn }
5188446b206SNathan Whitehorn
5198446b206SNathan Whitehorn /* Return the package handle that corresponds to an instance handle. */
5208446b206SNathan Whitehorn static phandle_t
ofw_real_instance_to_package(ofw_t ofw,ihandle_t instance)5218446b206SNathan Whitehorn ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
5228446b206SNathan Whitehorn {
52370d75337SNathan Whitehorn vm_offset_t argsptr;
524d4bccd63SNathan Whitehorn struct {
5258446b206SNathan Whitehorn cell_t name;
5268446b206SNathan Whitehorn cell_t nargs;
5278446b206SNathan Whitehorn cell_t nreturns;
5288446b206SNathan Whitehorn cell_t instance;
5298446b206SNathan Whitehorn cell_t package;
53070d75337SNathan Whitehorn } args;
53170d75337SNathan Whitehorn
532b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"instance-to-package");
533b49db827SBrandon Bergren args.nargs = IN(1);
534b49db827SBrandon Bergren args.nreturns = IN(1);
5358446b206SNathan Whitehorn
536b49db827SBrandon Bergren args.instance = IN(instance);
53770d75337SNathan Whitehorn ofw_real_start();
53870d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
53970d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) {
54070d75337SNathan Whitehorn ofw_real_stop();
5418446b206SNathan Whitehorn return (-1);
54270d75337SNathan Whitehorn }
54370d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
54470d75337SNathan Whitehorn ofw_real_stop();
545b49db827SBrandon Bergren return (OUT(args.package));
5468446b206SNathan Whitehorn }
5478446b206SNathan Whitehorn
5488446b206SNathan Whitehorn /* Get the length of a property of a package. */
5498446b206SNathan Whitehorn static ssize_t
ofw_real_getproplen(ofw_t ofw,phandle_t package,const char * propname)5508446b206SNathan Whitehorn ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
5518446b206SNathan Whitehorn {
55270d75337SNathan Whitehorn vm_offset_t argsptr;
553d4bccd63SNathan Whitehorn struct {
5548446b206SNathan Whitehorn cell_t name;
5558446b206SNathan Whitehorn cell_t nargs;
5568446b206SNathan Whitehorn cell_t nreturns;
5578446b206SNathan Whitehorn cell_t package;
5588446b206SNathan Whitehorn cell_t propname;
55970d75337SNathan Whitehorn int32_t proplen;
56070d75337SNathan Whitehorn } args;
56170d75337SNathan Whitehorn
562b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"getproplen");
563b49db827SBrandon Bergren args.nargs = IN(2);
564b49db827SBrandon Bergren args.nreturns = IN(1);
5658446b206SNathan Whitehorn
5668446b206SNathan Whitehorn ofw_real_start();
5678446b206SNathan Whitehorn
568b49db827SBrandon Bergren args.package = IN(package);
569b49db827SBrandon Bergren args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
57070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
57170d75337SNathan Whitehorn if (args.propname == 0 || openfirmware((void *)argsptr) == -1) {
5728446b206SNathan Whitehorn ofw_real_stop();
5738446b206SNathan Whitehorn return (-1);
5748446b206SNathan Whitehorn }
57570d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
5768446b206SNathan Whitehorn ofw_real_stop();
577b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.proplen));
5788446b206SNathan Whitehorn }
5798446b206SNathan Whitehorn
5808446b206SNathan Whitehorn /* Get the value of a property of a package. */
5818446b206SNathan Whitehorn static ssize_t
ofw_real_getprop(ofw_t ofw,phandle_t package,const char * propname,void * buf,size_t buflen)5828446b206SNathan Whitehorn ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
5838446b206SNathan Whitehorn size_t buflen)
5848446b206SNathan Whitehorn {
58570d75337SNathan Whitehorn vm_offset_t argsptr;
586d4bccd63SNathan Whitehorn struct {
5878446b206SNathan Whitehorn cell_t name;
5888446b206SNathan Whitehorn cell_t nargs;
5898446b206SNathan Whitehorn cell_t nreturns;
5908446b206SNathan Whitehorn cell_t package;
5918446b206SNathan Whitehorn cell_t propname;
5928446b206SNathan Whitehorn cell_t buf;
5938446b206SNathan Whitehorn cell_t buflen;
59470d75337SNathan Whitehorn int32_t size;
59570d75337SNathan Whitehorn } args;
59670d75337SNathan Whitehorn
597b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"getprop");
598b49db827SBrandon Bergren args.nargs = IN(4);
599b49db827SBrandon Bergren args.nreturns = IN(1);
6008446b206SNathan Whitehorn
6018446b206SNathan Whitehorn ofw_real_start();
6028446b206SNathan Whitehorn
603b49db827SBrandon Bergren args.package = IN(package);
604b49db827SBrandon Bergren args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
605b49db827SBrandon Bergren args.buf = IN(ofw_real_map(buf, buflen));
606b49db827SBrandon Bergren args.buflen = IN(buflen);
60770d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
60870d75337SNathan Whitehorn if (args.propname == 0 || args.buf == 0 ||
60970d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) {
6108446b206SNathan Whitehorn ofw_real_stop();
6118446b206SNathan Whitehorn return (-1);
6128446b206SNathan Whitehorn }
61370d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
614b49db827SBrandon Bergren ofw_real_unmap(OUT(args.buf), buf, buflen);
6158446b206SNathan Whitehorn
6168446b206SNathan Whitehorn ofw_real_stop();
617b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.size));
6188446b206SNathan Whitehorn }
6198446b206SNathan Whitehorn
6208446b206SNathan Whitehorn /* Get the next property of a package. */
6218446b206SNathan Whitehorn static int
ofw_real_nextprop(ofw_t ofw,phandle_t package,const char * previous,char * buf,size_t size)6228446b206SNathan Whitehorn ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
6238446b206SNathan Whitehorn char *buf, size_t size)
6248446b206SNathan Whitehorn {
62570d75337SNathan Whitehorn vm_offset_t argsptr;
626d4bccd63SNathan Whitehorn struct {
6278446b206SNathan Whitehorn cell_t name;
6288446b206SNathan Whitehorn cell_t nargs;
6298446b206SNathan Whitehorn cell_t nreturns;
6308446b206SNathan Whitehorn cell_t package;
6318446b206SNathan Whitehorn cell_t previous;
6328446b206SNathan Whitehorn cell_t buf;
6338446b206SNathan Whitehorn cell_t flag;
63470d75337SNathan Whitehorn } args;
63570d75337SNathan Whitehorn
636b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"nextprop");
637b49db827SBrandon Bergren args.nargs = IN(3);
638b49db827SBrandon Bergren args.nreturns = IN(1);
6398446b206SNathan Whitehorn
6408446b206SNathan Whitehorn ofw_real_start();
6418446b206SNathan Whitehorn
642b49db827SBrandon Bergren args.package = IN(package);
643b49db827SBrandon Bergren args.previous = IN(ofw_real_map(previous, (previous != NULL) ? (strlen(previous) + 1) : 0));
644b49db827SBrandon Bergren args.buf = IN(ofw_real_map(buf, size));
64570d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
646ec664c11SAndreas Tobler if (args.buf == 0 || openfirmware((void *)argsptr) == -1) {
6478446b206SNathan Whitehorn ofw_real_stop();
6488446b206SNathan Whitehorn return (-1);
6498446b206SNathan Whitehorn }
65070d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
651b49db827SBrandon Bergren ofw_real_unmap(OUT(args.buf), buf, size);
6528446b206SNathan Whitehorn
6538446b206SNathan Whitehorn ofw_real_stop();
654b49db827SBrandon Bergren return (OUT(args.flag));
6558446b206SNathan Whitehorn }
6568446b206SNathan Whitehorn
6578446b206SNathan Whitehorn /* Set the value of a property of a package. */
6588446b206SNathan Whitehorn /* XXX Has a bug on FirePower */
6598446b206SNathan Whitehorn static int
ofw_real_setprop(ofw_t ofw,phandle_t package,const char * propname,const void * buf,size_t len)6604fc23012SAndriy Gapon ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
6614fc23012SAndriy Gapon const void *buf, size_t len)
6628446b206SNathan Whitehorn {
66370d75337SNathan Whitehorn vm_offset_t argsptr;
664d4bccd63SNathan Whitehorn struct {
6658446b206SNathan Whitehorn cell_t name;
6668446b206SNathan Whitehorn cell_t nargs;
6678446b206SNathan Whitehorn cell_t nreturns;
6688446b206SNathan Whitehorn cell_t package;
6698446b206SNathan Whitehorn cell_t propname;
6708446b206SNathan Whitehorn cell_t buf;
6718446b206SNathan Whitehorn cell_t len;
6728446b206SNathan Whitehorn cell_t size;
67370d75337SNathan Whitehorn } args;
67470d75337SNathan Whitehorn
675b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"setprop");
676b49db827SBrandon Bergren args.nargs = IN(4);
677b49db827SBrandon Bergren args.nreturns = IN(1);
6788446b206SNathan Whitehorn
6798446b206SNathan Whitehorn ofw_real_start();
6808446b206SNathan Whitehorn
681b49db827SBrandon Bergren args.package = IN(package);
682b49db827SBrandon Bergren args.propname = IN(ofw_real_map(propname, strlen(propname) + 1));
683b49db827SBrandon Bergren args.buf = IN(ofw_real_map(buf, len));
684b49db827SBrandon Bergren args.len = IN(len);
68570d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
68670d75337SNathan Whitehorn if (args.propname == 0 || args.buf == 0 ||
68770d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) {
6888446b206SNathan Whitehorn ofw_real_stop();
6898446b206SNathan Whitehorn return (-1);
6908446b206SNathan Whitehorn }
69170d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
6928446b206SNathan Whitehorn ofw_real_stop();
693b49db827SBrandon Bergren return (OUT(args.size));
6948446b206SNathan Whitehorn }
6958446b206SNathan Whitehorn
6968446b206SNathan Whitehorn /* Convert a device specifier to a fully qualified pathname. */
6978446b206SNathan Whitehorn static ssize_t
ofw_real_canon(ofw_t ofw,const char * device,char * buf,size_t len)6988446b206SNathan Whitehorn ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
6998446b206SNathan Whitehorn {
70070d75337SNathan Whitehorn vm_offset_t argsptr;
701d4bccd63SNathan Whitehorn struct {
7028446b206SNathan Whitehorn cell_t name;
7038446b206SNathan Whitehorn cell_t nargs;
7048446b206SNathan Whitehorn cell_t nreturns;
7058446b206SNathan Whitehorn cell_t device;
7068446b206SNathan Whitehorn cell_t buf;
7078446b206SNathan Whitehorn cell_t len;
70870d75337SNathan Whitehorn int32_t size;
70970d75337SNathan Whitehorn } args;
71070d75337SNathan Whitehorn
711b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"canon");
712b49db827SBrandon Bergren args.nargs = IN(3);
713b49db827SBrandon Bergren args.nreturns = IN(1);
7148446b206SNathan Whitehorn
7158446b206SNathan Whitehorn ofw_real_start();
7168446b206SNathan Whitehorn
717b49db827SBrandon Bergren args.device = IN(ofw_real_map(device, strlen(device) + 1));
718b49db827SBrandon Bergren args.buf = IN(ofw_real_map(buf, len));
719b49db827SBrandon Bergren args.len = IN(len);
72070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
72170d75337SNathan Whitehorn if (args.device == 0 || args.buf == 0 ||
72270d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) {
7238446b206SNathan Whitehorn ofw_real_stop();
7248446b206SNathan Whitehorn return (-1);
7258446b206SNathan Whitehorn }
72670d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
727b49db827SBrandon Bergren ofw_real_unmap(OUT(args.buf), buf, len);
7288446b206SNathan Whitehorn
7298446b206SNathan Whitehorn ofw_real_stop();
730b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.size));
7318446b206SNathan Whitehorn }
7328446b206SNathan Whitehorn
7338446b206SNathan Whitehorn /* Return a package handle for the specified device. */
7348446b206SNathan Whitehorn static phandle_t
ofw_real_finddevice(ofw_t ofw,const char * device)7358446b206SNathan Whitehorn ofw_real_finddevice(ofw_t ofw, const char *device)
7368446b206SNathan Whitehorn {
73770d75337SNathan Whitehorn vm_offset_t argsptr;
738d4bccd63SNathan Whitehorn struct {
7398446b206SNathan Whitehorn cell_t name;
7408446b206SNathan Whitehorn cell_t nargs;
7418446b206SNathan Whitehorn cell_t nreturns;
7428446b206SNathan Whitehorn cell_t device;
7438446b206SNathan Whitehorn cell_t package;
74470d75337SNathan Whitehorn } args;
74570d75337SNathan Whitehorn
746b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"finddevice");
747b49db827SBrandon Bergren args.nargs = IN(1);
748b49db827SBrandon Bergren args.nreturns = IN(1);
7498446b206SNathan Whitehorn
7508446b206SNathan Whitehorn ofw_real_start();
7518446b206SNathan Whitehorn
752b49db827SBrandon Bergren args.device = IN(ofw_real_map(device, strlen(device) + 1));
75370d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
75470d75337SNathan Whitehorn if (args.device == 0 ||
75570d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) {
7568446b206SNathan Whitehorn ofw_real_stop();
7578446b206SNathan Whitehorn return (-1);
7588446b206SNathan Whitehorn }
75970d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
7608446b206SNathan Whitehorn ofw_real_stop();
761b49db827SBrandon Bergren return (OUT(args.package));
7628446b206SNathan Whitehorn }
7638446b206SNathan Whitehorn
7648446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to an instance. */
7658446b206SNathan Whitehorn static ssize_t
ofw_real_instance_to_path(ofw_t ofw,ihandle_t instance,char * buf,size_t len)7668446b206SNathan Whitehorn ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
7678446b206SNathan Whitehorn {
76870d75337SNathan Whitehorn vm_offset_t argsptr;
769d4bccd63SNathan Whitehorn struct {
7708446b206SNathan Whitehorn cell_t name;
7718446b206SNathan Whitehorn cell_t nargs;
7728446b206SNathan Whitehorn cell_t nreturns;
7738446b206SNathan Whitehorn cell_t instance;
7748446b206SNathan Whitehorn cell_t buf;
7758446b206SNathan Whitehorn cell_t len;
77670d75337SNathan Whitehorn int32_t size;
77770d75337SNathan Whitehorn } args;
77870d75337SNathan Whitehorn
779b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"instance-to-path");
780b49db827SBrandon Bergren args.nargs = IN(3);
781b49db827SBrandon Bergren args.nreturns = IN(1);
7828446b206SNathan Whitehorn
7838446b206SNathan Whitehorn ofw_real_start();
7848446b206SNathan Whitehorn
785b49db827SBrandon Bergren args.instance = IN(instance);
786b49db827SBrandon Bergren args.buf = IN(ofw_real_map(buf, len));
787b49db827SBrandon Bergren args.len = IN(len);
78870d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
78970d75337SNathan Whitehorn if (args.buf == 0 ||
79070d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) {
7918446b206SNathan Whitehorn ofw_real_stop();
7928446b206SNathan Whitehorn return (-1);
7938446b206SNathan Whitehorn }
79470d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
795b49db827SBrandon Bergren ofw_real_unmap(OUT(args.buf), buf, len);
7968446b206SNathan Whitehorn
7978446b206SNathan Whitehorn ofw_real_stop();
798b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.size));
7998446b206SNathan Whitehorn }
8008446b206SNathan Whitehorn
8018446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to a package. */
8028446b206SNathan Whitehorn static ssize_t
ofw_real_package_to_path(ofw_t ofw,phandle_t package,char * buf,size_t len)8038446b206SNathan Whitehorn ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
8048446b206SNathan Whitehorn {
80570d75337SNathan Whitehorn vm_offset_t argsptr;
806d4bccd63SNathan Whitehorn struct {
8078446b206SNathan Whitehorn cell_t name;
8088446b206SNathan Whitehorn cell_t nargs;
8098446b206SNathan Whitehorn cell_t nreturns;
8108446b206SNathan Whitehorn cell_t package;
8118446b206SNathan Whitehorn cell_t buf;
8128446b206SNathan Whitehorn cell_t len;
81370d75337SNathan Whitehorn int32_t size;
81470d75337SNathan Whitehorn } args;
81570d75337SNathan Whitehorn
816b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"package-to-path");
817b49db827SBrandon Bergren args.nargs = IN(3);
818b49db827SBrandon Bergren args.nreturns = IN(1);
8198446b206SNathan Whitehorn
8208446b206SNathan Whitehorn ofw_real_start();
8218446b206SNathan Whitehorn
822b49db827SBrandon Bergren args.package = IN(package);
823b49db827SBrandon Bergren args.buf = IN(ofw_real_map(buf, len));
824b49db827SBrandon Bergren args.len = IN(len);
82570d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
82670d75337SNathan Whitehorn if (args.buf == 0 ||
82770d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) {
8288446b206SNathan Whitehorn ofw_real_stop();
8298446b206SNathan Whitehorn return (-1);
8308446b206SNathan Whitehorn }
83170d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
832b49db827SBrandon Bergren ofw_real_unmap(OUT(args.buf), buf, len);
8338446b206SNathan Whitehorn
8348446b206SNathan Whitehorn ofw_real_stop();
835b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.size));
8368446b206SNathan Whitehorn }
8378446b206SNathan Whitehorn
8388446b206SNathan Whitehorn /* Call the method in the scope of a given instance. */
8398446b206SNathan Whitehorn static int
ofw_real_call_method(ofw_t ofw,ihandle_t instance,const char * method,int nargs,int nreturns,cell_t * args_and_returns)8408446b206SNathan Whitehorn ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
841054e5dcbSNathan Whitehorn int nargs, int nreturns, cell_t *args_and_returns)
8428446b206SNathan Whitehorn {
84370d75337SNathan Whitehorn vm_offset_t argsptr;
844d4bccd63SNathan Whitehorn struct {
8458446b206SNathan Whitehorn cell_t name;
8468446b206SNathan Whitehorn cell_t nargs;
8478446b206SNathan Whitehorn cell_t nreturns;
8488446b206SNathan Whitehorn cell_t method;
8498446b206SNathan Whitehorn cell_t instance;
8508446b206SNathan Whitehorn cell_t args_n_results[12];
85170d75337SNathan Whitehorn } args;
852cdb25d82SMarius Strobl cell_t *ap, *cp;
8538446b206SNathan Whitehorn int n;
8548446b206SNathan Whitehorn
855b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"call-method");
856b49db827SBrandon Bergren args.nargs = IN(2);
857b49db827SBrandon Bergren args.nreturns = IN(1);
85870d75337SNathan Whitehorn
8598446b206SNathan Whitehorn if (nargs > 6)
8608446b206SNathan Whitehorn return (-1);
8618446b206SNathan Whitehorn
8628446b206SNathan Whitehorn ofw_real_start();
863b49db827SBrandon Bergren args.nargs = IN(nargs + 2);
864b49db827SBrandon Bergren args.nreturns = IN(nreturns + 1);
865b49db827SBrandon Bergren args.method = IN(ofw_real_map(method, strlen(method) + 1));
866b49db827SBrandon Bergren args.instance = IN(instance);
8678446b206SNathan Whitehorn
8688446b206SNathan Whitehorn ap = args_and_returns;
8698446b206SNathan Whitehorn for (cp = args.args_n_results + (n = nargs); --n >= 0;)
870b49db827SBrandon Bergren *--cp = IN(*(ap++));
87170d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
87270d75337SNathan Whitehorn if (args.method == 0 ||
87370d75337SNathan Whitehorn openfirmware((void *)argsptr) == -1) {
8748446b206SNathan Whitehorn ofw_real_stop();
8758446b206SNathan Whitehorn return (-1);
8768446b206SNathan Whitehorn }
87770d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
8788446b206SNathan Whitehorn ofw_real_stop();
879b49db827SBrandon Bergren if (OUT(args.args_n_results[nargs]))
880b49db827SBrandon Bergren return (OUT(args.args_n_results[nargs]));
881b49db827SBrandon Bergren for (cp = args.args_n_results + nargs + (n = OUT(args.nreturns)); --n > 0;)
882b49db827SBrandon Bergren *(ap++) = OUT(*--cp);
8838446b206SNathan Whitehorn return (0);
8848446b206SNathan Whitehorn }
8858446b206SNathan Whitehorn
88670d75337SNathan Whitehorn static int
ofw_real_interpret(ofw_t ofw,const char * cmd,int nreturns,cell_t * returns)887cdb25d82SMarius Strobl ofw_real_interpret(ofw_t ofw, const char *cmd, int nreturns, cell_t *returns)
88870d75337SNathan Whitehorn {
88970d75337SNathan Whitehorn vm_offset_t argsptr;
89070d75337SNathan Whitehorn struct {
89170d75337SNathan Whitehorn cell_t name;
89270d75337SNathan Whitehorn cell_t nargs;
89370d75337SNathan Whitehorn cell_t nreturns;
89470d75337SNathan Whitehorn cell_t slot[16];
89570d75337SNathan Whitehorn } args;
89670d75337SNathan Whitehorn cell_t status;
89770d75337SNathan Whitehorn int i = 0, j = 0;
89870d75337SNathan Whitehorn
899b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"interpret");
900b49db827SBrandon Bergren args.nargs = IN(1);
90170d75337SNathan Whitehorn
90270d75337SNathan Whitehorn ofw_real_start();
903b49db827SBrandon Bergren args.nreturns = IN(++nreturns);
904b49db827SBrandon Bergren args.slot[i++] = IN(ofw_real_map(cmd, strlen(cmd) + 1));
90570d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
90670d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) {
90770d75337SNathan Whitehorn ofw_real_stop();
90870d75337SNathan Whitehorn return (-1);
90970d75337SNathan Whitehorn }
91070d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
91170d75337SNathan Whitehorn ofw_real_stop();
912b49db827SBrandon Bergren status = OUT(args.slot[i++]);
91370d75337SNathan Whitehorn while (i < 1 + nreturns)
914b49db827SBrandon Bergren returns[j++] = OUT(args.slot[i++]);
91570d75337SNathan Whitehorn return (status);
91670d75337SNathan Whitehorn }
91770d75337SNathan Whitehorn
9188446b206SNathan Whitehorn /*
9198446b206SNathan Whitehorn * Device I/O functions
9208446b206SNathan Whitehorn */
9218446b206SNathan Whitehorn
9228446b206SNathan Whitehorn /* Open an instance for a device. */
9238446b206SNathan Whitehorn static ihandle_t
ofw_real_open(ofw_t ofw,const char * device)9248446b206SNathan Whitehorn ofw_real_open(ofw_t ofw, const char *device)
9258446b206SNathan Whitehorn {
92670d75337SNathan Whitehorn vm_offset_t argsptr;
927d4bccd63SNathan Whitehorn struct {
9288446b206SNathan Whitehorn cell_t name;
9298446b206SNathan Whitehorn cell_t nargs;
9308446b206SNathan Whitehorn cell_t nreturns;
9318446b206SNathan Whitehorn cell_t device;
9328446b206SNathan Whitehorn cell_t instance;
93370d75337SNathan Whitehorn } args;
93470d75337SNathan Whitehorn
935b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"open");
936b49db827SBrandon Bergren args.nargs = IN(1);
937b49db827SBrandon Bergren args.nreturns = IN(1);
9388446b206SNathan Whitehorn
9398446b206SNathan Whitehorn ofw_real_start();
9408446b206SNathan Whitehorn
941b49db827SBrandon Bergren args.device = IN(ofw_real_map(device, strlen(device) + 1));
94270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
94370d75337SNathan Whitehorn if (args.device == 0 || openfirmware((void *)argsptr) == -1
9448446b206SNathan Whitehorn || args.instance == 0) {
9458446b206SNathan Whitehorn ofw_real_stop();
9468446b206SNathan Whitehorn return (-1);
9478446b206SNathan Whitehorn }
94870d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
9498446b206SNathan Whitehorn ofw_real_stop();
950b49db827SBrandon Bergren return (OUT(args.instance));
9518446b206SNathan Whitehorn }
9528446b206SNathan Whitehorn
9538446b206SNathan Whitehorn /* Close an instance. */
9548446b206SNathan Whitehorn static void
ofw_real_close(ofw_t ofw,ihandle_t instance)9558446b206SNathan Whitehorn ofw_real_close(ofw_t ofw, ihandle_t instance)
9568446b206SNathan Whitehorn {
95770d75337SNathan Whitehorn vm_offset_t argsptr;
958d4bccd63SNathan Whitehorn struct {
9598446b206SNathan Whitehorn cell_t name;
9608446b206SNathan Whitehorn cell_t nargs;
9618446b206SNathan Whitehorn cell_t nreturns;
9628446b206SNathan Whitehorn cell_t instance;
96370d75337SNathan Whitehorn } args;
9648446b206SNathan Whitehorn
965b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"close");
966b49db827SBrandon Bergren args.nargs = IN(1);
967b49db827SBrandon Bergren args.nreturns = IN(0);
968b49db827SBrandon Bergren args.instance = IN(instance);
96970d75337SNathan Whitehorn ofw_real_start();
97070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
97170d75337SNathan Whitehorn openfirmware((void *)argsptr);
97270d75337SNathan Whitehorn ofw_real_stop();
9738446b206SNathan Whitehorn }
9748446b206SNathan Whitehorn
9758446b206SNathan Whitehorn /* Read from an instance. */
9768446b206SNathan Whitehorn static ssize_t
ofw_real_read(ofw_t ofw,ihandle_t instance,void * addr,size_t len)9778446b206SNathan Whitehorn ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
9788446b206SNathan Whitehorn {
97970d75337SNathan Whitehorn vm_offset_t argsptr;
980d4bccd63SNathan Whitehorn struct {
9818446b206SNathan Whitehorn cell_t name;
9828446b206SNathan Whitehorn cell_t nargs;
9838446b206SNathan Whitehorn cell_t nreturns;
9848446b206SNathan Whitehorn cell_t instance;
9858446b206SNathan Whitehorn cell_t addr;
9868446b206SNathan Whitehorn cell_t len;
98770d75337SNathan Whitehorn int32_t actual;
98870d75337SNathan Whitehorn } args;
98970d75337SNathan Whitehorn
990b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"read");
991b49db827SBrandon Bergren args.nargs = IN(3);
992b49db827SBrandon Bergren args.nreturns = IN(1);
9938446b206SNathan Whitehorn
9948446b206SNathan Whitehorn ofw_real_start();
9958446b206SNathan Whitehorn
996b49db827SBrandon Bergren args.instance = IN(instance);
997b49db827SBrandon Bergren args.addr = IN(ofw_real_map(addr, len));
998b49db827SBrandon Bergren args.len = IN(len);
99970d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
100070d75337SNathan Whitehorn if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
10018446b206SNathan Whitehorn ofw_real_stop();
10028446b206SNathan Whitehorn return (-1);
10038446b206SNathan Whitehorn }
100470d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
1005b49db827SBrandon Bergren ofw_real_unmap(OUT(args.addr), addr, len);
10068446b206SNathan Whitehorn
10078446b206SNathan Whitehorn ofw_real_stop();
1008b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.actual));
10098446b206SNathan Whitehorn }
10108446b206SNathan Whitehorn
10118446b206SNathan Whitehorn /* Write to an instance. */
10128446b206SNathan Whitehorn static ssize_t
ofw_real_write(ofw_t ofw,ihandle_t instance,const void * addr,size_t len)10138446b206SNathan Whitehorn ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
10148446b206SNathan Whitehorn {
101570d75337SNathan Whitehorn vm_offset_t argsptr;
1016d4bccd63SNathan Whitehorn struct {
10178446b206SNathan Whitehorn cell_t name;
10188446b206SNathan Whitehorn cell_t nargs;
10198446b206SNathan Whitehorn cell_t nreturns;
10208446b206SNathan Whitehorn cell_t instance;
10218446b206SNathan Whitehorn cell_t addr;
10228446b206SNathan Whitehorn cell_t len;
102370d75337SNathan Whitehorn int32_t actual;
102470d75337SNathan Whitehorn } args;
102570d75337SNathan Whitehorn
1026b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"write");
1027b49db827SBrandon Bergren args.nargs = IN(3);
1028b49db827SBrandon Bergren args.nreturns = IN(1);
10298446b206SNathan Whitehorn
10308446b206SNathan Whitehorn ofw_real_start();
10318446b206SNathan Whitehorn
1032b49db827SBrandon Bergren args.instance = IN(instance);
1033b49db827SBrandon Bergren args.addr = IN(ofw_real_map(addr, len));
1034b49db827SBrandon Bergren args.len = IN(len);
103570d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
103670d75337SNathan Whitehorn if (args.addr == 0 || openfirmware((void *)argsptr) == -1) {
10378446b206SNathan Whitehorn ofw_real_stop();
10388446b206SNathan Whitehorn return (-1);
10398446b206SNathan Whitehorn }
104070d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
10418446b206SNathan Whitehorn ofw_real_stop();
1042b49db827SBrandon Bergren return ((ssize_t)(int32_t)OUT(args.actual));
10438446b206SNathan Whitehorn }
10448446b206SNathan Whitehorn
10458446b206SNathan Whitehorn /* Seek to a position. */
10468446b206SNathan Whitehorn static int
ofw_real_seek(ofw_t ofw,ihandle_t instance,u_int64_t pos)10478446b206SNathan Whitehorn ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
10488446b206SNathan Whitehorn {
104970d75337SNathan Whitehorn vm_offset_t argsptr;
1050d4bccd63SNathan Whitehorn struct {
10518446b206SNathan Whitehorn cell_t name;
10528446b206SNathan Whitehorn cell_t nargs;
10538446b206SNathan Whitehorn cell_t nreturns;
10548446b206SNathan Whitehorn cell_t instance;
10558446b206SNathan Whitehorn cell_t poshi;
10568446b206SNathan Whitehorn cell_t poslo;
10578446b206SNathan Whitehorn cell_t status;
105870d75337SNathan Whitehorn } args;
105970d75337SNathan Whitehorn
1060b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"seek");
1061b49db827SBrandon Bergren args.nargs = IN(3);
1062b49db827SBrandon Bergren args.nreturns = IN(1);
10638446b206SNathan Whitehorn
1064b49db827SBrandon Bergren args.instance = IN(instance);
1065b49db827SBrandon Bergren args.poshi = IN(pos >> 32);
1066b49db827SBrandon Bergren args.poslo = IN(pos);
106770d75337SNathan Whitehorn ofw_real_start();
106870d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
106970d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) {
107070d75337SNathan Whitehorn ofw_real_stop();
10718446b206SNathan Whitehorn return (-1);
107270d75337SNathan Whitehorn }
107370d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
107470d75337SNathan Whitehorn ofw_real_stop();
1075b49db827SBrandon Bergren return (OUT(args.status));
10768446b206SNathan Whitehorn }
10778446b206SNathan Whitehorn
10788446b206SNathan Whitehorn /*
10798446b206SNathan Whitehorn * Memory functions
10808446b206SNathan Whitehorn */
10818446b206SNathan Whitehorn
10828446b206SNathan Whitehorn /* Claim an area of memory. */
10838446b206SNathan Whitehorn static caddr_t
ofw_real_claim(ofw_t ofw,void * virt,size_t size,u_int align)10848446b206SNathan Whitehorn ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
10858446b206SNathan Whitehorn {
108670d75337SNathan Whitehorn vm_offset_t argsptr;
1087d4bccd63SNathan Whitehorn struct {
10888446b206SNathan Whitehorn cell_t name;
10898446b206SNathan Whitehorn cell_t nargs;
10908446b206SNathan Whitehorn cell_t nreturns;
10918446b206SNathan Whitehorn cell_t virt;
10928446b206SNathan Whitehorn cell_t size;
10938446b206SNathan Whitehorn cell_t align;
10948446b206SNathan Whitehorn cell_t baseaddr;
109570d75337SNathan Whitehorn } args;
10968446b206SNathan Whitehorn
1097b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"claim");
1098b49db827SBrandon Bergren args.nargs = IN(3);
1099b49db827SBrandon Bergren args.nreturns = IN(1);
110070d75337SNathan Whitehorn
1101b49db827SBrandon Bergren args.virt = IN((cell_t)(uintptr_t)virt);
1102b49db827SBrandon Bergren args.size = IN(size);
1103b49db827SBrandon Bergren args.align = IN(align);
110470d75337SNathan Whitehorn ofw_real_start();
110570d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
110670d75337SNathan Whitehorn if (openfirmware((void *)argsptr) == -1) {
110770d75337SNathan Whitehorn ofw_real_stop();
11088446b206SNathan Whitehorn return ((void *)-1);
110970d75337SNathan Whitehorn }
111070d75337SNathan Whitehorn ofw_real_unmap(argsptr, &args, sizeof(args));
111170d75337SNathan Whitehorn ofw_real_stop();
1112b49db827SBrandon Bergren return ((void *)(uintptr_t)(OUT(args.baseaddr)));
11138446b206SNathan Whitehorn }
11148446b206SNathan Whitehorn
11158446b206SNathan Whitehorn /* Release an area of memory. */
11168446b206SNathan Whitehorn static void
ofw_real_release(ofw_t ofw,void * virt,size_t size)11178446b206SNathan Whitehorn ofw_real_release(ofw_t ofw, void *virt, size_t size)
11188446b206SNathan Whitehorn {
111970d75337SNathan Whitehorn vm_offset_t argsptr;
1120d4bccd63SNathan Whitehorn struct {
11218446b206SNathan Whitehorn cell_t name;
11228446b206SNathan Whitehorn cell_t nargs;
11238446b206SNathan Whitehorn cell_t nreturns;
11248446b206SNathan Whitehorn cell_t virt;
11258446b206SNathan Whitehorn cell_t size;
112670d75337SNathan Whitehorn } args;
11278446b206SNathan Whitehorn
1128b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"release");
1129b49db827SBrandon Bergren args.nargs = IN(2);
1130b49db827SBrandon Bergren args.nreturns = IN(0);
113170d75337SNathan Whitehorn
1132b49db827SBrandon Bergren args.virt = IN((cell_t)(uintptr_t)virt);
1133b49db827SBrandon Bergren args.size = IN(size);
113470d75337SNathan Whitehorn ofw_real_start();
113570d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
113670d75337SNathan Whitehorn openfirmware((void *)argsptr);
113770d75337SNathan Whitehorn ofw_real_stop();
11388446b206SNathan Whitehorn }
11398446b206SNathan Whitehorn
11408446b206SNathan Whitehorn /*
11418446b206SNathan Whitehorn * Control transfer functions
11428446b206SNathan Whitehorn */
11438446b206SNathan Whitehorn
11448446b206SNathan Whitehorn /* Suspend and drop back to the Open Firmware interface. */
11458446b206SNathan Whitehorn static void
ofw_real_enter(ofw_t ofw)11468446b206SNathan Whitehorn ofw_real_enter(ofw_t ofw)
11478446b206SNathan Whitehorn {
114870d75337SNathan Whitehorn vm_offset_t argsptr;
1149d4bccd63SNathan Whitehorn struct {
11508446b206SNathan Whitehorn cell_t name;
11518446b206SNathan Whitehorn cell_t nargs;
11528446b206SNathan Whitehorn cell_t nreturns;
115370d75337SNathan Whitehorn } args;
11548446b206SNathan Whitehorn
1155b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"enter");
1156b49db827SBrandon Bergren args.nargs = IN(0);
1157b49db827SBrandon Bergren args.nreturns = IN(0);
115870d75337SNathan Whitehorn
115970d75337SNathan Whitehorn ofw_real_start();
116070d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
116170d75337SNathan Whitehorn openfirmware((void *)argsptr);
11628446b206SNathan Whitehorn /* We may come back. */
116370d75337SNathan Whitehorn ofw_real_stop();
11648446b206SNathan Whitehorn }
11658446b206SNathan Whitehorn
11668446b206SNathan Whitehorn /* Shut down and drop back to the Open Firmware interface. */
11678446b206SNathan Whitehorn static void
ofw_real_exit(ofw_t ofw)11688446b206SNathan Whitehorn ofw_real_exit(ofw_t ofw)
11698446b206SNathan Whitehorn {
117070d75337SNathan Whitehorn vm_offset_t argsptr;
1171d4bccd63SNathan Whitehorn struct {
11728446b206SNathan Whitehorn cell_t name;
11738446b206SNathan Whitehorn cell_t nargs;
11748446b206SNathan Whitehorn cell_t nreturns;
117570d75337SNathan Whitehorn } args;
11768446b206SNathan Whitehorn
1177b49db827SBrandon Bergren args.name = IN((cell_t)(uintptr_t)"exit");
1178b49db827SBrandon Bergren args.nargs = IN(0);
1179b49db827SBrandon Bergren args.nreturns = IN(0);
118070d75337SNathan Whitehorn
118170d75337SNathan Whitehorn ofw_real_start();
118270d75337SNathan Whitehorn argsptr = ofw_real_map(&args, sizeof(args));
118370d75337SNathan Whitehorn openfirmware((void *)argsptr);
11848446b206SNathan Whitehorn for (;;) /* just in case */
11858446b206SNathan Whitehorn ;
118670d75337SNathan Whitehorn ofw_real_stop();
11878446b206SNathan Whitehorn }
1188