1: /* 2: * SCCS id @(#)ts.c 2.1 (Berkeley) 8/5/83 3: */ 4: 5: /* 6: * TS11 tape driver 7: */ 8: 9: #include "ts.h" 10: #if NTS > 0 11: #include "param.h" 12: #include <sys/buf.h> 13: #include <sys/dir.h> 14: #include <sys/conf.h> 15: #include <sys/file.h> 16: #include <sys/user.h> 17: #include <sys/tsreg.h> 18: #ifdef TS_IOCTL 19: #include <sys/mtio.h> 20: #endif 21: 22: /* 23: * Software state per tape transport: 24: * 25: * 1. A tape drive is a unique-open device: we refuse opens when it is already. 26: * 2. We keep track of the current position on a block tape and seek 27: * before operations by forward/back spacing if necessary. 28: * 3. We remember if the last operation was a write on a tape, so if a tape 29: * is open read write and the last thing done is a write we can 30: * write a standard end of tape mark (two eofs). 31: * 4. We remember the status registers after the last command, using 32: * them internally and returning them to the SENSE ioctl. 33: */ 34: struct ts_softc { 35: char sc_openf; 36: char sc_lastiow; 37: short sc_resid; 38: daddr_t sc_blkno; 39: daddr_t sc_nxrec; 40: struct ts_cmd sc_cmd; 41: struct ts_sts sc_sts; 42: struct ts_char sc_char; 43: } ts_softc[NTS]; 44: 45: struct buf tstab; 46: struct buf ctsbuf; 47: /* 48: * Raw tape operations use rtsbuf. The driver 49: * notices when rtsbuf is being used and allows the user 50: * program to continue after errors and read records 51: * not of the standard length (BSIZE). 52: */ 53: struct buf rtsbuf; 54: 55: struct tsdevice *TSADDR; 56: 57: #define INF ((daddr_t) ((u_short) 65535)) 58: #define T_NOREWIND 0200 59: #define TSUNIT(dev) (minor(dev) & 03) 60: #define tswait(r) while (((TSADDR->(r)) & TS_SSR) == 0) 61: 62: /* command code definitions */ 63: 64: /* 65: * States for tstab.b_active, the state flag. 66: * This is used to sequence control in the driver. 67: */ 68: #define SSEEK 1 /* seeking */ 69: #define SIO 2 /* doing seq. i/o */ 70: #define SCOM 3 /* sending a control command */ 71: #define SREW 4 /* sending a drive rewind */ 72: 73: tsattach(addr, unit) 74: struct tsdevice *addr; 75: { 76: /* 77: * This driver supports only one controller. 78: */ 79: if (unit == 0) { 80: TSADDR = addr; 81: return(1); 82: } 83: return(0); 84: } 85: 86: /* 87: * Open the device. Tapes are unique open 88: * devices so we refuse if it is already open. 89: * We also check that a tape is available and 90: * don't block waiting here: if you want to wait 91: * for a tape you should timeout in user code. 92: */ 93: tsopen(dev, flag) 94: dev_t dev; 95: { 96: register tsunit; 97: register struct ts_softc *sc; 98: 99: tsunit = TSUNIT(dev); 100: if (TSADDR == (struct tsdevice *) NULL || tsunit >= NTS 101: || (sc = &ts_softc[tsunit])->sc_openf) { 102: u.u_error = ENXIO; 103: return; 104: } 105: if(tsinit(tsunit)) { 106: u.u_error = ENXIO; 107: return; 108: } 109: tstab.b_flags |= B_TAPE; 110: tscommand(dev, TS_SENSE, 1); 111: if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) { 112: uprintf("ts%d: not online\n", tsunit); 113: u.u_error = EIO; 114: return; 115: } 116: if ((flag & (FREAD | FWRITE)) == FWRITE 117: && (sc->sc_sts.s_xs0 & TS_WLK)) { 118: uprintf("ts%d: no write ring\n", tsunit); 119: u.u_error = EIO; 120: return; 121: } 122: sc->sc_openf = 1; 123: sc->sc_blkno = (daddr_t) 0; 124: sc->sc_nxrec = INF; 125: sc->sc_lastiow = 0; 126: } 127: 128: /* 129: * Close tape device. 130: * 131: * If tape was open for writing or last operation was 132: * a write, then write two EOF's and backspace over the last one. 133: * Unless his is a non-rewinding special file, rewind the tape. 134: * Make the tape available to others. 135: */ 136: tsclose(dev, flag) 137: register dev_t dev; 138: { 139: register struct ts_softc *sc = &ts_softc[TSUNIT(dev)]; 140: 141: if(flag == FWRITE || ((flag & FWRITE) && sc->sc_lastiow)) { 142: tscommand(dev, TS_WEOF, 1); 143: tscommand(dev, TS_WEOF, 1); 144: tscommand(dev, TS_SREV, 1); 145: } 146: if ((minor(dev) & T_NOREWIND) == 0 ) 147: /* 148: * 0 count means don't hang waiting for rewind complete. 149: * Rather ctsbuf stays busy until the operation completes 150: * preventing further opens from completing by 151: * preventing a TS_SENSE from completing. 152: */ 153: tscommand(dev, TS_REV, 0); 154: sc->sc_openf = 0; 155: } 156: 157: /* 158: * Execute a command on the tape drive 159: * a specified number of times. 160: */ 161: tscommand(dev, com, count) 162: dev_t dev; 163: register u_short count; 164: { 165: register s; 166: register struct buf *bp; 167: 168: bp = &ctsbuf; 169: s = spl5(); 170: while(bp->b_flags & B_BUSY) { 171: /* 172: * This special check is because B_BUSY never 173: * gets cleared in the non-waiting rewind case. 174: */ 175: if (bp->b_repcnt == 0 && (bp->b_flags & B_DONE)) 176: break; 177: bp->b_flags |= B_WANTED; 178: sleep((caddr_t) bp, PRIBIO); 179: } 180: bp->b_flags = B_BUSY | B_READ; 181: splx(s); 182: bp->b_dev = dev; 183: bp->b_repcnt = -count; 184: bp->b_command = com; 185: bp->b_blkno = (daddr_t) 0; 186: tsstrategy(bp); 187: /* 188: * In case of rewind from close, don't wait. 189: * This is the only case where count can be 0. 190: */ 191: if (count == 0) 192: return; 193: iowait(bp); 194: if(bp->b_flags & B_WANTED) 195: wakeup((caddr_t) bp); 196: bp->b_flags &= B_ERROR; 197: } 198: 199: /* 200: * Queue a tape operation. 201: */ 202: tsstrategy(bp) 203: register struct buf *bp; 204: { 205: register s; 206: 207: #ifdef UNIBUS_MAP 208: if (bp != &ctsbuf) 209: mapalloc(bp); 210: #endif 211: bp->av_forw = NULL; 212: s = spl5(); 213: if (tstab.b_actf == NULL) 214: tstab.b_actf = bp; 215: else 216: tstab.b_actl->av_forw = bp; 217: tstab.b_actl = bp; 218: /* 219: * If the controller is not busy, get 220: * it going. 221: */ 222: if (tstab.b_active == 0) 223: tsstart(); 224: splx(s); 225: } 226: 227: /* 228: * Start activity on a ts controller. 229: */ 230: tsstart() 231: { 232: daddr_t blkno; 233: int cmd, s, tsunit; 234: register struct ts_softc *sc; 235: register struct ts_cmd *tc; 236: register struct buf *bp; 237: 238: /* 239: * Start the controller if there is something for it to do. 240: */ 241: loop: 242: if ((bp = tstab.b_actf) == NULL) 243: return; 244: tsunit = TSUNIT(bp->b_dev); 245: sc = &ts_softc[tsunit]; 246: tc = &sc->sc_cmd; 247: /* 248: * Default is that last command was NOT a write command; 249: * if we do a write command we will notice this in tsintr(). 250: */ 251: sc->sc_lastiow = 0; 252: if (sc->sc_openf < 0 || (TSADDR->tssr & TS_OFL)) { 253: /* 254: * Have had a hard error on a non-raw tape 255: * or the tape unit is now unavailable 256: * (e.g. taken off line). 257: */ 258: bp->b_flags |= B_ERROR; 259: goto next; 260: } 261: if (bp == &ctsbuf) { 262: /* 263: * Execute control operation with the specified count. 264: */ 265: tstab.b_active = bp->b_command == TS_REW ? SREW : SCOM; 266: tc->c_repcnt = bp->b_repcnt; 267: goto dobpcmd; 268: } 269: /* 270: * The following checks handle boundary cases for operation 271: * on non-raw tapes. On raw tapes the initialization of 272: * sc->sc_nxrec by tsphys causes them to be skipped normally 273: * (except in the case of retries). 274: */ 275: if(dbtofsb(bp->b_blkno) > sc->sc_nxrec) { 276: /* 277: * Can't read past known end-of-file. 278: */ 279: bp->b_flags |= B_ERROR; 280: bp->b_error = ENXIO; 281: goto next; 282: } 283: if(dbtofsb(bp->b_blkno) == sc->sc_nxrec && bp->b_flags & B_READ) { 284: /* 285: * Reading at end of file returns 0 bytes. 286: * Buffer will be cleared (if written) in writei. 287: */ 288: bp->b_resid = bp->b_bcount; 289: goto next; 290: } 291: if((bp->b_flags & B_READ) == 0) 292: sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1; 293: /* 294: * If the data transfer command is in the correct place, 295: * set up all registers and do the transfer. 296: */ 297: if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { 298: tc->c_size = bp->b_bcount; 299: if ((bp->b_flags & B_READ) == 0) 300: cmd = TS_WCOM; 301: else 302: cmd = TS_RCOM; 303: if (tstab.b_errcnt) 304: cmd |= TS_RETRY; 305: tstab.b_active = SIO; 306: tc->c_cmd = TS_ACK | TS_CVC | TS_IE | cmd; 307: TSADDR->tsdb = &sc->sc_cmd.c_cmd; 308: return; 309: } 310: /* 311: * Tape positioned incorrectly; 312: * set to seek forward or backward to the correct spot. 313: * This happens for raw tapes only on error retries. 314: */ 315: tstab.b_active = SSEEK; 316: if(blkno < dbtofsb(bp->b_blkno)) { 317: bp->b_command = TS_SFORW; 318: bp->b_repcnt = dbtofsb(bp->b_blkno) - blkno; 319: } else 320: { 321: bp->b_command = TS_SREV; 322: bp->b_repcnt = blkno - dbtofsb(bp->b_blkno); 323: } 324: 325: dobpcmd: 326: /* 327: * Do the command in bp. 328: */ 329: tc->c_cmd = TS_ACK | TS_CVC | TS_IE | bp->b_command; 330: TSADDR->tsdb = &sc->sc_cmd.c_cmd; 331: return; 332: 333: next: 334: tstab.b_errcnt = 0; 335: tstab.b_actf = bp->av_forw; 336: iodone(bp); 337: goto loop; 338: } 339: 340: /* 341: * TS interrupt routine 342: */ 343: tsintr() 344: { 345: register state; 346: register struct buf *bp; 347: register struct ts_softc *sc; 348: int tsunit, err; 349: 350: if((bp = tstab.b_actf) == NULL) 351: return; 352: tsunit = TSUNIT (bp->b_dev); 353: 354: /* 355: * If last command was a rewind, and tape is still 356: * rewinding, wait for the rewind complete interrupt. 357: * 358: * SHOULD NEVER GET AN INTERRUPT IN THIS STATE. 359: */ 360: if (tstab.b_active == SREW) { 361: tstab.b_active = SCOM; 362: if ((TSADDR->tssr & TS_SSR) == 0) 363: return; 364: } 365: 366: /* 367: * An operation completed... record status 368: */ 369: sc = &ts_softc[tsunit]; 370: if ((bp->b_flags & B_READ) == 0) 371: sc->sc_lastiow = 1; 372: state = tstab.b_active; 373: tstab.b_active = 0; 374: 375: /* 376: * Check for errors. 377: */ 378: if(TSADDR->tssr & TS_SC) { 379: switch (TSADDR->tssr & TS_TC) { 380: case TS_UNREC: /* unrecoverable */ 381: case TS_FATAL: /* fatal error */ 382: case TS_ATTN: /* attention (shouldn't happen) */ 383: case TS_RECNM: /* recoverable, no motion */ 384: break; 385: 386: case TS_SUCC: /* successful termination */ 387: goto ignoreerr; 388: /*NOTREACHED*/ 389: 390: case TS_ALERT: /* tape status alert */ 391: /* 392: * If we hit the end of the tape file, 393: * update our position. 394: */ 395: if (sc->sc_sts.s_xs0 & (TS_TMK | TS_EOT)) { 396: tsseteof(bp); /* set blkno and nxrec */ 397: state = SCOM; /* force completion */ 398: /* 399: * Stuff bc so it will be unstuffed 400: * correctly later to get resid. 401: */ 402: sc->sc_sts.s_rbpcr = bp->b_bcount; 403: goto opdone; 404: /*NOTREACHED*/ 405: } 406: /* 407: * If we were reading raw tape and the record 408: * was too long or too short, then we don't 409: * consider this an error. 410: */ 411: if (bp == &rtsbuf && (bp->b_flags & B_READ) 412: && sc->sc_sts.s_xs0 & (TS_RLS | TS_RLL)) 413: goto ignoreerr; 414: /*NOTREACHED*/ 415: 416: case TS_RECOV: /* recoverable, tape moved */ 417: /* 418: * If this was an i/o operation, 419: * retry up to 8 times. 420: */ 421: if (state == SIO) { 422: if (++tstab.b_errcnt < 7) 423: goto opcont; 424: else 425: sc->sc_blkno++; 426: } else 427: { 428: /* 429: * Non-i/o errors on non-raw tape 430: * cause it to close. 431: */ 432: if (sc->sc_openf > 0 && bp != &rtsbuf) 433: sc->sc_openf = -1; 434: } 435: break; 436: case TS_REJECT: 437: if (state == SIO && sc->sc_sts.s_xs0 & TS_WLE) 438: printf("ts%d: no write ring\n", tsunit); 439: if ((sc->sc_sts.s_xs0 & TS_ONL) == 0) 440: printf("ts%d: not online\n", tsunit); 441: break; 442: } 443: /* 444: * Couldn't recover error. 445: */ 446: #ifdef UCB_DEVERR 447: printf("ts%d: hard error bn%d xs0=%b", TSUNIT(bp->b_dev), 448: bp->b_blkno, sc->sc_sts.s_xs0, TSXS0_BITS); 449: if (sc->sc_sts.s_xs1) 450: printf(" xs1=%b", sc->sc_sts.s_xs1, TSXS1_BITS); 451: if (sc->sc_sts.s_xs2) 452: printf(" xs2=%b", sc->sc_sts.s_xs2, TSXS2_BITS); 453: if (sc->sc_sts.s_xs3) 454: printf(" xs3=%b\n", sc->sc_sts.s_xs3, TSXS3_BITS); 455: #else 456: deverror(bp, sc->sc_sts.s_xs0, sc->sc_sts.s_xs1); 457: printf("%o,%o\n", sc->sc_sts.s_xs2, sc->sc_sts.s_xs3); 458: #endif 459: bp->b_flags |= B_ERROR; 460: goto opdone; 461: /*NOTREACHED*/ 462: } 463: /* 464: * Advance tape control finite state machine. 465: */ 466: ignoreerr: 467: switch (state) { 468: case SIO: 469: /* 470: * Read/write increments tape block number. 471: */ 472: sc->sc_blkno++; 473: goto opdone; 474: /*NOTREACHED*/ 475: 476: case SCOM: 477: /* 478: * For forward/backward space record 479: * update current position. 480: */ 481: if (bp == &ctsbuf) 482: switch (bp->b_command) { 483: case TS_SFORW: 484: sc->sc_blkno += bp->b_repcnt; 485: break; 486: 487: case TS_SREV: 488: sc->sc_blkno -= bp->b_repcnt; 489: break; 490: } 491: goto opdone; 492: /*NOTREACHED*/ 493: 494: case SSEEK: 495: sc->sc_blkno = dbtofsb(bp->b_blkno); 496: goto opcont; 497: /*NOTREACHED*/ 498: 499: default: 500: panic("tsintr"); 501: /*NOTREACHED*/ 502: } 503: 504: opdone: 505: /* 506: * Reset error count and remove 507: * from device queue. 508: */ 509: tstab.b_errcnt = 0; 510: tstab.b_actf = bp->av_forw; 511: bp->b_resid = sc->sc_sts.s_rbpcr; 512: iodone(bp); 513: 514: opcont: 515: tsstart(); 516: } 517: 518: tsseteof(bp) 519: register struct buf *bp; 520: { 521: register tsunit = TSUNIT(bp->b_dev); 522: register struct ts_softc *sc = &ts_softc[tsunit]; 523: 524: if (bp == &ctsbuf) { 525: if (sc->sc_blkno > dbtofsb(bp->b_blkno)) { 526: /* reversing */ 527: sc->sc_nxrec = dbtofsb(bp->b_blkno) - sc->sc_sts.s_rbpcr; 528: sc->sc_blkno = sc->sc_nxrec; 529: } 530: else 531: { 532: /* spacing forward */ 533: sc->sc_blkno = dbtofsb(bp->b_blkno) - sc->sc_sts.s_rbpcr; 534: sc->sc_nxrec = sc->sc_blkno - 1; 535: } 536: return; 537: } 538: else 539: /* eof on read */ 540: sc->sc_nxrec = dbtofsb(bp->b_blkno); 541: } 542: 543: /* 544: * Initialize the TS11. 545: */ 546: tsinit(tsunit) 547: { 548: register struct tsdevice *tsaddr = TSADDR; 549: struct ts_softc *sc = &ts_softc[tsunit]; 550: register struct ts_cmd *tcmd = &sc->sc_cmd; 551: register struct ts_char *tchar = &sc->sc_char; 552: 553: if (tsaddr->tssr & (TS_NBA | TS_OFL)) { 554: tsaddr->tssr = 0; /* subsystem initialize */ 555: tswait(tssr); 556: if (((u_short) tcmd) & 03) { 557: printf("ts%d: addr mod 4 != 0\n", tsunit); 558: return (1); 559: } 560: tchar->char_bptr = &sc->sc_sts; 561: tchar->char_bae = 0; 562: tchar->char_size = sizeof(struct ts_sts); 563: tchar->char_mode = TS_ESS; 564: tcmd->c_cmd = TS_ACK | TS_SETCHR; 565: tcmd->c_loba = tchar; 566: tcmd->c_hiba = 0; 567: tcmd->c_size = sizeof(struct ts_char); 568: tsaddr->tsdb = tcmd; 569: tswait(tssr); 570: if (tsaddr->tssr & TS_NBA) 571: return (1); 572: } 573: else 574: return(0); 575: } 576: 577: tsread(dev) 578: register dev_t dev; 579: { 580: tsphys(dev); 581: bphysio(tsstrategy, &rtsbuf, dev, B_READ); 582: } 583: 584: tswrite(dev) 585: register dev_t dev; 586: { 587: tsphys(dev); 588: bphysio(tsstrategy, &rtsbuf, dev, B_WRITE); 589: } 590: 591: tsphys(dev) 592: dev_t dev; 593: { 594: register struct ts_softc *sc; 595: daddr_t a; 596: 597: sc = &ts_softc[TSUNIT(dev)]; 598: a = dbtofsb(u.u_offset >> 9); 599: sc->sc_blkno = a; 600: sc->sc_nxrec = a + 1; 601: } 602: 603: #ifdef TS_IOCTL 604: /*ARGSUSED*/ 605: tsioctl(dev, cmd, addr, flag) 606: dev_t dev; 607: caddr_t addr; 608: { 609: register struct ts_softc *sc = &ts_softc[TSUNIT(dev)]; 610: register struct buf *bp = &ctsbuf; 611: register callcount; 612: u_short fcount; 613: struct mtop mtop; 614: struct mtget mtget; 615: /* we depend on the values and order of the MT codes here */ 616: static tsops[] = {TS_WEOF,TS_SFORW,TS_SREV,TS_SFORW,TS_SREV,TS_REW,TS_OFFL,TS_SENSE}; 617: 618: switch (cmd) { 619: 620: case MTIOCTOP: /* tape operation */ 621: if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 622: u.u_error = EFAULT; 623: return; 624: } 625: switch(mtop.mt_op) { 626: case MTWEOF: 627: callcount = mtop.mt_count; 628: fcount = 1; 629: break; 630: case MTFSF: 631: case MTBSF: 632: case MTFSR: 633: case MTBSR: 634: callcount = 1; 635: fcount = mtop.mt_count; 636: break; 637: case MTREW: 638: case MTOFFL: 639: case MTNOP: 640: callcount = 1; 641: fcount = 1; 642: break; 643: default: 644: u.u_error = ENXIO; 645: return; 646: } 647: if (callcount <= 0 || fcount <= 0) { 648: u.u_error = ENXIO; 649: return; 650: } 651: while (--callcount >= 0) { 652: tscommand(dev, tsops[mtop.mt_op], fcount); 653: if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 654: bp->b_resid) { 655: u.u_error = EIO; 656: break; 657: } 658: if ((bp->b_flags & B_ERROR) || sc->sc_sts.s_xs0 & TS_BOT) 659: break; 660: } 661: geterror(bp); 662: return; 663: case MTIOCGET: 664: mtget.mt_dsreg = 0; 665: mtget.mt_erreg = sc->sc_sts.s_xs0; 666: mtget.mt_resid = sc->sc_resid; 667: mtget.mt_type = MT_ISTS; 668: if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 669: u.u_error = EFAULT; 670: return; 671: default: 672: u.u_error = ENXIO; 673: } 674: } 675: #endif TS_IOCTL 676: #endif NTS