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 * $FreeBSD$ 58 */ 59 60 #include <machine/stdarg.h> 61 62 #include "openfirm.h" 63 64 static int (*openfirmware)(void *); 65 static ihandle_t stdin; 66 static ihandle_t stdout; 67 68 /* Initialiaser */ 69 70 void 71 OF_init(int (*openfirm)(void *)) 72 { 73 openfirmware = openfirm; 74 } 75 76 /* 77 * Generic functions 78 */ 79 80 /* Test to see if a service exists. */ 81 int 82 OF_test(char *name) 83 { 84 static struct { 85 char *name; 86 int nargs; 87 int nreturns; 88 char *service; 89 int missing; 90 } args = { 91 "test", 92 1, 93 1, 94 }; 95 96 args.service = name; 97 if (openfirmware(&args) == -1) 98 return -1; 99 return args.missing; 100 } 101 102 /* Return firmware millisecond count. */ 103 int 104 OF_milliseconds() 105 { 106 static struct { 107 char *name; 108 int nargs; 109 int nreturns; 110 int ms; 111 } args = { 112 "milliseconds", 113 0, 114 1, 115 }; 116 117 openfirmware(&args); 118 return args.ms; 119 } 120 121 /* 122 * Device tree functions 123 */ 124 125 /* Return the next sibling of this node or 0. */ 126 phandle_t 127 OF_peer(phandle_t node) 128 { 129 static struct { 130 char *name; 131 int nargs; 132 int nreturns; 133 phandle_t node; 134 phandle_t next; 135 } args = { 136 "peer", 137 1, 138 1, 139 }; 140 141 args.node = node; 142 if (openfirmware(&args) == -1) 143 return -1; 144 return args.next; 145 } 146 147 /* Return the first child of this node or 0. */ 148 phandle_t 149 OF_child(phandle_t node) 150 { 151 static struct { 152 char *name; 153 int nargs; 154 int nreturns; 155 phandle_t node; 156 phandle_t child; 157 } args = { 158 "child", 159 1, 160 1, 161 }; 162 163 args.node = node; 164 if (openfirmware(&args) == -1) 165 return -1; 166 return args.child; 167 } 168 169 /* Return the parent of this node or 0. */ 170 phandle_t 171 OF_parent(phandle_t node) 172 { 173 static struct { 174 char *name; 175 int nargs; 176 int nreturns; 177 phandle_t node; 178 phandle_t parent; 179 } args = { 180 "parent", 181 1, 182 1, 183 }; 184 185 args.node = node; 186 if (openfirmware(&args) == -1) 187 return -1; 188 return args.parent; 189 } 190 191 /* Return the package handle that corresponds to an instance handle. */ 192 phandle_t 193 OF_instance_to_package(ihandle_t instance) 194 { 195 static struct { 196 char *name; 197 int nargs; 198 int nreturns; 199 ihandle_t instance; 200 phandle_t package; 201 } args = { 202 "instance-to-package", 203 1, 204 1, 205 }; 206 207 args.instance = instance; 208 if (openfirmware(&args) == -1) 209 return -1; 210 return args.package; 211 } 212 213 /* Get the length of a property of a package. */ 214 int 215 OF_getproplen(phandle_t package, char *propname) 216 { 217 static struct { 218 char *name; 219 int nargs; 220 int nreturns; 221 phandle_t package; 222 char *propname; 223 int proplen; 224 } args = { 225 "getproplen", 226 2, 227 1, 228 }; 229 230 args.package = package; 231 args.propname = propname; 232 if (openfirmware(&args) == -1) 233 return -1; 234 return args.proplen; 235 } 236 237 /* Get the value of a property of a package. */ 238 int 239 OF_getprop(phandle_t package, char *propname, void *buf, int buflen) 240 { 241 static struct { 242 char *name; 243 int nargs; 244 int nreturns; 245 phandle_t package; 246 char *propname; 247 void *buf; 248 int buflen; 249 int size; 250 } args = { 251 "getprop", 252 4, 253 1, 254 }; 255 256 args.package = package; 257 args.propname = propname; 258 args.buf = buf; 259 args.buflen = buflen; 260 if (openfirmware(&args) == -1) 261 return -1; 262 return args.size; 263 } 264 265 /* Get the next property of a package. */ 266 int 267 OF_nextprop(phandle_t package, char *previous, char *buf) 268 { 269 static struct { 270 char *name; 271 int nargs; 272 int nreturns; 273 phandle_t package; 274 char *previous; 275 char *buf; 276 int flag; 277 } args = { 278 "nextprop", 279 3, 280 1, 281 }; 282 283 args.package = package; 284 args.previous = previous; 285 args.buf = buf; 286 if (openfirmware(&args) == -1) 287 return -1; 288 return args.flag; 289 } 290 291 /* Set the value of a property of a package. */ 292 /* XXX Has a bug on FirePower */ 293 int 294 OF_setprop(phandle_t package, char *propname, void *buf, int len) 295 { 296 static struct { 297 char *name; 298 int nargs; 299 int nreturns; 300 phandle_t package; 301 char *propname; 302 void *buf; 303 int len; 304 int size; 305 } args = { 306 "setprop", 307 4, 308 1, 309 }; 310 311 args.package = package; 312 args.propname = propname; 313 args.buf = buf; 314 args.len = len; 315 if (openfirmware(&args) == -1) 316 return -1; 317 return args.size; 318 } 319 320 /* Convert a device specifier to a fully qualified pathname. */ 321 int 322 OF_canon(char *device, char *buf, int len) 323 { 324 static struct { 325 char *name; 326 int nargs; 327 int nreturns; 328 char *device; 329 char *buf; 330 int len; 331 int size; 332 } args = { 333 "canon", 334 3, 335 1, 336 }; 337 338 args.device = device; 339 args.buf = buf; 340 args.len = len; 341 if (openfirmware(&args) == -1) 342 return -1; 343 return args.size; 344 } 345 346 /* Return a package handle for the specified device. */ 347 phandle_t 348 OF_finddevice(char *device) 349 { 350 static struct { 351 char *name; 352 int nargs; 353 int nreturns; 354 char *device; 355 phandle_t package; 356 } args = { 357 "finddevice", 358 1, 359 1, 360 }; 361 362 args.device = device; 363 if (openfirmware(&args) == -1) 364 return -1; 365 return args.package; 366 } 367 368 /* Return the fully qualified pathname corresponding to an instance. */ 369 int 370 OF_instance_to_path(ihandle_t instance, char *buf, int len) 371 { 372 static struct { 373 char *name; 374 int nargs; 375 int nreturns; 376 ihandle_t instance; 377 char *buf; 378 int len; 379 int size; 380 } args = { 381 "instance-to-path", 382 3, 383 1, 384 }; 385 386 args.instance = instance; 387 args.buf = buf; 388 args.len = len; 389 if (openfirmware(&args) == -1) 390 return -1; 391 return(args.size); 392 } 393 394 /* Return the fully qualified pathname corresponding to a package. */ 395 int 396 OF_package_to_path(phandle_t package, char *buf, int len) 397 { 398 static struct { 399 char *name; 400 int nargs; 401 int nreturns; 402 phandle_t package; 403 char *buf; 404 int len; 405 int size; 406 } args = { 407 "package-to-path", 408 3, 409 1, 410 }; 411 412 args.package = package; 413 args.buf = buf; 414 args.len = len; 415 if (openfirmware(&args) == -1) 416 return -1; 417 return(args.size); 418 } 419 420 /* Call the method in the scope of a given instance. */ 421 int 422 OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...) 423 { 424 va_list ap; 425 static struct { 426 char *name; 427 int nargs; 428 int nreturns; 429 char *method; 430 ihandle_t instance; 431 int args_n_results[12]; 432 } args = { 433 "call-method", 434 2, 435 1, 436 }; 437 int *ip, n; 438 439 if (nargs > 6) 440 return -1; 441 args.nargs = nargs + 2; 442 args.nreturns = nreturns + 1; 443 args.method = method; 444 args.instance = instance; 445 va_start(ap, nreturns); 446 for (ip = args.args_n_results + (n = nargs); --n >= 0;) 447 *--ip = va_arg(ap, int); 448 449 if (openfirmware(&args) == -1) 450 return -1; 451 if (args.args_n_results[nargs]) 452 return args.args_n_results[nargs]; 453 for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) 454 *va_arg(ap, int *) = *--ip; 455 va_end(ap); 456 return 0; 457 } 458 459 /* 460 * Device I/O functions. 461 */ 462 463 /* Open an instance for a device. */ 464 ihandle_t 465 OF_open(char *device) 466 { 467 static struct { 468 char *name; 469 int nargs; 470 int nreturns; 471 char *device; 472 ihandle_t instance; 473 } args = { 474 "open", 475 1, 476 1, 477 }; 478 479 args.device = device; 480 if (openfirmware(&args) == -1 || args.instance == 0) { 481 return -1; 482 } 483 return args.instance; 484 } 485 486 /* Close an instance. */ 487 void 488 OF_close(ihandle_t instance) 489 { 490 static struct { 491 char *name; 492 int nargs; 493 int nreturns; 494 ihandle_t instance; 495 } args = { 496 "close", 497 1, 498 0, 499 }; 500 501 args.instance = instance; 502 openfirmware(&args); 503 } 504 505 /* Read from an instance. */ 506 int 507 OF_read(ihandle_t instance, void *addr, int len) 508 { 509 static struct { 510 char *name; 511 int nargs; 512 int nreturns; 513 ihandle_t instance; 514 void *addr; 515 int len; 516 int actual; 517 } args = { 518 "read", 519 3, 520 1, 521 }; 522 523 args.instance = instance; 524 args.addr = addr; 525 args.len = len; 526 if (openfirmware(&args) == -1) 527 return -1; 528 return args.actual; 529 } 530 531 /* Write to an instance. */ 532 int 533 OF_write(ihandle_t instance, void *addr, int len) 534 { 535 static struct { 536 char *name; 537 int nargs; 538 int nreturns; 539 ihandle_t instance; 540 void *addr; 541 int len; 542 int actual; 543 } args = { 544 "write", 545 3, 546 1, 547 }; 548 549 args.instance = instance; 550 args.addr = addr; 551 args.len = len; 552 if (openfirmware(&args) == -1) 553 return -1; 554 return args.actual; 555 } 556 557 /* Seek to a position. */ 558 int 559 OF_seek(ihandle_t instance, u_quad_t pos) 560 { 561 static struct { 562 char *name; 563 int nargs; 564 int nreturns; 565 ihandle_t instance; 566 int poshi; 567 int poslo; 568 int status; 569 } args = { 570 "seek", 571 3, 572 1, 573 }; 574 575 args.instance = instance; 576 args.poshi = (int)(pos >> 32); 577 args.poslo = (int)pos; 578 if (openfirmware(&args) == -1) 579 return -1; 580 return args.status; 581 } 582 583 /* 584 * Memory functions. 585 */ 586 587 /* Claim an area of memory. */ 588 void * 589 OF_claim(void *virt, u_int size, u_int align) 590 { 591 static struct { 592 char *name; 593 int nargs; 594 int nreturns; 595 void *virt; 596 u_int size; 597 u_int align; 598 void *baseaddr; 599 } args = { 600 "claim", 601 3, 602 1, 603 }; 604 605 args.virt = virt; 606 args.size = size; 607 args.align = align; 608 if (openfirmware(&args) == -1) 609 return (void *)-1; 610 return args.baseaddr; 611 } 612 613 /* Release an area of memory. */ 614 void 615 OF_release(void *virt, u_int size) 616 { 617 static struct { 618 char *name; 619 int nargs; 620 int nreturns; 621 void *virt; 622 u_int size; 623 } args = { 624 "release", 625 2, 626 0, 627 }; 628 629 args.virt = virt; 630 args.size = size; 631 openfirmware(&args); 632 } 633 634 /* 635 * Control transfer functions. 636 */ 637 638 /* Reset the system and call "boot <bootspec>". */ 639 void 640 OF_boot(char *bootspec) 641 { 642 static struct { 643 char *name; 644 int nargs; 645 int nreturns; 646 char *bootspec; 647 } args = { 648 "boot", 649 1, 650 0, 651 }; 652 653 args.bootspec = bootspec; 654 openfirmware(&args); 655 for (;;); /* just in case */ 656 } 657 658 /* Suspend and drop back to the OpenFirmware interface. */ 659 void 660 OF_enter() 661 { 662 static struct { 663 char *name; 664 int nargs; 665 int nreturns; 666 } args = { 667 "enter", 668 0, 669 0 670 }; 671 672 openfirmware(&args); 673 return; /* We may come back. */ 674 } 675 676 /* Shut down and drop back to the OpenFirmware interface. */ 677 __dead void 678 OF_exit() 679 { 680 static struct { 681 char *name; 682 int nargs; 683 int nreturns; 684 } args = { 685 "exit", 686 0, 687 0 688 }; 689 690 openfirmware(&args); 691 for (;;); /* just in case */ 692 } 693 694 /* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */ 695 #ifdef __notyet__ 696 void 697 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 698 { 699 static struct { 700 char *name; 701 int nargs; 702 int nreturns; 703 void *virt; 704 u_int size; 705 void (*entry)(); 706 void *arg; 707 u_int len; 708 } args = { 709 "chain", 710 5, 711 0, 712 }; 713 714 args.virt = virt; 715 args.size = size; 716 args.entry = entry; 717 args.arg = arg; 718 args.len = len; 719 openfirmware(&args); 720 } 721 #else 722 void 723 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 724 { 725 /* 726 * This is a REALLY dirty hack till the firmware gets this going 727 */ 728 #if 0 729 OF_release(virt, size); 730 #endif 731 entry(0, 0, openfirmware, arg, len); 732 } 733 #endif 734