|
|
1.1 ! root 1: /* hp.c 6.2 83/09/25 */ ! 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: #include "../machine/pte.h" ! 22: ! 23: #include "../h/param.h" ! 24: #include "../h/systm.h" ! 25: #include "../h/dk.h" ! 26: #include "../h/buf.h" ! 27: #include "../h/conf.h" ! 28: #include "../h/dir.h" ! 29: #include "../h/user.h" ! 30: #include "../h/map.h" ! 31: #include "../vax/mtpr.h" ! 32: #include "../h/vm.h" ! 33: #include "../h/cmap.h" ! 34: #include "../h/dkbad.h" ! 35: #include "../h/ioctl.h" ! 36: #include "../h/uio.h" ! 37: ! 38: #include "../vax/dkio.h" ! 39: #include "../vaxmba/mbareg.h" ! 40: #include "../vaxmba/mbavar.h" ! 41: #include "../vaxmba/hpreg.h" ! 42: ! 43: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ ! 44: struct size { ! 45: daddr_t nblocks; ! 46: int cyloff; ! 47: } rp06_sizes[8] = { ! 48: 15884, 0, /* A=cyl 0 thru 37 */ ! 49: 33440, 38, /* B=cyl 38 thru 117 */ ! 50: 340670, 0, /* C=cyl 0 thru 814 */ ! 51: 15884, 118, /* D=cyl 118 thru 155 */ ! 52: 55936, 156, /* E=cyl 156 thru 289 */ ! 53: 219384, 290, /* F=cyl 290 thru 814 */ ! 54: 291280, 118, /* G=cyl 118 thru 814 */ ! 55: 0, 0, ! 56: }, rp05_sizes[8] = { ! 57: 15884, 0, /* A=cyl 0 thru 37 */ ! 58: 33440, 38, /* B=cyl 38 thru 117 */ ! 59: 171798, 0, /* C=cyl 0 thru 410 */ ! 60: 15884, 118, /* D=cyl 118 thru 155 */ ! 61: 55936, 156, /* E=cyl 156 thru 289 */ ! 62: 50512, 290, /* F=cyl 290 thru 410 */ ! 63: 122408, 118, /* G=cyl 118 thru 410 */ ! 64: 0, 0, ! 65: }, rm03_sizes[8] = { ! 66: 15884, 0, /* A=cyl 0 thru 99 */ ! 67: 33440, 100, /* B=cyl 100 thru 308 */ ! 68: 131680, 0, /* C=cyl 0 thru 822 */ ! 69: 15884, 309, /* D=cyl 309 thru 408 */ ! 70: 55936, 409, /* E=cyl 409 thru 758 */ ! 71: 10144, 759, /* F=cyl 759 thru 822 */ ! 72: 82144, 309, /* G=cyl 309 thru 822 */ ! 73: 0, 0, ! 74: }, rm05_sizes[8] = { ! 75: 15884, 0, /* A=cyl 0 thru 26 */ ! 76: 33440, 27, /* B=cyl 27 thru 81 */ ! 77: 500384, 0, /* C=cyl 0 thru 822 */ ! 78: 15884, 562, /* D=cyl 562 thru 588 */ ! 79: 55936, 589, /* E=cyl 589 thru 680 */ ! 80: 86240, 681, /* F=cyl 681 thru 822 */ ! 81: 158592, 562, /* G=cyl 562 thru 822 */ ! 82: 291346, 82, /* H=cyl 82 thru 561 */ ! 83: }, rm80_sizes[8] = { ! 84: 15884, 0, /* A=cyl 0 thru 36 */ ! 85: 33440, 37, /* B=cyl 37 thru 114 */ ! 86: 242606, 0, /* C=cyl 0 thru 558 */ ! 87: 15884, 115, /* D=cyl 115 thru 151 */ ! 88: 55936, 152, /* E=cyl 152 thru 280 */ ! 89: 120559, 281, /* F=cyl 281 thru 558 */ ! 90: 192603, 115, /* G=cyl 115 thru 558 */ ! 91: 0, 0, ! 92: }, rp07_sizes[8] = { ! 93: 15884, 0, /* A=cyl 0 thru 9 */ ! 94: 66880, 10, /* B=cyl 10 thru 51 */ ! 95: 1008000, 0, /* C=cyl 0 thru 629 */ ! 96: 15884, 235, /* D=cyl 235 thru 244 */ ! 97: 307200, 245, /* E=cyl 245 thru 436 */ ! 98: 308650, 437, /* F=cyl 437 thru 629 */ ! 99: 631850, 235, /* G=cyl 235 thru 629 */ ! 100: 291346, 52, /* H=cyl 52 thru 234 */ ! 101: }, cdc9775_sizes[8] = { ! 102: 15884, 0, /* A=cyl 0 thru 12 */ ! 103: 66880, 13, /* B=cyl 13 thru 65 */ ! 104: 1077760, 0, /* C=cyl 0 thru 841 */ ! 105: 15884, 294, /* D=cyl 294 thru 306 */ ! 106: 307200, 307, /* E=cyl 307 thru 546 */ ! 107: 377440, 547, /* F=cyl 547 thru 841 */ ! 108: 701280, 294, /* G=cyl 294 thru 841 */ ! 109: 291346, 66, /* H=cyl 66 thru 293 */ ! 110: }, cdc9730_sizes[8] = { ! 111: 15884, 0, /* A=cyl 0 thru 49 */ ! 112: 33440, 50, /* B=cyl 50 thru 154 */ ! 113: 263360, 0, /* C=cyl 0 thru 822 */ ! 114: 15884, 155, /* D=cyl 155 thru 204 */ ! 115: 55936, 205, /* E=cyl 205 thru 379 */ ! 116: 141664, 380, /* F=cyl 380 thru 822 */ ! 117: 213664, 155, /* G=cyl 155 thru 822 */ ! 118: 0, 0, ! 119: }, capricorn_sizes[8] = { ! 120: 15884, 0, /* A=cyl 0 thru 31 */ ! 121: 33440, 32, /* B=cyl 32 thru 97 */ ! 122: 524288, 0, /* C=cyl 0 thru 1023 */ ! 123: 15884, 668, /* D=cyl 668 thru 699 */ ! 124: 55936, 700, /* E=cyl 700 thru 809 */ ! 125: 109472, 810, /* F=cyl 810 thru 1023 */ ! 126: 182176, 668, /* G=cyl 668 thru 1023 */ ! 127: 291346, 98, /* H=cyl 98 thru 667 */ ! 128: }, eagle_sizes[8] = { ! 129: 15884, 0, /* A=cyl 0 thru 16 */ ! 130: 66880, 17, /* B=cyl 17 thru 86 */ ! 131: 808320, 0, /* C=cyl 0 thru 841 */ ! 132: 15884, 391, /* D=cyl 391 thru 407 */ ! 133: 307200, 408, /* E=cyl 408 thru 727 */ ! 134: 109296, 728, /* F=cyl 728 thru 841 */ ! 135: 432816, 391, /* G=cyl 391 thru 841 */ ! 136: 291346, 87, /* H=cyl 87 thru 390 */ ! 137: }, ampex_sizes[8] = { ! 138: 15884, 0, /* A=cyl 0 thru 26 */ ! 139: 33440, 27, /* B=cyl 27 thru 81 */ ! 140: 495520, 0, /* C=cyl 0 thru 814 */ ! 141: 15884, 562, /* D=cyl 562 thru 588 */ ! 142: 55936, 589, /* E=cyl 589 thru 680 */ ! 143: 81312, 681, /* F=cyl 681 thru 814 */ ! 144: 153664, 562, /* G=cyl 562 thru 814 */ ! 145: 291346, 82, /* H=cyl 82 thru 561 */ ! 146: }; ! 147: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ ! 148: ! 149: /* ! 150: * Table for converting Massbus drive types into ! 151: * indices into the partition tables. Slots are ! 152: * left for those drives devined from other means ! 153: * (e.g. SI, AMPEX, etc.). ! 154: */ ! 155: short hptypes[] = { ! 156: #define HPDT_RM03 0 ! 157: MBDT_RM03, ! 158: #define HPDT_RM05 1 ! 159: MBDT_RM05, ! 160: #define HPDT_RP06 2 ! 161: MBDT_RP06, ! 162: #define HPDT_RM80 3 ! 163: MBDT_RM80, ! 164: #define HPDT_RP04 4 ! 165: MBDT_RP04, ! 166: #define HPDT_RP05 5 ! 167: MBDT_RP05, ! 168: #define HPDT_RP07 6 ! 169: MBDT_RP07, ! 170: #define HPDT_ML11A 7 ! 171: MBDT_ML11A, ! 172: #define HPDT_ML11B 8 ! 173: MBDT_ML11B, ! 174: #define HPDT_9775 9 ! 175: -1, ! 176: #define HPDT_9730 10 ! 177: -1, ! 178: #define HPDT_CAPRICORN 11 ! 179: -1, ! 180: #define HPDT_EAGLE 12 ! 181: -1, ! 182: #define HPDT_9300 13 ! 183: -1, ! 184: #define HPDT_RM02 14 ! 185: MBDT_RM02, /* beware, actually capricorn or eagle */ ! 186: 0 ! 187: }; ! 188: struct mba_device *hpinfo[NHP]; ! 189: int hpattach(),hpustart(),hpstart(),hpdtint(); ! 190: struct mba_driver hpdriver = ! 191: { hpattach, 0, hpustart, hpstart, hpdtint, 0, ! 192: hptypes, "hp", 0, hpinfo }; ! 193: ! 194: /* ! 195: * Beware, sdist and rdist are not well tuned ! 196: * for many of the drives listed in this table. ! 197: * Try patching things with something i/o intensive ! 198: * running and watch iostat. ! 199: */ ! 200: struct hpst { ! 201: short nsect; /* # sectors/track */ ! 202: short ntrak; /* # tracks/cylinder */ ! 203: short nspc; /* # sector/cylinders */ ! 204: short ncyl; /* # cylinders */ ! 205: struct size *sizes; /* partition tables */ ! 206: short sdist; /* seek distance metric */ ! 207: short rdist; /* rotational distance metric */ ! 208: } hpst[] = { ! 209: { 32, 5, 32*5, 823, rm03_sizes, 3, 4 }, /* RM03 */ ! 210: { 32, 19, 32*19, 823, rm05_sizes, 3, 4 }, /* RM05 */ ! 211: { 22, 19, 22*19, 815, rp06_sizes, 3, 4 }, /* RP06 */ ! 212: { 31, 14, 31*14, 559, rm80_sizes, 3, 4 }, /* RM80 */ ! 213: { 22, 19, 22*19, 411, rp05_sizes, 3, 4 }, /* RP04 */ ! 214: { 22, 19, 22*19, 411, rp05_sizes, 3, 4 }, /* RP05 */ ! 215: { 50, 32, 50*32, 630, rp07_sizes, 7, 8 }, /* RP07 */ ! 216: { 1, 1, 1, 1, 0, 0, 0 }, /* ML11A */ ! 217: { 1, 1, 1, 1, 0, 0, 0 }, /* ML11B */ ! 218: { 32, 40, 32*40, 843, cdc9775_sizes, 3, 4 }, /* 9775 */ ! 219: { 32, 10, 32*10, 823, cdc9730_sizes, 3, 4 }, /* 9730 */ ! 220: { 32, 16, 32*16, 1024, capricorn_sizes,7, 8 }, /* Capricorn */ ! 221: { 48, 20, 48*20, 842, eagle_sizes, 7, 8 }, /* EAGLE */ ! 222: { 32, 19, 32*19, 815, ampex_sizes, 3, 4 }, /* 9300 */ ! 223: }; ! 224: ! 225: u_char hp_offset[16] = { ! 226: HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, ! 227: HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, ! 228: HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, ! 229: 0, 0, 0, 0, ! 230: }; ! 231: ! 232: struct buf rhpbuf[NHP]; ! 233: struct buf bhpbuf[NHP]; ! 234: struct dkbad hpbad[NHP]; ! 235: ! 236: struct hpsoftc { ! 237: u_char sc_hpinit; /* drive initialized */ ! 238: u_char sc_recal; /* recalibrate state */ ! 239: u_char sc_hdr; /* next i/o includes header */ ! 240: u_char sc_doseeks; /* perform explicit seeks */ ! 241: daddr_t sc_mlsize; /* ML11 size */ ! 242: } hpsoftc[NHP]; ! 243: ! 244: #define b_cylin b_resid ! 245: ! 246: /* #define ML11 0 to remove ML11 support */ ! 247: #define ML11 (hptypes[mi->mi_type] == MBDT_ML11A) ! 248: #define RP06 (hptypes[mi->mi_type] <= MBDT_RP06) ! 249: #define RM80 (hptypes[mi->mi_type] == MBDT_RM80) ! 250: ! 251: #define MASKREG(reg) ((reg)&0xffff) ! 252: ! 253: #ifdef INTRLVE ! 254: daddr_t dkblock(); ! 255: #endif ! 256: ! 257: /*ARGSUSED*/ ! 258: hpattach(mi, slave) ! 259: register struct mba_device *mi; ! 260: { ! 261: ! 262: mi->mi_type = hpmaptype(mi); ! 263: if (!ML11 && mi->mi_dk >= 0) { ! 264: struct hpst *st = &hpst[mi->mi_type]; ! 265: ! 266: dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256); ! 267: } ! 268: } ! 269: ! 270: /* ! 271: * Map apparent MASSBUS drive type into manufacturer ! 272: * specific configuration. For SI controllers this is done ! 273: * based on codes in the serial number register. For ! 274: * EMULEX controllers, the track and sector attributes are ! 275: * used when the drive type is an RM02 (not supported by DEC). ! 276: */ ! 277: hpmaptype(mi) ! 278: register struct mba_device *mi; ! 279: { ! 280: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; ! 281: register int type = mi->mi_type; ! 282: ! 283: /* ! 284: * Model-byte processing for SI controllers. ! 285: * NB: Only deals with RM03 and RM05 emulations. ! 286: */ ! 287: if (type == HPDT_RM03 || type == HPDT_RM05) { ! 288: int hpsn = hpaddr->hpsn; ! 289: ! 290: if ((hpsn & SIMB_LU) != mi->mi_drive) ! 291: return (type); ! 292: switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) { ! 293: ! 294: case SI9775D: ! 295: printf("hp%d: 9775 (direct)\n", mi->mi_unit); ! 296: type = HPDT_9775; ! 297: break; ! 298: ! 299: case SI9730D: ! 300: printf("hp%d: 9730 (direct)\n", mi->mi_unit); ! 301: type = HPDT_9730; ! 302: break; ! 303: ! 304: /* ! 305: * Beware, since the only SI controller we ! 306: * have has a 9300 instead of a 9766, we map the ! 307: * drive type into the 9300. This means that ! 308: * on a 9766 you lose the last 8 cylinders (argh). ! 309: */ ! 310: case SI9766: ! 311: printf("hp%d: 9300\n", mi->mi_unit); ! 312: type = HPDT_9300; ! 313: break; ! 314: ! 315: case SI9762: ! 316: printf("hp%d: 9762\n", mi->mi_unit); ! 317: type = HPDT_RM03; ! 318: break; ! 319: ! 320: case SICAPD: ! 321: printf("hp%d: capricorn\n", mi->mi_unit); ! 322: type = HPDT_CAPRICORN; ! 323: break; ! 324: ! 325: case SI9751D: ! 326: printf("hp%d: eagle\n", mi->mi_unit); ! 327: type = HPDT_EAGLE; ! 328: break; ! 329: } ! 330: return (type); ! 331: } ! 332: ! 333: /* ! 334: * EMULEX SC750 or SC780. Poke the holding register. ! 335: */ ! 336: if (type == HPDT_RM02) { ! 337: int ntracks, nsectors; ! 338: ! 339: hpaddr->hpof = HPOF_FMT22; ! 340: mbclrattn(mi); ! 341: hpaddr->hpcs1 = HP_NOP; ! 342: hpaddr->hphr = HPHR_MAXTRAK; ! 343: ntracks = MASKREG(hpaddr->hphr) + 1; ! 344: if (ntracks == 16) { ! 345: printf("hp%d: capricorn\n", mi->mi_unit); ! 346: type = HPDT_CAPRICORN; ! 347: goto done; ! 348: } ! 349: if (ntracks == 19) { ! 350: printf("hp%d: 9300\n", mi->mi_unit); ! 351: type = HPDT_9300; ! 352: goto done; ! 353: } ! 354: hpaddr->hpcs1 = HP_NOP; ! 355: hpaddr->hphr = HPHR_MAXSECT; ! 356: nsectors = MASKREG(hpaddr->hphr) + 1; ! 357: if (ntracks == 20 && nsectors == 48) { ! 358: type = HPDT_EAGLE; ! 359: printf("hp%d: eagle\n", mi->mi_unit); ! 360: goto done; ! 361: } ! 362: printf("hp%d: ntracks %d, nsectors %d: unknown device\n", ! 363: mi->mi_unit, ntracks, nsectors); ! 364: done: ! 365: hpaddr->hpcs1 = HP_DCLR|HP_GO; ! 366: mbclrattn(mi); /* conservative */ ! 367: return (type); ! 368: } ! 369: ! 370: /* ! 371: * Map all ML11's to the same type. Also calculate ! 372: * transfer rates based on device characteristics. ! 373: */ ! 374: if (type == HPDT_ML11A || type == HPDT_ML11B) { ! 375: register struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; ! 376: register int trt; ! 377: ! 378: sc->sc_mlsize = hpaddr->hpmr & HPMR_SZ; ! 379: if ((hpaddr->hpmr & HPMR_ARRTYP) == 0) ! 380: sc->sc_mlsize >>= 2; ! 381: if (mi->mi_dk >= 0) { ! 382: trt = (hpaddr->hpmr & HPMR_TRT) >> 8; ! 383: dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt)); ! 384: } ! 385: type = HPDT_ML11A; ! 386: } ! 387: return (type); ! 388: } ! 389: ! 390: hpopen(dev) ! 391: dev_t dev; ! 392: { ! 393: register int unit = minor(dev) >> 3; ! 394: register struct mba_device *mi; ! 395: ! 396: if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0) ! 397: return (ENXIO); ! 398: return (0); ! 399: } ! 400: ! 401: hpstrategy(bp) ! 402: register struct buf *bp; ! 403: { ! 404: register struct mba_device *mi; ! 405: register struct hpst *st; ! 406: register int unit; ! 407: long sz, bn; ! 408: int xunit = minor(bp->b_dev) & 07; ! 409: int s; ! 410: ! 411: sz = bp->b_bcount; ! 412: sz = (sz+511) >> 9; ! 413: unit = dkunit(bp); ! 414: if (unit >= NHP) ! 415: goto bad; ! 416: mi = hpinfo[unit]; ! 417: if (mi == 0 || mi->mi_alive == 0) ! 418: goto bad; ! 419: st = &hpst[mi->mi_type]; ! 420: if (ML11) { ! 421: struct hpsoftc *sc = &hpsoftc[unit]; ! 422: ! 423: if (bp->b_blkno < 0 || ! 424: dkblock(bp)+sz > sc->sc_mlsize) ! 425: goto bad; ! 426: bp->b_cylin = 0; ! 427: } else { ! 428: if (bp->b_blkno < 0 || ! 429: (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) ! 430: goto bad; ! 431: bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; ! 432: } ! 433: s = spl5(); ! 434: disksort(&mi->mi_tab, bp); ! 435: if (mi->mi_tab.b_active == 0) ! 436: mbustart(mi); ! 437: splx(s); ! 438: return; ! 439: ! 440: bad: ! 441: bp->b_flags |= B_ERROR; ! 442: iodone(bp); ! 443: return; ! 444: } ! 445: ! 446: hpustart(mi) ! 447: register struct mba_device *mi; ! 448: { ! 449: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; ! 450: register struct buf *bp = mi->mi_tab.b_actf; ! 451: register struct hpst *st; ! 452: struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; ! 453: daddr_t bn; ! 454: int sn, dist; ! 455: ! 456: st = &hpst[mi->mi_type]; ! 457: hpaddr->hpcs1 = 0; ! 458: if ((hpaddr->hpcs1&HP_DVA) == 0) ! 459: return (MBU_BUSY); ! 460: if ((hpaddr->hpds & HPDS_VV) == 0 || !sc->sc_hpinit) { ! 461: struct buf *bbp = &bhpbuf[mi->mi_unit]; ! 462: ! 463: sc->sc_hpinit = 1; ! 464: hpaddr->hpcs1 = HP_DCLR|HP_GO; ! 465: if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive)) ! 466: printf("DCLR attn\n"); ! 467: hpaddr->hpcs1 = HP_PRESET|HP_GO; ! 468: if (!ML11) ! 469: hpaddr->hpof = HPOF_FMT22; ! 470: mbclrattn(mi); ! 471: if (!ML11) { ! 472: bbp->b_flags = B_READ|B_BUSY; ! 473: bbp->b_dev = bp->b_dev; ! 474: bbp->b_bcount = 512; ! 475: bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit]; ! 476: bbp->b_blkno = st->ncyl*st->nspc - st->nsect; ! 477: bbp->b_cylin = st->ncyl - 1; ! 478: mi->mi_tab.b_actf = bbp; ! 479: bbp->av_forw = bp; ! 480: bp = bbp; ! 481: } ! 482: } ! 483: if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) ! 484: return (MBU_DODATA); ! 485: if (ML11) ! 486: return (MBU_DODATA); ! 487: if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY) ! 488: return (MBU_DODATA); ! 489: bn = dkblock(bp); ! 490: sn = bn%st->nspc; ! 491: sn = (sn + st->nsect - st->sdist) % st->nsect; ! 492: if (bp->b_cylin == MASKREG(hpaddr->hpdc)) { ! 493: if (sc->sc_doseeks) ! 494: return (MBU_DODATA); ! 495: dist = (MASKREG(hpaddr->hpla) >> 6) - st->nsect + 1; ! 496: if (dist < 0) ! 497: dist += st->nsect; ! 498: if (dist > st->nsect - st->rdist) ! 499: return (MBU_DODATA); ! 500: } else ! 501: hpaddr->hpdc = bp->b_cylin; ! 502: if (sc->sc_doseeks) ! 503: hpaddr->hpcs1 = HP_SEEK|HP_GO; ! 504: else { ! 505: hpaddr->hpda = sn; ! 506: hpaddr->hpcs1 = HP_SEARCH|HP_GO; ! 507: } ! 508: return (MBU_STARTED); ! 509: } ! 510: ! 511: hpstart(mi) ! 512: register struct mba_device *mi; ! 513: { ! 514: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; ! 515: register struct buf *bp = mi->mi_tab.b_actf; ! 516: register struct hpst *st = &hpst[mi->mi_type]; ! 517: struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; ! 518: daddr_t bn; ! 519: int sn, tn; ! 520: ! 521: bn = dkblock(bp); ! 522: if (ML11) ! 523: hpaddr->hpda = bn; ! 524: else { ! 525: sn = bn%st->nspc; ! 526: tn = sn/st->nsect; ! 527: sn %= st->nsect; ! 528: hpaddr->hpdc = bp->b_cylin; ! 529: hpaddr->hpda = (tn << 8) + sn; ! 530: } ! 531: if (sc->sc_hdr) { ! 532: if (bp->b_flags & B_READ) ! 533: return (HP_RHDR|HP_GO); ! 534: else ! 535: return (HP_WHDR|HP_GO); ! 536: } ! 537: return (0); ! 538: } ! 539: ! 540: hpdtint(mi, mbsr) ! 541: register struct mba_device *mi; ! 542: int mbsr; ! 543: { ! 544: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; ! 545: register struct buf *bp = mi->mi_tab.b_actf; ! 546: register struct hpst *st; ! 547: register int er1, er2; ! 548: struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; ! 549: int retry = 0; ! 550: ! 551: st = &hpst[mi->mi_type]; ! 552: if (bp->b_flags&B_BAD && hpecc(mi, CONT)) ! 553: return (MBD_RESTARTED); ! 554: if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) { ! 555: er1 = hpaddr->hper1; ! 556: er2 = hpaddr->hper2; ! 557: #ifdef HPDEBUG ! 558: if (hpdebug) { ! 559: int dc = hpaddr->hpdc, da = hpaddr->hpda; ! 560: ! 561: printf("hperr: bp %x cyl %d blk %d as %o ", ! 562: bp, bp->b_cylin, bp->b_blkno, ! 563: hpaddr->hpas&0xff); ! 564: printf("dc %x da %x\n",MASKREG(dc), MASKREG(da)); ! 565: printf("errcnt %d ", mi->mi_tab.b_errcnt); ! 566: printf("mbsr=%b ", mbsr, mbsr_bits); ! 567: printf("er1=%b er2=%b\n", MASKREG(er1), HPER1_BITS, ! 568: MASKREG(er2), HPER2_BITS); ! 569: DELAY(1000000); ! 570: } ! 571: #endif ! 572: if (er1 & HPER1_HCRC) { ! 573: er1 &= ~(HPER1_HCE|HPER1_FER); ! 574: er2 &= ~HPER2_BSE; ! 575: } ! 576: if (er1&HPER1_WLE) { ! 577: printf("hp%d: write locked\n", dkunit(bp)); ! 578: bp->b_flags |= B_ERROR; ! 579: } else if (MASKREG(er1) == HPER1_FER && RP06 && !sc->sc_hdr) { ! 580: if (hpecc(mi, BSE)) ! 581: return (MBD_RESTARTED); ! 582: goto hard; ! 583: } else if (++mi->mi_tab.b_errcnt > 27 || ! 584: mbsr & MBSR_HARD || ! 585: er1 & HPER1_HARD || ! 586: sc->sc_hdr || ! 587: (!ML11 && (er2 & HPER2_HARD))) { ! 588: /* ! 589: * HCRC means the header is screwed up and the sector ! 590: * might well exist in the bad sector table, ! 591: * better check.... ! 592: */ ! 593: if ((er1&HPER1_HCRC) && ! 594: !ML11 && !sc->sc_hdr && hpecc(mi, BSE)) ! 595: return (MBD_RESTARTED); ! 596: hard: ! 597: if (ML11) ! 598: bp->b_blkno = MASKREG(hpaddr->hpda); ! 599: else ! 600: bp->b_blkno = MASKREG(hpaddr->hpdc) * st->nspc + ! 601: (MASKREG(hpaddr->hpda) >> 8) * st->nsect + ! 602: (hpaddr->hpda&0xff); ! 603: /* ! 604: * If we have a data check error or a hard ! 605: * ecc error the bad sector has been read/written, ! 606: * and the controller registers are pointing to ! 607: * the next sector... ! 608: */ ! 609: if (er1&(HPER1_DCK|HPER1_ECH) || sc->sc_hdr) ! 610: bp->b_blkno--; ! 611: harderr(bp, "hp"); ! 612: if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC))) ! 613: printf("mbsr=%b ", mbsr, mbsr_bits); ! 614: printf("er1=%b er2=%b", ! 615: MASKREG(hpaddr->hper1), HPER1_BITS, ! 616: MASKREG(hpaddr->hper2), HPER2_BITS); ! 617: if (hpaddr->hpmr) ! 618: printf(" mr=%o", MASKREG(hpaddr->hpmr)); ! 619: if (hpaddr->hpmr2) ! 620: printf(" mr2=%o", MASKREG(hpaddr->hpmr2)); ! 621: if (sc->sc_hdr) ! 622: printf(" (hdr i/o)"); ! 623: printf("\n"); ! 624: bp->b_flags |= B_ERROR; ! 625: retry = 0; ! 626: sc->sc_recal = 0; ! 627: } else if ((er2 & HPER2_BSE) && !ML11) { ! 628: if (hpecc(mi, BSE)) ! 629: return (MBD_RESTARTED); ! 630: goto hard; ! 631: } else if (RM80 && er2&HPER2_SSE) { ! 632: (void) hpecc(mi, SSE); ! 633: return (MBD_RESTARTED); ! 634: } else if ((er1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) { ! 635: if (hpecc(mi, ECC)) ! 636: return (MBD_RESTARTED); ! 637: /* else done */ ! 638: } else ! 639: retry = 1; ! 640: hpaddr->hpcs1 = HP_DCLR|HP_GO; ! 641: if (ML11) { ! 642: if (mi->mi_tab.b_errcnt >= 16) ! 643: goto hard; ! 644: } else if ((mi->mi_tab.b_errcnt&07) == 4) { ! 645: hpaddr->hpcs1 = HP_RECAL|HP_GO; ! 646: sc->sc_recal = 1; ! 647: return (MBD_RESTARTED); ! 648: } ! 649: if (retry) ! 650: return (MBD_RETRY); ! 651: } ! 652: #ifdef HPDEBUG ! 653: else ! 654: if (hpdebug && sc->sc_recal) { ! 655: printf("recal %d ", sc->sc_recal); ! 656: printf("errcnt %d\n", mi->mi_tab.b_errcnt); ! 657: printf("mbsr=%b ", mbsr, mbsr_bits); ! 658: printf("er1=%b er2=%b\n", ! 659: hpaddr->hper1, HPER1_BITS, ! 660: hpaddr->hper2, HPER2_BITS); ! 661: } ! 662: #endif ! 663: switch (sc->sc_recal) { ! 664: ! 665: case 1: ! 666: hpaddr->hpdc = bp->b_cylin; ! 667: hpaddr->hpcs1 = HP_SEEK|HP_GO; ! 668: sc->sc_recal++; ! 669: return (MBD_RESTARTED); ! 670: case 2: ! 671: if (mi->mi_tab.b_errcnt < 16 || ! 672: (bp->b_flags & B_READ) == 0) ! 673: goto donerecal; ! 674: hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22; ! 675: hpaddr->hpcs1 = HP_OFFSET|HP_GO; ! 676: sc->sc_recal++; ! 677: return (MBD_RESTARTED); ! 678: donerecal: ! 679: case 3: ! 680: sc->sc_recal = 0; ! 681: return (MBD_RETRY); ! 682: } ! 683: sc->sc_hdr = 0; ! 684: bp->b_resid = MASKREG(-mi->mi_mba->mba_bcr); ! 685: if (mi->mi_tab.b_errcnt >= 16) { ! 686: /* ! 687: * This is fast and occurs rarely; we don't ! 688: * bother with interrupts. ! 689: */ ! 690: hpaddr->hpcs1 = HP_RTC|HP_GO; ! 691: while (hpaddr->hpds & HPDS_PIP) ! 692: ; ! 693: mbclrattn(mi); ! 694: } ! 695: if (!ML11) { ! 696: hpaddr->hpof = HPOF_FMT22; ! 697: hpaddr->hpcs1 = HP_RELEASE|HP_GO; ! 698: } ! 699: return (MBD_DONE); ! 700: } ! 701: ! 702: hpread(dev, uio) ! 703: dev_t dev; ! 704: struct uio *uio; ! 705: { ! 706: register int unit = minor(dev) >> 3; ! 707: ! 708: if (unit >= NHP) ! 709: return (ENXIO); ! 710: return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio)); ! 711: } ! 712: ! 713: hpwrite(dev, uio) ! 714: dev_t dev; ! 715: struct uio *uio; ! 716: { ! 717: register int unit = minor(dev) >> 3; ! 718: ! 719: if (unit >= NHP) ! 720: return (ENXIO); ! 721: return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio)); ! 722: } ! 723: ! 724: /*ARGSUSED*/ ! 725: hpioctl(dev, cmd, data, flag) ! 726: dev_t dev; ! 727: int cmd; ! 728: caddr_t data; ! 729: int flag; ! 730: { ! 731: ! 732: switch (cmd) { ! 733: ! 734: case DKIOCHDR: /* do header read/write */ ! 735: hpsoftc[minor(dev) >> 3].sc_hdr = 1; ! 736: return (0); ! 737: ! 738: default: ! 739: return (ENXIO); ! 740: } ! 741: } ! 742: ! 743: hpecc(mi, flag) ! 744: register struct mba_device *mi; ! 745: int flag; ! 746: { ! 747: register struct mba_regs *mbp = mi->mi_mba; ! 748: register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv; ! 749: register struct buf *bp = mi->mi_tab.b_actf; ! 750: register struct hpst *st = &hpst[mi->mi_type]; ! 751: int npf, o; ! 752: int bn, cn, tn, sn; ! 753: int bcr; ! 754: ! 755: bcr = MASKREG(mbp->mba_bcr); ! 756: if (bcr) ! 757: bcr |= 0xffff0000; /* sxt */ ! 758: if (flag == CONT) ! 759: npf = bp->b_error; ! 760: else ! 761: npf = btop(bcr + bp->b_bcount); ! 762: o = (int)bp->b_un.b_addr & PGOFSET; ! 763: bn = dkblock(bp); ! 764: cn = bp->b_cylin; ! 765: sn = bn%(st->nspc) + npf; ! 766: tn = sn/st->nsect; ! 767: sn %= st->nsect; ! 768: cn += tn/st->ntrak; ! 769: tn %= st->ntrak; ! 770: switch (flag) { ! 771: case ECC: { ! 772: register int i; ! 773: caddr_t addr; ! 774: struct pte mpte; ! 775: int bit, byte, mask; ! 776: ! 777: npf--; /* because block in error is previous block */ ! 778: printf("hp%d%c: soft ecc sn%d\n", dkunit(bp), ! 779: 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); ! 780: mask = MASKREG(rp->hpec2); ! 781: i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ ! 782: bit = i&07; ! 783: i = (i&~07)>>3; ! 784: byte = i + o; ! 785: while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { ! 786: mpte = mbp->mba_map[npf+btop(byte)]; ! 787: addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); ! 788: putmemc(addr, getmemc(addr)^(mask<<bit)); ! 789: byte++; ! 790: i++; ! 791: bit -= 8; ! 792: } ! 793: if (bcr == 0) ! 794: return (0); ! 795: npf++; ! 796: break; ! 797: } ! 798: ! 799: case SSE: ! 800: rp->hpof |= HPOF_SSEI; ! 801: mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); ! 802: break; ! 803: ! 804: case BSE: ! 805: #ifdef HPBDEBUG ! 806: if (hpbdebug) ! 807: printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); ! 808: #endif ! 809: if (rp->hpof&HPOF_SSEI) ! 810: sn++; ! 811: if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0) ! 812: return (0); ! 813: bp->b_flags |= B_BAD; ! 814: bp->b_error = npf + 1; ! 815: bn = st->ncyl*st->nspc - st->nsect - 1 - bn; ! 816: cn = bn/st->nspc; ! 817: sn = bn%st->nspc; ! 818: tn = sn/st->nsect; ! 819: sn %= st->nsect; ! 820: mbp->mba_bcr = -512; ! 821: rp->hpof &= ~HPOF_SSEI; ! 822: #ifdef HPBDEBUG ! 823: if (hpbdebug) ! 824: printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); ! 825: #endif ! 826: break; ! 827: ! 828: case CONT: ! 829: #ifdef HPBDEBUG ! 830: if (hpbdebug) ! 831: printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); ! 832: #endif ! 833: npf = bp->b_error; ! 834: bp->b_flags &= ~B_BAD; ! 835: mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); ! 836: if (MASKREG(mbp->mba_bcr) == 0) ! 837: return (0); ! 838: break; ! 839: } ! 840: rp->hpcs1 = HP_DCLR|HP_GO; ! 841: if (rp->hpof&HPOF_SSEI) ! 842: sn++; ! 843: rp->hpdc = cn; ! 844: rp->hpda = (tn<<8) + sn; ! 845: mbp->mba_sr = -1; ! 846: mbp->mba_var = (int)ptob(npf) + o; ! 847: rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO; ! 848: mi->mi_tab.b_errcnt = 0; /* error has been corrected */ ! 849: return (1); ! 850: } ! 851: ! 852: #define DBSIZE 20 ! 853: ! 854: hpdump(dev) ! 855: dev_t dev; ! 856: { ! 857: register struct mba_device *mi; ! 858: register struct mba_regs *mba; ! 859: struct hpdevice *hpaddr; ! 860: char *start; ! 861: int num, unit; ! 862: register struct hpst *st; ! 863: ! 864: num = maxfree; ! 865: start = 0; ! 866: unit = minor(dev) >> 3; ! 867: if (unit >= NHP) ! 868: return (ENXIO); ! 869: #define phys(a,b) ((b)((int)(a)&0x7fffffff)) ! 870: mi = phys(hpinfo[unit],struct mba_device *); ! 871: if (mi == 0 || mi->mi_alive == 0) ! 872: return (ENXIO); ! 873: mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; ! 874: mba->mba_cr = MBCR_INIT; ! 875: hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive]; ! 876: if ((hpaddr->hpds & HPDS_VV) == 0) { ! 877: hpaddr->hpcs1 = HP_DCLR|HP_GO; ! 878: hpaddr->hpcs1 = HP_PRESET|HP_GO; ! 879: hpaddr->hpof = HPOF_FMT22; ! 880: } ! 881: st = &hpst[mi->mi_type]; ! 882: if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks) ! 883: return (EINVAL); ! 884: while (num > 0) { ! 885: register struct pte *hpte = mba->mba_map; ! 886: register int i; ! 887: int blk, cn, sn, tn; ! 888: daddr_t bn; ! 889: ! 890: blk = num > DBSIZE ? DBSIZE : num; ! 891: bn = dumplo + btop(start); ! 892: cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff; ! 893: sn = bn%st->nspc; ! 894: tn = sn/st->nsect; ! 895: sn = sn%st->nsect; ! 896: hpaddr->hpdc = cn; ! 897: hpaddr->hpda = (tn << 8) + sn; ! 898: for (i = 0; i < blk; i++) ! 899: *(int *)hpte++ = (btop(start)+i) | PG_V; ! 900: mba->mba_sr = -1; ! 901: mba->mba_bcr = -(blk*NBPG); ! 902: mba->mba_var = 0; ! 903: hpaddr->hpcs1 = HP_WCOM | HP_GO; ! 904: while ((hpaddr->hpds & HPDS_DRY) == 0) ! 905: ; ! 906: if (hpaddr->hpds&HPDS_ERR) ! 907: return (EIO); ! 908: start += blk*NBPG; ! 909: num -= blk; ! 910: } ! 911: return (0); ! 912: } ! 913: ! 914: hpsize(dev) ! 915: dev_t dev; ! 916: { ! 917: int unit = minor(dev) >> 3; ! 918: struct mba_device *mi; ! 919: struct hpst *st; ! 920: ! 921: if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0) ! 922: return (-1); ! 923: st = &hpst[mi->mi_type]; ! 924: return ((int)st->sizes[minor(dev) & 07].nblocks); ! 925: } ! 926: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.