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