1: /* 2: * TJU77/TWU77/TJE16/TWE16 tape driver 3: */ 4: 5: /* 6: * SCCS id @(#)ht.c 2.1 (Berkeley) 8/5/83 7: */ 8: 9: #include "ht.h" 10: #if NHT > 0 11: #include "param.h" 12: #include <sys/systm.h> 13: #include <sys/buf.h> 14: #include <sys/conf.h> 15: #include <sys/dir.h> 16: #include <sys/file.h> 17: #include <sys/user.h> 18: #include <sys/htreg.h> 19: #ifdef HT_IOCTL 20: #include <sys/mtio.h> 21: #endif 22: 23: struct buf httab; 24: struct buf rhtbuf; 25: struct buf chtbuf; 26: 27: struct htdevice *HTADDR; 28: 29: #define INF 32760 30: 31: struct softc { 32: char sc_openf; 33: char sc_lastiow; 34: daddr_t sc_blkno; 35: daddr_t sc_nxrec; 36: u_short sc_erreg; 37: u_short sc_fsreg; 38: #ifdef HT_IOCTL 39: short sc_resid; 40: #endif 41: } tu_softc[NHT]; 42: 43: 44: #define SIO 1 45: #define SSFOR 2 46: #define SSREV 3 47: #define SRETRY 4 48: #define SCOM 5 49: #define SOK 6 50: 51: #define TUUNIT(dev) (minor(dev) & 077) 52: 53: /* bits in minor device */ 54: #define H_800BPI 0100 55: #define H_NOREWIND 0200 56: 57: htattach(addr, unit) 58: register struct htdevice *addr; 59: { 60: /* 61: * This driver supports only one controller. 62: */ 63: if (unit != 0) 64: return(0); 65: if ((addr != (struct htdevice *) NULL) && (fioword(addr) != -1)) { 66: HTADDR = addr; 67: #if PDP11 == 70 || PDP11 == GENERIC 68: if (fioword(&(addr->htbae)) != -1) 69: httab.b_flags |= B_RH70; 70: #endif 71: return(1); 72: } 73: HTADDR = (struct hpdevice *) NULL; 74: return(0); 75: } 76: 77: htopen(dev, flag) 78: dev_t dev; 79: { 80: register ds; 81: register htunit = TUUNIT(dev); 82: register struct tu_softc *sc = &tu_softc[htunit]; 83: 84: httab.b_flags |= B_TAPE; 85: htunit = minor(dev) & 077; 86: if (HTADDR == (struct htdevice *) NULL || htunit >= NHT) { 87: u.u_error = ENXIO; 88: return; 89: } 90: else 91: if (sc->sc_openf) { 92: u.u_error = EBUSY; 93: return; 94: } 95: sc->sc_blkno = (daddr_t) 0; 96: sc->sc_nxrec = (daddr_t) INF; 97: sc->sc_lastiow = 0; 98: ds = htcommand(dev, HT_SENSE, 1); 99: if ((ds & HTFS_MOL) == 0) { 100: uprintf("tu%d: not online\n", htunit); 101: u.u_error = EIO; 102: return; 103: } 104: if ((flag & FWRITE) && (ds & HTFS_WRL)) { 105: uprintf("tu%d: no write ring\n", htunit); 106: u.u_error = EIO; 107: return; 108: } 109: if (u.u_error == 0) 110: sc->sc_openf++; 111: } 112: 113: htclose(dev, flag) 114: dev_t dev; 115: { 116: register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 117: 118: if (flag == FWRITE || ((flag & FWRITE) && sc->sc_lastiow)) { 119: htcommand(dev, HT_WEOF, 1); 120: htcommand(dev, HT_WEOF, 1); 121: htcommand(dev, HT_SREV, 1); 122: } 123: if ((minor(dev) & H_NOREWIND) == 0) 124: htcommand(dev, HT_REW, 1); 125: sc->sc_openf = 0; 126: } 127: 128: /*ARGSUSED*/ 129: htcommand(dev, com, count) 130: u_short count; 131: dev_t dev; 132: { 133: register s; 134: register struct buf *bp; 135: 136: bp = &chtbuf; 137: s = spl5(); 138: while(bp->b_flags & B_BUSY) { 139: /* 140: * This special check is because B_BUSY never 141: * gets cleared in the non-waiting rewind case. 142: */ 143: if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE)) 144: break; 145: bp->b_flags |= B_WANTED; 146: sleep((caddr_t) bp, PRIBIO); 147: } 148: bp->b_flags = B_BUSY | B_READ; 149: splx(s); 150: bp->b_dev = dev; 151: #ifdef HT_IOCTL 152: if (com == HT_SFORW || com == HT_SREV) 153: bp->b_repcnt = count; 154: #endif 155: bp->b_command = com; 156: bp->b_blkno = (daddr_t) 0; 157: htstrategy(bp); 158: /* 159: * In case of rewind from close, don't wait. 160: * This is the only case where count can be 0. 161: */ 162: if (count == 0) 163: return; 164: iowait(bp); 165: if(bp->b_flags & B_WANTED) 166: wakeup((caddr_t)bp); 167: bp->b_flags &= B_ERROR; 168: return (bp->b_resid); 169: } 170: 171: htstrategy(bp) 172: register struct buf *bp; 173: { 174: int s; 175: register daddr_t *p; 176: register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; 177: 178: if(bp != &chtbuf) { 179: #ifdef UNIBUS_MAP 180: if ((httab.b_flags & B_RH70) == 0) 181: mapalloc(bp); 182: #endif 183: p = &sc->sc_nxrec; 184: if(dbtofsb(bp->b_blkno) > *p) { 185: bp->b_flags |= B_ERROR; 186: bp->b_error = ENXIO; 187: iodone(bp); 188: return; 189: } 190: if(dbtofsb(bp->b_blkno) == *p && bp->b_flags & B_READ) { 191: bp->b_resid = bp->b_bcount; 192: iodone(bp); 193: return; 194: } 195: if ((bp->b_flags & B_READ) == 0) { 196: *p = dbtofsb(bp->b_blkno) + 1; 197: sc->sc_lastiow = 1; 198: } 199: } 200: bp->av_forw = NULL; 201: s = spl5(); 202: if (httab.b_actf == NULL) 203: httab.b_actf = bp; 204: else 205: httab.b_actl->av_forw = bp; 206: httab.b_actl = bp; 207: if (httab.b_active == 0) 208: htstart(); 209: splx(s); 210: } 211: 212: htstart() 213: { 214: register struct buf *bp; 215: register den; 216: int htunit; 217: daddr_t blkno; 218: register struct softc *sc; 219: 220: loop: 221: if ((bp = httab.b_actf) == NULL) 222: return; 223: htunit = minor(bp->b_dev) & 0177; 224: sc = &tu_softc[TUUNIT(bp->b_dev)]; 225: sc->sc_erreg = HTADDR->hter; 226: sc->sc_fsreg = HTADDR->htfs; 227: #ifdef HT_IOCTL 228: sc->sc_resid = HTADDR->htfc; 229: #endif 230: HTADDR->htcs2 = ((htunit >> 3) & 07); 231: den = HTTC_1600BPI | HTTC_PDP11 | (htunit & 07); 232: if (htunit & H_800BPI) 233: den = HTTC_800BPI | HTTC_PDP11 | (htunit & 07); 234: if ((HTADDR->httc & 03777) != den) 235: HTADDR->httc = den; 236: if (HTADDR->htcs2 & HTCS2_NEF || (HTADDR->htfs & HTFS_MOL) == 0) 237: goto abort; 238: htunit &= 077; 239: blkno = sc->sc_blkno; 240: if (bp == &chtbuf) { 241: if (bp->b_command == HT_SENSE) { 242: bp->b_resid = HTADDR->htfs; 243: goto next; 244: } 245: httab.b_active = SCOM; 246: HTADDR->htfc = 0; 247: HTADDR->htcs1 = bp->b_command | HT_IE | HT_GO; 248: return; 249: } 250: if (sc->sc_openf < 0 || dbtofsb(bp->b_blkno) > sc->sc_nxrec) 251: goto abort; 252: if (blkno == dbtofsb(bp->b_blkno)) { 253: httab.b_active = SIO; 254: HTADDR->htba = bp->b_un.b_addr; 255: #if PDP11 == 70 || PDP11 == GENERIC 256: if(httab.b_flags & B_RH70) 257: HTADDR->htbae = bp->b_xmem; 258: #endif 259: HTADDR->htfc = -bp->b_bcount; 260: HTADDR->htwc = -(bp->b_bcount >> 1); 261: den = ((bp->b_xmem & 3) << 8) | HT_IE | HT_GO; 262: if(bp->b_flags & B_READ) 263: den |= HT_RCOM; 264: else { 265: if(HTADDR->htfs & HTFS_EOT) { 266: bp->b_resid = bp->b_bcount; 267: goto next; 268: } 269: den |= HT_WCOM; 270: } 271: HTADDR->htcs1 = den; 272: } else { 273: if (blkno < dbtofsb(bp->b_blkno)) { 274: httab.b_active = SSFOR; 275: HTADDR->htfc = blkno - dbtofsb(bp->b_blkno); 276: HTADDR->htcs1 = HT_SFORW | HT_IE | HT_GO; 277: } else { 278: httab.b_active = SSREV; 279: HTADDR->htfc = dbtofsb(bp->b_blkno) - blkno; 280: HTADDR->htcs1 = HT_SREV | HT_IE | HT_GO; 281: } 282: } 283: return; 284: 285: abort: 286: bp->b_flags |= B_ERROR; 287: 288: next: 289: httab.b_actf = bp->av_forw; 290: iodone(bp); 291: goto loop; 292: } 293: 294: htintr() 295: { 296: register struct buf *bp; 297: register state; 298: int err, htunit; 299: register struct softc *sc; 300: 301: if ((bp = httab.b_actf) == NULL) 302: return; 303: htunit = TUUNIT(bp->b_dev); 304: state = httab.b_active; 305: httab.b_active = 0; 306: sc = &tu_softc[htunit]; 307: sc->sc_erreg = HTADDR->hter; 308: sc->sc_fsreg = HTADDR->htfs; 309: #ifdef HT_IOCTL 310: sc->sc_resid = HTADDR->htfc; 311: #endif 312: if (HTADDR->htcs1 & HT_TRE) { 313: err = HTADDR->hter; 314: if (HTADDR->htcs2 & HTCS2_ERR || (err & HTER_HARD)) 315: state = 0; 316: if (bp == &rhtbuf) 317: err &= ~HTER_FCE; 318: if ((bp->b_flags & B_READ) && (HTADDR->htfs & HTFS_PES)) 319: err &= ~(HTER_CSITM | HTER_CORCRC); 320: if ((HTADDR->htfs & HTFS_MOL) == 0) { 321: if(sc->sc_openf) 322: sc->sc_openf = -1; 323: } 324: else 325: if (HTADDR->htfs & HTFS_TM) { 326: HTADDR->htwc = -(bp->b_bcount >> 1); 327: sc->sc_nxrec = dbtofsb(bp->b_blkno); 328: state = SOK; 329: } 330: else 331: if (state && err == 0) 332: state = SOK; 333: if (httab.b_errcnt > 4) 334: #ifdef UCB_DEVERR 335: printf("tu%d: hard error bn %D er=%b ds=%b\n", 336: htunit, bp->b_blkno, 337: sc->sc_erreg, HTER_BITS, 338: sc->sc_fsreg, HTFS_BITS); 339: #else 340: deverror(bp, sc->sc_erreg, sc->sc_fsreg); 341: #endif 342: htinit(); 343: if (state == SIO && ++httab.b_errcnt < 10) { 344: httab.b_active = SRETRY; 345: sc->sc_blkno++; 346: HTADDR->htfc = -1; 347: HTADDR->htcs1 = HT_SREV | HT_IE | HT_GO; 348: return; 349: } 350: if (state != SOK) { 351: bp->b_flags |= B_ERROR; 352: state = SIO; 353: } 354: } else 355: if (HTADDR->htcs1 & HT_SC) 356: if(HTADDR->htfs & HTFS_ERR) 357: htinit(); 358: 359: switch (state) { 360: case SIO: 361: case SOK: 362: sc->sc_blkno++; 363: 364: case SCOM: 365: httab.b_errcnt = 0; 366: httab.b_actf = bp->av_forw; 367: iodone(bp); 368: bp->b_resid = -(HTADDR->htwc << 1); 369: break; 370: 371: case SRETRY: 372: if((bp->b_flags & B_READ) == 0) { 373: httab.b_active = SSFOR; 374: HTADDR->htcs1 = HT_ERASE | HT_IE | HT_GO; 375: return; 376: } 377: 378: case SSFOR: 379: case SSREV: 380: if(HTADDR->htfs & HTFS_TM) { 381: if(state == SSREV) { 382: sc->sc_nxrec = dbtofsb(bp->b_blkno) - HTADDR->htfc; 383: sc->sc_blkno = sc->sc_nxrec; 384: } else 385: { 386: sc->sc_nxrec = dbtofsb(bp->b_blkno) + HTADDR->htfc - 1; 387: sc->sc_blkno = sc->sc_nxrec + 1; 388: } 389: } else 390: sc->sc_blkno = dbtofsb(bp->b_blkno); 391: break; 392: 393: default: 394: return; 395: } 396: htstart(); 397: } 398: 399: htinit() 400: { 401: register ocs2; 402: register omttc; 403: 404: omttc = HTADDR->httc & 03777; /* preserve old slave select, dens, format */ 405: ocs2 = HTADDR->htcs2 & 07; /* preserve old unit */ 406: 407: HTADDR->htcs2 = HTCS2_CLR; 408: HTADDR->htcs2 = ocs2; 409: HTADDR->httc = omttc; 410: HTADDR->htcs1 = HT_DCLR | HT_GO; 411: } 412: 413: htread(dev) 414: register dev_t dev; 415: { 416: htphys(dev); 417: bphysio(htstrategy, &rhtbuf, dev, B_READ); 418: } 419: 420: htwrite(dev) 421: register dev_t dev; 422: { 423: htphys(dev); 424: bphysio(htstrategy, &rhtbuf, dev, B_WRITE); 425: } 426: 427: htphys(dev) 428: dev_t dev; 429: { 430: daddr_t a; 431: register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 432: 433: a = dbtofsb(u.u_offset >> 9); 434: sc->sc_blkno = a; 435: sc->sc_nxrec = a + 1; 436: } 437: 438: #ifdef HT_IOCTL 439: 440: /*ARGSUSED*/ 441: htioctl(dev, cmd, addr, flag) 442: dev_t dev; 443: caddr_t addr; 444: { 445: register struct buf *bp = &chtbuf; 446: register struct softc *sc = &tu_softc[minor(dev)&07]; 447: register callcount; 448: int fcount; 449: struct mtop mtop; 450: struct mtget mtget; 451: /* we depend on the values and order of the MT codes here */ 452: static htops[] = {HT_WEOF, HT_SFORW, HT_SREV, HT_SFORW, 453: HT_SREV, HT_REW, HT_REWOFFL, HT_SENSE}; 454: 455: switch (cmd) { 456: 457: case MTIOCTOP: 458: if (copyin(addr, (caddr_t) &mtop, sizeof(mtop))) { 459: u.u_error = EFAULT; 460: return; 461: } 462: switch(mtop.mt_op) { 463: case MTWEOF: 464: callcount = mtop.mt_count; 465: fcount = 1; 466: break; 467: case MTFSF: 468: case MTBSF: 469: callcount = mtop.mt_count; 470: fcount = INF; 471: break; 472: case MTFSR: 473: case MTBSR: 474: callcount = 1; 475: fcount = mtop.mt_count; 476: break; 477: case MTREW: 478: case MTOFFL: 479: case MTNOP: 480: callcount = 1; 481: fcount = 1; 482: break; 483: default: 484: u.u_error = ENXIO; 485: return; 486: } 487: if (callcount <= 0 || fcount <= 0) { 488: u.u_error = ENXIO; 489: return; 490: } 491: while (--callcount >= 0) { 492: htcommand(dev, htops[mtop.mt_op], fcount); 493: if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) 494: && bp->b_resid) { 495: u.u_error = EIO; 496: break; 497: } 498: if ((bp->b_flags & B_ERROR) 499: || sc->sc_fsreg & HTFS_BOT) 500: break; 501: } 502: geterror(bp); 503: return; 504: case MTIOCGET: 505: mtget.mt_erreg = sc->sc_erreg; 506: mtget.mt_dsreg = sc->sc_fsreg; 507: mtget.mt_resid = sc->sc_resid; 508: mtget.mt_type = MT_ISHT; 509: if (copyout((caddr_t) &mtget, addr, sizeof(mtget))) 510: u.u_error = EFAULT; 511: return; 512: default: 513: u.u_error = ENXIO; 514: } 515: } 516: #endif HT_IOCTL 517: #endif NHT