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 <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 79 static void ofw_real_init(ofw_t, void *openfirm); 80 static int ofw_real_test(ofw_t, const char *name); 81 static phandle_t ofw_real_peer(ofw_t, phandle_t node); 82 static phandle_t ofw_real_child(ofw_t, phandle_t node); 83 static phandle_t ofw_real_parent(ofw_t, phandle_t node); 84 static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance); 85 static ssize_t ofw_real_getproplen(ofw_t, phandle_t package, 86 const char *propname); 87 static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname, 88 void *buf, size_t buflen); 89 static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous, 90 char *buf, size_t); 91 static int ofw_real_setprop(ofw_t, phandle_t package, const char *propname, 92 const void *buf, size_t len); 93 static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len); 94 static phandle_t ofw_real_finddevice(ofw_t, const char *device); 95 static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf, 96 size_t len); 97 static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf, 98 size_t len); 99 static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method, 100 int nargs, int nreturns, unsigned long *args_and_returns); 101 static ihandle_t ofw_real_open(ofw_t, const char *device); 102 static void ofw_real_close(ofw_t, ihandle_t instance); 103 static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len); 104 static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr, 105 size_t len); 106 static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos); 107 static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align); 108 static void ofw_real_release(ofw_t, void *virt, size_t size); 109 static void ofw_real_enter(ofw_t); 110 static void ofw_real_exit(ofw_t); 111 112 static 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 142 static ofw_def_t ofw_real = { 143 OFW_STD_REAL, 144 ofw_real_methods, 145 0 146 }; 147 OFW_DEF(ofw_real); 148 149 MALLOC_DEFINE(M_OFWREAL, "ofwreal", "Open Firmware Real Mode Bounce Page"); 150 151 static int (*openfirmware)(void *); 152 153 static vm_offset_t of_bounce_phys; 154 static caddr_t of_bounce_virt; 155 static off_t of_bounce_offset; 156 static size_t of_bounce_size; 157 static struct mtx of_bounce_mtx; 158 159 /* 160 * After the VM is up, allocate a wired, low memory bounce page. 161 */ 162 163 static void ofw_real_bounce_alloc(void *); 164 165 SYSINIT(ofw_real_bounce_alloc, SI_SUB_VM, SI_ORDER_ANY, 166 ofw_real_bounce_alloc, NULL); 167 168 static void 169 ofw_real_start(void) 170 { 171 mtx_lock(&of_bounce_mtx); 172 of_bounce_offset = 0; 173 } 174 175 static void 176 ofw_real_stop(void) 177 { 178 mtx_unlock(&of_bounce_mtx); 179 } 180 181 static void 182 ofw_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 206 static cell_t 207 ofw_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 246 static void 247 ofw_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 259 static void 260 ofw_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 } 267 268 /* 269 * Generic functions 270 */ 271 272 /* Test to see if a service exists. */ 273 static int 274 ofw_real_test(ofw_t ofw, const char *name) 275 { 276 static struct { 277 cell_t name; 278 cell_t nargs; 279 cell_t nreturns; 280 cell_t service; 281 cell_t missing; 282 } args = { 283 (cell_t)"test", 284 1, 285 1, 286 }; 287 288 ofw_real_start(); 289 290 args.service = ofw_real_map(name, strlen(name) + 1); 291 if (args.service == 0 || openfirmware(&args) == -1) { 292 ofw_real_stop(); 293 return (-1); 294 } 295 ofw_real_stop(); 296 return (args.missing); 297 } 298 299 /* 300 * Device tree functions 301 */ 302 303 /* Return the next sibling of this node or 0. */ 304 static phandle_t 305 ofw_real_peer(ofw_t ofw, phandle_t node) 306 { 307 static struct { 308 cell_t name; 309 cell_t nargs; 310 cell_t nreturns; 311 cell_t node; 312 cell_t next; 313 } args = { 314 (cell_t)"peer", 315 1, 316 1, 317 }; 318 319 args.node = node; 320 if (openfirmware(&args) == -1) 321 return (-1); 322 return (args.next); 323 } 324 325 /* Return the first child of this node or 0. */ 326 static phandle_t 327 ofw_real_child(ofw_t ofw, phandle_t node) 328 { 329 static struct { 330 cell_t name; 331 cell_t nargs; 332 cell_t nreturns; 333 cell_t node; 334 cell_t child; 335 } args = { 336 (cell_t)"child", 337 1, 338 1, 339 }; 340 341 args.node = node; 342 if (openfirmware(&args) == -1) 343 return (-1); 344 return (args.child); 345 } 346 347 /* Return the parent of this node or 0. */ 348 static phandle_t 349 ofw_real_parent(ofw_t ofw, phandle_t node) 350 { 351 static struct { 352 cell_t name; 353 cell_t nargs; 354 cell_t nreturns; 355 cell_t node; 356 cell_t parent; 357 } args = { 358 (cell_t)"parent", 359 1, 360 1, 361 }; 362 363 args.node = node; 364 if (openfirmware(&args) == -1) 365 return (-1); 366 return (args.parent); 367 } 368 369 /* Return the package handle that corresponds to an instance handle. */ 370 static phandle_t 371 ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance) 372 { 373 static struct { 374 cell_t name; 375 cell_t nargs; 376 cell_t nreturns; 377 cell_t instance; 378 cell_t package; 379 } args = { 380 (cell_t)"instance-to-package", 381 1, 382 1, 383 }; 384 385 args.instance = instance; 386 if (openfirmware(&args) == -1) 387 return (-1); 388 return (args.package); 389 } 390 391 /* Get the length of a property of a package. */ 392 static ssize_t 393 ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname) 394 { 395 static struct { 396 cell_t name; 397 cell_t nargs; 398 cell_t nreturns; 399 cell_t package; 400 cell_t propname; 401 cell_t proplen; 402 } args = { 403 (cell_t)"getproplen", 404 2, 405 1, 406 }; 407 408 ofw_real_start(); 409 410 args.package = package; 411 args.propname = ofw_real_map(propname, strlen(propname) + 1); 412 if (args.propname == 0 || openfirmware(&args) == -1) { 413 ofw_real_stop(); 414 return (-1); 415 } 416 ofw_real_stop(); 417 return (args.proplen); 418 } 419 420 /* Get the value of a property of a package. */ 421 static ssize_t 422 ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf, 423 size_t buflen) 424 { 425 static struct { 426 cell_t name; 427 cell_t nargs; 428 cell_t nreturns; 429 cell_t package; 430 cell_t propname; 431 cell_t buf; 432 cell_t buflen; 433 cell_t size; 434 } args = { 435 (cell_t)"getprop", 436 4, 437 1, 438 }; 439 440 ofw_real_start(); 441 442 args.package = package; 443 args.propname = ofw_real_map(propname, strlen(propname) + 1); 444 args.buf = ofw_real_map(buf, buflen); 445 args.buflen = buflen; 446 if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) { 447 ofw_real_stop(); 448 return (-1); 449 } 450 ofw_real_unmap(args.buf, buf, buflen); 451 452 ofw_real_stop(); 453 return (args.size); 454 } 455 456 /* Get the next property of a package. */ 457 static int 458 ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous, 459 char *buf, size_t size) 460 { 461 static struct { 462 cell_t name; 463 cell_t nargs; 464 cell_t nreturns; 465 cell_t package; 466 cell_t previous; 467 cell_t buf; 468 cell_t flag; 469 } args = { 470 (cell_t)"nextprop", 471 3, 472 1, 473 }; 474 475 ofw_real_start(); 476 477 args.package = package; 478 args.previous = ofw_real_map(previous, strlen(previous) + 1); 479 args.buf = ofw_real_map(buf, size); 480 if (args.previous == 0 || args.buf == 0 || openfirmware(&args) == -1) { 481 ofw_real_stop(); 482 return (-1); 483 } 484 ofw_real_unmap(args.buf, buf, size); 485 486 ofw_real_stop(); 487 return (args.flag); 488 } 489 490 /* Set the value of a property of a package. */ 491 /* XXX Has a bug on FirePower */ 492 static int 493 ofw_real_setprop(ofw_t ofw, phandle_t package, const char *propname, 494 const void *buf, size_t len) 495 { 496 static struct { 497 cell_t name; 498 cell_t nargs; 499 cell_t nreturns; 500 cell_t package; 501 cell_t propname; 502 cell_t buf; 503 cell_t len; 504 cell_t size; 505 } args = { 506 (cell_t)"setprop", 507 4, 508 1, 509 }; 510 511 ofw_real_start(); 512 513 args.package = package; 514 args.propname = ofw_real_map(propname, strlen(propname) + 1); 515 args.buf = ofw_real_map(buf, len); 516 args.len = len; 517 if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) { 518 ofw_real_stop(); 519 return (-1); 520 } 521 ofw_real_stop(); 522 return (args.size); 523 } 524 525 /* Convert a device specifier to a fully qualified pathname. */ 526 static ssize_t 527 ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len) 528 { 529 static struct { 530 cell_t name; 531 cell_t nargs; 532 cell_t nreturns; 533 cell_t device; 534 cell_t buf; 535 cell_t len; 536 cell_t size; 537 } args = { 538 (cell_t)"canon", 539 3, 540 1, 541 }; 542 543 ofw_real_start(); 544 545 args.device = ofw_real_map(device, strlen(device) + 1); 546 args.buf = ofw_real_map(buf, len); 547 args.len = len; 548 if (args.device == 0 || args.buf == 0 || openfirmware(&args) == -1) { 549 ofw_real_stop(); 550 return (-1); 551 } 552 ofw_real_unmap(args.buf, buf, len); 553 554 ofw_real_stop(); 555 return (args.size); 556 } 557 558 /* Return a package handle for the specified device. */ 559 static phandle_t 560 ofw_real_finddevice(ofw_t ofw, const char *device) 561 { 562 static struct { 563 cell_t name; 564 cell_t nargs; 565 cell_t nreturns; 566 cell_t device; 567 cell_t package; 568 } args = { 569 (cell_t)"finddevice", 570 1, 571 1, 572 }; 573 574 ofw_real_start(); 575 576 args.device = ofw_real_map(device, strlen(device) + 1); 577 if (args.device == 0 || openfirmware(&args) == -1) { 578 ofw_real_stop(); 579 return (-1); 580 } 581 ofw_real_stop(); 582 return (args.package); 583 } 584 585 /* Return the fully qualified pathname corresponding to an instance. */ 586 static ssize_t 587 ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len) 588 { 589 static struct { 590 cell_t name; 591 cell_t nargs; 592 cell_t nreturns; 593 cell_t instance; 594 cell_t buf; 595 cell_t len; 596 cell_t size; 597 } args = { 598 (cell_t)"instance-to-path", 599 3, 600 1, 601 }; 602 603 ofw_real_start(); 604 605 args.instance = instance; 606 args.buf = ofw_real_map(buf, len); 607 args.len = len; 608 if (args.buf == 0 || openfirmware(&args) == -1) { 609 ofw_real_stop(); 610 return (-1); 611 } 612 ofw_real_unmap(args.buf, buf, len); 613 614 ofw_real_stop(); 615 return (args.size); 616 } 617 618 /* Return the fully qualified pathname corresponding to a package. */ 619 static ssize_t 620 ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len) 621 { 622 static struct { 623 cell_t name; 624 cell_t nargs; 625 cell_t nreturns; 626 cell_t package; 627 cell_t buf; 628 cell_t len; 629 cell_t size; 630 } args = { 631 (cell_t)"package-to-path", 632 3, 633 1, 634 }; 635 636 ofw_real_start(); 637 638 args.package = package; 639 args.buf = ofw_real_map(buf, len); 640 args.len = len; 641 if (args.buf == 0 || openfirmware(&args) == -1) { 642 ofw_real_stop(); 643 return (-1); 644 } 645 ofw_real_unmap(args.buf, buf, len); 646 647 ofw_real_stop(); 648 return (args.size); 649 } 650 651 /* Call the method in the scope of a given instance. */ 652 static int 653 ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method, 654 int nargs, int nreturns, unsigned long *args_and_returns) 655 { 656 static struct { 657 cell_t name; 658 cell_t nargs; 659 cell_t nreturns; 660 cell_t method; 661 cell_t instance; 662 cell_t args_n_results[12]; 663 } args = { 664 (cell_t)"call-method", 665 2, 666 1, 667 }; 668 cell_t *cp; 669 unsigned long *ap; 670 int n; 671 672 if (nargs > 6) 673 return (-1); 674 675 ofw_real_start(); 676 args.nargs = nargs + 2; 677 args.nreturns = nreturns + 1; 678 args.method = ofw_real_map(method, strlen(method) + 1); 679 args.instance = instance; 680 681 ap = args_and_returns; 682 for (cp = args.args_n_results + (n = nargs); --n >= 0;) 683 *--cp = *(ap++); 684 if (args.method == 0 || openfirmware(&args) == -1) { 685 ofw_real_stop(); 686 return (-1); 687 } 688 ofw_real_stop(); 689 if (args.args_n_results[nargs]) 690 return (args.args_n_results[nargs]); 691 for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) 692 *(ap++) = *--cp; 693 return (0); 694 } 695 696 /* 697 * Device I/O functions 698 */ 699 700 /* Open an instance for a device. */ 701 static ihandle_t 702 ofw_real_open(ofw_t ofw, const char *device) 703 { 704 static struct { 705 cell_t name; 706 cell_t nargs; 707 cell_t nreturns; 708 cell_t device; 709 cell_t instance; 710 } args = { 711 (cell_t)"open", 712 1, 713 1, 714 }; 715 716 ofw_real_start(); 717 718 args.device = ofw_real_map(device, strlen(device) + 1); 719 if (args.device == 0 || openfirmware(&args) == -1 720 || args.instance == 0) { 721 ofw_real_stop(); 722 return (-1); 723 } 724 ofw_real_stop(); 725 return (args.instance); 726 } 727 728 /* Close an instance. */ 729 static void 730 ofw_real_close(ofw_t ofw, ihandle_t instance) 731 { 732 static struct { 733 cell_t name; 734 cell_t nargs; 735 cell_t nreturns; 736 cell_t instance; 737 } args = { 738 (cell_t)"close", 739 1, 740 }; 741 742 args.instance = instance; 743 openfirmware(&args); 744 } 745 746 /* Read from an instance. */ 747 static ssize_t 748 ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len) 749 { 750 static struct { 751 cell_t name; 752 cell_t nargs; 753 cell_t nreturns; 754 cell_t instance; 755 cell_t addr; 756 cell_t len; 757 cell_t actual; 758 } args = { 759 (cell_t)"read", 760 3, 761 1, 762 }; 763 764 ofw_real_start(); 765 766 args.instance = instance; 767 args.addr = ofw_real_map(addr, len); 768 args.len = len; 769 if (args.addr == 0 || openfirmware(&args) == -1) { 770 ofw_real_stop(); 771 return (-1); 772 } 773 ofw_real_unmap(args.addr, addr, len); 774 775 ofw_real_stop(); 776 return (args.actual); 777 } 778 779 /* Write to an instance. */ 780 static ssize_t 781 ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len) 782 { 783 static struct { 784 cell_t name; 785 cell_t nargs; 786 cell_t nreturns; 787 cell_t instance; 788 cell_t addr; 789 cell_t len; 790 cell_t actual; 791 } args = { 792 (cell_t)"write", 793 3, 794 1, 795 }; 796 797 ofw_real_start(); 798 799 args.instance = instance; 800 args.addr = ofw_real_map(addr, len); 801 args.len = len; 802 if (args.addr == 0 || openfirmware(&args) == -1) { 803 ofw_real_stop(); 804 return (-1); 805 } 806 ofw_real_stop(); 807 return (args.actual); 808 } 809 810 /* Seek to a position. */ 811 static int 812 ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos) 813 { 814 static struct { 815 cell_t name; 816 cell_t nargs; 817 cell_t nreturns; 818 cell_t instance; 819 cell_t poshi; 820 cell_t poslo; 821 cell_t status; 822 } args = { 823 (cell_t)"seek", 824 3, 825 1, 826 }; 827 828 args.instance = instance; 829 args.poshi = pos >> 32; 830 args.poslo = pos; 831 if (openfirmware(&args) == -1) 832 return (-1); 833 return (args.status); 834 } 835 836 /* 837 * Memory functions 838 */ 839 840 /* Claim an area of memory. */ 841 static caddr_t 842 ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align) 843 { 844 static struct { 845 cell_t name; 846 cell_t nargs; 847 cell_t nreturns; 848 cell_t virt; 849 cell_t size; 850 cell_t align; 851 cell_t baseaddr; 852 } args = { 853 (cell_t)"claim", 854 3, 855 1, 856 }; 857 858 args.virt = (cell_t)virt; 859 args.size = size; 860 args.align = align; 861 if (openfirmware(&args) == -1) 862 return ((void *)-1); 863 return ((void *)args.baseaddr); 864 } 865 866 /* Release an area of memory. */ 867 static void 868 ofw_real_release(ofw_t ofw, void *virt, size_t size) 869 { 870 static struct { 871 cell_t name; 872 cell_t nargs; 873 cell_t nreturns; 874 cell_t virt; 875 cell_t size; 876 } args = { 877 (cell_t)"release", 878 2, 879 }; 880 881 args.virt = (cell_t)virt; 882 args.size = size; 883 openfirmware(&args); 884 } 885 886 /* 887 * Control transfer functions 888 */ 889 890 /* Suspend and drop back to the Open Firmware interface. */ 891 static void 892 ofw_real_enter(ofw_t ofw) 893 { 894 static struct { 895 cell_t name; 896 cell_t nargs; 897 cell_t nreturns; 898 } args = { 899 (cell_t)"enter", 900 }; 901 902 openfirmware(&args); 903 /* We may come back. */ 904 } 905 906 /* Shut down and drop back to the Open Firmware interface. */ 907 static void 908 ofw_real_exit(ofw_t ofw) 909 { 910 static struct { 911 cell_t name; 912 cell_t nargs; 913 cell_t nreturns; 914 } args = { 915 (cell_t)"exit", 916 }; 917 918 openfirmware(&args); 919 for (;;) /* just in case */ 920 ; 921 } 922 923