1 /* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai 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 * Copyright (C) 2000 Benno Rice. 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 52 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 53 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 54 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 55 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 */ 57 58 #include <sys/cdefs.h> 59 __FBSDID("$FreeBSD$"); 60 61 #include <machine/stdarg.h> 62 63 #include <stand.h> 64 65 #include "openfirm.h" 66 67 int (*openfirmware)(void *); 68 69 phandle_t chosen; 70 ihandle_t mmu; 71 ihandle_t memory; 72 int real_mode = 0; 73 74 /* Initialiser */ 75 76 void 77 OF_init(int (*openfirm)(void *)) 78 { 79 phandle_t options; 80 char mode[sizeof("true")]; 81 82 openfirmware = openfirm; 83 84 if ((chosen = OF_finddevice("/chosen")) == -1) 85 OF_exit(); 86 if (OF_getprop(chosen, "memory", &memory, sizeof(memory)) == -1) { 87 memory = OF_open("/memory"); 88 if (memory == -1) 89 memory = OF_open("/memory@0"); 90 if (memory == -1) 91 OF_exit(); 92 } 93 if (OF_getprop(chosen, "mmu", &mmu, sizeof(mmu)) == -1) 94 OF_exit(); 95 96 /* 97 * Check if we run in real mode. If so, we do not need to map 98 * memory later on. 99 */ 100 options = OF_finddevice("/options"); 101 if (OF_getprop(options, "real-mode?", mode, sizeof(mode)) > 0 && 102 strcmp(mode, "true") == 0) 103 real_mode = 1; 104 } 105 106 /* 107 * Generic functions 108 */ 109 110 /* Test to see if a service exists. */ 111 int 112 OF_test(char *name) 113 { 114 static struct { 115 cell_t name; 116 cell_t nargs; 117 cell_t nreturns; 118 cell_t service; 119 cell_t missing; 120 } args = { 121 (cell_t)"test", 122 1, 123 1, 124 }; 125 126 args.service = (cell_t)name; 127 if (openfirmware(&args) == -1) 128 return (-1); 129 return (args.missing); 130 } 131 132 /* Return firmware millisecond count. */ 133 int 134 OF_milliseconds() 135 { 136 static struct { 137 cell_t name; 138 cell_t nargs; 139 cell_t nreturns; 140 cell_t ms; 141 } args = { 142 (cell_t)"milliseconds", 143 0, 144 1, 145 }; 146 147 openfirmware(&args); 148 return (args.ms); 149 } 150 151 /* 152 * Device tree functions 153 */ 154 155 /* Return the next sibling of this node or 0. */ 156 phandle_t 157 OF_peer(phandle_t node) 158 { 159 static struct { 160 cell_t name; 161 cell_t nargs; 162 cell_t nreturns; 163 cell_t node; 164 cell_t next; 165 } args = { 166 (cell_t)"peer", 167 1, 168 1, 169 }; 170 171 args.node = node; 172 if (openfirmware(&args) == -1) 173 return (-1); 174 return (args.next); 175 } 176 177 /* Return the first child of this node or 0. */ 178 phandle_t 179 OF_child(phandle_t node) 180 { 181 static struct { 182 cell_t name; 183 cell_t nargs; 184 cell_t nreturns; 185 cell_t node; 186 cell_t child; 187 } args = { 188 (cell_t)"child", 189 1, 190 1, 191 }; 192 193 args.node = node; 194 if (openfirmware(&args) == -1) 195 return (-1); 196 return (args.child); 197 } 198 199 /* Return the parent of this node or 0. */ 200 phandle_t 201 OF_parent(phandle_t node) 202 { 203 static struct { 204 cell_t name; 205 cell_t nargs; 206 cell_t nreturns; 207 cell_t node; 208 cell_t parent; 209 } args = { 210 (cell_t)"parent", 211 1, 212 1, 213 }; 214 215 args.node = node; 216 if (openfirmware(&args) == -1) 217 return (-1); 218 return (args.parent); 219 } 220 221 /* Return the package handle that corresponds to an instance handle. */ 222 phandle_t 223 OF_instance_to_package(ihandle_t instance) 224 { 225 static struct { 226 cell_t name; 227 cell_t nargs; 228 cell_t nreturns; 229 cell_t instance; 230 cell_t package; 231 } args = { 232 (cell_t)"instance-to-package", 233 1, 234 1, 235 }; 236 237 args.instance = instance; 238 if (openfirmware(&args) == -1) 239 return (-1); 240 return (args.package); 241 } 242 243 /* Get the length of a property of a package. */ 244 int 245 OF_getproplen(phandle_t package, const char *propname) 246 { 247 static struct { 248 cell_t name; 249 cell_t nargs; 250 cell_t nreturns; 251 cell_t package; 252 cell_t propname; 253 cell_t proplen; 254 } args = { 255 (cell_t)"getproplen", 256 2, 257 1, 258 }; 259 260 args.package = package; 261 args.propname = (cell_t)propname; 262 if (openfirmware(&args) == -1) 263 return (-1); 264 return (args.proplen); 265 } 266 267 /* Get the value of a property of a package. */ 268 int 269 OF_getprop(phandle_t package, const char *propname, void *buf, int buflen) 270 { 271 static struct { 272 cell_t name; 273 cell_t nargs; 274 cell_t nreturns; 275 cell_t package; 276 cell_t propname; 277 cell_t buf; 278 cell_t buflen; 279 cell_t size; 280 } args = { 281 (cell_t)"getprop", 282 4, 283 1, 284 }; 285 286 args.package = package; 287 args.propname = (cell_t)propname; 288 args.buf = (cell_t)buf; 289 args.buflen = buflen; 290 if (openfirmware(&args) == -1) 291 return (-1); 292 return (args.size); 293 } 294 295 /* Get the next property of a package. */ 296 int 297 OF_nextprop(phandle_t package, const char *previous, char *buf) 298 { 299 static struct { 300 cell_t name; 301 cell_t nargs; 302 cell_t nreturns; 303 cell_t package; 304 cell_t previous; 305 cell_t buf; 306 cell_t flag; 307 } args = { 308 (cell_t)"nextprop", 309 3, 310 1, 311 }; 312 313 args.package = package; 314 args.previous = (cell_t)previous; 315 args.buf = (cell_t)buf; 316 if (openfirmware(&args) == -1) 317 return (-1); 318 return (args.flag); 319 } 320 321 /* Set the value of a property of a package. */ 322 /* XXX Has a bug on FirePower */ 323 int 324 OF_setprop(phandle_t package, const char *propname, void *buf, int len) 325 { 326 static struct { 327 cell_t name; 328 cell_t nargs; 329 cell_t nreturns; 330 cell_t package; 331 cell_t propname; 332 cell_t buf; 333 cell_t len; 334 cell_t size; 335 } args = { 336 (cell_t)"setprop", 337 4, 338 1, 339 }; 340 341 args.package = package; 342 args.propname = (cell_t)propname; 343 args.buf = (cell_t)buf; 344 args.len = len; 345 if (openfirmware(&args) == -1) 346 return (-1); 347 return (args.size); 348 } 349 350 /* Convert a device specifier to a fully qualified pathname. */ 351 int 352 OF_canon(const char *device, char *buf, int len) 353 { 354 static struct { 355 cell_t name; 356 cell_t nargs; 357 cell_t nreturns; 358 cell_t device; 359 cell_t buf; 360 cell_t len; 361 cell_t size; 362 } args = { 363 (cell_t)"canon", 364 3, 365 1, 366 }; 367 368 args.device = (cell_t)device; 369 args.buf = (cell_t)buf; 370 args.len = len; 371 if (openfirmware(&args) == -1) 372 return (-1); 373 return (args.size); 374 } 375 376 /* Return a package handle for the specified device. */ 377 phandle_t 378 OF_finddevice(const char *device) 379 { 380 static struct { 381 cell_t name; 382 cell_t nargs; 383 cell_t nreturns; 384 cell_t device; 385 cell_t package; 386 } args = { 387 (cell_t)"finddevice", 388 1, 389 1, 390 }; 391 392 args.device = (cell_t)device; 393 if (openfirmware(&args) == -1) 394 return (-1); 395 return (args.package); 396 } 397 398 /* Return the fully qualified pathname corresponding to an instance. */ 399 int 400 OF_instance_to_path(ihandle_t instance, char *buf, int len) 401 { 402 static struct { 403 cell_t name; 404 cell_t nargs; 405 cell_t nreturns; 406 cell_t instance; 407 cell_t buf; 408 cell_t len; 409 cell_t size; 410 } args = { 411 (cell_t)"instance-to-path", 412 3, 413 1, 414 }; 415 416 args.instance = instance; 417 args.buf = (cell_t)buf; 418 args.len = len; 419 if (openfirmware(&args) == -1) 420 return (-1); 421 return (args.size); 422 } 423 424 /* Return the fully qualified pathname corresponding to a package. */ 425 int 426 OF_package_to_path(phandle_t package, char *buf, int len) 427 { 428 static struct { 429 cell_t name; 430 cell_t nargs; 431 cell_t nreturns; 432 cell_t package; 433 cell_t buf; 434 cell_t len; 435 cell_t size; 436 } args = { 437 (cell_t)"package-to-path", 438 3, 439 1, 440 }; 441 442 args.package = package; 443 args.buf = (cell_t)buf; 444 args.len = len; 445 if (openfirmware(&args) == -1) 446 return (-1); 447 return (args.size); 448 } 449 450 /* Call the method in the scope of a given instance. */ 451 int 452 OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...) 453 { 454 va_list ap; 455 static struct { 456 cell_t name; 457 cell_t nargs; 458 cell_t nreturns; 459 cell_t method; 460 cell_t instance; 461 cell_t args_n_results[12]; 462 } args = { 463 (cell_t)"call-method", 464 2, 465 1, 466 }; 467 cell_t *cp; 468 int n; 469 470 if (nargs > 6) 471 return (-1); 472 args.nargs = nargs + 2; 473 args.nreturns = nreturns + 1; 474 args.method = (cell_t)method; 475 args.instance = instance; 476 va_start(ap, nreturns); 477 for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;) 478 *--cp = va_arg(ap, cell_t); 479 if (openfirmware(&args) == -1) 480 return (-1); 481 if (args.args_n_results[nargs]) 482 return (args.args_n_results[nargs]); 483 for (cp = (cell_t *)(args.args_n_results + nargs + (n = args.nreturns)); 484 --n > 0;) 485 *va_arg(ap, cell_t *) = *--cp; 486 va_end(ap); 487 return (0); 488 } 489 490 /* 491 * Device I/O functions 492 */ 493 494 /* Open an instance for a device. */ 495 ihandle_t 496 OF_open(char *device) 497 { 498 static struct { 499 cell_t name; 500 cell_t nargs; 501 cell_t nreturns; 502 cell_t device; 503 cell_t instance; 504 } args = { 505 (cell_t)"open", 506 1, 507 1, 508 }; 509 510 args.device = (cell_t)device; 511 if (openfirmware(&args) == -1 || args.instance == 0) { 512 return (-1); 513 } 514 return (args.instance); 515 } 516 517 /* Close an instance. */ 518 void 519 OF_close(ihandle_t instance) 520 { 521 static struct { 522 cell_t name; 523 cell_t nargs; 524 cell_t nreturns; 525 cell_t instance; 526 } args = { 527 (cell_t)"close", 528 1, 529 }; 530 531 args.instance = instance; 532 openfirmware(&args); 533 } 534 535 /* Read from an instance. */ 536 int 537 OF_read(ihandle_t instance, void *addr, int len) 538 { 539 static struct { 540 cell_t name; 541 cell_t nargs; 542 cell_t nreturns; 543 cell_t instance; 544 cell_t addr; 545 cell_t len; 546 cell_t actual; 547 } args = { 548 (cell_t)"read", 549 3, 550 1, 551 }; 552 553 args.instance = instance; 554 args.addr = (cell_t)addr; 555 args.len = len; 556 557 #if defined(OPENFIRM_DEBUG) 558 printf("OF_read: called with instance=%08x, addr=%p, len=%d\n", 559 args.instance, args.addr, args.len); 560 #endif 561 562 if (openfirmware(&args) == -1) 563 return (-1); 564 565 #if defined(OPENFIRM_DEBUG) 566 printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n", 567 args.instance, args.addr, args.len, args.actual); 568 #endif 569 570 return (args.actual); 571 } 572 573 /* Write to an instance. */ 574 int 575 OF_write(ihandle_t instance, void *addr, int len) 576 { 577 static struct { 578 cell_t name; 579 cell_t nargs; 580 cell_t nreturns; 581 cell_t instance; 582 cell_t addr; 583 cell_t len; 584 cell_t actual; 585 } args = { 586 (cell_t)"write", 587 3, 588 1, 589 }; 590 591 args.instance = instance; 592 args.addr = (cell_t)addr; 593 args.len = len; 594 if (openfirmware(&args) == -1) 595 return (-1); 596 return (args.actual); 597 } 598 599 /* Seek to a position. */ 600 int 601 OF_seek(ihandle_t instance, uint64_t pos) 602 { 603 static struct { 604 cell_t name; 605 cell_t nargs; 606 cell_t nreturns; 607 cell_t instance; 608 cell_t poshi; 609 cell_t poslo; 610 cell_t status; 611 } args = { 612 (cell_t)"seek", 613 3, 614 1, 615 }; 616 617 args.instance = instance; 618 args.poshi = pos >> 32; 619 args.poslo = pos; 620 if (openfirmware(&args) == -1) 621 return (-1); 622 return (args.status); 623 } 624 625 /* Blocks. */ 626 unsigned int 627 OF_blocks(ihandle_t instance) 628 { 629 static struct { 630 cell_t name; 631 cell_t nargs; 632 cell_t nreturns; 633 cell_t instance; 634 cell_t result; 635 cell_t blocks; 636 } args = { 637 (cell_t)"#blocks", 638 2, 639 1, 640 }; 641 642 args.instance = instance; 643 if (openfirmware(&args) == -1) 644 return ((unsigned int)-1); 645 return (args.blocks); 646 } 647 648 /* Block size. */ 649 int 650 OF_block_size(ihandle_t instance) 651 { 652 static struct { 653 cell_t name; 654 cell_t nargs; 655 cell_t nreturns; 656 cell_t instance; 657 cell_t result; 658 cell_t size; 659 } args = { 660 (cell_t)"block-size", 661 2, 662 1, 663 }; 664 665 args.instance = instance; 666 if (openfirmware(&args) == -1) 667 return (512); 668 return (args.size); 669 } 670 671 /* 672 * Memory functions 673 */ 674 675 /* Claim an area of memory. */ 676 void * 677 OF_claim(void *virt, u_int size, u_int align) 678 { 679 static struct { 680 cell_t name; 681 cell_t nargs; 682 cell_t nreturns; 683 cell_t virt; 684 cell_t size; 685 cell_t align; 686 cell_t baseaddr; 687 } args = { 688 (cell_t)"claim", 689 3, 690 1, 691 }; 692 693 args.virt = (cell_t)virt; 694 args.size = size; 695 args.align = align; 696 if (openfirmware(&args) == -1) 697 return ((void *)-1); 698 return ((void *)args.baseaddr); 699 } 700 701 /* Release an area of memory. */ 702 void 703 OF_release(void *virt, u_int size) 704 { 705 static struct { 706 cell_t name; 707 cell_t nargs; 708 cell_t nreturns; 709 cell_t virt; 710 cell_t size; 711 } args = { 712 (cell_t)"release", 713 2, 714 }; 715 716 args.virt = (cell_t)virt; 717 args.size = size; 718 openfirmware(&args); 719 } 720 721 /* 722 * Control transfer functions 723 */ 724 725 /* Reset the system and call "boot <bootspec>". */ 726 void 727 OF_boot(char *bootspec) 728 { 729 static struct { 730 cell_t name; 731 cell_t nargs; 732 cell_t nreturns; 733 cell_t bootspec; 734 } args = { 735 (cell_t)"boot", 736 1, 737 }; 738 739 args.bootspec = (cell_t)bootspec; 740 openfirmware(&args); 741 for (;;) /* just in case */ 742 ; 743 } 744 745 /* Suspend and drop back to the Open Firmware interface. */ 746 void 747 OF_enter() 748 { 749 static struct { 750 cell_t name; 751 cell_t nargs; 752 cell_t nreturns; 753 } args = { 754 (cell_t)"enter", 755 }; 756 757 openfirmware(&args); 758 /* We may come back. */ 759 } 760 761 /* Shut down and drop back to the Open Firmware interface. */ 762 void 763 OF_exit() 764 { 765 static struct { 766 cell_t name; 767 cell_t nargs; 768 cell_t nreturns; 769 } args = { 770 (cell_t)"exit", 771 }; 772 773 openfirmware(&args); 774 for (;;) /* just in case */ 775 ; 776 } 777 778 void 779 OF_quiesce() 780 { 781 static struct { 782 cell_t name; 783 cell_t nargs; 784 cell_t nreturns; 785 } args = { 786 (cell_t)"quiesce", 787 }; 788 789 openfirmware(&args); 790 } 791 792 /* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */ 793 #if 0 794 void 795 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 796 { 797 static struct { 798 cell_t name; 799 cell_t nargs; 800 cell_t nreturns; 801 cell_t virt; 802 cell_t size; 803 cell_t entry; 804 cell_t arg; 805 cell_t len; 806 } args = { 807 (cell_t)"chain", 808 5, 809 }; 810 811 args.virt = (cell_t)virt; 812 args.size = size; 813 args.entry = (cell_t)entry; 814 args.arg = (cell_t)arg; 815 args.len = len; 816 openfirmware(&args); 817 } 818 #else 819 void 820 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 821 { 822 /* 823 * This is a REALLY dirty hack till the firmware gets this going 824 */ 825 #if 0 826 if (size > 0) 827 OF_release(virt, size); 828 #endif 829 entry(0, 0, openfirmware, arg, len); 830 } 831 #endif 832