1 /* $NetBSD: promdev.c,v 1.6 1998/10/12 21:17:28 pk Exp $ */ 2 3 /* 4 * Copyright (c) 1993 Paul Kranenburg 5 * Copyright (c) 1995 Gordon W. Ross 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 Paul Kranenburg. 19 * 4. The name of the author 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 THE AUTHOR ``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 THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Note: the `#ifndef BOOTXX' in here serve to queeze the code size 36 * of the 1st-stage boot program. 37 */ 38 #include <sys/param.h> 39 #include <sys/reboot.h> 40 #include <machine/idprom.h> 41 #include <machine/oldmon.h> 42 #include <machine/ctlreg.h> 43 #include <sparc/sparc/asm.h> 44 #include <machine/pte.h> 45 46 #include <lib/libsa/stand.h> 47 48 #include <sparc/stand/common/promdev.h> 49 50 int obp_close __P((struct open_file *)); 51 int obp_strategy __P((void *, int, daddr_t, size_t, void *, size_t *)); 52 ssize_t obp_xmit __P((struct promdata *, void *, size_t)); 53 ssize_t obp_recv __P((struct promdata *, void *, size_t)); 54 int prom0_close __P((struct open_file *)); 55 int prom0_strategy __P((void *, int, daddr_t, size_t, void *, size_t *)); 56 void prom0_iclose __P((struct saioreq *)); 57 int prom0_iopen __P((struct promdata *)); 58 ssize_t prom0_xmit __P((struct promdata *, void *, size_t)); 59 ssize_t prom0_recv __P((struct promdata *, void *, size_t)); 60 61 static char *prom_mapin __P((u_long, int, int)); 62 63 int getdevtype __P((int, char *)); 64 int getpropval __P((int, char *, void *, int)); 65 char *getpropstring __P((int, char *)); 66 67 static void prom0_fake __P((void)); 68 69 extern struct filesystem file_system_nfs[]; 70 extern struct filesystem file_system_ufs[]; 71 72 int prom_open __P((struct open_file *f, ...)) { return 0; } 73 int prom_ioctl __P((struct open_file *f, u_long c, void *d)) { return EIO; } 74 75 struct devsw devsw[] = { 76 { "prom0", prom0_strategy, prom_open, prom0_close, prom_ioctl }, 77 { "prom", obp_strategy, prom_open, obp_close, prom_ioctl } 78 }; 79 80 int ndevs = (sizeof(devsw)/sizeof(devsw[0])); 81 82 char *prom_bootdevice; 83 char *prom_bootfile; 84 int prom_boothow; 85 86 struct promvec *promvec; 87 static int saveecho; 88 89 void 90 prom_init() 91 { 92 static char storage[1024]; 93 char *ap, *cp, *dp; 94 95 if (cputyp == CPU_SUN4) 96 prom0_fake(); 97 98 if (promvec->pv_romvec_vers >= 2) { 99 char *ep = storage + sizeof(storage) - 1; 100 101 prom_bootdevice = *promvec->pv_v2bootargs.v2_bootpath; 102 103 #ifndef BOOTXX 104 cp = *promvec->pv_v2bootargs.v2_bootargs; 105 dp = prom_bootfile = storage; 106 107 /* Skip whitespace */ 108 while (*cp != 0 && (*cp == ' ' || *cp == '\t')) 109 cp++; 110 111 /* Check for options */ 112 if (cp[0] == '-' && 113 (cp[1] == 'a' || cp[1] == 's' || cp[1] == 'd')) 114 cp++; 115 else { 116 /* Copy kernel name */ 117 while (*cp != 0 && *cp != ' ' && *cp != '\t') { 118 if (dp >= ep) { 119 printf("v2_bootargs too long\n"); 120 _rtt(); 121 } 122 *dp++ = *cp++; 123 } 124 125 *dp = '\0'; 126 /* Skip whitespace */ 127 while (*cp != 0 && (*cp == ' ' || *cp == '\t')) 128 cp++; 129 } 130 131 ap = cp; 132 #endif 133 } else { 134 dp = prom_bootdevice = storage; 135 cp = (*promvec->pv_v0bootargs)->ba_argv[0]; 136 while (*cp) { 137 *dp++ = *cp; 138 if (*cp++ == ')') 139 break; 140 } 141 *dp = '\0'; 142 #ifndef BOOTXX 143 prom_bootfile = (*promvec->pv_v0bootargs)->ba_kernel; 144 ap = (*promvec->pv_v0bootargs)->ba_argv[1]; 145 #endif 146 } 147 148 #ifndef BOOTXX 149 if (ap == NULL || *ap++ != '-') 150 return; 151 152 while (*ap && *ap != ' ' && *ap != '\t' && *ap != '\n') { 153 switch (*ap) { 154 case 'a': 155 prom_boothow |= RB_ASKNAME; 156 break; 157 case 's': 158 prom_boothow |= RB_SINGLE; 159 break; 160 case 'd': 161 prom_boothow |= RB_KDB; 162 debug = 1; 163 break; 164 } 165 ap++; 166 } 167 #endif 168 } 169 170 int 171 devopen(f, fname, file) 172 struct open_file *f; 173 const char *fname; 174 char **file; 175 { 176 int error = 0, fd; 177 struct promdata *pd; 178 179 pd = (struct promdata *)alloc(sizeof *pd); 180 181 if (cputyp == CPU_SUN4) { 182 error = prom0_iopen(pd); 183 #ifndef BOOTXX 184 pd->xmit = prom0_xmit; 185 pd->recv = prom0_recv; 186 #endif 187 } else { 188 fd = (promvec->pv_romvec_vers >= 2) 189 ? (*promvec->pv_v2devops.v2_open)(prom_bootdevice) 190 : (*promvec->pv_v0devops.v0_open)(prom_bootdevice); 191 if (fd == 0) { 192 error = ENXIO; 193 } else { 194 pd->fd = fd; 195 #ifndef BOOTXX 196 pd->xmit = obp_xmit; 197 pd->recv = obp_recv; 198 #endif 199 } 200 } 201 202 if (error) { 203 printf("Can't open device `%s'\n", prom_bootdevice); 204 return (error); 205 } 206 207 #ifdef BOOTXX 208 pd->devtype = DT_BLOCK; 209 #else /* BOOTXX */ 210 pd->devtype = getdevtype(fd, prom_bootdevice); 211 /* Assume type BYTE is a raw device */ 212 if (pd->devtype != DT_BYTE) 213 *file = (char *)fname; 214 215 if (pd->devtype == DT_NET) { 216 bcopy(file_system_nfs, file_system, sizeof(struct fs_ops)); 217 if ((error = net_open(pd)) != 0) { 218 printf("Can't open network device `%s'\n", 219 prom_bootdevice); 220 return error; 221 } 222 } else 223 bcopy(file_system_ufs, file_system, sizeof(struct fs_ops)); 224 #endif /* BOOTXX */ 225 226 f->f_dev = &devsw[cputyp == CPU_SUN4 ? 0 : 1]; 227 f->f_devdata = (void *)pd; 228 return 0; 229 } 230 231 int 232 obp_strategy(devdata, flag, dblk, size, buf, rsize) 233 void *devdata; 234 int flag; 235 daddr_t dblk; 236 size_t size; 237 void *buf; 238 size_t *rsize; 239 { 240 int error = 0; 241 struct promdata *pd = (struct promdata *)devdata; 242 int fd = pd->fd; 243 244 #ifdef DEBUG_PROM 245 printf("promstrategy: size=%d dblk=%d\n", size, dblk); 246 #endif 247 248 if (promvec->pv_romvec_vers >= 2) { 249 if (pd->devtype == DT_BLOCK) 250 (*promvec->pv_v2devops.v2_seek)(fd, 0, dbtob(dblk)); 251 252 *rsize = (*((flag == F_READ) 253 ? (u_int (*)())promvec->pv_v2devops.v2_read 254 : (u_int (*)())promvec->pv_v2devops.v2_write 255 ))(fd, buf, size); 256 } else { 257 int n = (*((flag == F_READ) 258 ? (u_int (*)())promvec->pv_v0devops.v0_rbdev 259 : (u_int (*)())promvec->pv_v0devops.v0_wbdev 260 ))(fd, btodb(size), dblk, buf); 261 *rsize = dbtob(n); 262 } 263 264 #ifdef DEBUG_PROM 265 printf("rsize = %x\n", *rsize); 266 #endif 267 return error; 268 } 269 270 /* 271 * On old-monitor machines, things work differently. 272 */ 273 int 274 prom0_strategy(devdata, flag, dblk, size, buf, rsize) 275 void *devdata; 276 int flag; 277 daddr_t dblk; 278 size_t size; 279 void *buf; 280 size_t *rsize; 281 { 282 struct promdata *pd = devdata; 283 struct saioreq *si; 284 struct om_boottable *ops; 285 char *dmabuf; 286 int si_flag; 287 size_t xcnt; 288 289 si = pd->si; 290 ops = si->si_boottab; 291 292 #ifdef DEBUG_PROM 293 printf("prom_strategy: size=%d dblk=%d\n", size, dblk); 294 #endif 295 296 dmabuf = dvma_mapin(buf, size); 297 298 si->si_bn = dblk; 299 si->si_ma = dmabuf; 300 si->si_cc = size; 301 302 si_flag = (flag == F_READ) ? SAIO_F_READ : SAIO_F_WRITE; 303 xcnt = (*ops->b_strategy)(si, si_flag); 304 dvma_mapout(dmabuf, size); 305 306 #ifdef DEBUG_PROM 307 printf("disk_strategy: xcnt = %x\n", xcnt); 308 #endif 309 310 if (xcnt <= 0) 311 return (EIO); 312 313 *rsize = xcnt; 314 return (0); 315 } 316 317 int 318 obp_close(f) 319 struct open_file *f; 320 { 321 struct promdata *pd = f->f_devdata; 322 register int fd = pd->fd; 323 324 #ifndef BOOTXX 325 if (pd->devtype == DT_NET) 326 net_close(pd); 327 #endif 328 if (promvec->pv_romvec_vers >= 2) 329 (void)(*promvec->pv_v2devops.v2_close)(fd); 330 else 331 (void)(*promvec->pv_v0devops.v0_close)(fd); 332 return 0; 333 } 334 335 int 336 prom0_close(f) 337 struct open_file *f; 338 { 339 struct promdata *pd = f->f_devdata; 340 341 #ifndef BOOTXX 342 if (pd->devtype == DT_NET) 343 net_close(pd); 344 #endif 345 prom0_iclose(pd->si); 346 pd->si = NULL; 347 *romp->echo = saveecho; /* Hmm, probably must go somewhere else */ 348 return 0; 349 } 350 351 #ifndef BOOTXX 352 ssize_t 353 obp_xmit(pd, buf, len) 354 struct promdata *pd; 355 void *buf; 356 size_t len; 357 { 358 return (promvec->pv_romvec_vers >= 2 359 ? (*promvec->pv_v2devops.v2_write)(pd->fd, buf, len) 360 : (*promvec->pv_v0devops.v0_wnet)(pd->fd, len, buf)); 361 } 362 363 ssize_t 364 obp_recv(pd, buf, len) 365 struct promdata *pd; 366 void *buf; 367 size_t len; 368 { 369 int n; 370 371 n = (promvec->pv_romvec_vers >= 2 372 ? (*promvec->pv_v2devops.v2_read)(pd->fd, buf, len) 373 : (*promvec->pv_v0devops.v0_rnet)(pd->fd, len, buf)); 374 return (n == -2 ? 0 : n); 375 } 376 377 ssize_t 378 prom0_xmit(pd, buf, len) 379 struct promdata *pd; 380 void *buf; 381 size_t len; 382 { 383 struct saioreq *si; 384 struct saif *sif; 385 char *dmabuf; 386 int rv; 387 388 si = pd->si; 389 sif = si->si_sif; 390 if (sif == NULL) { 391 printf("xmit: not a network device\n"); 392 return (-1); 393 } 394 dmabuf = dvma_mapin(buf, len); 395 rv = sif->sif_xmit(si->si_devdata, dmabuf, len); 396 dvma_mapout(dmabuf, len); 397 398 return (ssize_t)(rv ? -1 : len); 399 } 400 401 ssize_t 402 prom0_recv(pd, buf, len) 403 struct promdata *pd; 404 void *buf; 405 size_t len; 406 { 407 struct saioreq *si; 408 struct saif *sif; 409 char *dmabuf; 410 int rv; 411 412 si = pd->si; 413 sif = si->si_sif; 414 dmabuf = dvma_mapin(buf, len); 415 rv = sif->sif_poll(si->si_devdata, dmabuf); 416 dvma_mapout(dmabuf, len); 417 418 return (ssize_t)rv; 419 } 420 421 int 422 getchar() 423 { 424 char c; 425 register int n; 426 427 if (promvec->pv_romvec_vers > 2) 428 while ((n = (*promvec->pv_v2devops.v2_read) 429 (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1)) != 1); 430 else 431 c = (*promvec->pv_getchar)(); 432 433 if (c == '\r') 434 c = '\n'; 435 return (c); 436 } 437 438 int 439 peekchar() 440 { 441 char c; 442 register int n; 443 444 if (promvec->pv_romvec_vers > 2) { 445 n = (*promvec->pv_v2devops.v2_read) 446 (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 1); 447 if (n < 0) 448 return -1; 449 } else 450 c = (*promvec->pv_nbgetchar)(); 451 452 if (c == '\r') 453 c = '\n'; 454 return (c); 455 } 456 #endif 457 458 static void 459 pv_putchar(c) 460 int c; 461 { 462 char c0 = c; 463 464 if (promvec->pv_romvec_vers > 2) 465 (*promvec->pv_v2devops.v2_write) 466 (*promvec->pv_v2bootargs.v2_fd1, &c0, 1); 467 else 468 (*promvec->pv_putchar)(c); 469 } 470 471 void 472 putchar(c) 473 int c; 474 { 475 476 if (c == '\n') 477 pv_putchar('\r'); 478 pv_putchar(c); 479 } 480 481 void 482 _rtt() 483 { 484 promvec->pv_halt(); 485 } 486 487 #ifndef BOOTXX 488 int hz = 1000; 489 490 time_t 491 getsecs() 492 { 493 register int ticks = getticks(); 494 return ((time_t)(ticks / hz)); 495 } 496 497 int 498 getticks() 499 { 500 if (promvec->pv_romvec_vers >= 2) { 501 char c; 502 (void)(*promvec->pv_v2devops.v2_read) 503 (*promvec->pv_v2bootargs.v2_fd0, (caddr_t)&c, 0); 504 } else { 505 (void)(*promvec->pv_nbgetchar)(); 506 } 507 return *(promvec->pv_ticks); 508 } 509 510 void 511 prom_getether(fd, ea) 512 u_char *ea; 513 { 514 if (cputyp == CPU_SUN4) { 515 static struct idprom sun4_idprom; 516 u_char *src, *dst; 517 int len, x; 518 519 if (sun4_idprom.id_format == 0) { 520 dst = (char*)&sun4_idprom; 521 src = (char*)AC_IDPROM; 522 len = sizeof(struct idprom); 523 do { 524 x = lduba(src++, ASI_CONTROL); 525 *dst++ = x; 526 } while (--len > 0); 527 } 528 bcopy(sun4_idprom.id_ether, ea, 6); 529 } else if (promvec->pv_romvec_vers <= 2) { 530 (void)(*promvec->pv_enaddr)(fd, (char *)ea); 531 } else { 532 char buf[64]; 533 sprintf(buf, "%x mac-address drop swap 6 cmove", ea); 534 promvec->pv_fortheval.v2_eval(buf); 535 } 536 } 537 538 539 /* 540 * A number of well-known devices on sun4s. 541 */ 542 static struct dtab { 543 char *name; 544 int type; 545 } dtab[] = { 546 { "sd", DT_BLOCK }, 547 { "st", DT_BLOCK }, 548 { "xd", DT_BLOCK }, 549 { "xy", DT_BLOCK }, 550 { "fd", DT_BLOCK }, 551 { "le", DT_NET }, 552 { "ie", DT_NET }, 553 { NULL, 0 } 554 }; 555 556 int 557 getdevtype(fd, name) 558 int fd; 559 char *name; 560 { 561 if (promvec->pv_romvec_vers >= 2) { 562 int node = (*promvec->pv_v2devops.v2_fd_phandle)(fd); 563 char *cp = getpropstring(node, "device_type"); 564 if (strcmp(cp, "block") == 0) 565 return DT_BLOCK; 566 else if (strcmp(cp, "network") == 0) 567 return DT_NET; 568 else if (strcmp(cp, "byte") == 0) 569 return DT_BYTE; 570 } else { 571 struct dtab *dp; 572 for (dp = dtab; dp->name; dp++) { 573 if (name[0] == dp->name[0] && 574 name[1] == dp->name[1]) 575 return dp->type; 576 } 577 } 578 return 0; 579 } 580 581 /* 582 * OpenPROM nodes & property routines (from <sparc/autoconf.c>). 583 */ 584 int 585 getpropval(node, name, buf, bufsiz) 586 int node; 587 char *name; 588 void *buf; 589 register int bufsiz; 590 { 591 register struct nodeops *no; 592 register int len; 593 594 no = promvec->pv_nodeops; 595 len = no->no_proplen(node, name); 596 if (len > bufsiz) { 597 printf("node %x property %s length %d > %d\n", 598 node, name, len, bufsiz); 599 return (0); 600 } 601 no->no_getprop(node, name, buf); 602 return (len); 603 } 604 605 /* 606 * Return a string property. There is a (small) limit on the length; 607 * the string is fetched into a static buffer which is overwritten on 608 * subsequent calls. 609 */ 610 char * 611 getpropstring(node, name) 612 int node; 613 char *name; 614 { 615 register int len; 616 static char stringbuf[64]; 617 618 len = getpropval(node, name, (void *)stringbuf, sizeof stringbuf - 1); 619 if (len == -1) 620 len = 0; 621 stringbuf[len] = '\0'; /* usually unnecessary */ 622 return (stringbuf); 623 } 624 #endif /* BOOTXX */ 625 626 /* 627 * Old monitor routines 628 */ 629 630 struct saioreq prom_si; 631 static int promdev_inuse; 632 633 int 634 prom0_iopen(pd) 635 struct promdata *pd; 636 { 637 struct om_bootparam *bp; 638 struct om_boottable *ops; 639 struct devinfo *dip; 640 struct saioreq *si; 641 int error; 642 643 if (promdev_inuse) 644 return(EMFILE); 645 646 bp = *romp->bootParam; 647 ops = bp->bootTable; 648 dip = ops->b_devinfo; 649 650 #ifdef DEBUG_PROM 651 printf("Boot device type: %s\n", ops->b_desc); 652 printf("d_devbytes=%d\n", dip->d_devbytes); 653 printf("d_dmabytes=%d\n", dip->d_dmabytes); 654 printf("d_localbytes=%d\n", dip->d_localbytes); 655 printf("d_stdcount=%d\n", dip->d_stdcount); 656 printf("d_stdaddrs[%d]=%x\n", bp->ctlrNum, dip->d_stdaddrs[bp->ctlrNum]); 657 printf("d_devtype=%d\n", dip->d_devtype); 658 printf("d_maxiobytes=%d\n", dip->d_maxiobytes); 659 #endif 660 661 dvma_init(); 662 663 si = &prom_si; 664 bzero((caddr_t)si, sizeof(*si)); 665 si->si_boottab = ops; 666 si->si_ctlr = bp->ctlrNum; 667 si->si_unit = bp->unitNum; 668 si->si_boff = bp->partNum; 669 670 if (si->si_ctlr > dip->d_stdcount) { 671 printf("Invalid controller number\n"); 672 return(ENXIO); 673 } 674 675 if (dip->d_devbytes) { 676 si->si_devaddr = prom_mapin(dip->d_stdaddrs[si->si_ctlr], 677 dip->d_devbytes, dip->d_devtype); 678 #ifdef DEBUG_PROM 679 printf("prom_iopen: devaddr=0x%x pte=0x%x\n", 680 si->si_devaddr, 681 getpte4((u_long)si->si_devaddr & ~PGOFSET)); 682 #endif 683 } 684 685 if (dip->d_dmabytes) { 686 si->si_dmaaddr = dvma_alloc(dip->d_dmabytes); 687 #ifdef DEBUG_PROM 688 printf("prom_iopen: dmaaddr=0x%x\n", si->si_dmaaddr); 689 #endif 690 } 691 692 if (dip->d_localbytes) { 693 si->si_devdata = alloc(dip->d_localbytes); 694 #ifdef DEBUG_PROM 695 printf("prom_iopen: devdata=0x%x\n", si->si_devdata); 696 #endif 697 } 698 699 /* OK, call the PROM device open routine. */ 700 error = (*ops->b_open)(si); 701 if (error != 0) { 702 printf("prom_iopen: \"%s\" error=%d\n", 703 ops->b_desc, error); 704 return (ENXIO); 705 } 706 #ifdef DEBUG_PROM 707 printf("prom_iopen: succeeded, error=%d\n", error); 708 #endif 709 710 pd->si = si; 711 promdev_inuse++; 712 return (0); 713 } 714 715 void 716 prom0_iclose(si) 717 struct saioreq *si; 718 { 719 struct om_boottable *ops; 720 struct devinfo *dip; 721 722 if (promdev_inuse == 0) 723 return; 724 725 ops = si->si_boottab; 726 dip = ops->b_devinfo; 727 728 (*ops->b_close)(si); 729 730 if (si->si_dmaaddr) { 731 dvma_free(si->si_dmaaddr, dip->d_dmabytes); 732 si->si_dmaaddr = NULL; 733 } 734 735 promdev_inuse = 0; 736 } 737 738 static struct mapinfo { 739 int maptype; 740 int pgtype; 741 int base; 742 } prom_mapinfo[] = { 743 { MAP_MAINMEM, PG_OBMEM, 0 }, 744 { MAP_OBIO, PG_OBIO, 0 }, 745 { MAP_MBMEM, PG_VME16, 0xFF000000 }, 746 { MAP_MBIO, PG_VME16, 0xFFFF0000 }, 747 { MAP_VME16A16D, PG_VME16, 0xFFFF0000 }, 748 { MAP_VME16A32D, PG_VME32, 0xFFFF0000 }, 749 { MAP_VME24A16D, PG_VME16, 0xFF000000 }, 750 { MAP_VME24A32D, PG_VME32, 0xFF000000 }, 751 { MAP_VME32A16D, PG_VME16, 0 }, 752 { MAP_VME32A32D, PG_VME32, 0 }, 753 }; 754 static prom_mapinfo_cnt = sizeof(prom_mapinfo) / sizeof(prom_mapinfo[0]); 755 756 /* The virtual address we will use for PROM device mappings. */ 757 static u_long prom_devmap = MONSHORTSEG; 758 759 static char * 760 prom_mapin(physaddr, length, maptype) 761 u_long physaddr; 762 int length, maptype; 763 { 764 int i, pa, pte, va; 765 766 if (length > (4*NBPG)) 767 panic("prom_mapin: length=%d\n", length); 768 769 for (i = 0; i < prom_mapinfo_cnt; i++) 770 if (prom_mapinfo[i].maptype == maptype) 771 goto found; 772 panic("prom_mapin: invalid maptype %d\n", maptype); 773 found: 774 775 pte = prom_mapinfo[i].pgtype; 776 pte |= (PG_V|PG_W|PG_S|PG_NC); 777 pa = prom_mapinfo[i].base; 778 pa += physaddr; 779 pte |= ((pa >> PGSHIFT) & PG_PFNUM); 780 781 va = prom_devmap; 782 do { 783 setpte4(va, pte); 784 va += NBPG; 785 pte += 1; 786 length -= NBPG; 787 } while (length > 0); 788 return ((char*)(prom_devmap | (pa & PGOFSET))); 789 } 790 791 void 792 prom0_fake() 793 { 794 static struct promvec promvecstore; 795 796 promvec = &promvecstore; 797 798 promvec->pv_stdin = romp->inSource; 799 promvec->pv_stdout = romp->outSink; 800 promvec->pv_putchar = romp->putChar; 801 promvec->pv_putstr = romp->fbWriteStr; 802 promvec->pv_nbgetchar = romp->mayGet; 803 promvec->pv_getchar = romp->getChar; 804 promvec->pv_romvec_vers = 0; /* eek! */ 805 promvec->pv_reboot = romp->reBoot; 806 promvec->pv_abort = romp->abortEntry; 807 promvec->pv_setctxt = romp->setcxsegmap; 808 promvec->pv_v0bootargs = (struct v0bootargs **)(romp->bootParam); 809 promvec->pv_halt = romp->exitToMon; 810 promvec->pv_ticks = romp->nmiClock; 811 saveecho = *romp->echo; 812 *romp->echo = 0; 813 } 814