1d84d862obrien/*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $	*/
2d84d862obrien
3bd77e02imp/*-
4d84d862obrien * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5d84d862obrien * Copyright (C) 1995, 1996 TooLs GmbH.
6d84d862obrien * All rights reserved.
7d84d862obrien *
8d84d862obrien * Redistribution and use in source and binary forms, with or without
9d84d862obrien * modification, are permitted provided that the following conditions
10d84d862obrien * are met:
11d84d862obrien * 1. Redistributions of source code must retain the above copyright
12d84d862obrien *    notice, this list of conditions and the following disclaimer.
13d84d862obrien * 2. Redistributions in binary form must reproduce the above copyright
14d84d862obrien *    notice, this list of conditions and the following disclaimer in the
15d84d862obrien *    documentation and/or other materials provided with the distribution.
16d84d862obrien * 3. All advertising materials mentioning features or use of this software
17d84d862obrien *    must display the following acknowledgement:
18d84d862obrien *	This product includes software developed by TooLs GmbH.
19d84d862obrien * 4. The name of TooLs GmbH may not be used to endorse or promote products
20d84d862obrien *    derived from this software without specific prior written permission.
21d84d862obrien *
22d84d862obrien * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23d84d862obrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24d84d862obrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25d84d862obrien * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26d84d862obrien * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27d84d862obrien * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28d84d862obrien * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29d84d862obrien * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30d84d862obrien * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31d84d862obrien * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32d84d862obrien */
33bd77e02imp/*-
34d84d862obrien * Copyright (C) 2000 Benno Rice.
35d84d862obrien * All rights reserved.
36d84d862obrien *
37d84d862obrien * Redistribution and use in source and binary forms, with or without
38d84d862obrien * modification, are permitted provided that the following conditions
39d84d862obrien * are met:
40d84d862obrien * 1. Redistributions of source code must retain the above copyright
41d84d862obrien *    notice, this list of conditions and the following disclaimer.
42d84d862obrien * 2. Redistributions in binary form must reproduce the above copyright
43d84d862obrien *    notice, this list of conditions and the following disclaimer in the
44d84d862obrien *    documentation and/or other materials provided with the distribution.
45d84d862obrien *
46d84d862obrien * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
47d84d862obrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48d84d862obrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49d84d862obrien * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50d84d862obrien * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51d84d862obrien * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
52d84d862obrien * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53d84d862obrien * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
54d84d862obrien * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
55d84d862obrien * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56d84d862obrien */
57d84d862obrien
5884dccedobrien#include <sys/cdefs.h>
5984dccedobrien__FBSDID("$FreeBSD$");
6084dccedobrien
61d84d862obrien#include <machine/stdarg.h>
62d84d862obrien
637d73a33benno#include <stand.h>
647d73a33benno
65d84d862obrien#include "openfirm.h"
66d84d862obrien
6736e649fjakeint (*openfirmware)(void *);
6836e649fjake
69d6e6728mariusphandle_t chosen;
704442365bennoihandle_t mmu;
714442365bennoihandle_t memory;
72d0e1702andreastint	  real_mode = 0;
73994f797benno
74128f33dmarius/* Initialiser */
75d84d862obrien
76d84d862obrienvoid
77d84d862obrienOF_init(int (*openfirm)(void *))
78d84d862obrien{
79d0e1702andreast	phandle_t options;
8070881bcandreast	char	  mode[sizeof("true")];
81994f797benno
82d84d862obrien	openfirmware = openfirm;
83994f797benno
84128f33dmarius	if ((chosen = OF_finddevice("/chosen")) == -1)
85128f33dmarius		OF_exit();
864da7d60nwhitehorn	if (OF_getprop(chosen, "memory", &memory, sizeof(memory)) == -1) {
874da7d60nwhitehorn		memory = OF_open("/memory");
884da7d60nwhitehorn		if (memory == -1)
894da7d60nwhitehorn			memory = OF_open("/memory@0");
904da7d60nwhitehorn		if (memory == -1)
914da7d60nwhitehorn			OF_exit();
924da7d60nwhitehorn	}
93d6e6728marius	if (OF_getprop(chosen, "mmu", &mmu, sizeof(mmu)) == -1)
94d6e6728marius		OF_exit();
95d0e1702andreast
9670881bcandreast	/*
97d0e1702andreast	 * Check if we run in real mode. If so, we do not need to map
98d0e1702andreast	 * memory later on.
99d0e1702andreast	 */
100d0e1702andreast	options = OF_finddevice("/options");
10170881bcandreast	if (OF_getprop(options, "real-mode?", mode, sizeof(mode)) > 0 &&
10270881bcandreast	    strcmp(mode, "true") == 0)
103d0e1702andreast		real_mode = 1;
104e9d6f8ckmacy}
105e9d6f8ckmacy
106d84d862obrien/*
107d84d862obrien * Generic functions
108d84d862obrien */
109d84d862obrien
110d84d862obrien/* Test to see if a service exists. */
111d84d862obrienint
112d84d862obrienOF_test(char *name)
113d84d862obrien{
114d84d862obrien	static struct {
115128f33dmarius		cell_t name;
116128f33dmarius		cell_t nargs;
117128f33dmarius		cell_t nreturns;
118128f33dmarius		cell_t service;
119128f33dmarius		cell_t missing;
120d84d862obrien	} args = {
1210d8645drobert		(cell_t)"test",
122d84d862obrien		1,
123d84d862obrien		1,
124d84d862obrien	};
125d84d862obrien
1260d8645drobert	args.service = (cell_t)name;
127d84d862obrien	if (openfirmware(&args) == -1)
128128f33dmarius		return (-1);
129128f33dmarius	return (args.missing);
130d84d862obrien}
131d84d862obrien
132d84d862obrien/* Return firmware millisecond count. */
133d84d862obrienint
134d84d862obrienOF_milliseconds()
135d84d862obrien{
136d84d862obrien	static struct {
137128f33dmarius		cell_t name;
138128f33dmarius		cell_t nargs;
139128f33dmarius		cell_t nreturns;
140128f33dmarius		cell_t ms;
141d84d862obrien	} args = {
1420d8645drobert		(cell_t)"milliseconds",
143d84d862obrien		0,
144d84d862obrien		1,
145d84d862obrien	};
146128f33dmarius
147d84d862obrien	openfirmware(&args);
148128f33dmarius	return (args.ms);
149d84d862obrien}
150d84d862obrien
151d84d862obrien/*
152d84d862obrien * Device tree functions
153d84d862obrien */
154d84d862obrien
155d84d862obrien/* Return the next sibling of this node or 0. */
156d84d862obrienphandle_t
157d84d862obrienOF_peer(phandle_t node)
158d84d862obrien{
159d84d862obrien	static struct {
160128f33dmarius		cell_t name;
161128f33dmarius		cell_t nargs;
162128f33dmarius		cell_t nreturns;
163128f33dmarius		cell_t node;
164128f33dmarius		cell_t next;
165d84d862obrien	} args = {
1660d8645drobert		(cell_t)"peer",
167d84d862obrien		1,
168d84d862obrien		1,
169d84d862obrien	};
170d84d862obrien
171128f33dmarius	args.node = node;
172d84d862obrien	if (openfirmware(&args) == -1)
173128f33dmarius		return (-1);
174128f33dmarius	return (args.next);
175d84d862obrien}
176d84d862obrien
177d84d862obrien/* Return the first child of this node or 0. */
178d84d862obrienphandle_t
179d84d862obrienOF_child(phandle_t node)
180d84d862obrien{
181d84d862obrien	static struct {
182128f33dmarius		cell_t name;
183128f33dmarius		cell_t nargs;
184128f33dmarius		cell_t nreturns;
185128f33dmarius		cell_t node;
186128f33dmarius		cell_t child;
187d84d862obrien	} args = {
1880d8645drobert		(cell_t)"child",
189d84d862obrien		1,
190d84d862obrien		1,
191d84d862obrien	};
192d84d862obrien
193128f33dmarius	args.node = node;
194d84d862obrien	if (openfirmware(&args) == -1)
195128f33dmarius		return (-1);
196128f33dmarius	return (args.child);
197d84d862obrien}
198d84d862obrien
199d84d862obrien/* Return the parent of this node or 0. */
200d84d862obrienphandle_t
201d84d862obrienOF_parent(phandle_t node)
202d84d862obrien{
203d84d862obrien	static struct {
204128f33dmarius		cell_t name;
205128f33dmarius		cell_t nargs;
206128f33dmarius		cell_t nreturns;
207128f33dmarius		cell_t node;
208128f33dmarius		cell_t parent;
209d84d862obrien	} args = {
2100d8645drobert		(cell_t)"parent",
211d84d862obrien		1,
212d84d862obrien		1,
213d84d862obrien	};
214d84d862obrien
215128f33dmarius	args.node = node;
216d84d862obrien	if (openfirmware(&args) == -1)
217128f33dmarius		return (-1);
218128f33dmarius	return (args.parent);
219d84d862obrien}
220d84d862obrien
221d84d862obrien/* Return the package handle that corresponds to an instance handle. */
222d84d862obrienphandle_t
223d84d862obrienOF_instance_to_package(ihandle_t instance)
224d84d862obrien{
225d84d862obrien	static struct {
226128f33dmarius		cell_t name;
227128f33dmarius		cell_t nargs;
228128f33dmarius		cell_t nreturns;
229128f33dmarius		cell_t instance;
230128f33dmarius		cell_t package;
231d84d862obrien	} args = {
2320d8645drobert		(cell_t)"instance-to-package",
233d84d862obrien		1,
234d84d862obrien		1,
235d84d862obrien	};
236128f33dmarius
237128f33dmarius	args.instance = instance;
238d84d862obrien	if (openfirmware(&args) == -1)
239128f33dmarius		return (-1);
240128f33dmarius	return (args.package);
241d84d862obrien}
242d84d862obrien
243d84d862obrien/* Get the length of a property of a package. */
244d84d862obrienint
24525cf093impOF_getproplen(phandle_t package, const char *propname)
246d84d862obrien{
247d84d862obrien	static struct {
248128f33dmarius		cell_t name;
249128f33dmarius		cell_t nargs;
250128f33dmarius		cell_t nreturns;
251128f33dmarius		cell_t package;
252128f33dmarius		cell_t propname;
253128f33dmarius		cell_t proplen;
254d84d862obrien	} args = {
2550d8645drobert		(cell_t)"getproplen",
256d84d862obrien		2,
257d84d862obrien		1,
258d84d862obrien	};
259d84d862obrien
260128f33dmarius	args.package = package;
2610d8645drobert	args.propname = (cell_t)propname;
262d84d862obrien	if (openfirmware(&args) == -1)
263128f33dmarius		return (-1);
264128f33dmarius	return (args.proplen);
265d84d862obrien}
266d84d862obrien
267d84d862obrien/* Get the value of a property of a package. */
268d84d862obrienint
26925cf093impOF_getprop(phandle_t package, const char *propname, void *buf, int buflen)
270d84d862obrien{
271d84d862obrien	static struct {
272128f33dmarius		cell_t name;
273128f33dmarius		cell_t nargs;
274128f33dmarius		cell_t nreturns;
275128f33dmarius		cell_t package;
276128f33dmarius		cell_t propname;
277128f33dmarius		cell_t buf;
278128f33dmarius		cell_t buflen;
279128f33dmarius		cell_t size;
280d84d862obrien	} args = {
2810d8645drobert		(cell_t)"getprop",
282d84d862obrien		4,
283d84d862obrien		1,
284d84d862obrien	};
285128f33dmarius
286128f33dmarius	args.package = package;
2870d8645drobert	args.propname = (cell_t)propname;
2880d8645drobert	args.buf = (cell_t)buf;
289128f33dmarius	args.buflen = buflen;
290d84d862obrien	if (openfirmware(&args) == -1)
291128f33dmarius		return (-1);
292128f33dmarius	return (args.size);
293d84d862obrien}
294d84d862obrien
295d84d862obrien/* Get the next property of a package. */
296d84d862obrienint
29725cf093impOF_nextprop(phandle_t package, const char *previous, char *buf)
298d84d862obrien{
299d84d862obrien	static struct {
300128f33dmarius		cell_t name;
301128f33dmarius		cell_t nargs;
302128f33dmarius		cell_t nreturns;
303128f33dmarius		cell_t package;
304128f33dmarius		cell_t previous;
305128f33dmarius		cell_t buf;
306128f33dmarius		cell_t flag;
307d84d862obrien	} args = {
3080d8645drobert		(cell_t)"nextprop",
309d84d862obrien		3,
310d84d862obrien		1,
311d84d862obrien	};
312d84d862obrien
313128f33dmarius	args.package = package;
3140d8645drobert	args.previous = (cell_t)previous;
3150d8645drobert	args.buf = (cell_t)buf;
316d84d862obrien	if (openfirmware(&args) == -1)
317128f33dmarius		return (-1);
318128f33dmarius	return (args.flag);
319d84d862obrien}
320d84d862obrien
321d84d862obrien/* Set the value of a property of a package. */
322d84d862obrien/* XXX Has a bug on FirePower */
323d84d862obrienint
32425cf093impOF_setprop(phandle_t package, const char *propname, void *buf, int len)
325d84d862obrien{
326d84d862obrien	static struct {
327128f33dmarius		cell_t name;
328128f33dmarius		cell_t nargs;
329128f33dmarius		cell_t nreturns;
330128f33dmarius		cell_t package;
331128f33dmarius		cell_t propname;
332128f33dmarius		cell_t buf;
333128f33dmarius		cell_t len;
334128f33dmarius		cell_t size;
335d84d862obrien	} args = {
3360d8645drobert		(cell_t)"setprop",
337d84d862obrien		4,
338d84d862obrien		1,
339d84d862obrien	};
340128f33dmarius
341128f33dmarius	args.package = package;
3420d8645drobert	args.propname = (cell_t)propname;
3430d8645drobert	args.buf = (cell_t)buf;
344128f33dmarius	args.len = len;
345d84d862obrien	if (openfirmware(&args) == -1)
346128f33dmarius		return (-1);
347128f33dmarius	return (args.size);
348d84d862obrien}
349d84d862obrien
350d84d862obrien/* Convert a device specifier to a fully qualified pathname. */
351d84d862obrienint
3527d73a33bennoOF_canon(const char *device, char *buf, int len)
353d84d862obrien{
354d84d862obrien	static struct {
355128f33dmarius		cell_t name;
356128f33dmarius		cell_t nargs;
357128f33dmarius		cell_t nreturns;
358128f33dmarius		cell_t device;
359128f33dmarius		cell_t buf;
360128f33dmarius		cell_t len;
361128f33dmarius		cell_t size;
362d84d862obrien	} args = {
3630d8645drobert		(cell_t)"canon",
364d84d862obrien		3,
365d84d862obrien		1,
366d84d862obrien	};
367128f33dmarius
3680d8645drobert	args.device = (cell_t)device;
3690d8645drobert	args.buf = (cell_t)buf;
370128f33dmarius	args.len = len;
371d84d862obrien	if (openfirmware(&args) == -1)
372128f33dmarius		return (-1);
373128f33dmarius	return (args.size);
374d84d862obrien}
375d84d862obrien
376d84d862obrien/* Return a package handle for the specified device. */
377d84d862obrienphandle_t
3787d73a33bennoOF_finddevice(const char *device)
379d84d862obrien{
380d84d862obrien	static struct {
381128f33dmarius		cell_t name;
382128f33dmarius		cell_t nargs;
383128f33dmarius		cell_t nreturns;
384128f33dmarius		cell_t device;
385128f33dmarius		cell_t package;
386d84d862obrien	} args = {
3870d8645drobert		(cell_t)"finddevice",
388d84d862obrien		1,
389d84d862obrien		1,
390128f33dmarius	};
391128f33dmarius
3920d8645drobert	args.device = (cell_t)device;
393d84d862obrien	if (openfirmware(&args) == -1)
394128f33dmarius		return (-1);
395128f33dmarius	return (args.package);
396d84d862obrien}
397d84d862obrien
398d84d862obrien/* Return the fully qualified pathname corresponding to an instance. */
399d84d862obrienint
400d84d862obrienOF_instance_to_path(ihandle_t instance, char *buf, int len)
401d84d862obrien{
402d84d862obrien	static struct {
403128f33dmarius		cell_t name;
404128f33dmarius		cell_t nargs;
405128f33dmarius		cell_t nreturns;
406128f33dmarius		cell_t instance;
407128f33dmarius		cell_t buf;
408128f33dmarius		cell_t len;
409128f33dmarius		cell_t size;
410d84d862obrien	} args = {
4110d8645drobert		(cell_t)"instance-to-path",
412d84d862obrien		3,
413d84d862obrien		1,
414d84d862obrien	};
415d84d862obrien
416128f33dmarius	args.instance = instance;
4170d8645drobert	args.buf = (cell_t)buf;
418128f33dmarius	args.len = len;
419d84d862obrien	if (openfirmware(&args) == -1)
420128f33dmarius		return (-1);
421128f33dmarius	return (args.size);
422d84d862obrien}
423d84d862obrien
424d84d862obrien/* Return the fully qualified pathname corresponding to a package. */
425d84d862obrienint
426d84d862obrienOF_package_to_path(phandle_t package, char *buf, int len)
427d84d862obrien{
428d84d862obrien	static struct {
429128f33dmarius		cell_t name;
430128f33dmarius		cell_t nargs;
431128f33dmarius		cell_t nreturns;
432128f33dmarius		cell_t package;
433128f33dmarius		cell_t buf;
434128f33dmarius		cell_t len;
435128f33dmarius		cell_t size;
436d84d862obrien	} args = {
4370d8645drobert		(cell_t)"package-to-path",
438d84d862obrien		3,
439d84d862obrien		1,
440d84d862obrien	};
441d84d862obrien
442128f33dmarius	args.package = package;
4430d8645drobert	args.buf = (cell_t)buf;
444128f33dmarius	args.len = len;
445d84d862obrien	if (openfirmware(&args) == -1)
446128f33dmarius		return (-1);
447128f33dmarius	return (args.size);
448d84d862obrien}
449d84d862obrien
450d84d862obrien/*  Call the method in the scope of a given instance. */
451d84d862obrienint
452d84d862obrienOF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
453d84d862obrien{
454d84d862obrien	va_list ap;
455d84d862obrien	static struct {
456128f33dmarius		cell_t name;
457128f33dmarius		cell_t nargs;
458128f33dmarius		cell_t nreturns;
459128f33dmarius		cell_t method;
460128f33dmarius		cell_t instance;
461128f33dmarius		cell_t args_n_results[12];
462d84d862obrien	} args = {
4630d8645drobert		(cell_t)"call-method",
464d84d862obrien		2,
465d84d862obrien		1,
466d84d862obrien	};
467d6e6728marius	cell_t *cp;
468d6e6728marius	int n;
469d84d862obrien
470d84d862obrien	if (nargs > 6)
471128f33dmarius		return (-1);
472d84d862obrien	args.nargs = nargs + 2;
473d84d862obrien	args.nreturns = nreturns + 1;
4740d8645drobert	args.method = (cell_t)method;
475128f33dmarius	args.instance = instance;
476d84d862obrien	va_start(ap, nreturns);
477d6e6728marius	for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;)
478d6e6728marius		*--cp = va_arg(ap, cell_t);
479d84d862obrien	if (openfirmware(&args) == -1)
480128f33dmarius		return (-1);
481d84d862obrien	if (args.args_n_results[nargs])
482128f33dmarius		return (args.args_n_results[nargs]);
483d6e6728marius	for (cp = (cell_t *)(args.args_n_results + nargs + (n = args.nreturns));
4840d8645drobert	    --n > 0;)
485d6e6728marius		*va_arg(ap, cell_t *) = *--cp;
486d84d862obrien	va_end(ap);
487128f33dmarius	return (0);
488d84d862obrien}
489d84d862obrien
490d84d862obrien/*
491128f33dmarius * Device I/O functions
492d84d862obrien */
493d84d862obrien
494d84d862obrien/* Open an instance for a device. */
495d84d862obrienihandle_t
496d84d862obrienOF_open(char *device)
497d84d862obrien{
498d84d862obrien	static struct {
499128f33dmarius		cell_t name;
500128f33dmarius		cell_t nargs;
501128f33dmarius		cell_t nreturns;
502128f33dmarius		cell_t device;
503128f33dmarius		cell_t instance;
504d84d862obrien	} args = {
5050d8645drobert		(cell_t)"open",
506d84d862obrien		1,
507d84d862obrien		1,
508d84d862obrien	};
509128f33dmarius
5100d8645drobert	args.device = (cell_t)device;
511d84d862obrien	if (openfirmware(&args) == -1 || args.instance == 0) {
512128f33dmarius		return (-1);
513d84d862obrien	}
514128f33dmarius	return (args.instance);
515d84d862obrien}
516d84d862obrien
517d84d862obrien/* Close an instance. */
518d84d862obrienvoid
519d84d862obrienOF_close(ihandle_t instance)
520d84d862obrien{
521d84d862obrien	static struct {
522128f33dmarius		cell_t name;
523128f33dmarius		cell_t nargs;
524128f33dmarius		cell_t nreturns;
525128f33dmarius		cell_t instance;
526d84d862obrien	} args = {
5270d8645drobert		(cell_t)"close",
528d84d862obrien		1,
529d84d862obrien	};
530128f33dmarius
531128f33dmarius	args.instance = instance;
532d84d862obrien	openfirmware(&args);
533d84d862obrien}
534d84d862obrien
535d84d862obrien/* Read from an instance. */
536d84d862obrienint
537d84d862obrienOF_read(ihandle_t instance, void *addr, int len)
538d84d862obrien{
539d84d862obrien	static struct {
540128f33dmarius		cell_t name;
541128f33dmarius		cell_t nargs;
542128f33dmarius		cell_t nreturns;
543128f33dmarius		cell_t instance;
544128f33dmarius		cell_t addr;
545128f33dmarius		cell_t len;
546128f33dmarius		cell_t actual;
547d84d862obrien	} args = {
5480d8645drobert		(cell_t)"read",
549d84d862obrien		3,
550d84d862obrien		1,
551d84d862obrien	};
552d84d862obrien
553128f33dmarius	args.instance = instance;
5540d8645drobert	args.addr = (cell_t)addr;
555128f33dmarius	args.len = len;
5567d73a33benno
5577d73a33benno#if defined(OPENFIRM_DEBUG)
5587d73a33benno	printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
5597d73a33benno	    args.instance, args.addr, args.len);
5607d73a33benno#endif
5617d73a33benno
562d84d862obrien	if (openfirmware(&args) == -1)
563128f33dmarius		return (-1);
5647d73a33benno
5657d73a33benno#if defined(OPENFIRM_DEBUG)
5667d73a33benno	printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
5677d73a33benno	    args.instance, args.addr, args.len, args.actual);
5687d73a33benno#endif
5697d73a33benno
570128f33dmarius	return (args.actual);
571d84d862obrien}
572d84d862obrien
573d84d862obrien/* Write to an instance. */
574d84d862obrienint
575d84d862obrienOF_write(ihandle_t instance, void *addr, int len)
576d84d862obrien{
577d84d862obrien	static struct {
578128f33dmarius		cell_t name;
579128f33dmarius		cell_t nargs;
580128f33dmarius		cell_t nreturns;
581128f33dmarius		cell_t instance;
582128f33dmarius		cell_t addr;
583128f33dmarius		cell_t len;
584128f33dmarius		cell_t actual;
585d84d862obrien	} args = {
5860d8645drobert		(cell_t)"write",
587d84d862obrien		3,
588d84d862obrien		1,
589d84d862obrien	};
590d84d862obrien
591128f33dmarius	args.instance = instance;
5920d8645drobert	args.addr = (cell_t)addr;
593128f33dmarius	args.len = len;
594d84d862obrien	if (openfirmware(&args) == -1)
595128f33dmarius		return (-1);
596128f33dmarius	return (args.actual);
597d84d862obrien}
598d84d862obrien
599d84d862obrien/* Seek to a position. */
600d84d862obrienint
601cb38894impOF_seek(ihandle_t instance, uint64_t pos)
602d84d862obrien{
603d84d862obrien	static struct {
604128f33dmarius		cell_t name;
605128f33dmarius		cell_t nargs;
606128f33dmarius		cell_t nreturns;
607128f33dmarius		cell_t instance;
608128f33dmarius		cell_t poshi;
609128f33dmarius		cell_t poslo;
610128f33dmarius		cell_t status;
611d84d862obrien	} args = {
6120d8645drobert		(cell_t)"seek",
613d84d862obrien		3,
614d84d862obrien		1,
615d84d862obrien	};
616128f33dmarius
617128f33dmarius	args.instance = instance;
6180d8645drobert	args.poshi = pos >> 32;
6190d8645drobert	args.poslo = pos;
620d84d862obrien	if (openfirmware(&args) == -1)
621128f33dmarius		return (-1);
622128f33dmarius	return (args.status);
623d84d862obrien}
624d84d862obrien
625697206dtsoome/* Blocks. */
626697206dtsoomeunsigned int
627697206dtsoomeOF_blocks(ihandle_t instance)
628697206dtsoome{
629697206dtsoome	static struct {
630697206dtsoome		cell_t name;
631697206dtsoome		cell_t nargs;
632697206dtsoome		cell_t nreturns;
633697206dtsoome		cell_t instance;
634697206dtsoome		cell_t result;
635697206dtsoome		cell_t blocks;
636697206dtsoome	} args = {
637697206dtsoome		(cell_t)"#blocks",
638697206dtsoome		2,
639697206dtsoome		1,
640697206dtsoome	};
641697206dtsoome
642697206dtsoome	args.instance = instance;
643697206dtsoome	if (openfirmware(&args) == -1)
644697206dtsoome		return ((unsigned int)-1);
645697206dtsoome	return (args.blocks);
646697206dtsoome}
647697206dtsoome
648697206dtsoome/* Block size. */
649697206dtsoomeint
650697206dtsoomeOF_block_size(ihandle_t instance)
651697206dtsoome{
652697206dtsoome	static struct {
653697206dtsoome		cell_t name;
654697206dtsoome		cell_t nargs;
655697206dtsoome		cell_t nreturns;
656697206dtsoome		cell_t instance;
657697206dtsoome		cell_t result;
658697206dtsoome		cell_t size;
659697206dtsoome	} args = {
660697206dtsoome		(cell_t)"block-size",
661697206dtsoome		2,
662697206dtsoome		1,
663697206dtsoome	};
664697206dtsoome
665697206dtsoome	args.instance = instance;
666697206dtsoome	if (openfirmware(&args) == -1)
667697206dtsoome		return (512);
668697206dtsoome	return (args.size);
669697206dtsoome}
670697206dtsoome
671697206dtsoome/*
672128f33dmarius * Memory functions
673d84d862obrien */
674d84d862obrien
675d84d862obrien/* Claim an area of memory. */
676d84d862obrienvoid *
677d84d862obrienOF_claim(void *virt, u_int size, u_int align)
678d84d862obrien{
679d84d862obrien	static struct {
680128f33dmarius		cell_t name;
681128f33dmarius		cell_t nargs;
682128f33dmarius		cell_t nreturns;
683128f33dmarius		cell_t virt;
684128f33dmarius		cell_t size;
685128f33dmarius		cell_t align;
686128f33dmarius		cell_t baseaddr;
687d84d862obrien	} args = {
6880d8645drobert		(cell_t)"claim",
689d84d862obrien		3,
690d84d862obrien		1,
691d84d862obrien	};
692d84d862obrien
6930d8645drobert	args.virt = (cell_t)virt;
694d84d862obrien	args.size = size;
695d84d862obrien	args.align = align;
696d84d862obrien	if (openfirmware(&args) == -1)
697128f33dmarius		return ((void *)-1);
698128f33dmarius	return ((void *)args.baseaddr);
6990d8645drobert}
7000d8645drobert
701d84d862obrien/* Release an area of memory. */
702d84d862obrienvoid
703d84d862obrienOF_release(void *virt, u_int size)
704d84d862obrien{
705d84d862obrien	static struct {
706128f33dmarius		cell_t name;
707128f33dmarius		cell_t nargs;
708128f33dmarius		cell_t nreturns;
709128f33dmarius		cell_t virt;
710128f33dmarius		cell_t size;
711d84d862obrien	} args = {
7120d8645drobert		(cell_t)"release",
713d84d862obrien		2,
714d84d862obrien	};
715128f33dmarius
7160d8645drobert	args.virt = (cell_t)virt;
717d84d862obrien	args.size = size;
718d84d862obrien	openfirmware(&args);
719d84d862obrien}
720d84d862obrien
721d84d862obrien/*
722128f33dmarius * Control transfer functions
723d84d862obrien */
724d84d862obrien
725d84d862obrien/* Reset the system and call "boot <bootspec>". */
726d84d862obrienvoid
727d84d862obrienOF_boot(char *bootspec)
728d84d862obrien{
729d84d862obrien	static struct {
730128f33dmarius		cell_t name;
731128f33dmarius		cell_t nargs;
732128f33dmarius		cell_t nreturns;
733128f33dmarius		cell_t bootspec;
734d84d862obrien	} args = {
7350d8645drobert		(cell_t)"boot",
736d84d862obrien		1,
737d84d862obrien	};
738d84d862obrien
7390d8645drobert	args.bootspec = (cell_t)bootspec;
740d84d862obrien	openfirmware(&args);
741128f33dmarius	for (;;)			/* just in case */
742128f33dmarius		;
743d84d862obrien}
744d84d862obrien
74524ad8a9marius/* Suspend and drop back to the Open Firmware interface. */
746d84d862obrienvoid
747d84d862obrienOF_enter()
748d84d862obrien{
749d84d862obrien	static struct {
750128f33dmarius		cell_t name;
751128f33dmarius		cell_t nargs;
752128f33dmarius		cell_t nreturns;
753d84d862obrien	} args = {
7540d8645drobert		(cell_t)"enter",
755d84d862obrien	};
756d84d862obrien
757d84d862obrien	openfirmware(&args);
758128f33dmarius	/* We may come back. */
759d84d862obrien}
760d84d862obrien
76124ad8a9marius/* Shut down and drop back to the Open Firmware interface. */
7627d73a33bennovoid
763d84d862obrienOF_exit()
764d84d862obrien{
765d84d862obrien	static struct {
766128f33dmarius		cell_t name;
767128f33dmarius		cell_t nargs;
768128f33dmarius		cell_t nreturns;
769d84d862obrien	} args = {
7700d8645drobert		(cell_t)"exit",
771d84d862obrien	};
772d84d862obrien
773d84d862obrien	openfirmware(&args);
774128f33dmarius	for (;;)			/* just in case */
775128f33dmarius		;
776d84d862obrien}
777d84d862obrien
77859b9a76nwhitehornvoid
77959b9a76nwhitehornOF_quiesce()
78059b9a76nwhitehorn{
78159b9a76nwhitehorn	static struct {
78259b9a76nwhitehorn		cell_t name;
78359b9a76nwhitehorn		cell_t nargs;
78459b9a76nwhitehorn		cell_t nreturns;
78559b9a76nwhitehorn	} args = {
78659b9a76nwhitehorn		(cell_t)"quiesce",
78759b9a76nwhitehorn	};
78859b9a76nwhitehorn
78959b9a76nwhitehorn	openfirmware(&args);
79059b9a76nwhitehorn}
79159b9a76nwhitehorn
792d84d862obrien/* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
7936001ea5grehan#if 0
794d84d862obrienvoid
795d84d862obrienOF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
796d84d862obrien{
797d84d862obrien	static struct {
798128f33dmarius		cell_t name;
799128f33dmarius		cell_t nargs;
800128f33dmarius		cell_t nreturns;
801128f33dmarius		cell_t virt;
802128f33dmarius		cell_t size;
803128f33dmarius		cell_t entry;
804128f33dmarius		cell_t arg;
805128f33dmarius		cell_t len;
806d84d862obrien	} args = {
8070d8645drobert		(cell_t)"chain",
808d84d862obrien		5,
809d84d862obrien	};
810d84d862obrien
8110d8645drobert	args.virt = (cell_t)virt;
812d84d862obrien	args.size = size;
8130d8645drobert	args.entry = (cell_t)entry;
8140d8645drobert	args.arg = (cell_t)arg;
815d84d862obrien	args.len = len;
816d84d862obrien	openfirmware(&args);
817d84d862obrien}
818d84d862obrien#else
819d84d862obrienvoid
820d84d862obrienOF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
821d84d862obrien{
822d84d862obrien	/*
823d84d862obrien	 * This is a REALLY dirty hack till the firmware gets this going
824d84d862obrien	 */
8256001ea5grehan#if 0
826994f797benno	if (size > 0)
827994f797benno		OF_release(virt, size);
8286001ea5grehan#endif
829d84d862obrien	entry(0, 0, openfirmware, arg, len);
830d84d862obrien}
831d84d862obrien#endif
832