1 /* $NetBSD: Locore.c,v 1.6 2005/12/11 12:19:08 christos 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 39 vaddr_t OF_claim_virt __P((vaddr_t vaddr, int len)); 40 vaddr_t OF_alloc_virt __P((int len, int align)); 41 int OF_free_virt __P((vaddr_t vaddr, int len)); 42 int OF_unmap_virt __P((vaddr_t vaddr, int len)); 43 vaddr_t OF_map_phys __P((paddr_t paddr, off_t size, vaddr_t vaddr, int mode)); 44 paddr_t OF_alloc_phys __P((int len, int align)); 45 paddr_t OF_claim_phys __P((paddr_t phys, int len)); 46 int OF_free_phys __P((paddr_t paddr, int len)); 47 48 extern int openfirmware(void *); 49 50 void setup __P((void)); 51 52 __dead void 53 _rtt() 54 { 55 struct { 56 cell_t name; 57 cell_t nargs; 58 cell_t nreturns; 59 } args; 60 61 args.name = ADR2CELL("exit"); 62 args.nargs = 0; 63 args.nreturns = 0; 64 openfirmware(&args); 65 while (1); /* just in case */ 66 } 67 68 void 69 OF_enter() 70 { 71 struct { 72 cell_t name; 73 cell_t nargs; 74 cell_t nreturns; 75 } args; 76 77 args.name = ADR2CELL("enter"); 78 args.nargs = 0; 79 args.nreturns = 0; 80 openfirmware(&args); 81 } 82 83 int 84 OF_finddevice(name) 85 const char *name; 86 { 87 struct { 88 cell_t name; 89 cell_t nargs; 90 cell_t nreturns; 91 cell_t device; 92 cell_t phandle; 93 } args; 94 95 args.name = ADR2CELL("finddevice"); 96 args.nargs = 1; 97 args.nreturns = 1; 98 args.device = ADR2CELL(name); 99 if (openfirmware(&args) == -1) 100 return -1; 101 return args.phandle; 102 } 103 104 int 105 OF_instance_to_package(ihandle) 106 int ihandle; 107 { 108 struct { 109 cell_t name; 110 cell_t nargs; 111 cell_t nreturns; 112 cell_t ihandle; 113 cell_t phandle; 114 } args; 115 116 args.name = ADR2CELL("instance-to-package"); 117 args.nargs = 1; 118 args.nreturns = 1; 119 args.ihandle = HDL2CELL(ihandle); 120 if (openfirmware(&args) == -1) 121 return -1; 122 return args.phandle; 123 } 124 125 int 126 OF_getprop(handle, prop, buf, buflen) 127 int handle; 128 const char *prop; 129 void *buf; 130 int buflen; 131 { 132 struct { 133 cell_t name; 134 cell_t nargs; 135 cell_t nreturns; 136 cell_t phandle; 137 cell_t prop; 138 cell_t buf; 139 cell_t buflen; 140 cell_t size; 141 } args; 142 143 args.name = ADR2CELL("getprop"); 144 args.nargs = 4; 145 args.nreturns = 1; 146 args.phandle = HDL2CELL(handle); 147 args.prop = ADR2CELL(prop); 148 args.buf = ADR2CELL(buf); 149 args.buflen = buflen; 150 if (openfirmware(&args) == -1) 151 return -1; 152 return args.size; 153 } 154 155 #ifdef __notyet__ /* Has a bug on FirePower */ 156 int 157 OF_setprop(handle, prop, buf, len) 158 u_int handle; 159 char *prop; 160 void *buf; 161 int len; 162 { 163 struct { 164 cell_t name; 165 cell_t nargs; 166 cell_t nreturns; 167 cell_t phandle; 168 cell_t prop; 169 cell_t buf; 170 cell_t len; 171 cell_t size; 172 } args; 173 174 args.name = ADR2CELL("setprop"); 175 args.nargs = 4; 176 args.nreturns = 1; 177 args.phandle = HDL2CELL(handle); 178 args.prop = ADR2CELL(prop); 179 args.buf = ADR2CELL(buf); 180 args.len = len; 181 if (openfirmware(&args) == -1) 182 return -1; 183 return args.size; 184 } 185 #endif 186 187 int 188 OF_open(dname) 189 const char *dname; 190 { 191 struct { 192 cell_t name; 193 cell_t nargs; 194 cell_t nreturns; 195 cell_t dname; 196 cell_t handle; 197 } args; 198 199 args.name = ADR2CELL("open"); 200 args.nargs = 1; 201 args.nreturns = 1; 202 args.dname = ADR2CELL(dname); 203 if (openfirmware(&args) == -1 || 204 args.handle == 0) 205 return -1; 206 return args.handle; 207 } 208 209 void 210 OF_close(handle) 211 int handle; 212 { 213 struct { 214 cell_t name; 215 cell_t nargs; 216 cell_t nreturns; 217 cell_t handle; 218 } args; 219 220 args.name = ADR2CELL("close"); 221 args.nargs = 1; 222 args.nreturns = 1; 223 args.handle = HDL2CELL(handle); 224 openfirmware(&args); 225 } 226 227 int 228 OF_write(handle, addr, len) 229 int handle; 230 const void *addr; 231 int len; 232 { 233 struct { 234 cell_t name; 235 cell_t nargs; 236 cell_t nreturns; 237 cell_t ihandle; 238 cell_t addr; 239 cell_t len; 240 cell_t actual; 241 } args; 242 243 args.name = ADR2CELL("write"); 244 args.nargs = 3; 245 args.nreturns = 1; 246 args.ihandle = HDL2CELL(handle); 247 args.addr = ADR2CELL(addr); 248 args.len = len; 249 if (openfirmware(&args) == -1) 250 return -1; 251 return args.actual; 252 } 253 254 int 255 OF_read(handle, addr, len) 256 int handle; 257 void *addr; 258 int len; 259 { 260 struct { 261 cell_t name; 262 cell_t nargs; 263 cell_t nreturns; 264 cell_t ihandle; 265 cell_t addr; 266 cell_t len; 267 cell_t actual; 268 } args; 269 270 args.name = ADR2CELL("read"); 271 args.nargs = 3; 272 args.nreturns = 1; 273 args.ihandle = HDL2CELL(handle); 274 args.addr = ADR2CELL(addr); 275 args.len = len; 276 if (openfirmware(&args) == -1) { 277 return -1; 278 } 279 return args.actual; 280 } 281 282 int 283 OF_seek(handle, pos) 284 int handle; 285 u_quad_t pos; 286 { 287 struct { 288 cell_t name; 289 cell_t nargs; 290 cell_t nreturns; 291 cell_t handle; 292 cell_t poshi; 293 cell_t poslo; 294 cell_t status; 295 } args; 296 297 args.name = ADR2CELL("seek"); 298 args.nargs = 3; 299 args.nreturns = 1; 300 args.handle = HDL2CELL(handle); 301 args.poshi = HDL2CELL(pos >> 32); 302 args.poslo = HDL2CELL(pos); 303 if (openfirmware(&args) == -1) { 304 return -1; 305 } 306 return args.status; 307 } 308 309 void 310 OF_release(virt, size) 311 void *virt; 312 u_int size; 313 { 314 struct { 315 cell_t name; 316 cell_t nargs; 317 cell_t nreturns; 318 cell_t virt; 319 cell_t size; 320 } args; 321 322 args.name = ADR2CELL("release"); 323 args.nargs = 2; 324 args.nreturns = 0; 325 args.virt = ADR2CELL(virt); 326 args.size = size; 327 openfirmware(&args); 328 } 329 330 int 331 OF_milliseconds() 332 { 333 struct { 334 cell_t name; 335 cell_t nargs; 336 cell_t nreturns; 337 cell_t ms; 338 } args; 339 340 args.name = ADR2CELL("milliseconds"); 341 args.nargs = 0; 342 args.nreturns = 1; 343 openfirmware(&args); 344 return args.ms; 345 } 346 347 void 348 OF_chain(virt, size, entry, arg, len) 349 void *virt; 350 u_int size; 351 void (*entry)(); 352 void *arg; 353 u_int len; 354 { 355 extern int64_t romp; 356 extern int debug; 357 struct { 358 cell_t name; 359 cell_t nargs; 360 cell_t nreturns; 361 cell_t virt; 362 cell_t size; 363 cell_t entry; 364 cell_t arg; 365 cell_t len; 366 } args; 367 368 args.name = ADR2CELL("chain"); 369 args.nargs = 5; 370 args.nreturns = 0; 371 args.virt = ADR2CELL(virt); 372 args.size = size; 373 args.entry = ADR2CELL(entry); 374 args.arg = ADR2CELL(arg); 375 args.len = len; 376 openfirmware(&args); 377 if (debug) { 378 printf("OF_chain: prom returned!\n"); 379 380 /* OK, firmware failed us. Try calling prog directly */ 381 printf("Calling entry(%p, %p, %x, %lx, %lx)\n", entry, arg, len, 382 (unsigned long)romp, (unsigned long)romp); 383 } 384 entry(0, arg, len, (unsigned long)romp, (unsigned long)romp); 385 panic("OF_chain: kernel returned!"); 386 __asm("ta 2" : :); 387 } 388 389 static u_int stdin; 390 static u_int stdout; 391 static u_int mmuh = -1; 392 static u_int memh = -1; 393 394 void 395 setup() 396 { 397 u_int chosen; 398 399 if ((chosen = OF_finddevice("/chosen")) == -1) 400 _rtt(); 401 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != sizeof(stdin) 402 || OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != sizeof(stdout) 403 || OF_getprop(chosen, "mmu", &mmuh, sizeof(mmuh)) != sizeof(mmuh) 404 || OF_getprop(chosen, "memory", &memh, sizeof(memh)) != sizeof(memh)) 405 _rtt(); 406 } 407 408 /* 409 * The following need either the handle to memory or the handle to the MMU. 410 */ 411 412 /* 413 * Grab some address space from the prom 414 * 415 * Only works while the prom is actively mapping us. 416 */ 417 vaddr_t 418 OF_claim_virt(vaddr, len) 419 vaddr_t vaddr; 420 int len; 421 { 422 struct { 423 cell_t name; 424 cell_t nargs; 425 cell_t nreturns; 426 cell_t method; 427 cell_t ihandle; 428 cell_t align; 429 cell_t len; 430 cell_t vaddr; 431 cell_t status; 432 cell_t retaddr; 433 } args; 434 435 #ifdef __notyet 436 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { 437 OF_printf("OF_claim_virt: cannot get mmuh\r\n"); 438 return -1LL; 439 } 440 #endif 441 args.name = ADR2CELL("call-method"); 442 args.nargs = 5; 443 args.nreturns = 2; 444 args.method = ADR2CELL("claim"); 445 args.ihandle = HDL2CELL(mmuh); 446 args.align = 0; 447 args.len = len; 448 args.vaddr = ADR2CELL(vaddr); 449 if(openfirmware(&args) != 0) 450 return -1LL; 451 return args.retaddr; /* Kluge till we go 64-bit */ 452 } 453 454 /* 455 * Request some address space from the prom 456 * 457 * Only works while the prom is actively mapping us. 458 */ 459 vaddr_t 460 OF_alloc_virt(len, align) 461 int len; 462 int align; 463 { 464 int retaddr=-1; 465 struct { 466 cell_t name; 467 cell_t nargs; 468 cell_t nreturns; 469 cell_t method; 470 cell_t ihandle; 471 cell_t align; 472 cell_t len; 473 cell_t status; 474 cell_t retaddr; 475 } args; 476 477 #ifdef __notyet 478 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { 479 OF_printf("OF_alloc_virt: cannot get mmuh\r\n"); 480 return -1LL; 481 } 482 #endif 483 args.name = ADR2CELL("call-method"); 484 args.nargs = 4; 485 args.nreturns = 2; 486 args.method = ADR2CELL("claim"); 487 args.ihandle = mmuh; 488 args.align = align; 489 args.len = len; 490 args.retaddr = ADR2CELL(&retaddr); 491 if(openfirmware(&args) != 0) 492 return -1LL; 493 return (vaddr_t)args.retaddr; /* Kluge till we go 64-bit */ 494 } 495 496 /* 497 * Release some address space to the prom 498 * 499 * Only works while the prom is actively mapping us. 500 */ 501 int 502 OF_free_virt(vaddr, len) 503 vaddr_t vaddr; 504 int len; 505 { 506 struct { 507 cell_t name; 508 cell_t nargs; 509 cell_t nreturns; 510 cell_t method; 511 cell_t ihandle; 512 cell_t len; 513 cell_t vaddr; 514 } args; 515 516 #ifdef __notyet 517 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { 518 OF_printf("OF_claim_virt: cannot get mmuh\r\n"); 519 return -1; 520 } 521 #endif 522 args.name = ADR2CELL("call-method"); 523 args.nargs = 4; 524 args.nreturns = 0; 525 args.method = ADR2CELL("release"); 526 args.ihandle = HDL2CELL(mmuh); 527 args.vaddr = ADR2CELL(vaddr); 528 args.len = len; 529 return openfirmware(&args); 530 } 531 532 533 /* 534 * Unmap some address space 535 * 536 * Only works while the prom is actively mapping us. 537 */ 538 int 539 OF_unmap_virt(vaddr, len) 540 vaddr_t vaddr; 541 int len; 542 { 543 struct { 544 cell_t name; 545 cell_t nargs; 546 cell_t nreturns; 547 cell_t method; 548 cell_t ihandle; 549 cell_t len; 550 cell_t vaddr; 551 } args; 552 553 #ifdef __notyet 554 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { 555 OF_printf("OF_claim_virt: cannot get mmuh\r\n"); 556 return -1; 557 } 558 #endif 559 args.name = ADR2CELL("call-method"); 560 args.nargs = 4; 561 args.nreturns = 0; 562 args.method = ADR2CELL("unmap"); 563 args.ihandle = HDL2CELL(mmuh); 564 args.vaddr = ADR2CELL(vaddr); 565 args.len = len; 566 return openfirmware(&args); 567 } 568 569 /* 570 * Have prom map in some memory 571 * 572 * Only works while the prom is actively mapping us. 573 */ 574 vaddr_t 575 OF_map_phys(paddr, size, vaddr, mode) 576 paddr_t paddr; 577 off_t size; 578 vaddr_t vaddr; 579 int mode; 580 { 581 struct { 582 cell_t name; 583 cell_t nargs; 584 cell_t nreturns; 585 cell_t method; 586 cell_t ihandle; 587 cell_t mode; 588 cell_t size; 589 cell_t vaddr; 590 cell_t paddr_hi; 591 cell_t paddr_lo; 592 cell_t status; 593 cell_t retaddr; 594 } args; 595 596 #ifdef __notyet 597 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) { 598 OF_printf("OF_map_phys: cannot get mmuh\r\n"); 599 return 0LL; 600 } 601 #endif 602 args.name = ADR2CELL("call-method"); 603 args.nargs = 7; 604 args.nreturns = 1; 605 args.method = ADR2CELL("map"); 606 args.ihandle = HDL2CELL(mmuh); 607 args.mode = mode; 608 args.size = size; 609 args.vaddr = ADR2CELL(vaddr); 610 args.paddr_hi = ADR2CELL(paddr>>32); 611 args.paddr_lo = ADR2CELL(paddr); 612 613 if (openfirmware(&args) == -1) 614 return -1; 615 if (args.status) 616 return -1; 617 return (vaddr_t)args.retaddr; 618 } 619 620 621 /* 622 * Request some RAM from the prom 623 * 624 * Only works while the prom is actively mapping us. 625 */ 626 paddr_t 627 OF_alloc_phys(len, align) 628 int len; 629 int align; 630 { 631 paddr_t paddr; 632 struct { 633 cell_t name; 634 cell_t nargs; 635 cell_t nreturns; 636 cell_t method; 637 cell_t ihandle; 638 cell_t align; 639 cell_t len; 640 cell_t status; 641 cell_t phys_hi; 642 cell_t phys_lo; 643 } args; 644 645 #ifdef __notyet 646 if (memh == -1 && ((memh = get_memory_handle()) == -1)) { 647 OF_printf("OF_alloc_phys: cannot get memh\r\n"); 648 return -1LL; 649 } 650 #endif 651 args.name = ADR2CELL("call-method"); 652 args.nargs = 4; 653 args.nreturns = 3; 654 args.method = ADR2CELL("claim"); 655 args.ihandle = HDL2CELL(memh); 656 args.align = align; 657 args.len = len; 658 if(openfirmware(&args) != 0) 659 return -1LL; 660 paddr = (paddr_t)(args.phys_hi<<32)|((unsigned int)(args.phys_lo)); 661 return paddr; /* Kluge till we go 64-bit */ 662 } 663 664 /* 665 * Request some specific RAM from the prom 666 * 667 * Only works while the prom is actively mapping us. 668 */ 669 paddr_t 670 OF_claim_phys(phys, len) 671 paddr_t phys; 672 int len; 673 { 674 paddr_t paddr; 675 struct { 676 cell_t name; 677 cell_t nargs; 678 cell_t nreturns; 679 cell_t method; 680 cell_t ihandle; 681 cell_t align; 682 cell_t len; 683 cell_t phys_hi; 684 cell_t phys_lo; 685 cell_t status; 686 cell_t res; 687 cell_t rphys_hi; 688 cell_t rphys_lo; 689 } args; 690 691 #ifdef __notyet 692 if (memh == -1 && ((memh = get_memory_handle()) == -1)) { 693 OF_printf("OF_alloc_phys: cannot get memh\r\n"); 694 return 0LL; 695 } 696 #endif 697 args.name = ADR2CELL("call-method"); 698 args.nargs = 6; 699 args.nreturns = 4; 700 args.method = ADR2CELL("claim"); 701 args.ihandle = HDL2CELL(memh); 702 args.align = 0; 703 args.len = len; 704 args.phys_hi = HDL2CELL(phys>>32); 705 args.phys_lo = HDL2CELL(phys); 706 if(openfirmware(&args) != 0) 707 return 0LL; 708 paddr = (paddr_t)(args.rphys_hi<<32)|((unsigned int)(args.rphys_lo)); 709 return paddr; 710 } 711 712 /* 713 * Free some RAM to prom 714 * 715 * Only works while the prom is actively mapping us. 716 */ 717 int 718 OF_free_phys(phys, len) 719 paddr_t phys; 720 int len; 721 { 722 struct { 723 cell_t name; 724 cell_t nargs; 725 cell_t nreturns; 726 cell_t method; 727 cell_t ihandle; 728 cell_t len; 729 cell_t phys_hi; 730 cell_t phys_lo; 731 } args; 732 733 #ifdef __notyet 734 if (memh == -1 && ((memh = get_memory_handle()) == -1)) { 735 OF_printf("OF_free_phys: cannot get memh\r\n"); 736 return -1; 737 } 738 #endif 739 args.name = ADR2CELL("call-method"); 740 args.nargs = 5; 741 args.nreturns = 0; 742 args.method = ADR2CELL("release"); 743 args.ihandle = HDL2CELL(memh); 744 args.len = len; 745 args.phys_hi = HDL2CELL(phys>>32); 746 args.phys_lo = HDL2CELL(phys); 747 return openfirmware(&args); 748 } 749 750 751 /* 752 * Claim virtual memory -- does not map it in. 753 */ 754 755 void * 756 OF_claim(virt, size, align) 757 void *virt; 758 u_int size; 759 u_int align; 760 { 761 #define SUNVMOF 762 #ifndef SUNVMOF 763 struct { 764 cell_t name; 765 cell_t nargs; 766 cell_t nreturns; 767 cell_t virt; 768 cell_t size; 769 cell_t align; 770 cell_t baseaddr; 771 } args; 772 773 774 args.name = ADR2CELL("claim"); 775 args.nargs = 3; 776 args.nreturns = 1; 777 args.virt = virt; 778 args.size = size; 779 args.align = align; 780 if (openfirmware(&args) == -1) 781 return (void *)-1; 782 return args.baseaddr; 783 #else 784 /* 785 * Sun Ultra machines run the firmware with VM enabled, 786 * so you need to handle allocating and mapping both 787 * virtual and physical memory. Ugh. 788 */ 789 790 paddr_t paddr; 791 void* newvirt = NULL; 792 793 if (virt == NULL) { 794 if ((virt = (void*)OF_alloc_virt(size, align)) == (void*)-1) { 795 printf("OF_alloc_virt(%d,%d) failed w/%x\n", size, align, virt); 796 return (void *)-1; 797 } 798 } else { 799 if ((newvirt = (void*)OF_claim_virt((vaddr_t)virt, size)) == (void*)-1) { 800 printf("OF_claim_virt(%x,%d) failed w/%x\n", virt, size, newvirt); 801 return (void *)-1; 802 } 803 } 804 if ((paddr = OF_alloc_phys(size, align)) == -1) { 805 printf("OF_alloc_phys(%d,%d) failed\n", size, align); 806 OF_free_virt((vaddr_t)virt, size); 807 return (void *)-1; 808 } 809 if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) { 810 printf("OF_map_phys(%x,%d,%x,%d) failed\n", paddr, size, virt, -1); 811 OF_free_phys((paddr_t)paddr, size); 812 OF_free_virt((vaddr_t)virt, size); 813 return (void *)-1; 814 } 815 return (void *)virt; 816 #endif 817 } 818 819 820 void 821 putchar(c) 822 int c; 823 { 824 char ch = c; 825 826 if (c == '\n') 827 putchar('\r'); 828 OF_write(stdout, &ch, 1); 829 } 830 831 int 832 getchar() 833 { 834 unsigned char ch = '\0'; 835 int l; 836 837 while ((l = OF_read(stdin, &ch, 1)) != 1) 838 if (l != -2 && l != 0) 839 return -1; 840 return ch; 841 } 842