X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/e320a1c9953020eb902875c8df655d636d115a93..de59ccc2375aad4c9f0ff41f3291584ead755f15:/usr/src/sys/vax/uba/tm.c diff --git a/usr/src/sys/vax/uba/tm.c b/usr/src/sys/vax/uba/tm.c index e4d5145aa6..ec16ede411 100644 --- a/usr/src/sys/vax/uba/tm.c +++ b/usr/src/sys/vax/uba/tm.c @@ -1,7 +1,8 @@ -/* tm.c 4.31 81/04/03 */ +/* tm.c 4.48 82/05/27 */ #include "te.h" -#if NTM > 0 +#include "ts.h" +#if NTE > 0 /* * 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 */ -} 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 @@ -123,8 +126,9 @@ tmprobe(reg) #ifdef lint br = 0; cvec = br; br = cvec; + tmintr(0); #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 @@ -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. */ - if (badaddr((caddr_t)&((struct device *)reg)->tmrd, 2)) + if (badaddr((caddr_t)&((struct tmdevice *)reg)->tmrd, 2)) return (0); return (1); } @@ -164,7 +168,6 @@ tmslave(ui, reg) tmattach(ui) struct uba_device *ui; { - /* * 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; } +int tmtimer(); /* * 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; + int s; teunit = TEUNIT(dev); if (teunit>=NTE || (sc = &te_softc[teunit])->sc_openf || @@ -206,13 +211,19 @@ get: 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; } @@ -221,6 +232,13 @@ get: 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; + register int s; bp = &ctmbuf[TMUNIT(dev)]; - (void) spl5(); + s = spl5(); 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; - (void) spl0(); + splx(s); 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 s; /* * 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; /* @@ -317,7 +338,6 @@ tmstrategy(bp) * 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 @@ -332,7 +352,7 @@ tmstrategy(bp) */ 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 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; @@ -364,7 +384,7 @@ loop: * 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; @@ -373,7 +393,7 @@ loop: * 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 @@ -389,8 +409,19 @@ loop: */ 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; @@ -446,6 +477,7 @@ loop: tmgapsdcnt++; sc->sc_lastcmd = TM_RCOM; /* will serve */ #endif + sc->sc_timo = 60; /* premature, but should serve */ (void) ubago(ui); return; } @@ -462,6 +494,7 @@ loop: 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 /* @@ -502,7 +535,7 @@ next: 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); @@ -518,7 +551,7 @@ tmintr(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; @@ -527,20 +560,23 @@ tmintr(tm11) 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 (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; @@ -665,12 +701,28 @@ opcont: 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); - 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)]) { @@ -751,7 +803,7 @@ tmreset(uban) 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) @@ -764,7 +816,8 @@ tmreset(uban) 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); } @@ -833,7 +886,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_type = MI_ISTM; + mtget.mt_type = MT_ISTM; if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) u.u_error = EFAULT; return; @@ -848,7 +901,7 @@ tmdump() { register struct uba_device *ui; register struct uba_regs *up; - register struct device *addr; + register struct tmdevice *addr; int blk, num; int start; @@ -861,7 +914,7 @@ tmdump() 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) { @@ -882,7 +935,7 @@ tmdump() tmdwrite(dbuf, num, addr, up) register dbuf, num; - register struct device *addr; + register struct tmdevice *addr; struct uba_regs *up; { register struct pte *io; @@ -900,7 +953,7 @@ tmdwrite(dbuf, num, addr, up) } tmwait(addr) - register struct device *addr; + register struct tmdevice *addr; { register s; @@ -910,7 +963,7 @@ tmwait(addr) } tmeof(addr) - struct device *addr; + struct tmdevice *addr; { tmwait(addr);