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