ofw_real.c revision 208614
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: head/sys/powerpc/ofw/ofw_real.c 208614 2010-05-28 10:43:56Z raj $"); 60 61#include <sys/param.h> 62#include <sys/kernel.h> 63#include <sys/lock.h> 64#include <sys/mutex.h> 65#include <sys/systm.h> 66 67#include <vm/vm.h> 68#include <vm/pmap.h> 69 70#include <machine/stdarg.h> 71#include <machine/bus.h> 72#include <machine/pmap.h> 73#include <machine/ofw_machdep.h> 74 75#include <dev/ofw/openfirm.h> 76#include <dev/ofw/ofwvar.h> 77#include "ofw_if.h" 78 79static int ofw_real_init(ofw_t, void *openfirm); 80static int ofw_real_test(ofw_t, const char *name); 81static phandle_t ofw_real_peer(ofw_t, phandle_t node); 82static phandle_t ofw_real_child(ofw_t, phandle_t node); 83static phandle_t ofw_real_parent(ofw_t, phandle_t node); 84static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance); 85static ssize_t ofw_real_getproplen(ofw_t, phandle_t package, 86 const char *propname); 87static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname, 88 void *buf, size_t buflen); 89static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous, 90 char *buf, size_t); 91static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname, 92 const void *buf, size_t len); 93static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len); 94static phandle_t ofw_real_finddevice(ofw_t, const char *device); 95static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf, 96 size_t len); 97static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf, 98 size_t len); 99static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method, 100 int nargs, int nreturns, unsigned long *args_and_returns); 101static ihandle_t ofw_real_open(ofw_t, const char *device); 102static void ofw_real_close(ofw_t, ihandle_t instance); 103static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len); 104static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr, 105 size_t len); 106static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos); 107static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align); 108static void ofw_real_release(ofw_t, void *virt, size_t size); 109static void ofw_real_enter(ofw_t); 110static void ofw_real_exit(ofw_t); 111 112static ofw_method_t ofw_real_methods[] = { 113 OFWMETHOD(ofw_init, ofw_real_init), 114 OFWMETHOD(ofw_peer, ofw_real_peer), 115 OFWMETHOD(ofw_child, ofw_real_child), 116 OFWMETHOD(ofw_parent, ofw_real_parent), 117 OFWMETHOD(ofw_instance_to_package, ofw_real_instance_to_package), 118 OFWMETHOD(ofw_getproplen, ofw_real_getproplen), 119 OFWMETHOD(ofw_getprop, ofw_real_getprop), 120 OFWMETHOD(ofw_nextprop, ofw_real_nextprop), 121 OFWMETHOD(ofw_setprop, ofw_real_setprop), 122 OFWMETHOD(ofw_canon, ofw_real_canon), 123 OFWMETHOD(ofw_finddevice, ofw_real_finddevice), 124 OFWMETHOD(ofw_instance_to_path, ofw_real_instance_to_path), 125 OFWMETHOD(ofw_package_to_path, ofw_real_package_to_path), 126 127 OFWMETHOD(ofw_test, ofw_real_test), 128 OFWMETHOD(ofw_call_method, ofw_real_call_method), 129 OFWMETHOD(ofw_open, ofw_real_open), 130 OFWMETHOD(ofw_close, ofw_real_close), 131 OFWMETHOD(ofw_read, ofw_real_read), 132 OFWMETHOD(ofw_write, ofw_real_write), 133 OFWMETHOD(ofw_seek, ofw_real_seek), 134 OFWMETHOD(ofw_claim, ofw_real_claim), 135 OFWMETHOD(ofw_release, ofw_real_release), 136 OFWMETHOD(ofw_enter, ofw_real_enter), 137 OFWMETHOD(ofw_exit, ofw_real_exit), 138 139 { 0, 0 } 140}; 141 142static ofw_def_t ofw_real = { 143 OFW_STD_REAL, 144 ofw_real_methods, 145 0 146}; 147OFW_DEF(ofw_real); 148 149MALLOC_DEFINE(M_OFWREAL, "ofwreal", "Open Firmware Real Mode Bounce Page"); 150 151static int (*openfirmware)(void *); 152 153static vm_offset_t of_bounce_phys; 154static caddr_t of_bounce_virt; 155static off_t of_bounce_offset; 156static size_t of_bounce_size; 157static struct mtx of_bounce_mtx; 158 159/* 160 * After the VM is up, allocate a wired, low memory bounce page. 161 */ 162 163static void ofw_real_bounce_alloc(void *); 164 165SYSINIT(ofw_real_bounce_alloc, SI_SUB_VM, SI_ORDER_ANY, 166 ofw_real_bounce_alloc, NULL); 167 168static void 169ofw_real_start(void) 170{ 171 mtx_lock(&of_bounce_mtx); 172 of_bounce_offset = 0; 173} 174 175static void 176ofw_real_stop(void) 177{ 178 mtx_unlock(&of_bounce_mtx); 179} 180 181static void 182ofw_real_bounce_alloc(void *junk) 183{ 184 /* 185 * Check that ofw_real is actually in use before allocating wads 186 * of memory. Do this by checking if our mutex has been set up. 187 */ 188 if (!mtx_initialized(&of_bounce_mtx)) 189 return; 190 191 /* 192 * Allocate a page of contiguous, wired physical memory that can 193 * fit into a 32-bit address space. 194 */ 195 196 mtx_lock(&of_bounce_mtx); 197 198 of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0, 199 0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE); 200 of_bounce_phys = vtophys(of_bounce_virt); 201 of_bounce_size = PAGE_SIZE; 202 203 mtx_unlock(&of_bounce_mtx); 204} 205 206static cell_t 207ofw_real_map(const void *buf, size_t len) 208{ 209 cell_t phys; 210 211 mtx_assert(&of_bounce_mtx, MA_OWNED); 212 213 if (of_bounce_virt == NULL) { 214 if (!pmap_bootstrapped) 215 return (cell_t)buf; 216 217 /* 218 * XXX: It is possible for us to get called before the VM has 219 * come online, but after the MMU is up. We don't have the 220 * bounce buffer yet, but can no longer presume a 1:1 mapping. 221 * Grab the physical address of the buffer, and hope it is 222 * in range if this happens. 223 */ 224 return (cell_t)vtophys(buf); 225 } 226 227 /* 228 * Make sure the bounce page offset satisfies any reasonable 229 * alignment constraint. 230 */ 231 of_bounce_offset += of_bounce_offset % sizeof(register_t); 232 233 if (of_bounce_offset + len > of_bounce_size) { 234 panic("Oversize Open Firmware call!"); 235 return 0; 236 } 237 238 memcpy(of_bounce_virt + of_bounce_offset, buf, len); 239 phys = of_bounce_phys + of_bounce_offset; 240 241 of_bounce_offset += len; 242 243 return phys; 244} 245 246static void 247ofw_real_unmap(cell_t physaddr, void *buf, size_t len) 248{ 249 mtx_assert(&of_bounce_mtx, MA_OWNED); 250 251 if (of_bounce_virt == NULL) 252 return; 253 254 memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len); 255} 256 257/* Initialiser */ 258 259static int 260ofw_real_init(ofw_t ofw, void *openfirm) 261{ 262 openfirmware = (int (*)(void *))openfirm; 263 264 mtx_init(&of_bounce_mtx, "OF Bounce Page", MTX_DEF, 0); 265 of_bounce_virt = NULL; 266 return (0); 267} 268 269/* 270 * Generic functions 271 */ 272 273/* Test to see if a service exists. */ 274static int 275ofw_real_test(ofw_t ofw, const char *name) 276{ 277 struct { 278 cell_t name; 279 cell_t nargs; 280 cell_t nreturns; 281 cell_t service; 282 cell_t missing; 283 } args = { 284 (cell_t)"test", 285 1, 286 1, 287 }; 288 289 ofw_real_start(); 290 291 args.service = ofw_real_map(name, strlen(name) + 1); 292 if (args.service == 0 || openfirmware(&args) == -1) { 293 ofw_real_stop(); 294 return (-1); 295 } 296 ofw_real_stop(); 297 return (args.missing); 298} 299 300/* 301 * Device tree functions 302 */ 303 304/* Return the next sibling of this node or 0. */ 305static phandle_t 306ofw_real_peer(ofw_t ofw, phandle_t node) 307{ 308 struct { 309 cell_t name; 310 cell_t nargs; 311 cell_t nreturns; 312 cell_t node; 313 cell_t next; 314 } args = { 315 (cell_t)"peer", 316 1, 317 1, 318 }; 319 320 args.node = node; 321 if (openfirmware(&args) == -1) 322 return (-1); 323 return (args.next); 324} 325 326/* Return the first child of this node or 0. */ 327static phandle_t 328ofw_real_child(ofw_t ofw, phandle_t node) 329{ 330 struct { 331 cell_t name; 332 cell_t nargs; 333 cell_t nreturns; 334 cell_t node; 335 cell_t child; 336 } args = { 337 (cell_t)"child", 338 1, 339 1, 340 }; 341 342 args.node = node; 343 if (openfirmware(&args) == -1) 344 return (-1); 345 return (args.child); 346} 347 348/* Return the parent of this node or 0. */ 349static phandle_t 350ofw_real_parent(ofw_t ofw, phandle_t node) 351{ 352 struct { 353 cell_t name; 354 cell_t nargs; 355 cell_t nreturns; 356 cell_t node; 357 cell_t parent; 358 } args = { 359 (cell_t)"parent", 360 1, 361 1, 362 }; 363 364 args.node = node; 365 if (openfirmware(&args) == -1) 366 return (-1); 367 return (args.parent); 368} 369 370/* Return the package handle that corresponds to an instance handle. */ 371static phandle_t 372ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance) 373{ 374 struct { 375 cell_t name; 376 cell_t nargs; 377 cell_t nreturns; 378 cell_t instance; 379 cell_t package; 380 } args = { 381 (cell_t)"instance-to-package", 382 1, 383 1, 384 }; 385 386 args.instance = instance; 387 if (openfirmware(&args) == -1) 388 return (-1); 389 return (args.package); 390} 391 392/* Get the length of a property of a package. */ 393static ssize_t 394ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname) 395{ 396 struct { 397 cell_t name; 398 cell_t nargs; 399 cell_t nreturns; 400 cell_t package; 401 cell_t propname; 402 cell_t proplen; 403 } args = { 404 (cell_t)"getproplen", 405 2, 406 1, 407 }; 408 409 ofw_real_start(); 410 411 args.package = package; 412 args.propname = ofw_real_map(propname, strlen(propname) + 1); 413 if (args.propname == 0 || openfirmware(&args) == -1) { 414 ofw_real_stop(); 415 return (-1); 416 } 417 ofw_real_stop(); 418 return (args.proplen); 419} 420 421/* Get the value of a property of a package. */ 422static ssize_t 423ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, 424 size_t buflen) 425{ 426 struct { 427 cell_t name; 428 cell_t nargs; 429 cell_t nreturns; 430 cell_t package; 431 cell_t propname; 432 cell_t buf; 433 cell_t buflen; 434 cell_t size; 435 } args = { 436 (cell_t)"getprop", 437 4, 438 1, 439 }; 440 441 ofw_real_start(); 442 443 args.package = package; 444 args.propname = ofw_real_map(propname, strlen(propname) + 1); 445 args.buf = ofw_real_map(buf, buflen); 446 args.buflen = buflen; 447 if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) { 448 ofw_real_stop(); 449 return (-1); 450 } 451 ofw_real_unmap(args.buf, buf, buflen); 452 453 ofw_real_stop(); 454 return (args.size); 455} 456 457/* Get the next property of a package. */ 458static int 459ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous, 460 char *buf, size_t size) 461{ 462 struct { 463 cell_t name; 464 cell_t nargs; 465 cell_t nreturns; 466 cell_t package; 467 cell_t previous; 468 cell_t buf; 469 cell_t flag; 470 } args = { 471 (cell_t)"nextprop", 472 3, 473 1, 474 }; 475 476 ofw_real_start(); 477 478 args.package = package; 479 args.previous = ofw_real_map(previous, strlen(previous) + 1); 480 args.buf = ofw_real_map(buf, size); 481 if (args.previous == 0 || args.buf == 0 || openfirmware(&args) == -1) { 482 ofw_real_stop(); 483 return (-1); 484 } 485 ofw_real_unmap(args.buf, buf, size); 486 487 ofw_real_stop(); 488 return (args.flag); 489} 490 491/* Set the value of a property of a package. */ 492/* XXX Has a bug on FirePower */ 493static int 494ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname, 495 const void *buf, size_t len) 496{ 497 struct { 498 cell_t name; 499 cell_t nargs; 500 cell_t nreturns; 501 cell_t package; 502 cell_t propname; 503 cell_t buf; 504 cell_t len; 505 cell_t size; 506 } args = { 507 (cell_t)"setprop", 508 4, 509 1, 510 }; 511 512 ofw_real_start(); 513 514 args.package = package; 515 args.propname = ofw_real_map(propname, strlen(propname) + 1); 516 args.buf = ofw_real_map(buf, len); 517 args.len = len; 518 if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) { 519 ofw_real_stop(); 520 return (-1); 521 } 522 ofw_real_stop(); 523 return (args.size); 524} 525 526/* Convert a device specifier to a fully qualified pathname. */ 527static ssize_t 528ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len) 529{ 530 struct { 531 cell_t name; 532 cell_t nargs; 533 cell_t nreturns; 534 cell_t device; 535 cell_t buf; 536 cell_t len; 537 cell_t size; 538 } args = { 539 (cell_t)"canon", 540 3, 541 1, 542 }; 543 544 ofw_real_start(); 545 546 args.device = ofw_real_map(device, strlen(device) + 1); 547 args.buf = ofw_real_map(buf, len); 548 args.len = len; 549 if (args.device == 0 || args.buf == 0 || openfirmware(&args) == -1) { 550 ofw_real_stop(); 551 return (-1); 552 } 553 ofw_real_unmap(args.buf, buf, len); 554 555 ofw_real_stop(); 556 return (args.size); 557} 558 559/* Return a package handle for the specified device. */ 560static phandle_t 561ofw_real_finddevice(ofw_t ofw, const char *device) 562{ 563 struct { 564 cell_t name; 565 cell_t nargs; 566 cell_t nreturns; 567 cell_t device; 568 cell_t package; 569 } args = { 570 (cell_t)"finddevice", 571 1, 572 1, 573 }; 574 575 ofw_real_start(); 576 577 args.device = ofw_real_map(device, strlen(device) + 1); 578 if (args.device == 0 || openfirmware(&args) == -1) { 579 ofw_real_stop(); 580 return (-1); 581 } 582 ofw_real_stop(); 583 return (args.package); 584} 585 586/* Return the fully qualified pathname corresponding to an instance. */ 587static ssize_t 588ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) 589{ 590 struct { 591 cell_t name; 592 cell_t nargs; 593 cell_t nreturns; 594 cell_t instance; 595 cell_t buf; 596 cell_t len; 597 cell_t size; 598 } args = { 599 (cell_t)"instance-to-path", 600 3, 601 1, 602 }; 603 604 ofw_real_start(); 605 606 args.instance = instance; 607 args.buf = ofw_real_map(buf, len); 608 args.len = len; 609 if (args.buf == 0 || openfirmware(&args) == -1) { 610 ofw_real_stop(); 611 return (-1); 612 } 613 ofw_real_unmap(args.buf, buf, len); 614 615 ofw_real_stop(); 616 return (args.size); 617} 618 619/* Return the fully qualified pathname corresponding to a package. */ 620static ssize_t 621ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) 622{ 623 struct { 624 cell_t name; 625 cell_t nargs; 626 cell_t nreturns; 627 cell_t package; 628 cell_t buf; 629 cell_t len; 630 cell_t size; 631 } args = { 632 (cell_t)"package-to-path", 633 3, 634 1, 635 }; 636 637 ofw_real_start(); 638 639 args.package = package; 640 args.buf = ofw_real_map(buf, len); 641 args.len = len; 642 if (args.buf == 0 || openfirmware(&args) == -1) { 643 ofw_real_stop(); 644 return (-1); 645 } 646 ofw_real_unmap(args.buf, buf, len); 647 648 ofw_real_stop(); 649 return (args.size); 650} 651 652/* Call the method in the scope of a given instance. */ 653static int 654ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, 655 int nargs, int nreturns, unsigned long *args_and_returns) 656{ 657 struct { 658 cell_t name; 659 cell_t nargs; 660 cell_t nreturns; 661 cell_t method; 662 cell_t instance; 663 cell_t args_n_results[12]; 664 } args = { 665 (cell_t)"call-method", 666 2, 667 1, 668 }; 669 cell_t *cp; 670 unsigned long *ap; 671 int n; 672 673 if (nargs > 6) 674 return (-1); 675 676 ofw_real_start(); 677 args.nargs = nargs + 2; 678 args.nreturns = nreturns + 1; 679 args.method = ofw_real_map(method, strlen(method) + 1); 680 args.instance = instance; 681 682 ap = args_and_returns; 683 for (cp = args.args_n_results + (n = nargs); --n >= 0;) 684 *--cp = *(ap++); 685 if (args.method == 0 || openfirmware(&args) == -1) { 686 ofw_real_stop(); 687 return (-1); 688 } 689 ofw_real_stop(); 690 if (args.args_n_results[nargs]) 691 return (args.args_n_results[nargs]); 692 for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) 693 *(ap++) = *--cp; 694 return (0); 695} 696 697/* 698 * Device I/O functions 699 */ 700 701/* Open an instance for a device. */ 702static ihandle_t 703ofw_real_open(ofw_t ofw, const char *device) 704{ 705 struct { 706 cell_t name; 707 cell_t nargs; 708 cell_t nreturns; 709 cell_t device; 710 cell_t instance; 711 } args = { 712 (cell_t)"open", 713 1, 714 1, 715 }; 716 717 ofw_real_start(); 718 719 args.device = ofw_real_map(device, strlen(device) + 1); 720 if (args.device == 0 || openfirmware(&args) == -1 721 || args.instance == 0) { 722 ofw_real_stop(); 723 return (-1); 724 } 725 ofw_real_stop(); 726 return (args.instance); 727} 728 729/* Close an instance. */ 730static void 731ofw_real_close(ofw_t ofw, ihandle_t instance) 732{ 733 struct { 734 cell_t name; 735 cell_t nargs; 736 cell_t nreturns; 737 cell_t instance; 738 } args = { 739 (cell_t)"close", 740 1, 741 0, 742 }; 743 744 args.instance = instance; 745 openfirmware(&args); 746} 747 748/* Read from an instance. */ 749static ssize_t 750ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) 751{ 752 struct { 753 cell_t name; 754 cell_t nargs; 755 cell_t nreturns; 756 cell_t instance; 757 cell_t addr; 758 cell_t len; 759 cell_t actual; 760 } args = { 761 (cell_t)"read", 762 3, 763 1, 764 }; 765 766 ofw_real_start(); 767 768 args.instance = instance; 769 args.addr = ofw_real_map(addr, len); 770 args.len = len; 771 if (args.addr == 0 || openfirmware(&args) == -1) { 772 ofw_real_stop(); 773 return (-1); 774 } 775 ofw_real_unmap(args.addr, addr, len); 776 777 ofw_real_stop(); 778 return (args.actual); 779} 780 781/* Write to an instance. */ 782static ssize_t 783ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) 784{ 785 struct { 786 cell_t name; 787 cell_t nargs; 788 cell_t nreturns; 789 cell_t instance; 790 cell_t addr; 791 cell_t len; 792 cell_t actual; 793 } args = { 794 (cell_t)"write", 795 3, 796 1, 797 }; 798 799 ofw_real_start(); 800 801 args.instance = instance; 802 args.addr = ofw_real_map(addr, len); 803 args.len = len; 804 if (args.addr == 0 || openfirmware(&args) == -1) { 805 ofw_real_stop(); 806 return (-1); 807 } 808 ofw_real_stop(); 809 return (args.actual); 810} 811 812/* Seek to a position. */ 813static int 814ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) 815{ 816 struct { 817 cell_t name; 818 cell_t nargs; 819 cell_t nreturns; 820 cell_t instance; 821 cell_t poshi; 822 cell_t poslo; 823 cell_t status; 824 } args = { 825 (cell_t)"seek", 826 3, 827 1, 828 }; 829 830 args.instance = instance; 831 args.poshi = pos >> 32; 832 args.poslo = pos; 833 if (openfirmware(&args) == -1) 834 return (-1); 835 return (args.status); 836} 837 838/* 839 * Memory functions 840 */ 841 842/* Claim an area of memory. */ 843static caddr_t 844ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align) 845{ 846 struct { 847 cell_t name; 848 cell_t nargs; 849 cell_t nreturns; 850 cell_t virt; 851 cell_t size; 852 cell_t align; 853 cell_t baseaddr; 854 } args = { 855 (cell_t)"claim", 856 3, 857 1, 858 }; 859 860 args.virt = (cell_t)virt; 861 args.size = size; 862 args.align = align; 863 if (openfirmware(&args) == -1) 864 return ((void *)-1); 865 return ((void *)args.baseaddr); 866} 867 868/* Release an area of memory. */ 869static void 870ofw_real_release(ofw_t ofw, void *virt, size_t size) 871{ 872 struct { 873 cell_t name; 874 cell_t nargs; 875 cell_t nreturns; 876 cell_t virt; 877 cell_t size; 878 } args = { 879 (cell_t)"release", 880 2, 881 0, 882 }; 883 884 args.virt = (cell_t)virt; 885 args.size = size; 886 openfirmware(&args); 887} 888 889/* 890 * Control transfer functions 891 */ 892 893/* Suspend and drop back to the Open Firmware interface. */ 894static void 895ofw_real_enter(ofw_t ofw) 896{ 897 struct { 898 cell_t name; 899 cell_t nargs; 900 cell_t nreturns; 901 } args = { 902 (cell_t)"enter", 903 0, 904 0, 905 }; 906 907 openfirmware(&args); 908 /* We may come back. */ 909} 910 911/* Shut down and drop back to the Open Firmware interface. */ 912static void 913ofw_real_exit(ofw_t ofw) 914{ 915 struct { 916 cell_t name; 917 cell_t nargs; 918 cell_t nreturns; 919 } args = { 920 (cell_t)"exit", 921 0, 922 0, 923 }; 924 925 openfirmware(&args); 926 for (;;) /* just in case */ 927 ; 928} 929 930