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