|
|
1.1 ! root 1: /* hp.c 4.1 11/9/80 */ ! 2: ! 3: #include "../conf/hp.h" ! 4: #if NHP > 0 ! 5: /* ! 6: * RP06/RM03/RM05 disk driver ! 7: */ ! 8: ! 9: #include "../h/param.h" ! 10: #include "../h/systm.h" ! 11: #include "../h/dk.h" ! 12: #include "../h/buf.h" ! 13: #include "../h/conf.h" ! 14: #include "../h/dir.h" ! 15: #include "../h/user.h" ! 16: #include "../h/map.h" ! 17: #include "../h/pte.h" ! 18: #include "../h/mba.h" ! 19: #include "../h/mtpr.h" ! 20: #include "../h/vm.h" ! 21: ! 22: struct device ! 23: { ! 24: int hpcs1; /* control and Status register 1 */ ! 25: int hpds; /* Drive Status */ ! 26: int hper1; /* Error register 1 */ ! 27: int hpmr; /* Maintenance */ ! 28: int hpas; /* Attention Summary */ ! 29: int hpda; /* Desired address register */ ! 30: int hpdt; /* Drive type */ ! 31: int hpla; /* Look ahead */ ! 32: int hpsn; /* serial number */ ! 33: int hpof; /* Offset register */ ! 34: int hpdc; /* Desired Cylinder address register */ ! 35: int hpcc; /* Current Cylinder */ ! 36: int hper2; /* Error register 2 */ ! 37: int hper3; /* Error register 3 */ ! 38: int hpec1; /* Burst error bit position */ ! 39: int hpec2; /* Burst error bit pattern */ ! 40: }; ! 41: ! 42: #define RP 022 ! 43: #define RM 024 ! 44: #define RM5 027 ! 45: #define NSECT 22 ! 46: #define NTRAC 19 ! 47: #define NRMSECT 32 ! 48: #define NRMTRAC 5 ! 49: ! 50: #define _hpSDIST 2 ! 51: #define _hpRDIST 3 ! 52: ! 53: int hpSDIST = _hpSDIST; ! 54: int hpRDIST = _hpRDIST; ! 55: int hpseek; ! 56: ! 57: struct size ! 58: { ! 59: daddr_t nblocks; ! 60: int cyloff; ! 61: } hp_sizes[8] = ! 62: { ! 63: 15884, 0, /* A=cyl 0 thru 37 */ ! 64: 33440, 38, /* B=cyl 38 thru 117 */ ! 65: 340670, 0, /* C=cyl 0 thru 814 */ ! 66: 0, 0, ! 67: 0, 0, ! 68: 0, 0, ! 69: 291346, 118, /* G=cyl 118 thru 814 */ ! 70: 0, 0, ! 71: }, rm_sizes[8] = { ! 72: 15884, 0, /* A=cyl 0 thru 99 */ ! 73: 33440, 100, /* B=cyl 100 thru 309 */ ! 74: 131680, 0, /* C=cyl 0 thru 822 */ ! 75: 0, 0, ! 76: 0, 0, ! 77: 0, 0, ! 78: 82080, 310, /* G=cyl 310 thru 822 */ ! 79: 0, 0, ! 80: }, rm5_sizes[8] = { ! 81: 15884, 0, /* A=cyl 0 thru 26 */ ! 82: 33440, 27, /* B=cyl 27 thru 81 */ ! 83: 500992, 0, /* C=cyl 0 thru 823 */ ! 84: 15884, 562, /* D=cyl 562 thru 588 */ ! 85: 55936, 589, /* E=cyl 589 thru 680 */ ! 86: 86944, 681, /* F=cyl 681 thru 823 */ ! 87: 159296, 562, /* G=cyl 562 thru 823 */ ! 88: 291346, 82, /* H=cyl 82 thru 561 */ ! 89: }; ! 90: ! 91: #define P400 020 ! 92: #define M400 0220 ! 93: #define P800 040 ! 94: #define M800 0240 ! 95: #define P1200 060 ! 96: #define M1200 0260 ! 97: int hp_offset[16] = ! 98: { ! 99: P400, M400, P400, M400, ! 100: P800, M800, P800, M800, ! 101: P1200, M1200, P1200, M1200, ! 102: 0, 0, 0, 0, ! 103: }; ! 104: ! 105: struct buf hptab; ! 106: struct buf rhpbuf; ! 107: struct buf hputab[NHP]; ! 108: char hp_type[NHP]; /* drive type */ ! 109: ! 110: #define GO 01 ! 111: #define PRESET 020 ! 112: #define RTC 016 ! 113: #define OFFSET 014 ! 114: #define SEEK 04 ! 115: #define SEARCH 030 ! 116: #define RECAL 06 ! 117: #define DCLR 010 ! 118: #define WCOM 060 ! 119: #define RCOM 070 ! 120: ! 121: #define IE 0100 ! 122: #define PIP 020000 ! 123: #define DRY 0200 ! 124: #define ERR 040000 ! 125: #define TRE 040000 ! 126: #define DCK 0100000 ! 127: #define WLE 04000 ! 128: #define ECH 0100 ! 129: #define VV 0100 ! 130: #define DPR 0400 ! 131: #define MOL 010000 ! 132: #define FMT22 010000 ! 133: ! 134: #define b_cylin b_resid ! 135: ! 136: #ifdef INTRLVE ! 137: daddr_t dkblock(); ! 138: #endif ! 139: ! 140: hpstrategy(bp) ! 141: register struct buf *bp; ! 142: { ! 143: register struct buf *dp; ! 144: register unit, xunit, nspc; ! 145: long sz, bn; ! 146: struct size *sizes; ! 147: ! 148: if ((mbaact&(1<<HPMBANUM)) == 0) ! 149: mbainit(HPMBANUM); ! 150: xunit = minor(bp->b_dev) & 077; ! 151: sz = bp->b_bcount; ! 152: sz = (sz+511) >> 9; ! 153: unit = dkunit(bp); ! 154: if (hp_type[unit] == 0) { ! 155: struct device *hpaddr; ! 156: double mspw; ! 157: ! 158: /* determine device type */ ! 159: hpaddr = mbadev(HPMBA, unit); ! 160: ! 161: /* record transfer rate (these are guesstimates secs/word) */ ! 162: switch (hp_type[unit] = hpaddr->hpdt) { ! 163: case RM: mspw = .0000019728; break; ! 164: case RM5: mspw = .0000020345; break; ! 165: case RP: mspw = .0000029592; break; ! 166: } ! 167: if (DK_N + unit <= DK_NMAX) ! 168: dk_mspw[DK_N+unit] = mspw; ! 169: } ! 170: switch (hp_type[unit]) { ! 171: ! 172: case RM: ! 173: sizes = rm_sizes; ! 174: nspc = NRMSECT*NRMTRAC; ! 175: break; ! 176: case RM5: ! 177: sizes = rm5_sizes; ! 178: nspc = NRMSECT*NTRAC; ! 179: break; ! 180: case RP: ! 181: sizes = hp_sizes; ! 182: nspc = NSECT*NTRAC; ! 183: break; ! 184: default: ! 185: printf("hp: unknown device type 0%o\n", hp_type[unit]); ! 186: u.u_error = ENXIO; ! 187: unit = NHP+1; /* force error */ ! 188: } ! 189: if (unit >= NHP || ! 190: bp->b_blkno < 0 || ! 191: (bn = dkblock(bp))+sz > sizes[xunit&07].nblocks) { ! 192: bp->b_flags |= B_ERROR; ! 193: iodone(bp); ! 194: return; ! 195: } ! 196: bp->b_cylin = bn/nspc + sizes[xunit&07].cyloff; ! 197: dp = &hputab[unit]; ! 198: (void) spl5(); ! 199: disksort(dp, bp); ! 200: if (dp->b_active == 0) { ! 201: hpustart(unit); ! 202: if(hptab.b_active == 0) ! 203: hpstart(); ! 204: } ! 205: (void) spl0(); ! 206: } ! 207: ! 208: hpustart(unit) ! 209: register unit; ! 210: { ! 211: register struct buf *bp, *dp; ! 212: register struct device *hpaddr; ! 213: daddr_t bn; ! 214: int sn, cn, csn; ! 215: ! 216: ((struct mba_regs *)HPMBA)->mba_cr |= MBAIE; ! 217: hpaddr = mbadev(HPMBA, 0); ! 218: hpaddr->hpas = 1<<unit; ! 219: ! 220: if(unit >= NHP) ! 221: return; ! 222: if (unit+DK_N <= DK_NMAX) ! 223: dk_busy &= ~(1<<(unit+DK_N)); ! 224: dp = &hputab[unit]; ! 225: if((bp=dp->b_actf) == NULL) ! 226: return; ! 227: hpaddr = mbadev(HPMBA, unit); ! 228: if((hpaddr->hpds & VV) == 0) { ! 229: hpaddr->hpcs1 = PRESET|GO; ! 230: hpaddr->hpof = FMT22; ! 231: } ! 232: if(dp->b_active) ! 233: goto done; ! 234: dp->b_active++; ! 235: if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) ! 236: goto done; ! 237: ! 238: bn = dkblock(bp); ! 239: cn = bp->b_cylin; ! 240: switch (hp_type[unit]) { ! 241: ! 242: case RM: ! 243: sn = bn%(NRMSECT*NRMTRAC); ! 244: sn = (sn+NRMSECT-hpSDIST)%NRMSECT; ! 245: break; ! 246: case RM5: ! 247: sn = bn%(NRMSECT*NTRAC); ! 248: sn = (sn+NRMSECT-hpSDIST)%NRMSECT; ! 249: break; ! 250: case RP: ! 251: sn = bn%(NSECT*NTRAC); ! 252: sn = (sn+NSECT-hpSDIST)%NSECT; ! 253: break; ! 254: default: ! 255: panic("hpustart"); ! 256: } ! 257: ! 258: if(cn - (hpaddr->hpdc & 0xffff)) ! 259: goto search; ! 260: else if (hpseek) ! 261: goto done; ! 262: csn = ((hpaddr->hpla & 0xffff)>>6) - sn + 1; ! 263: if(csn < 0) ! 264: csn += NSECT; ! 265: if(csn > NSECT-hpRDIST) ! 266: goto done; ! 267: ! 268: search: ! 269: hpaddr->hpdc = cn; ! 270: if (hpseek) ! 271: hpaddr->hpcs1 = SEEK|GO; ! 272: else { ! 273: hpaddr->hpda = sn; ! 274: hpaddr->hpcs1 = SEARCH|GO; ! 275: } ! 276: unit += DK_N; ! 277: if (unit <= DK_NMAX) { ! 278: dk_busy |= 1<<unit; ! 279: dk_seek[unit]++; ! 280: } ! 281: return; ! 282: ! 283: done: ! 284: dp->b_forw = NULL; ! 285: if(hptab.b_actf == NULL) ! 286: hptab.b_actf = dp; ! 287: else ! 288: hptab.b_actl->b_forw = dp; ! 289: hptab.b_actl = dp; ! 290: } ! 291: ! 292: hpstart() ! 293: { ! 294: register struct buf *bp, *dp; ! 295: register unit; ! 296: register struct device *hpaddr; ! 297: daddr_t bn; ! 298: int dn, sn, tn, cn, nspc, ns; ! 299: ! 300: loop: ! 301: if ((dp = hptab.b_actf) == NULL) ! 302: return; ! 303: if ((bp = dp->b_actf) == NULL) { ! 304: hptab.b_actf = dp->b_forw; ! 305: goto loop; ! 306: } ! 307: hptab.b_active++; ! 308: unit = minor(bp->b_dev) & 077; ! 309: dn = dkunit(bp); ! 310: bn = dkblock(bp); ! 311: switch (hp_type[dn]) { ! 312: case RM: ! 313: nspc = NRMSECT*NRMTRAC; ! 314: ns = NRMSECT; ! 315: cn = rm_sizes[unit&07].cyloff; ! 316: break; ! 317: case RM5: ! 318: nspc = NRMSECT*NTRAC; ! 319: ns = NRMSECT; ! 320: cn = rm5_sizes[unit&07].cyloff; ! 321: break; ! 322: case RP: ! 323: nspc = NSECT*NTRAC; ! 324: ns = NSECT; ! 325: cn = hp_sizes[unit&07].cyloff; ! 326: break; ! 327: default: ! 328: panic("hpstart"); ! 329: } ! 330: cn += bn/nspc; ! 331: sn = bn%nspc; ! 332: tn = sn/ns; ! 333: sn = sn%ns; ! 334: ! 335: hpaddr = mbadev(HPMBA, dn); ! 336: if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) { ! 337: hptab.b_active = 0; ! 338: hptab.b_errcnt = 0; ! 339: dp->b_actf = bp->av_forw; ! 340: bp->b_flags |= B_ERROR; ! 341: iodone(bp); ! 342: goto loop; ! 343: } ! 344: if(hptab.b_errcnt >= 16 && (bp->b_flags&B_WRITE) == 0) { ! 345: hpaddr->hpof = hp_offset[hptab.b_errcnt & 017] | FMT22; ! 346: HPMBA->mba_cr &= ~MBAIE; ! 347: hpaddr->hpcs1 = OFFSET|GO; ! 348: while(hpaddr->hpds & PIP) ! 349: ; ! 350: HPMBA->mba_cr |= MBAIE; ! 351: } ! 352: hpaddr->hpdc = cn; ! 353: hpaddr->hpda = (tn << 8) + sn; ! 354: mbastart(bp, (int *)hpaddr); ! 355: ! 356: unit = dn+DK_N; ! 357: if (unit <= DK_NMAX) { ! 358: dk_busy |= 1<<unit; ! 359: dk_xfer[unit]++; ! 360: dk_wds[unit] += bp->b_bcount>>6; ! 361: } ! 362: } ! 363: ! 364: hpintr(mbastat, as) ! 365: { ! 366: register struct buf *bp, *dp; ! 367: register unit; ! 368: register struct device *hpaddr; ! 369: ! 370: if(hptab.b_active) { ! 371: dp = hptab.b_actf; ! 372: bp = dp->b_actf; ! 373: unit = dkunit(bp); ! 374: if (DK_N+unit <= DK_NMAX) ! 375: dk_busy &= ~(1<<(DK_N+unit)); ! 376: hpaddr = mbadev(HPMBA, unit); ! 377: if (hpaddr->hpds & ERR || mbastat & MBAEBITS) { ! 378: while((hpaddr->hpds & DRY) == 0) ! 379: ; ! 380: if(++hptab.b_errcnt > 28 || hpaddr->hper1&WLE) ! 381: bp->b_flags |= B_ERROR; ! 382: else ! 383: hptab.b_active = 0; ! 384: if(hptab.b_errcnt > 27) ! 385: deverror(bp, mbastat, hpaddr->hper1); ! 386: if ((hpaddr->hper1&0xffff) == DCK) { ! 387: if (hpecc(hpaddr, bp)) ! 388: return; ! 389: } ! 390: hpaddr->hpcs1 = DCLR|GO; ! 391: if((hptab.b_errcnt&07) == 4) { ! 392: HPMBA->mba_cr &= ~MBAIE; ! 393: hpaddr->hpcs1 = RECAL|GO; ! 394: while(hpaddr->hpds & PIP) ! 395: ; ! 396: HPMBA->mba_cr |= MBAIE; ! 397: } ! 398: } ! 399: if(hptab.b_active) { ! 400: if(hptab.b_errcnt) { ! 401: HPMBA->mba_cr &= ~MBAIE; ! 402: hpaddr->hpcs1 = RTC|GO; ! 403: while(hpaddr->hpds & PIP) ! 404: ; ! 405: HPMBA->mba_cr |= MBAIE; ! 406: } ! 407: hptab.b_active = 0; ! 408: hptab.b_errcnt = 0; ! 409: hptab.b_actf = dp->b_forw; ! 410: dp->b_active = 0; ! 411: dp->b_errcnt = 0; ! 412: dp->b_actf = bp->av_forw; ! 413: bp->b_resid = -HPMBA->mba_bcr & 0xffff; ! 414: iodone(bp); ! 415: if(dp->b_actf) ! 416: hpustart(unit); ! 417: } ! 418: as &= ~(1<<unit); ! 419: } else { ! 420: if(as == 0) ! 421: HPMBA->mba_cr |= MBAIE; ! 422: } ! 423: for(unit=0; unit<NHP; unit++) ! 424: if(as & (1<<unit)) ! 425: hpustart(unit); ! 426: hpstart(); ! 427: } ! 428: ! 429: hpread(dev) ! 430: { ! 431: ! 432: physio(hpstrategy, &rhpbuf, dev, B_READ, minphys); ! 433: } ! 434: ! 435: hpwrite(dev) ! 436: { ! 437: ! 438: physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys); ! 439: } ! 440: ! 441: hpecc(rp, bp) ! 442: register struct device *rp; ! 443: register struct buf *bp; ! 444: { ! 445: struct mba_regs *mbp = HPMBA; ! 446: register int i; ! 447: caddr_t addr; ! 448: int reg, bit, byte, npf, mask, o; ! 449: int dn, bn, cn, tn, sn, ns, nt; ! 450: extern char buffers[NBUF][BSIZE]; ! 451: struct pte mpte; ! 452: int bcr; ! 453: ! 454: /* ! 455: * Npf is the number of sectors transferred before the sector ! 456: * containing the ECC error, and reg is the MBA register ! 457: * mapping (the first part of)the transfer. ! 458: * O is offset within a memory page of the first byte transferred. ! 459: */ ! 460: bcr = mbp->mba_bcr & 0xffff; ! 461: if (bcr) ! 462: bcr |= 0xffff0000; /* sxt */ ! 463: npf = btop(bcr + bp->b_bcount) - 1; ! 464: reg = npf; ! 465: o = (int)bp->b_un.b_addr & PGOFSET; ! 466: printf("%D ", bp->b_blkno + npf); ! 467: prdev("ECC", bp->b_dev); ! 468: mask = rp->hpec2&0xffff; ! 469: if (mask == 0) { ! 470: rp->hpof = FMT22; ! 471: return (0); ! 472: } ! 473: ! 474: /* ! 475: * Compute the byte and bit position of the error. ! 476: * The variable i is the byte offset in the transfer, ! 477: * the variable byte is the offset from a page boundary ! 478: * in main memory. ! 479: */ ! 480: i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */ ! 481: bit = i&07; ! 482: i = (i&~07)>>3; ! 483: byte = i + o; ! 484: /* ! 485: * Correct while possible bits remain of mask. Since mask ! 486: * contains 11 bits, we continue while the bit offset is > -11. ! 487: * Also watch out for end of this block and the end of the whole ! 488: * transfer. ! 489: */ ! 490: while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { ! 491: mpte = mbp->mba_map[reg+btop(byte)]; ! 492: addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); ! 493: putmemc(addr, getmemc(addr)^(mask<<bit)); ! 494: byte++; ! 495: i++; ! 496: bit -= 8; ! 497: } ! 498: hptab.b_active++; /* Either complete or continuing */ ! 499: if (bcr == 0) ! 500: return (0); ! 501: /* ! 502: * Have to continue the transfer... clear the drive, ! 503: * and compute the position where the transfer is to continue. ! 504: * We have completed npf+1 sectores of the transfer already; ! 505: * restart at offset o of next sector (i.e. in MBA register reg+1). ! 506: */ ! 507: rp->hpcs1 = DCLR|GO; ! 508: dn = dkunit(bp); ! 509: bn = dkblock(bp); ! 510: switch (hp_type[dn]) { ! 511: ! 512: case RM: ! 513: ns = NRMSECT; nt = NRMTRAC; break; ! 514: case RM5: ! 515: ns = NRMSECT; nt = NTRAC; break; ! 516: case RP: ! 517: ns = NSECT; nt = NTRAC; break; ! 518: default: ! 519: panic("hpecc"); ! 520: } ! 521: cn = bp->b_cylin; ! 522: sn = bn%(ns*nt) + npf + 1; ! 523: tn = sn/ns; ! 524: sn %= ns; ! 525: cn += tn/nt; ! 526: tn %= nt; ! 527: rp->hpdc = cn; ! 528: rp->hpda = (tn<<8) + sn; ! 529: mbp->mba_sr = -1; ! 530: mbp->mba_var = (int)ptob(reg+1) + o; ! 531: rp->hpcs1 = RCOM|GO; ! 532: return (1); ! 533: } ! 534: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.