1: # 2: #define DK_N 2 3: /* 4: * DV disk driver 5: * 6: * Adapted for Version 7 UNIX 8/21/79 - Bob Kridle 7: */ 8: 9: #include <sys/param.h> 10: #include <sys/buf.h> 11: #include <sys/conf.h> 12: #include <sys/systm.h> 13: #include <sys/dir.h> 14: #include <sys/user.h> 15: 16: #ifdef UCB_SCCSID 17: static char sccs_id[] = "@(#)dv.c 3.1"; 18: #endif 19: 20: 21: struct { 22: int dvcsr; 23: int dvdbr; 24: int dvmar; 25: int dvwcr; 26: int dvcbr; 27: int dvssr; 28: union 29: { 30: int i; 31: char c[2]; 32: } dvair; 33: int dvusr; 34: }; 35: 36: #define DVADDR ((struct device *) 0164000 ) 37: #define NDV 4 38: 39: struct dv_sizes { 40: daddr_t nblocks; 41: int cyloff; 42: } dv_sizes[] { 43: 10080, 0, /* cyl 0 thru 41 */ 44: 10080, 42, /* cyl 42 thru 83 */ 45: 77280, 84, /* cyl 84 thru 405 */ 46: 97440, 0, /* cyl 0 thru 405 */ 47: 54000, 180, /* cyl 180 thru 405 */ 48: 65520, 0, /* cyl 0 thru 272 */ 49: 31680, 273, /* cyl 273 thru 405 */ 50: 2048, 123, /* cyl 123 thru 132 */ 51: }; 52: 53: struct { 54: int hd1; 55: int hd2; 56: int cksum; 57: unsigned int chadr; 58: } dvhdr; 59: int dv_unit -1, dv_cyl, dv_head, dv_sctr, dv_count; 60: union 61: { 62: long l; 63: int in[2]; 64: } dv_addr; 65: 66: int dv_debug 0; 67: 68: int dv_wcheck, dv_sw 0; 69: 70: 71: int wcwcnt[4]; 72: 73: struct buf dvtab; 74: struct buf rdvbuf; 75: 76: char dvsecmap[] { 77: 0, 4, 8, 78: 1, 5, 9, 79: 2, 6, 10, 80: 3, 7, 11, 81: }; 82: 83: 84: #define HTBCOM 000000 85: #define CTBCOM 020000 86: #define CNBCOM 030000 87: #define INCHD 01 88: #define RECAL 02 89: #define RESET 020 90: #define SEEK 040 91: #define CLRDA 0100 92: #define CHRCOM 070000 93: #define CHWCOM 0130000 94: #define CHCD 071000 95: #define LDSCOM 0140000 96: #define CTLRST 0170000 97: #define CHRDATA 060000 98: #define CHWHEAD 0110000 99: #define WENABL 0100000 100: 101: #define DRVRDY 04000 102: #define ATTN 0400 103: #define DONE 0200 104: #define IENABLE 0100 105: #define GO 01 106: 107: /* 108: * Use av_back to save sector, 109: * b_resid for cylinder+track. 110: */ 111: 112: #define dvsec av_back 113: #define cylhd b_resid 114: 115: dvstrategy(bp) 116: register struct buf *bp; 117: { 118: register unsigned trkno; 119: register struct dv_sizes *sptr; 120: 121: if(bp->b_flags&B_PHYS) 122: mapalloc(bp); 123: sptr = &dv_sizes[minor(bp->b_dev)&07]; 124: if ((minor(bp->b_dev)&077) >= (NDV<<3) || 125: bp->b_blkno >= sptr->nblocks) { 126: bp->b_flags =| B_ERROR; 127: iodone(bp); 128: return; 129: } 130: bp->av_forw = NULL; 131: trkno = bp->b_blkno/12; 132: bp->cylhd = ((sptr->cyloff+trkno/20)<<5)|(trkno%20); 133: bp->dvsec = bp->b_blkno%12; 134: spl5(); 135: disksort(&dvtab,bp); 136: if (dvtab.b_active==0) 137: dvstart(); 138: spl0(); 139: } 140: 141: dvstart() 142: { 143: register struct buf *bp; 144: 145: if ((bp = dvtab.b_actf) == 0) { 146: /* 147: dv_busy = 0; 148: */ 149: return; 150: } 151: dv_cyl = bp->cylhd>>5; 152: dv_head = bp->cylhd&037; 153: dv_sctr = bp->dvsec; 154: dv_count = -bp->b_bcount; 155: dv_addr.in[0] = bp->b_xmem & 03; 156: dv_addr.in[1] = bp->b_un.b_addr; 157: dvexec(); 158: } 159: 160: dvexec() 161: { 162: register struct buf *bp; 163: register sctr, minord; 164: int i, cnt; 165: 166: bp = dvtab.b_actf; 167: sctr = dv_sctr; 168: minord = minor(bp->b_dev); 169: if (minord&64) 170: sctr = dvsecmap[sctr]; 171: dvtab.b_active++; 172: if (dv_unit!=((minord&077)>>3)) { /* select unit */ 173: dv_unit = (minord&077)>>3; 174: cnt = 0; 175: for (i = 0; i < 2; i++) 176: while((DVADDR->dvssr&DRVRDY) && --cnt) ; 177: DVADDR->dvcbr = LDSCOM | dv_unit; 178: } 179: if(dvrdy()) return; 180: DVADDR->dvcbr = CNBCOM | RESET | CLRDA; /* reset and clear */ 181: if (dv_cyl != (~(DVADDR->dvssr|0177000))) { /* seek */ 182: if(dvrdy()) return; 183: DVADDR->dvcbr = CTBCOM | dv_cyl; 184: if(dvrdy()) return; 185: DVADDR->dvcbr = CNBCOM | SEEK | RESET; 186: DVADDR->dvair.i = 1<<dv_unit; 187: DVADDR->dvcsr = DONE | IENABLE; 188: 189: /***** I/O monitoring stuff *****/ 190: /* Removed for V7 upgrade 191: * if((minord == 64) && (bp->b_blkno >= swplo1)) dv_busy = 18; 192: * else dv_busy = (((minord & 030) >> 2) | (minord & 01)) + 10; 193: * dk_busy =| 1<<DK_N; 194: * dv_numb[dv_busy] =+ 1; 195: */ 196: /************************/ 197: 198: return; 199: } 200: if(dvrdy()) return; 201: DVADDR->dvcbr = HTBCOM | dv_head; /* select head */ 202: if(dv_count <= -512) 203: DVADDR->dvwcr = -512; else 204: DVADDR->dvwcr = dv_count; 205: dvhdr.hd1 = (dv_head<<8)+dv_cyl; /* set up header */ 206: dvhdr.hd2 = 0170000|sctr; 207: dvhdr.cksum = -dvhdr.hd1-dvhdr.hd2; 208: dvhdr.chadr = dv_addr.in[1]; 209: if(dvrdy()) return; 210: DVADDR->dvmar = &dvhdr; 211: if(dv_debug) 212: printf("ST,h1=%o,h2=%o,h4=%o,mar=%o,wc=%o,x=%o,\n", 213: dvhdr.hd1, 214: dvhdr.hd2, 215: dvhdr.chadr, 216: DVADDR->dvmar, 217: DVADDR->dvwcr, 218: dv_addr.in[0] 219: ); 220: if (minord & 128) { 221: if (bp->b_flags & B_READ) { 222: dv_addr.in[0] = 0; 223: DVADDR->dvmar = dv_addr.in[1]; 224: DVADDR->dvcbr = CHRDATA | (sctr<<1); 225: } else { 226: DVADDR->dvcbr = CHWHEAD | (sctr<<1); 227: DVADDR->dvair.i =| WENABL; 228: } 229: } else { 230: if (bp->b_flags & B_READ) 231: DVADDR->dvcbr = CHRCOM | (sctr<<1); 232: else 233: if (dv_wcheck) 234: DVADDR->dvcbr = CHCD | (sctr<<1); 235: else 236: DVADDR->dvcbr = CHWCOM | (sctr<<1); 237: } 238: DVADDR->dvcsr = IENABLE | GO | (dv_addr.in[0]<<4); 239: 240: /***** I/O monitoring stuff *****/ 241: /* Removed for v7 Upgrade 242: * dk_busy =| 1<<DK_N; 243: * dk_numb[DK_N] =+ 1; 244: * dk_wds[DK_N] =+ 8; 245: * if((minord == 64) && (bp->b_blkno >= swplo1)) dv_busy = 9; 246: * else dv_busy = (((minord & 030) >> 2) | (minord & 01)) + 1; 247: * if (dv_count >= -512) 248: * dv_numb[dv_busy] =+ 1; 249: * if(bp->b_flags & B_READ) dv_rwds[dv_busy] =+ 8; 250: * else dv_wwds[dv_busy] =+ 8; 251: */ 252: /*****************************/ 253: 254: } 255: 256: int dv_tmp; 257: int dv_errct; 258: dvintr() 259: { 260: register struct buf *bp; 261: register int csr,i; 262: 263: if (dvtab.b_active == 0) 264: return; 265: if(dv_debug) 266: printf("IN,mar=%o,wc=%o,cbr=%o,\n", 267: DVADDR->dvmar, 268: DVADDR->dvwcr, 269: DVADDR->dvcbr 270: ); 271: 272: /***** I/O monitoring stuff *****/ 273: /* Removed for v7 Upgrade 274: * dk_busy =& ~(1<<DK_N); 275: * dv_busy = 19; 276: */ 277: /*********************************/ 278: 279: bp = dvtab.b_actf; 280: dvtab.b_active = 0; 281: csr = DVADDR->dvcsr; 282: DVADDR->dvcsr = DONE; 283: if (csr&ATTN) { /* seek complete */ 284: dv_wcheck = 0; 285: DVADDR->dvair.c[0] = 0; 286: if(DVADDR->dvssr>0) { /* error */ 287: printf("Seek error\n"); 288: deverror(bp, DVADDR->dvssr, csr); 289: DVADDR->dvcbr = CNBCOM | RECAL | RESET; 290: dv_unit = -1; 291: if(dvrdy()) return; 292: DVADDR->dvcbr = CTLRST; 293: if (++dvtab.b_errcnt<=10) { 294: dvexec(); 295: return; 296: } 297: dvherr(0); 298: return; 299: } else { 300: dvexec(); 301: return; 302: } 303: } else { /* r/w complete */ 304: if (dv_count <= -512) 305: i = -512; 306: else i = dv_count ; 307: if ((csr < 0 || dv_addr.in[1]-i != DVADDR->dvmar) && 308: (minor(bp->b_dev)&128)==0) { 309: if (dv_addr.in[1]-i != DVADDR->dvmar) { 310: printf("hdr/xfer err "); 311: printf("%o %o %o\n", dv_addr.in[1], DVADDR->dvmar, csr); 312: deverror(bp, DVADDR->dvssr, csr); 313: dv_wcheck = 0; 314: } 315: dv_tmp = csr; 316: dv_errct++; 317: dv_unit = -1; 318: if (dv_wcheck) { 319: printf("diva bad write\n"); 320: wcwcnt[(minor(bp->b_dev)&030) >> 3]++; 321: deverror(bp, DVADDR->dvssr, csr); 322: } 323: dv_wcheck = 0; 324: if((dvtab.b_errcnt&03)==03) { 325: deverror(bp, DVADDR->dvssr, csr); 326: DVADDR->dvcbr = CNBCOM | RECAL | RESET; 327: if(dvrdy()) return; 328: } 329: DVADDR->dvcbr = CTLRST; 330: if(++dvtab.b_errcnt<=12) { 331: dvexec(); 332: return; 333: } 334: dvherr(0); 335: return; 336: } else { 337: if (dv_sw && (bp->b_flags&B_READ)==B_WRITE && 338: dv_wcheck==0 && dv_count==-512) { 339: dv_wcheck = 1; 340: dvexec(); 341: return; 342: } 343: dv_wcheck = 0; 344: if ((dv_count =+ 512)<0) { /* more to do */ 345: dv_addr.l += 512; 346: if (++dv_sctr>=12) { 347: dv_sctr = 0; 348: if (++dv_head>=20) { 349: dv_head = 0; 350: dv_cyl++; 351: } 352: } 353: dvexec(); 354: return; 355: } 356: } 357: } 358: if (csr < 0 && (minor(bp->b_dev)&128)) { 359: DVADDR->dvcbr = CTLRST; 360: dv_unit = -1; 361: dvrdy(); 362: if (DVADDR->dvcsr < 0) { 363: DVADDR->dvcbr = CNBCOM | RECAL | RESET; 364: dvrdy(); 365: } 366: } 367: dv_wcheck = 0; 368: dvtab.b_errcnt = 0; 369: dvtab.b_actf = bp->av_forw; 370: /* This is not right but a kludge for the moment */ 371: bp->b_resid = 0; 372: iodone(bp); 373: dvstart(); 374: } 375: 376: 377: dvrdy() 378: { 379: register int cnt, i; 380: 381: if ((DVADDR->dvssr & DRVRDY) == 0) 382: return(0); 383: cnt = i = 0; 384: /* 385: * waste a bit of time, max .7(approx) sec on a 70 386: */ 387: for (; i < 2; i++) 388: while(--cnt && (DVADDR->dvssr&DRVRDY)); 389: if (DVADDR->dvssr & DRVRDY) { 390: printf("diva not ready\n"); 391: dvherr(1); 392: return(1); 393: } 394: return(0); 395: } 396: 397: dvherr(n) 398: { 399: register struct buf *bp; 400: 401: bp = dvtab.b_actf; 402: printf("Hard error on diva\n"); 403: deverror(bp, DVADDR->dvssr, DVADDR->dvcsr); 404: bp->b_flags =| B_ERROR; 405: dvtab.b_errcnt = 0; 406: dvtab.b_active = 0; 407: dvtab.b_actf = bp->av_forw; 408: iodone(bp); 409: if(n==0) 410: dvstart(); 411: } 412: dvread(dev) 413: { 414: 415: if(dvphys(dev)) 416: physio(dvstrategy, &rdvbuf, dev, B_READ); 417: } 418: 419: dvwrite(dev) 420: { 421: 422: if(dvphys(dev)) 423: physio(dvstrategy, &rdvbuf, dev, B_WRITE); 424: } 425: 426: dvphys(dev) 427: { 428: long c; 429: 430: c = u.u_offset >> 9; 431: c =+ (u.u_count+511) / 512; 432: if(c > dv_sizes[minor(dev) & 07].nblocks) { 433: u.u_error = ENXIO; 434: return(0); 435: } 436: return(1); 437: }