1 /* $OpenBSD: Locore.c,v 1.16 2014/07/12 21:54:58 jasper Exp $ */ 2 /* $NetBSD: Locore.c,v 1.1 1997/04/16 20:29:11 thorpej Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 6 * Copyright (C) 1995, 1996 TooLs GmbH. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by TooLs GmbH. 20 * 4. The name of TooLs GmbH may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 29 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 31 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 32 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <lib/libsa/stand.h> 36 #include <macppc/stand/openfirm.h> 37 #include <dev/cons.h> 38 39 40 /* 41 #include "machine/cpu.h" 42 */ 43 44 #define ENABLE_DECREMENTER_WORKAROUND 45 void patch_dec_intr(); 46 47 static int (*openfirmware)(void *); 48 49 static void setup(void); 50 51 asm (".text; .globl _entry; _entry: .long _start,0,0"); 52 asm(" .text \n" 53 " .globl bat_init \n" 54 "bat_init: \n" 55 " \n" 56 " mfmsr 8 \n" 57 " li 0,0 \n" 58 " mtmsr 0 \n" 59 " isync \n" 60 " \n" 61 " mtibatu 0,0 \n" 62 " mtibatu 1,0 \n" 63 " mtibatu 2,0 \n" 64 " mtibatu 3,0 \n" 65 " mtdbatu 0,0 \n" 66 " mtdbatu 1,0 \n" 67 " mtdbatu 2,0 \n" 68 " mtdbatu 3,0 \n" 69 " \n" 70 " li 9,0x12 \n" /* BATL(0, BAT_M, BAT_PP_RW) */ 71 " mtibatl 0,9 \n" 72 " mtdbatl 0,9 \n" 73 " li 9,0x1ffe \n" /* BATU(0, BAT_BL_256M, BAT_Vs) */ 74 " mtibatu 0,9 \n" 75 " mtdbatu 0,9 \n" 76 " isync \n" 77 " \n" 78 " mtmsr 8 \n" 79 " isync \n" 80 " blr \n"); 81 82 #ifdef XCOFF_GLUE 83 static int stack[8192/4 + 4] __attribute__((__used__)); 84 #endif 85 86 __dead void 87 _start(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl) 88 { 89 extern char etext[]; 90 91 #ifdef XCOFF_GLUE 92 asm( 93 "sync \n" 94 "isync \n" 95 "lis %r1,stack@ha \n" 96 "addi %r1,%r1,stack@l \n" 97 "addi %r1,%r1,8192 \n"); 98 #endif 99 syncicache((void *)RELOC, etext - (char *)RELOC); 100 101 bat_init(); 102 openfirmware = openfirm; /* Save entry to Open Firmware */ 103 #ifdef ENABLE_DECREMENTER_WORKAROUND 104 patch_dec_intr(); 105 #endif 106 setup(); 107 main(arg, argl); 108 exit(); 109 } 110 111 #ifdef ENABLE_DECREMENTER_WORKAROUND 112 void handle_decr_intr(); 113 __asm ( " .globl handle_decr_intr\n" 114 " .type handle_decr_intr@function\n" 115 "handle_decr_intr:\n" 116 " rfi\n"); 117 118 void 119 patch_dec_intr() 120 { 121 int time; 122 unsigned int *decr_intr = (unsigned int *)0x900; 123 unsigned int br_instr; 124 125 /* this hack is to prevent unexpected Decrementer Exceptions 126 * when Apple openfirmware enables interrupts 127 */ 128 time = 0x40000000; 129 asm("mtdec %0" :: "r"(time)); 130 131 /* we assume that handle_decr_intr is in the first 128 Meg */ 132 br_instr = (18 << 23) | (unsigned int)handle_decr_intr; 133 *decr_intr = br_instr; 134 } 135 #endif 136 137 __dead void 138 _rtt() 139 { 140 static struct { 141 char *name; 142 int nargs; 143 int nreturns; 144 } args = { 145 "exit", 146 0, 147 0 148 }; 149 150 openfirmware(&args); 151 while (1); /* just in case */ 152 } 153 154 int 155 OF_finddevice(char *name) 156 { 157 static struct { 158 char *name; 159 int nargs; 160 int nreturns; 161 char *device; 162 int phandle; 163 } args = { 164 "finddevice", 165 1, 166 1, 167 }; 168 169 args.device = name; 170 if (openfirmware(&args) == -1) 171 return -1; 172 return args.phandle; 173 } 174 175 int 176 OF_instance_to_package(int ihandle) 177 { 178 static struct { 179 char *name; 180 int nargs; 181 int nreturns; 182 int ihandle; 183 int phandle; 184 } args = { 185 "instance-to-package", 186 1, 187 1, 188 }; 189 190 args.ihandle = ihandle; 191 if (openfirmware(&args) == -1) 192 return -1; 193 return args.phandle; 194 } 195 196 int 197 OF_getprop(int handle, char *prop, void *buf, int buflen) 198 { 199 static struct { 200 char *name; 201 int nargs; 202 int nreturns; 203 int phandle; 204 char *prop; 205 void *buf; 206 int buflen; 207 int size; 208 } args = { 209 "getprop", 210 4, 211 1, 212 }; 213 214 args.phandle = handle; 215 args.prop = prop; 216 args.buf = buf; 217 args.buflen = buflen; 218 if (openfirmware(&args) == -1) 219 return -1; 220 return args.size; 221 } 222 223 int 224 OF_open(char *dname) 225 { 226 static struct { 227 char *name; 228 int nargs; 229 int nreturns; 230 char *dname; 231 int handle; 232 } args = { 233 "open", 234 1, 235 1, 236 }; 237 238 args.dname = dname; 239 if (openfirmware(&args) == -1) 240 return -1; 241 return args.handle; 242 } 243 244 void 245 OF_close(int handle) 246 { 247 static struct { 248 char *name; 249 int nargs; 250 int nreturns; 251 int handle; 252 } args = { 253 "close", 254 1, 255 0, 256 }; 257 258 args.handle = handle; 259 openfirmware(&args); 260 } 261 262 int 263 OF_write(int handle, void *addr, int len) 264 { 265 static struct { 266 char *name; 267 int nargs; 268 int nreturns; 269 int ihandle; 270 void *addr; 271 int len; 272 int actual; 273 } args = { 274 "write", 275 3, 276 1, 277 }; 278 279 args.ihandle = handle; 280 args.addr = addr; 281 args.len = len; 282 if (openfirmware(&args) == -1) 283 return -1; 284 return args.actual; 285 } 286 287 int 288 OF_read(int handle, void *addr, int len) 289 { 290 static struct { 291 char *name; 292 int nargs; 293 int nreturns; 294 int ihandle; 295 void *addr; 296 int len; 297 int actual; 298 } args = { 299 "read", 300 3, 301 1, 302 }; 303 304 args.ihandle = handle; 305 args.addr = addr; 306 args.len = len; 307 if (openfirmware(&args) == -1) 308 return -1; 309 return args.actual; 310 } 311 312 int 313 OF_seek(int handle, u_quad_t pos) 314 { 315 static struct { 316 char *name; 317 int nargs; 318 int nreturns; 319 int handle; 320 int poshi; 321 int poslo; 322 int status; 323 } args = { 324 "seek", 325 3, 326 1, 327 }; 328 329 args.handle = handle; 330 args.poshi = (int)(pos >> 32); 331 args.poslo = (int)pos; 332 if (openfirmware(&args) == -1) 333 return -1; 334 return args.status; 335 } 336 337 void * 338 OF_claim(void *virt, u_int size, u_int align) 339 { 340 static struct { 341 char *name; 342 int nargs; 343 int nreturns; 344 void *virt; 345 u_int size; 346 u_int align; 347 void *baseaddr; 348 } args = { 349 "claim", 350 3, 351 1, 352 }; 353 354 args.virt = virt; 355 args.size = size; 356 args.align = align; 357 if (openfirmware(&args) == -1) 358 return (void *)-1; 359 if (virt != 0) 360 return virt; 361 return args.baseaddr; 362 } 363 364 void 365 OF_release(void *virt, u_int size) 366 { 367 static struct { 368 char *name; 369 int nargs; 370 int nreturns; 371 void *virt; 372 u_int size; 373 } args = { 374 "release", 375 2, 376 0, 377 }; 378 379 args.virt = virt; 380 args.size = size; 381 openfirmware(&args); 382 } 383 384 int 385 OF_milliseconds() 386 { 387 static struct { 388 char *name; 389 int nargs; 390 int nreturns; 391 int ms; 392 } args = { 393 "milliseconds", 394 0, 395 1, 396 }; 397 398 openfirmware(&args); 399 return args.ms; 400 } 401 402 #ifdef __notyet__ 403 void 404 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 405 { 406 static struct { 407 char *name; 408 int nargs; 409 int nreturns; 410 void *virt; 411 u_int size; 412 void (*entry)(); 413 void *arg; 414 u_int len; 415 } args = { 416 "chain", 417 5, 418 0, 419 }; 420 421 args.virt = virt; 422 args.size = size; 423 args.entry = entry; 424 args.arg = arg; 425 args.len = len; 426 openfirmware(&args); 427 } 428 #else 429 void 430 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 431 { 432 /* 433 * This is a REALLY dirty hack till the firmware gets this going 434 OF_release(virt, size); 435 */ 436 entry(0, 0, openfirmware, arg, len); 437 } 438 #endif 439 440 int 441 OF_call_method(char *method, int ihandle, int nargs, int nreturns, ...) 442 { 443 va_list ap; 444 static struct { 445 char *name; 446 int nargs; 447 int nreturns; 448 char *method; 449 int ihandle; 450 int args_n_results[12]; 451 } args = { 452 "call-method", 453 2, 454 1, 455 }; 456 int *ip, n; 457 458 if (nargs > 6) 459 return -1; 460 args.nargs = nargs + 2; 461 args.nreturns = nreturns + 1; 462 args.method = method; 463 args.ihandle = ihandle; 464 va_start(ap, nreturns); 465 for (ip = args.args_n_results + (n = nargs); --n >= 0;) 466 *--ip = va_arg(ap, int); 467 468 if (openfirmware(&args) == -1) { 469 va_end(ap); 470 return -1; 471 } 472 if (args.args_n_results[nargs]) { 473 va_end(ap); 474 return args.args_n_results[nargs]; 475 } 476 for (ip = args.args_n_results + nargs + (n = args.nreturns); --n > 0;) 477 *va_arg(ap, int *) = *--ip; 478 va_end(ap); 479 return 0; 480 } 481 482 static int stdin; 483 static int stdout; 484 485 static void 486 setup() 487 { 488 int chosen; 489 490 if ((chosen = OF_finddevice("/chosen")) == -1) 491 _rtt(); 492 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != sizeof(stdin) 493 || OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != 494 sizeof(stdout)) 495 _rtt(); 496 if (stdout == 0) { 497 /* screen should be console, but it is not open */ 498 stdout = OF_open("screen"); 499 } 500 } 501 502 void 503 putchar(int c) 504 { 505 char ch = c; 506 if (c == '\177') { 507 ch = '\b'; 508 OF_write(stdout, &ch, 1); 509 ch = ' '; 510 OF_write(stdout, &ch, 1); 511 ch = '\b'; 512 } 513 if (c == '\n') 514 putchar('\r'); 515 OF_write(stdout, &ch, 1); 516 } 517 518 void 519 ofc_probe(struct consdev *cn) 520 { 521 cn->cn_pri = CN_LOWPRI; 522 cn->cn_dev = makedev(0,0); /* WTF */ 523 } 524 525 526 void 527 ofc_init(struct consdev *cn) 528 { 529 } 530 531 char buffered_char; 532 int 533 ofc_getc(dev_t dev) 534 { 535 u_int8_t ch; 536 int l; 537 538 if (dev & 0x80) { 539 if (buffered_char != 0) 540 return 1; 541 542 l = OF_read(stdin, &ch, 1); 543 if (l == 1) { 544 buffered_char = ch; 545 return 1; 546 } 547 return 0; 548 } 549 550 if (buffered_char != 0) { 551 ch = buffered_char; 552 buffered_char = 0; 553 return ch; 554 } 555 556 while ((l = OF_read(stdin, &ch, 1)) != 1) 557 if (l != -2 && l != 0) 558 return 0; 559 return ch; 560 561 } 562 563 void 564 ofc_putc(dev_t dev, int c) 565 { 566 char ch; 567 568 ch = 'a'; 569 OF_write(stdout, &ch, 1); 570 ch = c; 571 if (c == '\177' && c == '\b') { 572 ch = 'A'; 573 } 574 OF_write(stdout, &ch, 1); 575 } 576 577 578 void 579 machdep() 580 { 581 cninit(); 582 } 583