1/* $OpenBSD: Locore.c,v 1.18 2023/06/01 17:24:56 krw Exp $ */ 2/* $NetBSD: Locore.c,v 1.1 2000/08/20 14:58:36 mrg Exp $ */ 3 4/* 5 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 6 * Copyright (C) 1995, 1996 TooLs GmbH. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by TooLs GmbH. 20 * 4. The name of TooLs GmbH may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35#include <lib/libsa/stand.h> 36 37#include "openfirm.h" 38 39#include <machine/cpu.h> 40 41#ifdef SOFTRAID 42#include <dev/softraidvar.h> 43#include <lib/libsa/softraid.h> 44#endif 45 46static vaddr_t OF_claim_virt(vaddr_t vaddr, int len); 47static vaddr_t OF_alloc_virt(int len, int align); 48static int OF_free_virt(vaddr_t vaddr, int len); 49static int OF_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode); 50static paddr_t OF_alloc_phys(int len, int align); 51static int OF_free_phys(paddr_t paddr, int len); 52 53extern int openfirmware(void *); 54 55void setup(void); 56 57__dead void 58_rtt(void) 59{ 60 struct { 61 cell_t name; 62 cell_t nargs; 63 cell_t nreturns; 64 } args; 65 66#ifdef SOFTRAID 67 sr_clear_keys(); 68#endif 69 70 args.name = ADR2CELL("exit"); 71 args.nargs = 0; 72 args.nreturns = 0; 73 openfirmware(&args); 74 while (1); /* just in case */ 75} 76 77void 78OF_enter(void) 79{ 80 struct { 81 cell_t name; 82 cell_t nargs; 83 cell_t nreturns; 84 } args; 85 86 args.name = ADR2CELL("enter"); 87 args.nargs = 0; 88 args.nreturns = 0; 89 openfirmware(&args); 90} 91 92int 93OF_finddevice(char *name) 94{ 95 struct { 96 cell_t name; 97 cell_t nargs; 98 cell_t nreturns; 99 cell_t device; 100 cell_t phandle; 101 } args; 102 103 args.name = ADR2CELL("finddevice"); 104 args.nargs = 1; 105 args.nreturns = 1; 106 args.device = ADR2CELL(name); 107 if (openfirmware(&args) == -1) 108 return -1; 109 return args.phandle; 110} 111 112int 113OF_instance_to_package(int ihandle) 114{ 115 struct { 116 cell_t name; 117 cell_t nargs; 118 cell_t nreturns; 119 cell_t ihandle; 120 cell_t phandle; 121 } args; 122 123 args.name = ADR2CELL("instance-to-package"); 124 args.nargs = 1; 125 args.nreturns = 1; 126 args.ihandle = HDL2CELL(ihandle); 127 if (openfirmware(&args) == -1) 128 return -1; 129 return args.phandle; 130} 131 132int 133OF_getprop(int handle, char *prop, void *buf, int buflen) 134{ 135 struct { 136 cell_t name; 137 cell_t nargs; 138 cell_t nreturns; 139 cell_t phandle; 140 cell_t prop; 141 cell_t buf; 142 cell_t buflen; 143 cell_t size; 144 } args; 145 146 args.name = ADR2CELL("getprop"); 147 args.nargs = 4; 148 args.nreturns = 1; 149 args.phandle = HDL2CELL(handle); 150 args.prop = ADR2CELL(prop); 151 args.buf = ADR2CELL(buf); 152 args.buflen = buflen; 153 if (openfirmware(&args) == -1) 154 return -1; 155 return args.size; 156} 157 158int 159OF_open(char *dname) 160{ 161 struct { 162 cell_t name; 163 cell_t nargs; 164 cell_t nreturns; 165 cell_t dname; 166 cell_t handle; 167 } args; 168 169 args.name = ADR2CELL("open"); 170 args.nargs = 1; 171 args.nreturns = 1; 172 args.dname = ADR2CELL(dname); 173 if (openfirmware(&args) == -1 || 174 args.handle == 0) 175 return -1; 176 return args.handle; 177} 178 179void 180OF_close(int handle) 181{ 182 struct { 183 cell_t name; 184 cell_t nargs; 185 cell_t nreturns; 186 cell_t handle; 187 } args; 188 189 args.name = ADR2CELL("close"); 190 args.nargs = 1; 191 args.nreturns = 0; 192 args.handle = HDL2CELL(handle); 193 openfirmware(&args); 194} 195 196int 197OF_write(int handle, void *addr, int len) 198{ 199 struct { 200 cell_t name; 201 cell_t nargs; 202 cell_t nreturns; 203 cell_t ihandle; 204 cell_t addr; 205 cell_t len; 206 cell_t actual; 207 } args; 208 209 args.name = ADR2CELL("write"); 210 args.nargs = 3; 211 args.nreturns = 1; 212 args.ihandle = HDL2CELL(handle); 213 args.addr = ADR2CELL(addr); 214 args.len = len; 215 if (openfirmware(&args) == -1) 216 return -1; 217 return args.actual; 218} 219 220int 221OF_read(int handle, void *addr, int len) 222{ 223 struct { 224 cell_t name; 225 cell_t nargs; 226 cell_t nreturns; 227 cell_t ihandle; 228 cell_t addr; 229 cell_t len; 230 cell_t actual; 231 } args; 232 233 args.name = ADR2CELL("read"); 234 args.nargs = 3; 235 args.nreturns = 1; 236 args.ihandle = HDL2CELL(handle); 237 args.addr = ADR2CELL(addr); 238 args.len = len; 239 if (openfirmware(&args) == -1) { 240 return -1; 241 } 242 return args.actual; 243} 244 245int 246OF_seek(int handle, u_quad_t pos) 247{ 248 struct { 249 cell_t name; 250 cell_t nargs; 251 cell_t nreturns; 252 cell_t handle; 253 cell_t poshi; 254 cell_t poslo; 255 cell_t status; 256 } args; 257 258 args.name = ADR2CELL("seek"); 259 args.nargs = 3; 260 args.nreturns = 1; 261 args.handle = HDL2CELL(handle); 262 args.poshi = HDQ2CELL_HI(pos); 263 args.poslo = HDQ2CELL_LO(pos); 264 if (openfirmware(&args) == -1) { 265 return -1; 266 } 267 return args.status; 268} 269 270void 271OF_release(void *virt, u_int size) 272{ 273 struct { 274 cell_t name; 275 cell_t nargs; 276 cell_t nreturns; 277 cell_t virt; 278 cell_t size; 279 } args; 280 281 args.name = ADR2CELL("release"); 282 args.nargs = 2; 283 args.nreturns = 0; 284 args.virt = ADR2CELL(virt); 285 args.size = size; 286 openfirmware(&args); 287} 288 289int 290OF_milliseconds(void) 291{ 292 struct { 293 cell_t name; 294 cell_t nargs; 295 cell_t nreturns; 296 cell_t ms; 297 } args; 298 299 args.name = ADR2CELL("milliseconds"); 300 args.nargs = 0; 301 args.nreturns = 1; 302 openfirmware(&args); 303 return args.ms; 304} 305 306void 307OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 308{ 309 extern int64_t romp; 310 311 entry(0, arg, len, (unsigned long)romp, (unsigned long)romp); 312 panic("OF_chain: kernel returned!"); 313 __asm("ta 2" : :); 314} 315 316static u_int stdin; 317static u_int stdout; 318static u_int mmuh = -1; 319static u_int memh = -1; 320 321void 322setup(void) 323{ 324 u_int chosen; 325 326 if ((chosen = OF_finddevice("/chosen")) == -1) 327 _rtt(); 328 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != sizeof(stdin) 329 || OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != sizeof(stdout) 330 || OF_getprop(chosen, "mmu", &mmuh, sizeof(mmuh)) != sizeof(mmuh) 331 || OF_getprop(chosen, "memory", &memh, sizeof(memh)) != sizeof(memh)) 332 _rtt(); 333} 334 335/* 336 * The following need either the handle to memory or the handle to the MMU. 337 */ 338 339/* 340 * Grab some address space from the prom 341 * 342 * Only works while the prom is actively mapping us. 343 */ 344static vaddr_t 345OF_claim_virt(vaddr_t vaddr, int len) 346{ 347 struct { 348 cell_t name; 349 cell_t nargs; 350 cell_t nreturns; 351 cell_t method; 352 cell_t ihandle; 353 cell_t align; 354 cell_t len; 355 cell_t vaddr; 356 cell_t status; 357 cell_t retaddr; 358 } args; 359 360 args.name = ADR2CELL("call-method"); 361 args.nargs = 5; 362 args.nreturns = 2; 363 args.method = ADR2CELL("claim"); 364 args.ihandle = HDL2CELL(mmuh); 365 args.align = 0; 366 args.len = len; 367 args.vaddr = ADR2CELL(vaddr); 368 if (openfirmware(&args) != 0) 369 return -1LL; 370 return (vaddr_t)args.retaddr; 371} 372 373/* 374 * Request some address space from the prom 375 * 376 * Only works while the prom is actively mapping us. 377 */ 378static vaddr_t 379OF_alloc_virt(int len, int align) 380{ 381 int retaddr=-1; 382 struct { 383 cell_t name; 384 cell_t nargs; 385 cell_t nreturns; 386 cell_t method; 387 cell_t ihandle; 388 cell_t align; 389 cell_t len; 390 cell_t status; 391 cell_t retaddr; 392 } args; 393 394 args.name = ADR2CELL("call-method"); 395 args.nargs = 4; 396 args.nreturns = 2; 397 args.method = ADR2CELL("claim"); 398 args.ihandle = HDL2CELL(mmuh); 399 args.align = align; 400 args.len = len; 401 args.retaddr = ADR2CELL(&retaddr); 402 if (openfirmware(&args) != 0) 403 return -1LL; 404 return (vaddr_t)args.retaddr; 405} 406 407/* 408 * Release some address space to the prom 409 * 410 * Only works while the prom is actively mapping us. 411 */ 412static int 413OF_free_virt(vaddr_t vaddr, int len) 414{ 415 struct { 416 cell_t name; 417 cell_t nargs; 418 cell_t nreturns; 419 cell_t method; 420 cell_t ihandle; 421 cell_t len; 422 cell_t vaddr; 423 } args; 424 425 args.name = ADR2CELL("call-method"); 426 args.nargs = 4; 427 args.nreturns = 0; 428 args.method = ADR2CELL("release"); 429 args.ihandle = HDL2CELL(mmuh); 430 args.vaddr = ADR2CELL(vaddr); 431 args.len = len; 432 return openfirmware(&args); 433} 434 435 436/* 437 * Have prom map in some memory 438 * 439 * Only works while the prom is actively mapping us. 440 */ 441static int 442OF_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode) 443{ 444 struct { 445 cell_t name; 446 cell_t nargs; 447 cell_t nreturns; 448 cell_t method; 449 cell_t ihandle; 450 cell_t mode; 451 cell_t size; 452 cell_t vaddr; 453 cell_t paddr_hi; 454 cell_t paddr_lo; 455 } args; 456 457 args.name = ADR2CELL("call-method"); 458 args.nargs = 7; 459 args.nreturns = 0; 460 args.method = ADR2CELL("map"); 461 args.ihandle = HDL2CELL(mmuh); 462 args.mode = mode; 463 args.size = size; 464 args.vaddr = ADR2CELL(vaddr); 465 args.paddr_hi = HDQ2CELL_HI(paddr); 466 args.paddr_lo = HDQ2CELL_LO(paddr); 467 return openfirmware(&args); 468} 469 470 471/* 472 * Request some RAM from the prom 473 * 474 * Only works while the prom is actively mapping us. 475 */ 476static paddr_t 477OF_alloc_phys(int len, int align) 478{ 479 struct { 480 cell_t name; 481 cell_t nargs; 482 cell_t nreturns; 483 cell_t method; 484 cell_t ihandle; 485 cell_t align; 486 cell_t len; 487 cell_t status; 488 cell_t phys_hi; 489 cell_t phys_lo; 490 } args; 491 492 args.name = ADR2CELL("call-method"); 493 args.nargs = 4; 494 args.nreturns = 3; 495 args.method = ADR2CELL("claim"); 496 args.ihandle = HDL2CELL(memh); 497 args.align = align; 498 args.len = len; 499 if (openfirmware(&args) != 0) 500 return -1LL; 501 return (paddr_t)CELL2HDQ(args.phys_hi, args.phys_lo); 502} 503 504 505/* 506 * Free some RAM to prom 507 * 508 * Only works while the prom is actively mapping us. 509 */ 510static int 511OF_free_phys(paddr_t phys, int len) 512{ 513 struct { 514 cell_t name; 515 cell_t nargs; 516 cell_t nreturns; 517 cell_t method; 518 cell_t ihandle; 519 cell_t len; 520 cell_t phys_hi; 521 cell_t phys_lo; 522 } args; 523 524 args.name = ADR2CELL("call-method"); 525 args.nargs = 5; 526 args.nreturns = 0; 527 args.method = ADR2CELL("release"); 528 args.ihandle = HDL2CELL(memh); 529 args.len = len; 530 args.phys_hi = HDQ2CELL_HI(phys); 531 args.phys_lo = HDQ2CELL_LO(phys); 532 return openfirmware(&args); 533} 534 535 536/* 537 * Claim virtual memory -- does not map it in. 538 */ 539 540void * 541OF_claim(void *virt, u_int size, u_int align) 542{ 543 /* 544 * Sun Ultra machines run the firmware with VM enabled, 545 * so you need to handle allocating and mapping both 546 * virtual and physical memory. Ugh. 547 */ 548 paddr_t paddr; 549 void * newvirt = NULL; 550 551 if (virt == NULL) { 552 virt = (void *)OF_alloc_virt(size, align); 553 if (virt == (void *)-1LL) { 554 printf("OF_alloc_virt(%d,%d) failed w/%x\n", 555 size, align, virt); 556 return virt; 557 } 558 } else { 559 newvirt = (void *)OF_claim_virt((vaddr_t)virt, size); 560 if (newvirt == (void *)-1LL) { 561 printf("OF_claim_virt(%x,%d) failed w/%x\n", 562 virt, size, newvirt); 563 return newvirt; 564 } 565 virt = newvirt; 566 } 567 if ((paddr = OF_alloc_phys(size, align)) == (paddr_t)-1LL) { 568 printf("OF_alloc_phys(%d,%d) failed\n", size, align); 569 OF_free_virt((vaddr_t)virt, size); 570 return (void *)-1LL; 571 } 572 if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) { 573 printf("OF_map_phys(%x,%d,%x,%d) failed\n", 574 paddr, size, virt, -1); 575 OF_free_phys((paddr_t)paddr, size); 576 OF_free_virt((vaddr_t)virt, size); 577 return (void *)-1LL; 578 } 579 return virt; 580} 581 582int 583OF_peer(int phandle) 584{ 585 struct { 586 cell_t name; 587 cell_t nargs; 588 cell_t nreturns; 589 cell_t phandle; 590 cell_t sibling; 591 } args; 592 593 args.name = ADR2CELL("peer"); 594 args.nargs = 1; 595 args.nreturns = 1; 596 args.phandle = HDL2CELL(phandle); 597 if (openfirmware(&args) == -1) 598 return 0; 599 return args.sibling; 600} 601 602int 603OF_child(int phandle) 604{ 605 struct { 606 cell_t name; 607 cell_t nargs; 608 cell_t nreturns; 609 cell_t phandle; 610 cell_t child; 611 } args; 612 613 args.name = ADR2CELL("child"); 614 args.nargs = 1; 615 args.nreturns = 1; 616 args.phandle = HDL2CELL(phandle); 617 if (openfirmware(&args) == -1) 618 return 0; 619 return args.child; 620} 621 622int 623OF_parent(int phandle) 624{ 625 struct { 626 cell_t name; 627 cell_t nargs; 628 cell_t nreturns; 629 cell_t phandle; 630 cell_t parent; 631 } args; 632 633 args.name = ADR2CELL("parent"); 634 args.nargs = 1; 635 args.nreturns = 1; 636 args.phandle = HDL2CELL(phandle); 637 if (openfirmware(&args) == -1) 638 return 0; 639 return args.parent; 640} 641 642int 643OF_package_to_path(int phandle, char *buf, int buflen) 644{ 645 struct { 646 cell_t name; 647 cell_t nargs; 648 cell_t nreturns; 649 cell_t phandle; 650 cell_t buf; 651 cell_t buflen; 652 cell_t length; 653 } args; 654 655 if (buflen > PAGE_SIZE) 656 return -1; 657 args.name = ADR2CELL("package-to-path"); 658 args.nargs = 3; 659 args.nreturns = 1; 660 args.phandle = HDL2CELL(phandle); 661 args.buf = ADR2CELL(buf); 662 args.buflen = buflen; 663 if (openfirmware(&args) < 0) 664 return -1; 665 return args.length; 666} 667 668void 669putchar(int c) 670{ 671 char ch = c; 672 673 if (c == '\n') 674 putchar('\r'); 675 OF_write(stdout, &ch, 1); 676} 677 678int 679getchar(void) 680{ 681 unsigned char ch = '\0'; 682 int l; 683 684 while ((l = OF_read(stdin, &ch, 1)) != 1) 685 if (l != -2 && l != 0) 686 return -1; 687 return ch; 688} 689 690int 691cngetc(void) 692{ 693 return getchar(); 694} 695