xref: /freebsd/sys/powerpc/ofw/ofw_real.c (revision 8297758a)
18446b206SNathan Whitehorn /*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $	*/
28446b206SNathan Whitehorn 
38446b206SNathan Whitehorn /*-
48446b206SNathan Whitehorn  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
58446b206SNathan Whitehorn  * Copyright (C) 1995, 1996 TooLs GmbH.
68446b206SNathan Whitehorn  * All rights reserved.
78446b206SNathan Whitehorn  *
88446b206SNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
98446b206SNathan Whitehorn  * modification, are permitted provided that the following conditions
108446b206SNathan Whitehorn  * are met:
118446b206SNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
128446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
138446b206SNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
148446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
158446b206SNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
168446b206SNathan Whitehorn  * 3. All advertising materials mentioning features or use of this software
178446b206SNathan Whitehorn  *    must display the following acknowledgement:
188446b206SNathan Whitehorn  *	This product includes software developed by TooLs GmbH.
198446b206SNathan Whitehorn  * 4. The name of TooLs GmbH may not be used to endorse or promote products
208446b206SNathan Whitehorn  *    derived from this software without specific prior written permission.
218446b206SNathan Whitehorn  *
228446b206SNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
238446b206SNathan Whitehorn  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
248446b206SNathan Whitehorn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
258446b206SNathan Whitehorn  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
268446b206SNathan Whitehorn  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
278446b206SNathan Whitehorn  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
288446b206SNathan Whitehorn  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
298446b206SNathan Whitehorn  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
308446b206SNathan Whitehorn  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
318446b206SNathan Whitehorn  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
328446b206SNathan Whitehorn  */
338446b206SNathan Whitehorn /*-
348446b206SNathan Whitehorn  * Copyright (C) 2000 Benno Rice.
358446b206SNathan Whitehorn  * All rights reserved.
368446b206SNathan Whitehorn  *
378446b206SNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
388446b206SNathan Whitehorn  * modification, are permitted provided that the following conditions
398446b206SNathan Whitehorn  * are met:
408446b206SNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
418446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
428446b206SNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
438446b206SNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
448446b206SNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
458446b206SNathan Whitehorn  *
468446b206SNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
478446b206SNathan Whitehorn  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
488446b206SNathan Whitehorn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
498446b206SNathan Whitehorn  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
508446b206SNathan Whitehorn  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
518446b206SNathan Whitehorn  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
528446b206SNathan Whitehorn  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
538446b206SNathan Whitehorn  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
548446b206SNathan Whitehorn  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
558446b206SNathan Whitehorn  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
568446b206SNathan Whitehorn  */
578446b206SNathan Whitehorn 
588446b206SNathan Whitehorn #include <sys/cdefs.h>
598446b206SNathan Whitehorn __FBSDID("$FreeBSD$");
608446b206SNathan Whitehorn 
618446b206SNathan Whitehorn #include <sys/param.h>
628446b206SNathan Whitehorn #include <sys/kernel.h>
638446b206SNathan Whitehorn #include <sys/lock.h>
648446b206SNathan Whitehorn #include <sys/mutex.h>
658446b206SNathan Whitehorn #include <sys/systm.h>
668446b206SNathan Whitehorn 
678446b206SNathan Whitehorn #include <vm/vm.h>
688446b206SNathan Whitehorn #include <vm/pmap.h>
698446b206SNathan Whitehorn 
708446b206SNathan Whitehorn #include <machine/stdarg.h>
718446b206SNathan Whitehorn #include <machine/bus.h>
728446b206SNathan Whitehorn #include <machine/pmap.h>
738446b206SNathan Whitehorn #include <machine/ofw_machdep.h>
748446b206SNathan Whitehorn 
758446b206SNathan Whitehorn #include <dev/ofw/openfirm.h>
768446b206SNathan Whitehorn #include <dev/ofw/ofwvar.h>
778446b206SNathan Whitehorn #include "ofw_if.h"
788446b206SNathan Whitehorn 
798297758aSRafal Jaworowski static int ofw_real_init(ofw_t, void *openfirm);
808446b206SNathan Whitehorn static int ofw_real_test(ofw_t, const char *name);
818446b206SNathan Whitehorn static phandle_t ofw_real_peer(ofw_t, phandle_t node);
828446b206SNathan Whitehorn static phandle_t ofw_real_child(ofw_t, phandle_t node);
838446b206SNathan Whitehorn static phandle_t ofw_real_parent(ofw_t, phandle_t node);
848446b206SNathan Whitehorn static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
858446b206SNathan Whitehorn static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
868446b206SNathan Whitehorn     const char *propname);
878446b206SNathan Whitehorn static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
888446b206SNathan Whitehorn     void *buf, size_t buflen);
898446b206SNathan Whitehorn static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
908446b206SNathan Whitehorn     char *buf, size_t);
914fc23012SAndriy Gapon static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname,
924fc23012SAndriy Gapon     const void *buf, size_t len);
938446b206SNathan Whitehorn static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
948446b206SNathan Whitehorn static phandle_t ofw_real_finddevice(ofw_t, const char *device);
958446b206SNathan Whitehorn static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
968446b206SNathan Whitehorn     size_t len);
978446b206SNathan Whitehorn static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
988446b206SNathan Whitehorn     size_t len);
998446b206SNathan Whitehorn static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
1008446b206SNathan Whitehorn     int nargs, int nreturns, unsigned long *args_and_returns);
1018446b206SNathan Whitehorn static ihandle_t ofw_real_open(ofw_t, const char *device);
1028446b206SNathan Whitehorn static void ofw_real_close(ofw_t, ihandle_t instance);
1038446b206SNathan Whitehorn static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
1048446b206SNathan Whitehorn static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
1058446b206SNathan Whitehorn     size_t len);
1068446b206SNathan Whitehorn static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
1078446b206SNathan Whitehorn static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
1088446b206SNathan Whitehorn static void ofw_real_release(ofw_t, void *virt, size_t size);
1098446b206SNathan Whitehorn static void ofw_real_enter(ofw_t);
1108446b206SNathan Whitehorn static void ofw_real_exit(ofw_t);
1118446b206SNathan Whitehorn 
1128446b206SNathan Whitehorn static ofw_method_t ofw_real_methods[] = {
1138446b206SNathan Whitehorn 	OFWMETHOD(ofw_init,			ofw_real_init),
1148446b206SNathan Whitehorn 	OFWMETHOD(ofw_peer,			ofw_real_peer),
1158446b206SNathan Whitehorn 	OFWMETHOD(ofw_child,			ofw_real_child),
1168446b206SNathan Whitehorn 	OFWMETHOD(ofw_parent,			ofw_real_parent),
1178446b206SNathan Whitehorn 	OFWMETHOD(ofw_instance_to_package,	ofw_real_instance_to_package),
1188446b206SNathan Whitehorn 	OFWMETHOD(ofw_getproplen,		ofw_real_getproplen),
1198446b206SNathan Whitehorn 	OFWMETHOD(ofw_getprop,			ofw_real_getprop),
1208446b206SNathan Whitehorn 	OFWMETHOD(ofw_nextprop,			ofw_real_nextprop),
1218446b206SNathan Whitehorn 	OFWMETHOD(ofw_setprop,			ofw_real_setprop),
1228446b206SNathan Whitehorn 	OFWMETHOD(ofw_canon,			ofw_real_canon),
1238446b206SNathan Whitehorn 	OFWMETHOD(ofw_finddevice,		ofw_real_finddevice),
1248446b206SNathan Whitehorn 	OFWMETHOD(ofw_instance_to_path,		ofw_real_instance_to_path),
1258446b206SNathan Whitehorn 	OFWMETHOD(ofw_package_to_path,		ofw_real_package_to_path),
1268446b206SNathan Whitehorn 
1278446b206SNathan Whitehorn 	OFWMETHOD(ofw_test,			ofw_real_test),
1288446b206SNathan Whitehorn 	OFWMETHOD(ofw_call_method,		ofw_real_call_method),
1298446b206SNathan Whitehorn 	OFWMETHOD(ofw_open,			ofw_real_open),
1308446b206SNathan Whitehorn 	OFWMETHOD(ofw_close,			ofw_real_close),
1318446b206SNathan Whitehorn 	OFWMETHOD(ofw_read,			ofw_real_read),
1328446b206SNathan Whitehorn 	OFWMETHOD(ofw_write,			ofw_real_write),
1338446b206SNathan Whitehorn 	OFWMETHOD(ofw_seek,			ofw_real_seek),
1348446b206SNathan Whitehorn 	OFWMETHOD(ofw_claim,			ofw_real_claim),
1358446b206SNathan Whitehorn 	OFWMETHOD(ofw_release,			ofw_real_release),
1368446b206SNathan Whitehorn 	OFWMETHOD(ofw_enter,			ofw_real_enter),
1378446b206SNathan Whitehorn 	OFWMETHOD(ofw_exit,			ofw_real_exit),
1388446b206SNathan Whitehorn 
1398446b206SNathan Whitehorn 	{ 0, 0 }
1408446b206SNathan Whitehorn };
1418446b206SNathan Whitehorn 
1428446b206SNathan Whitehorn static ofw_def_t ofw_real = {
1438446b206SNathan Whitehorn 	OFW_STD_REAL,
1448446b206SNathan Whitehorn 	ofw_real_methods,
1458446b206SNathan Whitehorn 	0
1468446b206SNathan Whitehorn };
1478446b206SNathan Whitehorn OFW_DEF(ofw_real);
1488446b206SNathan Whitehorn 
1498446b206SNathan Whitehorn MALLOC_DEFINE(M_OFWREAL, "ofwreal", "Open Firmware Real Mode Bounce Page");
1508446b206SNathan Whitehorn 
1518446b206SNathan Whitehorn static int (*openfirmware)(void *);
1528446b206SNathan Whitehorn 
1538446b206SNathan Whitehorn static vm_offset_t	of_bounce_phys;
1548446b206SNathan Whitehorn static caddr_t		of_bounce_virt;
1558446b206SNathan Whitehorn static off_t		of_bounce_offset;
1568446b206SNathan Whitehorn static size_t		of_bounce_size;
1578446b206SNathan Whitehorn static struct mtx	of_bounce_mtx;
1588446b206SNathan Whitehorn 
1598446b206SNathan Whitehorn /*
1608446b206SNathan Whitehorn  * After the VM is up, allocate a wired, low memory bounce page.
1618446b206SNathan Whitehorn  */
1628446b206SNathan Whitehorn 
1638446b206SNathan Whitehorn static void ofw_real_bounce_alloc(void *);
1648446b206SNathan Whitehorn 
1658446b206SNathan Whitehorn SYSINIT(ofw_real_bounce_alloc, SI_SUB_VM, SI_ORDER_ANY,
1668446b206SNathan Whitehorn     ofw_real_bounce_alloc, NULL);
1678446b206SNathan Whitehorn 
1688446b206SNathan Whitehorn static void
1698446b206SNathan Whitehorn ofw_real_start(void)
1708446b206SNathan Whitehorn {
1718446b206SNathan Whitehorn 	mtx_lock(&of_bounce_mtx);
1728446b206SNathan Whitehorn 	of_bounce_offset = 0;
1738446b206SNathan Whitehorn }
1748446b206SNathan Whitehorn 
1758446b206SNathan Whitehorn static void
1768446b206SNathan Whitehorn ofw_real_stop(void)
1778446b206SNathan Whitehorn {
1788446b206SNathan Whitehorn 	mtx_unlock(&of_bounce_mtx);
1798446b206SNathan Whitehorn }
1808446b206SNathan Whitehorn 
1818446b206SNathan Whitehorn static void
1828446b206SNathan Whitehorn ofw_real_bounce_alloc(void *junk)
1838446b206SNathan Whitehorn {
1848446b206SNathan Whitehorn 	/*
1858446b206SNathan Whitehorn 	 * Check that ofw_real is actually in use before allocating wads
1868446b206SNathan Whitehorn 	 * of memory. Do this by checking if our mutex has been set up.
1878446b206SNathan Whitehorn 	 */
1888446b206SNathan Whitehorn 	if (!mtx_initialized(&of_bounce_mtx))
1898446b206SNathan Whitehorn 		return;
1908446b206SNathan Whitehorn 
1918446b206SNathan Whitehorn 	/*
1928446b206SNathan Whitehorn 	 * Allocate a page of contiguous, wired physical memory that can
1938446b206SNathan Whitehorn 	 * fit into a 32-bit address space.
1948446b206SNathan Whitehorn 	 */
1958446b206SNathan Whitehorn 
1968446b206SNathan Whitehorn 	mtx_lock(&of_bounce_mtx);
1978446b206SNathan Whitehorn 
1988446b206SNathan Whitehorn 	of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0,
1998446b206SNathan Whitehorn 			     0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE);
2008446b206SNathan Whitehorn 	of_bounce_phys = vtophys(of_bounce_virt);
2018446b206SNathan Whitehorn 	of_bounce_size = PAGE_SIZE;
2028446b206SNathan Whitehorn 
2038446b206SNathan Whitehorn 	mtx_unlock(&of_bounce_mtx);
2048446b206SNathan Whitehorn }
2058446b206SNathan Whitehorn 
2068446b206SNathan Whitehorn static cell_t
2078446b206SNathan Whitehorn ofw_real_map(const void *buf, size_t len)
2088446b206SNathan Whitehorn {
2098446b206SNathan Whitehorn 	cell_t phys;
2108446b206SNathan Whitehorn 
2118446b206SNathan Whitehorn 	mtx_assert(&of_bounce_mtx, MA_OWNED);
2128446b206SNathan Whitehorn 
2138446b206SNathan Whitehorn 	if (of_bounce_virt == NULL) {
2148446b206SNathan Whitehorn 		if (!pmap_bootstrapped)
2158446b206SNathan Whitehorn 			return (cell_t)buf;
2168446b206SNathan Whitehorn 
2178446b206SNathan Whitehorn 		/*
2188446b206SNathan Whitehorn 		 * XXX: It is possible for us to get called before the VM has
2198446b206SNathan Whitehorn 		 * come online, but after the MMU is up. We don't have the
2208446b206SNathan Whitehorn 		 * bounce buffer yet, but can no longer presume a 1:1 mapping.
2218446b206SNathan Whitehorn 		 * Grab the physical address of the buffer, and hope it is
2228446b206SNathan Whitehorn 		 * in range if this happens.
2238446b206SNathan Whitehorn 		 */
2248446b206SNathan Whitehorn 		return (cell_t)vtophys(buf);
2258446b206SNathan Whitehorn 	}
2268446b206SNathan Whitehorn 
2278446b206SNathan Whitehorn 	/*
2288446b206SNathan Whitehorn 	 * Make sure the bounce page offset satisfies any reasonable
2298446b206SNathan Whitehorn 	 * alignment constraint.
2308446b206SNathan Whitehorn 	 */
2318446b206SNathan Whitehorn 	of_bounce_offset += of_bounce_offset % sizeof(register_t);
2328446b206SNathan Whitehorn 
2338446b206SNathan Whitehorn 	if (of_bounce_offset + len > of_bounce_size) {
2348446b206SNathan Whitehorn 		panic("Oversize Open Firmware call!");
2358446b206SNathan Whitehorn 		return 0;
2368446b206SNathan Whitehorn 	}
2378446b206SNathan Whitehorn 
2388446b206SNathan Whitehorn 	memcpy(of_bounce_virt + of_bounce_offset, buf, len);
2398446b206SNathan Whitehorn 	phys = of_bounce_phys + of_bounce_offset;
2408446b206SNathan Whitehorn 
2418446b206SNathan Whitehorn 	of_bounce_offset += len;
2428446b206SNathan Whitehorn 
2438446b206SNathan Whitehorn 	return phys;
2448446b206SNathan Whitehorn }
2458446b206SNathan Whitehorn 
2468446b206SNathan Whitehorn static void
2478446b206SNathan Whitehorn ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
2488446b206SNathan Whitehorn {
2498446b206SNathan Whitehorn 	mtx_assert(&of_bounce_mtx, MA_OWNED);
2508446b206SNathan Whitehorn 
2518446b206SNathan Whitehorn 	if (of_bounce_virt == NULL)
2528446b206SNathan Whitehorn 		return;
2538446b206SNathan Whitehorn 
2548446b206SNathan Whitehorn 	memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
2558446b206SNathan Whitehorn }
2568446b206SNathan Whitehorn 
2578446b206SNathan Whitehorn /* Initialiser */
2588446b206SNathan Whitehorn 
2598297758aSRafal Jaworowski static int
2608446b206SNathan Whitehorn ofw_real_init(ofw_t ofw, void *openfirm)
2618446b206SNathan Whitehorn {
2628446b206SNathan Whitehorn 	openfirmware = (int (*)(void *))openfirm;
2638446b206SNathan Whitehorn 
2648446b206SNathan Whitehorn 	mtx_init(&of_bounce_mtx, "OF Bounce Page", MTX_DEF, 0);
2658446b206SNathan Whitehorn 	of_bounce_virt = NULL;
2668297758aSRafal Jaworowski 	return (0);
2678446b206SNathan Whitehorn }
2688446b206SNathan Whitehorn 
2698446b206SNathan Whitehorn /*
2708446b206SNathan Whitehorn  * Generic functions
2718446b206SNathan Whitehorn  */
2728446b206SNathan Whitehorn 
2738446b206SNathan Whitehorn /* Test to see if a service exists. */
2748446b206SNathan Whitehorn static int
2758446b206SNathan Whitehorn ofw_real_test(ofw_t ofw, const char *name)
2768446b206SNathan Whitehorn {
277d4bccd63SNathan Whitehorn 	struct {
2788446b206SNathan Whitehorn 		cell_t name;
2798446b206SNathan Whitehorn 		cell_t nargs;
2808446b206SNathan Whitehorn 		cell_t nreturns;
2818446b206SNathan Whitehorn 		cell_t service;
2828446b206SNathan Whitehorn 		cell_t missing;
2838446b206SNathan Whitehorn 	} args = {
2848446b206SNathan Whitehorn 		(cell_t)"test",
2858446b206SNathan Whitehorn 		1,
2868446b206SNathan Whitehorn 		1,
2878446b206SNathan Whitehorn 	};
2888446b206SNathan Whitehorn 
2898446b206SNathan Whitehorn 	ofw_real_start();
2908446b206SNathan Whitehorn 
2918446b206SNathan Whitehorn 	args.service = ofw_real_map(name, strlen(name) + 1);
2928446b206SNathan Whitehorn 	if (args.service == 0 || openfirmware(&args) == -1) {
2938446b206SNathan Whitehorn 		ofw_real_stop();
2948446b206SNathan Whitehorn 		return (-1);
2958446b206SNathan Whitehorn 	}
2968446b206SNathan Whitehorn 	ofw_real_stop();
2978446b206SNathan Whitehorn 	return (args.missing);
2988446b206SNathan Whitehorn }
2998446b206SNathan Whitehorn 
3008446b206SNathan Whitehorn /*
3018446b206SNathan Whitehorn  * Device tree functions
3028446b206SNathan Whitehorn  */
3038446b206SNathan Whitehorn 
3048446b206SNathan Whitehorn /* Return the next sibling of this node or 0. */
3058446b206SNathan Whitehorn static phandle_t
3068446b206SNathan Whitehorn ofw_real_peer(ofw_t ofw, phandle_t node)
3078446b206SNathan Whitehorn {
308d4bccd63SNathan Whitehorn 	struct {
3098446b206SNathan Whitehorn 		cell_t name;
3108446b206SNathan Whitehorn 		cell_t nargs;
3118446b206SNathan Whitehorn 		cell_t nreturns;
3128446b206SNathan Whitehorn 		cell_t node;
3138446b206SNathan Whitehorn 		cell_t next;
3148446b206SNathan Whitehorn 	} args = {
3158446b206SNathan Whitehorn 		(cell_t)"peer",
3168446b206SNathan Whitehorn 		1,
3178446b206SNathan Whitehorn 		1,
3188446b206SNathan Whitehorn 	};
3198446b206SNathan Whitehorn 
3208446b206SNathan Whitehorn 	args.node = node;
3218446b206SNathan Whitehorn 	if (openfirmware(&args) == -1)
3228446b206SNathan Whitehorn 		return (-1);
3238446b206SNathan Whitehorn 	return (args.next);
3248446b206SNathan Whitehorn }
3258446b206SNathan Whitehorn 
3268446b206SNathan Whitehorn /* Return the first child of this node or 0. */
3278446b206SNathan Whitehorn static phandle_t
3288446b206SNathan Whitehorn ofw_real_child(ofw_t ofw, phandle_t node)
3298446b206SNathan Whitehorn {
330d4bccd63SNathan Whitehorn 	struct {
3318446b206SNathan Whitehorn 		cell_t name;
3328446b206SNathan Whitehorn 		cell_t nargs;
3338446b206SNathan Whitehorn 		cell_t nreturns;
3348446b206SNathan Whitehorn 		cell_t node;
3358446b206SNathan Whitehorn 		cell_t child;
3368446b206SNathan Whitehorn 	} args = {
3378446b206SNathan Whitehorn 		(cell_t)"child",
3388446b206SNathan Whitehorn 		1,
3398446b206SNathan Whitehorn 		1,
3408446b206SNathan Whitehorn 	};
3418446b206SNathan Whitehorn 
3428446b206SNathan Whitehorn 	args.node = node;
3438446b206SNathan Whitehorn 	if (openfirmware(&args) == -1)
3448446b206SNathan Whitehorn 		return (-1);
3458446b206SNathan Whitehorn 	return (args.child);
3468446b206SNathan Whitehorn }
3478446b206SNathan Whitehorn 
3488446b206SNathan Whitehorn /* Return the parent of this node or 0. */
3498446b206SNathan Whitehorn static phandle_t
3508446b206SNathan Whitehorn ofw_real_parent(ofw_t ofw, phandle_t node)
3518446b206SNathan Whitehorn {
352d4bccd63SNathan Whitehorn 	struct {
3538446b206SNathan Whitehorn 		cell_t name;
3548446b206SNathan Whitehorn 		cell_t nargs;
3558446b206SNathan Whitehorn 		cell_t nreturns;
3568446b206SNathan Whitehorn 		cell_t node;
3578446b206SNathan Whitehorn 		cell_t parent;
3588446b206SNathan Whitehorn 	} args = {
3598446b206SNathan Whitehorn 		(cell_t)"parent",
3608446b206SNathan Whitehorn 		1,
3618446b206SNathan Whitehorn 		1,
3628446b206SNathan Whitehorn 	};
3638446b206SNathan Whitehorn 
3648446b206SNathan Whitehorn 	args.node = node;
3658446b206SNathan Whitehorn 	if (openfirmware(&args) == -1)
3668446b206SNathan Whitehorn 		return (-1);
3678446b206SNathan Whitehorn 	return (args.parent);
3688446b206SNathan Whitehorn }
3698446b206SNathan Whitehorn 
3708446b206SNathan Whitehorn /* Return the package handle that corresponds to an instance handle. */
3718446b206SNathan Whitehorn static phandle_t
3728446b206SNathan Whitehorn ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
3738446b206SNathan Whitehorn {
374d4bccd63SNathan Whitehorn 	struct {
3758446b206SNathan Whitehorn 		cell_t name;
3768446b206SNathan Whitehorn 		cell_t nargs;
3778446b206SNathan Whitehorn 		cell_t nreturns;
3788446b206SNathan Whitehorn 		cell_t instance;
3798446b206SNathan Whitehorn 		cell_t package;
3808446b206SNathan Whitehorn 	} args = {
3818446b206SNathan Whitehorn 		(cell_t)"instance-to-package",
3828446b206SNathan Whitehorn 		1,
3838446b206SNathan Whitehorn 		1,
3848446b206SNathan Whitehorn 	};
3858446b206SNathan Whitehorn 
3868446b206SNathan Whitehorn 	args.instance = instance;
3878446b206SNathan Whitehorn 	if (openfirmware(&args) == -1)
3888446b206SNathan Whitehorn 		return (-1);
3898446b206SNathan Whitehorn 	return (args.package);
3908446b206SNathan Whitehorn }
3918446b206SNathan Whitehorn 
3928446b206SNathan Whitehorn /* Get the length of a property of a package. */
3938446b206SNathan Whitehorn static ssize_t
3948446b206SNathan Whitehorn ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
3958446b206SNathan Whitehorn {
396d4bccd63SNathan Whitehorn 	struct {
3978446b206SNathan Whitehorn 		cell_t name;
3988446b206SNathan Whitehorn 		cell_t nargs;
3998446b206SNathan Whitehorn 		cell_t nreturns;
4008446b206SNathan Whitehorn 		cell_t package;
4018446b206SNathan Whitehorn 		cell_t propname;
4028446b206SNathan Whitehorn 		cell_t proplen;
4038446b206SNathan Whitehorn 	} args = {
4048446b206SNathan Whitehorn 		(cell_t)"getproplen",
4058446b206SNathan Whitehorn 		2,
4068446b206SNathan Whitehorn 		1,
4078446b206SNathan Whitehorn 	};
4088446b206SNathan Whitehorn 
4098446b206SNathan Whitehorn 	ofw_real_start();
4108446b206SNathan Whitehorn 
4118446b206SNathan Whitehorn 	args.package = package;
4128446b206SNathan Whitehorn 	args.propname = ofw_real_map(propname, strlen(propname) + 1);
4138446b206SNathan Whitehorn 	if (args.propname == 0 || openfirmware(&args) == -1) {
4148446b206SNathan Whitehorn 		ofw_real_stop();
4158446b206SNathan Whitehorn 		return (-1);
4168446b206SNathan Whitehorn 	}
4178446b206SNathan Whitehorn 	ofw_real_stop();
4188446b206SNathan Whitehorn 	return (args.proplen);
4198446b206SNathan Whitehorn }
4208446b206SNathan Whitehorn 
4218446b206SNathan Whitehorn /* Get the value of a property of a package. */
4228446b206SNathan Whitehorn static ssize_t
4238446b206SNathan Whitehorn ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
4248446b206SNathan Whitehorn     size_t buflen)
4258446b206SNathan Whitehorn {
426d4bccd63SNathan Whitehorn 	struct {
4278446b206SNathan Whitehorn 		cell_t name;
4288446b206SNathan Whitehorn 		cell_t nargs;
4298446b206SNathan Whitehorn 		cell_t nreturns;
4308446b206SNathan Whitehorn 		cell_t package;
4318446b206SNathan Whitehorn 		cell_t propname;
4328446b206SNathan Whitehorn 		cell_t buf;
4338446b206SNathan Whitehorn 		cell_t buflen;
4348446b206SNathan Whitehorn 		cell_t size;
4358446b206SNathan Whitehorn 	} args = {
4368446b206SNathan Whitehorn 		(cell_t)"getprop",
4378446b206SNathan Whitehorn 		4,
4388446b206SNathan Whitehorn 		1,
4398446b206SNathan Whitehorn 	};
4408446b206SNathan Whitehorn 
4418446b206SNathan Whitehorn 	ofw_real_start();
4428446b206SNathan Whitehorn 
4438446b206SNathan Whitehorn 	args.package = package;
4448446b206SNathan Whitehorn 	args.propname = ofw_real_map(propname, strlen(propname) + 1);
4458446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, buflen);
4468446b206SNathan Whitehorn 	args.buflen = buflen;
4478446b206SNathan Whitehorn 	if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) {
4488446b206SNathan Whitehorn 		ofw_real_stop();
4498446b206SNathan Whitehorn 		return (-1);
4508446b206SNathan Whitehorn 	}
4518446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, buflen);
4528446b206SNathan Whitehorn 
4538446b206SNathan Whitehorn 	ofw_real_stop();
4548446b206SNathan Whitehorn 	return (args.size);
4558446b206SNathan Whitehorn }
4568446b206SNathan Whitehorn 
4578446b206SNathan Whitehorn /* Get the next property of a package. */
4588446b206SNathan Whitehorn static int
4598446b206SNathan Whitehorn ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
4608446b206SNathan Whitehorn     char *buf, size_t size)
4618446b206SNathan Whitehorn {
462d4bccd63SNathan Whitehorn 	struct {
4638446b206SNathan Whitehorn 		cell_t name;
4648446b206SNathan Whitehorn 		cell_t nargs;
4658446b206SNathan Whitehorn 		cell_t nreturns;
4668446b206SNathan Whitehorn 		cell_t package;
4678446b206SNathan Whitehorn 		cell_t previous;
4688446b206SNathan Whitehorn 		cell_t buf;
4698446b206SNathan Whitehorn 		cell_t flag;
4708446b206SNathan Whitehorn 	} args = {
4718446b206SNathan Whitehorn 		(cell_t)"nextprop",
4728446b206SNathan Whitehorn 		3,
4738446b206SNathan Whitehorn 		1,
4748446b206SNathan Whitehorn 	};
4758446b206SNathan Whitehorn 
4768446b206SNathan Whitehorn 	ofw_real_start();
4778446b206SNathan Whitehorn 
4788446b206SNathan Whitehorn 	args.package = package;
4798446b206SNathan Whitehorn 	args.previous = ofw_real_map(previous, strlen(previous) + 1);
4808446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, size);
4818446b206SNathan Whitehorn 	if (args.previous == 0 || args.buf == 0 || openfirmware(&args) == -1) {
4828446b206SNathan Whitehorn 		ofw_real_stop();
4838446b206SNathan Whitehorn 		return (-1);
4848446b206SNathan Whitehorn 	}
4858446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, size);
4868446b206SNathan Whitehorn 
4878446b206SNathan Whitehorn 	ofw_real_stop();
4888446b206SNathan Whitehorn 	return (args.flag);
4898446b206SNathan Whitehorn }
4908446b206SNathan Whitehorn 
4918446b206SNathan Whitehorn /* Set the value of a property of a package. */
4928446b206SNathan Whitehorn /* XXX Has a bug on FirePower */
4938446b206SNathan Whitehorn static int
4944fc23012SAndriy Gapon ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname,
4954fc23012SAndriy Gapon     const void *buf, size_t len)
4968446b206SNathan Whitehorn {
497d4bccd63SNathan Whitehorn 	struct {
4988446b206SNathan Whitehorn 		cell_t name;
4998446b206SNathan Whitehorn 		cell_t nargs;
5008446b206SNathan Whitehorn 		cell_t nreturns;
5018446b206SNathan Whitehorn 		cell_t package;
5028446b206SNathan Whitehorn 		cell_t propname;
5038446b206SNathan Whitehorn 		cell_t buf;
5048446b206SNathan Whitehorn 		cell_t len;
5058446b206SNathan Whitehorn 		cell_t size;
5068446b206SNathan Whitehorn 	} args = {
5078446b206SNathan Whitehorn 		(cell_t)"setprop",
5088446b206SNathan Whitehorn 		4,
5098446b206SNathan Whitehorn 		1,
5108446b206SNathan Whitehorn 	};
5118446b206SNathan Whitehorn 
5128446b206SNathan Whitehorn 	ofw_real_start();
5138446b206SNathan Whitehorn 
5148446b206SNathan Whitehorn 	args.package = package;
5158446b206SNathan Whitehorn 	args.propname = ofw_real_map(propname, strlen(propname) + 1);
5168446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, len);
5178446b206SNathan Whitehorn 	args.len = len;
5188446b206SNathan Whitehorn 	if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) {
5198446b206SNathan Whitehorn 		ofw_real_stop();
5208446b206SNathan Whitehorn 		return (-1);
5218446b206SNathan Whitehorn 	}
5228446b206SNathan Whitehorn 	ofw_real_stop();
5238446b206SNathan Whitehorn 	return (args.size);
5248446b206SNathan Whitehorn }
5258446b206SNathan Whitehorn 
5268446b206SNathan Whitehorn /* Convert a device specifier to a fully qualified pathname. */
5278446b206SNathan Whitehorn static ssize_t
5288446b206SNathan Whitehorn ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
5298446b206SNathan Whitehorn {
530d4bccd63SNathan Whitehorn 	struct {
5318446b206SNathan Whitehorn 		cell_t name;
5328446b206SNathan Whitehorn 		cell_t nargs;
5338446b206SNathan Whitehorn 		cell_t nreturns;
5348446b206SNathan Whitehorn 		cell_t device;
5358446b206SNathan Whitehorn 		cell_t buf;
5368446b206SNathan Whitehorn 		cell_t len;
5378446b206SNathan Whitehorn 		cell_t size;
5388446b206SNathan Whitehorn 	} args = {
5398446b206SNathan Whitehorn 		(cell_t)"canon",
5408446b206SNathan Whitehorn 		3,
5418446b206SNathan Whitehorn 		1,
5428446b206SNathan Whitehorn 	};
5438446b206SNathan Whitehorn 
5448446b206SNathan Whitehorn 	ofw_real_start();
5458446b206SNathan Whitehorn 
5468446b206SNathan Whitehorn 	args.device = ofw_real_map(device, strlen(device) + 1);
5478446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, len);
5488446b206SNathan Whitehorn 	args.len = len;
5498446b206SNathan Whitehorn 	if (args.device == 0 || args.buf == 0 || openfirmware(&args) == -1) {
5508446b206SNathan Whitehorn 		ofw_real_stop();
5518446b206SNathan Whitehorn 		return (-1);
5528446b206SNathan Whitehorn 	}
5538446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, len);
5548446b206SNathan Whitehorn 
5558446b206SNathan Whitehorn 	ofw_real_stop();
5568446b206SNathan Whitehorn 	return (args.size);
5578446b206SNathan Whitehorn }
5588446b206SNathan Whitehorn 
5598446b206SNathan Whitehorn /* Return a package handle for the specified device. */
5608446b206SNathan Whitehorn static phandle_t
5618446b206SNathan Whitehorn ofw_real_finddevice(ofw_t ofw, const char *device)
5628446b206SNathan Whitehorn {
563d4bccd63SNathan Whitehorn 	struct {
5648446b206SNathan Whitehorn 		cell_t name;
5658446b206SNathan Whitehorn 		cell_t nargs;
5668446b206SNathan Whitehorn 		cell_t nreturns;
5678446b206SNathan Whitehorn 		cell_t device;
5688446b206SNathan Whitehorn 		cell_t package;
5698446b206SNathan Whitehorn 	} args = {
5708446b206SNathan Whitehorn 		(cell_t)"finddevice",
5718446b206SNathan Whitehorn 		1,
5728446b206SNathan Whitehorn 		1,
5738446b206SNathan Whitehorn 	};
5748446b206SNathan Whitehorn 
5758446b206SNathan Whitehorn 	ofw_real_start();
5768446b206SNathan Whitehorn 
5778446b206SNathan Whitehorn 	args.device = ofw_real_map(device, strlen(device) + 1);
5788446b206SNathan Whitehorn 	if (args.device == 0 || openfirmware(&args) == -1) {
5798446b206SNathan Whitehorn 		ofw_real_stop();
5808446b206SNathan Whitehorn 		return (-1);
5818446b206SNathan Whitehorn 	}
5828446b206SNathan Whitehorn 	ofw_real_stop();
5838446b206SNathan Whitehorn 	return (args.package);
5848446b206SNathan Whitehorn }
5858446b206SNathan Whitehorn 
5868446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to an instance. */
5878446b206SNathan Whitehorn static ssize_t
5888446b206SNathan Whitehorn ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
5898446b206SNathan Whitehorn {
590d4bccd63SNathan Whitehorn 	struct {
5918446b206SNathan Whitehorn 		cell_t name;
5928446b206SNathan Whitehorn 		cell_t nargs;
5938446b206SNathan Whitehorn 		cell_t nreturns;
5948446b206SNathan Whitehorn 		cell_t instance;
5958446b206SNathan Whitehorn 		cell_t buf;
5968446b206SNathan Whitehorn 		cell_t len;
5978446b206SNathan Whitehorn 		cell_t size;
5988446b206SNathan Whitehorn 	} args = {
5998446b206SNathan Whitehorn 		(cell_t)"instance-to-path",
6008446b206SNathan Whitehorn 		3,
6018446b206SNathan Whitehorn 		1,
6028446b206SNathan Whitehorn 	};
6038446b206SNathan Whitehorn 
6048446b206SNathan Whitehorn 	ofw_real_start();
6058446b206SNathan Whitehorn 
6068446b206SNathan Whitehorn 	args.instance = instance;
6078446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, len);
6088446b206SNathan Whitehorn 	args.len = len;
6098446b206SNathan Whitehorn 	if (args.buf == 0 || openfirmware(&args) == -1) {
6108446b206SNathan Whitehorn 		ofw_real_stop();
6118446b206SNathan Whitehorn 		return (-1);
6128446b206SNathan Whitehorn 	}
6138446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, len);
6148446b206SNathan Whitehorn 
6158446b206SNathan Whitehorn 	ofw_real_stop();
6168446b206SNathan Whitehorn 	return (args.size);
6178446b206SNathan Whitehorn }
6188446b206SNathan Whitehorn 
6198446b206SNathan Whitehorn /* Return the fully qualified pathname corresponding to a package. */
6208446b206SNathan Whitehorn static ssize_t
6218446b206SNathan Whitehorn ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
6228446b206SNathan Whitehorn {
623d4bccd63SNathan Whitehorn 	struct {
6248446b206SNathan Whitehorn 		cell_t name;
6258446b206SNathan Whitehorn 		cell_t nargs;
6268446b206SNathan Whitehorn 		cell_t nreturns;
6278446b206SNathan Whitehorn 		cell_t package;
6288446b206SNathan Whitehorn 		cell_t buf;
6298446b206SNathan Whitehorn 		cell_t len;
6308446b206SNathan Whitehorn 		cell_t size;
6318446b206SNathan Whitehorn 	} args = {
6328446b206SNathan Whitehorn 		(cell_t)"package-to-path",
6338446b206SNathan Whitehorn 		3,
6348446b206SNathan Whitehorn 		1,
6358446b206SNathan Whitehorn 	};
6368446b206SNathan Whitehorn 
6378446b206SNathan Whitehorn 	ofw_real_start();
6388446b206SNathan Whitehorn 
6398446b206SNathan Whitehorn 	args.package = package;
6408446b206SNathan Whitehorn 	args.buf = ofw_real_map(buf, len);
6418446b206SNathan Whitehorn 	args.len = len;
6428446b206SNathan Whitehorn 	if (args.buf == 0 || openfirmware(&args) == -1) {
6438446b206SNathan Whitehorn 		ofw_real_stop();
6448446b206SNathan Whitehorn 		return (-1);
6458446b206SNathan Whitehorn 	}
6468446b206SNathan Whitehorn 	ofw_real_unmap(args.buf, buf, len);
6478446b206SNathan Whitehorn 
6488446b206SNathan Whitehorn 	ofw_real_stop();
6498446b206SNathan Whitehorn 	return (args.size);
6508446b206SNathan Whitehorn }
6518446b206SNathan Whitehorn 
6528446b206SNathan Whitehorn /*  Call the method in the scope of a given instance. */
6538446b206SNathan Whitehorn static int
6548446b206SNathan Whitehorn ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
6558446b206SNathan Whitehorn     int nargs, int nreturns, unsigned long *args_and_returns)
6568446b206SNathan Whitehorn {
657d4bccd63SNathan Whitehorn 	struct {
6588446b206SNathan Whitehorn 		cell_t name;
6598446b206SNathan Whitehorn 		cell_t nargs;
6608446b206SNathan Whitehorn 		cell_t nreturns;
6618446b206SNathan Whitehorn 		cell_t method;
6628446b206SNathan Whitehorn 		cell_t instance;
6638446b206SNathan Whitehorn 		cell_t args_n_results[12];
6648446b206SNathan Whitehorn 	} args = {
6658446b206SNathan Whitehorn 		(cell_t)"call-method",
6668446b206SNathan Whitehorn 		2,
6678446b206SNathan Whitehorn 		1,
6688446b206SNathan Whitehorn 	};
6698446b206SNathan Whitehorn 	cell_t *cp;
6708446b206SNathan Whitehorn 	unsigned long *ap;
6718446b206SNathan Whitehorn 	int n;
6728446b206SNathan Whitehorn 
6738446b206SNathan Whitehorn 	if (nargs > 6)
6748446b206SNathan Whitehorn 		return (-1);
6758446b206SNathan Whitehorn 
6768446b206SNathan Whitehorn 	ofw_real_start();
6778446b206SNathan Whitehorn 	args.nargs = nargs + 2;
6788446b206SNathan Whitehorn 	args.nreturns = nreturns + 1;
6798446b206SNathan Whitehorn 	args.method = ofw_real_map(method, strlen(method) + 1);
6808446b206SNathan Whitehorn 	args.instance = instance;
6818446b206SNathan Whitehorn 
6828446b206SNathan Whitehorn 	ap = args_and_returns;
6838446b206SNathan Whitehorn 	for (cp = args.args_n_results + (n = nargs); --n >= 0;)
6848446b206SNathan Whitehorn 		*--cp = *(ap++);
6858446b206SNathan Whitehorn 	if (args.method == 0 || openfirmware(&args) == -1) {
6868446b206SNathan Whitehorn 		ofw_real_stop();
6878446b206SNathan Whitehorn 		return (-1);
6888446b206SNathan Whitehorn 	}
6898446b206SNathan Whitehorn 	ofw_real_stop();
6908446b206SNathan Whitehorn 	if (args.args_n_results[nargs])
6918446b206SNathan Whitehorn 		return (args.args_n_results[nargs]);
6928446b206SNathan Whitehorn 	for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
6938446b206SNathan Whitehorn 		*(ap++) = *--cp;
6948446b206SNathan Whitehorn 	return (0);
6958446b206SNathan Whitehorn }
6968446b206SNathan Whitehorn 
6978446b206SNathan Whitehorn /*
6988446b206SNathan Whitehorn  * Device I/O functions
6998446b206SNathan Whitehorn  */
7008446b206SNathan Whitehorn 
7018446b206SNathan Whitehorn /* Open an instance for a device. */
7028446b206SNathan Whitehorn static ihandle_t
7038446b206SNathan Whitehorn ofw_real_open(ofw_t ofw, const char *device)
7048446b206SNathan Whitehorn {
705d4bccd63SNathan Whitehorn 	struct {
7068446b206SNathan Whitehorn 		cell_t name;
7078446b206SNathan Whitehorn 		cell_t nargs;
7088446b206SNathan Whitehorn 		cell_t nreturns;
7098446b206SNathan Whitehorn 		cell_t device;
7108446b206SNathan Whitehorn 		cell_t instance;
7118446b206SNathan Whitehorn 	} args = {
7128446b206SNathan Whitehorn 		(cell_t)"open",
7138446b206SNathan Whitehorn 		1,
7148446b206SNathan Whitehorn 		1,
7158446b206SNathan Whitehorn 	};
7168446b206SNathan Whitehorn 
7178446b206SNathan Whitehorn 	ofw_real_start();
7188446b206SNathan Whitehorn 
7198446b206SNathan Whitehorn 	args.device = ofw_real_map(device, strlen(device) + 1);
7208446b206SNathan Whitehorn 	if (args.device == 0 || openfirmware(&args) == -1
7218446b206SNathan Whitehorn 	    || args.instance == 0) {
7228446b206SNathan Whitehorn 		ofw_real_stop();
7238446b206SNathan Whitehorn 		return (-1);
7248446b206SNathan Whitehorn 	}
7258446b206SNathan Whitehorn 	ofw_real_stop();
7268446b206SNathan Whitehorn 	return (args.instance);
7278446b206SNathan Whitehorn }
7288446b206SNathan Whitehorn 
7298446b206SNathan Whitehorn /* Close an instance. */
7308446b206SNathan Whitehorn static void
7318446b206SNathan Whitehorn ofw_real_close(ofw_t ofw, ihandle_t instance)
7328446b206SNathan Whitehorn {
733d4bccd63SNathan Whitehorn 	struct {
7348446b206SNathan Whitehorn 		cell_t name;
7358446b206SNathan Whitehorn 		cell_t nargs;
7368446b206SNathan Whitehorn 		cell_t nreturns;
7378446b206SNathan Whitehorn 		cell_t instance;
7388446b206SNathan Whitehorn 	} args = {
7398446b206SNathan Whitehorn 		(cell_t)"close",
7408446b206SNathan Whitehorn 		1,
741bd7e69e4SMarius Strobl 		0,
7428446b206SNathan Whitehorn 	};
7438446b206SNathan Whitehorn 
7448446b206SNathan Whitehorn 	args.instance = instance;
7458446b206SNathan Whitehorn 	openfirmware(&args);
7468446b206SNathan Whitehorn }
7478446b206SNathan Whitehorn 
7488446b206SNathan Whitehorn /* Read from an instance. */
7498446b206SNathan Whitehorn static ssize_t
7508446b206SNathan Whitehorn ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
7518446b206SNathan Whitehorn {
752d4bccd63SNathan Whitehorn 	struct {
7538446b206SNathan Whitehorn 		cell_t name;
7548446b206SNathan Whitehorn 		cell_t nargs;
7558446b206SNathan Whitehorn 		cell_t nreturns;
7568446b206SNathan Whitehorn 		cell_t instance;
7578446b206SNathan Whitehorn 		cell_t addr;
7588446b206SNathan Whitehorn 		cell_t len;
7598446b206SNathan Whitehorn 		cell_t actual;
7608446b206SNathan Whitehorn 	} args = {
7618446b206SNathan Whitehorn 		(cell_t)"read",
7628446b206SNathan Whitehorn 		3,
7638446b206SNathan Whitehorn 		1,
7648446b206SNathan Whitehorn 	};
7658446b206SNathan Whitehorn 
7668446b206SNathan Whitehorn 	ofw_real_start();
7678446b206SNathan Whitehorn 
7688446b206SNathan Whitehorn 	args.instance = instance;
7698446b206SNathan Whitehorn 	args.addr = ofw_real_map(addr, len);
7708446b206SNathan Whitehorn 	args.len = len;
7718446b206SNathan Whitehorn 	if (args.addr == 0 || openfirmware(&args) == -1) {
7728446b206SNathan Whitehorn 		ofw_real_stop();
7738446b206SNathan Whitehorn 		return (-1);
7748446b206SNathan Whitehorn 	}
7758446b206SNathan Whitehorn 	ofw_real_unmap(args.addr, addr, len);
7768446b206SNathan Whitehorn 
7778446b206SNathan Whitehorn 	ofw_real_stop();
7788446b206SNathan Whitehorn 	return (args.actual);
7798446b206SNathan Whitehorn }
7808446b206SNathan Whitehorn 
7818446b206SNathan Whitehorn /* Write to an instance. */
7828446b206SNathan Whitehorn static ssize_t
7838446b206SNathan Whitehorn ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
7848446b206SNathan Whitehorn {
785d4bccd63SNathan Whitehorn 	struct {
7868446b206SNathan Whitehorn 		cell_t name;
7878446b206SNathan Whitehorn 		cell_t nargs;
7888446b206SNathan Whitehorn 		cell_t nreturns;
7898446b206SNathan Whitehorn 		cell_t instance;
7908446b206SNathan Whitehorn 		cell_t addr;
7918446b206SNathan Whitehorn 		cell_t len;
7928446b206SNathan Whitehorn 		cell_t actual;
7938446b206SNathan Whitehorn 	} args = {
7948446b206SNathan Whitehorn 		(cell_t)"write",
7958446b206SNathan Whitehorn 		3,
7968446b206SNathan Whitehorn 		1,
7978446b206SNathan Whitehorn 	};
7988446b206SNathan Whitehorn 
7998446b206SNathan Whitehorn 	ofw_real_start();
8008446b206SNathan Whitehorn 
8018446b206SNathan Whitehorn 	args.instance = instance;
8028446b206SNathan Whitehorn 	args.addr = ofw_real_map(addr, len);
8038446b206SNathan Whitehorn 	args.len = len;
8048446b206SNathan Whitehorn 	if (args.addr == 0 || openfirmware(&args) == -1) {
8058446b206SNathan Whitehorn 		ofw_real_stop();
8068446b206SNathan Whitehorn 		return (-1);
8078446b206SNathan Whitehorn 	}
8088446b206SNathan Whitehorn 	ofw_real_stop();
8098446b206SNathan Whitehorn 	return (args.actual);
8108446b206SNathan Whitehorn }
8118446b206SNathan Whitehorn 
8128446b206SNathan Whitehorn /* Seek to a position. */
8138446b206SNathan Whitehorn static int
8148446b206SNathan Whitehorn ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
8158446b206SNathan Whitehorn {
816d4bccd63SNathan Whitehorn 	struct {
8178446b206SNathan Whitehorn 		cell_t name;
8188446b206SNathan Whitehorn 		cell_t nargs;
8198446b206SNathan Whitehorn 		cell_t nreturns;
8208446b206SNathan Whitehorn 		cell_t instance;
8218446b206SNathan Whitehorn 		cell_t poshi;
8228446b206SNathan Whitehorn 		cell_t poslo;
8238446b206SNathan Whitehorn 		cell_t status;
8248446b206SNathan Whitehorn 	} args = {
8258446b206SNathan Whitehorn 		(cell_t)"seek",
8268446b206SNathan Whitehorn 		3,
8278446b206SNathan Whitehorn 		1,
8288446b206SNathan Whitehorn 	};
8298446b206SNathan Whitehorn 
8308446b206SNathan Whitehorn 	args.instance = instance;
8318446b206SNathan Whitehorn 	args.poshi = pos >> 32;
8328446b206SNathan Whitehorn 	args.poslo = pos;
8338446b206SNathan Whitehorn 	if (openfirmware(&args) == -1)
8348446b206SNathan Whitehorn 		return (-1);
8358446b206SNathan Whitehorn 	return (args.status);
8368446b206SNathan Whitehorn }
8378446b206SNathan Whitehorn 
8388446b206SNathan Whitehorn /*
8398446b206SNathan Whitehorn  * Memory functions
8408446b206SNathan Whitehorn  */
8418446b206SNathan Whitehorn 
8428446b206SNathan Whitehorn /* Claim an area of memory. */
8438446b206SNathan Whitehorn static caddr_t
8448446b206SNathan Whitehorn ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
8458446b206SNathan Whitehorn {
846d4bccd63SNathan Whitehorn 	struct {
8478446b206SNathan Whitehorn 		cell_t name;
8488446b206SNathan Whitehorn 		cell_t nargs;
8498446b206SNathan Whitehorn 		cell_t nreturns;
8508446b206SNathan Whitehorn 		cell_t virt;
8518446b206SNathan Whitehorn 		cell_t size;
8528446b206SNathan Whitehorn 		cell_t align;
8538446b206SNathan Whitehorn 		cell_t baseaddr;
8548446b206SNathan Whitehorn 	} args = {
8558446b206SNathan Whitehorn 		(cell_t)"claim",
8568446b206SNathan Whitehorn 		3,
8578446b206SNathan Whitehorn 		1,
8588446b206SNathan Whitehorn 	};
8598446b206SNathan Whitehorn 
8608446b206SNathan Whitehorn 	args.virt = (cell_t)virt;
8618446b206SNathan Whitehorn 	args.size = size;
8628446b206SNathan Whitehorn 	args.align = align;
8638446b206SNathan Whitehorn 	if (openfirmware(&args) == -1)
8648446b206SNathan Whitehorn 		return ((void *)-1);
8658446b206SNathan Whitehorn 	return ((void *)args.baseaddr);
8668446b206SNathan Whitehorn }
8678446b206SNathan Whitehorn 
8688446b206SNathan Whitehorn /* Release an area of memory. */
8698446b206SNathan Whitehorn static void
8708446b206SNathan Whitehorn ofw_real_release(ofw_t ofw, void *virt, size_t size)
8718446b206SNathan Whitehorn {
872d4bccd63SNathan Whitehorn 	struct {
8738446b206SNathan Whitehorn 		cell_t name;
8748446b206SNathan Whitehorn 		cell_t nargs;
8758446b206SNathan Whitehorn 		cell_t nreturns;
8768446b206SNathan Whitehorn 		cell_t virt;
8778446b206SNathan Whitehorn 		cell_t size;
8788446b206SNathan Whitehorn 	} args = {
8798446b206SNathan Whitehorn 		(cell_t)"release",
8808446b206SNathan Whitehorn 		2,
881bd7e69e4SMarius Strobl 		0,
8828446b206SNathan Whitehorn 	};
8838446b206SNathan Whitehorn 
8848446b206SNathan Whitehorn 	args.virt = (cell_t)virt;
8858446b206SNathan Whitehorn 	args.size = size;
8868446b206SNathan Whitehorn 	openfirmware(&args);
8878446b206SNathan Whitehorn }
8888446b206SNathan Whitehorn 
8898446b206SNathan Whitehorn /*
8908446b206SNathan Whitehorn  * Control transfer functions
8918446b206SNathan Whitehorn  */
8928446b206SNathan Whitehorn 
8938446b206SNathan Whitehorn /* Suspend and drop back to the Open Firmware interface. */
8948446b206SNathan Whitehorn static void
8958446b206SNathan Whitehorn ofw_real_enter(ofw_t ofw)
8968446b206SNathan Whitehorn {
897d4bccd63SNathan Whitehorn 	struct {
8988446b206SNathan Whitehorn 		cell_t name;
8998446b206SNathan Whitehorn 		cell_t nargs;
9008446b206SNathan Whitehorn 		cell_t nreturns;
9018446b206SNathan Whitehorn 	} args = {
9028446b206SNathan Whitehorn 		(cell_t)"enter",
903bd7e69e4SMarius Strobl 		0,
904bd7e69e4SMarius Strobl 		0,
9058446b206SNathan Whitehorn 	};
9068446b206SNathan Whitehorn 
9078446b206SNathan Whitehorn 	openfirmware(&args);
9088446b206SNathan Whitehorn 	/* We may come back. */
9098446b206SNathan Whitehorn }
9108446b206SNathan Whitehorn 
9118446b206SNathan Whitehorn /* Shut down and drop back to the Open Firmware interface. */
9128446b206SNathan Whitehorn static void
9138446b206SNathan Whitehorn ofw_real_exit(ofw_t ofw)
9148446b206SNathan Whitehorn {
915d4bccd63SNathan Whitehorn 	struct {
9168446b206SNathan Whitehorn 		cell_t name;
9178446b206SNathan Whitehorn 		cell_t nargs;
9188446b206SNathan Whitehorn 		cell_t nreturns;
9198446b206SNathan Whitehorn 	} args = {
9208446b206SNathan Whitehorn 		(cell_t)"exit",
921bd7e69e4SMarius Strobl 		0,
922bd7e69e4SMarius Strobl 		0,
9238446b206SNathan Whitehorn 	};
9248446b206SNathan Whitehorn 
9258446b206SNathan Whitehorn 	openfirmware(&args);
9268446b206SNathan Whitehorn 	for (;;)			/* just in case */
9278446b206SNathan Whitehorn 		;
9288446b206SNathan Whitehorn }
9298446b206SNathan Whitehorn 
930