fix to reeves fix of dgo handling (reset b_active to 1)
[unix-history] / usr / src / sys / vax / uba / tm.c
index a967bb4..ec16ede 100644 (file)
@@ -1,7 +1,8 @@
-/*     tm.c    4.33    81/04/08        */
+/*     tm.c    4.48    82/05/27        */
 
 #include "te.h"
 
 #include "te.h"
-#if NTM > 0
+#include "ts.h"
+#if NTE > 0
 /*
  * TM11/TE10 tape driver
  *
 /*
  * TM11/TE10 tape driver
  *
@@ -97,7 +98,9 @@ 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 */
-} te_softc[NTM];
+       daddr_t sc_timo;        /* time until timeout expires */
+       short   sc_tact;        /* timeout is active */
+} te_softc[NTE];
 #ifdef unneeded
 int    tmgapsdcnt;             /* DEBUG */
 #endif
 #ifdef unneeded
 int    tmgapsdcnt;             /* DEBUG */
 #endif
@@ -123,8 +126,9 @@ tmprobe(reg)
 
 #ifdef lint
        br = 0; cvec = br; br = cvec;
 
 #ifdef lint
        br = 0; cvec = br; br = cvec;
+       tmintr(0);
 #endif
 #endif
-       ((struct device *)reg)->tmcs = TM_IE;
+       ((struct tmdevice *)reg)->tmcs = TM_IE;
        /*
         * If this is a tm11, it ought to have interrupted
         * by now, if it isn't (ie: it is a ts04) then we just
        /*
         * If this is a tm11, it ought to have interrupted
         * by now, if it isn't (ie: it is a ts04) then we just
@@ -137,7 +141,7 @@ tmprobe(reg)
         * a uba error for a ts; but our caller will notice that
         * so we won't check for it.
         */
         * a uba error for a ts; but our caller will notice that
         * so we won't check for it.
         */
-       if (badaddr((caddr_t)&((struct device *)reg)->tmrd, 2))
+       if (badaddr((caddr_t)&((struct tmdevice *)reg)->tmrd, 2))
                return (0);
        return (1);
 }
                return (0);
        return (1);
 }
@@ -164,7 +168,6 @@ tmslave(ui, reg)
 tmattach(ui)
        struct uba_device *ui;
 {
 tmattach(ui)
        struct uba_device *ui;
 {
-
        /*
         * 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 +175,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.
@@ -187,6 +191,7 @@ tmopen(dev, flag)
        register struct uba_device *ui;
        register struct te_softc *sc;
        int olddens, dens;
        register struct uba_device *ui;
        register struct te_softc *sc;
        int olddens, dens;
+       int s;
 
        teunit = TEUNIT(dev);
        if (teunit>=NTE || (sc = &te_softc[teunit])->sc_openf ||
 
        teunit = TEUNIT(dev);
        if (teunit>=NTE || (sc = &te_softc[teunit])->sc_openf ||
@@ -206,13 +211,19 @@ get:
                goto get;
        }
        sc->sc_dens = olddens;
                goto get;
        }
        sc->sc_dens = olddens;
-       if ((sc->sc_erreg&(TMER_SELR|TMER_TUR)) != (TMER_SELR|TMER_TUR) ||
-           (flag&FWRITE) && (sc->sc_erreg&TMER_WRL) ||
-           (sc->sc_erreg&TMER_BOT) == 0 && (flag&FWRITE) &&
-               dens != sc->sc_dens) {
-               /*
-                * Not online or density switch in mid-tape or write locked.
-                */
+       if ((sc->sc_erreg&(TMER_SELR|TMER_TUR)) != (TMER_SELR|TMER_TUR)) {
+               uprintf("te%d: not online\n", teunit);
+               u.u_error = EIO;
+               return;
+       }
+       if ((flag&FWRITE) && (sc->sc_erreg&TMER_WRL)) {
+               uprintf("te%d: no write ring\n", teunit);
+               u.u_error = EIO;
+               return;
+       }
+       if ((sc->sc_erreg&TMER_BOT) == 0 && (flag&FWRITE) &&
+           dens != sc->sc_dens) {
+               uprintf("te%d: can't change density in mid-tape\n", teunit);
                u.u_error = EIO;
                return;
        }
                u.u_error = EIO;
                return;
        }
@@ -221,6 +232,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;
+       s = spl6();
+       if (sc->sc_tact == 0) {
+               sc->sc_timo = INF;
+               sc->sc_tact = 1;
+               timeout(tmtimer, (caddr_t)dev, 5*hz);
+       }
+       splx(s);
 }
 
 /*
 }
 
 /*
@@ -262,9 +280,10 @@ tmcommand(dev, com, count)
        int com, count;
 {
        register struct buf *bp;
        int com, count;
 {
        register struct buf *bp;
+       register int s;
 
        bp = &ctmbuf[TMUNIT(dev)];
 
        bp = &ctmbuf[TMUNIT(dev)];
-       (void) spl5();
+       s = spl5();
        while (bp->b_flags&B_BUSY) {
                /*
                 * This special check is because B_BUSY never
        while (bp->b_flags&B_BUSY) {
                /*
                 * This special check is because B_BUSY never
@@ -276,7 +295,7 @@ tmcommand(dev, com, count)
                sleep((caddr_t)bp, PRIBIO);
        }
        bp->b_flags = B_BUSY|B_READ;
                sleep((caddr_t)bp, PRIBIO);
        }
        bp->b_flags = B_BUSY|B_READ;
-       (void) spl0();
+       splx(s);
        bp->b_dev = dev;
        bp->b_repcnt = -count;
        bp->b_command = com;
        bp->b_dev = dev;
        bp->b_repcnt = -count;
        bp->b_command = com;
@@ -303,13 +322,15 @@ tmstrategy(bp)
        int teunit = TEUNIT(bp->b_dev);
        register struct uba_ctlr *um;
        register struct buf *dp;
        int teunit = TEUNIT(bp->b_dev);
        register struct uba_ctlr *um;
        register struct buf *dp;
+       int s;
 
        /*
         * Put transfer at end of unit queue
         */
        dp = &teutab[teunit];
        bp->av_forw = NULL;
 
        /*
         * Put transfer at end of unit queue
         */
        dp = &teutab[teunit];
        bp->av_forw = NULL;
-       (void) spl5();
+       s = spl5();
+       um = tedinfo[teunit]->ui_mi;
        if (dp->b_actf == NULL) {
                dp->b_actf = bp;
                /*
        if (dp->b_actf == NULL) {
                dp->b_actf = bp;
                /*
@@ -317,7 +338,6 @@ tmstrategy(bp)
                 * put at end of controller queue.
                 */
                dp->b_forw = NULL;
                 * put at end of controller queue.
                 */
                dp->b_forw = NULL;
-               um = tedinfo[teunit]->ui_mi;
                if (um->um_tab.b_actf == NULL)
                        um->um_tab.b_actf = dp;
                else
                if (um->um_tab.b_actf == NULL)
                        um->um_tab.b_actf = dp;
                else
@@ -332,7 +352,7 @@ tmstrategy(bp)
         */
        if (um->um_tab.b_active == 0)
                tmstart(um);
         */
        if (um->um_tab.b_active == 0)
                tmstart(um);
-       (void) spl0();
+       splx(s);
 }
 
 /*
 }
 
 /*
@@ -342,7 +362,7 @@ tmstart(um)
        register struct uba_ctlr *um;
 {
        register struct buf *bp, *dp;
        register struct uba_ctlr *um;
 {
        register struct buf *bp, *dp;
-       register struct device *addr = (struct device *)um->um_addr;
+       register struct tmdevice *addr = (struct tmdevice *)um->um_addr;
        register struct te_softc *sc;
        register struct uba_device *ui;
        int teunit, cmd;
        register struct te_softc *sc;
        register struct uba_device *ui;
        int teunit, cmd;
@@ -364,7 +384,7 @@ loop:
         * Record pre-transfer status (e.g. for TM_SENSE)
         */
        sc = &te_softc[teunit];
         * Record pre-transfer status (e.g. for TM_SENSE)
         */
        sc = &te_softc[teunit];
-       addr = (struct device *)um->um_addr;
+       addr = (struct tmdevice *)um->um_addr;
        addr->tmcs = (ui->ui_slave << 8);
        sc->sc_dsreg = addr->tmcs;
        sc->sc_erreg = addr->tmer;
        addr->tmcs = (ui->ui_slave << 8);
        sc->sc_dsreg = addr->tmcs;
        sc->sc_erreg = addr->tmer;
@@ -389,8 +409,19 @@ 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*(int)-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 +477,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 +494,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
        /*
@@ -502,7 +535,7 @@ next:
 tmdgo(um)
        register struct uba_ctlr *um;
 {
 tmdgo(um)
        register struct uba_ctlr *um;
 {
-       register struct device *addr = (struct device *)um->um_addr;
+       register struct tmdevice *addr = (struct tmdevice *)um->um_addr;
 
        addr->tmba = um->um_ubinfo;
        addr->tmcs = um->um_cmd | ((um->um_ubinfo >> 12) & 0x30);
 
        addr->tmba = um->um_ubinfo;
        addr->tmcs = um->um_cmd | ((um->um_ubinfo >> 12) & 0x30);
@@ -518,7 +551,7 @@ tmintr(tm11)
        struct buf *dp;
        register struct buf *bp;
        register struct uba_ctlr *um = tmminfo[tm11];
        struct buf *dp;
        register struct buf *bp;
        register struct uba_ctlr *um = tmminfo[tm11];
-       register struct device *addr;
+       register struct tmdevice *addr;
        register struct te_softc *sc;
        int teunit;
        register state;
        register struct te_softc *sc;
        int teunit;
        register state;
@@ -527,20 +560,23 @@ tmintr(tm11)
                return;
        bp = dp->b_actf;
        teunit = TEUNIT(bp->b_dev);
                return;
        bp = dp->b_actf;
        teunit = TEUNIT(bp->b_dev);
-       addr = (struct device *)tedinfo[teunit]->ui_addr;
+       addr = (struct tmdevice *)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,12 +701,28 @@ opcont:
        tmstart(um);
 }
 
        tmstart(um);
 }
 
+tmtimer(dev)
+       int dev;
+{
+       register struct te_softc *sc = &te_softc[TEUNIT(dev)];
+       register short x;
+
+       if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) {
+               printf("te%d: lost interrupt\n", TEUNIT(dev));
+               sc->sc_timo = INF;
+               x = spl5();
+               tmintr(TMUNIT(dev));
+               (void) splx(x);
+       }
+       timeout(tmtimer, (caddr_t)dev, 5*hz);
+}
+
 tmseteof(bp)
        register struct buf *bp;
 {
        register int teunit = TEUNIT(bp->b_dev);
 tmseteof(bp)
        register struct buf *bp;
 {
        register int teunit = TEUNIT(bp->b_dev);
-       register struct device *addr = 
-           (struct device *)tedinfo[teunit]->ui_addr;
+       register struct tmdevice *addr = 
+           (struct tmdevice *)tedinfo[teunit]->ui_addr;
        register struct te_softc *sc = &te_softc[teunit];
 
        if (bp == &ctmbuf[TMUNIT(bp->b_dev)]) {
        register struct te_softc *sc = &te_softc[teunit];
 
        if (bp == &ctmbuf[TMUNIT(bp->b_dev)]) {
@@ -751,7 +803,7 @@ tmreset(uban)
                        printf("<%d>", (um->um_ubinfo>>28)&0xf);
                        ubadone(um);
                }
                        printf("<%d>", (um->um_ubinfo>>28)&0xf);
                        ubadone(um);
                }
-               ((struct device *)(um->um_addr))->tmcs = TM_DCLR;
+               ((struct tmdevice *)(um->um_addr))->tmcs = TM_DCLR;
                for (teunit = 0; teunit < NTE; teunit++) {
                        if ((ui = tedinfo[teunit]) == 0 || ui->ui_mi != um ||
                            ui->ui_alive == 0)
                for (teunit = 0; teunit < NTE; teunit++) {
                        if ((ui = tedinfo[teunit]) == 0 || ui->ui_mi != um ||
                            ui->ui_alive == 0)
@@ -764,7 +816,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);
        }
@@ -848,7 +901,7 @@ tmdump()
 {
        register struct uba_device *ui;
        register struct uba_regs *up;
 {
        register struct uba_device *ui;
        register struct uba_regs *up;
-       register struct device *addr;
+       register struct tmdevice *addr;
        int blk, num;
        int start;
 
        int blk, num;
        int start;
 
@@ -861,7 +914,7 @@ tmdump()
        up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba;
        ubainit(up);
        DELAY(1000000);
        up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba;
        ubainit(up);
        DELAY(1000000);
-       addr = (struct device *)ui->ui_physaddr;
+       addr = (struct tmdevice *)ui->ui_physaddr;
        tmwait(addr);
        addr->tmcs = TM_DCLR | TM_GO;
        while (num > 0) {
        tmwait(addr);
        addr->tmcs = TM_DCLR | TM_GO;
        while (num > 0) {
@@ -882,7 +935,7 @@ tmdump()
 
 tmdwrite(dbuf, num, addr, up)
        register dbuf, num;
 
 tmdwrite(dbuf, num, addr, up)
        register dbuf, num;
-       register struct device *addr;
+       register struct tmdevice *addr;
        struct uba_regs *up;
 {
        register struct pte *io;
        struct uba_regs *up;
 {
        register struct pte *io;
@@ -900,7 +953,7 @@ tmdwrite(dbuf, num, addr, up)
 }
 
 tmwait(addr)
 }
 
 tmwait(addr)
-       register struct device *addr;
+       register struct tmdevice *addr;
 {
        register s;
 
 {
        register s;
 
@@ -910,7 +963,7 @@ tmwait(addr)
 }
 
 tmeof(addr)
 }
 
 tmeof(addr)
-       struct device *addr;
+       struct tmdevice *addr;
 {
 
        tmwait(addr);
 {
 
        tmwait(addr);