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