-/* tm.c 4.30 81/03/21 */
+/* tm.c 4.36 81/04/15 */
#include "te.h"
+#include "ts.h"
#if NTM > 0
/*
* TM11/TE10 tape driver
short sc_lastcmd; /* last command to handle direction changes */
#endif
u_short sc_dens; /* prototype command with density info */
+ daddr_t sc_timo; /* time until timeout expires */
+ short sc_tact; /* timeout is active */
} te_softc[NTM];
#ifdef unneeded
int tmgapsdcnt; /* DEBUG */
#define SCOM 3 /* sending control command */
#define SREW 4 /* sending a drive rewind */
+#if NTS > 0
+/*
+ * Kludge to get around fact that we don't really
+ * check if a ts is there... if there are both tm's and ts's
+ * declared in the system, then this driver sets havetm to 1
+ * if it finds a tm, and ts just pretends there isn't a ts.
+ */
+int havetm = 0;
+#endif
/*
* Determine if there is a controller for
* a tm at address reg. Our goal is to make the
struct uba_device *ui;
{
+#if NTS > 0
+ havetm = 1;
+#endif
/*
* Tetotm is used in TMUNIT to index the ctmbuf and rtmbuf
* arrays given a te unit number.
tetotm[ui->ui_unit] = ui->ui_mi->um_ctlr;
}
+int tmtimer();
/*
* Open the device. Tapes are unique open
* devices, so we refuse if it is already open.
sc->sc_nxrec = INF;
sc->sc_lastiow = 0;
sc->sc_dens = dens;
+ (void) spl6();
+ if (sc->sc_tact == 0) {
+ sc->sc_timo = INF;
+ sc->sc_tact = 1;
+ timeout(tmtimer, dev, 5*hz);
+ }
+ (void) spl0();
}
/*
* Default is that last command was NOT a write command;
* if we do a write command we will notice this in tmintr().
*/
- sc->sc_lastiow = 1;
+ sc->sc_lastiow = 0;
if (sc->sc_openf < 0 || (addr->tmcs&TM_CUR) == 0) {
/*
* Have had a hard error on a non-raw tape
*/
if (bp->b_command == TM_SENSE)
goto next;
- um->um_tab.b_active =
- bp->b_command == TM_REW ? SREW : SCOM;
+ /*
+ * Set next state; give 5 minutes to complete
+ * rewind, or 10 seconds per iteration (minimum 60
+ * seconds and max 5 minute) to complete other ops.
+ */
+ if (bp->b_command == TM_REW) {
+ um->um_tab.b_active = SREW;
+ sc->sc_timo = 5 * 60;
+ } else {
+ um->um_tab.b_active = SCOM;
+ sc->sc_timo = min(max(10 * bp->b_repcnt, 60), 5 * 60);
+ }
if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV)
addr->tmbc = bp->b_repcnt;
goto dobpcmd;
tmgapsdcnt++;
sc->sc_lastcmd = TM_RCOM; /* will serve */
#endif
+ sc->sc_timo = 60; /* premature, but should serve */
(void) ubago(ui);
return;
}
bp->b_command = TM_SREV;
addr->tmbc = dbtofsb(bp->b_blkno) - blkno;
}
+ sc->sc_timo = min(max(10 * -addr->tmbc, 60), 5 * 60);
dobpcmd:
#ifdef notdef
/*
bp = dp->b_actf;
teunit = TEUNIT(bp->b_dev);
addr = (struct device *)tedinfo[teunit]->ui_addr;
+ sc = &te_softc[teunit];
/*
* If last command was a rewind, and tape is still
* rewinding, wait for the rewind complete interrupt.
*/
if (um->um_tab.b_active == SREW) {
um->um_tab.b_active = SCOM;
- if (addr->tmer&TMER_RWS)
+ if (addr->tmer&TMER_RWS) {
+ sc->sc_timo = 5*60; /* 5 minutes */
return;
+ }
}
/*
* An operation completed... record status
*/
- sc = &te_softc[teunit];
+ sc->sc_timo = INF;
sc->sc_dsreg = addr->tmcs;
sc->sc_erreg = addr->tmer;
sc->sc_resid = addr->tmbc;
tmstart(um);
}
+tmtimer(dev)
+ int dev;
+{
+ register struct te_softc *sc = &te_softc[TEUNIT(dev)];
+
+ if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) {
+ printf("te%d: lost interrupt\n");
+ sc->sc_timo = INF;
+ (void) spl5();
+ tmintr(TMUNIT(dev));
+ (void) spl0();
+ }
+ timeout(tmtimer, dev, 5*hz);
+}
+
tmseteof(bp)
register struct buf *bp;
{
else
um->um_tab.b_actl->b_forw = dp;
um->um_tab.b_actl = dp;
- te_softc[teunit].sc_openf = -1;
+ if (te_softc[teunit].sc_openf > 0)
+ te_softc[teunit].sc_openf = -1;
}
tmstart(um);
}
mtget.mt_dsreg = sc->sc_dsreg;
mtget.mt_erreg = sc->sc_erreg;
mtget.mt_resid = sc->sc_resid;
+ mtget.mt_type = MT_ISTM;
if (copyout((caddr_t)&mtget, addr, sizeof(mtget)))
u.u_error = EFAULT;
return;