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