|
|
1.1 ! root 1: /* hp.c 4.47 82/02/18 */ ! 2: ! 3: #ifdef HPDEBUG ! 4: int hpdebug; ! 5: #endif ! 6: #ifdef HPBDEBUG ! 7: int hpbdebug; ! 8: #endif ! 9: ! 10: #include "hp.h" ! 11: #if NHP > 0 ! 12: /* ! 13: * HP disk driver for RP0x+RMxx+ML11 ! 14: * ! 15: * TODO: ! 16: * check RM80 skip sector handling when ECC's occur later ! 17: * check offset recovery handling ! 18: * see if DCLR and/or RELEASE set attention status ! 19: * print bits of mr && mr2 symbolically ! 20: */ ! 21: ! 22: #include "../h/param.h" ! 23: #include "../h/systm.h" ! 24: #include "../h/dk.h" ! 25: #include "../h/buf.h" ! 26: #include "../h/conf.h" ! 27: #include "../h/dir.h" ! 28: #include "../h/user.h" ! 29: #include "../h/map.h" ! 30: #include "../h/pte.h" ! 31: #include "../h/mbareg.h" ! 32: #include "../h/mbavar.h" ! 33: #include "../h/mtpr.h" ! 34: #include "../h/vm.h" ! 35: #include "../h/cmap.h" ! 36: #include "../h/dkbad.h" ! 37: #include "../h/dkio.h" ! 38: ! 39: #include "../h/hpreg.h" ! 40: ! 41: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ ! 42: struct size { ! 43: daddr_t nblocks; ! 44: int cyloff; ! 45: } hp6_sizes[8] = { ! 46: 15884, 0, /* A=cyl 0 thru 37 */ ! 47: 33440, 38, /* B=cyl 38 thru 117 */ ! 48: 340670, 0, /* C=cyl 0 thru 814 */ ! 49: 0, 0, ! 50: 0, 0, ! 51: 0, 0, ! 52: #ifndef NOBADSECT ! 53: 291280, 118, /* G=cyl 118 thru 814 */ ! 54: #else ! 55: 291346, 118, ! 56: #endif ! 57: 0, 0, ! 58: }, rm3_sizes[8] = { ! 59: 15884, 0, /* A=cyl 0 thru 99 */ ! 60: 33440, 100, /* B=cyl 100 thru 309 */ ! 61: 131680, 0, /* C=cyl 0 thru 822 */ ! 62: 0, 0, ! 63: 0, 0, ! 64: 0, 0, ! 65: #ifndef NOBADSECT ! 66: 81984, 310, /* G=cyl 310 thru 822 */ ! 67: #else ! 68: 82080, 310, ! 69: #endif ! 70: 0, 0, ! 71: }, rm5_sizes[8] = { ! 72: 15884, 0, /* A=cyl 0 thru 26 */ ! 73: 33440, 27, /* B=cyl 27 thru 81 */ ! 74: 500384, 0, /* C=cyl 0 thru 822 */ ! 75: 15884, 562, /* D=cyl 562 thru 588 */ ! 76: 55936, 589, /* E=cyl 589 thru 680 */ ! 77: #ifndef NOBADSECT ! 78: 86240, 681, /* F=cyl 681 thru 822 */ ! 79: 158592, 562, /* G=cyl 562 thru 822 */ ! 80: #else ! 81: 86636, 681, ! 82: 158688, 562, ! 83: #endif ! 84: 291346, 82, /* H=cyl 82 thru 561 */ ! 85: }, rm80_sizes[8] = { ! 86: 15884, 0, /* A=cyl 0 thru 36 */ ! 87: 33440, 37, /* B=cyl 37 thru 114 */ ! 88: 242606, 0, /* C=cyl 0 thru 558 */ ! 89: 0, 0, ! 90: 0, 0, ! 91: 192223, 115, /* F=cyl 115 thru 558 */ ! 92: 82080, 115, /* G=cyl 115 thru 304 */ ! 93: 110143, 305, /* H=cyl 305 thru 558 */ ! 94: }, mfj_sizes[8] = { ! 95: 10240, 0, /* A=cyl 0 thru 31 */ ! 96: 20480, 32, /* B=cyl 32 thru 95 */ ! 97: 232640, 96, /* C=cyl 96 thru 822 */ ! 98: 0, 0, ! 99: 0, 0, ! 100: 0, 0, ! 101: 0, 0, ! 102: 0, 0, ! 103: }, eagle_sizes[8] ={ ! 104: 27520, 0, /* A=cyl 0 thru 31 */ ! 105: 27520, 32, /* B=cyl 32 thru 63 */ ! 106: 667360, 64, /* C=cyl 64 thru 839 */ ! 107: 232640, 64, /* D=cyl 64 thru 340 (partial) */ ! 108: 232640, 341, /* E=cyl 341 thru 617 (partial) */ ! 109: 0, 0, ! 110: 0, 0, ! 111: 0, 0, ! 112: /* 48 sector Emulex Eagle */ ! 113: }, eag48_sizes[8] = { /* cyl 841 used for bad sectors + info */ ! 114: ! 115: 45*960, 0, /* A = cyl 0 thru 44 for /tmp */ ! 116: 64*960, 45, /* B = cyl 45 thru 108 for swap */ ! 117: 842*960, 0, /* C = all cyl 0 thru 841 for testing */ ! 118: 244*960,109, /* D = cyl 109 thru 352 nearly 1/3 */ ! 119: 244*960,353, /* E = cyl 353 thru 596 nearly 1/3 */ ! 120: 244*960,597, /* F = cyl 597 thru 840 nearly 1/3 */ ! 121: 0, 0, /* G = cyl 0 thru 402 nearly 1/2 */ ! 122: 0, 0, /* H = cyl 438 thru 840 nearly 1/2 */ ! 123: }, hp7_sizes[8] = { ! 124: 15884, 0, /* A=cyl 0 thru 9 */ ! 125: 64000, 10, /* B=cyl 10 thru 49 */ ! 126: 1008000,0, /* C=cyl 0 thru 629 */ ! 127: 504000, 0, /* D=cyl 0 thru 314 */ ! 128: 504000, 315, /* E=cyl 315 thru 629 */ ! 129: 928000, 50, /* F=cyl 50 thru 629 */ ! 130: 0, 0, ! 131: 0, 0, ! 132: }; ! 133: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ ! 134: ! 135: #ifndef JONES ! 136: #define _hpSDIST 2 ! 137: #define _hpRDIST 3 ! 138: #else JONES ! 139: /* ! 140: these constants were originally 2 and 3 respectively. they ! 141: have been changed to improve the performance of the eagle ! 142: drives with the emulex controller. to date, 8,9 is better than ! 143: 2,3. 12,13 did not do any better than 8,9. changing these ! 144: constants changes the lead for all drives using the hp driver ! 145: including the rm80. that's a mistake, but empirically, ! 146: changing these to 8,9 did not measurably change rm80 ! 147: performance. ! 148: */ ! 149: #define _hpSDIST 8 ! 150: #define _hpRDIST 9 ! 151: #endif JONES ! 152: ! 153: int hpSDIST = _hpSDIST; ! 154: int hpRDIST = _hpRDIST; ! 155: ! 156: short hptypes[] = ! 157: { MBDT_RM03, MBDT_RM05, MBDT_RP06, MBDT_RM80, MBDT_RP05, MBDT_RP07, ! 158: MBDT_FUJI, MBDT_FUJI, MBDT_FUJI, MBDT_ML11A, MBDT_ML11B, 0 }; ! 159: struct mba_device *hpinfo[NHP]; ! 160: int hpattach(),hpustart(),hpstart(),hpdtint(); ! 161: struct mba_driver hpdriver = ! 162: { hpattach, 0, hpustart, hpstart, hpdtint, 0, ! 163: hptypes, "hp", 0, hpinfo }; ! 164: ! 165: struct hpst { ! 166: short nsect; ! 167: short ntrak; ! 168: short nspc; ! 169: short ncyl; ! 170: struct size *sizes; ! 171: } hpst[] = { ! 172: 32, 5, 32*5, 823, rm3_sizes, /* RM03 */ ! 173: 32, 19, 32*19, 823, rm5_sizes, /* RM05 */ ! 174: 22, 19, 22*19, 815, hp6_sizes, /* RP06 */ ! 175: 31, 14, 31*14, 559, rm80_sizes, /* RM80 */ ! 176: 22, 19, 22*19, 411, hp6_sizes, /* RP05 */ ! 177: 50, 32, 50*32, 630, hp7_sizes, /* RP07 */ ! 178: /* the following three entries must be contiguous */ ! 179: 32, 10, 32*10, 823, mfj_sizes, /* little fujitsu */ ! 180: 43, 20, 43*20, 842, eagle_sizes, /* eagle */ ! 181: 48, 20, 48*20, 842, eag48_sizes, /* eagle 48 sectors */ ! 182: 1, 1, 1, 1, 0, /* ML11A */ ! 183: 1, 1, 1, 1, 0, /* ML11B */ ! 184: }; ! 185: ! 186: u_char hp_offset[16] = { ! 187: HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, ! 188: HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, ! 189: HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, ! 190: 0, 0, 0, 0, ! 191: }; ! 192: ! 193: struct buf rhpbuf[NHP]; ! 194: #ifndef NOBADSECT ! 195: struct buf bhpbuf[NHP]; ! 196: struct dkbad hpbad[NHP]; ! 197: #endif ! 198: char hpinit[NHP]; ! 199: char hprecal[NHP]; ! 200: char hphdr[NHP]; ! 201: daddr_t mlsize[NHP]; ! 202: ! 203: #define b_cylin b_resid ! 204: ! 205: /* #define ML11 0 to remove ML11 support */ ! 206: #define ML11 0 ! 207: /*#define ML11 (hptypes[mi->mi_type] == MBDT_ML11A)*/ ! 208: #define RP06 (hptypes[mi->mi_type] <= MBDT_RP06) ! 209: #define RM80 (hptypes[mi->mi_type] == MBDT_RM80) ! 210: ! 211: #ifdef INTRLVE ! 212: daddr_t dkblock(); ! 213: #endif ! 214: ! 215: int hpseek; ! 216: ! 217: /*ARGSUSED*/ ! 218: hpattach(mi, slave) ! 219: struct mba_device *mi; ! 220: { ! 221: register struct hpst *st = &hpst[mi->mi_type]; ! 222: ! 223: if (hptypes[mi->mi_type] == MBDT_ML11B) ! 224: mi->mi_type--; /* A CHEAT - ML11B D.T. SHOULD == ML11A */ ! 225: if (ML11) { ! 226: register struct hpdevice *hpaddr = ! 227: (struct hpdevice *)mi->mi_drv; ! 228: register int trt, sz; ! 229: ! 230: sz = hpaddr->hpmr & HPMR_SZ; ! 231: if ((hpaddr->hpmr & HPMR_ARRTYP) == 0) ! 232: sz >>= 2; ! 233: mlsize[mi->mi_unit] = sz; ! 234: if (mi->mi_dk >= 0) { ! 235: trt = (hpaddr->hpmr & HPMR_TRT) >> 8; ! 236: dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt)); ! 237: } ! 238: } else if (mi->mi_dk >= 0) { ! 239: register struct hpdevice *hp; ! 240: register int type; ! 241: ! 242: hp = (struct hpdevice *) mi->mi_drv; ! 243: type = hp->hpdt & MBDT_TYPE; ! 244: if (type == MBDT_FUJI) { ! 245: short maxtrk, maxsect; ! 246: /* ! 247: * we have some kind of disk on an Emulex SC750. ! 248: * We assume it's a little Fuji, and must now check ! 249: * if it's an Eagle. ! 250: */ ! 251: hp->hphr = HPHR_MAXTRK; ! 252: maxtrk = hp->hphr; ! 253: if (maxtrk >= hpst[mi->mi_type].ntrak) { ! 254: mi->mi_type++; ! 255: /* it's an Eagle. now check # of sectors */ ! 256: hp->hphr = HPHR_MAXSECT; ! 257: maxsect = hp->hphr; ! 258: if (maxsect > hpst[mi->mi_type].nsect) { ! 259: printf("%d sectors\n", maxsect); ! 260: mi->mi_type++; ! 261: } ! 262: } ! 263: } ! 264: st = &hpst[mi->mi_type]; ! 265: dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256); ! 266: } ! 267: } ! 268: ! 269: hpstrategy(bp) ! 270: register struct buf *bp; ! 271: { ! 272: register struct mba_device *mi; ! 273: register struct hpst *st; ! 274: register int unit; ! 275: long sz, bn; ! 276: int xunit = minor(bp->b_dev) & 07; ! 277: int s; ! 278: ! 279: sz = bp->b_bcount; ! 280: sz = (sz+511) >> 9; ! 281: unit = dkunit(bp); ! 282: if (unit >= NHP) ! 283: goto bad; ! 284: mi = hpinfo[unit]; ! 285: if (mi == 0 || mi->mi_alive == 0) ! 286: goto bad; ! 287: st = &hpst[mi->mi_type]; ! 288: if (ML11) { ! 289: if (bp->b_blkno < 0 || dkblock(bp)+sz > mlsize[mi->mi_unit]) ! 290: goto bad; ! 291: bp->b_cylin = 0; ! 292: } else { ! 293: if (bp->b_blkno < 0 || ! 294: (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) ! 295: goto bad; ! 296: bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; ! 297: } ! 298: s = spl5(); ! 299: disksort(&mi->mi_tab, bp); ! 300: if (mi->mi_tab.b_active == 0) ! 301: mbustart(mi); ! 302: splx(s); ! 303: return; ! 304: ! 305: bad: ! 306: bp->b_flags |= B_ERROR; ! 307: iodone(bp); ! 308: return; ! 309: } ! 310: ! 311: hpustart(mi) ! 312: register struct mba_device *mi; ! 313: { ! 314: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; ! 315: register struct buf *bp = mi->mi_tab.b_actf; ! 316: register struct hpst *st = &hpst[mi->mi_type]; ! 317: daddr_t bn; ! 318: int sn, dist; ! 319: ! 320: hpaddr->hpcs1 = 0; ! 321: if ((hpaddr->hpcs1&HP_DVA) == 0) ! 322: return (MBU_BUSY); ! 323: if ((hpaddr->hpds & HPDS_VV) == 0 || hpinit[mi->mi_unit] == 0) { ! 324: #ifndef NOBADSECT ! 325: struct buf *bbp = &bhpbuf[mi->mi_unit]; ! 326: #endif ! 327: ! 328: hpinit[mi->mi_unit] = 1; ! 329: hpaddr->hpcs1 = HP_DCLR|HP_GO; ! 330: if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive)) ! 331: printf("DCLR attn\n"); ! 332: hpaddr->hpcs1 = HP_PRESET|HP_GO; ! 333: if (!ML11) ! 334: hpaddr->hpof = HPOF_FMT22; ! 335: mbclrattn(mi); ! 336: #ifndef NOBADSECT ! 337: if (!ML11) { ! 338: bbp->b_flags = B_READ|B_BUSY; ! 339: bbp->b_dev = bp->b_dev; ! 340: bbp->b_bcount = 512; ! 341: bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit]; ! 342: bbp->b_blkno = st->ncyl*st->nspc - st->nsect; ! 343: bbp->b_cylin = st->ncyl - 1; ! 344: mi->mi_tab.b_actf = bbp; ! 345: bbp->av_forw = bp; ! 346: bp = bbp; ! 347: } ! 348: #endif ! 349: } ! 350: if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) ! 351: return (MBU_DODATA); ! 352: if (ML11) ! 353: return (MBU_DODATA); ! 354: if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY) ! 355: return (MBU_DODATA); ! 356: bn = dkblock(bp); ! 357: sn = bn%st->nspc; ! 358: sn = (sn+st->nsect-hpSDIST)%st->nsect; ! 359: if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) { ! 360: if (hpseek) ! 361: return (MBU_DODATA); ! 362: dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1; ! 363: if (dist < 0) ! 364: dist += st->nsect; ! 365: if (dist > st->nsect - hpRDIST) ! 366: return (MBU_DODATA); ! 367: } else ! 368: hpaddr->hpdc = bp->b_cylin; ! 369: if (hpseek) ! 370: hpaddr->hpcs1 = HP_SEEK|HP_GO; ! 371: else { ! 372: hpaddr->hpda = sn; ! 373: hpaddr->hpcs1 = HP_SEARCH|HP_GO; ! 374: } ! 375: return (MBU_STARTED); ! 376: } ! 377: ! 378: hpstart(mi) ! 379: register struct mba_device *mi; ! 380: { ! 381: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; ! 382: register struct buf *bp = mi->mi_tab.b_actf; ! 383: register struct hpst *st = &hpst[mi->mi_type]; ! 384: daddr_t bn; ! 385: int sn, tn; ! 386: ! 387: bn = dkblock(bp); ! 388: if (ML11) ! 389: hpaddr->hpda = bn; ! 390: else { ! 391: sn = bn%st->nspc; ! 392: tn = sn/st->nsect; ! 393: sn %= st->nsect; ! 394: hpaddr->hpdc = bp->b_cylin; ! 395: hpaddr->hpda = (tn << 8) + sn; ! 396: } ! 397: if (hphdr[mi->mi_unit]) { ! 398: if (bp->b_flags & B_READ) ! 399: return (HP_RHDR|HP_GO); ! 400: else ! 401: return (HP_WHDR|HP_GO); ! 402: } ! 403: return (0); ! 404: } ! 405: ! 406: hpdtint(mi, mbsr) ! 407: register struct mba_device *mi; ! 408: int mbsr; ! 409: { ! 410: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; ! 411: register struct buf *bp = mi->mi_tab.b_actf; ! 412: register int er1, er2; ! 413: int retry = 0; ! 414: ! 415: #ifndef NOBADSECT ! 416: if (bp->b_flags&B_BAD) { ! 417: if (hpecc(mi, CONT)) ! 418: return(MBD_RESTARTED); ! 419: } ! 420: #endif ! 421: if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) { ! 422: #ifdef HPDEBUG ! 423: if (hpdebug) { ! 424: int dc = hpaddr->hpdc, da = hpaddr->hpda; ! 425: struct hpst *st = &hpst[mi->mi_type]; ! 426: ! 427: printf("hperr: bp %x cyl %d blk %d as %o ", ! 428: bp, bp->b_cylin, bp->b_blkno, ! 429: hpaddr->hpas&0xff); ! 430: printf("dc %x da %x\n",dc&0xffff, da&0xffff); ! 431: printf("errcnt %d ", mi->mi_tab.b_errcnt); ! 432: printf("mbsr=%b ", mbsr, mbsr_bits); ! 433: printf("er1=%b er2=%b\n", ! 434: hpaddr->hper1, HPER1_BITS, ! 435: hpaddr->hper2, HPER2_BITS); ! 436: DELAY(1000000); ! 437: } ! 438: #endif ! 439: er1 = hpaddr->hper1; ! 440: er2 = hpaddr->hper2; ! 441: if (er1 & HPER1_HCRC) { ! 442: er1 &= ~(HPER1_HCE|HPER1_FER); ! 443: er2 &= ~HPER2_BSE; ! 444: } ! 445: if (er1&HPER1_WLE) { ! 446: printf("hp%d: write locked\n", dkunit(bp)); ! 447: bp->b_flags |= B_ERROR; ! 448: } else if ((er1&0xffff) == HPER1_FER && RP06 && ! 449: hphdr[mi->mi_unit] == 0) { ! 450: #ifndef NOBADSECT ! 451: if (hpecc(mi, BSE)) ! 452: { ! 453: #ifdef HPBDEBUG ! 454: if (hpdebug) ! 455: printf("MBD_RESTARTED\n"); ! 456: #endif ! 457: return(MBD_RESTARTED); ! 458: } ! 459: else ! 460: #endif ! 461: goto hard; ! 462: } else if (++mi->mi_tab.b_errcnt > 27 || ! 463: mbsr & MBSR_HARD || ! 464: er1 & HPER1_HARD || ! 465: hphdr[mi->mi_unit] || ! 466: (!ML11 && (er2 & HPER2_HARD))) { ! 467: hard: ! 468: harderr(bp, "hp"); ! 469: if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC))) ! 470: printf("mbsr=%b ", mbsr, mbsr_bits); ! 471: printf("er1=%b er2=%b", ! 472: hpaddr->hper1, HPER1_BITS, ! 473: hpaddr->hper2, HPER2_BITS); ! 474: if (hpaddr->hpmr) ! 475: printf(" mr=%o", hpaddr->hpmr&0xffff); ! 476: if (hpaddr->hpmr2) ! 477: printf(" mr2=%o", hpaddr->hpmr2&0xffff); ! 478: printf("\n"); ! 479: bp->b_flags |= B_ERROR; ! 480: hprecal[mi->mi_unit] = 0; ! 481: } else if ((er2 & HPER2_BSE) && !ML11) { ! 482: #ifndef NOBADSECT ! 483: if (hpecc(mi, BSE)) ! 484: return(MBD_RESTARTED); ! 485: else ! 486: #endif ! 487: goto hard; ! 488: } else if (RM80 && er2&HPER2_SSE) { ! 489: (void) hpecc(mi, SSE); ! 490: return (MBD_RESTARTED); ! 491: } else if ((er1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) { ! 492: if (hpecc(mi, ECC)) ! 493: return (MBD_RESTARTED); ! 494: /* else done */ ! 495: } else ! 496: retry = 1; ! 497: hpaddr->hpcs1 = HP_DCLR|HP_GO; ! 498: if (ML11) { ! 499: if (mi->mi_tab.b_errcnt >= 16) ! 500: goto hard; ! 501: } else if ((mi->mi_tab.b_errcnt&07) == 4) { ! 502: hpaddr->hpcs1 = HP_RECAL|HP_GO; ! 503: hprecal[mi->mi_unit] = 1; ! 504: return(MBD_RESTARTED); ! 505: } ! 506: if (retry) ! 507: return (MBD_RETRY); ! 508: } ! 509: #ifdef HPDEBUG ! 510: else ! 511: if (hpdebug && hprecal[mi->mi_unit]) { ! 512: printf("recal %d ", hprecal[mi->mi_unit]); ! 513: printf("errcnt %d\n", mi->mi_tab.b_errcnt); ! 514: printf("mbsr=%b ", mbsr, mbsr_bits); ! 515: printf("er1=%b er2=%b\n", ! 516: hpaddr->hper1, HPER1_BITS, ! 517: hpaddr->hper2, HPER2_BITS); ! 518: } ! 519: #endif ! 520: switch (hprecal[mi->mi_unit]) { ! 521: ! 522: case 1: ! 523: hpaddr->hpdc = bp->b_cylin; ! 524: hpaddr->hpcs1 = HP_SEEK|HP_GO; ! 525: hprecal[mi->mi_unit]++; ! 526: return (MBD_RESTARTED); ! 527: case 2: ! 528: if (mi->mi_tab.b_errcnt < 16 || ! 529: (bp->b_flags & B_READ) == 0) ! 530: goto donerecal; ! 531: hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22; ! 532: hpaddr->hpcs1 = HP_OFFSET|HP_GO; ! 533: hprecal[mi->mi_unit]++; ! 534: return (MBD_RESTARTED); ! 535: donerecal: ! 536: case 3: ! 537: hprecal[mi->mi_unit] = 0; ! 538: return (MBD_RETRY); ! 539: } ! 540: hphdr[mi->mi_unit] = 0; ! 541: bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff; ! 542: if (mi->mi_tab.b_errcnt >= 16) { ! 543: /* ! 544: * This is fast and occurs rarely; we don't ! 545: * bother with interrupts. ! 546: */ ! 547: hpaddr->hpcs1 = HP_RTC|HP_GO; ! 548: while (hpaddr->hpds & HPDS_PIP) ! 549: ; ! 550: mbclrattn(mi); ! 551: } ! 552: if (!ML11) { ! 553: hpaddr->hpof = HPOF_FMT22; ! 554: hpaddr->hpcs1 = HP_RELEASE|HP_GO; ! 555: } ! 556: return (MBD_DONE); ! 557: } ! 558: ! 559: hpread(dev) ! 560: dev_t dev; ! 561: { ! 562: register int unit = minor(dev) >> 3; ! 563: ! 564: if (unit >= NHP) ! 565: u.u_error = ENXIO; ! 566: else ! 567: physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys); ! 568: } ! 569: ! 570: hpwrite(dev) ! 571: dev_t dev; ! 572: { ! 573: register int unit = minor(dev) >> 3; ! 574: ! 575: if (unit >= NHP) ! 576: u.u_error = ENXIO; ! 577: else ! 578: physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys); ! 579: } ! 580: ! 581: /*ARGSUSED*/ ! 582: hpioctl(dev, cmd, addr, flag) ! 583: dev_t dev; ! 584: int cmd; ! 585: caddr_t addr; ! 586: int flag; ! 587: { ! 588: ! 589: switch (cmd) { ! 590: case DKIOCHDR: /* do header read/write */ ! 591: if (suser()) ! 592: hphdr[minor(dev)>>3] = 1; ! 593: return; ! 594: ! 595: default: ! 596: u.u_error = ENXIO; ! 597: } ! 598: } ! 599: ! 600: hpecc(mi, flag) ! 601: register struct mba_device *mi; ! 602: int flag; ! 603: { ! 604: register struct mba_regs *mbp = mi->mi_mba; ! 605: register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv; ! 606: register struct buf *bp = mi->mi_tab.b_actf; ! 607: register struct hpst *st = &hpst[mi->mi_type]; ! 608: int npf, o; ! 609: int bn, cn, tn, sn; ! 610: int bcr; ! 611: static nerr; ! 612: ! 613: bcr = mbp->mba_bcr & 0xffff; ! 614: if (bcr) ! 615: bcr |= 0xffff0000; /* sxt */ ! 616: #ifndef NOBADSECT ! 617: if (flag == CONT) ! 618: npf = bp->b_error; ! 619: else ! 620: #endif ! 621: npf = btop(bcr + bp->b_bcount); ! 622: o = (int)bp->b_un.b_addr & PGOFSET; ! 623: bn = dkblock(bp); ! 624: #ifdef HPBDEBUG ! 625: if (hpbdebug) ! 626: printf("hpecc: mbp->mba_bcr %x bcr %x bp->b_bcount %x bp->b_error %x bn %x npf %x\n", ! 627: mbp->mba_bcr, bcr, bp->b_bcount, bp->b_error, bn, npf); ! 628: if (hpbdebug) ! 629: printf("ber npf: %x\n", ((rp->hpdc & 0xffff) * (st->nspc)) ! 630: + ((((rp->hpda) >> 8) & 0xff) * st->nsect) ! 631: + ((rp->hpda) & 0xff) ! 632: - (((st->sizes[minor(bp->b_dev)&07].cyloff) * st->nspc) ! 633: + 1 + bn)); ! 634: #endif ! 635: cn = bp->b_cylin; ! 636: sn = bn%(st->nspc) + npf; ! 637: tn = sn/st->nsect; ! 638: sn %= st->nsect; ! 639: cn += tn/st->ntrak; ! 640: tn %= st->ntrak; ! 641: switch (flag) { ! 642: case ECC: ! 643: { ! 644: register int i; ! 645: caddr_t addr; ! 646: struct pte mpte; ! 647: int bit, byte, mask; ! 648: ! 649: npf--; /* because block in error is previous block */ ! 650: printf("hp%d%c: soft ecc sn%d\n", dkunit(bp), ! 651: 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); ! 652: nerr++; ! 653: if ((nerr%100)==0) ! 654: printf("%d soft errors\n", nerr); ! 655: mask = rp->hpec2&0xffff; ! 656: i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */ ! 657: bit = i&07; ! 658: i = (i&~07)>>3; ! 659: byte = i + o; ! 660: while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { ! 661: mpte = mbp->mba_map[npf+btop(byte)]; ! 662: addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); ! 663: putmemc(addr, getmemc(addr)^(mask<<bit)); ! 664: byte++; ! 665: i++; ! 666: bit -= 8; ! 667: } ! 668: if (bcr == 0) ! 669: return (0); ! 670: npf++; ! 671: break; ! 672: } ! 673: ! 674: case SSE: ! 675: #ifdef HPBDEBUG ! 676: if (hpbdebug) ! 677: printf("hpeccSSE\n"); ! 678: #endif ! 679: rp->hpof |= HPOF_SSEI; ! 680: mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); ! 681: break; ! 682: ! 683: #ifndef NOBADSECT ! 684: case BSE: ! 685: #ifdef HPBDEBUG ! 686: if (hpbdebug) ! 687: printf("hpeccBSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); ! 688: #endif ! 689: if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0) ! 690: return(0); ! 691: bp->b_flags |= B_BAD; ! 692: bp->b_error = npf + 1; ! 693: bn = st->ncyl*st->nspc - st->nsect - 1 - bn; ! 694: cn = bn/st->nspc; ! 695: sn = bn%st->nspc; ! 696: tn = sn/st->nsect; ! 697: sn %= st->nsect; ! 698: mbp->mba_bcr = -512; ! 699: #ifdef HPBDEBUG ! 700: if (hpbdebug) ! 701: printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); ! 702: #endif ! 703: break; ! 704: ! 705: case CONT: ! 706: #ifdef HPBDEBUG ! 707: if (hpbdebug) ! 708: printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); ! 709: #endif ! 710: npf = bp->b_error; ! 711: bp->b_flags &= ~B_BAD; ! 712: mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); ! 713: if ((mbp->mba_bcr & 0xffff) == 0) ! 714: return(0); ! 715: break; ! 716: #endif ! 717: } ! 718: #ifdef HPBDEBUG ! 719: if (hpbdebug) ! 720: printf("hpecc, endcase: bn %d\n",bn); ! 721: #endif ! 722: rp->hpcs1 = HP_DCLR|HP_GO; ! 723: if (rp->hpof&HPOF_SSEI) ! 724: sn++; ! 725: rp->hpdc = cn; ! 726: rp->hpda = (tn<<8) + sn; ! 727: mbp->mba_sr = -1; ! 728: mbp->mba_var = (int)ptob(npf) + o; ! 729: rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO; ! 730: mi->mi_tab.b_errcnt = 0; /* error has been corrected */ ! 731: return (1); ! 732: } ! 733: ! 734: #define DBSIZE 20 ! 735: ! 736: hpdump(dev) ! 737: dev_t dev; ! 738: { ! 739: register struct mba_device *mi; ! 740: register struct mba_regs *mba; ! 741: struct hpdevice *hpaddr; ! 742: char *start; ! 743: int num, unit; ! 744: register struct hpst *st; ! 745: ! 746: num = maxfree; ! 747: start = 0; ! 748: unit = minor(dev) >> 3; ! 749: if (unit >= NHP) ! 750: return (ENXIO); ! 751: #define phys(a,b) ((b)((int)(a)&0x7fffffff)) ! 752: mi = phys(hpinfo[unit],struct mba_device *); ! 753: if (mi == 0 || mi->mi_alive == 0) ! 754: return (ENXIO); ! 755: mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; ! 756: mba->mba_cr = MBCR_INIT; ! 757: hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive]; ! 758: if ((hpaddr->hpds & HPDS_VV) == 0) { ! 759: hpaddr->hpcs1 = HP_DCLR|HP_GO; ! 760: hpaddr->hpcs1 = HP_PRESET|HP_GO; ! 761: hpaddr->hpof = HPOF_FMT22; ! 762: } ! 763: st = &hpst[mi->mi_type]; ! 764: if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks) ! 765: return (EINVAL); ! 766: while (num > 0) { ! 767: register struct pte *hpte = mba->mba_map; ! 768: register int i; ! 769: int blk, cn, sn, tn; ! 770: daddr_t bn; ! 771: ! 772: blk = num > DBSIZE ? DBSIZE : num; ! 773: bn = dumplo + btop(start); ! 774: cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff; ! 775: sn = bn%st->nspc; ! 776: tn = sn/st->nsect; ! 777: sn = sn%st->nsect; ! 778: hpaddr->hpdc = cn; ! 779: hpaddr->hpda = (tn << 8) + sn; ! 780: for (i = 0; i < blk; i++) ! 781: *(int *)hpte++ = (btop(start)+i) | PG_V; ! 782: mba->mba_sr = -1; ! 783: mba->mba_bcr = -(blk*NBPG); ! 784: mba->mba_var = 0; ! 785: hpaddr->hpcs1 = HP_WCOM | HP_GO; ! 786: while ((hpaddr->hpds & HPDS_DRY) == 0) ! 787: ; ! 788: if (hpaddr->hpds&HPDS_ERR) ! 789: return (EIO); ! 790: start += blk*NBPG; ! 791: num -= blk; ! 792: } ! 793: return (0); ! 794: } ! 795: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.