lint
[unix-history] / usr / src / sys / vax / uba / tm.c
index 7ead61e..acf3e96 100644 (file)
@@ -1,6 +1,7 @@
-/*     tm.c    4.30    81/03/21        */
+/*     tm.c    4.37    81/04/28        */
 
 #include "te.h"
 
 #include "te.h"
+#include "ts.h"
 #if NTM > 0
 /*
  * TM11/TE10 tape driver
 #if NTM > 0
 /*
  * TM11/TE10 tape driver
@@ -97,6 +98,8 @@ struct        te_softc {
        short   sc_lastcmd;     /* last command to handle direction changes */
 #endif
        u_short sc_dens;        /* prototype command with density info */
        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 */
 } te_softc[NTM];
 #ifdef unneeded
 int    tmgapsdcnt;             /* DEBUG */
@@ -111,6 +114,15 @@ int        tmgapsdcnt;             /* DEBUG */
 #define        SCOM    3               /* sending control command */
 #define        SREW    4               /* sending a drive rewind */
 
 #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
 /*
  * Determine if there is a controller for
  * a tm at address reg.  Our goal is to make the
@@ -165,6 +177,9 @@ tmattach(ui)
        struct uba_device *ui;
 {
 
        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 is used in TMUNIT to index the ctmbuf and rtmbuf
         * arrays given a te unit number.
@@ -172,6 +187,7 @@ tmattach(ui)
        tetotm[ui->ui_unit] = ui->ui_mi->um_ctlr;
 }
 
        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.
 /*
  * Open the device.  Tapes are unique open
  * devices, so we refuse if it is already open.
@@ -221,6 +237,13 @@ get:
        sc->sc_nxrec = INF;
        sc->sc_lastiow = 0;
        sc->sc_dens = dens;
        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, (caddr_t)dev, 5*hz);
+       }
+       (void) spl0();
 }
 
 /*
 }
 
 /*
@@ -373,7 +396,7 @@ loop:
         * Default is that last command was NOT a write command;
         * if we do a write command we will notice this in tmintr().
         */
         * 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 (sc->sc_openf < 0 || (addr->tmcs&TM_CUR) == 0) {
                /*
                 * Have had a hard error on a non-raw tape
@@ -389,8 +412,18 @@ loop:
                 */
                if (bp->b_command == TM_SENSE)
                        goto next;
                 */
                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 minutes) 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 = imin(imax(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;
                if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV)
                        addr->tmbc = bp->b_repcnt;
                goto dobpcmd;
@@ -446,6 +479,7 @@ loop:
                                tmgapsdcnt++;
                sc->sc_lastcmd = TM_RCOM;               /* will serve */
 #endif
                                tmgapsdcnt++;
                sc->sc_lastcmd = TM_RCOM;               /* will serve */
 #endif
+               sc->sc_timo = 60;       /* premature, but should serve */
                (void) ubago(ui);
                return;
        }
                (void) ubago(ui);
                return;
        }
@@ -462,6 +496,7 @@ loop:
                bp->b_command = TM_SREV;
                addr->tmbc = dbtofsb(bp->b_blkno) - blkno;
        }
                bp->b_command = TM_SREV;
                addr->tmbc = dbtofsb(bp->b_blkno) - blkno;
        }
+       sc->sc_timo = imin(imax(10 * -addr->tmbc, 60), 5 * 60);
 dobpcmd:
 #ifdef notdef
        /*
 dobpcmd:
 #ifdef notdef
        /*
@@ -528,19 +563,22 @@ tmintr(tm11)
        bp = dp->b_actf;
        teunit = TEUNIT(bp->b_dev);
        addr = (struct device *)tedinfo[teunit]->ui_addr;
        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 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;
                        return;
+               }
        }
        /*
         * An operation completed... record status
         */
        }
        /*
         * 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;
        sc->sc_dsreg = addr->tmcs;
        sc->sc_erreg = addr->tmer;
        sc->sc_resid = addr->tmbc;
@@ -665,6 +703,21 @@ opcont:
        tmstart(um);
 }
 
        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, (caddr_t)dev, 5*hz);
+}
+
 tmseteof(bp)
        register struct buf *bp;
 {
 tmseteof(bp)
        register struct buf *bp;
 {
@@ -764,7 +817,8 @@ tmreset(uban)
                        else
                                um->um_tab.b_actl->b_forw = dp;
                        um->um_tab.b_actl = dp;
                        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);
        }
                }
                tmstart(um);
        }
@@ -833,6 +887,7 @@ tmioctl(dev, cmd, addr, flag)
                mtget.mt_dsreg = sc->sc_dsreg;
                mtget.mt_erreg = sc->sc_erreg;
                mtget.mt_resid = sc->sc_resid;
                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;
                if (copyout((caddr_t)&mtget, addr, sizeof(mtget)))
                        u.u_error = EFAULT;
                return;