1/* $OpenBSD: Locore.c,v 1.18 2022/10/21 21:26:49 gkoehler 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 <macppc/stand/openfirm.h> 36#include <dev/cons.h> 37 38#include "libsa.h" 39 40int main(void); 41 42#define ENABLE_DECREMENTER_WORKAROUND 43void bat_init(void); 44void patch_dec_intr(void); 45 46__dead void exit(void); 47 48static int (*openfirmware)(void *); 49 50static void setup(void); 51 52asm (".text; .globl _entry; _entry: .long _start,0,0"); 53asm(" .text \n" 54" .globl bat_init \n" 55"bat_init: \n" 56" \n" 57" mfmsr 8 \n" 58" li 0,0 \n" 59" mtmsr 0 \n" 60" isync \n" 61" \n" 62" mtibatu 0,0 \n" 63" mtibatu 1,0 \n" 64" mtibatu 2,0 \n" 65" mtibatu 3,0 \n" 66" mtdbatu 0,0 \n" 67" mtdbatu 1,0 \n" 68" mtdbatu 2,0 \n" 69" mtdbatu 3,0 \n" 70" \n" 71" li 9,0x12 \n" /* BATL(0, BAT_M, BAT_PP_RW) */ 72" mtibatl 0,9 \n" 73" mtdbatl 0,9 \n" 74" li 9,0x1ffe \n" /* BATU(0, BAT_BL_256M, BAT_Vs) */ 75" mtibatu 0,9 \n" 76" mtdbatu 0,9 \n" 77" isync \n" 78" \n" 79" mtmsr 8 \n" 80" isync \n" 81" blr \n"); 82 83#ifdef XCOFF_GLUE 84static int stack[8192/4 + 4] __attribute__((__used__)); 85#endif 86 87__dead void 88_start(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl) 89{ 90 extern char etext[]; 91 92#ifdef XCOFF_GLUE 93 asm( 94 "sync \n" 95 "isync \n" 96 "lis %r1,stack@ha \n" 97 "addi %r1,%r1,stack@l \n" 98 "addi %r1,%r1,8192 \n"); 99#endif 100 syncicache((void *)RELOC, etext - (char *)RELOC); 101 102 bat_init(); 103 openfirmware = openfirm; /* Save entry to Open Firmware */ 104#ifdef ENABLE_DECREMENTER_WORKAROUND 105 patch_dec_intr(); 106#endif 107 setup(); 108 main(); 109 exit(); 110} 111 112#ifdef ENABLE_DECREMENTER_WORKAROUND 113void handle_decr_intr(); 114__asm ( " .globl handle_decr_intr\n" 115 "handle_decr_intr:\n" 116 " rfi\n"); 117 118void 119patch_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 154int 155OF_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 175int 176OF_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 196int 197OF_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 223int 224OF_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 244void 245OF_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 262int 263OF_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 287int 288OF_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 312int 313OF_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 337void * 338OF_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 364void 365OF_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 384int 385OF_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__ 403void 404OF_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 429void 430OF_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 440int 441OF_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 482static int stdin; 483static int stdout; 484 485static void 486setup() 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 502void 503putchar(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 518void 519ofc_probe(struct consdev *cn) 520{ 521 cn->cn_pri = CN_LOWPRI; 522 cn->cn_dev = makedev(0,0); /* WTF */ 523} 524 525 526void 527ofc_init(struct consdev *cn) 528{ 529} 530 531char buffered_char; 532int 533ofc_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 563void 564ofc_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 578void 579machdep() 580{ 581 cninit(); 582} 583