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 --- 42 unchanged lines hidden (view full) --- 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: head/sys/dev/ofw/ofw_standard.c 186347 2008-12-20 00:33:10Z nwhitehorn $"); |
60 61#include <sys/param.h> 62#include <sys/kernel.h> 63#include <sys/malloc.h> 64#include <sys/systm.h> 65 66#include <machine/stdarg.h> 67 68#include <dev/ofw/openfirm.h> |
69#include <dev/ofw/ofwvar.h> 70#include "ofw_if.h" |
71 |
72static void ofw_std_init(ofw_t ofw, void *openfirm); 73static int ofw_std_test(ofw_t ofw, const char *name); 74static int ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns, 75 unsigned long *returns); 76static phandle_t ofw_std_peer(ofw_t ofw, phandle_t node); 77static phandle_t ofw_std_child(ofw_t ofw, phandle_t node); 78static phandle_t ofw_std_parent(ofw_t ofw, phandle_t node); 79static phandle_t ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance); 80static ssize_t ofw_std_getproplen(ofw_t ofw, phandle_t package, 81 const char *propname); 82static ssize_t ofw_std_getprop(ofw_t ofw, phandle_t package, 83 const char *propname, void *buf, size_t buflen); 84static int ofw_std_nextprop(ofw_t ofw, phandle_t package, const char *previous, 85 char *buf, size_t); 86static int ofw_std_setprop(ofw_t ofw, phandle_t package, char *propname, 87 void *buf, size_t len); 88static ssize_t ofw_std_canon(ofw_t ofw, const char *device, char *buf, 89 size_t len); 90static phandle_t ofw_std_finddevice(ofw_t ofw, const char *device); 91static ssize_t ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance, 92 char *buf, size_t len); 93static ssize_t ofw_std_package_to_path(ofw_t ofw, phandle_t package, char *buf, 94 size_t len); 95static int ofw_std_call_method(ofw_t ofw, ihandle_t instance, 96 const char *method, int nargs, int nreturns, 97 unsigned long *args_and_returns); 98static ihandle_t ofw_std_open(ofw_t ofw, const char *device); 99static void ofw_std_close(ofw_t ofw, ihandle_t instance); 100static ssize_t ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr, 101 size_t len); 102static ssize_t ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr, 103 size_t len); 104static int ofw_std_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos); 105static caddr_t ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align); 106static void ofw_std_release(ofw_t ofw, void *virt, size_t size); 107static void ofw_std_enter(ofw_t ofw); 108static void ofw_std_exit(ofw_t ofw); |
109 |
110static ofw_method_t ofw_std_methods[] = { 111 OFWMETHOD(ofw_init, ofw_std_init), 112 OFWMETHOD(ofw_peer, ofw_std_peer), 113 OFWMETHOD(ofw_child, ofw_std_child), 114 OFWMETHOD(ofw_parent, ofw_std_parent), 115 OFWMETHOD(ofw_instance_to_package, ofw_std_instance_to_package), 116 OFWMETHOD(ofw_getproplen, ofw_std_getproplen), 117 OFWMETHOD(ofw_getprop, ofw_std_getprop), 118 OFWMETHOD(ofw_nextprop, ofw_std_nextprop), 119 OFWMETHOD(ofw_setprop, ofw_std_setprop), 120 OFWMETHOD(ofw_canon, ofw_std_canon), 121 OFWMETHOD(ofw_finddevice, ofw_std_finddevice), 122 OFWMETHOD(ofw_instance_to_path, ofw_std_instance_to_path), 123 OFWMETHOD(ofw_package_to_path, ofw_std_package_to_path), |
124 |
125 OFWMETHOD(ofw_test, ofw_std_test), 126 OFWMETHOD(ofw_call_method, ofw_std_call_method), 127 OFWMETHOD(ofw_interpret, ofw_std_interpret), 128 OFWMETHOD(ofw_open, ofw_std_open), 129 OFWMETHOD(ofw_close, ofw_std_close), 130 OFWMETHOD(ofw_read, ofw_std_read), 131 OFWMETHOD(ofw_write, ofw_std_write), 132 OFWMETHOD(ofw_seek, ofw_std_seek), 133 OFWMETHOD(ofw_claim, ofw_std_claim), 134 OFWMETHOD(ofw_release, ofw_std_release), 135 OFWMETHOD(ofw_enter, ofw_std_enter), 136 OFWMETHOD(ofw_exit, ofw_std_exit), |
137 |
138 { 0, 0 } 139}; |
140 |
141static ofw_def_t ofw_std = { 142 OFW_STD_DIRECT, 143 ofw_std_methods, 144 0 145}; 146OFW_DEF(ofw_std); |
147 |
148static int (*openfirmware)(void *); |
149 |
150/* Initialiser */ 151 152static void 153ofw_std_init(ofw_t ofw, void *openfirm) 154{ 155 openfirmware = (int (*)(void *))openfirm; |
156} 157 158/* 159 * Generic functions 160 */ 161 162/* Test to see if a service exists. */ |
163static int 164ofw_std_test(ofw_t ofw, const char *name) |
165{ 166 static struct { 167 cell_t name; 168 cell_t nargs; 169 cell_t nreturns; 170 cell_t service; 171 cell_t missing; 172 } args = { 173 (cell_t)"test", 174 1, 175 1, 176 }; 177 178 args.service = (cell_t)name; 179 if (openfirmware(&args) == -1) 180 return (-1); 181 return (args.missing); 182} 183 |
184static int 185ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns, 186 unsigned long *returns) |
187{ |
188 static struct { 189 cell_t name; 190 cell_t nargs; 191 cell_t nreturns; 192 cell_t slot[16]; 193 } args = { 194 (cell_t)"interpret", 195 1, 196 }; 197 cell_t status; |
198 int i = 0, j = 0; |
199 |
200 args.nreturns = ++nreturns; 201 args.slot[i++] = (cell_t)cmd; |
202 if (openfirmware(&args) == -1) { |
203 return (-1); 204 } 205 status = args.slot[i++]; 206 while (i < 1 + nreturns) |
207 returns[j] = args.slot[i++]; |
208 return (status); 209} 210 |
211/* 212 * Device tree functions 213 */ 214 215/* Return the next sibling of this node or 0. */ |
216static phandle_t 217ofw_std_peer(ofw_t ofw, phandle_t node) |
218{ 219 static struct { 220 cell_t name; 221 cell_t nargs; 222 cell_t nreturns; 223 cell_t node; 224 cell_t next; 225 } args = { --- 4 unchanged lines hidden (view full) --- 230 231 args.node = node; 232 if (openfirmware(&args) == -1) 233 return (-1); 234 return (args.next); 235} 236 237/* Return the first child of this node or 0. */ |
238static phandle_t 239ofw_std_child(ofw_t ofw, phandle_t node) |
240{ 241 static struct { 242 cell_t name; 243 cell_t nargs; 244 cell_t nreturns; 245 cell_t node; 246 cell_t child; 247 } args = { --- 4 unchanged lines hidden (view full) --- 252 253 args.node = node; 254 if (openfirmware(&args) == -1) 255 return (-1); 256 return (args.child); 257} 258 259/* Return the parent of this node or 0. */ |
260static phandle_t 261ofw_std_parent(ofw_t ofw, phandle_t node) |
262{ 263 static struct { 264 cell_t name; 265 cell_t nargs; 266 cell_t nreturns; 267 cell_t node; 268 cell_t parent; 269 } args = { --- 4 unchanged lines hidden (view full) --- 274 275 args.node = node; 276 if (openfirmware(&args) == -1) 277 return (-1); 278 return (args.parent); 279} 280 281/* Return the package handle that corresponds to an instance handle. */ |
282static phandle_t 283ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance) |
284{ 285 static struct { 286 cell_t name; 287 cell_t nargs; 288 cell_t nreturns; 289 cell_t instance; 290 cell_t package; 291 } args = { --- 4 unchanged lines hidden (view full) --- 296 297 args.instance = instance; 298 if (openfirmware(&args) == -1) 299 return (-1); 300 return (args.package); 301} 302 303/* Get the length of a property of a package. */ |
304static ssize_t 305ofw_std_getproplen(ofw_t ofw, phandle_t package, const char *propname) |
306{ 307 static struct { 308 cell_t name; 309 cell_t nargs; 310 cell_t nreturns; 311 cell_t package; 312 cell_t propname; 313 cell_t proplen; --- 6 unchanged lines hidden (view full) --- 320 args.package = package; 321 args.propname = (cell_t)propname; 322 if (openfirmware(&args) == -1) 323 return (-1); 324 return (args.proplen); 325} 326 327/* Get the value of a property of a package. */ |
328static ssize_t 329ofw_std_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, 330 size_t buflen) |
331{ 332 static struct { 333 cell_t name; 334 cell_t nargs; 335 cell_t nreturns; 336 cell_t package; 337 cell_t propname; 338 cell_t buf; --- 9 unchanged lines hidden (view full) --- 348 args.propname = (cell_t)propname; 349 args.buf = (cell_t)buf; 350 args.buflen = buflen; 351 if (openfirmware(&args) == -1) 352 return (-1); 353 return (args.size); 354} 355 |
356/* Get the next property of a package. */ |
357static int 358ofw_std_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf, 359 size_t size) |
360{ 361 static struct { 362 cell_t name; 363 cell_t nargs; 364 cell_t nreturns; 365 cell_t package; 366 cell_t previous; 367 cell_t buf; --- 9 unchanged lines hidden (view full) --- 377 args.buf = (cell_t)buf; 378 if (openfirmware(&args) == -1) 379 return (-1); 380 return (args.flag); 381} 382 383/* Set the value of a property of a package. */ 384/* XXX Has a bug on FirePower */ |
385static int 386ofw_std_setprop(ofw_t ofw, phandle_t package, char *propname, void *buf, 387 size_t len) |
388{ 389 static struct { 390 cell_t name; 391 cell_t nargs; 392 cell_t nreturns; 393 cell_t package; 394 cell_t propname; 395 cell_t buf; --- 10 unchanged lines hidden (view full) --- 406 args.buf = (cell_t)buf; 407 args.len = len; 408 if (openfirmware(&args) == -1) 409 return (-1); 410 return (args.size); 411} 412 413/* Convert a device specifier to a fully qualified pathname. */ |
414static ssize_t 415ofw_std_canon(ofw_t ofw, const char *device, char *buf, size_t len) |
416{ 417 static struct { 418 cell_t name; 419 cell_t nargs; 420 cell_t nreturns; 421 cell_t device; 422 cell_t buf; 423 cell_t len; --- 8 unchanged lines hidden (view full) --- 432 args.buf = (cell_t)buf; 433 args.len = len; 434 if (openfirmware(&args) == -1) 435 return (-1); 436 return (args.size); 437} 438 439/* Return a package handle for the specified device. */ |
440static phandle_t 441ofw_std_finddevice(ofw_t ofw, const char *device) |
442{ 443 static struct { 444 cell_t name; 445 cell_t nargs; 446 cell_t nreturns; 447 cell_t device; 448 cell_t package; 449 } args = { --- 4 unchanged lines hidden (view full) --- 454 455 args.device = (cell_t)device; 456 if (openfirmware(&args) == -1) 457 return (-1); 458 return (args.package); 459} 460 461/* Return the fully qualified pathname corresponding to an instance. */ |
462static ssize_t 463ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) |
464{ 465 static struct { 466 cell_t name; 467 cell_t nargs; 468 cell_t nreturns; 469 cell_t instance; 470 cell_t buf; 471 cell_t len; --- 8 unchanged lines hidden (view full) --- 480 args.buf = (cell_t)buf; 481 args.len = len; 482 if (openfirmware(&args) == -1) 483 return (-1); 484 return (args.size); 485} 486 487/* Return the fully qualified pathname corresponding to a package. */ |
488static ssize_t 489ofw_std_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) |
490{ 491 static struct { 492 cell_t name; 493 cell_t nargs; 494 cell_t nreturns; 495 cell_t package; 496 cell_t buf; 497 cell_t len; --- 8 unchanged lines hidden (view full) --- 506 args.buf = (cell_t)buf; 507 args.len = len; 508 if (openfirmware(&args) == -1) 509 return (-1); 510 return (args.size); 511} 512 513/* Call the method in the scope of a given instance. */ |
514static int 515ofw_std_call_method(ofw_t ofw, ihandle_t instance, const char *method, 516 int nargs, int nreturns, unsigned long *args_and_returns) |
517{ |
518 static struct { 519 cell_t name; 520 cell_t nargs; 521 cell_t nreturns; 522 cell_t method; 523 cell_t instance; 524 cell_t args_n_results[12]; 525 } args = { 526 (cell_t)"call-method", 527 2, 528 1, 529 }; 530 cell_t *cp; |
531 unsigned long *ap; |
532 int n; 533 534 if (nargs > 6) 535 return (-1); 536 args.nargs = nargs + 2; 537 args.nreturns = nreturns + 1; 538 args.method = (cell_t)method; 539 args.instance = instance; |
540 541 ap = args_and_returns; |
542 for (cp = args.args_n_results + (n = nargs); --n >= 0;) |
543 *--cp = *(ap++); |
544 if (openfirmware(&args) == -1) 545 return (-1); 546 if (args.args_n_results[nargs]) 547 return (args.args_n_results[nargs]); 548 for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) |
549 *(ap++) = *--cp; |
550 return (0); 551} 552 553/* 554 * Device I/O functions 555 */ 556 557/* Open an instance for a device. */ |
558static ihandle_t 559ofw_std_open(ofw_t ofw, const char *device) |
560{ 561 static struct { 562 cell_t name; 563 cell_t nargs; 564 cell_t nreturns; 565 cell_t device; 566 cell_t instance; 567 } args = { --- 5 unchanged lines hidden (view full) --- 573 args.device = (cell_t)device; 574 if (openfirmware(&args) == -1 || args.instance == 0) { 575 return (-1); 576 } 577 return (args.instance); 578} 579 580/* Close an instance. */ |
581static void 582ofw_std_close(ofw_t ofw, ihandle_t instance) |
583{ 584 static struct { 585 cell_t name; 586 cell_t nargs; 587 cell_t nreturns; 588 cell_t instance; 589 } args = { 590 (cell_t)"close", 591 1, 592 }; 593 594 args.instance = instance; 595 openfirmware(&args); 596} 597 598/* Read from an instance. */ |
599static ssize_t 600ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) |
601{ 602 static struct { 603 cell_t name; 604 cell_t nargs; 605 cell_t nreturns; 606 cell_t instance; 607 cell_t addr; 608 cell_t len; --- 9 unchanged lines hidden (view full) --- 618 args.len = len; 619 if (openfirmware(&args) == -1) 620 return (-1); 621 622 return (args.actual); 623} 624 625/* Write to an instance. */ |
626static ssize_t 627ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) |
628{ 629 static struct { 630 cell_t name; 631 cell_t nargs; 632 cell_t nreturns; 633 cell_t instance; 634 cell_t addr; 635 cell_t len; --- 8 unchanged lines hidden (view full) --- 644 args.addr = (cell_t)addr; 645 args.len = len; 646 if (openfirmware(&args) == -1) 647 return (-1); 648 return (args.actual); 649} 650 651/* Seek to a position. */ |
652static int 653ofw_std_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) |
654{ 655 static struct { 656 cell_t name; 657 cell_t nargs; 658 cell_t nreturns; 659 cell_t instance; 660 cell_t poshi; 661 cell_t poslo; --- 12 unchanged lines hidden (view full) --- 674 return (args.status); 675} 676 677/* 678 * Memory functions 679 */ 680 681/* Claim an area of memory. */ |
682static caddr_t 683ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align) |
684{ 685 static struct { 686 cell_t name; 687 cell_t nargs; 688 cell_t nreturns; 689 cell_t virt; 690 cell_t size; 691 cell_t align; --- 8 unchanged lines hidden (view full) --- 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/* Release an area of memory. */ |
708static void 709ofw_std_release(ofw_t ofw, void *virt, size_t size) |
710{ 711 static struct { 712 cell_t name; 713 cell_t nargs; 714 cell_t nreturns; 715 cell_t virt; 716 cell_t size; 717 } args = { --- 5 unchanged lines hidden (view full) --- 723 args.size = size; 724 openfirmware(&args); 725} 726 727/* 728 * Control transfer functions 729 */ 730 |
731/* Suspend and drop back to the Open Firmware interface. */ |
732static void 733ofw_std_enter(ofw_t ofw) |
734{ 735 static struct { 736 cell_t name; 737 cell_t nargs; 738 cell_t nreturns; 739 } args = { 740 (cell_t)"enter", 741 }; 742 743 openfirmware(&args); 744 /* We may come back. */ 745} 746 747/* Shut down and drop back to the Open Firmware interface. */ |
748static void 749ofw_std_exit(ofw_t ofw) |
750{ 751 static struct { 752 cell_t name; 753 cell_t nargs; 754 cell_t nreturns; 755 } args = { 756 (cell_t)"exit", 757 }; 758 759 openfirmware(&args); 760 for (;;) /* just in case */ 761 ; 762} 763 |