1: /* 2: * Copyright (c) 1982, 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)ht.c 7.1 (Berkeley) 6/5/86 7: */ 8: 9: #include "tu.h" 10: #if NHT > 0 11: /* 12: * TM03/TU?? tape driver 13: * 14: * TODO: 15: * cleanup messages on errors 16: * test ioctl's 17: * see how many rewind interrups we get if we kick when not at BOT 18: * fixup rle error on block tape code 19: */ 20: #include "../machine/pte.h" 21: 22: #include "param.h" 23: #include "systm.h" 24: #include "buf.h" 25: #include "conf.h" 26: #include "dir.h" 27: #include "file.h" 28: #include "user.h" 29: #include "map.h" 30: #include "ioctl.h" 31: #include "mtio.h" 32: #include "cmap.h" 33: #include "uio.h" 34: #include "tty.h" 35: 36: #include "../vax/cpu.h" 37: #include "mbareg.h" 38: #include "mbavar.h" 39: #include "htreg.h" 40: 41: struct buf rhtbuf[NHT]; 42: struct buf chtbuf[NHT]; 43: 44: short httypes[] = 45: { MBDT_TM03, MBDT_TE16, MBDT_TU45, MBDT_TU77, 0 }; 46: struct mba_device *htinfo[NHT]; 47: int htattach(), htslave(), htustart(), htndtint(), htdtint(); 48: struct mba_driver htdriver = 49: { htattach, htslave, htustart, 0, htdtint, htndtint, 50: httypes, "ht", "tu", htinfo }; 51: 52: #define MASKREG(r) ((r) & 0xffff) 53: 54: /* bits in minor device */ 55: #define TUUNIT(dev) (minor(dev)&03) 56: #define H_NOREWIND 04 57: #define H_1600BPI 08 58: 59: #define HTUNIT(dev) (tutoht[TUUNIT(dev)]) 60: 61: #define INF (daddr_t)1000000L /* a block number that wont exist */ 62: 63: struct tu_softc { 64: char sc_openf; 65: char sc_flags; 66: daddr_t sc_blkno; 67: daddr_t sc_nxrec; 68: u_short sc_erreg; 69: u_short sc_dsreg; 70: short sc_resid; 71: short sc_dens; 72: struct mba_device *sc_mi; 73: int sc_slave; 74: struct tty *sc_ttyp; /* record user's tty for errors */ 75: } tu_softc[NTU]; 76: short tutoht[NTU]; 77: 78: /* 79: * Bits for sc_flags. 80: */ 81: #define H_WRITTEN 1 /* last operation was a write */ 82: #define H_ERASED 2 /* last write retry was an erase gap */ 83: #define H_REWIND 4 /* last unit start was a rewind */ 84: 85: char hter_bits[] = HTER_BITS; 86: char htds_bits[] = HTDS_BITS; 87: 88: /*ARGSUSED*/ 89: htattach(mi) 90: struct mba_device *mi; 91: { 92: 93: } 94: 95: htslave(mi, ms, sn) 96: struct mba_device *mi; 97: struct mba_slave *ms; 98: int sn; 99: { 100: register struct tu_softc *sc = &tu_softc[ms->ms_unit]; 101: register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 102: 103: htaddr->httc = sn; 104: if (htaddr->htdt & HTDT_SPR) { 105: sc->sc_mi = mi; 106: sc->sc_slave = sn; 107: tutoht[ms->ms_unit] = mi->mi_unit; 108: return (1); 109: } else 110: return (0); 111: } 112: 113: htopen(dev, flag) 114: dev_t dev; 115: int flag; 116: { 117: register int tuunit; 118: register struct mba_device *mi; 119: register struct tu_softc *sc; 120: int olddens, dens; 121: 122: tuunit = TUUNIT(dev); 123: if (tuunit >= NTU || (mi = htinfo[HTUNIT(dev)]) == 0 || 124: mi->mi_alive == 0) 125: return (ENXIO); 126: if ((sc = &tu_softc[tuunit])->sc_openf) 127: return (EBUSY); 128: olddens = sc->sc_dens; 129: dens = sc->sc_dens = 130: ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)| 131: HTTC_PDP11|sc->sc_slave; 132: htcommand(dev, HT_SENSE, 1); 133: sc->sc_dens = olddens; 134: if ((sc->sc_dsreg & HTDS_MOL) == 0) { 135: uprintf("tu%d: not online\n", tuunit); 136: return (EIO); 137: } 138: if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) { 139: uprintf("tu%d: no write ring\n", tuunit); 140: return (EIO); 141: } 142: if ((sc->sc_dsreg & HTDS_BOT) == 0 && (flag&FWRITE) && 143: dens != sc->sc_dens) { 144: uprintf("tu%d: can't change density in mid-tape\n", tuunit); 145: return (EIO); 146: } 147: sc->sc_openf = 1; 148: sc->sc_blkno = (daddr_t)0; 149: sc->sc_nxrec = INF; 150: sc->sc_flags = 0; 151: sc->sc_dens = dens; 152: sc->sc_ttyp = u.u_ttyp; 153: return (0); 154: } 155: 156: htclose(dev, flag) 157: register dev_t dev; 158: register flag; 159: { 160: register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 161: 162: if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN))) { 163: htcommand(dev, HT_WEOF, 1); 164: htcommand(dev, HT_WEOF, 1); 165: htcommand(dev, HT_SREV, 1); 166: } 167: if ((minor(dev)&H_NOREWIND) == 0) 168: htcommand(dev, HT_REW, 0); 169: sc->sc_openf = 0; 170: } 171: 172: htcommand(dev, com, count) 173: dev_t dev; 174: int com, count; 175: { 176: register struct buf *bp; 177: register int s; 178: 179: bp = &chtbuf[HTUNIT(dev)]; 180: s = spl5(); 181: while (bp->b_flags&B_BUSY) { 182: if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) 183: break; 184: bp->b_flags |= B_WANTED; 185: sleep((caddr_t)bp, PRIBIO); 186: } 187: bp->b_flags = B_BUSY|B_READ; 188: splx(s); 189: bp->b_dev = dev; 190: bp->b_command = com; 191: bp->b_repcnt = count; 192: bp->b_blkno = 0; 193: htstrategy(bp); 194: if (count == 0) 195: return; 196: iowait(bp); 197: if (bp->b_flags&B_WANTED) 198: wakeup((caddr_t)bp); 199: bp->b_flags &= B_ERROR; 200: } 201: 202: htstrategy(bp) 203: register struct buf *bp; 204: { 205: register struct mba_device *mi = htinfo[HTUNIT(bp->b_dev)]; 206: register struct buf *dp; 207: register int s; 208: 209: bp->av_forw = NULL; 210: dp = &mi->mi_tab; 211: s = spl5(); 212: if (dp->b_actf == NULL) 213: dp->b_actf = bp; 214: else 215: dp->b_actl->av_forw = bp; 216: dp->b_actl = bp; 217: if (dp->b_active == 0) 218: mbustart(mi); 219: splx(s); 220: } 221: 222: htustart(mi) 223: register struct mba_device *mi; 224: { 225: register struct htdevice *htaddr = 226: (struct htdevice *)mi->mi_drv; 227: register struct buf *bp = mi->mi_tab.b_actf; 228: register struct tu_softc *sc = &tu_softc[TUUNIT(bp->b_dev)]; 229: daddr_t blkno; 230: 231: htaddr->httc = sc->sc_dens; 232: #ifdef notdef 233: /* unneeded, may hang controller */ 234: if (bp == &chtbuf[HTUNIT(bp->b_dev)] && bp->b_command == HT_SENSE) { 235: htaddr->htcs1 = HT_SENSE|HT_GO; 236: mbclrattn(mi); 237: } 238: #endif 239: sc->sc_dsreg = htaddr->htds; 240: sc->sc_erreg = htaddr->hter; 241: sc->sc_resid = htaddr->htfc; 242: sc->sc_flags &= ~(H_WRITTEN|H_REWIND); 243: if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0) 244: if (sc->sc_openf > 0) 245: sc->sc_openf = -1; 246: if (sc->sc_openf < 0) { 247: bp->b_flags |= B_ERROR; 248: return (MBU_NEXT); 249: } 250: if (bp != &chtbuf[HTUNIT(bp->b_dev)]) { 251: if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { 252: bp->b_flags |= B_ERROR; 253: bp->b_error = ENXIO; 254: return (MBU_NEXT); 255: } 256: if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && 257: bp->b_flags&B_READ) { 258: bp->b_resid = bp->b_bcount; 259: clrbuf(bp); 260: return (MBU_NEXT); 261: } 262: if ((bp->b_flags&B_READ)==0) 263: sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; 264: } else { 265: if (bp->b_command == HT_SENSE) 266: return (MBU_NEXT); 267: if (bp->b_command == HT_REW) 268: sc->sc_flags |= H_REWIND; 269: else 270: htaddr->htfc = -bp->b_bcount; 271: htaddr->htcs1 = bp->b_command|HT_GO; 272: return (MBU_STARTED); 273: } 274: if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { 275: htaddr->htfc = -bp->b_bcount; 276: if ((bp->b_flags&B_READ) == 0) { 277: if (mi->mi_tab.b_errcnt) { 278: if ((sc->sc_flags & H_ERASED) == 0) { 279: sc->sc_flags |= H_ERASED; 280: htaddr->htcs1 = HT_ERASE | HT_GO; 281: return (MBU_STARTED); 282: } 283: sc->sc_flags &= ~H_ERASED; 284: } 285: if (htaddr->htds & HTDS_EOT) { 286: bp->b_resid = bp->b_bcount; 287: bp->b_flags |= B_ERROR; 288: return (MBU_NEXT); 289: } 290: } 291: return (MBU_DODATA); 292: } 293: if (blkno < bdbtofsb(bp->b_blkno)) { 294: htaddr->htfc = blkno - bdbtofsb(bp->b_blkno); 295: htaddr->htcs1 = HT_SFORW|HT_GO; 296: } else { 297: htaddr->htfc = bdbtofsb(bp->b_blkno) - blkno; 298: htaddr->htcs1 = HT_SREV|HT_GO; 299: } 300: return (MBU_STARTED); 301: } 302: 303: htdtint(mi, mbsr) 304: register struct mba_device *mi; 305: int mbsr; 306: { 307: register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 308: register struct buf *bp = mi->mi_tab.b_actf; 309: register struct tu_softc *sc; 310: int ds, er, mbs; 311: 312: sc = &tu_softc[TUUNIT(bp->b_dev)]; 313: ds = sc->sc_dsreg = MASKREG(htaddr->htds); 314: er = sc->sc_erreg = MASKREG(htaddr->hter); 315: sc->sc_resid = MASKREG(htaddr->htfc); 316: mbs = mbsr; 317: sc->sc_blkno++; 318: if((bp->b_flags & B_READ) == 0) 319: sc->sc_flags |= H_WRITTEN; 320: if ((ds&(HTDS_ERR|HTDS_MOL)) != HTDS_MOL || mbs & MBSR_EBITS) { 321: htaddr->htcs1 = HT_DCLR|HT_GO; 322: mbclrattn(mi); 323: if (bp == &rhtbuf[HTUNIT(bp->b_dev)]) { 324: er &= ~HTER_FCE; 325: mbs &= ~(MBSR_DTABT|MBSR_MBEXC); 326: } 327: if (bp->b_flags & B_READ && ds & HTDS_PES) 328: er &= ~(HTER_CSITM|HTER_CORCRC); 329: if (er&HTER_HARD || mbs&MBSR_EBITS || (ds&HTDS_MOL) == 0 || 330: er && ++mi->mi_tab.b_errcnt >= 7) { 331: if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 332: sc->sc_openf = -1; 333: if ((er&HTER_HARD) == HTER_FCE && 334: (mbs&MBSR_EBITS) == (MBSR_DTABT|MBSR_MBEXC) && 335: (ds&HTDS_MOL)) 336: goto noprint; 337: tprintf(sc->sc_ttyp, "tu%d: hard error bn%d mbsr=%b er=%b ds=%b\n", 338: TUUNIT(bp->b_dev), bp->b_blkno, 339: mbsr, mbsr_bits, 340: sc->sc_erreg, hter_bits, 341: sc->sc_dsreg, htds_bits); 342: noprint: 343: bp->b_flags |= B_ERROR; 344: return (MBD_DONE); 345: } 346: if (er) 347: return (MBD_RETRY); 348: } 349: bp->b_resid = 0; 350: if (bp->b_flags & B_READ) 351: if (ds&HTDS_TM) { /* must be a read, right? */ 352: bp->b_resid = bp->b_bcount; 353: sc->sc_nxrec = bdbtofsb(bp->b_blkno); 354: } else if(bp->b_bcount > MASKREG(htaddr->htfc)) 355: bp->b_resid = bp->b_bcount - MASKREG(htaddr->htfc); 356: return (MBD_DONE); 357: } 358: 359: htndtint(mi) 360: register struct mba_device *mi; 361: { 362: register struct htdevice *htaddr = (struct htdevice *)mi->mi_drv; 363: register struct buf *bp = mi->mi_tab.b_actf; 364: register struct tu_softc *sc; 365: int er, ds, fc; 366: 367: ds = MASKREG(htaddr->htds); 368: er = MASKREG(htaddr->hter); 369: fc = MASKREG(htaddr->htfc); 370: if (er) { 371: htaddr->htcs1 = HT_DCLR|HT_GO; 372: mbclrattn(mi); 373: } 374: if (bp == 0) 375: return (MBN_SKIP); 376: sc = &tu_softc[TUUNIT(bp->b_dev)]; 377: sc->sc_dsreg = ds; 378: sc->sc_erreg = er; 379: sc->sc_resid = fc; 380: if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 381: switch ((int)bp->b_command) { 382: case HT_REWOFFL: 383: /* offline is on purpose; don't do anything special */ 384: ds |= HTDS_MOL; 385: break; 386: case HT_SREV: 387: /* if backspace file hit bot, its not an error */ 388: if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT && 389: bp->b_repcnt == INF) 390: er &= ~HTER_NEF; 391: break; 392: } 393: er &= ~HTER_FCE; 394: if (er == 0) 395: ds &= ~HTDS_ERR; 396: } 397: if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) { 398: if ((ds & HTDS_MOL) == 0 && sc->sc_openf > 0) 399: sc->sc_openf = -1; 400: tprintf(sc->sc_ttyp, "tu%d: hard error bn%d er=%b ds=%b\n", 401: TUUNIT(bp->b_dev), bp->b_blkno, 402: sc->sc_erreg, hter_bits, sc->sc_dsreg, htds_bits); 403: bp->b_flags |= B_ERROR; 404: return (MBN_DONE); 405: } 406: if (bp == &chtbuf[HTUNIT(bp->b_dev)]) { 407: if (sc->sc_flags & H_REWIND) 408: return (ds & HTDS_BOT ? MBN_DONE : MBN_RETRY); 409: bp->b_resid = -sc->sc_resid; 410: return (MBN_DONE); 411: } 412: if (ds & HTDS_TM) 413: if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { 414: sc->sc_nxrec = bdbtofsb(bp->b_blkno) - fc; 415: sc->sc_blkno = sc->sc_nxrec; 416: } else { 417: sc->sc_blkno = bdbtofsb(bp->b_blkno) + fc; 418: sc->sc_nxrec = sc->sc_blkno - 1; 419: } 420: else 421: sc->sc_blkno = bdbtofsb(bp->b_blkno); 422: return (MBN_RETRY); 423: } 424: 425: htread(dev, uio) 426: dev_t dev; 427: struct uio *uio; 428: { 429: int errno; 430: 431: errno = htphys(dev, uio); 432: if (errno) 433: return (errno); 434: return (physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_READ, minphys, uio)); 435: } 436: 437: htwrite(dev, uio) 438: dev_t dev; 439: struct uio *uio; 440: { 441: int errno; 442: 443: errno = htphys(dev, uio); 444: if (errno) 445: return (errno); 446: return (physio(htstrategy, &rhtbuf[HTUNIT(dev)], dev, B_WRITE, minphys, uio)); 447: } 448: 449: htphys(dev, uio) 450: dev_t dev; 451: struct uio *uio; 452: { 453: register int htunit; 454: register struct tu_softc *sc; 455: register struct mba_device *mi; 456: daddr_t a; 457: 458: htunit = HTUNIT(dev); 459: if (htunit >= NHT || (mi = htinfo[htunit]) == 0 || mi->mi_alive == 0) 460: return (ENXIO); 461: a = uio->uio_offset >> 9; 462: sc = &tu_softc[TUUNIT(dev)]; 463: sc->sc_blkno = bdbtofsb(a); 464: sc->sc_nxrec = bdbtofsb(a)+1; 465: return (0); 466: } 467: 468: /*ARGSUSED*/ 469: htioctl(dev, cmd, data, flag) 470: dev_t dev; 471: int cmd; 472: caddr_t data; 473: int flag; 474: { 475: register struct tu_softc *sc = &tu_softc[TUUNIT(dev)]; 476: register struct buf *bp = &chtbuf[HTUNIT(dev)]; 477: register callcount; 478: int fcount; 479: struct mtop *mtop; 480: struct mtget *mtget; 481: /* we depend of the values and order of the MT codes here */ 482: static htops[] = 483: {HT_WEOF,HT_SFORW,HT_SREV,HT_SFORW,HT_SREV,HT_REW,HT_REWOFFL,HT_SENSE}; 484: 485: switch (cmd) { 486: 487: case MTIOCTOP: /* tape operation */ 488: mtop = (struct mtop *)data; 489: switch (mtop->mt_op) { 490: 491: case MTWEOF: 492: callcount = mtop->mt_count; 493: fcount = 1; 494: break; 495: 496: case MTFSF: case MTBSF: 497: callcount = mtop->mt_count; 498: fcount = INF; 499: break; 500: 501: case MTFSR: case MTBSR: 502: callcount = 1; 503: fcount = mtop->mt_count; 504: break; 505: 506: case MTREW: case MTOFFL: 507: callcount = 1; 508: fcount = 1; 509: break; 510: 511: default: 512: return (ENXIO); 513: } 514: if (callcount <= 0 || fcount <= 0) 515: return (EINVAL); 516: while (--callcount >= 0) { 517: htcommand(dev, htops[mtop->mt_op], fcount); 518: if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && 519: bp->b_resid) 520: return (EIO); 521: if ((bp->b_flags&B_ERROR) || sc->sc_dsreg&HTDS_BOT) 522: break; 523: } 524: return (geterror(bp)); 525: 526: case MTIOCGET: 527: mtget = (struct mtget *)data; 528: mtget->mt_dsreg = sc->sc_dsreg; 529: mtget->mt_erreg = sc->sc_erreg; 530: mtget->mt_resid = sc->sc_resid; 531: mtget->mt_type = MT_ISHT; 532: break; 533: 534: default: 535: return (ENXIO); 536: } 537: return (0); 538: } 539: 540: #define DBSIZE 20 541: 542: htdump() 543: { 544: register struct mba_device *mi; 545: register struct mba_regs *mp; 546: register struct htdevice *htaddr; 547: int blk, num; 548: int start; 549: 550: start = 0; 551: num = maxfree; 552: #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 553: if (htinfo[0] == 0) 554: return (ENXIO); 555: mi = phys(htinfo[0], struct mba_device *); 556: mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 557: mp->mba_cr = MBCR_IE; 558: htaddr = (struct htdevice *)&mp->mba_drv[mi->mi_drive]; 559: htaddr->httc = HTTC_PDP11|HTTC_1600BPI; 560: htaddr->htcs1 = HT_DCLR|HT_GO; 561: while (num > 0) { 562: blk = num > DBSIZE ? DBSIZE : num; 563: htdwrite(start, blk, htaddr, mp); 564: start += blk; 565: num -= blk; 566: } 567: hteof(htaddr); 568: hteof(htaddr); 569: htwait(htaddr); 570: if (htaddr->htds&HTDS_ERR) 571: return (EIO); 572: htaddr->htcs1 = HT_REW|HT_GO; 573: return (0); 574: } 575: 576: htdwrite(dbuf, num, htaddr, mp) 577: register dbuf, num; 578: register struct htdevice *htaddr; 579: struct mba_regs *mp; 580: { 581: register struct pte *io; 582: register int i; 583: 584: htwait(htaddr); 585: io = mp->mba_map; 586: for (i = 0; i < num; i++) 587: *(int *)io++ = dbuf++ | PG_V; 588: htaddr->htfc = -(num*NBPG); 589: mp->mba_sr = -1; 590: mp->mba_bcr = -(num*NBPG); 591: mp->mba_var = 0; 592: htaddr->htcs1 = HT_WCOM|HT_GO; 593: } 594: 595: htwait(htaddr) 596: struct htdevice *htaddr; 597: { 598: register s; 599: 600: do 601: s = htaddr->htds; 602: while ((s & HTDS_DRY) == 0); 603: } 604: 605: hteof(htaddr) 606: struct htdevice *htaddr; 607: { 608: 609: htwait(htaddr); 610: htaddr->htcs1 = HT_WEOF|HT_GO; 611: } 612: #endif