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