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