1 /* $NetBSD: promdev.c,v 1.21 2008/04/05 06:39:08 tsutsui 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 <sys/systm.h> 41 #include <machine/oldmon.h> 42 #include <machine/promlib.h> 43 #include <machine/ctlreg.h> 44 #include <sparc/sparc/asm.h> 45 #include <machine/pte.h> 46 47 #include <lib/libsa/stand.h> 48 #include <lib/libkern/libkern.h> 49 #include <sparc/stand/common/promdev.h> 50 51 #ifndef BOOTXX 52 #include <sys/disklabel.h> 53 #include <dev/sun/disklabel.h> 54 #include <dev/raidframe/raidframevar.h> 55 #endif 56 57 /* OBP V0-3 PROM vector */ 58 #define obpvec ((struct promvec *)romp) 59 60 int obp_close(struct open_file *); 61 int obp_strategy(void *, int, daddr_t, size_t, void *, size_t *); 62 int obp_v0_strategy(void *, int, daddr_t, size_t, void *, size_t *); 63 ssize_t obp_v0_xmit(struct promdata *, void *, size_t); 64 ssize_t obp_v0_recv(struct promdata *, void *, size_t); 65 int obp_v2_strategy(void *, int, daddr_t, size_t, void *, size_t *); 66 ssize_t obp_v2_xmit(struct promdata *, void *, size_t); 67 ssize_t obp_v2_recv(struct promdata *, void *, size_t); 68 int oldmon_close(struct open_file *); 69 int oldmon_strategy(void *, int, daddr_t, size_t, void *, size_t *); 70 void oldmon_iclose(struct saioreq *); 71 int oldmon_iopen(struct promdata *); 72 ssize_t oldmon_xmit(struct promdata *, void *, size_t); 73 ssize_t oldmon_recv(struct promdata *, void *, size_t); 74 75 static char *oldmon_mapin(u_long, int, int); 76 #ifndef BOOTXX 77 static char *mygetpropstring(int, char *); 78 static int getdevtype(int, char *); 79 #endif 80 81 extern struct fs_ops file_system_nfs[]; 82 extern struct fs_ops file_system_ufs[]; 83 84 #define null_devopen (void *)sparc_noop 85 #define null_devioctl (void *)sparc_noop 86 87 #if 0 88 struct devsw devsw[]; 89 int ndevs = (sizeof(devsw)/sizeof(devsw[0])); 90 #endif 91 92 struct devsw oldmon_devsw = 93 { "oldmon", oldmon_strategy, null_devopen, oldmon_close, null_devioctl }; 94 struct devsw obp_v0_devsw = 95 { "obp v0", obp_v0_strategy, null_devopen, obp_close, null_devioctl }; 96 struct devsw obp_v2_devsw = 97 { "obp v2", obp_v2_strategy, null_devopen, obp_close, null_devioctl }; 98 99 100 char prom_bootdevice[MAX_PROM_PATH]; 101 static int saveecho; 102 103 #ifndef BOOTXX 104 static daddr_t doffset = 0; 105 #endif 106 107 108 void 109 putchar(int c) 110 { 111 112 if (c == '\n') 113 prom_putchar('\r'); 114 prom_putchar(c); 115 } 116 117 void 118 _rtt(void) 119 { 120 121 prom_halt(); 122 } 123 124 int 125 devopen(struct open_file *f, const char *fname, char **file) 126 { 127 int error = 0, fd = 0; 128 struct promdata *pd; 129 #ifndef BOOTXX 130 char *partition; 131 int part = 0; 132 char rawpart[MAX_PROM_PATH]; 133 struct promdata *disk_pd; 134 char buf[DEV_BSIZE]; 135 struct disklabel *dlp; 136 size_t read; 137 #endif 138 139 pd = (struct promdata *)alloc(sizeof *pd); 140 f->f_devdata = (void *)pd; 141 142 switch (prom_version()) { 143 case PROM_OLDMON: 144 error = oldmon_iopen(pd); 145 #ifndef BOOTXX 146 pd->xmit = oldmon_xmit; 147 pd->recv = oldmon_recv; 148 #endif 149 f->f_dev = &oldmon_devsw; 150 saveecho = *romVectorPtr->echo; 151 *romVectorPtr->echo = 0; 152 break; 153 154 case PROM_OBP_V0: 155 case PROM_OBP_V2: 156 case PROM_OBP_V3: 157 case PROM_OPENFIRM: 158 if (*prom_bootdevice == '\0') { 159 error = ENXIO; 160 break; 161 } 162 fd = prom_open(prom_bootdevice); 163 if (fd == 0) { 164 error = ENXIO; 165 break; 166 } 167 pd->fd = fd; 168 switch (prom_version()) { 169 case PROM_OBP_V0: 170 #ifndef BOOTXX 171 pd->xmit = obp_v0_xmit; 172 pd->recv = obp_v0_recv; 173 #endif 174 f->f_dev = &obp_v0_devsw; 175 break; 176 case PROM_OBP_V2: 177 case PROM_OBP_V3: 178 case PROM_OPENFIRM: 179 #ifndef BOOTXX 180 pd->xmit = obp_v2_xmit; 181 pd->recv = obp_v2_recv; 182 #endif 183 f->f_dev = &obp_v2_devsw; 184 } 185 } 186 187 if (error) { 188 printf("Can't open device `%s'\n", prom_bootdevice); 189 return (error); 190 } 191 192 #ifdef BOOTXX 193 pd->devtype = DT_BLOCK; 194 #else /* BOOTXX */ 195 pd->devtype = getdevtype(fd, prom_bootdevice); 196 /* Assume type BYTE is a raw device */ 197 if (pd->devtype != DT_BYTE) 198 *file = (char *)fname; 199 200 if (pd->devtype == DT_NET) { 201 nfsys = 1; 202 memcpy(file_system, file_system_nfs, 203 sizeof(struct fs_ops) * nfsys); 204 if ((error = net_open(pd)) != 0) { 205 printf("Can't open NFS network connection on `%s'\n", 206 prom_bootdevice); 207 return (error); 208 } 209 } else { 210 memcpy(file_system, file_system_ufs, 211 sizeof(struct fs_ops) * nfsys); 212 213 #ifdef NOTDEF_DEBUG 214 printf("devopen: Checking disklabel for RAID partition\n"); 215 #endif 216 217 /* 218 * We need to read from the raw partition (i.e. the 219 * beginning of the disk in order to check the NetBSD 220 * disklabel to see if the boot partition is type RAID. 221 * 222 * For machines with prom_version() == PROM_OLDMON, we 223 * only handle boot from RAID for the first disk partition. 224 */ 225 disk_pd = (struct promdata *)alloc(sizeof *disk_pd); 226 memcpy(disk_pd, pd, sizeof(struct promdata)); 227 if (prom_version() != PROM_OLDMON) { 228 strcpy(rawpart, prom_bootdevice); 229 if ((partition = strchr(rawpart, ':')) != '\0' && 230 *++partition >= 'a' && 231 *partition <= 'a' + MAXPARTITIONS) { 232 part = *partition - 'a'; 233 *partition = RAW_PART + 'a'; 234 } else 235 strcat(rawpart, ":c"); 236 if ((disk_pd->fd = prom_open(rawpart)) == 0) 237 return 0; 238 } 239 error = f->f_dev->dv_strategy(disk_pd, F_READ, LABELSECTOR, 240 DEV_BSIZE, &buf, &read); 241 if (prom_version() != PROM_OLDMON) 242 prom_close(disk_pd->fd); 243 if (error || (read != DEV_BSIZE)) 244 return 0; 245 #ifdef NOTDEF_DEBUG 246 { 247 int x = 0; 248 char *p = (char *) buf; 249 250 printf(" Sector %d:\n", LABELSECTOR); 251 printf("00000000 "); 252 while (x < DEV_BSIZE) { 253 if (*p >= 0x00 && *p < 0x10) 254 printf("0%x ", *p & 0xff); 255 else 256 printf("%x ", *p & 0xff); 257 x++; 258 if (x && !(x % 8)) 259 printf(" "); 260 if (x && !(x % 16)) { 261 if(x < 0x100) 262 printf("\n000000%x ", x); 263 else 264 printf("\n00000%x ", x); 265 } 266 p++; 267 } 268 printf("\n"); 269 } 270 #endif 271 /* Check for NetBSD disk label. */ 272 dlp = (struct disklabel *) (buf + LABELOFFSET); 273 if (dlp->d_magic == DISKMAGIC && !dkcksum(dlp) && 274 dlp->d_partitions[part].p_fstype == FS_RAID) { 275 #ifdef NOTDEF_DEBUG 276 printf("devopen: found RAID partition, " 277 "adjusting offset to %d\n", RF_PROTECTED_SECTORS); 278 #endif 279 doffset = RF_PROTECTED_SECTORS; 280 } 281 } 282 #endif /* BOOTXX */ 283 return (0); 284 } 285 286 287 int 288 obp_v0_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 289 void *buf, size_t *rsize) 290 { 291 int n, error = 0; 292 struct promdata *pd = (struct promdata *)devdata; 293 int fd = pd->fd; 294 295 #ifndef BOOTXX 296 dblk += doffset; 297 #endif 298 #ifdef DEBUG_PROM 299 printf("promstrategy: size=%d dblk=%d\n", size, dblk); 300 #endif 301 302 #define prom_bread(fd, nblk, dblk, buf) \ 303 (*obpvec->pv_v0devops.v0_rbdev)(fd, nblk, dblk, buf) 304 #define prom_bwrite(fd, nblk, dblk, buf) \ 305 (*obpvec->pv_v0devops.v0_wbdev)(fd, nblk, dblk, buf) 306 307 #ifndef BOOTXX /* We know it's a block device, so save some space */ 308 if (pd->devtype != DT_BLOCK) { 309 printf("promstrategy: non-block device not supported\n"); 310 error = EINVAL; 311 } 312 #endif 313 314 n = (flag == F_READ) 315 ? prom_bread(fd, btodb(size), dblk, buf) 316 : prom_bwrite(fd, btodb(size), dblk, buf); 317 318 *rsize = dbtob(n); 319 320 #ifdef DEBUG_PROM 321 printf("rsize = %x\n", *rsize); 322 #endif 323 return (error); 324 } 325 326 int 327 obp_v2_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 328 void *buf, size_t *rsize) 329 { 330 int error = 0; 331 struct promdata *pd = (struct promdata *)devdata; 332 int fd = pd->fd; 333 334 #ifndef BOOTXX 335 dblk += doffset; 336 #endif 337 #ifdef DEBUG_PROM 338 printf("promstrategy: size=%d dblk=%d\n", size, dblk); 339 #endif 340 341 #ifndef BOOTXX /* We know it's a block device, so save some space */ 342 if (pd->devtype == DT_BLOCK) 343 #endif 344 prom_seek(fd, dbtob(dblk)); 345 346 *rsize = (flag == F_READ) 347 ? prom_read(fd, buf, size) 348 : prom_write(fd, buf, size); 349 350 #ifdef DEBUG_PROM 351 printf("rsize = %x\n", *rsize); 352 #endif 353 return (error); 354 } 355 356 /* 357 * On old-monitor machines, things work differently. 358 */ 359 int 360 oldmon_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 361 void *buf, size_t *rsize) 362 { 363 struct promdata *pd = devdata; 364 struct saioreq *si; 365 struct om_boottable *ops; 366 char *dmabuf; 367 int si_flag; 368 size_t xcnt; 369 370 si = pd->si; 371 ops = si->si_boottab; 372 373 #ifndef BOOTXX 374 dblk += doffset; 375 #endif 376 #ifdef DEBUG_PROM 377 printf("prom_strategy: size=%d dblk=%d\n", size, dblk); 378 #endif 379 380 dmabuf = dvma_mapin(buf, size); 381 382 si->si_bn = dblk; 383 si->si_ma = dmabuf; 384 si->si_cc = size; 385 386 si_flag = (flag == F_READ) ? SAIO_F_READ : SAIO_F_WRITE; 387 xcnt = (*ops->b_strategy)(si, si_flag); 388 dvma_mapout(dmabuf, size); 389 390 #ifdef DEBUG_PROM 391 printf("disk_strategy: xcnt = %x\n", xcnt); 392 #endif 393 394 if (xcnt <= 0) 395 return (EIO); 396 397 *rsize = xcnt; 398 return (0); 399 } 400 401 int 402 obp_close(struct open_file *f) 403 { 404 struct promdata *pd = f->f_devdata; 405 register int fd = pd->fd; 406 407 #ifndef BOOTXX 408 if (pd->devtype == DT_NET) 409 net_close(pd); 410 #endif 411 prom_close(fd); 412 return 0; 413 } 414 415 int 416 oldmon_close(struct open_file *f) 417 { 418 struct promdata *pd = f->f_devdata; 419 420 #ifndef BOOTXX 421 if (pd->devtype == DT_NET) 422 net_close(pd); 423 #endif 424 oldmon_iclose(pd->si); 425 pd->si = NULL; 426 *romVectorPtr->echo = saveecho; /* Hmm, probably must go somewhere else */ 427 return 0; 428 } 429 430 #ifndef BOOTXX 431 ssize_t 432 obp_v0_xmit(struct promdata *pd, void *buf, size_t len) 433 { 434 435 return ((*obpvec->pv_v0devops.v0_wnet)(pd->fd, len, buf)); 436 } 437 438 ssize_t 439 obp_v2_xmit(struct promdata *pd, void *buf, size_t len) 440 { 441 442 return (prom_write(pd->fd, buf, len)); 443 } 444 445 ssize_t 446 obp_v0_recv(struct promdata *pd, void *buf, size_t len) 447 { 448 449 return ((*obpvec->pv_v0devops.v0_rnet)(pd->fd, len, buf)); 450 } 451 452 ssize_t 453 obp_v2_recv(struct promdata *pd, void *buf, size_t len) 454 { 455 int n; 456 457 n = prom_read(pd->fd, buf, len); 458 459 /* OBP V2 & V3 may return -2 */ 460 return (n == -2 ? 0 : n); 461 } 462 463 ssize_t 464 oldmon_xmit(struct promdata *pd, void *buf, size_t len) 465 { 466 struct saioreq *si; 467 struct saif *sif; 468 char *dmabuf; 469 int rv; 470 471 si = pd->si; 472 sif = si->si_sif; 473 if (sif == NULL) { 474 printf("xmit: not a network device\n"); 475 return (-1); 476 } 477 dmabuf = dvma_mapin(buf, len); 478 rv = sif->sif_xmit(si->si_devdata, dmabuf, len); 479 dvma_mapout(dmabuf, len); 480 481 return (ssize_t)(rv ? -1 : len); 482 } 483 484 ssize_t 485 oldmon_recv(struct promdata *pd, void *buf, size_t len) 486 { 487 struct saioreq *si; 488 struct saif *sif; 489 char *dmabuf; 490 int rv; 491 492 si = pd->si; 493 sif = si->si_sif; 494 dmabuf = dvma_mapin(buf, len); 495 rv = sif->sif_poll(si->si_devdata, dmabuf); 496 dvma_mapout(dmabuf, len); 497 498 return (ssize_t)rv; 499 } 500 501 int 502 getchar(void) 503 { 504 505 return (prom_getchar()); 506 } 507 508 time_t 509 getsecs(void) 510 { 511 512 (void)prom_peekchar(); 513 return (prom_ticks() / 1000); 514 } 515 516 /* 517 * A number of well-known devices on sun4s. 518 */ 519 static struct dtab { 520 char *name; 521 int type; 522 } dtab[] = { 523 { "sd", DT_BLOCK }, 524 { "st", DT_BLOCK }, 525 { "xd", DT_BLOCK }, 526 { "xy", DT_BLOCK }, 527 { "fd", DT_BLOCK }, 528 { "le", DT_NET }, 529 { "ie", DT_NET }, 530 { NULL, 0 } 531 }; 532 533 int 534 getdevtype(int fd, char *name) 535 { 536 struct dtab *dp; 537 int node; 538 char *cp; 539 540 switch (prom_version()) { 541 case PROM_OLDMON: 542 case PROM_OBP_V0: 543 for (dp = dtab; dp->name; dp++) { 544 if (name[0] == dp->name[0] && 545 name[1] == dp->name[1]) 546 return (dp->type); 547 } 548 break; 549 550 case PROM_OBP_V2: 551 case PROM_OBP_V3: 552 case PROM_OPENFIRM: 553 node = prom_instance_to_package(fd); 554 cp = mygetpropstring(node, "device_type"); 555 if (strcmp(cp, "block") == 0) 556 return (DT_BLOCK); 557 else if (strcmp(cp, "network") == 0) 558 return (DT_NET); 559 else if (strcmp(cp, "byte") == 0) 560 return (DT_BYTE); 561 break; 562 } 563 return (0); 564 } 565 566 /* 567 * Return a string property. There is a (small) limit on the length; 568 * the string is fetched into a static buffer which is overwritten on 569 * subsequent calls. 570 */ 571 char * 572 mygetpropstring(int node, char *name) 573 { 574 int len; 575 static char buf[64]; 576 577 len = prom_proplen(node, name); 578 if (len > 0) 579 _prom_getprop(node, name, buf, len); 580 else 581 len = 0; 582 583 buf[len] = '\0'; /* usually unnecessary */ 584 return (buf); 585 } 586 #endif /* BOOTXX */ 587 588 /* 589 * Old monitor routines 590 */ 591 592 struct saioreq prom_si; 593 static int promdev_inuse; 594 595 int 596 oldmon_iopen(struct promdata *pd) 597 { 598 struct om_bootparam *bp; 599 struct om_boottable *ops; 600 struct devinfo *dip; 601 struct saioreq *si; 602 int error; 603 604 if (promdev_inuse) 605 return (EMFILE); 606 607 bp = *romVectorPtr->bootParam; 608 ops = bp->bootTable; 609 dip = ops->b_devinfo; 610 611 #ifdef DEBUG_PROM 612 printf("Boot device type: %s\n", ops->b_desc); 613 printf("d_devbytes=%d\n", dip->d_devbytes); 614 printf("d_dmabytes=%d\n", dip->d_dmabytes); 615 printf("d_localbytes=%d\n", dip->d_localbytes); 616 printf("d_stdcount=%d\n", dip->d_stdcount); 617 printf("d_stdaddrs[%d]=%x\n", bp->ctlrNum, dip->d_stdaddrs[bp->ctlrNum]); 618 printf("d_devtype=%d\n", dip->d_devtype); 619 printf("d_maxiobytes=%d\n", dip->d_maxiobytes); 620 #endif 621 622 dvma_init(); 623 624 si = &prom_si; 625 memset(si, 0, sizeof(*si)); 626 si->si_boottab = ops; 627 si->si_ctlr = bp->ctlrNum; 628 si->si_unit = bp->unitNum; 629 si->si_boff = bp->partNum; 630 631 if (si->si_ctlr > dip->d_stdcount) 632 return (ECTLR); 633 634 if (dip->d_devbytes) { 635 si->si_devaddr = oldmon_mapin(dip->d_stdaddrs[si->si_ctlr], 636 dip->d_devbytes, dip->d_devtype); 637 #ifdef DEBUG_PROM 638 printf("prom_iopen: devaddr=0x%x pte=0x%x\n", 639 si->si_devaddr, 640 getpte4((u_long)si->si_devaddr & ~PGOFSET)); 641 #endif 642 } 643 644 if (dip->d_dmabytes) { 645 si->si_dmaaddr = dvma_alloc(dip->d_dmabytes); 646 #ifdef DEBUG_PROM 647 printf("prom_iopen: dmaaddr=0x%x\n", si->si_dmaaddr); 648 #endif 649 } 650 651 if (dip->d_localbytes) { 652 si->si_devdata = alloc(dip->d_localbytes); 653 #ifdef DEBUG_PROM 654 printf("prom_iopen: devdata=0x%x\n", si->si_devdata); 655 #endif 656 } 657 658 /* OK, call the PROM device open routine. */ 659 error = (*ops->b_open)(si); 660 if (error != 0) { 661 printf("prom_iopen: \"%s\" error=%d\n", ops->b_desc, error); 662 return (ENXIO); 663 } 664 #ifdef DEBUG_PROM 665 printf("prom_iopen: succeeded, error=%d\n", error); 666 #endif 667 668 pd->si = si; 669 promdev_inuse++; 670 return (0); 671 } 672 673 void 674 oldmon_iclose(struct saioreq *si) 675 { 676 struct om_boottable *ops; 677 struct devinfo *dip; 678 679 if (promdev_inuse == 0) 680 return; 681 682 ops = si->si_boottab; 683 dip = ops->b_devinfo; 684 685 (*ops->b_close)(si); 686 687 if (si->si_dmaaddr) { 688 dvma_free(si->si_dmaaddr, dip->d_dmabytes); 689 si->si_dmaaddr = NULL; 690 } 691 692 promdev_inuse = 0; 693 } 694 695 static struct mapinfo { 696 int maptype; 697 int pgtype; 698 int base; 699 } oldmon_mapinfo[] = { 700 #define PG_COMMON (PG_V|PG_W|PG_S|PG_NC) 701 { MAP_MAINMEM, PG_OBMEM | PG_COMMON, 0 }, 702 { MAP_OBIO, PG_OBIO | PG_COMMON, 0 }, 703 { MAP_MBMEM, PG_VME16 | PG_COMMON, 0xFF000000 }, 704 { MAP_MBIO, PG_VME16 | PG_COMMON, 0xFFFF0000 }, 705 { MAP_VME16A16D, PG_VME16 | PG_COMMON, 0xFFFF0000 }, 706 { MAP_VME16A32D, PG_VME32 | PG_COMMON, 0xFFFF0000 }, 707 { MAP_VME24A16D, PG_VME16 | PG_COMMON, 0xFF000000 }, 708 { MAP_VME24A32D, PG_VME32 | PG_COMMON, 0xFF000000 }, 709 { MAP_VME32A16D, PG_VME16 | PG_COMMON, 0 }, 710 { MAP_VME32A32D, PG_VME32 | PG_COMMON, 0 }, 711 }; 712 static int oldmon_mapinfo_cnt = 713 sizeof(oldmon_mapinfo) / sizeof(oldmon_mapinfo[0]); 714 715 /* The virtual address we will use for PROM device mappings. */ 716 static u_long prom_devmap = MONSHORTSEG; 717 718 static char * 719 oldmon_mapin(u_long physaddr, int length, int maptype) 720 { 721 int i, pa, pte, va; 722 723 if (length > (4*NBPG)) 724 panic("oldmon_mapin: length=%d", length); 725 726 for (i = 0; i < oldmon_mapinfo_cnt; i++) 727 if (oldmon_mapinfo[i].maptype == maptype) 728 goto found; 729 panic("oldmon_mapin: invalid maptype %d", maptype); 730 731 found: 732 pte = oldmon_mapinfo[i].pgtype; 733 pa = oldmon_mapinfo[i].base; 734 pa += physaddr; 735 pte |= ((pa >> SUN4_PGSHIFT) & PG_PFNUM); 736 737 va = prom_devmap; 738 do { 739 setpte4(va, pte); 740 va += NBPG; 741 pte += 1; 742 length -= NBPG; 743 } while (length > 0); 744 return ((char*)(prom_devmap | (pa & PGOFSET))); 745 } 746