Home | History | Annotate | Line # | Download | only in ofwboot
      1 /*	$NetBSD: Locore.c,v 1.17 2022/05/14 07:11:23 hgutch 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 	} args;
    668 
    669 #ifdef	__notyet
    670 	if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
    671 		OF_printf("OF_map_phys: cannot get mmuh\r\n");
    672 		return 0LL;
    673 	}
    674 #endif
    675 	args.name = ADR2CELL("call-method");
    676 	args.nargs = 7;
    677 	args.nreturns = 0;
    678 	args.method = ADR2CELL("map");
    679 	args.ihandle = HDL2CELL(mmuh);
    680 	args.mode = mode;
    681 	args.size = size;
    682 	args.vaddr = ADR2CELL(vaddr);
    683 	args.paddr_hi = HDQ2CELL_HI(paddr);
    684 	args.paddr_lo = HDQ2CELL_LO(paddr);
    685 
    686 	if (openfirmware(&args) == -1)
    687 		return -1;
    688 	return 0;
    689 }
    690 
    691 
    692 /*
    693  * Request some RAM from the prom
    694  *
    695  * Only works while the prom is actively mapping us.
    696  */
    697 paddr_t
    698 OF_alloc_phys(int len, int align)
    699 {
    700 	struct {
    701 		cell_t name;
    702 		cell_t nargs;
    703 		cell_t nreturns;
    704 		cell_t method;
    705 		cell_t ihandle;
    706 		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  */
    736 paddr_t
    737 OF_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  */
    780 int
    781 OF_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 
    816 void *
    817 OF_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