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