1 /* $OpenBSD: Locore.c,v 1.16 2018/12/31 11:44:57 claudio 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 vaddr_t 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 vaddr_t 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 cell_t status; 456 cell_t retaddr; 457 } args; 458 459 args.name = ADR2CELL("call-method"); 460 args.nargs = 7; 461 args.nreturns = 1; 462 args.method = ADR2CELL("map"); 463 args.ihandle = HDL2CELL(mmuh); 464 args.mode = mode; 465 args.size = size; 466 args.vaddr = ADR2CELL(vaddr); 467 args.paddr_hi = HDQ2CELL_HI(paddr); 468 args.paddr_lo = HDQ2CELL_LO(paddr); 469 470 if (openfirmware(&args) == -1) 471 return -1; 472 if (args.status) 473 return -1; 474 return (vaddr_t)args.retaddr; 475 } 476 477 478 /* 479 * Request some RAM from the prom 480 * 481 * Only works while the prom is actively mapping us. 482 */ 483 static paddr_t 484 OF_alloc_phys(int len, int align) 485 { 486 struct { 487 cell_t name; 488 cell_t nargs; 489 cell_t nreturns; 490 cell_t method; 491 cell_t ihandle; 492 cell_t align; 493 cell_t len; 494 cell_t status; 495 cell_t phys_hi; 496 cell_t phys_lo; 497 } args; 498 499 args.name = ADR2CELL("call-method"); 500 args.nargs = 4; 501 args.nreturns = 3; 502 args.method = ADR2CELL("claim"); 503 args.ihandle = HDL2CELL(memh); 504 args.align = align; 505 args.len = len; 506 if (openfirmware(&args) != 0) 507 return -1LL; 508 return (paddr_t)CELL2HDQ(args.phys_hi, args.phys_lo); 509 } 510 511 512 /* 513 * Free some RAM to prom 514 * 515 * Only works while the prom is actively mapping us. 516 */ 517 static int 518 OF_free_phys(paddr_t phys, int len) 519 { 520 struct { 521 cell_t name; 522 cell_t nargs; 523 cell_t nreturns; 524 cell_t method; 525 cell_t ihandle; 526 cell_t len; 527 cell_t phys_hi; 528 cell_t phys_lo; 529 } args; 530 531 args.name = ADR2CELL("call-method"); 532 args.nargs = 5; 533 args.nreturns = 0; 534 args.method = ADR2CELL("release"); 535 args.ihandle = HDL2CELL(memh); 536 args.len = len; 537 args.phys_hi = HDQ2CELL_HI(phys); 538 args.phys_lo = HDQ2CELL_LO(phys); 539 return openfirmware(&args); 540 } 541 542 543 /* 544 * Claim virtual memory -- does not map it in. 545 */ 546 547 void * 548 OF_claim(void *virt, u_int size, u_int align) 549 { 550 /* 551 * Sun Ultra machines run the firmware with VM enabled, 552 * so you need to handle allocating and mapping both 553 * virtual and physical memory. Ugh. 554 */ 555 paddr_t paddr; 556 void * newvirt = NULL; 557 558 if (virt == NULL) { 559 virt = (void *)OF_alloc_virt(size, align); 560 if (virt == (void *)-1LL) { 561 printf("OF_alloc_virt(%d,%d) failed w/%x\n", 562 size, align, virt); 563 return virt; 564 } 565 } else { 566 newvirt = (void *)OF_claim_virt((vaddr_t)virt, size); 567 if (newvirt == (void *)-1LL) { 568 printf("OF_claim_virt(%x,%d) failed w/%x\n", 569 virt, size, newvirt); 570 return newvirt; 571 } 572 virt = newvirt; 573 } 574 if ((paddr = OF_alloc_phys(size, align)) == (paddr_t)-1LL) { 575 printf("OF_alloc_phys(%d,%d) failed\n", size, align); 576 OF_free_virt((vaddr_t)virt, size); 577 return (void *)-1LL; 578 } 579 if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) { 580 printf("OF_map_phys(%x,%d,%x,%d) failed\n", 581 paddr, size, virt, -1); 582 OF_free_phys((paddr_t)paddr, size); 583 OF_free_virt((vaddr_t)virt, size); 584 return (void *)-1LL; 585 } 586 return virt; 587 } 588 589 int 590 OF_peer(int phandle) 591 { 592 struct { 593 cell_t name; 594 cell_t nargs; 595 cell_t nreturns; 596 cell_t phandle; 597 cell_t sibling; 598 } args; 599 600 args.name = ADR2CELL("peer"); 601 args.nargs = 1; 602 args.nreturns = 1; 603 args.phandle = HDL2CELL(phandle); 604 if (openfirmware(&args) == -1) 605 return 0; 606 return args.sibling; 607 } 608 609 int 610 OF_child(int phandle) 611 { 612 struct { 613 cell_t name; 614 cell_t nargs; 615 cell_t nreturns; 616 cell_t phandle; 617 cell_t child; 618 } args; 619 620 args.name = ADR2CELL("child"); 621 args.nargs = 1; 622 args.nreturns = 1; 623 args.phandle = HDL2CELL(phandle); 624 if (openfirmware(&args) == -1) 625 return 0; 626 return args.child; 627 } 628 629 int 630 OF_parent(int phandle) 631 { 632 struct { 633 cell_t name; 634 cell_t nargs; 635 cell_t nreturns; 636 cell_t phandle; 637 cell_t parent; 638 } args; 639 640 args.name = ADR2CELL("parent"); 641 args.nargs = 1; 642 args.nreturns = 1; 643 args.phandle = HDL2CELL(phandle); 644 if (openfirmware(&args) == -1) 645 return 0; 646 return args.parent; 647 } 648 649 int 650 OF_package_to_path(int phandle, char *buf, int buflen) 651 { 652 struct { 653 cell_t name; 654 cell_t nargs; 655 cell_t nreturns; 656 cell_t phandle; 657 cell_t buf; 658 cell_t buflen; 659 cell_t length; 660 } args; 661 662 if (buflen > PAGE_SIZE) 663 return -1; 664 args.name = ADR2CELL("package-to-path"); 665 args.nargs = 3; 666 args.nreturns = 1; 667 args.phandle = HDL2CELL(phandle); 668 args.buf = ADR2CELL(buf); 669 args.buflen = buflen; 670 if (openfirmware(&args) < 0) 671 return -1; 672 return args.length; 673 } 674 675 void 676 putchar(int c) 677 { 678 char ch = c; 679 680 if (c == '\n') 681 putchar('\r'); 682 OF_write(stdout, &ch, 1); 683 } 684 685 int 686 getchar(void) 687 { 688 unsigned char ch = '\0'; 689 int l; 690 691 while ((l = OF_read(stdin, &ch, 1)) != 1) 692 if (l != -2 && l != 0) 693 return -1; 694 return ch; 695 } 696 697 int 698 cngetc(void) 699 { 700 return getchar(); 701 } 702