1: /* 2: * SCCS id @(#)hp.c 2.1 (Berkeley) 8/23/83 3: * This driver has been modified to perform bad-sector forwarding. 4: * It has not been tested after that modification. 5: * If you want to use it, install it instead of the normal hp driver, 6: * AND TEST BOTH BAD-SECTOR FORWARDING AND ECC CORRECTION. 7: * The driver does not know how to distinguish RP04's from RP05/6's; 8: * make sure that the definition of HP_NCYL is correct for all 9: * of your HP's, or add some way to distinguish (by drive 10: * number or something). 11: */ 12: 13: /* 14: * RJP04/RWP04/RJP06/RWP06 disk driver 15: */ 16: #include "hp.h" 17: #if NHP > 0 18: #include "param.h" 19: #include <sys/systm.h> 20: #include <sys/buf.h> 21: #include <sys/conf.h> 22: #include <sys/dir.h> 23: #include <sys/user.h> 24: #include <sys/seg.h> 25: #include <sys/hpreg.h> 26: #ifndef INTRLVE 27: #include <sys/inline.h> 28: #endif 29: #include <sys/uba.h> 30: #include <sys/dkbad.h> 31: 32: #define HP_NCYL 815 33: #define HP_NSECT 22 34: #define HP_NTRAC 19 35: #define HP_SDIST 2 36: #define HP_RDIST 6 37: 38: extern struct size hp_sizes[]; 39: extern struct hpdevice *HPADDR; 40: 41: int hp_offset[] = 42: { 43: HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 44: HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 45: HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 46: 0, 0, 0, 0 47: }; 48: 49: struct buf hptab; 50: #ifdef UCB_DBUFS 51: struct buf rhpbuf[NHP]; 52: #else 53: struct buf rhpbuf; 54: #endif 55: struct buf hputab[NHP]; 56: #ifdef BADSECT 57: struct dkbad hpbad[NHP]; 58: struct buf bhpbuf[NHP]; 59: bool_t hp_init[NHP]; 60: #endif 61: 62: #ifdef INTRLVE 63: extern daddr_t dkblock(); 64: #endif 65: 66: void 67: hproot() 68: { 69: hpattach(HPADDR, 0); 70: } 71: 72: hpattach(addr, unit) 73: register struct hpdevice *addr; 74: { 75: if (unit != 0) 76: return(0); 77: if ((addr != (struct hpdevice *) NULL) && (fioword(addr) != -1)) { 78: HPADDR = addr; 79: #if PDP11 == 70 || PDP11 == GENERIC 80: if (fioword(&(addr->hpbae)) != -1) 81: hptab.b_flags |= B_RH70; 82: #endif 83: return(1); 84: } 85: HPADDR = (struct hpdevice *) NULL; 86: return(0); 87: } 88: 89: hpstrategy(bp) 90: register struct buf *bp; 91: { 92: register struct buf *dp; 93: register unit; 94: long bn; 95: 96: unit = minor(bp->b_dev) & 077; 97: if (unit >= (NHP << 3) || (HPADDR == (struct hpdevice *) NULL)) { 98: bp->b_error = ENXIO; 99: goto errexit; 100: } 101: if (bp->b_blkno < 0 || 102: (bn = dkblock(bp)) + (long) ((bp->b_bcount + 511) >> 9) 103: > hp_sizes[unit & 07].nblocks) { 104: bp->b_error = EINVAL; 105: errexit: 106: bp->b_flags |= B_ERROR; 107: iodone(bp); 108: return; 109: } 110: #ifdef UNIBUS_MAP 111: if ((hptab.b_flags & B_RH70) == 0) 112: mapalloc(bp); 113: #endif 114: bp->b_cylin = bn / (HP_NSECT * HP_NTRAC) + hp_sizes[unit & 07].cyloff; 115: unit = dkunit(bp); 116: dp = &hputab[unit]; 117: (void) _spl5(); 118: disksort(dp, bp); 119: if (dp->b_active == 0) { 120: hpustart(unit); 121: if (hptab.b_active == 0) 122: hpstart(); 123: } 124: (void) _spl0(); 125: } 126: 127: /* 128: * Unit start routine. 129: * Seek the drive to where the data are 130: * and then generate another interrupt 131: * to actually start the transfer. 132: * If there is only one drive on the controller 133: * or we are very close to the data, don't 134: * bother with the search. If called after 135: * searching once, don't bother to look 136: * where we are, just queue for transfer (to avoid 137: * positioning forever without transferring). 138: */ 139: hpustart(unit) 140: register unit; 141: { 142: register struct hpdevice *hpaddr = HPADDR; 143: register struct buf *dp; 144: struct buf *bp; 145: daddr_t bn; 146: int sn, cn, csn; 147: 148: hpaddr->hpcs2.w = unit; 149: hpaddr->hpcs1.c[0] = HP_IE; 150: hpaddr->hpas = 1 << unit; 151: 152: if (unit >= NHP) 153: return; 154: #ifdef HP_DKN 155: dk_busy &= ~(1 << (unit + HP_DKN)); 156: #endif HP_DKN 157: dp = &hputab[unit]; 158: if ((bp = dp->b_actf) == NULL) 159: return; 160: /* 161: * If we have already positioned this drive, 162: * then just put it on the ready queue. 163: */ 164: if (dp->b_active) 165: goto done; 166: dp->b_active++; 167: 168: /* 169: * If drive has just come up, 170: * set up the pack. 171: */ 172: #ifdef BADSECT 173: if (((hpaddr->hpds & HPDS_VV) == 0) || (hp_init[unit] == 0)) 174: #else 175: if ((hpaddr->hpds & HPDS_VV) == 0) 176: #endif 177: { 178: #ifdef BADSECT 179: struct buf *bbp = &bhpbuf[unit]; 180: hp_init[unit] = 1; 181: #endif 182: /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ 183: hpaddr->hpcs1.c[0] = HP_IE | HP_PRESET | HP_GO; 184: hpaddr->hpof = HPOF_FMT22; 185: #ifdef BADSECT 186: bbp->b_flags = B_READ | B_BUSY | B_PHYS; 187: bbp->b_dev = bp->b_dev; 188: bbp->b_bcount = sizeof(struct dkbad); 189: bbp->b_un.b_addr = (caddr_t)&hpbad[unit]; 190: bbp->b_blkno = (daddr_t)HP_NCYL * (HP_NSECT*HP_NTRAC) 191: - HP_NSECT; 192: bbp->b_cylin = HP_NCYL - 1; 193: #ifdef UNIBUS_MAP 194: if ((hptab.b_flags & B_RH70) == 0) 195: mapalloc(bbp); 196: #endif UNIBUS_MAP 197: dp->b_actf = bbp; 198: bbp->av_forw = bp; 199: bp = bbp; 200: #endif BADSECT 201: } 202: 203: #if NHP > 1 204: /* 205: * If drive is offline, forget about positioning. 206: */ 207: if ((hpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) 208: goto done; 209: 210: /* 211: * Figure out where this transfer is going to 212: * and see if we are close enough to justify not searching. 213: */ 214: bn = dkblock(bp); 215: cn = bp->b_cylin; 216: sn = bn % (HP_NSECT * HP_NTRAC); 217: sn = (sn + HP_NSECT - HP_SDIST) % HP_NSECT; 218: 219: if (hpaddr->hpcc != cn) 220: goto search; 221: csn = (hpaddr->hpla >> 6) - sn + HP_SDIST - 1; 222: if (csn < 0) 223: csn += HP_NSECT; 224: if (csn > HP_NSECT - HP_RDIST) 225: goto done; 226: 227: search: 228: hpaddr->hpdc = cn; 229: hpaddr->hpda = sn; 230: hpaddr->hpcs1.c[0] = HP_IE | HP_SEARCH | HP_GO; 231: #ifdef HP_DKN 232: /* 233: * Mark unit busy for iostat. 234: */ 235: unit += HP_DKN; 236: dk_busy |= 1 << unit; 237: dk_numb[unit]++; 238: #endif HP_DKN 239: return; 240: #endif NHP > 1 241: 242: done: 243: /* 244: * Device is ready to go. 245: * Put it on the ready queue for the controller. 246: */ 247: dp->b_forw = NULL; 248: if (hptab.b_actf == NULL) 249: hptab.b_actf = dp; 250: else 251: hptab.b_actl->b_forw = dp; 252: hptab.b_actl = dp; 253: } 254: 255: /* 256: * Start up a transfer on a drive. 257: */ 258: hpstart() 259: { 260: register struct hpdevice *hpaddr = HPADDR; 261: register struct buf *bp; 262: register unit; 263: struct buf *dp; 264: daddr_t bn; 265: int dn, sn, tn, cn; 266: 267: loop: 268: /* 269: * Pull a request off the controller queue. 270: */ 271: if ((dp = hptab.b_actf) == NULL) 272: return; 273: if ((bp = dp->b_actf) == NULL) { 274: hptab.b_actf = dp->b_forw; 275: goto loop; 276: } 277: /* 278: * Mark controller busy and 279: * determine destination of this request. 280: */ 281: hptab.b_active++; 282: unit = minor(bp->b_dev) & 077; 283: dn = dkunit(bp); 284: bn = dkblock(bp); 285: cn = bn / (HP_NSECT * HP_NTRAC) + hp_sizes[unit & 07].cyloff; 286: sn = bn % (HP_NSECT * HP_NTRAC); 287: tn = sn / HP_NSECT; 288: sn = sn % HP_NSECT; 289: 290: /* 291: * Select drive. 292: */ 293: hpaddr->hpcs2.w = dn; 294: /* 295: * Check that it is ready and online. 296: */ 297: if ((hpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) { 298: hptab.b_active = 0; 299: hptab.b_errcnt = 0; 300: dp->b_actf = bp->av_forw; 301: bp->b_flags |= B_ERROR; 302: iodone(bp); 303: goto loop; 304: } 305: if (hptab.b_errcnt >= 16 && (bp->b_flags & B_READ)) { 306: hpaddr->hpof = hp_offset[hptab.b_errcnt & 017] | HPOF_FMT22; 307: hpaddr->hpcs1.w = HP_OFFSET | HP_GO; 308: while ((hpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) 309: ; 310: } 311: hpaddr->hpdc = cn; 312: hpaddr->hpda = (tn << 8) + sn; 313: hpaddr->hpba = bp->b_un.b_addr; 314: #if PDP11 == 70 || PDP11 == GENERIC 315: if (hptab.b_flags & B_RH70) 316: hpaddr->hpbae = bp->b_xmem; 317: #endif 318: hpaddr->hpwc = -(bp->b_bcount >> 1); 319: /* 320: * Warning: unit is being used as a temporary. 321: */ 322: unit = ((bp->b_xmem & 3) << 8) | HP_IE | HP_GO; 323: #ifdef HP_FORMAT 324: if (minor(bp->b_dev) & 0200) 325: unit |= bp->b_flags & B_READ? HP_RHDR : HP_WHDR; 326: else 327: unit |= bp->b_flags & B_READ? HP_RCOM : HP_WCOM; 328: #else 329: if (bp->b_flags & B_READ) 330: unit |= HP_RCOM; 331: else 332: unit |= HP_WCOM; 333: #endif 334: hpaddr->hpcs1.w = unit; 335: 336: #ifdef HP_DKN 337: dk_busy |= 1 << (HP_DKN + NHP); 338: dk_numb[HP_DKN + NHP]++; 339: dk_wds[HP_DKN + NHP] += bp->b_bcount >> 6; 340: #endif HP_DKN 341: } 342: 343: /* 344: * Handle a disk interrupt. 345: */ 346: hpintr() 347: { 348: register struct hpdevice *hpaddr = HPADDR; 349: register struct buf *dp; 350: register unit; 351: struct buf *bp; 352: int as, i, j; 353: 354: as = hpaddr->hpas & 0377; 355: if (hptab.b_active) { 356: #ifdef HP_DKN 357: dk_busy &= ~(1 << (HP_DKN + NHP)); 358: #endif HP_DKN 359: /* 360: * Get device and block structures. Select the drive. 361: */ 362: dp = hptab.b_actf; 363: bp = dp->b_actf; 364: #ifdef BADSECT 365: if (bp->b_flags&B_BAD) 366: if (hpecc(bp, CONT)) 367: return; 368: #endif 369: unit = dkunit(bp); 370: hpaddr->hpcs2.c[0] = unit; 371: /* 372: * Check for and process errors. 373: */ 374: if (hpaddr->hpcs1.w & HP_TRE) { 375: while ((hpaddr->hpds & HPDS_DRY) == 0) 376: ; 377: if (hpaddr->hper1 & HPER1_WLE) { 378: /* 379: * Give up on write locked devices 380: * immediately. 381: */ 382: printf("hp%d: write locked\n", unit); 383: bp->b_flags |= B_ERROR; 384: #ifdef BADSECT 385: } else if (hpaddr->hper1 & HPER1_FER)) { 386: #ifdef HP_FORMAT 387: /* 388: * Allow this error on format devices. 389: */ 390: if (minor(bp->b_dev) & 0200) 391: goto errdone; 392: #endif 393: if (hpecc(bp, BSE)) 394: return; 395: else 396: goto hard; 397: #endif BADSECT 398: } else { 399: hard: 400: if (++hptab.b_errcnt > 28) { 401: bp->b_flags |= B_ERROR; 402: #ifdef UCB_DEVERR 403: harderr(bp, "hp"); 404: printf("cs2=%b er1=%b\n", hpaddr->hpcs2.w, 405: HPCS2_BITS, hpaddr->hper1, HPER1_BITS); 406: #else 407: deverror(bp, hpaddr->hpcs2.w, hpaddr->hper1); 408: #endif 409: } else 410: hptab.b_active = 0; 411: } 412: #ifdef UCB_ECC 413: /* 414: * If soft ecc, correct it (continuing 415: * by returning if necessary). 416: * Otherwise, fall through and retry the transfer. 417: */ 418: if((hpaddr->hper1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) 419: if (hpecc(bp, ECC)) 420: return; 421: #endif 422: erdone: 423: hpaddr->hpcs1.w = HP_TRE | HP_IE | HP_DCLR | HP_GO; 424: if ((hptab.b_errcnt & 07) == 4) { 425: hpaddr->hpcs1.w = HP_RECAL | HP_IE | HP_GO; 426: while ((hpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) 427: ; 428: } 429: } 430: if (hptab.b_active) { 431: if (hptab.b_errcnt) { 432: hpaddr->hpcs1.w = HP_RTC | HP_GO; 433: while ((hpaddr->hpds & (HPDS_PIP | HPDS_DRY)) != HPDS_DRY) 434: ; 435: } 436: hptab.b_active = 0; 437: hptab.b_errcnt = 0; 438: hptab.b_actf = dp->b_forw; 439: dp->b_active = 0; 440: dp->b_actf = bp->av_forw; 441: bp->b_resid = - (hpaddr->hpwc << 1); 442: iodone(bp); 443: hpaddr->hpcs1.w = HP_IE; 444: if (dp->b_actf) 445: hpustart(unit); 446: } 447: as &= ~(1 << unit); 448: } else 449: { 450: if (as == 0) 451: hpaddr->hpcs1.w = HP_IE; 452: hpaddr->hpcs1.c[1] = HP_TRE >> 8; 453: } 454: for (unit = 0; unit < NHP; unit++) 455: if (as & (1 << unit)) 456: hpustart(unit); 457: hpstart(); 458: } 459: 460: hpread(dev) 461: dev_t dev; 462: { 463: #ifdef UCB_DBUFS 464: register int unit = (minor(dev) >> 3) & 07; 465: 466: if (unit >= NHP) 467: u.u_error = ENXIO; 468: else 469: physio(hpstrategy, &rhpbuf[unit], dev, B_READ); 470: #else 471: physio(hpstrategy, &rhpbuf, dev, B_READ); 472: #endif 473: } 474: 475: hpwrite(dev) 476: dev_t dev; 477: { 478: #ifdef UCB_DBUFS 479: register int unit = (minor(dev) >> 3) & 07; 480: 481: if (unit >= NHP) 482: u.u_error = ENXIO; 483: else 484: physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE); 485: #else 486: physio(hpstrategy, &rhpbuf, dev, B_WRITE); 487: #endif 488: } 489: 490: #ifdef UCB_ECC 491: #define exadr(x,y) (((long)(x) << 16) | (unsigned)(y)) 492: 493: /* 494: * Correct an ECC error and restart the i/o to complete 495: * the transfer if necessary. This is quite complicated because 496: * the correction may be going to an odd memory address base 497: * and the transfer may cross a sector boundary. 498: */ 499: hpecc(bp, flag) 500: register struct buf *bp; 501: { 502: register struct hpdevice *hpaddr = HPADDR; 503: register unsigned byte; 504: ubadr_t bb, addr; 505: long wrong; 506: int bit, wc; 507: unsigned ndone, npx; 508: int ocmd; 509: int cn, tn, sn; 510: daddr_t bn; 511: #ifdef UNIBUS_MAP 512: struct ubmap *ubp; 513: #endif 514: int unit; 515: 516: /* 517: * ndone is #bytes including the error 518: * which is assumed to be in the last disk page transferred. 519: */ 520: unit = dkunit(bp); 521: #ifdef BADSECT 522: if (flag == CONT) { 523: npx = bp->b_error; 524: bp->b_error = 0; 525: ndone = npx * PGSIZE; 526: wc = ((int)(ndone - bp->b_bcount)) / NBPW; 527: } else 528: #endif 529: { 530: wc = hpaddr->hpwc; 531: ndone = (wc * NBPW) + bp->b_bcount; 532: npx = ndone / PGSIZE; 533: } 534: ocmd = (hpaddr->hpcs1.w & ~HP_DRY) | HP_IE | HP_GO; 535: bb = exadr(bp->b_xmem, bp->b_un.b_addr); 536: bn = dkblock(bp); 537: cn = bp->b_cylin - bn / (HP_NSECT * HP_NTRAC); 538: bn += npx; 539: cn += bn / (HP_NSECT * HP_NTRAC); 540: sn = bn % (HP_NSECT * HP_NTRAC); 541: tn = sn / HP_NSECT; 542: sn %= HP_NSECT; 543: 544: switch (flag) { 545: case ECC: 546: printf("hp%d%c: soft ecc bn %D\n", 547: unit, 'a' + (minor(bp->b_dev) & 07), 548: bp->b_blkno + (npx - 1)); 549: wrong = hpaddr->hpec2; 550: if (wrong == 0) { 551: hpaddr->hpof = HPOF_FMT22; 552: hpaddr->hpcs1.w |= HP_IE; 553: return (0); 554: } 555: 556: /* 557: * Compute the byte/bit position of the err 558: * within the last disk page transferred. 559: * Hpec1 is origin-1. 560: */ 561: byte = hpaddr->hpec1 - 1; 562: bit = byte & 07; 563: byte >>= 3; 564: byte += ndone - PGSIZE; 565: wrong <<= bit; 566: 567: /* 568: * Correct until mask is zero or until end of transfer, 569: * whichever comes first. 570: */ 571: while (byte < bp->b_bcount && wrong != 0) { 572: addr = bb + byte; 573: #ifdef UNIBUS_MAP 574: if (bp->b_flags & (B_MAP|B_UBAREMAP)) { 575: /* 576: * Simulate UNIBUS map if UNIBUS transfer. 577: */ 578: ubp = UBMAP + ((addr >> 13) & 037); 579: addr = exadr(ubp->ub_hi, ubp->ub_lo) 580: + (addr & 017777); 581: } 582: #endif 583: putmemc(addr, getmemc(addr) ^ (int) wrong); 584: byte++; 585: wrong >>= 8; 586: } 587: break; 588: #ifdef BADSECT 589: case BSE: 590: if ((bn = isbad(&hpbad[unit], cn, tn, sn)) < 0) 591: return(0); 592: bp->b_flags |= B_BAD; 593: bp->b_error = npx + 1; 594: bn = (daddr_t)HP_NCYL * (HP_NSECT * HP_NTRAC) 595: - HP_NSECT - 1 - bn; 596: cn = bn/(HP_NSECT * HP_NTRAC); 597: sn = bn%(HP_NSECT * HP_NTRAC); 598: tn = sn/HP_NSECT; 599: sn %= HP_NSECT; 600: #ifdef DEBUG 601: printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 602: #endif 603: wc = -(512 / NBPW); 604: break; 605: 606: case CONT: 607: bp->b_flags &= ~B_BAD; 608: #ifdef DEBUG 609: printf("hpecc CONT: bn %D cn %d tn %d sn %d\n", bn, cn, tn, sn); 610: #endif 611: break; 612: #endif BADSECT 613: } 614: 615: hptab.b_active++; 616: if (wc == 0) 617: return (0); 618: 619: /* 620: * Have to continue the transfer. Clear the drive 621: * and compute the position where the transfer is to continue. 622: * We have completed npx sectors of the transfer already. 623: */ 624: hpaddr->hpcs2.w = unit; 625: hpaddr->hpcs1.w = HP_TRE | HP_DCLR | HP_GO; 626: 627: addr = bb + ndone; 628: hpaddr->hpdc = cn; 629: hpaddr->hpda = (tn << 8) + sn; 630: hpaddr->hpwc = wc; 631: hpaddr->hpba = (int) addr; 632: #if PDP11 == 70 || PDP11 == GENERIC 633: if (hptab.b_flags & B_RH70) 634: hpaddr->hpbae = (int) (addr >> 16); 635: #endif 636: hpaddr->hpcs1.w = ocmd; 637: return (1); 638: } 639: #endif UCB_ECC 640: 641: #if defined(HP_DUMP) && defined(UCB_AUTOBOOT) 642: /* 643: * Dump routine for RP04/05/06. 644: * Dumps from dumplo to end of memory/end of disk section for minor(dev). 645: * It uses the UNIBUS map to dump all of memory if there is a UNIBUS map 646: * and this isn't an RH70. This depends on UNIBUS_MAP being defined. 647: */ 648: 649: #ifdef UNIBUS_MAP 650: #define DBSIZE (UBPAGE/PGSIZE) /* unit of transfer, one UBPAGE */ 651: #else 652: #define DBSIZE 16 /* unit of transfer, same number */ 653: #endif 654: 655: hpdump(dev) 656: dev_t dev; 657: { 658: register struct hpdevice *hpaddr = HPADDR; 659: daddr_t bn, dumpsize; 660: long paddr; 661: register sn; 662: register count; 663: #ifdef UNIBUS_MAP 664: extern bool_t ubmap; 665: register struct ubmap *ubp; 666: #endif 667: 668: if ((bdevsw[major(dev)].d_strategy != hpstrategy) /* paranoia */ 669: || ((dev=minor(dev)) > (NHP << 3))) 670: return(EINVAL); 671: dumpsize = hp_sizes[dev & 07].nblocks; 672: if ((dumplo < 0) || (dumplo >= dumpsize)) 673: return(EINVAL); 674: dumpsize -= dumplo; 675: 676: hpaddr->hpcs2.w = dev >> 3; 677: if ((hpaddr->hpds & HPDS_VV) == 0) { 678: hpaddr->hpcs1.w = HP_DCLR | HP_GO; 679: hpaddr->hpcs1.w = HP_PRESET | HP_GO; 680: hpaddr->hpof = HPOF_FMT22; 681: } 682: if ((hpaddr->hpds & (HPDS_DPR | HPDS_MOL)) != (HPDS_DPR | HPDS_MOL)) 683: return(EFAULT); 684: dev &= 07; 685: #ifdef UNIBUS_MAP 686: ubp = &UBMAP[0]; 687: #endif 688: for (paddr = 0L; dumpsize > 0; dumpsize -= count) { 689: count = dumpsize>DBSIZE? DBSIZE: dumpsize; 690: bn = dumplo + (paddr >> PGSHIFT); 691: hpaddr->hpdc = bn / (HP_NSECT*HP_NTRAC) + hp_sizes[dev].cyloff; 692: sn = bn % (HP_NSECT * HP_NTRAC); 693: hpaddr->hpda = ((sn / HP_NSECT) << 8) | (sn % HP_NSECT); 694: hpaddr->hpwc = -(count << (PGSHIFT - 1)); 695: #ifdef UNIBUS_MAP 696: /* 697: * If UNIBUS_MAP exists, use 698: * the map, unless on an 11/70 with RH70. 699: */ 700: if (ubmap && ((hptab.b_flags & B_RH70) == 0)) { 701: ubp->ub_lo = loint(paddr); 702: ubp->ub_hi = hiint(paddr); 703: hpaddr->hpba = 0; 704: hpaddr->hpcs1.w = HP_WCOM | HP_GO; 705: } 706: else 707: #endif 708: { 709: /* 710: * Non-UNIBUS map, or 11/70 RH70 (MASSBUS) 711: */ 712: hpaddr->hpba = loint(paddr); 713: #if PDP11 == 70 || PDP11 == GENERIC 714: if (hptab.b_flags & B_RH70) 715: hpaddr->hpbae = hiint(paddr); 716: #endif 717: hpaddr->hpcs1.w = HP_WCOM | HP_GO | ((paddr >> 8) & (03 << 8)); 718: } 719: while (hpaddr->hpcs1.w & HP_GO) 720: ; 721: if (hpaddr->hpcs1.w & HP_TRE) { 722: if (hpaddr->hpcs2.w & HPCS2_NEM) 723: return(0); /* made it to end of memory */ 724: return(EIO); 725: } 726: paddr += (DBSIZE << PGSHIFT); 727: } 728: return(0); /* filled disk minor dev */ 729: } 730: #endif HP_DUMP 731: #endif NHP