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 46 static vaddr_t OF_claim_virt(vaddr_t vaddr, int len); 47 static vaddr_t OF_alloc_virt(int len, int align); 48 static int OF_free_virt(vaddr_t vaddr, int len); 49 static int OF_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode); 50 static paddr_t OF_alloc_phys(int len, int align); 51 static int OF_free_phys(paddr_t paddr, int len); 52 53 extern int openfirmware(void *); 54 55 void 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 77 void 78 OF_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 92 int 93 OF_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 112 int 113 OF_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 132 int 133 OF_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 158 int 159 OF_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 179 void 180 OF_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 196 int 197 OF_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 220 int 221 OF_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 245 int 246 OF_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 270 void 271 OF_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 289 int 290 OF_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 306 void 307 OF_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 316 static u_int stdin; 317 static u_int stdout; 318 static u_int mmuh = -1; 319 static u_int memh = -1; 320 321 void 322 setup(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 */ 344 static vaddr_t 345 OF_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 */ 378 static vaddr_t 379 OF_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 */ 412 static int 413 OF_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 */ 441 static int 442 OF_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 */ 476 static paddr_t 477 OF_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 */ 510 static int 511 OF_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 540 void * 541 OF_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 582 int 583 OF_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 602 int 603 OF_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 622 int 623 OF_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 642 int 643 OF_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 668 void 669 putchar(int c) 670 { 671 char ch = c; 672 673 if (c == '\n') 674 putchar('\r'); 675 OF_write(stdout, &ch, 1); 676 } 677 678 int 679 getchar(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 690 int 691 cngetc(void) 692 { 693 return getchar(); 694 } 695