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