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, 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, 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, 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, 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, u_int64_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 /* 626 * Memory functions 627 */ 628 629 /* Claim an area of memory. */ 630 void * 631 OF_claim(void *virt, u_int size, u_int align) 632 { 633 static struct { 634 cell_t name; 635 cell_t nargs; 636 cell_t nreturns; 637 cell_t virt; 638 cell_t size; 639 cell_t align; 640 cell_t baseaddr; 641 } args = { 642 (cell_t)"claim", 643 3, 644 1, 645 }; 646 647 args.virt = (cell_t)virt; 648 args.size = size; 649 args.align = align; 650 if (openfirmware(&args) == -1) 651 return ((void *)-1); 652 return ((void *)args.baseaddr); 653 } 654 655 /* Release an area of memory. */ 656 void 657 OF_release(void *virt, u_int size) 658 { 659 static struct { 660 cell_t name; 661 cell_t nargs; 662 cell_t nreturns; 663 cell_t virt; 664 cell_t size; 665 } args = { 666 (cell_t)"release", 667 2, 668 }; 669 670 args.virt = (cell_t)virt; 671 args.size = size; 672 openfirmware(&args); 673 } 674 675 /* 676 * Control transfer functions 677 */ 678 679 /* Reset the system and call "boot <bootspec>". */ 680 void 681 OF_boot(char *bootspec) 682 { 683 static struct { 684 cell_t name; 685 cell_t nargs; 686 cell_t nreturns; 687 cell_t bootspec; 688 } args = { 689 (cell_t)"boot", 690 1, 691 }; 692 693 args.bootspec = (cell_t)bootspec; 694 openfirmware(&args); 695 for (;;) /* just in case */ 696 ; 697 } 698 699 /* Suspend and drop back to the Open Firmware interface. */ 700 void 701 OF_enter() 702 { 703 static struct { 704 cell_t name; 705 cell_t nargs; 706 cell_t nreturns; 707 } args = { 708 (cell_t)"enter", 709 }; 710 711 openfirmware(&args); 712 /* We may come back. */ 713 } 714 715 /* Shut down and drop back to the Open Firmware interface. */ 716 void 717 OF_exit() 718 { 719 static struct { 720 cell_t name; 721 cell_t nargs; 722 cell_t nreturns; 723 } args = { 724 (cell_t)"exit", 725 }; 726 727 openfirmware(&args); 728 for (;;) /* just in case */ 729 ; 730 } 731 732 void 733 OF_quiesce() 734 { 735 static struct { 736 cell_t name; 737 cell_t nargs; 738 cell_t nreturns; 739 } args = { 740 (cell_t)"quiesce", 741 }; 742 743 openfirmware(&args); 744 } 745 746 /* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */ 747 #if 0 748 void 749 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 750 { 751 static struct { 752 cell_t name; 753 cell_t nargs; 754 cell_t nreturns; 755 cell_t virt; 756 cell_t size; 757 cell_t entry; 758 cell_t arg; 759 cell_t len; 760 } args = { 761 (cell_t)"chain", 762 5, 763 }; 764 765 args.virt = (cell_t)virt; 766 args.size = size; 767 args.entry = (cell_t)entry; 768 args.arg = (cell_t)arg; 769 args.len = len; 770 openfirmware(&args); 771 } 772 #else 773 void 774 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 775 { 776 /* 777 * This is a REALLY dirty hack till the firmware gets this going 778 */ 779 #if 0 780 if (size > 0) 781 OF_release(virt, size); 782 #endif 783 entry(0, 0, openfirmware, arg, len); 784 } 785 #endif 786