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