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