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