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