1 /* $OpenBSD: Locore.c,v 1.14 2016/09/11 17:53:26 jsing Exp $ */ 2 /* $NetBSD: Locore.c,v 1.1 2000/08/20 14:58:36 mrg 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 37 #include "openfirm.h" 38 39 #include <machine/cpu.h> 40 41 static vaddr_t OF_claim_virt(vaddr_t vaddr, int len); 42 static vaddr_t OF_alloc_virt(int len, int align); 43 static int OF_free_virt(vaddr_t vaddr, int len); 44 static vaddr_t OF_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode); 45 static paddr_t OF_alloc_phys(int len, int align); 46 static int OF_free_phys(paddr_t paddr, int len); 47 48 extern int openfirmware(void *); 49 50 void setup(void); 51 52 __dead void 53 _rtt(void) 54 { 55 struct { 56 cell_t name; 57 cell_t nargs; 58 cell_t nreturns; 59 } args; 60 61 #ifdef SOFTRAID 62 sr_clear_keys(); 63 #endif 64 65 args.name = ADR2CELL("exit"); 66 args.nargs = 0; 67 args.nreturns = 0; 68 openfirmware(&args); 69 while (1); /* just in case */ 70 } 71 72 void 73 OF_enter(void) 74 { 75 struct { 76 cell_t name; 77 cell_t nargs; 78 cell_t nreturns; 79 } args; 80 81 args.name = ADR2CELL("enter"); 82 args.nargs = 0; 83 args.nreturns = 0; 84 openfirmware(&args); 85 } 86 87 int 88 OF_finddevice(char *name) 89 { 90 struct { 91 cell_t name; 92 cell_t nargs; 93 cell_t nreturns; 94 cell_t device; 95 cell_t phandle; 96 } args; 97 98 args.name = ADR2CELL("finddevice"); 99 args.nargs = 1; 100 args.nreturns = 1; 101 args.device = ADR2CELL(name); 102 if (openfirmware(&args) == -1) 103 return -1; 104 return args.phandle; 105 } 106 107 int 108 OF_instance_to_package(int ihandle) 109 { 110 struct { 111 cell_t name; 112 cell_t nargs; 113 cell_t nreturns; 114 cell_t ihandle; 115 cell_t phandle; 116 } args; 117 118 args.name = ADR2CELL("instance-to-package"); 119 args.nargs = 1; 120 args.nreturns = 1; 121 args.ihandle = HDL2CELL(ihandle); 122 if (openfirmware(&args) == -1) 123 return -1; 124 return args.phandle; 125 } 126 127 int 128 OF_getprop(int handle, char *prop, void *buf, int buflen) 129 { 130 struct { 131 cell_t name; 132 cell_t nargs; 133 cell_t nreturns; 134 cell_t phandle; 135 cell_t prop; 136 cell_t buf; 137 cell_t buflen; 138 cell_t size; 139 } args; 140 141 args.name = ADR2CELL("getprop"); 142 args.nargs = 4; 143 args.nreturns = 1; 144 args.phandle = HDL2CELL(handle); 145 args.prop = ADR2CELL(prop); 146 args.buf = ADR2CELL(buf); 147 args.buflen = buflen; 148 if (openfirmware(&args) == -1) 149 return -1; 150 return args.size; 151 } 152 153 int 154 OF_open(char *dname) 155 { 156 struct { 157 cell_t name; 158 cell_t nargs; 159 cell_t nreturns; 160 cell_t dname; 161 cell_t handle; 162 } args; 163 164 args.name = ADR2CELL("open"); 165 args.nargs = 1; 166 args.nreturns = 1; 167 args.dname = ADR2CELL(dname); 168 if (openfirmware(&args) == -1 || 169 args.handle == 0) 170 return -1; 171 return args.handle; 172 } 173 174 void 175 OF_close(int handle) 176 { 177 struct { 178 cell_t name; 179 cell_t nargs; 180 cell_t nreturns; 181 cell_t handle; 182 } args; 183 184 args.name = ADR2CELL("close"); 185 args.nargs = 1; 186 args.nreturns = 0; 187 args.handle = HDL2CELL(handle); 188 openfirmware(&args); 189 } 190 191 int 192 OF_write(int handle, void *addr, int len) 193 { 194 struct { 195 cell_t name; 196 cell_t nargs; 197 cell_t nreturns; 198 cell_t ihandle; 199 cell_t addr; 200 cell_t len; 201 cell_t actual; 202 } args; 203 204 args.name = ADR2CELL("write"); 205 args.nargs = 3; 206 args.nreturns = 1; 207 args.ihandle = HDL2CELL(handle); 208 args.addr = ADR2CELL(addr); 209 args.len = len; 210 if (openfirmware(&args) == -1) 211 return -1; 212 return args.actual; 213 } 214 215 int 216 OF_read(int handle, void *addr, int len) 217 { 218 struct { 219 cell_t name; 220 cell_t nargs; 221 cell_t nreturns; 222 cell_t ihandle; 223 cell_t addr; 224 cell_t len; 225 cell_t actual; 226 } args; 227 228 args.name = ADR2CELL("read"); 229 args.nargs = 3; 230 args.nreturns = 1; 231 args.ihandle = HDL2CELL(handle); 232 args.addr = ADR2CELL(addr); 233 args.len = len; 234 if (openfirmware(&args) == -1) { 235 return -1; 236 } 237 return args.actual; 238 } 239 240 int 241 OF_seek(int handle, u_quad_t pos) 242 { 243 struct { 244 cell_t name; 245 cell_t nargs; 246 cell_t nreturns; 247 cell_t handle; 248 cell_t poshi; 249 cell_t poslo; 250 cell_t status; 251 } args; 252 253 args.name = ADR2CELL("seek"); 254 args.nargs = 3; 255 args.nreturns = 1; 256 args.handle = HDL2CELL(handle); 257 args.poshi = HDQ2CELL_HI(pos); 258 args.poslo = HDQ2CELL_LO(pos); 259 if (openfirmware(&args) == -1) { 260 return -1; 261 } 262 return args.status; 263 } 264 265 void 266 OF_release(void *virt, u_int size) 267 { 268 struct { 269 cell_t name; 270 cell_t nargs; 271 cell_t nreturns; 272 cell_t virt; 273 cell_t size; 274 } args; 275 276 args.name = ADR2CELL("release"); 277 args.nargs = 2; 278 args.nreturns = 0; 279 args.virt = ADR2CELL(virt); 280 args.size = size; 281 openfirmware(&args); 282 } 283 284 int 285 OF_milliseconds(void) 286 { 287 struct { 288 cell_t name; 289 cell_t nargs; 290 cell_t nreturns; 291 cell_t ms; 292 } args; 293 294 args.name = ADR2CELL("milliseconds"); 295 args.nargs = 0; 296 args.nreturns = 1; 297 openfirmware(&args); 298 return args.ms; 299 } 300 301 void 302 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len) 303 { 304 extern int64_t romp; 305 306 entry(0, arg, len, (unsigned long)romp, (unsigned long)romp); 307 panic("OF_chain: kernel returned!"); 308 __asm("ta 2" : :); 309 } 310 311 static u_int stdin; 312 static u_int stdout; 313 static u_int mmuh = -1; 314 static u_int memh = -1; 315 316 void 317 setup(void) 318 { 319 u_int chosen; 320 321 if ((chosen = OF_finddevice("/chosen")) == -1) 322 _rtt(); 323 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != sizeof(stdin) 324 || OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != sizeof(stdout) 325 || OF_getprop(chosen, "mmu", &mmuh, sizeof(mmuh)) != sizeof(mmuh) 326 || OF_getprop(chosen, "memory", &memh, sizeof(memh)) != sizeof(memh)) 327 _rtt(); 328 } 329 330 /* 331 * The following need either the handle to memory or the handle to the MMU. 332 */ 333 334 /* 335 * Grab some address space from the prom 336 * 337 * Only works while the prom is actively mapping us. 338 */ 339 static vaddr_t 340 OF_claim_virt(vaddr_t vaddr, int len) 341 { 342 struct { 343 cell_t name; 344 cell_t nargs; 345 cell_t nreturns; 346 cell_t method; 347 cell_t ihandle; 348 cell_t align; 349 cell_t len; 350 cell_t vaddr; 351 cell_t status; 352 cell_t retaddr; 353 } args; 354 355 args.name = ADR2CELL("call-method"); 356 args.nargs = 5; 357 args.nreturns = 2; 358 args.method = ADR2CELL("claim"); 359 args.ihandle = HDL2CELL(mmuh); 360 args.align = 0; 361 args.len = len; 362 args.vaddr = ADR2CELL(vaddr); 363 if (openfirmware(&args) != 0) 364 return -1LL; 365 return (vaddr_t)args.retaddr; 366 } 367 368 /* 369 * Request some address space from the prom 370 * 371 * Only works while the prom is actively mapping us. 372 */ 373 static vaddr_t 374 OF_alloc_virt(int len, int align) 375 { 376 int retaddr=-1; 377 struct { 378 cell_t name; 379 cell_t nargs; 380 cell_t nreturns; 381 cell_t method; 382 cell_t ihandle; 383 cell_t align; 384 cell_t len; 385 cell_t status; 386 cell_t retaddr; 387 } args; 388 389 args.name = ADR2CELL("call-method"); 390 args.nargs = 4; 391 args.nreturns = 2; 392 args.method = ADR2CELL("claim"); 393 args.ihandle = HDL2CELL(mmuh); 394 args.align = align; 395 args.len = len; 396 args.retaddr = ADR2CELL(&retaddr); 397 if (openfirmware(&args) != 0) 398 return -1LL; 399 return (vaddr_t)args.retaddr; 400 } 401 402 /* 403 * Release some address space to the prom 404 * 405 * Only works while the prom is actively mapping us. 406 */ 407 static int 408 OF_free_virt(vaddr_t vaddr, int len) 409 { 410 struct { 411 cell_t name; 412 cell_t nargs; 413 cell_t nreturns; 414 cell_t method; 415 cell_t ihandle; 416 cell_t len; 417 cell_t vaddr; 418 } args; 419 420 args.name = ADR2CELL("call-method"); 421 args.nargs = 4; 422 args.nreturns = 0; 423 args.method = ADR2CELL("release"); 424 args.ihandle = HDL2CELL(mmuh); 425 args.vaddr = ADR2CELL(vaddr); 426 args.len = len; 427 return openfirmware(&args); 428 } 429 430 431 /* 432 * Have prom map in some memory 433 * 434 * Only works while the prom is actively mapping us. 435 */ 436 static vaddr_t 437 OF_map_phys(paddr_t paddr, off_t size, vaddr_t vaddr, int mode) 438 { 439 struct { 440 cell_t name; 441 cell_t nargs; 442 cell_t nreturns; 443 cell_t method; 444 cell_t ihandle; 445 cell_t mode; 446 cell_t size; 447 cell_t vaddr; 448 cell_t paddr_hi; 449 cell_t paddr_lo; 450 cell_t status; 451 cell_t retaddr; 452 } args; 453 454 args.name = ADR2CELL("call-method"); 455 args.nargs = 7; 456 args.nreturns = 1; 457 args.method = ADR2CELL("map"); 458 args.ihandle = HDL2CELL(mmuh); 459 args.mode = mode; 460 args.size = size; 461 args.vaddr = ADR2CELL(vaddr); 462 args.paddr_hi = HDQ2CELL_HI(paddr); 463 args.paddr_lo = HDQ2CELL_LO(paddr); 464 465 if (openfirmware(&args) == -1) 466 return -1; 467 if (args.status) 468 return -1; 469 return (vaddr_t)args.retaddr; 470 } 471 472 473 /* 474 * Request some RAM from the prom 475 * 476 * Only works while the prom is actively mapping us. 477 */ 478 static paddr_t 479 OF_alloc_phys(int len, int align) 480 { 481 struct { 482 cell_t name; 483 cell_t nargs; 484 cell_t nreturns; 485 cell_t method; 486 cell_t ihandle; 487 cell_t align; 488 cell_t len; 489 cell_t status; 490 cell_t phys_hi; 491 cell_t phys_lo; 492 } args; 493 494 args.name = ADR2CELL("call-method"); 495 args.nargs = 4; 496 args.nreturns = 3; 497 args.method = ADR2CELL("claim"); 498 args.ihandle = HDL2CELL(memh); 499 args.align = align; 500 args.len = len; 501 if (openfirmware(&args) != 0) 502 return -1LL; 503 return (paddr_t)CELL2HDQ(args.phys_hi, args.phys_lo); 504 } 505 506 507 /* 508 * Free some RAM to prom 509 * 510 * Only works while the prom is actively mapping us. 511 */ 512 static int 513 OF_free_phys(paddr_t phys, int len) 514 { 515 struct { 516 cell_t name; 517 cell_t nargs; 518 cell_t nreturns; 519 cell_t method; 520 cell_t ihandle; 521 cell_t len; 522 cell_t phys_hi; 523 cell_t phys_lo; 524 } args; 525 526 args.name = ADR2CELL("call-method"); 527 args.nargs = 5; 528 args.nreturns = 0; 529 args.method = ADR2CELL("release"); 530 args.ihandle = HDL2CELL(memh); 531 args.len = len; 532 args.phys_hi = HDQ2CELL_HI(phys); 533 args.phys_lo = HDQ2CELL_LO(phys); 534 return openfirmware(&args); 535 } 536 537 538 /* 539 * Claim virtual memory -- does not map it in. 540 */ 541 542 void * 543 OF_claim(void *virt, u_int size, u_int align) 544 { 545 /* 546 * Sun Ultra machines run the firmware with VM enabled, 547 * so you need to handle allocating and mapping both 548 * virtual and physical memory. Ugh. 549 */ 550 paddr_t paddr; 551 void * newvirt = NULL; 552 553 if (virt == NULL) { 554 virt = (void *)OF_alloc_virt(size, align); 555 if (virt == (void *)-1LL) { 556 printf("OF_alloc_virt(%d,%d) failed w/%x\n", 557 size, align, virt); 558 return virt; 559 } 560 } else { 561 newvirt = (void *)OF_claim_virt((vaddr_t)virt, size); 562 if (newvirt == (void *)-1LL) { 563 printf("OF_claim_virt(%x,%d) failed w/%x\n", 564 virt, size, newvirt); 565 return newvirt; 566 } 567 virt = newvirt; 568 } 569 if ((paddr = OF_alloc_phys(size, align)) == (paddr_t)-1LL) { 570 printf("OF_alloc_phys(%d,%d) failed\n", size, align); 571 OF_free_virt((vaddr_t)virt, size); 572 return (void *)-1LL; 573 } 574 if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) { 575 printf("OF_map_phys(%x,%d,%x,%d) failed\n", 576 paddr, size, virt, -1); 577 OF_free_phys((paddr_t)paddr, size); 578 OF_free_virt((vaddr_t)virt, size); 579 return (void *)-1LL; 580 } 581 return virt; 582 } 583 584 int 585 OF_peer(int phandle) 586 { 587 struct { 588 cell_t name; 589 cell_t nargs; 590 cell_t nreturns; 591 cell_t phandle; 592 cell_t sibling; 593 } args; 594 595 args.name = ADR2CELL("peer"); 596 args.nargs = 1; 597 args.nreturns = 1; 598 args.phandle = HDL2CELL(phandle); 599 if (openfirmware(&args) == -1) 600 return 0; 601 return args.sibling; 602 } 603 604 int 605 OF_child(int phandle) 606 { 607 struct { 608 cell_t name; 609 cell_t nargs; 610 cell_t nreturns; 611 cell_t phandle; 612 cell_t child; 613 } args; 614 615 args.name = ADR2CELL("child"); 616 args.nargs = 1; 617 args.nreturns = 1; 618 args.phandle = HDL2CELL(phandle); 619 if (openfirmware(&args) == -1) 620 return 0; 621 return args.child; 622 } 623 624 int 625 OF_package_to_path(int phandle, char *buf, int buflen) 626 { 627 struct { 628 cell_t name; 629 cell_t nargs; 630 cell_t nreturns; 631 cell_t phandle; 632 cell_t buf; 633 cell_t buflen; 634 cell_t length; 635 } args; 636 637 if (buflen > PAGE_SIZE) 638 return -1; 639 args.name = ADR2CELL("package-to-path"); 640 args.nargs = 3; 641 args.nreturns = 1; 642 args.phandle = HDL2CELL(phandle); 643 args.buf = ADR2CELL(buf); 644 args.buflen = buflen; 645 if (openfirmware(&args) < 0) 646 return -1; 647 return args.length; 648 } 649 650 void 651 putchar(int c) 652 { 653 char ch = c; 654 655 if (c == '\n') 656 putchar('\r'); 657 OF_write(stdout, &ch, 1); 658 } 659 660 int 661 getchar(void) 662 { 663 unsigned char ch = '\0'; 664 int l; 665 666 while ((l = OF_read(stdin, &ch, 1)) != 1) 667 if (l != -2 && l != 0) 668 return -1; 669 return ch; 670 } 671 672 int 673 cngetc(void) 674 { 675 return getchar(); 676 } 677