167204Sobrien/*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $	*/
267204Sobrien
3139738Simp/*-
467204Sobrien * Copyright (C) 1995, 1996 Wolfgang Solfrank.
567204Sobrien * Copyright (C) 1995, 1996 TooLs GmbH.
667204Sobrien * All rights reserved.
767204Sobrien *
867204Sobrien * Redistribution and use in source and binary forms, with or without
967204Sobrien * modification, are permitted provided that the following conditions
1067204Sobrien * are met:
1167204Sobrien * 1. Redistributions of source code must retain the above copyright
1267204Sobrien *    notice, this list of conditions and the following disclaimer.
1367204Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1467204Sobrien *    notice, this list of conditions and the following disclaimer in the
1567204Sobrien *    documentation and/or other materials provided with the distribution.
1667204Sobrien * 3. All advertising materials mentioning features or use of this software
1767204Sobrien *    must display the following acknowledgement:
1867204Sobrien *	This product includes software developed by TooLs GmbH.
1967204Sobrien * 4. The name of TooLs GmbH may not be used to endorse or promote products
2067204Sobrien *    derived from this software without specific prior written permission.
2167204Sobrien *
2267204Sobrien * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2367204Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2467204Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2567204Sobrien * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2667204Sobrien * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2767204Sobrien * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2867204Sobrien * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2967204Sobrien * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3067204Sobrien * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3167204Sobrien * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3267204Sobrien */
33139738Simp/*-
3467204Sobrien * Copyright (C) 2000 Benno Rice.
3567204Sobrien * All rights reserved.
3667204Sobrien *
3767204Sobrien * Redistribution and use in source and binary forms, with or without
3867204Sobrien * modification, are permitted provided that the following conditions
3967204Sobrien * are met:
4067204Sobrien * 1. Redistributions of source code must retain the above copyright
4167204Sobrien *    notice, this list of conditions and the following disclaimer.
4267204Sobrien * 2. Redistributions in binary form must reproduce the above copyright
4367204Sobrien *    notice, this list of conditions and the following disclaimer in the
4467204Sobrien *    documentation and/or other materials provided with the distribution.
4567204Sobrien *
4667204Sobrien * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
4767204Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
4867204Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
4967204Sobrien * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
5067204Sobrien * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
5167204Sobrien * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
5267204Sobrien * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
5367204Sobrien * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
5467204Sobrien * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
5567204Sobrien * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5667204Sobrien */
5767204Sobrien
58124140Sobrien#include <sys/cdefs.h>
59124140Sobrien__FBSDID("$FreeBSD: releng/10.3/sys/boot/ofw/libofw/openfirm.c 215577 2010-11-20 19:23:16Z andreast $");
60124140Sobrien
6167204Sobrien#include <machine/stdarg.h>
6267204Sobrien
6368548Sbenno#include <stand.h>
6468548Sbenno
6567204Sobrien#include "openfirm.h"
6667204Sobrien
6785717Sjakeint (*openfirmware)(void *);
6885717Sjake
69170854Smariusphandle_t chosen;
70100318Sbennoihandle_t mmu;
71100318Sbennoihandle_t memory;
72215438Sandreastint	  real_mode = 0;
7384617Sbenno
74170838Smarius/* Initialiser */
7567204Sobrien
7667204Sobrienvoid
7767204SobrienOF_init(int (*openfirm)(void *))
7867204Sobrien{
79215438Sandreast	phandle_t options;
80215577Sandreast	char	  mode[sizeof("true")];
8184617Sbenno
8267204Sobrien	openfirmware = openfirm;
8384617Sbenno
84170838Smarius	if ((chosen = OF_finddevice("/chosen")) == -1)
85170838Smarius		OF_exit();
86214493Snwhitehorn	if (OF_getprop(chosen, "memory", &memory, sizeof(memory)) == -1) {
87214493Snwhitehorn		memory = OF_open("/memory");
88214493Snwhitehorn		if (memory == -1)
89214493Snwhitehorn			memory = OF_open("/memory@0");
90214493Snwhitehorn		if (memory == -1)
91214493Snwhitehorn			OF_exit();
92214493Snwhitehorn	}
93170854Smarius	if (OF_getprop(chosen, "mmu", &mmu, sizeof(mmu)) == -1)
94170854Smarius		OF_exit();
95215438Sandreast
96215577Sandreast	/*
97215438Sandreast	 * Check if we run in real mode. If so, we do not need to map
98215438Sandreast	 * memory later on.
99215438Sandreast	 */
100215438Sandreast	options = OF_finddevice("/options");
101215577Sandreast	if (OF_getprop(options, "real-mode?", mode, sizeof(mode)) > 0 &&
102215577Sandreast	    strcmp(mode, "true") == 0)
103215438Sandreast		real_mode = 1;
104163145Skmacy}
105163145Skmacy
10667204Sobrien/*
10767204Sobrien * Generic functions
10867204Sobrien */
10967204Sobrien
11067204Sobrien/* Test to see if a service exists. */
11167204Sobrienint
11267204SobrienOF_test(char *name)
11367204Sobrien{
11467204Sobrien	static struct {
115170838Smarius		cell_t name;
116170838Smarius		cell_t nargs;
117170838Smarius		cell_t nreturns;
118170838Smarius		cell_t service;
119170838Smarius		cell_t missing;
12067204Sobrien	} args = {
12184972Srobert		(cell_t)"test",
12267204Sobrien		1,
12367204Sobrien		1,
12467204Sobrien	};
12567204Sobrien
12684972Srobert	args.service = (cell_t)name;
12767204Sobrien	if (openfirmware(&args) == -1)
128170838Smarius		return (-1);
129170838Smarius	return (args.missing);
13067204Sobrien}
13167204Sobrien
13267204Sobrien/* Return firmware millisecond count. */
13367204Sobrienint
13467204SobrienOF_milliseconds()
13567204Sobrien{
13667204Sobrien	static struct {
137170838Smarius		cell_t name;
138170838Smarius		cell_t nargs;
139170838Smarius		cell_t nreturns;
140170838Smarius		cell_t ms;
14167204Sobrien	} args = {
14284972Srobert		(cell_t)"milliseconds",
14367204Sobrien		0,
14467204Sobrien		1,
14567204Sobrien	};
146170838Smarius
14767204Sobrien	openfirmware(&args);
148170838Smarius	return (args.ms);
14967204Sobrien}
15067204Sobrien
15167204Sobrien/*
15267204Sobrien * Device tree functions
15367204Sobrien */
15467204Sobrien
15567204Sobrien/* Return the next sibling of this node or 0. */
15667204Sobrienphandle_t
15767204SobrienOF_peer(phandle_t node)
15867204Sobrien{
15967204Sobrien	static struct {
160170838Smarius		cell_t name;
161170838Smarius		cell_t nargs;
162170838Smarius		cell_t nreturns;
163170838Smarius		cell_t node;
164170838Smarius		cell_t next;
16567204Sobrien	} args = {
16684972Srobert		(cell_t)"peer",
16767204Sobrien		1,
16867204Sobrien		1,
16967204Sobrien	};
17067204Sobrien
171170838Smarius	args.node = node;
17267204Sobrien	if (openfirmware(&args) == -1)
173170838Smarius		return (-1);
174170838Smarius	return (args.next);
17567204Sobrien}
17667204Sobrien
17767204Sobrien/* Return the first child of this node or 0. */
17867204Sobrienphandle_t
17967204SobrienOF_child(phandle_t node)
18067204Sobrien{
18167204Sobrien	static struct {
182170838Smarius		cell_t name;
183170838Smarius		cell_t nargs;
184170838Smarius		cell_t nreturns;
185170838Smarius		cell_t node;
186170838Smarius		cell_t child;
18767204Sobrien	} args = {
18884972Srobert		(cell_t)"child",
18967204Sobrien		1,
19067204Sobrien		1,
19167204Sobrien	};
19267204Sobrien
193170838Smarius	args.node = node;
19467204Sobrien	if (openfirmware(&args) == -1)
195170838Smarius		return (-1);
196170838Smarius	return (args.child);
19767204Sobrien}
19867204Sobrien
19967204Sobrien/* Return the parent of this node or 0. */
20067204Sobrienphandle_t
20167204SobrienOF_parent(phandle_t node)
20267204Sobrien{
20367204Sobrien	static struct {
204170838Smarius		cell_t name;
205170838Smarius		cell_t nargs;
206170838Smarius		cell_t nreturns;
207170838Smarius		cell_t node;
208170838Smarius		cell_t parent;
20967204Sobrien	} args = {
21084972Srobert		(cell_t)"parent",
21167204Sobrien		1,
21267204Sobrien		1,
21367204Sobrien	};
21467204Sobrien
215170838Smarius	args.node = node;
21667204Sobrien	if (openfirmware(&args) == -1)
217170838Smarius		return (-1);
218170838Smarius	return (args.parent);
21967204Sobrien}
22067204Sobrien
22167204Sobrien/* Return the package handle that corresponds to an instance handle. */
22267204Sobrienphandle_t
22367204SobrienOF_instance_to_package(ihandle_t instance)
22467204Sobrien{
22567204Sobrien	static struct {
226170838Smarius		cell_t name;
227170838Smarius		cell_t nargs;
228170838Smarius		cell_t nreturns;
229170838Smarius		cell_t instance;
230170838Smarius		cell_t package;
23167204Sobrien	} args = {
23284972Srobert		(cell_t)"instance-to-package",
23367204Sobrien		1,
23467204Sobrien		1,
23567204Sobrien	};
236170838Smarius
237170838Smarius	args.instance = instance;
23867204Sobrien	if (openfirmware(&args) == -1)
239170838Smarius		return (-1);
240170838Smarius	return (args.package);
24167204Sobrien}
24267204Sobrien
24367204Sobrien/* Get the length of a property of a package. */
24467204Sobrienint
24567204SobrienOF_getproplen(phandle_t package, char *propname)
24667204Sobrien{
24767204Sobrien	static struct {
248170838Smarius		cell_t name;
249170838Smarius		cell_t nargs;
250170838Smarius		cell_t nreturns;
251170838Smarius		cell_t package;
252170838Smarius		cell_t propname;
253170838Smarius		cell_t proplen;
25467204Sobrien	} args = {
25584972Srobert		(cell_t)"getproplen",
25667204Sobrien		2,
25767204Sobrien		1,
25867204Sobrien	};
25967204Sobrien
260170838Smarius	args.package = package;
26184972Srobert	args.propname = (cell_t)propname;
26267204Sobrien	if (openfirmware(&args) == -1)
263170838Smarius		return (-1);
264170838Smarius	return (args.proplen);
26567204Sobrien}
26667204Sobrien
26767204Sobrien/* Get the value of a property of a package. */
26867204Sobrienint
26967204SobrienOF_getprop(phandle_t package, char *propname, void *buf, int buflen)
27067204Sobrien{
27167204Sobrien	static struct {
272170838Smarius		cell_t name;
273170838Smarius		cell_t nargs;
274170838Smarius		cell_t nreturns;
275170838Smarius		cell_t package;
276170838Smarius		cell_t propname;
277170838Smarius		cell_t buf;
278170838Smarius		cell_t buflen;
279170838Smarius		cell_t size;
28067204Sobrien	} args = {
28184972Srobert		(cell_t)"getprop",
28267204Sobrien		4,
28367204Sobrien		1,
28467204Sobrien	};
285170838Smarius
286170838Smarius	args.package = package;
28784972Srobert	args.propname = (cell_t)propname;
28884972Srobert	args.buf = (cell_t)buf;
289170838Smarius	args.buflen = buflen;
29067204Sobrien	if (openfirmware(&args) == -1)
291170838Smarius		return (-1);
292170838Smarius	return (args.size);
29367204Sobrien}
29467204Sobrien
29567204Sobrien/* Get the next property of a package. */
29667204Sobrienint
29767204SobrienOF_nextprop(phandle_t package, char *previous, char *buf)
29867204Sobrien{
29967204Sobrien	static struct {
300170838Smarius		cell_t name;
301170838Smarius		cell_t nargs;
302170838Smarius		cell_t nreturns;
303170838Smarius		cell_t package;
304170838Smarius		cell_t previous;
305170838Smarius		cell_t buf;
306170838Smarius		cell_t flag;
30767204Sobrien	} args = {
30884972Srobert		(cell_t)"nextprop",
30967204Sobrien		3,
31067204Sobrien		1,
31167204Sobrien	};
31267204Sobrien
313170838Smarius	args.package = package;
31484972Srobert	args.previous = (cell_t)previous;
31584972Srobert	args.buf = (cell_t)buf;
31667204Sobrien	if (openfirmware(&args) == -1)
317170838Smarius		return (-1);
318170838Smarius	return (args.flag);
31967204Sobrien}
32067204Sobrien
32167204Sobrien/* Set the value of a property of a package. */
32267204Sobrien/* XXX Has a bug on FirePower */
32367204Sobrienint
32467204SobrienOF_setprop(phandle_t package, char *propname, void *buf, int len)
32567204Sobrien{
32667204Sobrien	static struct {
327170838Smarius		cell_t name;
328170838Smarius		cell_t nargs;
329170838Smarius		cell_t nreturns;
330170838Smarius		cell_t package;
331170838Smarius		cell_t propname;
332170838Smarius		cell_t buf;
333170838Smarius		cell_t len;
334170838Smarius		cell_t size;
33567204Sobrien	} args = {
33684972Srobert		(cell_t)"setprop",
33767204Sobrien		4,
33867204Sobrien		1,
33967204Sobrien	};
340170838Smarius
341170838Smarius	args.package = package;
34284972Srobert	args.propname = (cell_t)propname;
34384972Srobert	args.buf = (cell_t)buf;
344170838Smarius	args.len = len;
34567204Sobrien	if (openfirmware(&args) == -1)
346170838Smarius		return (-1);
347170838Smarius	return (args.size);
34867204Sobrien}
34967204Sobrien
35067204Sobrien/* Convert a device specifier to a fully qualified pathname. */
35167204Sobrienint
35268548SbennoOF_canon(const char *device, char *buf, int len)
35367204Sobrien{
35467204Sobrien	static struct {
355170838Smarius		cell_t name;
356170838Smarius		cell_t nargs;
357170838Smarius		cell_t nreturns;
358170838Smarius		cell_t device;
359170838Smarius		cell_t buf;
360170838Smarius		cell_t len;
361170838Smarius		cell_t size;
36267204Sobrien	} args = {
36384972Srobert		(cell_t)"canon",
36467204Sobrien		3,
36567204Sobrien		1,
36667204Sobrien	};
367170838Smarius
36884972Srobert	args.device = (cell_t)device;
36984972Srobert	args.buf = (cell_t)buf;
370170838Smarius	args.len = len;
37167204Sobrien	if (openfirmware(&args) == -1)
372170838Smarius		return (-1);
373170838Smarius	return (args.size);
37467204Sobrien}
37567204Sobrien
37667204Sobrien/* Return a package handle for the specified device. */
37767204Sobrienphandle_t
37868548SbennoOF_finddevice(const char *device)
37967204Sobrien{
38067204Sobrien	static struct {
381170838Smarius		cell_t name;
382170838Smarius		cell_t nargs;
383170838Smarius		cell_t nreturns;
384170838Smarius		cell_t device;
385170838Smarius		cell_t package;
38667204Sobrien	} args = {
38784972Srobert		(cell_t)"finddevice",
38867204Sobrien		1,
38967204Sobrien		1,
390170838Smarius	};
391170838Smarius
39284972Srobert	args.device = (cell_t)device;
39367204Sobrien	if (openfirmware(&args) == -1)
394170838Smarius		return (-1);
395170838Smarius	return (args.package);
39667204Sobrien}
39767204Sobrien
39867204Sobrien/* Return the fully qualified pathname corresponding to an instance. */
39967204Sobrienint
40067204SobrienOF_instance_to_path(ihandle_t instance, char *buf, int len)
40167204Sobrien{
40267204Sobrien	static struct {
403170838Smarius		cell_t name;
404170838Smarius		cell_t nargs;
405170838Smarius		cell_t nreturns;
406170838Smarius		cell_t instance;
407170838Smarius		cell_t buf;
408170838Smarius		cell_t len;
409170838Smarius		cell_t size;
41067204Sobrien	} args = {
41184972Srobert		(cell_t)"instance-to-path",
41267204Sobrien		3,
41367204Sobrien		1,
41467204Sobrien	};
41567204Sobrien
416170838Smarius	args.instance = instance;
41784972Srobert	args.buf = (cell_t)buf;
418170838Smarius	args.len = len;
41967204Sobrien	if (openfirmware(&args) == -1)
420170838Smarius		return (-1);
421170838Smarius	return (args.size);
42267204Sobrien}
42367204Sobrien
42467204Sobrien/* Return the fully qualified pathname corresponding to a package. */
42567204Sobrienint
42667204SobrienOF_package_to_path(phandle_t package, char *buf, int len)
42767204Sobrien{
42867204Sobrien	static struct {
429170838Smarius		cell_t name;
430170838Smarius		cell_t nargs;
431170838Smarius		cell_t nreturns;
432170838Smarius		cell_t package;
433170838Smarius		cell_t buf;
434170838Smarius		cell_t len;
435170838Smarius		cell_t size;
43667204Sobrien	} args = {
43784972Srobert		(cell_t)"package-to-path",
43867204Sobrien		3,
43967204Sobrien		1,
44067204Sobrien	};
44167204Sobrien
442170838Smarius	args.package = package;
44384972Srobert	args.buf = (cell_t)buf;
444170838Smarius	args.len = len;
44567204Sobrien	if (openfirmware(&args) == -1)
446170838Smarius		return (-1);
447170838Smarius	return (args.size);
44867204Sobrien}
44967204Sobrien
45067204Sobrien/*  Call the method in the scope of a given instance. */
45167204Sobrienint
45267204SobrienOF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
45367204Sobrien{
45467204Sobrien	va_list ap;
45567204Sobrien	static struct {
456170838Smarius		cell_t name;
457170838Smarius		cell_t nargs;
458170838Smarius		cell_t nreturns;
459170838Smarius		cell_t method;
460170838Smarius		cell_t instance;
461170838Smarius		cell_t args_n_results[12];
46267204Sobrien	} args = {
46384972Srobert		(cell_t)"call-method",
46467204Sobrien		2,
46567204Sobrien		1,
46667204Sobrien	};
467170854Smarius	cell_t *cp;
468170854Smarius	int n;
46967204Sobrien
47067204Sobrien	if (nargs > 6)
471170838Smarius		return (-1);
47267204Sobrien	args.nargs = nargs + 2;
47367204Sobrien	args.nreturns = nreturns + 1;
47484972Srobert	args.method = (cell_t)method;
475170838Smarius	args.instance = instance;
47667204Sobrien	va_start(ap, nreturns);
477170854Smarius	for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;)
478170854Smarius		*--cp = va_arg(ap, cell_t);
47967204Sobrien	if (openfirmware(&args) == -1)
480170838Smarius		return (-1);
48167204Sobrien	if (args.args_n_results[nargs])
482170838Smarius		return (args.args_n_results[nargs]);
483170854Smarius	for (cp = (cell_t *)(args.args_n_results + nargs + (n = args.nreturns));
48484972Srobert	    --n > 0;)
485170854Smarius		*va_arg(ap, cell_t *) = *--cp;
48667204Sobrien	va_end(ap);
487170838Smarius	return (0);
48867204Sobrien}
48967204Sobrien
49067204Sobrien/*
491170838Smarius * Device I/O functions
49267204Sobrien */
49367204Sobrien
49467204Sobrien/* Open an instance for a device. */
49567204Sobrienihandle_t
49667204SobrienOF_open(char *device)
49767204Sobrien{
49867204Sobrien	static struct {
499170838Smarius		cell_t name;
500170838Smarius		cell_t nargs;
501170838Smarius		cell_t nreturns;
502170838Smarius		cell_t device;
503170838Smarius		cell_t instance;
50467204Sobrien	} args = {
50584972Srobert		(cell_t)"open",
50667204Sobrien		1,
50767204Sobrien		1,
50867204Sobrien	};
509170838Smarius
51084972Srobert	args.device = (cell_t)device;
51167204Sobrien	if (openfirmware(&args) == -1 || args.instance == 0) {
512170838Smarius		return (-1);
51367204Sobrien	}
514170838Smarius	return (args.instance);
51567204Sobrien}
51667204Sobrien
51767204Sobrien/* Close an instance. */
51867204Sobrienvoid
51967204SobrienOF_close(ihandle_t instance)
52067204Sobrien{
52167204Sobrien	static struct {
522170838Smarius		cell_t name;
523170838Smarius		cell_t nargs;
524170838Smarius		cell_t nreturns;
525170838Smarius		cell_t instance;
52667204Sobrien	} args = {
52784972Srobert		(cell_t)"close",
52867204Sobrien		1,
52967204Sobrien	};
530170838Smarius
531170838Smarius	args.instance = instance;
53267204Sobrien	openfirmware(&args);
53367204Sobrien}
53467204Sobrien
53567204Sobrien/* Read from an instance. */
53667204Sobrienint
53767204SobrienOF_read(ihandle_t instance, void *addr, int len)
53867204Sobrien{
53967204Sobrien	static struct {
540170838Smarius		cell_t name;
541170838Smarius		cell_t nargs;
542170838Smarius		cell_t nreturns;
543170838Smarius		cell_t instance;
544170838Smarius		cell_t addr;
545170838Smarius		cell_t len;
546170838Smarius		cell_t actual;
54767204Sobrien	} args = {
54884972Srobert		(cell_t)"read",
54967204Sobrien		3,
55067204Sobrien		1,
55167204Sobrien	};
55267204Sobrien
553170838Smarius	args.instance = instance;
55484972Srobert	args.addr = (cell_t)addr;
555170838Smarius	args.len = len;
55668548Sbenno
55768548Sbenno#if defined(OPENFIRM_DEBUG)
55868548Sbenno	printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
55968548Sbenno	    args.instance, args.addr, args.len);
56068548Sbenno#endif
56168548Sbenno
56267204Sobrien	if (openfirmware(&args) == -1)
563170838Smarius		return (-1);
56468548Sbenno
56568548Sbenno#if defined(OPENFIRM_DEBUG)
56668548Sbenno	printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
56768548Sbenno	    args.instance, args.addr, args.len, args.actual);
56868548Sbenno#endif
56968548Sbenno
570170838Smarius	return (args.actual);
57167204Sobrien}
57267204Sobrien
57367204Sobrien/* Write to an instance. */
57467204Sobrienint
57567204SobrienOF_write(ihandle_t instance, void *addr, int len)
57667204Sobrien{
57767204Sobrien	static struct {
578170838Smarius		cell_t name;
579170838Smarius		cell_t nargs;
580170838Smarius		cell_t nreturns;
581170838Smarius		cell_t instance;
582170838Smarius		cell_t addr;
583170838Smarius		cell_t len;
584170838Smarius		cell_t actual;
58567204Sobrien	} args = {
58684972Srobert		(cell_t)"write",
58767204Sobrien		3,
58867204Sobrien		1,
58967204Sobrien	};
59067204Sobrien
591170838Smarius	args.instance = instance;
59284972Srobert	args.addr = (cell_t)addr;
593170838Smarius	args.len = len;
59467204Sobrien	if (openfirmware(&args) == -1)
595170838Smarius		return (-1);
596170838Smarius	return (args.actual);
59767204Sobrien}
59867204Sobrien
59967204Sobrien/* Seek to a position. */
60067204Sobrienint
60168548SbennoOF_seek(ihandle_t instance, u_int64_t pos)
60267204Sobrien{
60367204Sobrien	static struct {
604170838Smarius		cell_t name;
605170838Smarius		cell_t nargs;
606170838Smarius		cell_t nreturns;
607170838Smarius		cell_t instance;
608170838Smarius		cell_t poshi;
609170838Smarius		cell_t poslo;
610170838Smarius		cell_t status;
61167204Sobrien	} args = {
61284972Srobert		(cell_t)"seek",
61367204Sobrien		3,
61467204Sobrien		1,
61567204Sobrien	};
616170838Smarius
617170838Smarius	args.instance = instance;
61884972Srobert	args.poshi = pos >> 32;
61984972Srobert	args.poslo = pos;
62067204Sobrien	if (openfirmware(&args) == -1)
621170838Smarius		return (-1);
622170838Smarius	return (args.status);
62367204Sobrien}
62467204Sobrien
62567204Sobrien/*
626170838Smarius * Memory functions
62767204Sobrien */
62867204Sobrien
62967204Sobrien/* Claim an area of memory. */
63067204Sobrienvoid *
63167204SobrienOF_claim(void *virt, u_int size, u_int align)
63267204Sobrien{
63367204Sobrien	static struct {
634170838Smarius		cell_t name;
635170838Smarius		cell_t nargs;
636170838Smarius		cell_t nreturns;
637170838Smarius		cell_t virt;
638170838Smarius		cell_t size;
639170838Smarius		cell_t align;
640170838Smarius		cell_t baseaddr;
64167204Sobrien	} args = {
64284972Srobert		(cell_t)"claim",
64367204Sobrien		3,
64467204Sobrien		1,
64567204Sobrien	};
64667204Sobrien
64784972Srobert	args.virt = (cell_t)virt;
64867204Sobrien	args.size = size;
64967204Sobrien	args.align = align;
65067204Sobrien	if (openfirmware(&args) == -1)
651170838Smarius		return ((void *)-1);
652170838Smarius	return ((void *)args.baseaddr);
65367204Sobrien}
65467204Sobrien
65567204Sobrien/* Release an area of memory. */
65667204Sobrienvoid
65767204SobrienOF_release(void *virt, u_int size)
65867204Sobrien{
65967204Sobrien	static struct {
660170838Smarius		cell_t name;
661170838Smarius		cell_t nargs;
662170838Smarius		cell_t nreturns;
663170838Smarius		cell_t virt;
664170838Smarius		cell_t size;
66567204Sobrien	} args = {
66684972Srobert		(cell_t)"release",
66767204Sobrien		2,
66867204Sobrien	};
669170838Smarius
67084972Srobert	args.virt = (cell_t)virt;
67167204Sobrien	args.size = size;
67267204Sobrien	openfirmware(&args);
67367204Sobrien}
67467204Sobrien
67567204Sobrien/*
676170838Smarius * Control transfer functions
67767204Sobrien */
67867204Sobrien
67967204Sobrien/* Reset the system and call "boot <bootspec>". */
68067204Sobrienvoid
68167204SobrienOF_boot(char *bootspec)
68267204Sobrien{
68367204Sobrien	static struct {
684170838Smarius		cell_t name;
685170838Smarius		cell_t nargs;
686170838Smarius		cell_t nreturns;
687170838Smarius		cell_t bootspec;
68867204Sobrien	} args = {
68984972Srobert		(cell_t)"boot",
69067204Sobrien		1,
69167204Sobrien	};
69267204Sobrien
69384972Srobert	args.bootspec = (cell_t)bootspec;
69467204Sobrien	openfirmware(&args);
695170838Smarius	for (;;)			/* just in case */
696170838Smarius		;
69767204Sobrien}
69867204Sobrien
699133862Smarius/* Suspend and drop back to the Open Firmware interface. */
70067204Sobrienvoid
70167204SobrienOF_enter()
70267204Sobrien{
70367204Sobrien	static struct {
704170838Smarius		cell_t name;
705170838Smarius		cell_t nargs;
706170838Smarius		cell_t nreturns;
70767204Sobrien	} args = {
70884972Srobert		(cell_t)"enter",
70967204Sobrien	};
71067204Sobrien
71167204Sobrien	openfirmware(&args);
712170838Smarius	/* We may come back. */
71367204Sobrien}
71467204Sobrien
715133862Smarius/* Shut down and drop back to the Open Firmware interface. */
71668548Sbennovoid
71767204SobrienOF_exit()
71867204Sobrien{
71967204Sobrien	static struct {
720170838Smarius		cell_t name;
721170838Smarius		cell_t nargs;
722170838Smarius		cell_t nreturns;
72367204Sobrien	} args = {
72484972Srobert		(cell_t)"exit",
72567204Sobrien	};
72667204Sobrien
72767204Sobrien	openfirmware(&args);
728170838Smarius	for (;;)			/* just in case */
729170838Smarius		;
73067204Sobrien}
73167204Sobrien
73267204Sobrien/* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
733131783Sgrehan#if 0
73467204Sobrienvoid
73567204SobrienOF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
73667204Sobrien{
73767204Sobrien	static struct {
738170838Smarius		cell_t name;
739170838Smarius		cell_t nargs;
740170838Smarius		cell_t nreturns;
741170838Smarius		cell_t virt;
742170838Smarius		cell_t size;
743170838Smarius		cell_t entry;
744170838Smarius		cell_t arg;
745170838Smarius		cell_t len;
74667204Sobrien	} args = {
74784972Srobert		(cell_t)"chain",
74867204Sobrien		5,
74967204Sobrien	};
75067204Sobrien
75184972Srobert	args.virt = (cell_t)virt;
75267204Sobrien	args.size = size;
75384972Srobert	args.entry = (cell_t)entry;
75484972Srobert	args.arg = (cell_t)arg;
75567204Sobrien	args.len = len;
75667204Sobrien	openfirmware(&args);
75767204Sobrien}
75867204Sobrien#else
75967204Sobrienvoid
76067204SobrienOF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
76167204Sobrien{
76267204Sobrien	/*
76367204Sobrien	 * This is a REALLY dirty hack till the firmware gets this going
76467204Sobrien	 */
765131783Sgrehan#if 0
76684617Sbenno	if (size > 0)
76784617Sbenno		OF_release(virt, size);
768131783Sgrehan#endif
76967204Sobrien	entry(0, 0, openfirmware, arg, len);
77067204Sobrien}
77167204Sobrien#endif
772