1: /* 2: * RP04/RP06 disk driver 3: */ 4: 5: #include "../h/param.h" 6: #include "../h/systm.h" 7: #include "../h/buf.h" 8: #include "../h/conf.h" 9: #include "../h/dir.h" 10: #include "../h/user.h" 11: 12: #define DK_N 0 13: 14: struct device 15: { 16: union { 17: int w; 18: char c[2]; 19: } hpcs1; /* Control and Status register 1 */ 20: int hpwc; /* Word count register */ 21: caddr_t hpba; /* UNIBUS address register */ 22: int hpda; /* Desired address register */ 23: union { 24: int w; 25: char c[2]; 26: } hpcs2; /* Control and Status register 2*/ 27: int hpds; /* Drive Status */ 28: int hper1; /* Error register 1 */ 29: int hpas; /* Attention Summary */ 30: int hpla; /* Look ahead */ 31: int hpdb; /* Data buffer */ 32: int hpmr; /* Maintenance register */ 33: int hpdt; /* Drive type */ 34: int hpsn; /* Serial number */ 35: int hpof; /* Offset register */ 36: int hpdc; /* Desired Cylinder address register*/ 37: int hpcc; /* Current Cylinder */ 38: int hper2; /* Error register 2 */ 39: int hper3; /* Error register 3 */ 40: int hpec1; /* Burst error bit position */ 41: int hpec2; /* Burst error bit pattern */ 42: int hpbae; /* 11/70 bus extension */ 43: int hpcs3; 44: }; 45: 46: #define HPADDR ((struct device *)0176700) 47: #define NHP 2 48: #define NSECT 22 49: #define NTRAC 19 50: #define SDIST 2 51: #define RDIST 6 52: 53: struct size 54: { 55: daddr_t nblocks; 56: int cyloff; 57: } hp_sizes[8] = 58: { 59: 9614, 0, /* cyl 0 thru 22 */ 60: 8778, 23, /* cyl 23 thru 43 */ 61: 0, 0, 62: 0, 0, 63: 161348, 44, /* cyl 44 thru 429 */ 64: 160930, 430, /* cyl 430 thru 814 */ 65: 153406, 44, /* cyl 44 thru 410 (rp04, rp05) */ 66: 322278, 44, /* cyl 44 thru 814 (rp06) */ 67: }; 68: 69: #define P400 020 70: #define M400 0220 71: #define P800 040 72: #define M800 0240 73: #define P1200 060 74: #define M1200 0260 75: int hp_offset[16] = 76: { 77: P400, M400, P400, M400, 78: P800, M800, P800, M800, 79: P1200, M1200, P1200, M1200, 80: 0, 0, 0, 0, 81: }; 82: 83: struct buf hptab; 84: struct buf rhpbuf; 85: struct buf hputab[NHP]; 86: 87: #define GO 01 88: #define PRESET 020 89: #define RTC 016 90: #define OFFSET 014 91: #define SEARCH 030 92: #define RECAL 06 93: #define DCLR 010 94: #define WCOM 060 95: #define RCOM 070 96: 97: #define IE 0100 98: #define PIP 020000 99: #define DRY 0200 100: #define ERR 040000 101: #define TRE 040000 102: #define DCK 0100000 103: #define WLE 04000 104: #define ECH 0100 105: #define VV 0100 106: #define DPR 0400 107: #define MOL 010000 108: #define FMT22 010000 109: 110: #define b_cylin b_resid 111: 112: daddr_t dkblock(); 113: 114: hpstrategy(bp) 115: register struct buf *bp; 116: { 117: register struct buf *dp; 118: register unit; 119: long sz, bn; 120: 121: unit = minor(bp->b_dev) & 077; 122: sz = bp->b_bcount; 123: sz = (sz+511) >> 9; 124: if (unit >= (NHP<<3) || 125: bp->b_blkno < 0 || 126: (bn = dkblock(bp))+sz > hp_sizes[unit&07].nblocks) { 127: bp->b_flags |= B_ERROR; 128: iodone(bp); 129: return; 130: } 131: bp->b_cylin = bn/(NSECT*NTRAC) + hp_sizes[unit&07].cyloff; 132: unit = dkunit(bp); 133: dp = &hputab[unit]; 134: spl5(); 135: disksort(dp, bp); 136: if (dp->b_active == 0) { 137: hpustart(unit); 138: if(hptab.b_active == 0) 139: hpstart(); 140: } 141: spl0(); 142: } 143: 144: hpustart(unit) 145: register unit; 146: { 147: register struct buf *bp, *dp; 148: daddr_t bn; 149: int sn, cn, csn; 150: 151: HPADDR->hpcs2.w = unit; 152: HPADDR->hpcs1.c[0] = IE; 153: HPADDR->hpas = 1<<unit; 154: 155: if(unit >= NHP) 156: return; 157: dk_busy &= ~(1<<(unit+DK_N)); 158: dp = &hputab[unit]; 159: if((bp=dp->b_actf) == NULL) 160: return; 161: if((HPADDR->hpds & VV) == 0) { 162: HPADDR->hpcs1.c[0] = IE|PRESET|GO; 163: HPADDR->hpof = FMT22; 164: } 165: if(dp->b_active) 166: goto done; 167: dp->b_active++; 168: if ((HPADDR->hpds & (DPR|MOL)) != (DPR|MOL)) 169: goto done; 170: 171: bn = dkblock(bp); 172: cn = bp->b_cylin; 173: sn = bn%(NSECT*NTRAC); 174: sn = (sn+NSECT-SDIST)%NSECT; 175: 176: if(HPADDR->hpcc != cn) 177: goto search; 178: csn = (HPADDR->hpla>>6) - sn + SDIST - 1; 179: if(csn < 0) 180: csn += NSECT; 181: if(csn > NSECT-RDIST) 182: goto done; 183: 184: search: 185: HPADDR->hpdc = cn; 186: HPADDR->hpda = sn; 187: HPADDR->hpcs1.c[0] = IE|SEARCH|GO; 188: unit += DK_N; 189: dk_busy |= 1<<unit; 190: dk_numb[unit] += 1; 191: return; 192: 193: done: 194: dp->b_forw = NULL; 195: if(hptab.b_actf == NULL) 196: hptab.b_actf = dp; else 197: hptab.b_actl->b_forw = dp; 198: hptab.b_actl = dp; 199: } 200: 201: hpstart() 202: { 203: register struct buf *bp, *dp; 204: register unit; 205: daddr_t bn; 206: int dn, sn, tn, cn; 207: 208: loop: 209: if ((dp = hptab.b_actf) == NULL) 210: return; 211: if ((bp = dp->b_actf) == NULL) { 212: hptab.b_actf = dp->b_forw; 213: goto loop; 214: } 215: hptab.b_active++; 216: unit = minor(bp->b_dev) & 077; 217: dn = dkunit(bp); 218: bn = dkblock(bp); 219: cn = bn/(NSECT*NTRAC) + hp_sizes[unit&07].cyloff; 220: sn = bn%(NSECT*NTRAC); 221: tn = sn/NSECT; 222: sn = sn%NSECT; 223: 224: HPADDR->hpcs2.w = dn; 225: if ((HPADDR->hpds & (DPR|MOL)) != (DPR|MOL)) { 226: hptab.b_active = 0; 227: hptab.b_errcnt = 0; 228: dp->b_actf = bp->av_forw; 229: bp->b_flags |= B_ERROR; 230: iodone(bp); 231: goto loop; 232: } 233: if(hptab.b_errcnt >= 16) { 234: HPADDR->hpof = hp_offset[hptab.b_errcnt & 017] | FMT22; 235: HPADDR->hpcs1.w = OFFSET|GO; 236: while(HPADDR->hpds & PIP) 237: ; 238: } 239: HPADDR->hpdc = cn; 240: HPADDR->hpda = (tn << 8) + sn; 241: HPADDR->hpba = bp->b_un.b_addr; 242: if(cputype == 70) 243: HPADDR->hpbae = bp->b_xmem; 244: HPADDR->hpwc = -(bp->b_bcount>>1); 245: unit = ((bp->b_xmem&3) << 8) | IE | GO; 246: if(bp->b_flags & B_READ) 247: unit |= RCOM; else 248: unit |= WCOM; 249: HPADDR->hpcs1.w = unit; 250: 251: dk_busy |= 1<<(DK_N+NHP); 252: dk_numb[DK_N+NHP] += 1; 253: unit = bp->b_bcount>>6; 254: dk_wds[DK_N+NHP] += unit; 255: } 256: 257: hpintr() 258: { 259: register struct buf *bp, *dp; 260: register unit; 261: int as, i, j; 262: 263: as = HPADDR->hpas & 0377; 264: if(hptab.b_active) { 265: dk_busy &= ~(1<<(DK_N+NHP)); 266: dp = hptab.b_actf; 267: bp = dp->b_actf; 268: unit = dkunit(bp); 269: HPADDR->hpcs2.c[0] = unit; 270: if (HPADDR->hpcs1.w & TRE) { /* error bit */ 271: while((HPADDR->hpds & DRY) == 0) 272: ; 273: if(++hptab.b_errcnt > 28 || HPADDR->hper1&WLE) 274: bp->b_flags |= B_ERROR; else 275: hptab.b_active = 0; 276: if(hptab.b_errcnt > 27) 277: deverror(bp, HPADDR->hpcs2.w, HPADDR->hper1); 278: if((bp->b_flags&B_PHYS) == 0 && 279: (HPADDR->hper1 & (DCK|ECH)) == DCK) { 280: i = HPADDR->hpec1 - 1; 281: j = i&017; 282: i >>= 4; 283: if(i >= 0 && i <256) { 284: bp->b_un.b_words[i] ^= HPADDR->hpec2 << j; 285: bp->b_un.b_words[i+1] ^= HPADDR->hpec2 >> (16-j); 286: } 287: hptab.b_active++; 288: printf("%D ", bp->b_blkno); 289: prdev("ECC", bp->b_dev); 290: } 291: HPADDR->hpcs1.w = TRE|IE|DCLR|GO; 292: if((hptab.b_errcnt&07) == 4) { 293: HPADDR->hpcs1.w = RECAL|IE|GO; 294: while(HPADDR->hpds & PIP) 295: ; 296: } 297: } 298: if(hptab.b_active) { 299: if(hptab.b_errcnt) { 300: HPADDR->hpcs1.w = RTC|GO; 301: while(HPADDR->hpds & PIP) 302: ; 303: } 304: hptab.b_active = 0; 305: hptab.b_errcnt = 0; 306: hptab.b_actf = dp->b_forw; 307: dp->b_active = 0; 308: dp->b_errcnt = 0; 309: dp->b_actf = bp->av_forw; 310: bp->b_resid = -(HPADDR->hpwc<<1); 311: iodone(bp); 312: HPADDR->hpcs1.w = IE; 313: if(dp->b_actf) 314: hpustart(unit); 315: } 316: as &= ~(1<<unit); 317: } else { 318: if(as == 0) 319: HPADDR->hpcs1.w = IE; 320: HPADDR->hpcs1.c[1] = TRE>>8; 321: } 322: for(unit=0; unit<NHP; unit++) 323: if(as & (1<<unit)) 324: hpustart(unit); 325: hpstart(); 326: } 327: 328: hpread(dev) 329: { 330: 331: physio(hpstrategy, &rhpbuf, dev, B_READ); 332: } 333: 334: hpwrite(dev) 335: { 336: 337: physio(hpstrategy, &rhpbuf, dev, B_WRITE); 338: }