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.
|
61#include <machine/stdarg.h> 62 63#include <stand.h> 64 65#include "openfirm.h" 66 67int (*openfirmware)(void *); 68 69static ihandle_t stdin; 70static ihandle_t stdout; 71 72ihandle_t mmu; 73ihandle_t memory; 74 75/* Initialiaser */ 76 77void 78OF_init(int (*openfirm)(void *)) 79{ 80 phandle_t chosen; 81 82 openfirmware = openfirm; 83 84 chosen = OF_finddevice("/chosen"); 85 OF_getprop(chosen, "memory", &memory, sizeof(memory)); 86 if (memory == 0) 87 panic("failed to get memory ihandle"); 88 OF_getprop(chosen, "mmu", &mmu, sizeof(mmu)); 89 if (mmu == 0) 90 panic("failed to get mmu ihandle"); 91} 92 93/* 94 * Generic functions 95 */ 96 97/* Test to see if a service exists. */ 98int 99OF_test(char *name) 100{ 101 static struct { 102 cell_t name; 103 cell_t nargs; 104 cell_t nreturns; 105 cell_t service; 106 cell_t missing; 107 } args = { 108 (cell_t)"test", 109 1, 110 1, 111 0, 112 0 113 }; 114 115 args.service = (cell_t)name; 116 if (openfirmware(&args) == -1) 117 return -1; 118 return (int)args.missing; 119} 120 121/* Return firmware millisecond count. */ 122int 123OF_milliseconds() 124{ 125 static struct { 126 cell_t name; 127 cell_t nargs; 128 cell_t nreturns; 129 cell_t ms; 130 } args = { 131 (cell_t)"milliseconds", 132 0, 133 1, 134 0 135 }; 136 137 openfirmware(&args); 138 return (int)args.ms; 139} 140 141/* 142 * Device tree functions 143 */ 144 145/* Return the next sibling of this node or 0. */ 146phandle_t 147OF_peer(phandle_t node) 148{ 149 static struct { 150 cell_t name; 151 cell_t nargs; 152 cell_t nreturns; 153 cell_t node; 154 cell_t next; 155 } args = { 156 (cell_t)"peer", 157 1, 158 1, 159 0, 160 0 161 }; 162 163 args.node = (u_int)node; 164 if (openfirmware(&args) == -1) 165 return -1; 166 return (phandle_t)args.next; 167} 168 169/* Return the first child of this node or 0. */ 170phandle_t 171OF_child(phandle_t node) 172{ 173 static struct { 174 cell_t name; 175 cell_t nargs; 176 cell_t nreturns; 177 cell_t node; 178 cell_t child; 179 } args = { 180 (cell_t)"child", 181 1, 182 1, 183 0, 184 0 185 }; 186 187 args.node = (u_int)node; 188 if (openfirmware(&args) == -1) 189 return -1; 190 return (phandle_t)args.child; 191} 192 193/* Return the parent of this node or 0. */ 194phandle_t 195OF_parent(phandle_t node) 196{ 197 static struct { 198 cell_t name; 199 cell_t nargs; 200 cell_t nreturns; 201 cell_t node; 202 cell_t parent; 203 } args = { 204 (cell_t)"parent", 205 1, 206 1, 207 0, 208 0 209 }; 210 211 args.node = (u_int)node; 212 if (openfirmware(&args) == -1) 213 return -1; 214 return (phandle_t)args.parent; 215} 216 217/* Return the package handle that corresponds to an instance handle. */ 218phandle_t 219OF_instance_to_package(ihandle_t instance) 220{ 221 static struct { 222 cell_t name; 223 cell_t nargs; 224 cell_t nreturns; 225 cell_t instance; 226 cell_t package; 227 } args = { 228 (cell_t)"instance-to-package", 229 1, 230 1, 231 0, 232 0 233 }; 234 235 args.instance = (u_int)instance; 236 if (openfirmware(&args) == -1) 237 return -1; 238 return (phandle_t)args.package; 239} 240 241/* Get the length of a property of a package. */ 242int 243OF_getproplen(phandle_t package, char *propname) 244{ 245 static struct { 246 cell_t name; 247 cell_t nargs; 248 cell_t nreturns; 249 cell_t package; 250 cell_t propname; 251 cell_t proplen; 252 } args = { 253 (cell_t)"getproplen", 254 2, 255 1, 256 0, 257 0, 258 0 259 }; 260 261 args.package = (u_int)package; 262 args.propname = (cell_t)propname; 263 if (openfirmware(&args) == -1) 264 return -1; 265 return (int)args.proplen; 266} 267 268/* Get the value of a property of a package. */ 269int 270OF_getprop(phandle_t package, char *propname, void *buf, int buflen) 271{ 272 static struct { 273 cell_t name; 274 cell_t nargs; 275 cell_t nreturns; 276 cell_t package; 277 cell_t propname; 278 cell_t buf; 279 cell_t buflen; 280 cell_t size; 281 } args = { 282 (cell_t)"getprop", 283 4, 284 1, 285 0, 286 0, 287 0, 288 0, 289 0 290 }; 291 292 args.package = (u_int)package; 293 args.propname = (cell_t)propname; 294 args.buf = (cell_t)buf; 295 args.buflen = (u_int)buflen; 296 if (openfirmware(&args) == -1) 297 return -1; 298 return (int)args.size; 299} 300 301/* Get the next property of a package. */ 302int 303OF_nextprop(phandle_t package, char *previous, char *buf) 304{ 305 static struct { 306 cell_t name; 307 cell_t nargs; 308 cell_t nreturns; 309 cell_t package; 310 cell_t previous; 311 cell_t buf; 312 cell_t flag; 313 } args = { 314 (cell_t)"nextprop", 315 3, 316 1, 317 0, 318 0, 319 0, 320 0 321 }; 322 323 args.package = (u_int)package; 324 args.previous = (cell_t)previous; 325 args.buf = (cell_t)buf; 326 if (openfirmware(&args) == -1) 327 return -1; 328 return (int)args.flag; 329} 330 331/* Set the value of a property of a package. */ 332/* XXX Has a bug on FirePower */ 333int 334OF_setprop(phandle_t package, char *propname, void *buf, int len) 335{ 336 static struct { 337 cell_t name; 338 cell_t nargs; 339 cell_t nreturns; 340 cell_t package; 341 cell_t propname; 342 cell_t buf; 343 cell_t len; 344 cell_t size; 345 } args = { 346 (cell_t)"setprop", 347 4, 348 1, 349 0, 350 0, 351 0, 352 0, 353 0 354 }; 355 356 args.package = (u_int)package; 357 args.propname = (cell_t)propname; 358 args.buf = (cell_t)buf; 359 args.len = (u_int)len; 360 if (openfirmware(&args) == -1) 361 return -1; 362 return (int)args.size; 363} 364 365/* Convert a device specifier to a fully qualified pathname. */ 366int 367OF_canon(const char *device, char *buf, int len) 368{ 369 static struct { 370 cell_t name; 371 cell_t nargs; 372 cell_t nreturns; 373 cell_t device; 374 cell_t buf; 375 cell_t len; 376 cell_t size; 377 } args = { 378 (cell_t)"canon", 379 3, 380 1, 381 0, 382 0, 383 0, 384 0 385 }; 386 387 args.device = (cell_t)device; 388 args.buf = (cell_t)buf; 389 args.len = (cell_t)len; 390 if (openfirmware(&args) == -1) 391 return -1; 392 return (int)args.size; 393} 394 395/* Return a package handle for the specified device. */ 396phandle_t 397OF_finddevice(const char *device) 398{ 399 int i; 400 static struct { 401 cell_t name; 402 cell_t nargs; 403 cell_t nreturns; 404 cell_t device; 405 cell_t package; 406 } args = { 407 (cell_t)"finddevice", 408 1, 409 1, 410 0, 411 0 412 }; 413 414 args.device = (cell_t)device; 415 if (openfirmware(&args) == -1) 416 return -1; 417 418 return (phandle_t)args.package; 419} 420 421/* Return the fully qualified pathname corresponding to an instance. */ 422int 423OF_instance_to_path(ihandle_t instance, char *buf, int len) 424{ 425 static struct { 426 cell_t name; 427 cell_t nargs; 428 cell_t nreturns; 429 cell_t instance; 430 cell_t buf; 431 cell_t len; 432 cell_t size; 433 } args = { 434 (cell_t)"instance-to-path", 435 3, 436 1, 437 0, 438 0, 439 0, 440 0 441 }; 442 443 args.instance = (u_int)instance; 444 args.buf = (cell_t)buf; 445 args.len = (u_int)len; 446 if (openfirmware(&args) == -1) 447 return -1; 448 return (int)args.size; 449} 450 451/* Return the fully qualified pathname corresponding to a package. */ 452int 453OF_package_to_path(phandle_t package, char *buf, int len) 454{ 455 static struct { 456 cell_t name; 457 cell_t nargs; 458 cell_t nreturns; 459 cell_t package; 460 cell_t buf; 461 cell_t len; 462 cell_t size; 463 } args = { 464 (cell_t)"package-to-path", 465 3, 466 1, 467 0, 468 0, 469 0, 470 0 471 }; 472 473 args.package = (u_int)package; 474 args.buf = (cell_t)buf; 475 args.len = (u_int)len; 476 if (openfirmware(&args) == -1) 477 return -1; 478 return (int)args.size; 479} 480 481/* Call the method in the scope of a given instance. */ 482int 483OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...) 484{ 485 va_list ap; 486 static struct { 487 cell_t name; 488 cell_t nargs; 489 cell_t nreturns; 490 cell_t method; 491 cell_t instance; 492 cell_t args_n_results[12]; 493 } args = { 494 (cell_t)"call-method", 495 2, 496 1, 497 0, 498 0, 499 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 500 }; 501 int *ip, n; 502 503 if (nargs > 6) 504 return -1; 505 args.nargs = nargs + 2; 506 args.nreturns = nreturns + 1; 507 args.method = (cell_t)method; 508 args.instance = (u_int)instance; 509 va_start(ap, nreturns); 510 for (ip = (int *)(args.args_n_results + (n = nargs)); --n >= 0;) 511 *--ip = va_arg(ap, int); 512 513 if (openfirmware(&args) == -1) 514 return -1; 515 if (args.args_n_results[nargs]) 516 return (int)args.args_n_results[nargs]; 517 for (ip = (int *)(args.args_n_results + nargs + (n = args.nreturns)); 518 --n > 0;) 519 *va_arg(ap, int *) = *--ip; 520 va_end(ap); 521 return 0; 522} 523 524/* 525 * Device I/O functions. 526 */ 527 528/* Open an instance for a device. */ 529ihandle_t 530OF_open(char *device) 531{ 532 static struct { 533 cell_t name; 534 cell_t nargs; 535 cell_t nreturns; 536 cell_t device; 537 cell_t instance; 538 } args = { 539 (cell_t)"open", 540 1, 541 1, 542 0, 543 0 544 }; 545 546 args.device = (cell_t)device; 547 if (openfirmware(&args) == -1 || args.instance == 0) { 548 return -1; 549 } 550 return (ihandle_t)args.instance; 551} 552 553/* Close an instance. */ 554void 555OF_close(ihandle_t instance) 556{ 557 static struct { 558 cell_t name; 559 cell_t nargs; 560 cell_t nreturns; 561 cell_t instance; 562 } args = { 563 (cell_t)"close", 564 1, 565 0, 566 0 567 }; 568 569 args.instance = (u_int)instance; 570 openfirmware(&args); 571} 572 573/* Read from an instance. */ 574int 575OF_read(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)"read", 587 3, 588 1, 589 0, 590 0, 591 0, 592 0 593 }; 594 595 args.instance = (u_int)instance; 596 args.addr = (cell_t)addr; 597 args.len = (u_int)len; 598 599#if defined(OPENFIRM_DEBUG) 600 printf("OF_read: called with instance=%08x, addr=%p, len=%d\n", 601 args.instance, args.addr, args.len); 602#endif 603 604 if (openfirmware(&args) == -1) 605 return -1; 606 607#if defined(OPENFIRM_DEBUG) 608 printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n", 609 args.instance, args.addr, args.len, args.actual); 610#endif 611 612 return (int)args.actual; 613} 614 615/* Write to an instance. */ 616int 617OF_write(ihandle_t instance, void *addr, int len) 618{ 619 static struct { 620 cell_t name; 621 cell_t nargs; 622 cell_t nreturns; 623 cell_t instance; 624 cell_t addr; 625 cell_t len; 626 cell_t actual; 627 } args = { 628 (cell_t)"write", 629 3, 630 1, 631 0, 632 0, 633 0, 634 0 635 }; 636 637 args.instance = (u_int)instance; 638 args.addr = (cell_t)addr; 639 args.len = (u_int)len; 640 if (openfirmware(&args) == -1) 641 return -1; 642 return (int)args.actual; 643} 644 645/* Seek to a position. */ 646int 647OF_seek(ihandle_t instance, u_int64_t pos) 648{ 649 static struct { 650 cell_t name; 651 cell_t nargs; 652 cell_t nreturns; 653 cell_t instance; 654 cell_t poshi; 655 cell_t poslo; 656 cell_t status; 657 } args = { 658 (cell_t)"seek", 659 3, 660 1, 661 0, 662 0, 663 0, 664 0 665 }; 666 667 args.instance = (u_int)instance; 668 args.poshi = pos >> 32; 669 args.poslo = pos; 670 if (openfirmware(&args) == -1) 671 return -1; 672 return (int)args.status; 673} 674 675/* 676 * Memory functions. 677 */ 678 679/* Claim an area of memory. */ 680void * 681OF_claim(void *virt, u_int size, u_int align) 682{ 683 static struct { 684 cell_t name; 685 cell_t nargs; 686 cell_t nreturns; 687 cell_t virt; 688 cell_t size; 689 cell_t align; 690 cell_t baseaddr; 691 } args = { 692 (cell_t)"claim", 693 3, 694 1, 695 0, 696 0, 697 0, 698 0 699 }; 700 701 args.virt = (cell_t)virt; 702 args.size = size; 703 args.align = align; 704 if (openfirmware(&args) == -1) 705 return (void *)-1; 706 return (void *)args.baseaddr; 707} 708 709/* Allocate an area of physical memory */ 710vm_offset_t 711OF_claim_virt(vm_offset_t virt, size_t size, int align) 712{ 713 static struct { 714 cell_t name; 715 cell_t nargs; 716 cell_t nret; 717 cell_t method; 718 cell_t ihandle; 719 cell_t align; 720 cell_t size; 721 cell_t virt; 722 cell_t status; 723 cell_t ret; 724 } args = { 725 (cell_t)"call-method", 726 5, 727 2, 728 (cell_t)"claim", 729 0, 730 0, 731 0, 732 0, 733 0, /* ret */ 734 0, 735 }; 736 737 args.ihandle = mmu; 738 args.align = align; 739 args.size = size; 740 args.virt = virt; 741 742 if (openfirmware(&args) == -1) 743 return (vm_offset_t)-1; 744 745 return (vm_offset_t)args.ret; 746} 747 748/* Allocate an area of physical memory */ 749void * 750OF_alloc_phys(size_t size, int align) 751{ 752 static struct { 753 cell_t name; 754 cell_t nargs; 755 cell_t nret; 756 cell_t method; 757 cell_t ihandle; 758 cell_t align; 759 cell_t size; 760 cell_t status; 761 cell_t phys_hi; 762 cell_t phys_low; 763 } args = { 764 (cell_t)"call-method", 765 4, 766 3, 767 (cell_t)"claim", 768 0, 769 0, 770 0, 771 0, /* ret */ 772 0, 773 0, 774 }; 775 776 args.ihandle = memory; 777 args.size = size; 778 args.align = align; 779 780 if (openfirmware(&args) == -1) 781 return (void *)-1; 782 783 return (void *)(args.phys_hi << 32 | args.phys_low); 784} 785 786/* Release an area of memory. */ 787void 788OF_release(void *virt, u_int size) 789{ 790 static struct { 791 cell_t name; 792 cell_t nargs; 793 cell_t nreturns; 794 cell_t virt; 795 cell_t size; 796 } args = { 797 (cell_t)"release", 798 2, 799 0, 800 0, 801 0 802 }; 803 804 args.virt = (cell_t)virt; 805 args.size = size; 806 openfirmware(&args); 807} 808 809/* Release an area of physical memory. */ 810void 811OF_release_phys(vm_offset_t phys, u_int size) 812{ 813 static struct { 814 cell_t name; 815 cell_t nargs; 816 cell_t nret; 817 cell_t method; 818 cell_t ihandle; 819 cell_t size; 820 cell_t phys_hi; 821 cell_t phys_lo; 822 } args = { 823 (cell_t)"call-method", 824 5, 825 0, 826 (cell_t)"release", 827 0, 828 0, 829 0, 830 0 831 }; 832 833 args.ihandle = memory; 834 args.phys_hi = (u_int32_t)(phys >> 32); 835 args.phys_lo = (u_int32_t)phys; 836 args.size = size; 837 openfirmware(&args); 838} 839 840/* 841 * Control transfer functions. 842 */ 843 844/* Reset the system and call "boot <bootspec>". */ 845void 846OF_boot(char *bootspec) 847{ 848 static struct { 849 cell_t name; 850 cell_t nargs; 851 cell_t nreturns; 852 cell_t bootspec; 853 } args = { 854 (cell_t)"boot", 855 1, 856 0, 857 0 858 }; 859 860 args.bootspec = (cell_t)bootspec; 861 openfirmware(&args); 862 for (;;); /* just in case */ 863} 864 865/* Suspend and drop back to the OpenFirmware interface. */ 866void 867OF_enter() 868{ 869 static struct { 870 cell_t name; 871 cell_t nargs; 872 cell_t nreturns; 873 } args = { 874 (cell_t)"enter", 875 0, 876 0 877 }; 878 879 openfirmware(&args); 880} 881 882/* Shut down and drop back to the OpenFirmware interface. */ 883void 884OF_exit() 885{ 886 static struct { 887 cell_t name; 888 cell_t nargs; 889 cell_t nreturns; 890 } args = { 891 (cell_t)"exit", 892 0, 893 0 894 }; 895 896 openfirmware(&args); 897 for (;;); /* just in case */ 898} 899 900/* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */ 901#ifdef __notyet__ 902void 903OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 904{ 905 static struct { 906 cell_t name; 907 cell_t nargs; 908 cell_t nreturns; 909 cell_t virt; 910 cell_t size; 911 cell_t entry; 912 cell_t arg; 913 cell_t len; 914 } args = { 915 (cell_t)"chain", 916 5, 917 0, 918 0, 919 0, 920 0, 921 0, 922 0 923 }; 924 925 args.virt = (cell_t)virt; 926 args.size = size; 927 args.entry = (cell_t)entry; 928 args.arg = (cell_t)arg; 929 args.len = len; 930 openfirmware(&args); 931} 932#else 933void 934OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 935{ 936 /* 937 * This is a REALLY dirty hack till the firmware gets this going 938 */ 939 if (size > 0) 940 OF_release(virt, size); 941 942 entry(0, 0, openfirmware, arg, len); 943} 944#endif
|