xref: /netbsd-src/sys/arch/sparc/stand/ofwboot/Locore.c (revision 53b02e147d4ed531c0d2a5ca9b3e8026ba3e99b5)
1 /*	$NetBSD: Locore.c,v 1.16 2017/09/15 13:25:34 martin Exp $	*/
2 
3 /*
4  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5  * Copyright (C) 1995, 1996 TooLs GmbH.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by TooLs GmbH.
19  * 4. The name of TooLs GmbH may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <lib/libsa/stand.h>
35 #include "openfirm.h"
36 
37 #include <machine/cpu.h>
38 #include <machine/vmparam.h>
39 
40 /*
41  * We are trying to boot a sparc v9 cpu, so openfirmware has to be 64bit,
42  * and the kernel we load will be dealing with 64bits too (even if it is
43  * a 32bit kernel.
44  * Make sure we picked up the right defines:
45  */
46 __CTASSERT(sizeof(cell_t)==8);
47 __CTASSERT(sizeof(paddr_t)==8);
48 
49 extern int openfirmware(void *);
50 
51 
52 __dead void
53 _rtt(void)
54 {
55 
56 	OF_exit();
57 }
58 
59 void __attribute__((__noreturn__))
60 OF_exit(void)
61 {
62 	struct {
63 		cell_t name;
64 		cell_t nargs;
65 		cell_t nreturns;
66 	} args;
67 
68 	args.name = ADR2CELL("exit");
69 	args.nargs = 0;
70 	args.nreturns = 0;
71 	openfirmware(&args);
72 
73 	printf("OF_exit failed");
74 	for (;;)
75 		continue;
76 }
77 
78 void
79 OF_enter(void)
80 {
81 	struct {
82 		cell_t name;
83 		cell_t nargs;
84 		cell_t nreturns;
85 	} args;
86 
87 	args.name = ADR2CELL("enter");
88 	args.nargs = 0;
89 	args.nreturns = 0;
90 	openfirmware(&args);
91 }
92 
93 int
94 OF_finddevice(const char *name)
95 {
96 	struct {
97 		cell_t name;
98 		cell_t nargs;
99 		cell_t nreturns;
100 		cell_t device;
101 		cell_t phandle;
102 	} args;
103 
104 	args.name = ADR2CELL("finddevice");
105 	args.nargs = 1;
106 	args.nreturns = 1;
107 	args.device = ADR2CELL(name);
108 	if (openfirmware(&args) == -1)
109 		return -1;
110 	return args.phandle;
111 }
112 
113 int
114 OF_instance_to_package(int ihandle)
115 {
116 	struct {
117 		cell_t name;
118 		cell_t nargs;
119 		cell_t nreturns;
120 		cell_t ihandle;
121 		cell_t phandle;
122 	} args;
123 
124 	args.name = ADR2CELL("instance-to-package");
125 	args.nargs = 1;
126 	args.nreturns = 1;
127 	args.ihandle = HDL2CELL(ihandle);
128 	if (openfirmware(&args) == -1)
129 		return -1;
130 	return args.phandle;
131 }
132 
133 int
134 OF_instance_to_path(int ihandle, char *buf, int buflen)
135 {
136 	struct {
137 		cell_t name;
138 		cell_t nargs;
139 		cell_t nreturns;
140 		cell_t ihandle;
141 		cell_t buf;
142 		cell_t buflen;
143 		cell_t length;
144 	} args;
145 
146 	args.name = ADR2CELL("instance-to-path");
147 	args.nargs = 3;
148 	args.nreturns = 1;
149 	args.ihandle = HDL2CELL(ihandle);
150 	args.buf = ADR2CELL(buf);
151 	args.buflen = buflen;
152 	if (openfirmware(&args) < 0)
153 		return -1;
154 	return args.length;
155 }
156 
157 int
158 OF_parent(int phandle)
159 {
160 	struct {
161 		cell_t name;
162 		cell_t nargs;
163 		cell_t nreturns;
164 		cell_t phandle;
165 		cell_t parent;
166 	} args;
167 
168 	args.name = ADR2CELL("parent");
169 	args.nargs = 1;
170 	args.nreturns = 1;
171 	args.phandle = HDL2CELL(phandle);
172 	if (openfirmware(&args) == -1)
173 		return 0;
174 	return args.parent;
175 }
176 
177 int
178 OF_getprop(int handle, const char *prop, void *buf, int buflen)
179 {
180 	struct {
181 		cell_t name;
182 		cell_t nargs;
183 		cell_t nreturns;
184 		cell_t phandle;
185 		cell_t prop;
186 		cell_t buf;
187 		cell_t buflen;
188 		cell_t size;
189 	} args;
190 
191 	args.name = ADR2CELL("getprop");
192 	args.nargs = 4;
193 	args.nreturns = 1;
194 	args.phandle = HDL2CELL(handle);
195 	args.prop = ADR2CELL(prop);
196 	args.buf = ADR2CELL(buf);
197 	args.buflen = buflen;
198 	if (openfirmware(&args) == -1)
199 		return -1;
200 	return args.size;
201 }
202 
203 #ifdef	__notyet__	/* Has a bug on FirePower */
204 int
205 OF_setprop(u_int handle, char *prop, void *buf, int len)
206 {
207 	struct {
208 		cell_t name;
209 		cell_t nargs;
210 		cell_t nreturns;
211 		cell_t phandle;
212 		cell_t prop;
213 		cell_t buf;
214 		cell_t len;
215 		cell_t size;
216 	} args;
217 
218 	args.name = ADR2CELL("setprop");
219 	args.nargs = 4;
220 	args.nreturns = 1;
221 	args.phandle = HDL2CELL(handle);
222 	args.prop = ADR2CELL(prop);
223 	args.buf = ADR2CELL(buf);
224 	args.len = len;
225 	if (openfirmware(&args) == -1)
226 		return -1;
227 	return args.size;
228 }
229 #endif
230 
231 int
232 OF_interpret(const char *cmd, int nargs, int nreturns, ...)
233 {
234 	va_list ap;
235 	struct {
236 		cell_t name;
237 		cell_t nargs;
238 		cell_t nreturns;
239 		cell_t slot[16];
240 	} args;
241 	cell_t status;
242 	int i = 0;
243 
244 	args.name = ADR2CELL("interpret");
245 	args.nargs = ++nargs;
246 	args.nreturns = ++nreturns;
247 	args.slot[i++] = ADR2CELL(cmd);
248 	va_start(ap, nreturns);
249 	while (i < nargs) {
250 		args.slot[i++] = va_arg(ap, cell_t);
251 	}
252 	if (openfirmware(&args) == -1) {
253 		va_end(ap);
254 		return (-1);
255 	}
256 	status = args.slot[i++];
257 	while (i < nargs+nreturns) {
258 		*va_arg(ap, cell_t *) = args.slot[i++];
259 	}
260 	va_end(ap);
261 
262 	return status;
263 }
264 
265 int
266 OF_package_to_path(int phandle, char *buf, int buflen)
267 {
268 	struct {
269 		cell_t name;
270 		cell_t nargs;
271 		cell_t nreturns;
272 		cell_t phandle;
273 		cell_t buf;
274 		cell_t buflen;
275 		cell_t length;
276 	} args;
277 
278 	if (buflen > PAGE_SIZE)
279 		return -1;
280 	args.name = ADR2CELL("package-to-path");
281 	args.nargs = 3;
282 	args.nreturns = 1;
283 	args.phandle = HDL2CELL(phandle);
284 	args.buf = ADR2CELL(buf);
285 	args.buflen = buflen;
286 	if (openfirmware(&args) < 0)
287 		return -1;
288 	return args.length;
289 }
290 
291 int
292 OF_open(const char *dname)
293 {
294 	struct {
295 		cell_t name;
296 		cell_t nargs;
297 		cell_t nreturns;
298 		cell_t dname;
299 		cell_t handle;
300 	} args;
301 
302 	args.name = ADR2CELL("open");
303 	args.nargs = 1;
304 	args.nreturns = 1;
305 	args.dname = ADR2CELL(dname);
306 	if (openfirmware(&args) == -1 ||
307 	    args.handle == 0)
308 		return -1;
309 	return args.handle;
310 }
311 
312 void
313 OF_close(int handle)
314 {
315 	struct {
316 		cell_t name;
317 		cell_t nargs;
318 		cell_t nreturns;
319 		cell_t handle;
320 	} args;
321 
322 	args.name = ADR2CELL("close");
323 	args.nargs = 1;
324 	args.nreturns = 0;
325 	args.handle = HDL2CELL(handle);
326 	openfirmware(&args);
327 }
328 
329 int
330 OF_write(int handle, const void *addr, int len)
331 {
332 	struct {
333 		cell_t name;
334 		cell_t nargs;
335 		cell_t nreturns;
336 		cell_t ihandle;
337 		cell_t addr;
338 		cell_t len;
339 		cell_t actual;
340 	} args;
341 
342 	args.name = ADR2CELL("write");
343 	args.nargs = 3;
344 	args.nreturns = 1;
345 	args.ihandle = HDL2CELL(handle);
346 	args.addr = ADR2CELL(addr);
347 	args.len = len;
348 	if (openfirmware(&args) == -1)
349 		return -1;
350 	return args.actual;
351 }
352 
353 int
354 OF_read(int handle, void *addr, int len)
355 {
356 	struct {
357 		cell_t name;
358 		cell_t nargs;
359 		cell_t nreturns;
360 		cell_t ihandle;
361 		cell_t addr;
362 		cell_t len;
363 		cell_t actual;
364 	} args;
365 
366 	args.name = ADR2CELL("read");
367 	args.nargs = 3;
368 	args.nreturns = 1;
369 	args.ihandle = HDL2CELL(handle);
370 	args.addr = ADR2CELL(addr);
371 	args.len = len;
372 	if (openfirmware(&args) == -1) {
373 		return -1;
374 	}
375 	return args.actual;
376 }
377 
378 int
379 OF_seek(int handle, u_quad_t pos)
380 {
381 	struct {
382 		cell_t name;
383 		cell_t nargs;
384 		cell_t nreturns;
385 		cell_t handle;
386 		cell_t poshi;
387 		cell_t poslo;
388 		cell_t status;
389 	} args;
390 
391 	args.name = ADR2CELL("seek");
392 	args.nargs = 3;
393 	args.nreturns = 1;
394 	args.handle = HDL2CELL(handle);
395 	args.poshi = HDQ2CELL_HI(pos);
396 	args.poslo = HDQ2CELL_LO(pos);
397 	if (openfirmware(&args) == -1) {
398 		return -1;
399 	}
400 	return args.status;
401 }
402 
403 void
404 OF_release(void *virt, u_int size)
405 {
406 	struct {
407 		cell_t name;
408 		cell_t nargs;
409 		cell_t nreturns;
410 		cell_t virt;
411 		cell_t size;
412 	} args;
413 
414 	args.name = ADR2CELL("release");
415 	args.nargs = 2;
416 	args.nreturns = 0;
417 	args.virt = ADR2CELL(virt);
418 	args.size = size;
419 	openfirmware(&args);
420 }
421 
422 int
423 OF_milliseconds(void)
424 {
425 	struct {
426 		cell_t name;
427 		cell_t nargs;
428 		cell_t nreturns;
429 		cell_t ms;
430 	} args;
431 
432 	args.name = ADR2CELL("milliseconds");
433 	args.nargs = 0;
434 	args.nreturns = 1;
435 	openfirmware(&args);
436 	return args.ms;
437 }
438 
439 int
440 OF_peer(int phandle)
441 {
442 	struct {
443 		cell_t name;
444 		cell_t nargs;
445 		cell_t nreturns;
446 		cell_t phandle;
447 		cell_t sibling;
448 	} args;
449 
450 	args.name = ADR2CELL("peer");
451 	args.nargs = 1;
452 	args.nreturns = 1;
453 	args.phandle = HDL2CELL(phandle);
454 	if (openfirmware(&args) == -1)
455 		return 0;
456 	return args.sibling;
457 }
458 
459 int
460 OF_child(int phandle)
461 {
462 	struct {
463 		cell_t name;
464 		cell_t nargs;
465 		cell_t nreturns;
466 		cell_t phandle;
467 		cell_t child;
468 	} args;
469 
470 	args.name = ADR2CELL("child");
471 	args.nargs = 1;
472 	args.nreturns = 1;
473 	args.phandle = HDL2CELL(phandle);
474 	if (openfirmware(&args) == -1)
475 		return 0;
476 	return args.child;
477 }
478 
479 static u_int mmuh = -1;
480 static u_int memh = -1;
481 
482 void
483 OF_initialize(void)
484 {
485 	u_int chosen;
486 
487 	if ( (chosen = OF_finddevice("/chosen")) == -1) {
488 		OF_exit();
489 	}
490 	if (OF_getprop(chosen, "mmu", &mmuh, sizeof(mmuh)) != sizeof(mmuh)
491 	    || OF_getprop(chosen, "memory", &memh, sizeof(memh)) != sizeof(memh))
492 		OF_exit();
493 }
494 
495 /*
496  * The following need either the handle to memory or the handle to the MMU.
497  */
498 
499 /*
500  * Grab some address space from the prom
501  *
502  * Only works while the prom is actively mapping us.
503  */
504 vaddr_t
505 OF_claim_virt(vaddr_t vaddr, int len)
506 {
507 	struct {
508 		cell_t name;
509 		cell_t nargs;
510 		cell_t nreturns;
511 		cell_t method;
512 		cell_t ihandle;
513 		cell_t align;
514 		cell_t len;
515 		cell_t vaddr;
516 		cell_t status;
517 		cell_t retaddr;
518 	} args;
519 
520 #ifdef	__notyet
521 	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
522 		OF_printf("OF_claim_virt: cannot get mmuh\r\n");
523 		return -1LL;
524 	}
525 #endif
526 	args.name = ADR2CELL("call-method");
527 	args.nargs = 5;
528 	args.nreturns = 2;
529 	args.method = ADR2CELL("claim");
530 	args.ihandle = HDL2CELL(mmuh);
531 	args.align = 0;
532 	args.len = len;
533 	args.vaddr = ADR2CELL(vaddr);
534 	if (openfirmware(&args) != 0)
535 		return -1LL;
536 	return (vaddr_t)args.retaddr;
537 }
538 
539 /*
540  * Request some address space from the prom
541  *
542  * Only works while the prom is actively mapping us.
543  */
544 vaddr_t
545 OF_alloc_virt(int len, int align)
546 {
547 	int retaddr=-1;
548 	struct {
549 		cell_t name;
550 		cell_t nargs;
551 		cell_t nreturns;
552 		cell_t method;
553 		cell_t ihandle;
554 		cell_t align;
555 		cell_t len;
556 		cell_t status;
557 		cell_t retaddr;
558 	} args;
559 
560 #ifdef	__notyet
561 	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
562 		OF_printf("OF_alloc_virt: cannot get mmuh\r\n");
563 		return -1LL;
564 	}
565 #endif
566 	args.name = ADR2CELL("call-method");
567 	args.nargs = 4;
568 	args.nreturns = 2;
569 	args.method = ADR2CELL("claim");
570 	args.ihandle = HDL2CELL(mmuh);
571 	args.align = align;
572 	args.len = len;
573 	args.retaddr = ADR2CELL(&retaddr);
574 	if (openfirmware(&args) != 0)
575 		return -1LL;
576 	return (vaddr_t)args.retaddr;
577 }
578 
579 /*
580  * Release some address space to the prom
581  *
582  * Only works while the prom is actively mapping us.
583  */
584 int
585 OF_free_virt(vaddr_t vaddr, int len)
586 {
587 	struct {
588 		cell_t name;
589 		cell_t nargs;
590 		cell_t nreturns;
591 		cell_t method;
592 		cell_t ihandle;
593 		cell_t len;
594 		cell_t vaddr;
595 	} args;
596 
597 #ifdef	__notyet
598 	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
599 		OF_printf("OF_claim_virt: cannot get mmuh\r\n");
600 		return -1;
601 	}
602 #endif
603 	args.name = ADR2CELL("call-method");
604 	args.nargs = 4;
605 	args.nreturns = 0;
606 	args.method = ADR2CELL("release");
607 	args.ihandle = HDL2CELL(mmuh);
608 	args.vaddr = ADR2CELL(vaddr);
609 	args.len = len;
610 	return openfirmware(&args);
611 }
612 
613 
614 /*
615  * Unmap some address space
616  *
617  * Only works while the prom is actively mapping us.
618  */
619 int
620 OF_unmap_virt(vaddr_t vaddr, int len)
621 {
622 	struct {
623 		cell_t name;
624 		cell_t nargs;
625 		cell_t nreturns;
626 		cell_t method;
627 		cell_t ihandle;
628 		cell_t len;
629 		cell_t vaddr;
630 	} args;
631 
632 #ifdef	__notyet
633 	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
634 		OF_printf("OF_claim_virt: cannot get mmuh\r\n");
635 		return -1;
636 	}
637 #endif
638 	args.name = ADR2CELL("call-method");
639 	args.nargs = 4;
640 	args.nreturns = 0;
641 	args.method = ADR2CELL("unmap");
642 	args.ihandle = HDL2CELL(mmuh);
643 	args.vaddr = ADR2CELL(vaddr);
644 	args.len = len;
645 	return openfirmware(&args);
646 }
647 
648 /*
649  * Have prom map in some memory
650  *
651  * Only works while the prom is actively mapping us.
652  */
653 vaddr_t
654 OF_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode)
655 {
656 	struct {
657 		cell_t name;
658 		cell_t nargs;
659 		cell_t nreturns;
660 		cell_t method;
661 		cell_t ihandle;
662 		cell_t mode;
663 		cell_t size;
664 		cell_t vaddr;
665 		cell_t paddr_hi;
666 		cell_t paddr_lo;
667 		cell_t status;
668 		cell_t retaddr;
669 	} args;
670 
671 #ifdef	__notyet
672 	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
673 		OF_printf("OF_map_phys: cannot get mmuh\r\n");
674 		return 0LL;
675 	}
676 #endif
677 	args.name = ADR2CELL("call-method");
678 	args.nargs = 7;
679 	args.nreturns = 1;
680 	args.method = ADR2CELL("map");
681 	args.ihandle = HDL2CELL(mmuh);
682 	args.mode = mode;
683 	args.size = size;
684 	args.vaddr = ADR2CELL(vaddr);
685 	args.paddr_hi = HDQ2CELL_HI(paddr);
686 	args.paddr_lo = HDQ2CELL_LO(paddr);
687 
688 	if (openfirmware(&args) == -1)
689 		return -1;
690 	if (args.status)
691 		return -1;
692 	return (vaddr_t)args.retaddr;
693 }
694 
695 
696 /*
697  * Request some RAM from the prom
698  *
699  * Only works while the prom is actively mapping us.
700  */
701 paddr_t
702 OF_alloc_phys(int len, int align)
703 {
704 	struct {
705 		cell_t name;
706 		cell_t nargs;
707 		cell_t nreturns;
708 		cell_t method;
709 		cell_t ihandle;
710 		cell_t align;
711 		cell_t len;
712 		cell_t status;
713 		cell_t phys_hi;
714 		cell_t phys_lo;
715 	} args;
716 
717 #ifdef	__notyet
718 	if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
719 		OF_printf("OF_alloc_phys: cannot get memh\r\n");
720 		return -1LL;
721 	}
722 #endif
723 	args.name = ADR2CELL("call-method");
724 	args.nargs = 4;
725 	args.nreturns = 3;
726 	args.method = ADR2CELL("claim");
727 	args.ihandle = HDL2CELL(memh);
728 	args.align = align;
729 	args.len = len;
730 	if (openfirmware(&args) != 0)
731 		return -1LL;
732 	return (paddr_t)CELL2HDQ(args.phys_hi, args.phys_lo);
733 }
734 
735 /*
736  * Request some specific RAM from the prom
737  *
738  * Only works while the prom is actively mapping us.
739  */
740 paddr_t
741 OF_claim_phys(paddr_t phys, int len)
742 {
743 	struct {
744 		cell_t name;
745 		cell_t nargs;
746 		cell_t nreturns;
747 		cell_t method;
748 		cell_t ihandle;
749 		cell_t align;
750 		cell_t len;
751 		cell_t phys_hi;
752 		cell_t phys_lo;
753 		cell_t status;
754 		cell_t res;
755 		cell_t rphys_hi;
756 		cell_t rphys_lo;
757 	} args;
758 
759 #ifdef	__notyet
760 	if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
761 		OF_printf("OF_alloc_phys: cannot get memh\r\n");
762 		return 0LL;
763 	}
764 #endif
765 	args.name = ADR2CELL("call-method");
766 	args.nargs = 6;
767 	args.nreturns = 4;
768 	args.method = ADR2CELL("claim");
769 	args.ihandle = HDL2CELL(memh);
770 	args.align = 0;
771 	args.len = len;
772 	args.phys_hi = HDQ2CELL_HI(phys);
773 	args.phys_lo = HDQ2CELL_LO(phys);
774 	if (openfirmware(&args) != 0)
775 		return 0LL;
776 	return (paddr_t)CELL2HDQ(args.rphys_hi, args.rphys_lo);
777 }
778 
779 /*
780  * Free some RAM to prom
781  *
782  * Only works while the prom is actively mapping us.
783  */
784 int
785 OF_free_phys(paddr_t phys, int len)
786 {
787 	struct {
788 		cell_t name;
789 		cell_t nargs;
790 		cell_t nreturns;
791 		cell_t method;
792 		cell_t ihandle;
793 		cell_t len;
794 		cell_t phys_hi;
795 		cell_t phys_lo;
796 	} args;
797 
798 #ifdef	__notyet
799 	if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
800 		OF_printf("OF_free_phys: cannot get memh\r\n");
801 		return -1;
802 	}
803 #endif
804 	args.name = ADR2CELL("call-method");
805 	args.nargs = 5;
806 	args.nreturns = 0;
807 	args.method = ADR2CELL("release");
808 	args.ihandle = HDL2CELL(memh);
809 	args.len = len;
810 	args.phys_hi = HDQ2CELL_HI(phys);
811 	args.phys_lo = HDQ2CELL_LO(phys);
812 	return openfirmware(&args);
813 }
814 
815 
816 /*
817  * Claim virtual memory -- does not map it in.
818  */
819 
820 void *
821 OF_claim(void *virt, u_int size, u_int align)
822 {
823 #define SUNVMOF
824 #ifndef SUNVMOF
825 	struct {
826 		cell_t name;
827 		cell_t nargs;
828 		cell_t nreturns;
829 		cell_t virt;
830 		cell_t size;
831 		cell_t align;
832 		cell_t baseaddr;
833 	} args;
834 
835 
836 	args.name = ADR2CELL("claim");
837 	args.nargs = 3;
838 	args.nreturns = 1;
839 	args.virt = virt;
840 	args.size = size;
841 	args.align = align;
842 	if (openfirmware(&args) == -1)
843 		return (void *)-1;
844 	return args.baseaddr;
845 #else
846 /*
847  * Sun Ultra machines run the firmware with VM enabled,
848  * so you need to handle allocating and mapping both
849  * virtual and physical memory.  Ugh.
850  */
851 
852 	paddr_t paddr;
853 	void* newvirt = NULL;
854 
855 	if (virt == NULL) {
856 		if ((virt = (void*)OF_alloc_virt(size, align)) == (void*)-1) {
857 			printf("OF_alloc_virt(%d,%d) failed w/%p\n", size, align, virt);
858 			return (void *)-1;
859 		}
860 	} else {
861 		if ((newvirt = (void*)OF_claim_virt((vaddr_t)virt, size)) == (void*)-1) {
862 			printf("OF_claim_virt(%p,%d) failed w/%p\n", virt, size, newvirt);
863 			return (void *)-1;
864 		}
865 	}
866 	if ((paddr = OF_alloc_phys(size, align)) == (paddr_t)-1) {
867 		printf("OF_alloc_phys(%d,%d) failed\n", size, align);
868 		OF_free_virt((vaddr_t)virt, size);
869 		return (void *)-1;
870 	}
871 	if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) {
872 		printf("OF_map_phys(0x%lx,%d,%p,%d) failed\n",
873 		    (u_long)paddr, size, virt, -1);
874 		OF_free_phys((paddr_t)paddr, size);
875 		OF_free_virt((vaddr_t)virt, size);
876 		return (void *)-1;
877 	}
878 	return (void *)virt;
879 #endif
880 }
881