1 /* $NetBSD: openfirm.c,v 1.11 2001/09/24 13:22:33 wiz 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 #include <sys/param.h> 34 #include <sys/systm.h> 35 36 #include <machine/psl.h> 37 #include <machine/stdarg.h> 38 39 #include <dev/ofw/openfirm.h> 40 41 char *OF_buf; 42 43 void ofw_stack(void); 44 void ofbcopy(const void *, void *, size_t); 45 46 int 47 OF_peer(phandle) 48 int phandle; 49 { 50 static struct { 51 char *name; 52 int nargs; 53 int nreturns; 54 int phandle; 55 int sibling; 56 } args = { 57 "peer", 58 1, 59 1, 60 }; 61 62 ofw_stack(); 63 args.phandle = phandle; 64 if (openfirmware(&args) == -1) 65 return 0; 66 return args.sibling; 67 } 68 69 int 70 OF_child(phandle) 71 int phandle; 72 { 73 static struct { 74 char *name; 75 int nargs; 76 int nreturns; 77 int phandle; 78 int child; 79 } args = { 80 "child", 81 1, 82 1, 83 }; 84 85 ofw_stack(); 86 args.phandle = phandle; 87 if (openfirmware(&args) == -1) 88 return 0; 89 return args.child; 90 } 91 92 int 93 OF_parent(phandle) 94 int phandle; 95 { 96 static struct { 97 char *name; 98 int nargs; 99 int nreturns; 100 int phandle; 101 int parent; 102 } args = { 103 "parent", 104 1, 105 1, 106 }; 107 108 ofw_stack(); 109 args.phandle = phandle; 110 if (openfirmware(&args) == -1) 111 return 0; 112 return args.parent; 113 } 114 115 int 116 OF_instance_to_package(ihandle) 117 int ihandle; 118 { 119 static struct { 120 char *name; 121 int nargs; 122 int nreturns; 123 int ihandle; 124 int phandle; 125 } args = { 126 "instance-to-package", 127 1, 128 1, 129 }; 130 131 ofw_stack(); 132 args.ihandle = ihandle; 133 if (openfirmware(&args) == -1) 134 return -1; 135 return args.phandle; 136 } 137 138 int 139 OF_getproplen(handle, prop) 140 int handle; 141 char *prop; 142 { 143 static struct { 144 char *name; 145 int nargs; 146 int nreturns; 147 int phandle; 148 char *prop; 149 int proplen; 150 } args = { 151 "getproplen", 152 2, 153 1, 154 }; 155 156 ofw_stack(); 157 args.phandle = handle; 158 args.prop = prop; 159 if (openfirmware(&args) == -1) 160 return -1; 161 return args.proplen; 162 } 163 164 int 165 OF_getprop(handle, prop, buf, buflen) 166 int handle; 167 char *prop; 168 void *buf; 169 int buflen; 170 { 171 static struct { 172 char *name; 173 int nargs; 174 int nreturns; 175 int phandle; 176 char *prop; 177 void *buf; 178 int buflen; 179 int size; 180 } args = { 181 "getprop", 182 4, 183 1, 184 }; 185 186 ofw_stack(); 187 if (buflen > NBPG) 188 return -1; 189 args.phandle = handle; 190 args.prop = prop; 191 args.buf = OF_buf; 192 args.buflen = buflen; 193 if (openfirmware(&args) == -1) 194 return -1; 195 if (args.size > buflen) 196 args.size = buflen; 197 if (args.size > 0) 198 ofbcopy(OF_buf, buf, args.size); 199 return args.size; 200 } 201 202 int 203 OF_nextprop(handle, prop, nextprop) 204 int handle; 205 char *prop; 206 void *nextprop; 207 { 208 static struct { 209 char *name; 210 int nargs; 211 int nreturns; 212 int phandle; 213 char *prop; 214 char *buf; 215 int flag; 216 } args = { 217 "nextprop", 218 3, 219 1, 220 }; 221 222 ofw_stack(); 223 args.phandle = handle; 224 args.prop = prop; 225 args.buf = OF_buf; 226 if (openfirmware(&args) == -1) 227 return -1; 228 strncpy(nextprop, OF_buf, 32); 229 return args.flag; 230 } 231 232 int 233 OF_finddevice(name) 234 char *name; 235 { 236 static struct { 237 char *name; 238 int nargs; 239 int nreturns; 240 char *device; 241 int phandle; 242 } args = { 243 "finddevice", 244 1, 245 1, 246 }; 247 248 ofw_stack(); 249 args.device = name; 250 if (openfirmware(&args) == -1) 251 return -1; 252 return args.phandle; 253 } 254 255 int 256 OF_instance_to_path(ihandle, buf, buflen) 257 int ihandle; 258 char *buf; 259 int buflen; 260 { 261 static struct { 262 char *name; 263 int nargs; 264 int nreturns; 265 int ihandle; 266 char *buf; 267 int buflen; 268 int length; 269 } args = { 270 "instance-to-path", 271 3, 272 1, 273 }; 274 275 if (buflen > NBPG) 276 return -1; 277 args.ihandle = ihandle; 278 args.buf = OF_buf; 279 args.buflen = buflen; 280 if (openfirmware(&args) < 0) 281 return -1; 282 if (args.length > buflen) 283 args.length = buflen; 284 if (args.length > 0) 285 ofbcopy(OF_buf, buf, args.length); 286 return args.length; 287 } 288 289 int 290 OF_package_to_path(phandle, buf, buflen) 291 int phandle; 292 char *buf; 293 int buflen; 294 { 295 static struct { 296 char *name; 297 int nargs; 298 int nreturns; 299 int phandle; 300 char *buf; 301 int buflen; 302 int length; 303 } args = { 304 "package-to-path", 305 3, 306 1, 307 }; 308 309 ofw_stack(); 310 if (buflen > NBPG) 311 return -1; 312 args.phandle = phandle; 313 args.buf = OF_buf; 314 args.buflen = buflen; 315 if (openfirmware(&args) < 0) 316 return -1; 317 if (args.length > buflen) 318 args.length = buflen; 319 if (args.length > 0) 320 ofbcopy(OF_buf, buf, args.length); 321 return args.length; 322 } 323 324 int 325 #ifdef __STDC__ 326 OF_call_method(char *method, int ihandle, int nargs, int nreturns, ...) 327 #else 328 OF_call_method(method, ihandle, nargs, nreturns, va_alist) 329 char *method; 330 int ihandle; 331 int nargs; 332 int nreturns; 333 va_dcl 334 #endif 335 { 336 va_list ap; 337 static struct { 338 char *name; 339 int nargs; 340 int nreturns; 341 char *method; 342 int ihandle; 343 int args_n_results[12]; 344 } args = { 345 "call-method", 346 2, 347 1, 348 }; 349 int *ip, n; 350 351 if (nargs > 6) 352 return -1; 353 args.nargs = nargs + 2; 354 args.nreturns = nreturns + 1; 355 args.method = method; 356 args.ihandle = ihandle; 357 va_start(ap, nreturns); 358 for (ip = args.args_n_results + (n = nargs); --n >= 0;) 359 *--ip = va_arg(ap, int); 360 ofw_stack(); 361 if (openfirmware(&args) == -1) { 362 va_end(ap); 363 return -1; 364 } 365 if (args.args_n_results[nargs]) { 366 va_end(ap); 367 return args.args_n_results[nargs]; 368 } 369 for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) 370 *va_arg(ap, int *) = *--ip; 371 va_end(ap); 372 return 0; 373 } 374 375 int 376 #ifdef __STDC__ 377 OF_call_method_1(char *method, int ihandle, int nargs, ...) 378 #else 379 OF_call_method_1(method, ihandle, nargs, va_alist) 380 char *method; 381 int ihandle; 382 int nargs; 383 va_dcl 384 #endif 385 { 386 va_list ap; 387 static struct { 388 char *name; 389 int nargs; 390 int nreturns; 391 char *method; 392 int ihandle; 393 int args_n_results[8]; 394 } args = { 395 "call-method", 396 2, 397 2, 398 }; 399 int *ip, n; 400 401 if (nargs > 6) 402 return -1; 403 args.nargs = nargs + 2; 404 args.method = method; 405 args.ihandle = ihandle; 406 va_start(ap, nargs); 407 for (ip = args.args_n_results + (n = nargs); --n >= 0;) 408 *--ip = va_arg(ap, int); 409 va_end(ap); 410 ofw_stack(); 411 if (openfirmware(&args) == -1) 412 return -1; 413 if (args.args_n_results[nargs]) 414 return -1; 415 return args.args_n_results[nargs + 1]; 416 } 417 418 int 419 OF_open(dname) 420 char *dname; 421 { 422 static struct { 423 char *name; 424 int nargs; 425 int nreturns; 426 char *dname; 427 int handle; 428 } args = { 429 "open", 430 1, 431 1, 432 }; 433 int l; 434 435 ofw_stack(); 436 if ((l = strlen(dname)) >= NBPG) 437 return -1; 438 ofbcopy(dname, OF_buf, l + 1); 439 args.dname = OF_buf; 440 if (openfirmware(&args) == -1) 441 return -1; 442 return args.handle; 443 } 444 445 void 446 OF_close(handle) 447 int handle; 448 { 449 static struct { 450 char *name; 451 int nargs; 452 int nreturns; 453 int handle; 454 } args = { 455 "close", 456 1, 457 0, 458 }; 459 460 ofw_stack(); 461 args.handle = handle; 462 openfirmware(&args); 463 } 464 465 /* 466 * This assumes that character devices don't read in multiples of NBPG. 467 */ 468 int 469 OF_read(handle, addr, len) 470 int handle; 471 void *addr; 472 int len; 473 { 474 static struct { 475 char *name; 476 int nargs; 477 int nreturns; 478 int ihandle; 479 void *addr; 480 int len; 481 int actual; 482 } args = { 483 "read", 484 3, 485 1, 486 }; 487 int l, act = 0; 488 char *p = addr; 489 490 ofw_stack(); 491 args.ihandle = handle; 492 args.addr = OF_buf; 493 for (; len > 0; len -= l, p += l) { 494 l = min(NBPG, len); 495 args.len = l; 496 if (openfirmware(&args) == -1) 497 return -1; 498 if (args.actual > 0) { 499 ofbcopy(OF_buf, p, args.actual); 500 act += args.actual; 501 } 502 if (args.actual < l) { 503 if (act) 504 return act; 505 else 506 return args.actual; 507 } 508 } 509 return act; 510 } 511 512 int 513 OF_write(handle, addr, len) 514 int handle; 515 void *addr; 516 int len; 517 { 518 static struct { 519 char *name; 520 int nargs; 521 int nreturns; 522 int ihandle; 523 void *addr; 524 int len; 525 int actual; 526 } args = { 527 "write", 528 3, 529 1, 530 }; 531 int l, act = 0; 532 char *p = addr; 533 534 ofw_stack(); 535 args.ihandle = handle; 536 args.addr = OF_buf; 537 for (; len > 0; len -= l, p += l) { 538 l = min(NBPG, len); 539 ofbcopy(p, OF_buf, l); 540 args.len = l; 541 if (openfirmware(&args) == -1) 542 return -1; 543 l = args.actual; 544 act += l; 545 } 546 return act; 547 } 548 549 int 550 OF_seek(handle, pos) 551 int handle; 552 u_quad_t pos; 553 { 554 static struct { 555 char *name; 556 int nargs; 557 int nreturns; 558 int handle; 559 int poshi; 560 int poslo; 561 int status; 562 } args = { 563 "seek", 564 3, 565 1, 566 }; 567 568 ofw_stack(); 569 args.handle = handle; 570 args.poshi = (int)(pos >> 32); 571 args.poslo = (int)pos; 572 if (openfirmware(&args) == -1) 573 return -1; 574 return args.status; 575 } 576 577 void 578 OF_boot(bootspec) 579 char *bootspec; 580 { 581 static struct { 582 char *name; 583 int nargs; 584 int nreturns; 585 char *bootspec; 586 } args = { 587 "boot", 588 1, 589 0, 590 }; 591 int l; 592 593 if ((l = strlen(bootspec)) >= NBPG) 594 panic("OF_boot"); 595 ofw_stack(); 596 ofbcopy(bootspec, OF_buf, l + 1); 597 args.bootspec = OF_buf; 598 openfirmware(&args); 599 while (1); /* just in case */ 600 } 601 602 void 603 OF_enter() 604 { 605 static struct { 606 char *name; 607 int nargs; 608 int nreturns; 609 } args = { 610 "enter", 611 0, 612 0, 613 }; 614 615 ofw_stack(); 616 openfirmware(&args); 617 } 618 619 void 620 OF_exit() 621 { 622 static struct { 623 char *name; 624 int nargs; 625 int nreturns; 626 } args = { 627 "exit", 628 0, 629 0, 630 }; 631 632 ofw_stack(); 633 openfirmware(&args); 634 while (1); /* just in case */ 635 } 636 637 void 638 (*OF_set_callback (void (*newfunc)(void *))) (void *) 639 { 640 static struct { 641 char *name; 642 int nargs; 643 int nreturns; 644 void (*newfunc)(void *); 645 void (*oldfunc)(void *); 646 } args = { 647 "set-callback", 648 1, 649 1, 650 }; 651 652 ofw_stack(); 653 args.newfunc = newfunc; 654 if (openfirmware(&args) == -1) 655 return 0; 656 return args.oldfunc; 657 } 658 659 /* 660 * This version of bcopy doesn't work for overlapping regions! 661 */ 662 void 663 ofbcopy(src, dst, len) 664 const void *src; 665 void *dst; 666 size_t len; 667 { 668 const char *sp = src; 669 char *dp = dst; 670 671 if (src == dst) 672 return; 673 674 /* 675 * Do some optimization? XXX 676 */ 677 while (len-- > 0) 678 *dp++ = *sp++; 679 } 680