1195098Sed/*	$NetBSD: Locore.c,v 1.17 2022/05/14 07:11:23 hgutch Exp $	*/
2195098Sed
3195098Sed/*
4195098Sed * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5195098Sed * Copyright (C) 1995, 1996 TooLs GmbH.
6195098Sed * All rights reserved.
7195098Sed *
8195098Sed * Redistribution and use in source and binary forms, with or without
9195098Sed * modification, are permitted provided that the following conditions
10195098Sed * are met:
11198090Srdivacky * 1. Redistributions of source code must retain the above copyright
12198090Srdivacky *    notice, this list of conditions and the following disclaimer.
13195098Sed * 2. Redistributions in binary form must reproduce the above copyright
14198090Srdivacky *    notice, this list of conditions and the following disclaimer in the
15195340Sed *    documentation and/or other materials provided with the distribution.
16198090Srdivacky * 3. All advertising materials mentioning features or use of this software
17198090Srdivacky *    must display the following acknowledgement:
18195098Sed *	This product includes software developed by TooLs GmbH.
19205407Srdivacky * 4. The name of TooLs GmbH may not be used to endorse or promote products
20202878Srdivacky *    derived from this software without specific prior written permission.
21202878Srdivacky *
22198090Srdivacky * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23198090Srdivacky * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24198090Srdivacky * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25202878Srdivacky * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26195098Sed * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27195098Sed * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28195098Sed * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29195098Sed * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30198090Srdivacky * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31202878Srdivacky * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32198090Srdivacky */
33205407Srdivacky
34198090Srdivacky#include <lib/libsa/stand.h>
35202878Srdivacky#include "openfirm.h"
36202878Srdivacky
37202878Srdivacky#include <machine/cpu.h>
38203954Srdivacky#include <machine/vmparam.h>
39203954Srdivacky
40203954Srdivacky/*
41203954Srdivacky * We are trying to boot a sparc v9 cpu, so openfirmware has to be 64bit,
42203954Srdivacky * and the kernel we load will be dealing with 64bits too (even if it is
43198090Srdivacky * a 32bit kernel.
44202878Srdivacky * Make sure we picked up the right defines:
45202878Srdivacky */
46203954Srdivacky__CTASSERT(sizeof(cell_t)==8);
47205218Srdivacky__CTASSERT(sizeof(paddr_t)==8);
48205218Srdivacky
49203954Srdivackyextern int openfirmware(void *);
50203954Srdivacky
51203954Srdivacky
52203954Srdivacky__dead void
53203954Srdivacky_rtt(void)
54198090Srdivacky{
55195098Sed
56202878Srdivacky	OF_exit();
57203954Srdivacky}
58202878Srdivacky
59202878Srdivackyvoid __attribute__((__noreturn__))
60202878SrdivackyOF_exit(void)
61202878Srdivacky{
62202878Srdivacky	struct {
63202878Srdivacky		cell_t name;
64202878Srdivacky		cell_t nargs;
65202878Srdivacky		cell_t nreturns;
66202878Srdivacky	} args;
67203954Srdivacky
68203954Srdivacky	args.name = ADR2CELL("exit");
69203954Srdivacky	args.nargs = 0;
70203954Srdivacky	args.nreturns = 0;
71206274Srdivacky	openfirmware(&args);
72206274Srdivacky
73206274Srdivacky	printf("OF_exit failed");
74203954Srdivacky	for (;;)
75202878Srdivacky		continue;
76202878Srdivacky}
77202878Srdivacky
78202878Srdivackyvoid
79202878SrdivackyOF_enter(void)
80203954Srdivacky{
81203954Srdivacky	struct {
82203954Srdivacky		cell_t name;
83203954Srdivacky		cell_t nargs;
84202878Srdivacky		cell_t nreturns;
85202878Srdivacky	} args;
86202878Srdivacky
87202878Srdivacky	args.name = ADR2CELL("enter");
88202878Srdivacky	args.nargs = 0;
89202878Srdivacky	args.nreturns = 0;
90202878Srdivacky	openfirmware(&args);
91202878Srdivacky}
92203954Srdivacky
93202878Srdivackyint
94202878SrdivackyOF_finddevice(const char *name)
95202878Srdivacky{
96202878Srdivacky	struct {
97203954Srdivacky		cell_t name;
98198090Srdivacky		cell_t nargs;
99198090Srdivacky		cell_t nreturns;
100195098Sed		cell_t device;
101198090Srdivacky		cell_t phandle;
102195098Sed	} args;
103198090Srdivacky
104195098Sed	args.name = ADR2CELL("finddevice");
105202878Srdivacky	args.nargs = 1;
106195098Sed	args.nreturns = 1;
107198090Srdivacky	args.device = ADR2CELL(name);
108195098Sed	if (openfirmware(&args) == -1)
109202878Srdivacky		return -1;
110195098Sed	return args.phandle;
111198090Srdivacky}
112208599Srdivacky
113208599Srdivackyint
114208599SrdivackyOF_instance_to_package(int ihandle)
115208599Srdivacky{
116203954Srdivacky	struct {
117202878Srdivacky		cell_t name;
118198090Srdivacky		cell_t nargs;
119195098Sed		cell_t nreturns;
120202878Srdivacky		cell_t ihandle;
121202878Srdivacky		cell_t phandle;
122202878Srdivacky	} args;
123202878Srdivacky
124202878Srdivacky	args.name = ADR2CELL("instance-to-package");
125202878Srdivacky	args.nargs = 1;
126198090Srdivacky	args.nreturns = 1;
127198090Srdivacky	args.ihandle = HDL2CELL(ihandle);
128195098Sed	if (openfirmware(&args) == -1)
129208599Srdivacky		return -1;
130208599Srdivacky	return args.phandle;
131208599Srdivacky}
132202878Srdivacky
133195098Sedint
134202878SrdivackyOF_instance_to_path(int ihandle, char *buf, int buflen)
135202878Srdivacky{
136203954Srdivacky	struct {
137203954Srdivacky		cell_t name;
138195098Sed		cell_t nargs;
139202878Srdivacky		cell_t nreturns;
140202878Srdivacky		cell_t ihandle;
141202878Srdivacky		cell_t buf;
142198090Srdivacky		cell_t buflen;
143198090Srdivacky		cell_t length;
144198090Srdivacky	} args;
145195098Sed
146204642Srdivacky	args.name = ADR2CELL("instance-to-path");
147204642Srdivacky	args.nargs = 3;
148204642Srdivacky	args.nreturns = 1;
149198090Srdivacky	args.ihandle = HDL2CELL(ihandle);
150198090Srdivacky	args.buf = ADR2CELL(buf);
151203954Srdivacky	args.buflen = buflen;
152203954Srdivacky	if (openfirmware(&args) < 0)
153203954Srdivacky		return -1;
154203954Srdivacky	return args.length;
155203954Srdivacky}
156198090Srdivacky
157206274Srdivackyint
158206274SrdivackyOF_parent(int phandle)
159206274Srdivacky{
160206274Srdivacky	struct {
161206274Srdivacky		cell_t name;
162198090Srdivacky		cell_t nargs;
163198090Srdivacky		cell_t nreturns;
164198090Srdivacky		cell_t phandle;
165198090Srdivacky		cell_t parent;
166195098Sed	} args;
167198090Srdivacky
168195098Sed	args.name = ADR2CELL("parent");
169202878Srdivacky	args.nargs = 1;
170202878Srdivacky	args.nreturns = 1;
171202878Srdivacky	args.phandle = HDL2CELL(phandle);
172202878Srdivacky	if (openfirmware(&args) == -1)
173202878Srdivacky		return 0;
174202878Srdivacky	return args.parent;
175202878Srdivacky}
176202878Srdivacky
177202878Srdivackyint
178202878SrdivackyOF_getprop(int handle, const char *prop, void *buf, int buflen)
179202878Srdivacky{
180202878Srdivacky	struct {
181202878Srdivacky		cell_t name;
182202878Srdivacky		cell_t nargs;
183202878Srdivacky		cell_t nreturns;
184202878Srdivacky		cell_t phandle;
185202878Srdivacky		cell_t prop;
186202878Srdivacky		cell_t buf;
187202878Srdivacky		cell_t buflen;
188202878Srdivacky		cell_t size;
189202878Srdivacky	} args;
190202878Srdivacky
191202878Srdivacky	args.name = ADR2CELL("getprop");
192202878Srdivacky	args.nargs = 4;
193202878Srdivacky	args.nreturns = 1;
194202878Srdivacky	args.phandle = HDL2CELL(handle);
195202878Srdivacky	args.prop = ADR2CELL(prop);
196202878Srdivacky	args.buf = ADR2CELL(buf);
197202878Srdivacky	args.buflen = buflen;
198202878Srdivacky	if (openfirmware(&args) == -1)
199202878Srdivacky		return -1;
200202878Srdivacky	return args.size;
201202878Srdivacky}
202202878Srdivacky
203202878Srdivacky#ifdef	__notyet__	/* Has a bug on FirePower */
204202878Srdivackyint
205202878SrdivackyOF_setprop(u_int handle, char *prop, void *buf, int len)
206202878Srdivacky{
207202878Srdivacky	struct {
208202878Srdivacky		cell_t name;
209202878Srdivacky		cell_t nargs;
210202878Srdivacky		cell_t nreturns;
211202878Srdivacky		cell_t phandle;
212195098Sed		cell_t prop;
213195098Sed		cell_t buf;
214195098Sed		cell_t len;
215195098Sed		cell_t size;
216195098Sed	} args;
217198090Srdivacky
218198090Srdivacky	args.name = ADR2CELL("setprop");
219195098Sed	args.nargs = 4;
220195098Sed	args.nreturns = 1;
221198090Srdivacky	args.phandle = HDL2CELL(handle);
222195098Sed	args.prop = ADR2CELL(prop);
223195098Sed	args.buf = ADR2CELL(buf);
224195098Sed	args.len = len;
225195098Sed	if (openfirmware(&args) == -1)
226198090Srdivacky		return -1;
227208599Srdivacky	return args.size;
228195098Sed}
229195098Sed#endif
230202878Srdivacky
231202878Srdivackyint
232198090SrdivackyOF_interpret(const char *cmd, int nargs, int nreturns, ...)
233195098Sed{
234195098Sed	va_list ap;
235202878Srdivacky	struct {
236198090Srdivacky		cell_t name;
237198090Srdivacky		cell_t nargs;
238202878Srdivacky		cell_t nreturns;
239195098Sed		cell_t slot[16];
240202878Srdivacky	} args;
241198090Srdivacky	cell_t status;
242195098Sed	int i = 0;
243198090Srdivacky
244202878Srdivacky	args.name = ADR2CELL("interpret");
245202878Srdivacky	args.nargs = ++nargs;
246198396Srdivacky	args.nreturns = ++nreturns;
247198396Srdivacky	args.slot[i++] = ADR2CELL(cmd);
248208599Srdivacky	va_start(ap, nreturns);
249195098Sed	while (i < nargs) {
250195098Sed		args.slot[i++] = va_arg(ap, cell_t);
251198396Srdivacky	}
252202878Srdivacky	if (openfirmware(&args) == -1) {
253195098Sed		va_end(ap);
254202878Srdivacky		return (-1);
255203954Srdivacky	}
256203954Srdivacky	status = args.slot[i++];
257203954Srdivacky	while (i < nargs+nreturns) {
258203954Srdivacky		*va_arg(ap, cell_t *) = args.slot[i++];
259203954Srdivacky	}
260203954Srdivacky	va_end(ap);
261203954Srdivacky
262203954Srdivacky	return status;
263203954Srdivacky}
264203954Srdivacky
265203954Srdivackyint
266203954SrdivackyOF_package_to_path(int phandle, char *buf, int buflen)
267203954Srdivacky{
268203954Srdivacky	struct {
269203954Srdivacky		cell_t name;
270203954Srdivacky		cell_t nargs;
271203954Srdivacky		cell_t nreturns;
272203954Srdivacky		cell_t phandle;
273203954Srdivacky		cell_t buf;
274203954Srdivacky		cell_t buflen;
275203954Srdivacky		cell_t length;
276203954Srdivacky	} args;
277203954Srdivacky
278202878Srdivacky	if (buflen > PAGE_SIZE)
279202878Srdivacky		return -1;
280202878Srdivacky	args.name = ADR2CELL("package-to-path");
281202878Srdivacky	args.nargs = 3;
282202878Srdivacky	args.nreturns = 1;
283202878Srdivacky	args.phandle = HDL2CELL(phandle);
284202878Srdivacky	args.buf = ADR2CELL(buf);
285202878Srdivacky	args.buflen = buflen;
286202878Srdivacky	if (openfirmware(&args) < 0)
287202878Srdivacky		return -1;
288202878Srdivacky	return args.length;
289202878Srdivacky}
290202878Srdivacky
291195098Sedint
292195098SedOF_open(const char *dname)
293202878Srdivacky{
294202878Srdivacky	struct {
295195098Sed		cell_t name;
296195098Sed		cell_t nargs;
297198090Srdivacky		cell_t nreturns;
298202878Srdivacky		cell_t dname;
299202878Srdivacky		cell_t handle;
300198090Srdivacky	} args;
301198090Srdivacky
302208599Srdivacky	args.name = ADR2CELL("open");
303208599Srdivacky	args.nargs = 1;
304208599Srdivacky	args.nreturns = 1;
305208599Srdivacky	args.dname = ADR2CELL(dname);
306208599Srdivacky	if (openfirmware(&args) == -1 ||
307208599Srdivacky	    args.handle == 0)
308208599Srdivacky		return -1;
309208599Srdivacky	return args.handle;
310208599Srdivacky}
311208599Srdivacky
312208599Srdivackyvoid
313208599SrdivackyOF_close(int handle)
314208599Srdivacky{
315208599Srdivacky	struct {
316208599Srdivacky		cell_t name;
317208599Srdivacky		cell_t nargs;
318208599Srdivacky		cell_t nreturns;
319208599Srdivacky		cell_t handle;
320208599Srdivacky	} args;
321208599Srdivacky
322203954Srdivacky	args.name = ADR2CELL("close");
323203954Srdivacky	args.nargs = 1;
324203954Srdivacky	args.nreturns = 0;
325203954Srdivacky	args.handle = HDL2CELL(handle);
326203954Srdivacky	openfirmware(&args);
327202878Srdivacky}
328198090Srdivacky
329202878Srdivackyint
330203954SrdivackyOF_write(int handle, const void *addr, int len)
331203954Srdivacky{
332202878Srdivacky	struct {
333202878Srdivacky		cell_t name;
334202878Srdivacky		cell_t nargs;
335202878Srdivacky		cell_t nreturns;
336202878Srdivacky		cell_t ihandle;
337198090Srdivacky		cell_t addr;
338198090Srdivacky		cell_t len;
339202878Srdivacky		cell_t actual;
340202878Srdivacky	} args;
341202878Srdivacky
342202878Srdivacky	args.name = ADR2CELL("write");
343202878Srdivacky	args.nargs = 3;
344202878Srdivacky	args.nreturns = 1;
345202878Srdivacky	args.ihandle = HDL2CELL(handle);
346202878Srdivacky	args.addr = ADR2CELL(addr);
347202878Srdivacky	args.len = len;
348202878Srdivacky	if (openfirmware(&args) == -1)
349198090Srdivacky		return -1;
350198090Srdivacky	return args.actual;
351198090Srdivacky}
352198090Srdivacky
353198090Srdivackyint
354198090SrdivackyOF_read(int handle, void *addr, int len)
355198090Srdivacky{
356198090Srdivacky	struct {
357198090Srdivacky		cell_t name;
358198090Srdivacky		cell_t nargs;
359202878Srdivacky		cell_t nreturns;
360198090Srdivacky		cell_t ihandle;
361198090Srdivacky		cell_t addr;
362198090Srdivacky		cell_t len;
363202878Srdivacky		cell_t actual;
364198090Srdivacky	} args;
365198090Srdivacky
366208599Srdivacky	args.name = ADR2CELL("read");
367208599Srdivacky	args.nargs = 3;
368208599Srdivacky	args.nreturns = 1;
369208599Srdivacky	args.ihandle = HDL2CELL(handle);
370208599Srdivacky	args.addr = ADR2CELL(addr);
371208599Srdivacky	args.len = len;
372208599Srdivacky	if (openfirmware(&args) == -1) {
373208599Srdivacky		return -1;
374208599Srdivacky	}
375208599Srdivacky	return args.actual;
376208599Srdivacky}
377208599Srdivacky
378208599Srdivackyint
379208599SrdivackyOF_seek(int handle, u_quad_t pos)
380208599Srdivacky{
381208599Srdivacky	struct {
382208599Srdivacky		cell_t name;
383202878Srdivacky		cell_t nargs;
384202878Srdivacky		cell_t nreturns;
385203954Srdivacky		cell_t handle;
386203954Srdivacky		cell_t poshi;
387203954Srdivacky		cell_t poslo;
388203954Srdivacky		cell_t status;
389203954Srdivacky	} args;
390203954Srdivacky
391203954Srdivacky	args.name = ADR2CELL("seek");
392203954Srdivacky	args.nargs = 3;
393203954Srdivacky	args.nreturns = 1;
394203954Srdivacky	args.handle = HDL2CELL(handle);
395203954Srdivacky	args.poshi = HDQ2CELL_HI(pos);
396203954Srdivacky	args.poslo = HDQ2CELL_LO(pos);
397203954Srdivacky	if (openfirmware(&args) == -1) {
398203954Srdivacky		return -1;
399203954Srdivacky	}
400203954Srdivacky	return args.status;
401203954Srdivacky}
402203954Srdivacky
403203954Srdivackyvoid
404203954SrdivackyOF_release(void *virt, u_int size)
405203954Srdivacky{
406203954Srdivacky	struct {
407203954Srdivacky		cell_t name;
408203954Srdivacky		cell_t nargs;
409203954Srdivacky		cell_t nreturns;
410203954Srdivacky		cell_t virt;
411203954Srdivacky		cell_t size;
412203954Srdivacky	} args;
413203954Srdivacky
414203954Srdivacky	args.name = ADR2CELL("release");
415203954Srdivacky	args.nargs = 2;
416203954Srdivacky	args.nreturns = 0;
417203954Srdivacky	args.virt = ADR2CELL(virt);
418203954Srdivacky	args.size = size;
419202878Srdivacky	openfirmware(&args);
420195098Sed}
421202878Srdivacky
422202878Srdivackyint
423202878SrdivackyOF_milliseconds(void)
424202878Srdivacky{
425202878Srdivacky	struct {
426202878Srdivacky		cell_t name;
427202878Srdivacky		cell_t nargs;
428202878Srdivacky		cell_t nreturns;
429202878Srdivacky		cell_t ms;
430202878Srdivacky	} args;
431202878Srdivacky
432202878Srdivacky	args.name = ADR2CELL("milliseconds");
433202878Srdivacky	args.nargs = 0;
434202878Srdivacky	args.nreturns = 1;
435202878Srdivacky	openfirmware(&args);
436202878Srdivacky	return args.ms;
437202878Srdivacky}
438202878Srdivacky
439203954Srdivackyint
440203954SrdivackyOF_peer(int phandle)
441202878Srdivacky{
442195098Sed	struct {
443195098Sed		cell_t name;
444202878Srdivacky		cell_t nargs;
445202878Srdivacky		cell_t nreturns;
446202878Srdivacky		cell_t phandle;
447202878Srdivacky		cell_t sibling;
448195098Sed	} args;
449202878Srdivacky
450195098Sed	args.name = ADR2CELL("peer");
451202878Srdivacky	args.nargs = 1;
452202878Srdivacky	args.nreturns = 1;
453202878Srdivacky	args.phandle = HDL2CELL(phandle);
454202878Srdivacky	if (openfirmware(&args) == -1)
455202878Srdivacky		return 0;
456202878Srdivacky	return args.sibling;
457202878Srdivacky}
458202878Srdivacky
459202878Srdivackyint
460202878SrdivackyOF_child(int phandle)
461202878Srdivacky{
462202878Srdivacky	struct {
463202878Srdivacky		cell_t name;
464202878Srdivacky		cell_t nargs;
465202878Srdivacky		cell_t nreturns;
466202878Srdivacky		cell_t phandle;
467195098Sed		cell_t child;
468202878Srdivacky	} args;
469202878Srdivacky
470202878Srdivacky	args.name = ADR2CELL("child");
471202878Srdivacky	args.nargs = 1;
472202878Srdivacky	args.nreturns = 1;
473195098Sed	args.phandle = HDL2CELL(phandle);
474202878Srdivacky	if (openfirmware(&args) == -1)
475202878Srdivacky		return 0;
476202878Srdivacky	return args.child;
477202878Srdivacky}
478202878Srdivacky
479202878Srdivackystatic u_int mmuh = -1;
480202878Srdivackystatic u_int memh = -1;
481202878Srdivacky
482202878Srdivackyvoid
483202878SrdivackyOF_initialize(void)
484202878Srdivacky{
485202878Srdivacky	u_int chosen;
486202878Srdivacky
487203954Srdivacky	if ( (chosen = OF_finddevice("/chosen")) == -1) {
488202878Srdivacky		OF_exit();
489195098Sed	}
490195098Sed	if (OF_getprop(chosen, "mmu", &mmuh, sizeof(mmuh)) != sizeof(mmuh)
491203954Srdivacky	    || OF_getprop(chosen, "memory", &memh, sizeof(memh)) != sizeof(memh))
492203954Srdivacky		OF_exit();
493203954Srdivacky}
494203954Srdivacky
495203954Srdivacky/*
496203954Srdivacky * The following need either the handle to memory or the handle to the MMU.
497203954Srdivacky */
498202878Srdivacky
499202878Srdivacky/*
500202878Srdivacky * Grab some address space from the prom
501202878Srdivacky *
502202878Srdivacky * Only works while the prom is actively mapping us.
503202878Srdivacky */
504202878Srdivackyvaddr_t
505202878SrdivackyOF_claim_virt(vaddr_t vaddr, int len)
506202878Srdivacky{
507202878Srdivacky	struct {
508202878Srdivacky		cell_t name;
509202878Srdivacky		cell_t nargs;
510202878Srdivacky		cell_t nreturns;
511202878Srdivacky		cell_t method;
512202878Srdivacky		cell_t ihandle;
513202878Srdivacky		cell_t align;
514202878Srdivacky		cell_t len;
515202878Srdivacky		cell_t vaddr;
516202878Srdivacky		cell_t status;
517195098Sed		cell_t retaddr;
518195098Sed	} args;
519195098Sed
520198090Srdivacky#ifdef	__notyet
521198090Srdivacky	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
522198090Srdivacky		OF_printf("OF_claim_virt: cannot get mmuh\r\n");
523198090Srdivacky		return -1LL;
524198090Srdivacky	}
525198090Srdivacky#endif
526198090Srdivacky	args.name = ADR2CELL("call-method");
527198090Srdivacky	args.nargs = 5;
528198090Srdivacky	args.nreturns = 2;
529198090Srdivacky	args.method = ADR2CELL("claim");
530198090Srdivacky	args.ihandle = HDL2CELL(mmuh);
531198090Srdivacky	args.align = 0;
532198090Srdivacky	args.len = len;
533198090Srdivacky	args.vaddr = ADR2CELL(vaddr);
534198090Srdivacky	if (openfirmware(&args) != 0)
535198090Srdivacky		return -1LL;
536195098Sed	return (vaddr_t)args.retaddr;
537198090Srdivacky}
538198090Srdivacky
539198090Srdivacky/*
540198090Srdivacky * Request some address space from the prom
541198090Srdivacky *
542198090Srdivacky * Only works while the prom is actively mapping us.
543198090Srdivacky */
544202878Srdivackyvaddr_t
545198090SrdivackyOF_alloc_virt(int len, int align)
546198090Srdivacky{
547198090Srdivacky	int retaddr=-1;
548198090Srdivacky	struct {
549198090Srdivacky		cell_t name;
550195098Sed		cell_t nargs;
551198090Srdivacky		cell_t nreturns;
552198090Srdivacky		cell_t method;
553198090Srdivacky		cell_t ihandle;
554198090Srdivacky		cell_t align;
555198090Srdivacky		cell_t len;
556195098Sed		cell_t status;
557195098Sed		cell_t retaddr;
558198090Srdivacky	} args;
559195098Sed
560195098Sed#ifdef	__notyet
561195098Sed	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
562202878Srdivacky		OF_printf("OF_alloc_virt: cannot get mmuh\r\n");
563195098Sed		return -1LL;
564195098Sed	}
565204642Srdivacky#endif
566204642Srdivacky	args.name = ADR2CELL("call-method");
567204642Srdivacky	args.nargs = 4;
568204642Srdivacky	args.nreturns = 2;
569204642Srdivacky	args.method = ADR2CELL("claim");
570204642Srdivacky	args.ihandle = HDL2CELL(mmuh);
571204642Srdivacky	args.align = align;
572198090Srdivacky	args.len = len;
573195098Sed	args.retaddr = ADR2CELL(&retaddr);
574195098Sed	if (openfirmware(&args) != 0)
575202878Srdivacky		return -1LL;
576202878Srdivacky	return (vaddr_t)args.retaddr;
577195098Sed}
578195098Sed
579198090Srdivacky/*
580203954Srdivacky * Release some address space to the prom
581203954Srdivacky *
582203954Srdivacky * Only works while the prom is actively mapping us.
583203954Srdivacky */
584203954Srdivackyint
585203954SrdivackyOF_free_virt(vaddr_t vaddr, int len)
586198090Srdivacky{
587203954Srdivacky	struct {
588203954Srdivacky		cell_t name;
589203954Srdivacky		cell_t nargs;
590203954Srdivacky		cell_t nreturns;
591203954Srdivacky		cell_t method;
592203954Srdivacky		cell_t ihandle;
593203954Srdivacky		cell_t len;
594203954Srdivacky		cell_t vaddr;
595203954Srdivacky	} args;
596203954Srdivacky
597203954Srdivacky#ifdef	__notyet
598203954Srdivacky	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
599203954Srdivacky		OF_printf("OF_claim_virt: cannot get mmuh\r\n");
600203954Srdivacky		return -1;
601203954Srdivacky	}
602203954Srdivacky#endif
603203954Srdivacky	args.name = ADR2CELL("call-method");
604203954Srdivacky	args.nargs = 4;
605203954Srdivacky	args.nreturns = 0;
606203954Srdivacky	args.method = ADR2CELL("release");
607203954Srdivacky	args.ihandle = HDL2CELL(mmuh);
608203954Srdivacky	args.vaddr = ADR2CELL(vaddr);
609203954Srdivacky	args.len = len;
610203954Srdivacky	return openfirmware(&args);
611203954Srdivacky}
612203954Srdivacky
613203954Srdivacky
614203954Srdivacky/*
615203954Srdivacky * Unmap some address space
616203954Srdivacky *
617203954Srdivacky * Only works while the prom is actively mapping us.
618203954Srdivacky */
619203954Srdivackyint
620203954SrdivackyOF_unmap_virt(vaddr_t vaddr, int len)
621203954Srdivacky{
622203954Srdivacky	struct {
623203954Srdivacky		cell_t name;
624203954Srdivacky		cell_t nargs;
625203954Srdivacky		cell_t nreturns;
626203954Srdivacky		cell_t method;
627203954Srdivacky		cell_t ihandle;
628203954Srdivacky		cell_t len;
629203954Srdivacky		cell_t vaddr;
630203954Srdivacky	} args;
631203954Srdivacky
632203954Srdivacky#ifdef	__notyet
633203954Srdivacky	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
634203954Srdivacky		OF_printf("OF_claim_virt: cannot get mmuh\r\n");
635203954Srdivacky		return -1;
636203954Srdivacky	}
637203954Srdivacky#endif
638203954Srdivacky	args.name = ADR2CELL("call-method");
639203954Srdivacky	args.nargs = 4;
640198090Srdivacky	args.nreturns = 0;
641203954Srdivacky	args.method = ADR2CELL("unmap");
642203954Srdivacky	args.ihandle = HDL2CELL(mmuh);
643203954Srdivacky	args.vaddr = ADR2CELL(vaddr);
644203954Srdivacky	args.len = len;
645203954Srdivacky	return openfirmware(&args);
646203954Srdivacky}
647203954Srdivacky
648203954Srdivacky/*
649203954Srdivacky * Have prom map in some memory
650203954Srdivacky *
651203954Srdivacky * Only works while the prom is actively mapping us.
652198090Srdivacky */
653203954Srdivackyvaddr_t
654203954SrdivackyOF_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode)
655198090Srdivacky{
656203954Srdivacky	struct {
657203954Srdivacky		cell_t name;
658203954Srdivacky		cell_t nargs;
659203954Srdivacky		cell_t nreturns;
660203954Srdivacky		cell_t method;
661195340Sed		cell_t ihandle;
662203954Srdivacky		cell_t mode;
663198090Srdivacky		cell_t size;
664203954Srdivacky		cell_t vaddr;
665203954Srdivacky		cell_t paddr_hi;
666203954Srdivacky		cell_t paddr_lo;
667203954Srdivacky	} args;
668203954Srdivacky
669203954Srdivacky#ifdef	__notyet
670203954Srdivacky	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
671203954Srdivacky		OF_printf("OF_map_phys: cannot get mmuh\r\n");
672208599Srdivacky		return 0LL;
673206083Srdivacky	}
674208599Srdivacky#endif
675208599Srdivacky	args.name = ADR2CELL("call-method");
676208599Srdivacky	args.nargs = 7;
677206083Srdivacky	args.nreturns = 0;
678203954Srdivacky	args.method = ADR2CELL("map");
679206274Srdivacky	args.ihandle = HDL2CELL(mmuh);
680203954Srdivacky	args.mode = mode;
681203954Srdivacky	args.size = size;
682202878Srdivacky	args.vaddr = ADR2CELL(vaddr);
683195098Sed	args.paddr_hi = HDQ2CELL_HI(paddr);
684195098Sed	args.paddr_lo = HDQ2CELL_LO(paddr);
685206274Srdivacky
686206274Srdivacky	if (openfirmware(&args) == -1)
687206274Srdivacky		return -1;
688206274Srdivacky	return 0;
689206274Srdivacky}
690206274Srdivacky
691206274Srdivacky
692206274Srdivacky/*
693206274Srdivacky * Request some RAM from the prom
694206274Srdivacky *
695195098Sed * Only works while the prom is actively mapping us.
696195098Sed */
697195098Sedpaddr_t
698203954SrdivackyOF_alloc_phys(int len, int align)
699202878Srdivacky{
700202878Srdivacky	struct {
701205218Srdivacky		cell_t name;
702202878Srdivacky		cell_t nargs;
703203954Srdivacky		cell_t nreturns;
704205218Srdivacky		cell_t method;
705203954Srdivacky		cell_t ihandle;
706195098Sed		cell_t align;
707		cell_t len;
708		cell_t status;
709		cell_t phys_hi;
710		cell_t phys_lo;
711	} args;
712
713#ifdef	__notyet
714	if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
715		OF_printf("OF_alloc_phys: cannot get memh\r\n");
716		return -1LL;
717	}
718#endif
719	args.name = ADR2CELL("call-method");
720	args.nargs = 4;
721	args.nreturns = 3;
722	args.method = ADR2CELL("claim");
723	args.ihandle = HDL2CELL(memh);
724	args.align = align;
725	args.len = len;
726	if (openfirmware(&args) != 0)
727		return -1LL;
728	return (paddr_t)CELL2HDQ(args.phys_hi, args.phys_lo);
729}
730
731/*
732 * Request some specific RAM from the prom
733 *
734 * Only works while the prom is actively mapping us.
735 */
736paddr_t
737OF_claim_phys(paddr_t phys, int len)
738{
739	struct {
740		cell_t name;
741		cell_t nargs;
742		cell_t nreturns;
743		cell_t method;
744		cell_t ihandle;
745		cell_t align;
746		cell_t len;
747		cell_t phys_hi;
748		cell_t phys_lo;
749		cell_t status;
750		cell_t res;
751		cell_t rphys_hi;
752		cell_t rphys_lo;
753	} args;
754
755#ifdef	__notyet
756	if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
757		OF_printf("OF_alloc_phys: cannot get memh\r\n");
758		return 0LL;
759	}
760#endif
761	args.name = ADR2CELL("call-method");
762	args.nargs = 6;
763	args.nreturns = 4;
764	args.method = ADR2CELL("claim");
765	args.ihandle = HDL2CELL(memh);
766	args.align = 0;
767	args.len = len;
768	args.phys_hi = HDQ2CELL_HI(phys);
769	args.phys_lo = HDQ2CELL_LO(phys);
770	if (openfirmware(&args) != 0)
771		return 0LL;
772	return (paddr_t)CELL2HDQ(args.rphys_hi, args.rphys_lo);
773}
774
775/*
776 * Free some RAM to prom
777 *
778 * Only works while the prom is actively mapping us.
779 */
780int
781OF_free_phys(paddr_t phys, int len)
782{
783	struct {
784		cell_t name;
785		cell_t nargs;
786		cell_t nreturns;
787		cell_t method;
788		cell_t ihandle;
789		cell_t len;
790		cell_t phys_hi;
791		cell_t phys_lo;
792	} args;
793
794#ifdef	__notyet
795	if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
796		OF_printf("OF_free_phys: cannot get memh\r\n");
797		return -1;
798	}
799#endif
800	args.name = ADR2CELL("call-method");
801	args.nargs = 5;
802	args.nreturns = 0;
803	args.method = ADR2CELL("release");
804	args.ihandle = HDL2CELL(memh);
805	args.len = len;
806	args.phys_hi = HDQ2CELL_HI(phys);
807	args.phys_lo = HDQ2CELL_LO(phys);
808	return openfirmware(&args);
809}
810
811
812/*
813 * Claim virtual memory -- does not map it in.
814 */
815
816void *
817OF_claim(void *virt, u_int size, u_int align)
818{
819#define SUNVMOF
820#ifndef SUNVMOF
821	struct {
822		cell_t name;
823		cell_t nargs;
824		cell_t nreturns;
825		cell_t virt;
826		cell_t size;
827		cell_t align;
828		cell_t baseaddr;
829	} args;
830
831
832	args.name = ADR2CELL("claim");
833	args.nargs = 3;
834	args.nreturns = 1;
835	args.virt = virt;
836	args.size = size;
837	args.align = align;
838	if (openfirmware(&args) == -1)
839		return (void *)-1;
840	return args.baseaddr;
841#else
842/*
843 * Sun Ultra machines run the firmware with VM enabled,
844 * so you need to handle allocating and mapping both
845 * virtual and physical memory.  Ugh.
846 */
847
848	paddr_t paddr;
849	void* newvirt = NULL;
850
851	if (virt == NULL) {
852		if ((virt = (void*)OF_alloc_virt(size, align)) == (void*)-1) {
853			printf("OF_alloc_virt(%d,%d) failed w/%p\n", size, align, virt);
854			return (void *)-1;
855		}
856	} else {
857		if ((newvirt = (void*)OF_claim_virt((vaddr_t)virt, size)) == (void*)-1) {
858			printf("OF_claim_virt(%p,%d) failed w/%p\n", virt, size, newvirt);
859			return (void *)-1;
860		}
861	}
862	if ((paddr = OF_alloc_phys(size, align)) == (paddr_t)-1) {
863		printf("OF_alloc_phys(%d,%d) failed\n", size, align);
864		OF_free_virt((vaddr_t)virt, size);
865		return (void *)-1;
866	}
867	if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) {
868		printf("OF_map_phys(0x%lx,%d,%p,%d) failed\n",
869		    (u_long)paddr, size, virt, -1);
870		OF_free_phys((paddr_t)paddr, size);
871		OF_free_virt((vaddr_t)virt, size);
872		return (void *)-1;
873	}
874	return (void *)virt;
875#endif
876}
877