openfirm.c revision 100318
167204Sobrien/*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $	*/
267204Sobrien
367204Sobrien/*
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 */
3367204Sobrien/*
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 * $FreeBSD: head/sys/boot/ofw/libofw/openfirm.c 100318 2002-07-18 12:39:02Z benno $
5867204Sobrien */
5967204Sobrien
6067204Sobrien#include <machine/stdarg.h>
6167204Sobrien
6268548Sbenno#include <stand.h>
6368548Sbenno
6467204Sobrien#include "openfirm.h"
6567204Sobrien
6685717Sjakeint (*openfirmware)(void *);
6785717Sjake
6867204Sobrienstatic ihandle_t stdin;
6967204Sobrienstatic ihandle_t stdout;
7067204Sobrien
71100318Sbennoihandle_t mmu;
72100318Sbennoihandle_t memory;
7384617Sbenno
7467204Sobrien/* Initialiaser */
7567204Sobrien
7667204Sobrienvoid
7767204SobrienOF_init(int (*openfirm)(void *))
7867204Sobrien{
7984617Sbenno	phandle_t	chosen;
8084617Sbenno
8167204Sobrien	openfirmware = openfirm;
8284617Sbenno
8384617Sbenno	chosen = OF_finddevice("/chosen");
8484617Sbenno	OF_getprop(chosen, "memory", &memory, sizeof(memory));
8584617Sbenno	if (memory == 0)
8684617Sbenno		panic("failed to get memory ihandle");
8784617Sbenno	OF_getprop(chosen, "mmu", &mmu, sizeof(mmu));
8884617Sbenno	if (mmu == 0)
8984617Sbenno		panic("failed to get mmu ihandle");
9067204Sobrien}
9167204Sobrien
9267204Sobrien/*
9367204Sobrien * Generic functions
9467204Sobrien */
9567204Sobrien
9667204Sobrien/* Test to see if a service exists. */
9767204Sobrienint
9867204SobrienOF_test(char *name)
9967204Sobrien{
10067204Sobrien	static struct {
10184972Srobert		cell_t	name;
10284972Srobert		cell_t	nargs;
10384972Srobert		cell_t	nreturns;
10484972Srobert		cell_t	service;
10584972Srobert		cell_t	missing;
10667204Sobrien	} args = {
10784972Srobert		(cell_t)"test",
10867204Sobrien		1,
10967204Sobrien		1,
11084972Srobert		0,
11184972Srobert		0
11267204Sobrien	};
11367204Sobrien
11484972Srobert	args.service = (cell_t)name;
11567204Sobrien	if (openfirmware(&args) == -1)
11667204Sobrien		return -1;
11784972Srobert	return (int)args.missing;
11867204Sobrien}
11967204Sobrien
12067204Sobrien/* Return firmware millisecond count. */
12167204Sobrienint
12267204SobrienOF_milliseconds()
12367204Sobrien{
12467204Sobrien	static struct {
12584972Srobert		cell_t	name;
12684972Srobert		cell_t	nargs;
12784972Srobert		cell_t	nreturns;
12884972Srobert		cell_t	ms;
12967204Sobrien	} args = {
13084972Srobert		(cell_t)"milliseconds",
13167204Sobrien		0,
13267204Sobrien		1,
13384972Srobert		0
13467204Sobrien	};
13567204Sobrien
13667204Sobrien	openfirmware(&args);
13784972Srobert	return (int)args.ms;
13867204Sobrien}
13967204Sobrien
14067204Sobrien/*
14167204Sobrien * Device tree functions
14267204Sobrien */
14367204Sobrien
14467204Sobrien/* Return the next sibling of this node or 0. */
14567204Sobrienphandle_t
14667204SobrienOF_peer(phandle_t node)
14767204Sobrien{
14867204Sobrien	static struct {
14984972Srobert		cell_t		name;
15084972Srobert		cell_t		nargs;
15184972Srobert		cell_t		nreturns;
15284972Srobert		cell_t		node;
15384972Srobert		cell_t		next;
15467204Sobrien	} args = {
15584972Srobert		(cell_t)"peer",
15667204Sobrien		1,
15767204Sobrien		1,
15884972Srobert		0,
15984972Srobert		0
16067204Sobrien	};
16167204Sobrien
16284972Srobert	args.node = (u_int)node;
16367204Sobrien	if (openfirmware(&args) == -1)
16467204Sobrien		return -1;
16584972Srobert	return (phandle_t)args.next;
16667204Sobrien}
16767204Sobrien
16867204Sobrien/* Return the first child of this node or 0. */
16967204Sobrienphandle_t
17067204SobrienOF_child(phandle_t node)
17167204Sobrien{
17267204Sobrien	static struct {
17384972Srobert		cell_t		name;
17484972Srobert		cell_t		nargs;
17584972Srobert		cell_t		nreturns;
17684972Srobert		cell_t		node;
17784972Srobert		cell_t		child;
17867204Sobrien	} args = {
17984972Srobert		(cell_t)"child",
18067204Sobrien		1,
18167204Sobrien		1,
18284972Srobert		0,
18384972Srobert		0
18467204Sobrien	};
18567204Sobrien
18684972Srobert	args.node = (u_int)node;
18767204Sobrien	if (openfirmware(&args) == -1)
18867204Sobrien		return -1;
18984972Srobert	return (phandle_t)args.child;
19067204Sobrien}
19167204Sobrien
19267204Sobrien/* Return the parent of this node or 0. */
19367204Sobrienphandle_t
19467204SobrienOF_parent(phandle_t node)
19567204Sobrien{
19667204Sobrien	static struct {
19784972Srobert		cell_t		name;
19884972Srobert		cell_t		nargs;
19984972Srobert		cell_t		nreturns;
20084972Srobert		cell_t		node;
20184972Srobert		cell_t		parent;
20267204Sobrien	} args = {
20384972Srobert		(cell_t)"parent",
20467204Sobrien		1,
20567204Sobrien		1,
20684972Srobert		0,
20784972Srobert		0
20867204Sobrien	};
20967204Sobrien
21084972Srobert	args.node = (u_int)node;
21167204Sobrien	if (openfirmware(&args) == -1)
21267204Sobrien		return -1;
21384972Srobert	return (phandle_t)args.parent;
21467204Sobrien}
21567204Sobrien
21667204Sobrien/* Return the package handle that corresponds to an instance handle. */
21767204Sobrienphandle_t
21867204SobrienOF_instance_to_package(ihandle_t instance)
21967204Sobrien{
22067204Sobrien	static struct {
22184972Srobert		cell_t	name;
22284972Srobert		cell_t	nargs;
22384972Srobert		cell_t	nreturns;
22484972Srobert		cell_t	instance;
22584972Srobert		cell_t	package;
22667204Sobrien	} args = {
22784972Srobert		(cell_t)"instance-to-package",
22867204Sobrien		1,
22967204Sobrien		1,
23084972Srobert		0,
23184972Srobert		0
23267204Sobrien	};
23367204Sobrien
23484972Srobert	args.instance = (u_int)instance;
23567204Sobrien	if (openfirmware(&args) == -1)
23667204Sobrien		return -1;
23784972Srobert	return (phandle_t)args.package;
23867204Sobrien}
23967204Sobrien
24067204Sobrien/* Get the length of a property of a package. */
24167204Sobrienint
24267204SobrienOF_getproplen(phandle_t package, char *propname)
24367204Sobrien{
24467204Sobrien	static struct {
24584972Srobert		cell_t	name;
24684972Srobert		cell_t	nargs;
24784972Srobert		cell_t	nreturns;
24884972Srobert		cell_t	package;
24984972Srobert		cell_t	propname;
25084972Srobert		cell_t	proplen;
25167204Sobrien	} args = {
25284972Srobert		(cell_t)"getproplen",
25367204Sobrien		2,
25467204Sobrien		1,
25584972Srobert		0,
25684972Srobert		0,
25784972Srobert		0
25867204Sobrien	};
25967204Sobrien
26084972Srobert	args.package = (u_int)package;
26184972Srobert	args.propname = (cell_t)propname;
26267204Sobrien	if (openfirmware(&args) == -1)
26367204Sobrien		return -1;
26484972Srobert	return (int)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 {
27284972Srobert		cell_t		name;
27384972Srobert		cell_t		nargs;
27484972Srobert		cell_t		nreturns;
27584972Srobert		cell_t		package;
27684972Srobert		cell_t		propname;
27784972Srobert		cell_t		buf;
27884972Srobert		cell_t		buflen;
27984972Srobert		cell_t		size;
28067204Sobrien	} args = {
28184972Srobert		(cell_t)"getprop",
28267204Sobrien		4,
28367204Sobrien		1,
28484972Srobert		0,
28584972Srobert		0,
28684972Srobert		0,
28784972Srobert		0,
28884972Srobert		0
28967204Sobrien	};
29067204Sobrien
29184972Srobert	args.package = (u_int)package;
29284972Srobert	args.propname = (cell_t)propname;
29384972Srobert	args.buf = (cell_t)buf;
29484972Srobert	args.buflen = (u_int)buflen;
29567204Sobrien	if (openfirmware(&args) == -1)
29667204Sobrien		return -1;
29784972Srobert	return (int)args.size;
29867204Sobrien}
29967204Sobrien
30067204Sobrien/* Get the next property of a package. */
30167204Sobrienint
30267204SobrienOF_nextprop(phandle_t package, char *previous, char *buf)
30367204Sobrien{
30467204Sobrien	static struct {
30584972Srobert		cell_t		name;
30684972Srobert		cell_t		nargs;
30784972Srobert		cell_t		nreturns;
30884972Srobert		cell_t		package;
30984972Srobert		cell_t		previous;
31084972Srobert		cell_t		buf;
31184972Srobert		cell_t		flag;
31267204Sobrien	} args = {
31384972Srobert		(cell_t)"nextprop",
31467204Sobrien		3,
31567204Sobrien		1,
31684972Srobert		0,
31784972Srobert		0,
31884972Srobert		0,
31984972Srobert		0
32067204Sobrien	};
32167204Sobrien
32284972Srobert	args.package = (u_int)package;
32384972Srobert	args.previous = (cell_t)previous;
32484972Srobert	args.buf = (cell_t)buf;
32567204Sobrien	if (openfirmware(&args) == -1)
32667204Sobrien		return -1;
32784972Srobert	return (int)args.flag;
32867204Sobrien}
32967204Sobrien
33067204Sobrien/* Set the value of a property of a package. */
33167204Sobrien/* XXX Has a bug on FirePower */
33267204Sobrienint
33367204SobrienOF_setprop(phandle_t package, char *propname, void *buf, int len)
33467204Sobrien{
33567204Sobrien	static struct {
33684972Srobert		cell_t		name;
33784972Srobert		cell_t		nargs;
33884972Srobert		cell_t		nreturns;
33984972Srobert		cell_t		package;
34084972Srobert		cell_t		propname;
34184972Srobert		cell_t		buf;
34284972Srobert		cell_t		len;
34384972Srobert		cell_t		size;
34467204Sobrien	} args = {
34584972Srobert		(cell_t)"setprop",
34667204Sobrien		4,
34767204Sobrien		1,
34884972Srobert		0,
34984972Srobert		0,
35084972Srobert		0,
35184972Srobert		0,
35284972Srobert		0
35367204Sobrien	};
35467204Sobrien
35584972Srobert	args.package = (u_int)package;
35684972Srobert	args.propname = (cell_t)propname;
35784972Srobert	args.buf = (cell_t)buf;
35884972Srobert	args.len = (u_int)len;
35967204Sobrien	if (openfirmware(&args) == -1)
36067204Sobrien		return -1;
36184972Srobert	return (int)args.size;
36267204Sobrien}
36367204Sobrien
36467204Sobrien/* Convert a device specifier to a fully qualified pathname. */
36567204Sobrienint
36668548SbennoOF_canon(const char *device, char *buf, int len)
36767204Sobrien{
36867204Sobrien	static struct {
36984972Srobert		cell_t	name;
37084972Srobert		cell_t	nargs;
37184972Srobert		cell_t	nreturns;
37284972Srobert		cell_t	device;
37384972Srobert		cell_t	buf;
37484972Srobert		cell_t	len;
37584972Srobert		cell_t	size;
37667204Sobrien	} args = {
37784972Srobert		(cell_t)"canon",
37867204Sobrien		3,
37967204Sobrien		1,
38084972Srobert		0,
38184972Srobert		0,
38284972Srobert		0,
38384972Srobert		0
38467204Sobrien	};
38567204Sobrien
38684972Srobert	args.device = (cell_t)device;
38784972Srobert	args.buf = (cell_t)buf;
38884972Srobert	args.len = (cell_t)len;
38967204Sobrien	if (openfirmware(&args) == -1)
39067204Sobrien		return -1;
39184972Srobert	return (int)args.size;
39267204Sobrien}
39367204Sobrien
39467204Sobrien/* Return a package handle for the specified device. */
39567204Sobrienphandle_t
39668548SbennoOF_finddevice(const char *device)
39767204Sobrien{
39884972Srobert	int i;
39967204Sobrien	static struct {
40084972Srobert		cell_t		name;
40184972Srobert		cell_t		nargs;
40284972Srobert		cell_t		nreturns;
40384972Srobert		cell_t		device;
40484972Srobert		cell_t		package;
40567204Sobrien	} args = {
40684972Srobert		(cell_t)"finddevice",
40767204Sobrien		1,
40867204Sobrien		1,
40984972Srobert		0,
41084972Srobert		0
41167204Sobrien	};
41267204Sobrien
41384972Srobert	args.device = (cell_t)device;
41467204Sobrien	if (openfirmware(&args) == -1)
41567204Sobrien		return -1;
41684972Srobert
41784972Srobert	return (phandle_t)args.package;
41867204Sobrien}
41967204Sobrien
42067204Sobrien/* Return the fully qualified pathname corresponding to an instance. */
42167204Sobrienint
42267204SobrienOF_instance_to_path(ihandle_t instance, char *buf, int len)
42367204Sobrien{
42467204Sobrien	static struct {
42584972Srobert		cell_t		name;
42684972Srobert		cell_t		nargs;
42784972Srobert		cell_t		nreturns;
42884972Srobert		cell_t		instance;
42984972Srobert		cell_t		buf;
43084972Srobert		cell_t		len;
43184972Srobert		cell_t		size;
43267204Sobrien	} args = {
43384972Srobert		(cell_t)"instance-to-path",
43467204Sobrien		3,
43567204Sobrien		1,
43684972Srobert		0,
43784972Srobert		0,
43884972Srobert		0,
43984972Srobert		0
44067204Sobrien	};
44167204Sobrien
44284972Srobert	args.instance = (u_int)instance;
44384972Srobert	args.buf = (cell_t)buf;
44484972Srobert	args.len = (u_int)len;
44567204Sobrien	if (openfirmware(&args) == -1)
44667204Sobrien		return -1;
44784972Srobert	return (int)args.size;
44867204Sobrien}
44967204Sobrien
45067204Sobrien/* Return the fully qualified pathname corresponding to a package. */
45167204Sobrienint
45267204SobrienOF_package_to_path(phandle_t package, char *buf, int len)
45367204Sobrien{
45467204Sobrien	static struct {
45584972Srobert		cell_t		name;
45684972Srobert		cell_t		nargs;
45784972Srobert		cell_t		nreturns;
45884972Srobert		cell_t		package;
45984972Srobert		cell_t		buf;
46084972Srobert		cell_t		len;
46184972Srobert		cell_t		size;
46267204Sobrien	} args = {
46384972Srobert		(cell_t)"package-to-path",
46467204Sobrien		3,
46567204Sobrien		1,
46684972Srobert		0,
46784972Srobert		0,
46884972Srobert		0,
46984972Srobert		0
47067204Sobrien	};
47167204Sobrien
47284972Srobert	args.package = (u_int)package;
47384972Srobert	args.buf = (cell_t)buf;
47484972Srobert	args.len = (u_int)len;
47567204Sobrien	if (openfirmware(&args) == -1)
47667204Sobrien		return -1;
47784972Srobert	return (int)args.size;
47867204Sobrien}
47967204Sobrien
48067204Sobrien/*  Call the method in the scope of a given instance. */
48167204Sobrienint
48267204SobrienOF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
48367204Sobrien{
48467204Sobrien	va_list ap;
48567204Sobrien	static struct {
48684972Srobert		cell_t		name;
48784972Srobert		cell_t		nargs;
48884972Srobert		cell_t		nreturns;
48984972Srobert		cell_t		method;
49084972Srobert		cell_t		instance;
49184972Srobert		cell_t		args_n_results[12];
49267204Sobrien	} args = {
49384972Srobert		(cell_t)"call-method",
49467204Sobrien		2,
49567204Sobrien		1,
49684972Srobert		0,
49784972Srobert		0,
49884972Srobert		{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
49967204Sobrien	};
50067204Sobrien	int *ip, n;
50167204Sobrien
50267204Sobrien	if (nargs > 6)
50367204Sobrien		return -1;
50467204Sobrien	args.nargs = nargs + 2;
50567204Sobrien	args.nreturns = nreturns + 1;
50684972Srobert	args.method = (cell_t)method;
50784972Srobert	args.instance = (u_int)instance;
50867204Sobrien	va_start(ap, nreturns);
50984972Srobert	for (ip = (int *)(args.args_n_results + (n = nargs)); --n >= 0;)
51067204Sobrien		*--ip = va_arg(ap, int);
51167204Sobrien
51267204Sobrien	if (openfirmware(&args) == -1)
51367204Sobrien		return -1;
51467204Sobrien	if (args.args_n_results[nargs])
51584972Srobert		return (int)args.args_n_results[nargs];
51684972Srobert	for (ip = (int *)(args.args_n_results + nargs + (n = args.nreturns));
51784972Srobert	    --n > 0;)
51867204Sobrien		*va_arg(ap, int *) = *--ip;
51967204Sobrien	va_end(ap);
52067204Sobrien	return 0;
52167204Sobrien}
52267204Sobrien
52367204Sobrien/*
52467204Sobrien * Device I/O functions.
52567204Sobrien */
52667204Sobrien
52767204Sobrien/* Open an instance for a device. */
52867204Sobrienihandle_t
52967204SobrienOF_open(char *device)
53067204Sobrien{
53167204Sobrien	static struct {
53284972Srobert		cell_t		name;
53384972Srobert		cell_t		nargs;
53484972Srobert		cell_t		nreturns;
53584972Srobert		cell_t		device;
53684972Srobert		cell_t		instance;
53767204Sobrien	} args = {
53884972Srobert		(cell_t)"open",
53967204Sobrien		1,
54067204Sobrien		1,
54184972Srobert		0,
54284972Srobert		0
54367204Sobrien	};
54467204Sobrien
54584972Srobert	args.device = (cell_t)device;
54667204Sobrien	if (openfirmware(&args) == -1 || args.instance == 0) {
54767204Sobrien		return -1;
54867204Sobrien	}
54984972Srobert	return (ihandle_t)args.instance;
55067204Sobrien}
55167204Sobrien
55267204Sobrien/* Close an instance. */
55367204Sobrienvoid
55467204SobrienOF_close(ihandle_t instance)
55567204Sobrien{
55667204Sobrien	static struct {
55784972Srobert		cell_t		name;
55884972Srobert		cell_t		nargs;
55984972Srobert		cell_t		nreturns;
56084972Srobert		cell_t		instance;
56167204Sobrien	} args = {
56284972Srobert		(cell_t)"close",
56367204Sobrien		1,
56467204Sobrien		0,
56584972Srobert		0
56667204Sobrien	};
56767204Sobrien
56884972Srobert	args.instance = (u_int)instance;
56967204Sobrien	openfirmware(&args);
57067204Sobrien}
57167204Sobrien
57267204Sobrien/* Read from an instance. */
57367204Sobrienint
57467204SobrienOF_read(ihandle_t instance, void *addr, int len)
57567204Sobrien{
57667204Sobrien	static struct {
57784972Srobert		cell_t		name;
57884972Srobert		cell_t		nargs;
57984972Srobert		cell_t		nreturns;
58084972Srobert		cell_t		instance;
58184972Srobert		cell_t		addr;
58284972Srobert		cell_t		len;
58384972Srobert		cell_t		actual;
58467204Sobrien	} args = {
58584972Srobert		(cell_t)"read",
58667204Sobrien		3,
58767204Sobrien		1,
58884972Srobert		0,
58984972Srobert		0,
59084972Srobert		0,
59184972Srobert		0
59267204Sobrien	};
59367204Sobrien
59484972Srobert	args.instance = (u_int)instance;
59584972Srobert	args.addr = (cell_t)addr;
59684972Srobert	args.len = (u_int)len;
59768548Sbenno
59868548Sbenno#if defined(OPENFIRM_DEBUG)
59968548Sbenno	printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
60068548Sbenno	    args.instance, args.addr, args.len);
60168548Sbenno#endif
60268548Sbenno
60367204Sobrien	if (openfirmware(&args) == -1)
60467204Sobrien		return -1;
60568548Sbenno
60668548Sbenno#if defined(OPENFIRM_DEBUG)
60768548Sbenno	printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
60868548Sbenno	    args.instance, args.addr, args.len, args.actual);
60968548Sbenno#endif
61068548Sbenno
61184972Srobert	return (int)args.actual;
61267204Sobrien}
61367204Sobrien
61467204Sobrien/* Write to an instance. */
61567204Sobrienint
61667204SobrienOF_write(ihandle_t instance, void *addr, int len)
61767204Sobrien{
61867204Sobrien	static struct {
61984972Srobert		cell_t		name;
62084972Srobert		cell_t		nargs;
62184972Srobert		cell_t		nreturns;
62284972Srobert		cell_t		instance;
62384972Srobert		cell_t		addr;
62484972Srobert		cell_t		len;
62584972Srobert		cell_t		actual;
62667204Sobrien	} args = {
62784972Srobert		(cell_t)"write",
62867204Sobrien		3,
62967204Sobrien		1,
63084972Srobert		0,
63184972Srobert		0,
63284972Srobert		0,
63384972Srobert		0
63467204Sobrien	};
63567204Sobrien
63684972Srobert	args.instance = (u_int)instance;
63784972Srobert	args.addr = (cell_t)addr;
63884972Srobert	args.len = (u_int)len;
63967204Sobrien	if (openfirmware(&args) == -1)
64067204Sobrien		return -1;
64184972Srobert	return (int)args.actual;
64267204Sobrien}
64367204Sobrien
64467204Sobrien/* Seek to a position. */
64567204Sobrienint
64668548SbennoOF_seek(ihandle_t instance, u_int64_t pos)
64767204Sobrien{
64867204Sobrien	static struct {
64984972Srobert		cell_t		name;
65084972Srobert		cell_t		nargs;
65184972Srobert		cell_t		nreturns;
65284972Srobert		cell_t		instance;
65384972Srobert		cell_t		poshi;
65484972Srobert		cell_t		poslo;
65584972Srobert		cell_t		status;
65667204Sobrien	} args = {
65784972Srobert		(cell_t)"seek",
65867204Sobrien		3,
65967204Sobrien		1,
66084972Srobert		0,
66184972Srobert		0,
66284972Srobert		0,
66384972Srobert		0
66467204Sobrien	};
66567204Sobrien
66684972Srobert	args.instance = (u_int)instance;
66784972Srobert	args.poshi = pos >> 32;
66884972Srobert	args.poslo = pos;
66967204Sobrien	if (openfirmware(&args) == -1)
67067204Sobrien		return -1;
67184972Srobert	return (int)args.status;
67267204Sobrien}
67367204Sobrien
67467204Sobrien/*
67567204Sobrien * Memory functions.
67667204Sobrien */
67767204Sobrien
67867204Sobrien/* Claim an area of memory. */
67967204Sobrienvoid *
68067204SobrienOF_claim(void *virt, u_int size, u_int align)
68167204Sobrien{
68267204Sobrien	static struct {
68384972Srobert		cell_t	name;
68484972Srobert		cell_t	nargs;
68584972Srobert		cell_t	nreturns;
68684972Srobert		cell_t	virt;
68784972Srobert		cell_t	size;
68884972Srobert		cell_t	align;
68984972Srobert		cell_t	baseaddr;
69067204Sobrien	} args = {
69184972Srobert		(cell_t)"claim",
69267204Sobrien		3,
69367204Sobrien		1,
69484972Srobert		0,
69584972Srobert		0,
69684972Srobert		0,
69784972Srobert		0
69867204Sobrien	};
69967204Sobrien
70084972Srobert	args.virt = (cell_t)virt;
70167204Sobrien	args.size = size;
70267204Sobrien	args.align = align;
70367204Sobrien	if (openfirmware(&args) == -1)
70467204Sobrien		return (void *)-1;
70584972Srobert	return (void *)args.baseaddr;
70667204Sobrien}
70767204Sobrien
70884972Srobert/* Allocate an area of physical memory */
70991108Sjakevm_offset_t
71091108SjakeOF_claim_virt(vm_offset_t virt, size_t size, int align)
71191108Sjake{
71291108Sjake	static struct {
71391108Sjake		cell_t	name;
71491108Sjake		cell_t	nargs;
71591108Sjake		cell_t	nret;
71691108Sjake		cell_t	method;
71791108Sjake		cell_t	ihandle;
71891108Sjake		cell_t	align;
71991108Sjake		cell_t	size;
72091108Sjake		cell_t	virt;
72191108Sjake		cell_t	status;
72291108Sjake		cell_t	ret;
72391108Sjake	} args = {
72491108Sjake		(cell_t)"call-method",
72591108Sjake		5,
72691108Sjake		2,
72791108Sjake		(cell_t)"claim",
72891108Sjake		0,
72991108Sjake		0,
73091108Sjake		0,
73191108Sjake		0,
73291108Sjake		0,	/* ret */
73391108Sjake		0,
73491108Sjake	};
73591108Sjake
73691108Sjake	args.ihandle = mmu;
73791108Sjake	args.align = align;
73891108Sjake	args.size = size;
73991108Sjake	args.virt = virt;
74091108Sjake
74191108Sjake	if (openfirmware(&args) == -1)
74291108Sjake		return (vm_offset_t)-1;
74391108Sjake
74491108Sjake	return (vm_offset_t)args.ret;
74591108Sjake}
74691108Sjake
74791108Sjake/* Allocate an area of physical memory */
74884972Srobertvoid *
74984972SrobertOF_alloc_phys(size_t size, int align)
75084972Srobert{
75184972Srobert	static struct {
75284972Srobert		cell_t	name;
75384972Srobert		cell_t	nargs;
75484972Srobert		cell_t	nret;
75584972Srobert		cell_t	method;
75684972Srobert		cell_t	ihandle;
75784972Srobert		cell_t	align;
75884972Srobert		cell_t	size;
75984972Srobert		cell_t	status;
76084972Srobert		cell_t	phys_hi;
76184972Srobert		cell_t	phys_low;
76284972Srobert	} args = {
76384972Srobert		(cell_t)"call-method",
76484972Srobert		4,
76584972Srobert		3,
76684972Srobert		(cell_t)"claim",
76784972Srobert		0,
76884972Srobert		0,
76984972Srobert		0,
77084972Srobert		0,	/* ret */
77184972Srobert		0,
77284972Srobert		0,
77384972Srobert	};
77484972Srobert
77584972Srobert	args.ihandle = memory;
77684972Srobert	args.size = size;
77784972Srobert	args.align = align;
77884972Srobert
77984972Srobert	if (openfirmware(&args) == -1)
78084972Srobert		return (void *)-1;
78184972Srobert
78284972Srobert	return (void *)(args.phys_hi << 32 | args.phys_low);
78384972Srobert}
78484972Srobert
78567204Sobrien/* Release an area of memory. */
78667204Sobrienvoid
78767204SobrienOF_release(void *virt, u_int size)
78867204Sobrien{
78967204Sobrien	static struct {
79084972Srobert		cell_t	name;
79184972Srobert		cell_t	nargs;
79284972Srobert		cell_t	nreturns;
79384972Srobert		cell_t	virt;
79484972Srobert		cell_t	size;
79567204Sobrien	} args = {
79684972Srobert		(cell_t)"release",
79767204Sobrien		2,
79867204Sobrien		0,
79984972Srobert		0,
80084972Srobert		0
80167204Sobrien	};
80267204Sobrien
80384972Srobert	args.virt = (cell_t)virt;
80467204Sobrien	args.size = size;
80567204Sobrien	openfirmware(&args);
80667204Sobrien}
80767204Sobrien
80891108Sjake/* Release an area of physical memory. */
80991108Sjakevoid
81091108SjakeOF_release_phys(vm_offset_t phys, u_int size)
81191108Sjake{
81291108Sjake	static struct {
81391108Sjake		cell_t	name;
81491108Sjake		cell_t	nargs;
81591108Sjake		cell_t	nret;
81691108Sjake		cell_t	method;
81791108Sjake		cell_t	ihandle;
81891108Sjake		cell_t	size;
81991108Sjake		cell_t	phys_hi;
82091108Sjake		cell_t	phys_lo;
82191108Sjake	} args = {
82291108Sjake		(cell_t)"call-method",
82391108Sjake		5,
82491108Sjake		0,
82591108Sjake		(cell_t)"release",
82691108Sjake		0,
82791108Sjake		0,
82891108Sjake		0,
82991108Sjake		0
83091108Sjake	};
83191108Sjake
83291108Sjake	args.ihandle = memory;
83391108Sjake	args.phys_hi = (u_int32_t)(phys >> 32);
83491108Sjake	args.phys_lo = (u_int32_t)phys;
83591108Sjake	args.size = size;
83691108Sjake	openfirmware(&args);
83791108Sjake}
83891108Sjake
83967204Sobrien/*
84067204Sobrien * Control transfer functions.
84167204Sobrien */
84267204Sobrien
84367204Sobrien/* Reset the system and call "boot <bootspec>". */
84467204Sobrienvoid
84567204SobrienOF_boot(char *bootspec)
84667204Sobrien{
84767204Sobrien	static struct {
84884972Srobert		cell_t	name;
84984972Srobert		cell_t	nargs;
85084972Srobert		cell_t	nreturns;
85184972Srobert		cell_t	bootspec;
85267204Sobrien	} args = {
85384972Srobert		(cell_t)"boot",
85467204Sobrien		1,
85567204Sobrien		0,
85684972Srobert		0
85767204Sobrien	};
85867204Sobrien
85984972Srobert	args.bootspec = (cell_t)bootspec;
86067204Sobrien	openfirmware(&args);
86167204Sobrien	for (;;);			/* just in case */
86267204Sobrien}
86367204Sobrien
86467204Sobrien/* Suspend and drop back to the OpenFirmware interface. */
86567204Sobrienvoid
86667204SobrienOF_enter()
86767204Sobrien{
86867204Sobrien	static struct {
86984972Srobert		cell_t	name;
87084972Srobert		cell_t	nargs;
87184972Srobert		cell_t	nreturns;
87267204Sobrien	} args = {
87384972Srobert		(cell_t)"enter",
87467204Sobrien		0,
87567204Sobrien		0
87667204Sobrien	};
87767204Sobrien
87867204Sobrien	openfirmware(&args);
87967204Sobrien}
88067204Sobrien
88167204Sobrien/* Shut down and drop back to the OpenFirmware interface. */
88268548Sbennovoid
88367204SobrienOF_exit()
88467204Sobrien{
88567204Sobrien	static struct {
88684972Srobert		cell_t	name;
88784972Srobert		cell_t	nargs;
88884972Srobert		cell_t	nreturns;
88967204Sobrien	} args = {
89084972Srobert		(cell_t)"exit",
89167204Sobrien		0,
89267204Sobrien		0
89367204Sobrien	};
89467204Sobrien
89567204Sobrien	openfirmware(&args);
89667204Sobrien	for (;;);			/* just in case */
89767204Sobrien}
89867204Sobrien
89967204Sobrien/* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
90084972Srobert#ifdef	__notyet__
90167204Sobrienvoid
90267204SobrienOF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
90367204Sobrien{
90467204Sobrien	static struct {
90584972Srobert		cell_t	name;
90684972Srobert		cell_t	nargs;
90784972Srobert		cell_t	nreturns;
90884972Srobert		cell_t	virt;
90984972Srobert		cell_t	size;
91084972Srobert		cell_t	entry;
91184972Srobert		cell_t	arg;
91284972Srobert		cell_t	len;
91367204Sobrien	} args = {
91484972Srobert		(cell_t)"chain",
91567204Sobrien		5,
91667204Sobrien		0,
91784972Srobert		0,
91884972Srobert		0,
91984972Srobert		0,
92084972Srobert		0,
92184972Srobert		0
92267204Sobrien	};
92367204Sobrien
92484972Srobert	args.virt = (cell_t)virt;
92567204Sobrien	args.size = size;
92684972Srobert	args.entry = (cell_t)entry;
92784972Srobert	args.arg = (cell_t)arg;
92867204Sobrien	args.len = len;
92967204Sobrien	openfirmware(&args);
93067204Sobrien}
93167204Sobrien#else
93267204Sobrienvoid
93367204SobrienOF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
93467204Sobrien{
93567204Sobrien	/*
93667204Sobrien	 * This is a REALLY dirty hack till the firmware gets this going
93767204Sobrien	 */
93884617Sbenno	if (size > 0)
93984617Sbenno		OF_release(virt, size);
94084617Sbenno
94167204Sobrien	entry(0, 0, openfirmware, arg, len);
94267204Sobrien}
94367204Sobrien#endif
944