|
|
1.1 ! root 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: * @(#)tm.c 7.1 (Berkeley) 6/5/86 ! 7: */ ! 8: ! 9: #include "te.h" ! 10: #include "ts.h" ! 11: #if NTE > 0 ! 12: /* ! 13: * TM11/TE10 tape driver ! 14: * ! 15: * TODO: ! 16: * test driver with more than one slave ! 17: * test driver with more than one controller ! 18: * test reset code ! 19: * what happens if you offline tape during rewind? ! 20: * test using file system on tape ! 21: */ ! 22: #include "../machine/pte.h" ! 23: ! 24: #include "param.h" ! 25: #include "systm.h" ! 26: #include "buf.h" ! 27: #include "dir.h" ! 28: #include "conf.h" ! 29: #include "user.h" ! 30: #include "file.h" ! 31: #include "map.h" ! 32: #include "vm.h" ! 33: #include "ioctl.h" ! 34: #include "mtio.h" ! 35: #include "cmap.h" ! 36: #include "uio.h" ! 37: #include "kernel.h" ! 38: #include "tty.h" ! 39: ! 40: #include "../vax/cpu.h" ! 41: #include "ubareg.h" ! 42: #include "ubavar.h" ! 43: #include "tmreg.h" ! 44: ! 45: /* ! 46: * There is a ctmbuf per tape controller. ! 47: * It is used as the token to pass to the internal routines ! 48: * to execute tape ioctls, and also acts as a lock on the slaves ! 49: * on the controller, since there is only one per controller. ! 50: * In particular, when the tape is rewinding on close we release ! 51: * the user process but any further attempts to use the tape drive ! 52: * before the rewind completes will hang waiting for ctmbuf. ! 53: */ ! 54: struct buf ctmbuf[NTM]; ! 55: ! 56: /* ! 57: * Raw tape operations use rtmbuf. The driver ! 58: * notices when rtmbuf is being used and allows the user ! 59: * program to continue after errors and read records ! 60: * not of the standard length (BSIZE). ! 61: */ ! 62: struct buf rtmbuf[NTM]; ! 63: ! 64: /* ! 65: * Driver unibus interface routines and variables. ! 66: */ ! 67: int tmprobe(), tmslave(), tmattach(), tmdgo(), tmintr(); ! 68: struct uba_ctlr *tmminfo[NTM]; ! 69: struct uba_device *tedinfo[NTE]; ! 70: struct buf teutab[NTE]; ! 71: short tetotm[NTE]; ! 72: u_short tmstd[] = { 0772520, 0 }; ! 73: struct uba_driver tmdriver = ! 74: { tmprobe, tmslave, tmattach, tmdgo, tmstd, "te", tedinfo, "tm", tmminfo, 0 }; ! 75: ! 76: /* bits in minor device */ ! 77: #define TEUNIT(dev) (minor(dev)&03) ! 78: #define TMUNIT(dev) (tetotm[TEUNIT(dev)]) ! 79: #define T_NOREWIND 04 ! 80: #define T_1600BPI 0x8 ! 81: ! 82: #define INF (daddr_t)1000000L ! 83: ! 84: /* ! 85: * Software state per tape transport. ! 86: * ! 87: * 1. A tape drive is a unique-open device; we refuse opens when it is already. ! 88: * 2. We keep track of the current position on a block tape and seek ! 89: * before operations by forward/back spacing if necessary. ! 90: * 3. We remember if the last operation was a write on a tape, so if a tape ! 91: * is open read write and the last thing done is a write we can ! 92: * write a standard end of tape mark (two eofs). ! 93: * 4. We remember the status registers after the last command, using ! 94: * then internally and returning them to the SENSE ioctl. ! 95: * 5. We remember the last density the tape was used at. If it is ! 96: * not a BOT when we start using it and we are writing, we don't ! 97: * let the density be changed. ! 98: */ ! 99: struct te_softc { ! 100: char sc_openf; /* lock against multiple opens */ ! 101: char sc_lastiow; /* last op was a write */ ! 102: daddr_t sc_blkno; /* block number, for block device tape */ ! 103: daddr_t sc_nxrec; /* position of end of tape, if known */ ! 104: u_short sc_erreg; /* copy of last erreg */ ! 105: u_short sc_dsreg; /* copy of last dsreg */ ! 106: short sc_resid; /* copy of last bc */ ! 107: #ifdef unneeded ! 108: short sc_lastcmd; /* last command to handle direction changes */ ! 109: #endif ! 110: u_short sc_dens; /* prototype command with density info */ ! 111: short sc_tact; /* timeout is active */ ! 112: daddr_t sc_timo; /* time until timeout expires */ ! 113: struct tty *sc_ttyp; /* record user's tty for errors */ ! 114: } te_softc[NTE]; ! 115: #ifdef unneeded ! 116: int tmgapsdcnt; /* DEBUG */ ! 117: #endif ! 118: ! 119: /* ! 120: * States for um->um_tab.b_active, the per controller state flag. ! 121: * This is used to sequence control in the driver. ! 122: */ ! 123: #define SSEEK 1 /* seeking */ ! 124: #define SIO 2 /* doing seq i/o */ ! 125: #define SCOM 3 /* sending control command */ ! 126: #define SREW 4 /* sending a drive rewind */ ! 127: ! 128: /* ! 129: * Determine if there is a controller for ! 130: * a tm at address reg. Our goal is to make the ! 131: * device interrupt. ! 132: */ ! 133: tmprobe(reg) ! 134: caddr_t reg; ! 135: { ! 136: register int br, cvec; /* must be r11,r10; value-result */ ! 137: ! 138: #ifdef lint ! 139: br = 0; cvec = br; br = cvec; ! 140: tmintr(0); ! 141: #endif ! 142: ((struct tmdevice *)reg)->tmcs = TM_IE; ! 143: /* ! 144: * If this is a tm11, it ought to have interrupted ! 145: * by now, if it isn't (ie: it is a ts04) then we just ! 146: * hope that it didn't interrupt, so autoconf will ignore it. ! 147: * Just in case, we will reference one ! 148: * of the more distant registers, and hope for a machine ! 149: * check, or similar disaster if this is a ts. ! 150: * ! 151: * Note: on an 11/780, badaddr will just generate ! 152: * a uba error for a ts; but our caller will notice that ! 153: * so we won't check for it. ! 154: */ ! 155: if (badaddr((caddr_t)&((struct tmdevice *)reg)->tmrd, 2)) ! 156: return (0); ! 157: return (sizeof (struct tmdevice)); ! 158: } ! 159: ! 160: /* ! 161: * Due to a design flaw, we cannot ascertain if the tape ! 162: * exists or not unless it is on line - ie: unless a tape is ! 163: * mounted. This is too servere a restriction to bear, ! 164: * so all units are assumed to exist. ! 165: */ ! 166: /*ARGSUSED*/ ! 167: tmslave(ui, reg) ! 168: struct uba_device *ui; ! 169: caddr_t reg; ! 170: { ! 171: ! 172: return (1); ! 173: } ! 174: ! 175: /* ! 176: * Record attachment of the unit to the controller. ! 177: */ ! 178: /*ARGSUSED*/ ! 179: tmattach(ui) ! 180: struct uba_device *ui; ! 181: { ! 182: /* ! 183: * Tetotm is used in TMUNIT to index the ctmbuf and rtmbuf ! 184: * arrays given a te unit number. ! 185: */ ! 186: tetotm[ui->ui_unit] = ui->ui_mi->um_ctlr; ! 187: } ! 188: ! 189: int tmtimer(); ! 190: /* ! 191: * Open the device. Tapes are unique open ! 192: * devices, so we refuse if it is already open. ! 193: * We also check that a tape is available, and ! 194: * don't block waiting here; if you want to wait ! 195: * for a tape you should timeout in user code. ! 196: */ ! 197: ! 198: #ifdef AVIV ! 199: int tmdens[4] = { 0x6000, 0x0000, 0x2000, 0 }; ! 200: int tmdiag; ! 201: #endif AVIV ! 202: ! 203: tmopen(dev, flag) ! 204: dev_t dev; ! 205: int flag; ! 206: { ! 207: register int teunit; ! 208: register struct uba_device *ui; ! 209: register struct te_softc *sc; ! 210: int olddens, dens; ! 211: int s; ! 212: ! 213: teunit = TEUNIT(dev); ! 214: if (teunit>=NTE || (ui = tedinfo[teunit]) == 0 || ui->ui_alive == 0) ! 215: return (ENXIO); ! 216: if ((sc = &te_softc[teunit])->sc_openf) ! 217: return (EBUSY); ! 218: olddens = sc->sc_dens; ! 219: dens = TM_IE | TM_GO | (ui->ui_slave << 8); ! 220: #ifndef AVIV ! 221: if ((minor(dev) & T_1600BPI) == 0) ! 222: dens |= TM_D800; ! 223: #else AVIV ! 224: dens |= tmdens[(minor(dev)>>3)&03]; ! 225: #endif AVIV ! 226: sc->sc_dens = dens; ! 227: get: ! 228: tmcommand(dev, TM_SENSE, 1); ! 229: if (sc->sc_erreg&TMER_SDWN) { ! 230: sleep((caddr_t)&lbolt, PZERO+1); ! 231: goto get; ! 232: } ! 233: sc->sc_dens = olddens; ! 234: if ((sc->sc_erreg&(TMER_SELR|TMER_TUR)) != (TMER_SELR|TMER_TUR)) { ! 235: uprintf("te%d: not online\n", teunit); ! 236: return (EIO); ! 237: } ! 238: if ((flag&FWRITE) && (sc->sc_erreg&TMER_WRL)) { ! 239: uprintf("te%d: no write ring\n", teunit); ! 240: return (EIO); ! 241: } ! 242: if ((sc->sc_erreg&TMER_BOT) == 0 && (flag&FWRITE) && ! 243: dens != sc->sc_dens) { ! 244: uprintf("te%d: can't change density in mid-tape\n", teunit); ! 245: return (EIO); ! 246: } ! 247: sc->sc_openf = 1; ! 248: sc->sc_blkno = (daddr_t)0; ! 249: sc->sc_nxrec = INF; ! 250: sc->sc_lastiow = 0; ! 251: sc->sc_dens = dens; ! 252: sc->sc_ttyp = u.u_ttyp; ! 253: s = splclock(); ! 254: if (sc->sc_tact == 0) { ! 255: sc->sc_timo = INF; ! 256: sc->sc_tact = 1; ! 257: timeout(tmtimer, (caddr_t)dev, 5*hz); ! 258: } ! 259: splx(s); ! 260: return (0); ! 261: } ! 262: ! 263: /* ! 264: * Close tape device. ! 265: * ! 266: * If tape was open for writing or last operation was ! 267: * a write, then write two EOF's and backspace over the last one. ! 268: * Unless this is a non-rewinding special file, rewind the tape. ! 269: * Make the tape available to others. ! 270: */ ! 271: tmclose(dev, flag) ! 272: register dev_t dev; ! 273: register flag; ! 274: { ! 275: register struct te_softc *sc = &te_softc[TEUNIT(dev)]; ! 276: ! 277: if (flag == FWRITE || (flag&FWRITE) && sc->sc_lastiow) { ! 278: tmcommand(dev, TM_WEOF, 1); ! 279: tmcommand(dev, TM_WEOF, 1); ! 280: tmcommand(dev, TM_SREV, 1); ! 281: } ! 282: if ((minor(dev)&T_NOREWIND) == 0) ! 283: /* ! 284: * 0 count means don't hang waiting for rewind complete ! 285: * rather ctmbuf stays busy until the operation completes ! 286: * preventing further opens from completing by ! 287: * preventing a TM_SENSE from completing. ! 288: */ ! 289: tmcommand(dev, TM_REW, 0); ! 290: sc->sc_openf = 0; ! 291: } ! 292: ! 293: /* ! 294: * Execute a command on the tape drive ! 295: * a specified number of times. ! 296: */ ! 297: tmcommand(dev, com, count) ! 298: dev_t dev; ! 299: int com, count; ! 300: { ! 301: register struct buf *bp; ! 302: register int s; ! 303: ! 304: bp = &ctmbuf[TMUNIT(dev)]; ! 305: s = spl5(); ! 306: while (bp->b_flags&B_BUSY) { ! 307: /* ! 308: * This special check is because B_BUSY never ! 309: * gets cleared in the non-waiting rewind case. ! 310: */ ! 311: if (bp->b_repcnt == 0 && (bp->b_flags&B_DONE)) ! 312: break; ! 313: bp->b_flags |= B_WANTED; ! 314: sleep((caddr_t)bp, PRIBIO); ! 315: } ! 316: bp->b_flags = B_BUSY|B_READ; ! 317: splx(s); ! 318: bp->b_dev = dev; ! 319: bp->b_repcnt = -count; ! 320: bp->b_command = com; ! 321: bp->b_blkno = 0; ! 322: tmstrategy(bp); ! 323: /* ! 324: * In case of rewind from close, don't wait. ! 325: * This is the only case where count can be 0. ! 326: */ ! 327: if (count == 0) ! 328: return; ! 329: iowait(bp); ! 330: if (bp->b_flags&B_WANTED) ! 331: wakeup((caddr_t)bp); ! 332: bp->b_flags &= B_ERROR; ! 333: } ! 334: ! 335: /* ! 336: * Queue a tape operation. ! 337: */ ! 338: tmstrategy(bp) ! 339: register struct buf *bp; ! 340: { ! 341: int teunit = TEUNIT(bp->b_dev); ! 342: register struct uba_ctlr *um; ! 343: register struct buf *dp; ! 344: int s; ! 345: ! 346: /* ! 347: * Put transfer at end of unit queue ! 348: */ ! 349: dp = &teutab[teunit]; ! 350: bp->av_forw = NULL; ! 351: s = spl5(); ! 352: um = tedinfo[teunit]->ui_mi; ! 353: if (dp->b_actf == NULL) { ! 354: dp->b_actf = bp; ! 355: /* ! 356: * Transport not already active... ! 357: * put at end of controller queue. ! 358: */ ! 359: dp->b_forw = NULL; ! 360: if (um->um_tab.b_actf == NULL) ! 361: um->um_tab.b_actf = dp; ! 362: else ! 363: um->um_tab.b_actl->b_forw = dp; ! 364: um->um_tab.b_actl = dp; ! 365: } else ! 366: dp->b_actl->av_forw = bp; ! 367: dp->b_actl = bp; ! 368: /* ! 369: * If the controller is not busy, get ! 370: * it going. ! 371: */ ! 372: if (um->um_tab.b_active == 0) ! 373: tmstart(um); ! 374: splx(s); ! 375: } ! 376: ! 377: /* ! 378: * Start activity on a tm controller. ! 379: */ ! 380: tmstart(um) ! 381: register struct uba_ctlr *um; ! 382: { ! 383: register struct buf *bp, *dp; ! 384: register struct tmdevice *addr = (struct tmdevice *)um->um_addr; ! 385: register struct te_softc *sc; ! 386: register struct uba_device *ui; ! 387: int teunit, cmd; ! 388: daddr_t blkno; ! 389: ! 390: /* ! 391: * Look for an idle transport on the controller. ! 392: */ ! 393: loop: ! 394: if ((dp = um->um_tab.b_actf) == NULL) ! 395: return; ! 396: if ((bp = dp->b_actf) == NULL) { ! 397: um->um_tab.b_actf = dp->b_forw; ! 398: goto loop; ! 399: } ! 400: teunit = TEUNIT(bp->b_dev); ! 401: ui = tedinfo[teunit]; ! 402: /* ! 403: * Record pre-transfer status (e.g. for TM_SENSE) ! 404: */ ! 405: sc = &te_softc[teunit]; ! 406: addr = (struct tmdevice *)um->um_addr; ! 407: addr->tmcs = (ui->ui_slave << 8); ! 408: sc->sc_dsreg = addr->tmcs; ! 409: sc->sc_erreg = addr->tmer; ! 410: sc->sc_resid = addr->tmbc; ! 411: /* ! 412: * Default is that last command was NOT a write command; ! 413: * if we do a write command we will notice this in tmintr(). ! 414: */ ! 415: sc->sc_lastiow = 0; ! 416: if (sc->sc_openf < 0 || (addr->tmcs&TM_CUR) == 0) { ! 417: /* ! 418: * Have had a hard error on a non-raw tape ! 419: * or the tape unit is now unavailable ! 420: * (e.g. taken off line). ! 421: */ ! 422: bp->b_flags |= B_ERROR; ! 423: goto next; ! 424: } ! 425: if (bp == &ctmbuf[TMUNIT(bp->b_dev)]) { ! 426: /* ! 427: * Execute control operation with the specified count. ! 428: */ ! 429: if (bp->b_command == TM_SENSE) ! 430: goto next; ! 431: /* ! 432: * Set next state; give 5 minutes to complete ! 433: * rewind, or 10 seconds per iteration (minimum 60 ! 434: * seconds and max 5 minutes) to complete other ops. ! 435: */ ! 436: if (bp->b_command == TM_REW) { ! 437: um->um_tab.b_active = SREW; ! 438: sc->sc_timo = 5 * 60; ! 439: } else { ! 440: um->um_tab.b_active = SCOM; ! 441: sc->sc_timo = ! 442: imin(imax(10*(int)-bp->b_repcnt,60),5*60); ! 443: } ! 444: if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV) ! 445: addr->tmbc = bp->b_repcnt; ! 446: goto dobpcmd; ! 447: } ! 448: /* ! 449: * The following checks handle boundary cases for operation ! 450: * on non-raw tapes. On raw tapes the initialization of ! 451: * sc->sc_nxrec by tmphys causes them to be skipped normally ! 452: * (except in the case of retries). ! 453: */ ! 454: if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) { ! 455: /* ! 456: * Can't read past known end-of-file. ! 457: */ ! 458: bp->b_flags |= B_ERROR; ! 459: bp->b_error = ENXIO; ! 460: goto next; ! 461: } ! 462: if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && ! 463: bp->b_flags&B_READ) { ! 464: /* ! 465: * Reading at end of file returns 0 bytes. ! 466: */ ! 467: bp->b_resid = bp->b_bcount; ! 468: clrbuf(bp); ! 469: goto next; ! 470: } ! 471: if ((bp->b_flags&B_READ) == 0) ! 472: /* ! 473: * Writing sets EOF ! 474: */ ! 475: sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1; ! 476: /* ! 477: * If the data transfer command is in the correct place, ! 478: * set up all the registers except the csr, and give ! 479: * control over to the UNIBUS adapter routines, to ! 480: * wait for resources to start the i/o. ! 481: */ ! 482: if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) { ! 483: addr->tmbc = -bp->b_bcount; ! 484: if ((bp->b_flags&B_READ) == 0) { ! 485: if (um->um_tab.b_errcnt) ! 486: cmd = TM_WIRG; ! 487: else ! 488: cmd = TM_WCOM; ! 489: } else ! 490: cmd = TM_RCOM; ! 491: um->um_tab.b_active = SIO; ! 492: um->um_cmd = sc->sc_dens|cmd; ! 493: #ifdef notdef ! 494: if (tmreverseop(sc->sc_lastcmd)) ! 495: while (addr->tmer & TMER_SDWN) ! 496: DELAY(10),tmgapsdcnt++; ! 497: sc->sc_lastcmd = TM_RCOM; /* will serve */ ! 498: #endif ! 499: sc->sc_timo = 60; /* premature, but should serve */ ! 500: (void) ubago(ui); ! 501: return; ! 502: } ! 503: /* ! 504: * Tape positioned incorrectly; ! 505: * set to seek forwards or backwards to the correct spot. ! 506: * This happens for raw tapes only on error retries. ! 507: */ ! 508: um->um_tab.b_active = SSEEK; ! 509: if (blkno < bdbtofsb(bp->b_blkno)) { ! 510: bp->b_command = TM_SFORW; ! 511: addr->tmbc = blkno - bdbtofsb(bp->b_blkno); ! 512: } else { ! 513: bp->b_command = TM_SREV; ! 514: addr->tmbc = bdbtofsb(bp->b_blkno) - blkno; ! 515: } ! 516: sc->sc_timo = imin(imax(10 * -addr->tmbc, 60), 5 * 60); ! 517: dobpcmd: ! 518: #ifdef notdef ! 519: /* ! 520: * It is strictly necessary to wait for the tape ! 521: * to stop before changing directions, but the TC11 ! 522: * handles this for us. ! 523: */ ! 524: if (tmreverseop(sc->sc_lastcmd) != tmreverseop(bp->b_command)) ! 525: while (addr->tmer & TM_SDWN) ! 526: DELAY(10),tmgapsdcnt++; ! 527: sc->sc_lastcmd = bp->b_command; ! 528: #endif ! 529: /* ! 530: * Do the command in bp. ! 531: */ ! 532: addr->tmcs = (sc->sc_dens | bp->b_command); ! 533: return; ! 534: ! 535: next: ! 536: /* ! 537: * Done with this operation due to error or ! 538: * the fact that it doesn't do anything. ! 539: * Release UBA resources (if any), dequeue ! 540: * the transfer and continue processing this slave. ! 541: */ ! 542: if (um->um_ubinfo) ! 543: ubadone(um); ! 544: um->um_tab.b_errcnt = 0; ! 545: dp->b_actf = bp->av_forw; ! 546: iodone(bp); ! 547: goto loop; ! 548: } ! 549: ! 550: /* ! 551: * The UNIBUS resources we needed have been ! 552: * allocated to us; start the device. ! 553: */ ! 554: tmdgo(um) ! 555: register struct uba_ctlr *um; ! 556: { ! 557: register struct tmdevice *addr = (struct tmdevice *)um->um_addr; ! 558: ! 559: addr->tmba = um->um_ubinfo; ! 560: addr->tmcs = um->um_cmd | ((um->um_ubinfo >> 12) & 0x30); ! 561: } ! 562: ! 563: /* ! 564: * Tm interrupt routine. ! 565: */ ! 566: /*ARGSUSED*/ ! 567: tmintr(tm11) ! 568: int tm11; ! 569: { ! 570: struct buf *dp; ! 571: register struct buf *bp; ! 572: register struct uba_ctlr *um = tmminfo[tm11]; ! 573: register struct tmdevice *addr; ! 574: register struct te_softc *sc; ! 575: int teunit; ! 576: register state; ! 577: ! 578: if ((dp = um->um_tab.b_actf) == NULL) ! 579: return; ! 580: bp = dp->b_actf; ! 581: teunit = TEUNIT(bp->b_dev); ! 582: addr = (struct tmdevice *)tedinfo[teunit]->ui_addr; ! 583: sc = &te_softc[teunit]; ! 584: /* ! 585: * If last command was a rewind, and tape is still ! 586: * rewinding, wait for the rewind complete interrupt. ! 587: */ ! 588: if (um->um_tab.b_active == SREW) { ! 589: um->um_tab.b_active = SCOM; ! 590: if (addr->tmer&TMER_RWS) { ! 591: sc->sc_timo = 5*60; /* 5 minutes */ ! 592: return; ! 593: } ! 594: } ! 595: /* ! 596: * An operation completed... record status ! 597: */ ! 598: sc->sc_timo = INF; ! 599: sc->sc_dsreg = addr->tmcs; ! 600: sc->sc_erreg = addr->tmer; ! 601: sc->sc_resid = addr->tmbc; ! 602: if ((bp->b_flags & B_READ) == 0) ! 603: sc->sc_lastiow = 1; ! 604: state = um->um_tab.b_active; ! 605: um->um_tab.b_active = 0; ! 606: /* ! 607: * Check for errors. ! 608: */ ! 609: if (addr->tmcs&TM_ERR) { ! 610: while (addr->tmer & TMER_SDWN) ! 611: DELAY(10); /* await settle down */ ! 612: /* ! 613: * If we hit the end of the tape file, update our position. ! 614: */ ! 615: if (addr->tmer&TMER_EOF) { ! 616: tmseteof(bp); /* set blkno and nxrec */ ! 617: state = SCOM; /* force completion */ ! 618: /* ! 619: * Stuff bc so it will be unstuffed correctly ! 620: * later to get resid. ! 621: */ ! 622: addr->tmbc = -bp->b_bcount; ! 623: goto opdone; ! 624: } ! 625: /* ! 626: * If we were reading raw tape and the only error was that the ! 627: * record was too long, then we don't consider this an error. ! 628: */ ! 629: if (bp == &rtmbuf[TMUNIT(bp->b_dev)] && (bp->b_flags&B_READ) && ! 630: (addr->tmer&(TMER_HARD|TMER_SOFT)) == TMER_RLE) ! 631: goto ignoreerr; ! 632: /* ! 633: * If error is not hard, and this was an i/o operation ! 634: * retry up to 8 times. ! 635: */ ! 636: if ((addr->tmer&TMER_HARD)==0 && state==SIO) { ! 637: if (++um->um_tab.b_errcnt < 7) { ! 638: sc->sc_blkno++; ! 639: ubadone(um); ! 640: goto opcont; ! 641: } ! 642: } else ! 643: /* ! 644: * Hard or non-i/o errors on non-raw tape ! 645: * cause it to close. ! 646: */ ! 647: if (sc->sc_openf>0 && bp != &rtmbuf[TMUNIT(bp->b_dev)]) ! 648: sc->sc_openf = -1; ! 649: /* ! 650: * Couldn't recover error ! 651: */ ! 652: tprintf(sc->sc_ttyp, ! 653: "te%d: hard error bn%d er=%b\n", minor(bp->b_dev)&03, ! 654: bp->b_blkno, sc->sc_erreg, TMER_BITS); ! 655: #ifdef AVIV ! 656: if (tmdiag) { ! 657: addr->tmmr = DAB; ! 658: printf("reject code 0%o", addr->tmmr & DAB_MASK); ! 659: addr->tmmr = DTS; ! 660: if (addr->tmmr & DTS_MASK) ! 661: printf(", dead track 0%o", addr->tmmr & DTS_MASK); ! 662: addr->tmmr = RWERR; ! 663: printf(", read/write errors %b\n", ! 664: addr->tmmr & RWERR_MASK, ! 665: RWERR_BITS); ! 666: addr->tmmr = DRSENSE; ! 667: printf("drive sense %b, ", addr->tmmr & DRSENSE_MASK, ! 668: DRSENSE_BITS); ! 669: printf("fsr %b\n", addr->tmfsr, FSR_BITS); ! 670: } ! 671: #endif AVIV ! 672: bp->b_flags |= B_ERROR; ! 673: goto opdone; ! 674: } ! 675: /* ! 676: * Advance tape control FSM. ! 677: */ ! 678: ignoreerr: ! 679: switch (state) { ! 680: ! 681: case SIO: ! 682: /* ! 683: * Read/write increments tape block number ! 684: */ ! 685: sc->sc_blkno++; ! 686: goto opdone; ! 687: ! 688: case SCOM: ! 689: /* ! 690: * For forward/backward space record update current position. ! 691: */ ! 692: if (bp == &ctmbuf[TMUNIT(bp->b_dev)]) ! 693: switch ((int)bp->b_command) { ! 694: ! 695: case TM_SFORW: ! 696: sc->sc_blkno -= bp->b_repcnt; ! 697: break; ! 698: ! 699: case TM_SREV: ! 700: sc->sc_blkno += bp->b_repcnt; ! 701: break; ! 702: } ! 703: goto opdone; ! 704: ! 705: case SSEEK: ! 706: sc->sc_blkno = bdbtofsb(bp->b_blkno); ! 707: goto opcont; ! 708: ! 709: default: ! 710: panic("tmintr"); ! 711: } ! 712: opdone: ! 713: /* ! 714: * Reset error count and remove ! 715: * from device queue. ! 716: */ ! 717: um->um_tab.b_errcnt = 0; ! 718: dp->b_actf = bp->av_forw; ! 719: /* ! 720: * Check resid; watch out for resid >32767 (tmbc not negative). ! 721: */ ! 722: bp->b_resid = ((int) -addr->tmbc) & 0xffff; ! 723: ubadone(um); ! 724: iodone(bp); ! 725: /* ! 726: * Circulate slave to end of controller ! 727: * queue to give other slaves a chance. ! 728: */ ! 729: um->um_tab.b_actf = dp->b_forw; ! 730: if (dp->b_actf) { ! 731: dp->b_forw = NULL; ! 732: if (um->um_tab.b_actf == NULL) ! 733: um->um_tab.b_actf = dp; ! 734: else ! 735: um->um_tab.b_actl->b_forw = dp; ! 736: um->um_tab.b_actl = dp; ! 737: } ! 738: if (um->um_tab.b_actf == 0) ! 739: return; ! 740: opcont: ! 741: tmstart(um); ! 742: } ! 743: ! 744: tmtimer(dev) ! 745: int dev; ! 746: { ! 747: register struct te_softc *sc = &te_softc[TEUNIT(dev)]; ! 748: register short x; ! 749: ! 750: if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) { ! 751: printf("te%d: lost interrupt\n", TEUNIT(dev)); ! 752: sc->sc_timo = INF; ! 753: x = spl5(); ! 754: tmintr(TMUNIT(dev)); ! 755: (void) splx(x); ! 756: } ! 757: timeout(tmtimer, (caddr_t)dev, 5*hz); ! 758: } ! 759: ! 760: tmseteof(bp) ! 761: register struct buf *bp; ! 762: { ! 763: register int teunit = TEUNIT(bp->b_dev); ! 764: register struct tmdevice *addr = ! 765: (struct tmdevice *)tedinfo[teunit]->ui_addr; ! 766: register struct te_softc *sc = &te_softc[teunit]; ! 767: ! 768: if (bp == &ctmbuf[TMUNIT(bp->b_dev)]) { ! 769: if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) { ! 770: /* reversing */ ! 771: sc->sc_nxrec = bdbtofsb(bp->b_blkno) - addr->tmbc; ! 772: sc->sc_blkno = sc->sc_nxrec; ! 773: } else { ! 774: /* spacing forward */ ! 775: sc->sc_blkno = bdbtofsb(bp->b_blkno) + addr->tmbc; ! 776: sc->sc_nxrec = sc->sc_blkno - 1; ! 777: } ! 778: return; ! 779: } ! 780: /* eof on read */ ! 781: sc->sc_nxrec = bdbtofsb(bp->b_blkno); ! 782: } ! 783: ! 784: tmread(dev, uio) ! 785: dev_t dev; ! 786: struct uio *uio; ! 787: { ! 788: int errno; ! 789: ! 790: errno = tmphys(dev, uio); ! 791: if (errno) ! 792: return (errno); ! 793: return (physio(tmstrategy, &rtmbuf[TMUNIT(dev)], dev, B_READ, minphys, uio)); ! 794: } ! 795: ! 796: tmwrite(dev, uio) ! 797: dev_t dev; ! 798: struct uio *uio; ! 799: { ! 800: int errno; ! 801: ! 802: errno = tmphys(dev, uio); ! 803: if (errno) ! 804: return (errno); ! 805: return (physio(tmstrategy, &rtmbuf[TMUNIT(dev)], dev, B_WRITE, minphys, uio)); ! 806: } ! 807: ! 808: /* ! 809: * Check that a raw device exists. ! 810: * If it does, set up sc_blkno and sc_nxrec ! 811: * so that the tape will appear positioned correctly. ! 812: */ ! 813: tmphys(dev, uio) ! 814: dev_t dev; ! 815: struct uio *uio; ! 816: { ! 817: register int teunit = TEUNIT(dev); ! 818: register daddr_t a; ! 819: register struct te_softc *sc; ! 820: register struct uba_device *ui; ! 821: ! 822: if (teunit >= NTE || (ui=tedinfo[teunit]) == 0 || ui->ui_alive == 0) ! 823: return (ENXIO); ! 824: sc = &te_softc[teunit]; ! 825: a = bdbtofsb(uio->uio_offset >> 9); ! 826: sc->sc_blkno = a; ! 827: sc->sc_nxrec = a + 1; ! 828: return (0); ! 829: } ! 830: ! 831: tmreset(uban) ! 832: int uban; ! 833: { ! 834: register struct uba_ctlr *um; ! 835: register tm11, teunit; ! 836: register struct uba_device *ui; ! 837: register struct buf *dp; ! 838: ! 839: for (tm11 = 0; tm11 < NTM; tm11++) { ! 840: if ((um = tmminfo[tm11]) == 0 || um->um_alive == 0 || ! 841: um->um_ubanum != uban) ! 842: continue; ! 843: printf(" tm%d", tm11); ! 844: um->um_tab.b_active = 0; ! 845: um->um_tab.b_actf = um->um_tab.b_actl = 0; ! 846: if (um->um_ubinfo) { ! 847: printf("<%d>", (um->um_ubinfo>>28)&0xf); ! 848: um->um_ubinfo = 0; ! 849: } ! 850: ((struct tmdevice *)(um->um_addr))->tmcs = TM_DCLR; ! 851: for (teunit = 0; teunit < NTE; teunit++) { ! 852: if ((ui = tedinfo[teunit]) == 0 || ui->ui_mi != um || ! 853: ui->ui_alive == 0) ! 854: continue; ! 855: dp = &teutab[teunit]; ! 856: dp->b_active = 0; ! 857: dp->b_forw = 0; ! 858: if (um->um_tab.b_actf == NULL) ! 859: um->um_tab.b_actf = dp; ! 860: else ! 861: um->um_tab.b_actl->b_forw = dp; ! 862: um->um_tab.b_actl = dp; ! 863: if (te_softc[teunit].sc_openf > 0) ! 864: te_softc[teunit].sc_openf = -1; ! 865: } ! 866: tmstart(um); ! 867: } ! 868: } ! 869: ! 870: /*ARGSUSED*/ ! 871: tmioctl(dev, cmd, data, flag) ! 872: caddr_t data; ! 873: dev_t dev; ! 874: { ! 875: int teunit = TEUNIT(dev); ! 876: register struct te_softc *sc = &te_softc[teunit]; ! 877: register struct buf *bp = &ctmbuf[TMUNIT(dev)]; ! 878: register callcount; ! 879: int fcount; ! 880: struct mtop *mtop; ! 881: struct mtget *mtget; ! 882: /* we depend of the values and order of the MT codes here */ ! 883: static tmops[] = ! 884: {TM_WEOF,TM_SFORW,TM_SREV,TM_SFORW,TM_SREV,TM_REW,TM_OFFL,TM_SENSE}; ! 885: ! 886: switch (cmd) { ! 887: ! 888: case MTIOCTOP: /* tape operation */ ! 889: mtop = (struct mtop *)data; ! 890: switch (mtop->mt_op) { ! 891: ! 892: case MTWEOF: ! 893: callcount = mtop->mt_count; ! 894: fcount = 1; ! 895: break; ! 896: ! 897: case MTFSF: case MTBSF: ! 898: callcount = mtop->mt_count; ! 899: fcount = INF; ! 900: break; ! 901: ! 902: case MTFSR: case MTBSR: ! 903: callcount = 1; ! 904: fcount = mtop->mt_count; ! 905: break; ! 906: ! 907: case MTREW: case MTOFFL: case MTNOP: ! 908: callcount = 1; ! 909: fcount = 1; ! 910: break; ! 911: ! 912: default: ! 913: return (ENXIO); ! 914: } ! 915: if (callcount <= 0 || fcount <= 0) ! 916: return (EINVAL); ! 917: while (--callcount >= 0) { ! 918: tmcommand(dev, tmops[mtop->mt_op], fcount); ! 919: if ((mtop->mt_op == MTFSR || mtop->mt_op == MTBSR) && ! 920: bp->b_resid) ! 921: return (EIO); ! 922: if ((bp->b_flags&B_ERROR) || sc->sc_erreg&TMER_BOT) ! 923: break; ! 924: } ! 925: return (geterror(bp)); ! 926: ! 927: case MTIOCGET: ! 928: mtget = (struct mtget *)data; ! 929: mtget->mt_dsreg = sc->sc_dsreg; ! 930: mtget->mt_erreg = sc->sc_erreg; ! 931: mtget->mt_resid = sc->sc_resid; ! 932: mtget->mt_type = MT_ISTM; ! 933: break; ! 934: ! 935: default: ! 936: return (ENXIO); ! 937: } ! 938: return (0); ! 939: } ! 940: ! 941: #define DBSIZE 20 ! 942: ! 943: tmdump() ! 944: { ! 945: register struct uba_device *ui; ! 946: register struct uba_regs *up; ! 947: register struct tmdevice *addr; ! 948: int blk, num; ! 949: int start; ! 950: ! 951: start = 0; ! 952: num = maxfree; ! 953: #define phys(a,b) ((b)((int)(a)&0x7fffffff)) ! 954: if (tedinfo[0] == 0) ! 955: return (ENXIO); ! 956: ui = phys(tedinfo[0], struct uba_device *); ! 957: up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba; ! 958: ubainit(up); ! 959: DELAY(1000000); ! 960: addr = (struct tmdevice *)ui->ui_physaddr; ! 961: tmwait(addr); ! 962: addr->tmcs = TM_DCLR | TM_GO; ! 963: while (num > 0) { ! 964: blk = num > DBSIZE ? DBSIZE : num; ! 965: tmdwrite(start, blk, addr, up); ! 966: start += blk; ! 967: num -= blk; ! 968: } ! 969: tmeof(addr); ! 970: tmeof(addr); ! 971: tmwait(addr); ! 972: if (addr->tmcs&TM_ERR) ! 973: return (EIO); ! 974: addr->tmcs = TM_REW | TM_GO; ! 975: tmwait(addr); ! 976: return (0); ! 977: } ! 978: ! 979: tmdwrite(dbuf, num, addr, up) ! 980: register dbuf, num; ! 981: register struct tmdevice *addr; ! 982: struct uba_regs *up; ! 983: { ! 984: register struct pte *io; ! 985: register int npf; ! 986: ! 987: tmwait(addr); ! 988: io = up->uba_map; ! 989: npf = num+1; ! 990: while (--npf != 0) ! 991: *(int *)io++ = (dbuf++ | (1<<UBAMR_DPSHIFT) | UBAMR_MRV); ! 992: *(int *)io = 0; ! 993: addr->tmbc = -(num*NBPG); ! 994: addr->tmba = 0; ! 995: addr->tmcs = TM_WCOM | TM_GO; ! 996: } ! 997: ! 998: tmwait(addr) ! 999: register struct tmdevice *addr; ! 1000: { ! 1001: register s; ! 1002: ! 1003: do ! 1004: s = addr->tmcs; ! 1005: while ((s & TM_CUR) == 0); ! 1006: } ! 1007: ! 1008: tmeof(addr) ! 1009: struct tmdevice *addr; ! 1010: { ! 1011: ! 1012: tmwait(addr); ! 1013: addr->tmcs = TM_WEOF | TM_GO; ! 1014: } ! 1015: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.