1 /* $NetBSD: Locore.c,v 1.10 2002/03/29 15:15:07 tsutsui 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 #include <lib/libsa/stand.h> 35 36 #include <machine/cpu.h> 37 #include <machine/stdarg.h> 38 39 #include "openfirm.h" 40 41 static int (*openfirmware) __P((void *)); 42 43 static void startup __P((void *, int, int (*)(void *), char *, int)); 44 static void setup __P((void)); 45 46 static int stack[8192/4 + 4]; 47 48 #ifdef XCOFF_GLUE 49 asm(" 50 .text 51 .globl _entry 52 _entry: 53 .long _start,0,0 54 "); 55 #endif 56 57 asm(" 58 .text 59 .globl _start 60 _start: 61 li 8,0 62 li 9,0x100 63 mtctr 9 64 1: 65 dcbf 0,8 66 icbi 0,8 67 addi 8,8,0x20 68 bdnz 1b 69 sync 70 isync 71 72 lis 1,stack@ha 73 addi 1,1,stack@l 74 addi 1,1,8192 75 76 mfmsr 8 77 li 0,0 78 mtmsr 0 79 isync 80 81 mtibatu 0,0 82 mtibatu 1,0 83 mtibatu 2,0 84 mtibatu 3,0 85 mtdbatu 0,0 86 mtdbatu 1,0 87 mtdbatu 2,0 88 mtdbatu 3,0 89 90 li 9,0x12 /* BATL(0, BAT_M, BAT_PP_RW) */ 91 mtibatl 0,9 92 mtdbatl 0,9 93 li 9,0x1ffe /* BATU(0, BAT_BL_256M, BAT_Vs) */ 94 mtibatu 0,9 95 mtdbatu 0,9 96 isync 97 98 mtmsr 8 99 isync 100 101 b startup 102 "); 103 104 #if 0 105 static int 106 openfirmware(arg) 107 void *arg; 108 { 109 110 asm volatile ("sync; isync"); 111 openfirmware_entry(arg); 112 asm volatile ("sync; isync"); 113 } 114 #endif 115 116 static void 117 startup(vpd, res, openfirm, arg, argl) 118 void *vpd; 119 int res; 120 int (*openfirm)(void *); 121 char *arg; 122 int argl; 123 { 124 extern char etext[], _end[], _edata[]; 125 126 memset(_edata, 0, (_end - _edata)); 127 openfirmware = openfirm; 128 setup(); 129 main(); 130 OF_exit(); 131 } 132 133 __dead void 134 OF_exit() 135 { 136 static struct { 137 char *name; 138 int nargs; 139 int nreturns; 140 } args = { 141 "exit", 142 0, 143 0 144 }; 145 146 openfirmware(&args); 147 for (;;); /* just in case */ 148 } 149 150 int 151 OF_finddevice(name) 152 char *name; 153 { 154 static struct { 155 char *name; 156 int nargs; 157 int nreturns; 158 char *device; 159 int phandle; 160 } args = { 161 "finddevice", 162 1, 163 1, 164 }; 165 166 args.device = name; 167 if (openfirmware(&args) == -1) 168 return -1; 169 return args.phandle; 170 } 171 172 int 173 OF_instance_to_package(ihandle) 174 int ihandle; 175 { 176 static struct { 177 char *name; 178 int nargs; 179 int nreturns; 180 int ihandle; 181 int phandle; 182 } args = { 183 "instance-to-package", 184 1, 185 1, 186 }; 187 188 args.ihandle = ihandle; 189 if (openfirmware(&args) == -1) 190 return -1; 191 return args.phandle; 192 } 193 194 int 195 OF_getprop(handle, prop, buf, buflen) 196 int handle; 197 char *prop; 198 void *buf; 199 int buflen; 200 { 201 static struct { 202 char *name; 203 int nargs; 204 int nreturns; 205 int phandle; 206 char *prop; 207 void *buf; 208 int buflen; 209 int size; 210 } args = { 211 "getprop", 212 4, 213 1, 214 }; 215 216 args.phandle = handle; 217 args.prop = prop; 218 args.buf = buf; 219 args.buflen = buflen; 220 if (openfirmware(&args) == -1) 221 return -1; 222 return args.size; 223 } 224 225 #ifdef __notyet__ /* Has a bug on FirePower */ 226 int 227 OF_setprop(handle, prop, buf, len) 228 int handle; 229 char *prop; 230 void *buf; 231 int len; 232 { 233 static struct { 234 char *name; 235 int nargs; 236 int nreturns; 237 int phandle; 238 char *prop; 239 void *buf; 240 int len; 241 int size; 242 } args = { 243 "setprop", 244 4, 245 1, 246 }; 247 248 args.phandle = handle; 249 args.prop = prop; 250 args.buf = buf; 251 args.len = len; 252 if (openfirmware(&args) == -1) 253 return -1; 254 return args.size; 255 } 256 #endif 257 258 int 259 OF_open(dname) 260 char *dname; 261 { 262 static struct { 263 char *name; 264 int nargs; 265 int nreturns; 266 char *dname; 267 int handle; 268 } args = { 269 "open", 270 1, 271 1, 272 }; 273 274 #ifdef OFW_DEBUG 275 printf("OF_open(%s) -> ", dname); 276 #endif 277 args.dname = dname; 278 if (openfirmware(&args) == -1 || 279 args.handle == 0) { 280 #ifdef OFW_DEBUG 281 printf("lose\n"); 282 #endif 283 return -1; 284 } 285 #ifdef OFW_DEBUG 286 printf("%d\n", args.handle); 287 #endif 288 return args.handle; 289 } 290 291 void 292 OF_close(handle) 293 int handle; 294 { 295 static struct { 296 char *name; 297 int nargs; 298 int nreturns; 299 int handle; 300 } args = { 301 "close", 302 1, 303 0, 304 }; 305 306 #ifdef OFW_DEBUG 307 printf("OF_close(%d)\n", handle); 308 #endif 309 args.handle = handle; 310 openfirmware(&args); 311 } 312 313 int 314 OF_write(handle, addr, len) 315 int handle; 316 void *addr; 317 int len; 318 { 319 static struct { 320 char *name; 321 int nargs; 322 int nreturns; 323 int ihandle; 324 void *addr; 325 int len; 326 int actual; 327 } args = { 328 "write", 329 3, 330 1, 331 }; 332 333 #ifdef OFW_DEBUG 334 if (len != 1) 335 printf("OF_write(%d, %x, %x) -> ", handle, addr, len); 336 #endif 337 args.ihandle = handle; 338 args.addr = addr; 339 args.len = len; 340 if (openfirmware(&args) == -1) { 341 #ifdef OFW_DEBUG 342 printf("lose\n"); 343 #endif 344 return -1; 345 } 346 #ifdef OFW_DEBUG 347 if (len != 1) 348 printf("%x\n", args.actual); 349 #endif 350 return args.actual; 351 } 352 353 int 354 OF_read(handle, addr, len) 355 int handle; 356 void *addr; 357 int len; 358 { 359 static struct { 360 char *name; 361 int nargs; 362 int nreturns; 363 int ihandle; 364 void *addr; 365 int len; 366 int actual; 367 } args = { 368 "read", 369 3, 370 1, 371 }; 372 373 #ifdef OFW_DEBUG 374 if (len != 1) 375 printf("OF_read(%d, %x, %x) -> ", handle, addr, len); 376 #endif 377 args.ihandle = handle; 378 args.addr = addr; 379 args.len = len; 380 if (openfirmware(&args) == -1) { 381 #ifdef OFW_DEBUG 382 printf("lose\n"); 383 #endif 384 return -1; 385 } 386 #ifdef OFW_DEBUG 387 if (len != 1) 388 printf("%x\n", args.actual); 389 #endif 390 return args.actual; 391 } 392 393 int 394 OF_seek(handle, pos) 395 int handle; 396 u_quad_t pos; 397 { 398 static struct { 399 char *name; 400 int nargs; 401 int nreturns; 402 int handle; 403 int poshi; 404 int poslo; 405 int status; 406 } args = { 407 "seek", 408 3, 409 1, 410 }; 411 412 #ifdef OFW_DEBUG 413 printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos); 414 #endif 415 args.handle = handle; 416 args.poshi = (int)(pos >> 32); 417 args.poslo = (int)pos; 418 if (openfirmware(&args) == -1) { 419 #ifdef OFW_DEBUG 420 printf("lose\n"); 421 #endif 422 return -1; 423 } 424 #ifdef OFW_DEBUG 425 printf("%d\n", args.status); 426 #endif 427 return args.status; 428 } 429 430 void * 431 OF_claim(virt, size, align) 432 void *virt; 433 u_int size; 434 u_int align; 435 { 436 static struct { 437 char *name; 438 int nargs; 439 int nreturns; 440 void *virt; 441 u_int size; 442 u_int align; 443 void *baseaddr; 444 } args = { 445 "claim", 446 3, 447 1, 448 }; 449 450 #ifdef OFW_DEBUG 451 printf("OF_claim(%x, %x, %x) -> ", virt, size, align); 452 #endif 453 args.virt = virt; 454 args.size = size; 455 args.align = align; 456 if (openfirmware(&args) == -1) { 457 #ifdef OFW_DEBUG 458 printf("lose\n"); 459 #endif 460 return (void *)-1; 461 } 462 #ifdef OFW_DEBUG 463 printf("%x\n", args.baseaddr); 464 #endif 465 return args.baseaddr; 466 } 467 468 void 469 OF_release(virt, size) 470 void *virt; 471 u_int size; 472 { 473 static struct { 474 char *name; 475 int nargs; 476 int nreturns; 477 void *virt; 478 u_int size; 479 } args = { 480 "release", 481 2, 482 0, 483 }; 484 485 #ifdef OFW_DEBUG 486 printf("OF_release(%x, %x)\n", virt, size); 487 #endif 488 args.virt = virt; 489 args.size = size; 490 openfirmware(&args); 491 } 492 493 int 494 OF_milliseconds() 495 { 496 static struct { 497 char *name; 498 int nargs; 499 int nreturns; 500 int ms; 501 } args = { 502 "milliseconds", 503 0, 504 1, 505 }; 506 507 openfirmware(&args); 508 return args.ms; 509 } 510 511 #ifdef __notyet__ 512 void 513 OF_chain(virt, size, entry, arg, len) 514 void *virt; 515 u_int size; 516 void (*entry)(); 517 void *arg; 518 u_int len; 519 { 520 static struct { 521 char *name; 522 int nargs; 523 int nreturns; 524 void *virt; 525 u_int size; 526 void (*entry)(); 527 void *arg; 528 u_int len; 529 } args = { 530 "chain", 531 5, 532 0, 533 }; 534 535 args.virt = virt; 536 args.size = size; 537 args.entry = entry; 538 args.arg = arg; 539 args.len = len; 540 openfirmware(&args); 541 } 542 #else 543 void 544 OF_chain(virt, size, entry, arg, len) 545 void *virt; 546 u_int size; 547 void (*entry)(); 548 void *arg; 549 u_int len; 550 { 551 /* 552 * This is a REALLY dirty hack till the firmware gets this going 553 */ 554 #if 0 555 OF_release(virt, size); 556 #endif 557 entry(0, 0, openfirmware, arg, len); 558 } 559 #endif 560 561 int 562 #ifdef __STDC__ 563 OF_call_method(char *method, int ihandle, int nargs, int nreturns, ...) 564 #else 565 OF_call_method(method, ihandle, nargs, nreturns, va_alist) 566 char *method; 567 int ihandle; 568 int nargs; 569 int nreturns; 570 va_dcl 571 #endif 572 { 573 va_list ap; 574 static struct { 575 char *name; 576 int nargs; 577 int nreturns; 578 char *method; 579 int ihandle; 580 int args_n_results[12]; 581 } args = { 582 "call-method", 583 2, 584 1, 585 }; 586 int *ip, n; 587 588 if (nargs > 6) 589 return -1; 590 args.nargs = nargs + 2; 591 args.nreturns = nreturns + 1; 592 args.method = method; 593 args.ihandle = ihandle; 594 va_start(ap, nreturns); 595 for (ip = args.args_n_results + (n = nargs); --n >= 0;) 596 *--ip = va_arg(ap, int); 597 598 if (openfirmware(&args) == -1) { 599 va_end(ap); 600 return -1; 601 } 602 if (args.args_n_results[nargs]) { 603 va_end(ap); 604 return args.args_n_results[nargs]; 605 } 606 for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) 607 *va_arg(ap, int *) = *--ip; 608 va_end(ap); 609 return 0; 610 } 611 612 static int stdin; 613 static int stdout; 614 615 static void 616 setup() 617 { 618 int chosen; 619 620 if ((chosen = OF_finddevice("/chosen")) == -1) 621 OF_exit(); 622 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != 623 sizeof(stdin) || 624 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != 625 sizeof(stdout)) 626 OF_exit(); 627 } 628 629 void 630 putchar(c) 631 int c; 632 { 633 char ch = c; 634 635 if (c == '\n') 636 putchar('\r'); 637 OF_write(stdout, &ch, 1); 638 } 639 640 int 641 getchar() 642 { 643 unsigned char ch = '\0'; 644 int l; 645 646 while ((l = OF_read(stdin, &ch, 1)) != 1) 647 if (l != -2 && l != 0) 648 return -1; 649 return ch; 650 } 651