|
|
1.1 ! root 1: /* hp.c 6.3 83/09/23 */ ! 2: ! 3: /* ! 4: * RP??/RM?? disk driver ! 5: * with ECC handling and bad block forwarding. ! 6: * Also supports header io operations and ! 7: * commands to write check header and data. ! 8: */ ! 9: #include "../h/param.h" ! 10: #include "../h/inode.h" ! 11: #include "../h/fs.h" ! 12: #include "../h/dkbad.h" ! 13: ! 14: #include "../vax/pte.h" ! 15: #include "../vaxmba/hpreg.h" ! 16: #include "../vaxmba/mbareg.h" ! 17: ! 18: #include "saio.h" ! 19: #include "savax.h" ! 20: ! 21: #define MASKREG(reg) ((reg)&0xffff) ! 22: ! 23: #define MAXBADDESC 126 ! 24: #define SECTSIZ 512 /* sector size in bytes */ ! 25: #define HDRSIZ 4 /* number of bytes in sector header */ ! 26: #define MAXECC 5 /* max # bits allow in ecc error w/ F_ECCLM */ ! 27: ! 28: char hp_type[MAXNMBA*8] = { 0 }; ! 29: extern struct st hpst[]; ! 30: ! 31: short hptypes[] = { ! 32: MBDT_RM03, ! 33: MBDT_RM05, ! 34: MBDT_RP06, ! 35: MBDT_RM80, ! 36: MBDT_RP05, ! 37: MBDT_RP07, ! 38: MBDT_ML11A, ! 39: MBDT_ML11B, ! 40: -1, /* 9755 */ ! 41: -1, /* 9730 */ ! 42: -1, /* Capricorn */ ! 43: -1, /* Eagle */ ! 44: MBDT_RM02, /* actually something else */ ! 45: -1, /* 9300 */ ! 46: 0 ! 47: }; ! 48: ! 49: #define RP06 (hptypes[hp_type[unit]] <= MBDT_RP06) ! 50: #define ML11 (hptypes[hp_type[unit]] == MBDT_ML11A) ! 51: #define RM80 (hptypes[hp_type[unit]] == MBDT_RM80) ! 52: ! 53: u_char hp_offset[16] = { ! 54: HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, ! 55: HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, ! 56: HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, ! 57: 0, 0, 0, 0, ! 58: }; ! 59: ! 60: struct dkbad hpbad[MAXNMBA*8]; ! 61: int ssect[MAXNMBA*8]; /* 1 when on track w/skip sector */ ! 62: ! 63: int hpdebug[MAXNMBA*8]; ! 64: #define HPF_BSEDEBUG 01 /* debugging bad sector forwarding */ ! 65: #define HPF_ECCDEBUG 02 /* debugging ecc correction */ ! 66: ! 67: int sectsiz; ! 68: ! 69: /* ! 70: * When awaiting command completion, don't ! 71: * hang on to the status register since ! 72: * this ties up some controllers. ! 73: */ ! 74: #define HPWAIT(addr) \ ! 75: while ((((addr)->hpds)&HPDS_DRY)==0) DELAY(500); ! 76: ! 77: hpopen(io) ! 78: register struct iob *io; ! 79: { ! 80: register unit = io->i_unit; ! 81: struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); ! 82: register struct st *st; ! 83: ! 84: mbainit(UNITTOMBA(unit)); ! 85: if (hp_type[unit] == 0) { ! 86: register i, type = hpaddr->hpdt & MBDT_TYPE; ! 87: struct iob tio; ! 88: ! 89: for (i = 0; hptypes[i]; i++) ! 90: if (hptypes[i] == type) ! 91: goto found; ! 92: _stop("unknown drive type"); ! 93: found: ! 94: hpaddr->hpcs1 = HP_DCLR|HP_GO; /* init drive */ ! 95: hpaddr->hpcs1 = HP_PRESET|HP_GO; ! 96: if (!ML11) ! 97: hpaddr->hpof = HPOF_FMT22; ! 98: hp_type[unit] = hpmaptype(hpaddr, i, unit); ! 99: /* ! 100: * Read in the bad sector table. ! 101: */ ! 102: st = &hpst[hp_type[unit]]; ! 103: tio = *io; ! 104: tio.i_bn = st->nspc * st->ncyl - st->nsect; ! 105: tio.i_ma = (char *)&hpbad[unit]; ! 106: tio.i_cc = sizeof (struct dkbad); ! 107: tio.i_flgs |= F_RDDATA; ! 108: for (i = 0; i < 5; i++) { ! 109: if (hpstrategy(&tio, READ) == sizeof (struct dkbad)) ! 110: break; ! 111: tio.i_bn += 2; ! 112: } ! 113: if (i == 5) { ! 114: printf("Unable to read bad sector table\n"); ! 115: for (i = 0; i < MAXBADDESC; i++) { ! 116: hpbad[unit].bt_bad[i].bt_cyl = -1; ! 117: hpbad[unit].bt_bad[i].bt_trksec = -1; ! 118: } ! 119: } ! 120: } ! 121: if (io->i_boff < 0 || io->i_boff > 7 || ! 122: st->off[io->i_boff]== -1) ! 123: _stop("hp bad minor"); ! 124: io->i_boff = st->off[io->i_boff] * st->nspc; ! 125: } ! 126: ! 127: hpstrategy(io, func) ! 128: register struct iob *io; ! 129: { ! 130: register unit = io->i_unit; ! 131: struct mba_regs *mba = mbamba(unit); ! 132: daddr_t bn, startblock; ! 133: struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); ! 134: struct st *st = &hpst[hp_type[unit]]; ! 135: int cn, tn, sn, bytecnt, bytesleft; ! 136: char *membase; ! 137: int er1, er2, hprecal; ! 138: ! 139: sectsiz = SECTSIZ; ! 140: if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0) ! 141: sectsiz += HDRSIZ; ! 142: if ((hpaddr->hpds & HPDS_VV) == 0) { ! 143: hpaddr->hpcs1 = HP_DCLR|HP_GO; ! 144: hpaddr->hpcs1 = HP_PRESET|HP_GO; ! 145: if (!ML11) ! 146: hpaddr->hpof = HPOF_FMT22; ! 147: } ! 148: io->i_errcnt = 0; ! 149: ssect[unit] = 0; ! 150: bytecnt = io->i_cc; ! 151: membase = io->i_ma; ! 152: startblock = io->i_bn; ! 153: hprecal = 0; ! 154: ! 155: restart: ! 156: bn = io->i_bn; ! 157: cn = bn/st->nspc; ! 158: sn = bn%st->nspc; ! 159: tn = sn/st->nsect; ! 160: sn = sn%st->nsect + ssect[unit]; ! 161: ! 162: HPWAIT(hpaddr); ! 163: mba->mba_sr = -1; ! 164: if (ML11) ! 165: hpaddr->hpda = bn; ! 166: else { ! 167: hpaddr->hpdc = cn; ! 168: hpaddr->hpda = (tn << 8) + sn; ! 169: } ! 170: if (mbastart(io, func) != 0) /* start transfer */ ! 171: return (-1); ! 172: HPWAIT(hpaddr); ! 173: /* ! 174: * Successful data transfer, return. ! 175: */ ! 176: if ((hpaddr->hpds&HPDS_ERR) == 0 && (mba->mba_sr&MBSR_EBITS) == 0) ! 177: goto done; ! 178: ! 179: /* ! 180: * Error handling. Calculate location of error. ! 181: */ ! 182: bytesleft = MASKREG(mba->mba_bcr); ! 183: if (bytesleft) ! 184: bytesleft |= 0xffff0000; /* sxt */ ! 185: bn = io->i_bn + (io->i_cc + bytesleft) / sectsiz; ! 186: er1 = MASKREG(hpaddr->hper1); ! 187: er2 = MASKREG(hpaddr->hper2); ! 188: if (er1 & (HPER1_DCK|HPER1_ECH)) ! 189: bn--; /* Error is in Prev block */ ! 190: cn = bn/st->nspc; ! 191: sn = bn%st->nspc; ! 192: tn = sn/st->nsect; ! 193: sn = sn%st->nsect; ! 194: if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG)) { ! 195: printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b\n", ! 196: cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); ! 197: printf("er1=%b er2=%b\n", er1, HPER1_BITS, er2, HPER2_BITS); ! 198: printf("bytes left: %d, of 0x%x, da 0x%x\n",-bytesleft, ! 199: hpaddr->hpof, hpaddr->hpda); ! 200: } ! 201: if (er1 & HPER1_HCRC) { ! 202: er1 &= ~(HPER1_HCE|HPER1_FER); ! 203: er2 &= ~HPER2_BSE; ! 204: } ! 205: /* ! 206: * Give up early if drive write locked. ! 207: */ ! 208: if (er1&HPER1_WLE) { ! 209: printf("hp%d: write locked\n", unit); ! 210: return (-1); ! 211: } ! 212: /* ! 213: * Interpret format error bit as a bad block on RP06's. ! 214: */ ! 215: if (MASKREG(er1) == HPER1_FER && RP06) ! 216: goto badsect; ! 217: ! 218: /* ! 219: * If a hard error, or maximum retry count ! 220: * exceeded, clear controller state and ! 221: * pass back error to caller. ! 222: */ ! 223: if (++io->i_errcnt > 27 || (er1 & HPER1_HARD) || ! 224: (!ML11 && (er2 & HPER2_HARD))) { ! 225: /* ! 226: * The last ditch effort to bad sector forward ! 227: * below will probably fail since mba byte ctr ! 228: * (bcr) is different for BSE and ECC errors and ! 229: * the wrong block will be revectored to if one ! 230: * has 2 contiguous bad blocks and reads the second. ! 231: * For now, we can probably just let a header CRC ! 232: * error be handled like a BSE since no data will ! 233: * have been transferred and the bcr should the same ! 234: * as it would with a BSE error. ! 235: * --ghg. ! 236: */ ! 237: if (er1 & HPER1_HCRC) ! 238: if ((io->i_flgs&F_NBSF) == 0 && hpecc(io, BSE) == 0) ! 239: goto success; ! 240: hard0: ! 241: io->i_error = EHER; ! 242: if (mba->mba_sr & (MBSR_WCKUP|MBSR_WCKLWR)) ! 243: io->i_error = EWCK; ! 244: hard: ! 245: io->i_errblk = bn + ssect[unit]; ! 246: printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b \n", ! 247: cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); ! 248: printf("er1=%b er2=%b", er1, HPER1_BITS, er2, HPER2_BITS); ! 249: if (hpaddr->hpmr) ! 250: printf(" mr1=%o", MASKREG(hpaddr->hpmr)); ! 251: if (hpaddr->hpmr2) ! 252: printf(" mr2=%o", MASKREG(hpaddr->hpmr2)); ! 253: if (hpdebug[unit] & (HPF_BSEDEBUG|HPF_ECCDEBUG)) ! 254: printf(" dc=%d, da=0x%x",MASKREG(hpaddr->hpdc), ! 255: MASKREG(hpaddr->hpda)); ! 256: hpaddr->hpcs1 = HP_DCLR|HP_GO; ! 257: printf("\n"); ! 258: bytecnt = -1; ! 259: goto done; ! 260: ! 261: } ! 262: /* ! 263: * Attempt to forward bad sectors on ! 264: * anything but an ML11. If drive ! 265: * supports skip sector handling, try to ! 266: * use it first; otherwise try the ! 267: * bad sector table. ! 268: */ ! 269: if ((er2 & HPER2_BSE) && !ML11) { ! 270: badsect: ! 271: if (!ssect[unit] && (er2&HPER2_SSE)) ! 272: goto skipsect; ! 273: if (io->i_flgs & F_NBSF) { ! 274: io->i_error = EBSE; ! 275: goto hard; ! 276: } ! 277: if (hpecc(io, BSE) == 0) ! 278: goto success; ! 279: io->i_error = EBSE; ! 280: goto hard; ! 281: } ! 282: ! 283: /* ! 284: * Skip sector handling. ! 285: */ ! 286: if (RM80 && (er2 & HPER2_SSE)) { ! 287: skipsect: ! 288: (void) hpecc(io, SSE); ! 289: ssect[unit] = 1; ! 290: goto success; ! 291: } ! 292: /* ! 293: * ECC correction? ! 294: */ ! 295: if ((er1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) { ! 296: if (hpecc(io, ECC) == 0) ! 297: goto success; ! 298: io->i_error = EECC; ! 299: io->i_errblk = bn + ssect[unit]; ! 300: return (-1); ! 301: } ! 302: #ifdef F_SEVRE ! 303: if (io->i_flgs & F_SEVRE) ! 304: goto hard; ! 305: #endif ! 306: if (ML11 && (io->i_errcnt >= 16)) ! 307: goto hard0; ! 308: /* fall thru to retry */ ! 309: hpaddr->hpcs1 = HP_DCLR|HP_GO; ! 310: HPWAIT(hpaddr); ! 311: ! 312: /* ! 313: * Every fourth retry recalibrate. ! 314: */ ! 315: if (((io->i_errcnt & 07) == 4) ) { ! 316: hpaddr->hpcs1 = HP_RECAL|HP_GO; ! 317: HPWAIT(hpaddr); ! 318: hpaddr->hpdc = cn; ! 319: hpaddr->hpcs1 = HP_SEEK|HP_GO; ! 320: HPWAIT(hpaddr); ! 321: } ! 322: ! 323: if (io->i_errcnt >= 16 && (io->i_flgs & F_READ)) { ! 324: hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22; ! 325: hpaddr->hpcs1 = HP_OFFSET|HP_GO; ! 326: HPWAIT(hpaddr); ! 327: } ! 328: if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG)) ! 329: printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", ! 330: io->i_bn, io->i_cc, io->i_ma, hprecal); ! 331: goto restart; /* retry whole transfer --ghg */ ! 332: ! 333: success: ! 334: /* ! 335: * On successful error recovery, bump ! 336: * block number to advance to next portion ! 337: * of i/o transfer. ! 338: */ ! 339: bn++; ! 340: if ((bn-startblock) * sectsiz < bytecnt) { ! 341: io->i_bn = bn; ! 342: io->i_ma = membase + (io->i_bn - startblock)*sectsiz; ! 343: io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz; ! 344: if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG)) ! 345: printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", ! 346: io->i_bn, io->i_cc, io->i_ma, hprecal); ! 347: goto restart; ! 348: } ! 349: done: ! 350: if (io->i_errcnt >= 16) { ! 351: hpaddr->hpcs1 = HP_RTC|HP_GO; ! 352: while (hpaddr->hpds & HPDS_PIP) ! 353: ; ! 354: } ! 355: return (bytecnt); ! 356: } ! 357: ! 358: hpecc(io, flag) ! 359: register struct iob *io; ! 360: int flag; ! 361: { ! 362: register unit = io->i_unit; ! 363: register struct mba_regs *mbp = mbamba(unit); ! 364: register struct hpdevice *rp = (struct hpdevice *)mbadrv(unit); ! 365: register struct st *st = &hpst[hp_type[unit]]; ! 366: int npf, bn, cn, tn, sn, bcr; ! 367: ! 368: bcr = MASKREG(mbp->mba_bcr); ! 369: if (bcr) ! 370: bcr |= 0xffff0000; /* sxt */ ! 371: npf = (bcr + io->i_cc) / sectsiz; /* # sectors read */ ! 372: if (flag == ECC) ! 373: npf--; /* Error is in prev block --ghg */ ! 374: bn = io->i_bn + npf + ssect[unit]; /* physical block #*/ ! 375: if (hpdebug[unit]&HPF_ECCDEBUG) ! 376: printf("bcr=%d npf=%d ssect=%d sectsiz=%d i_cc=%d\n", ! 377: bcr, npf, ssect[unit], sectsiz, io->i_cc); ! 378: /* ! 379: * ECC correction logic. ! 380: */ ! 381: if (flag == ECC) { ! 382: register int i; ! 383: caddr_t addr; ! 384: int bit, o, mask, ecccnt = 0; ! 385: ! 386: printf("hp%d: soft ecc sn%d\n", unit, bn); ! 387: mask = MASKREG(rp->hpec2); ! 388: i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ ! 389: bit = i&07; ! 390: o = (i & ~07) >> 3; ! 391: rp->hpcs1 = HP_DCLR | HP_GO; ! 392: while (o <sectsiz && npf*sectsiz + o < io->i_cc && bit > -11) { ! 393: addr = io->i_ma + (npf*sectsiz) + o; ! 394: /* ! 395: * No data transfer occurs with a write check, ! 396: * so don't correct the resident copy of data. ! 397: */ ! 398: if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) { ! 399: if (hpdebug[unit] & HPF_ECCDEBUG) ! 400: printf("addr=%x old=%x ", addr, ! 401: (*addr & 0xff)); ! 402: *addr ^= (mask << bit); ! 403: if (hpdebug[unit] & HPF_ECCDEBUG) ! 404: printf("new=%x\n",(*addr & 0xff)); ! 405: } ! 406: o++, bit -= 8; ! 407: if ((io->i_flgs & F_ECCLM) && ecccnt++ >= MAXECC) ! 408: return (1); ! 409: } ! 410: #ifdef F_SEVRE ! 411: if (io->i_flgs & F_SEVRE) ! 412: return(1); ! 413: #endif ! 414: return (0); ! 415: } ! 416: ! 417: /* ! 418: * Skip sector error. ! 419: * Set skip-sector-inhibit and ! 420: * read next sector ! 421: */ ! 422: if (flag == SSE) { ! 423: rp->hpcs1 = HP_DCLR | HP_GO; ! 424: HPWAIT(rp); ! 425: rp->hpof |= HPOF_SSEI; ! 426: return (0); ! 427: } ! 428: ! 429: /* ! 430: * Bad block forwarding. ! 431: */ ! 432: if (flag == BSE) { ! 433: int bbn; ! 434: ! 435: rp->hpcs1 = HP_DCLR | HP_GO; ! 436: if (hpdebug[unit] & HPF_BSEDEBUG) ! 437: printf("hpecc: BSE @ bn %d\n", bn); ! 438: cn = bn/st->nspc; ! 439: sn = bn%st->nspc; ! 440: tn = sn/st->nsect; ! 441: sn = sn%st->nsect; ! 442: bcr += sectsiz; ! 443: if ((bbn = isbad(&hpbad[unit], cn, tn, sn)) < 0) ! 444: return (1); ! 445: bbn = st->ncyl*st->nspc - st->nsect - 1 - bbn; ! 446: cn = bbn/st->nspc; ! 447: sn = bbn%st->nspc; ! 448: tn = sn/st->nsect; ! 449: sn = sn%st->nsect; ! 450: io->i_cc = sectsiz; ! 451: io->i_ma += npf*sectsiz; ! 452: if (hpdebug[unit] & HPF_BSEDEBUG) ! 453: printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); ! 454: rp->hpof &= ~HPOF_SSEI; ! 455: mbp->mba_sr = -1; ! 456: rp->hpdc = cn; ! 457: rp->hpda = (tn<<8) + sn; ! 458: mbastart(io,io->i_flgs); ! 459: io->i_errcnt = 0; ! 460: HPWAIT(rp); ! 461: return (rp->hpds&HPDS_ERR); ! 462: } ! 463: printf("hpecc: flag=%d\n", flag); ! 464: return (1); ! 465: } ! 466: ! 467: /*ARGSUSED*/ ! 468: hpioctl(io, cmd, arg) ! 469: struct iob *io; ! 470: int cmd; ! 471: caddr_t arg; ! 472: { ! 473: register unit = io->i_unit; ! 474: struct st *st = &hpst[hp_type[unit]], *tmp; ! 475: struct mba_drv *drv = mbadrv(unit); ! 476: int flag; ! 477: ! 478: switch(cmd) { ! 479: ! 480: case SAIODEBUG: ! 481: flag = (int)arg; ! 482: if (flag > 0) ! 483: hpdebug[unit] |= flag; ! 484: else ! 485: hpdebug[unit] &= ~flag; ! 486: return (0); ! 487: ! 488: case SAIODEVDATA: ! 489: if ((drv->mbd_dt&MBDT_TAP) == 0) { ! 490: tmp = (struct st *)arg; ! 491: *tmp = *st; ! 492: return (0); ! 493: } ! 494: return (ECMD); ! 495: ! 496: case SAIOSSI: /* skip-sector-inhibit */ ! 497: if (drv->mbd_dt&MBDT_TAP) ! 498: return (ECMD); ! 499: if ((io->i_flgs&F_SSI) == 0) { ! 500: /* make sure this is done once only */ ! 501: io->i_flgs |= F_SSI; ! 502: st->nsect++; ! 503: st->nspc += st->ntrak; ! 504: } ! 505: return (0); ! 506: ! 507: case SAIONOSSI: /* remove skip-sector-inhibit */ ! 508: if (io->i_flgs & F_SSI) { ! 509: io->i_flgs &= ~F_SSI; ! 510: drv->mbd_of &= ~HPOF_SSEI; ! 511: st->nsect--; ! 512: st->nspc -= st->ntrak; ! 513: } ! 514: return(0); ! 515: ! 516: case SAIOSSDEV: /* drive have skip sector? */ ! 517: return (RM80 ? 0 : ECMD); ! 518: } ! 519: return (ECMD); ! 520: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.