1*3095Swnj /* tm.c 4.24 03/08/81 */ 21919Swnj 32709Swnj #include "te.h" 42630Swnj #if NTM > 0 52670Swnj int tmgapsdcnt; /* DEBUG */ 61919Swnj /* 72630Swnj * TM11/TE10 tape driver 82471Swnj * 9*3095Swnj * TODO: 10*3095Swnj * test driver with more than one slave 11*3095Swnj * test driver with more than one controller 12*3095Swnj * test reset code 13*3095Swnj * test rewinds without hanging in driver 14*3095Swnj * what happens if you offline tape during rewind? 15*3095Swnj * test using file system on tape 161919Swnj */ 171919Swnj #include "../h/param.h" 181919Swnj #include "../h/buf.h" 191919Swnj #include "../h/dir.h" 201919Swnj #include "../h/conf.h" 211919Swnj #include "../h/user.h" 221919Swnj #include "../h/file.h" 231919Swnj #include "../h/map.h" 241919Swnj #include "../h/pte.h" 252574Swnj #include "../h/vm.h" 262982Swnj #include "../h/ubareg.h" 272982Swnj #include "../h/ubavar.h" 281919Swnj #include "../h/mtio.h" 291919Swnj #include "../h/ioctl.h" 302363Swnj #include "../h/cmap.h" 312396Swnj #include "../h/cpu.h" 321919Swnj 332396Swnj #include "../h/tmreg.h" 341919Swnj 35*3095Swnj /* 36*3095Swnj * There is a ctmbuf per tape controller. 37*3095Swnj * It is used as the token to pass to the internal routines 38*3095Swnj * to execute tape ioctls, and also acts as a lock on the slaves 39*3095Swnj * on the controller, since there is only one per controller. 40*3095Swnj * In particular, when the tape is rewinding on close we release 41*3095Swnj * the user process but any further attempts to use the tape drive 42*3095Swnj * before the rewind completes will hang waiting for ctmbuf. 43*3095Swnj */ 44*3095Swnj struct buf ctmbuf[NTM]; 451919Swnj 46*3095Swnj /* 47*3095Swnj * Raw tape operations use rtmbuf. The driver 48*3095Swnj * notices when rtmbuf is being used and allows the user 49*3095Swnj * program to continue after errors and read records 50*3095Swnj * not of the standard length (BSIZE). 51*3095Swnj */ 52*3095Swnj struct buf rtmbuf[NTM]; 53*3095Swnj 54*3095Swnj /* 55*3095Swnj * Driver unibus interface routines and variables. 56*3095Swnj */ 572608Swnj int tmprobe(), tmslave(), tmattach(), tmdgo(), tmintr(); 582982Swnj struct uba_ctlr *tmminfo[NTM]; 59*3095Swnj struct uba_device *tedinfo[NTE]; 60*3095Swnj struct buf teutab[NTE]; 61*3095Swnj short tetotm[NTE]; 622458Swnj u_short tmstd[] = { 0772520, 0 }; 632396Swnj struct uba_driver tmdriver = 64*3095Swnj { tmprobe, tmslave, tmattach, tmdgo, tmstd, "te", tedinfo, "tm", tmminfo, 0 }; 651919Swnj 661919Swnj /* bits in minor device */ 67*3095Swnj #define TEUNIT(dev) (minor(dev)&03) 68*3095Swnj #define TMUNIT(dev) (tetotm[TEUNIT(dev)]) 691919Swnj #define T_NOREWIND 04 701919Swnj #define T_1600BPI 08 711919Swnj 721919Swnj #define INF (daddr_t)1000000L 731919Swnj 742608Swnj /* 752608Swnj * Software state per tape transport. 76*3095Swnj * 77*3095Swnj * 1. A tape drive is a unique-open device; we refuse opens when it is already. 78*3095Swnj * 2. We keep track of the current position on a block tape and seek 79*3095Swnj * before operations by forward/back spacing if necessary. 80*3095Swnj * 3. We remember if the last operation was a write on a tape, so if a tape 81*3095Swnj * is open read write and the last thing done is a write we can 82*3095Swnj * write a standard end of tape mark (two eofs). 83*3095Swnj * 4. We remember the status registers after the last command, using 84*3095Swnj * then internally and returning them to the SENSE ioctl. 85*3095Swnj * 5. We remember the last density the tape was used at. If it is 86*3095Swnj * not a BOT when we start using it and we are writing, we don't 87*3095Swnj * let the density be changed. 882608Swnj */ 89*3095Swnj struct te_softc { 902608Swnj char sc_openf; /* lock against multiple opens */ 912608Swnj char sc_lastiow; /* last op was a write */ 922608Swnj daddr_t sc_blkno; /* block number, for block device tape */ 93*3095Swnj daddr_t sc_nxrec; /* position of end of tape, if known */ 942608Swnj u_short sc_erreg; /* copy of last erreg */ 952608Swnj u_short sc_dsreg; /* copy of last dsreg */ 962608Swnj short sc_resid; /* copy of last bc */ 972928Swnj #ifdef notdef 982670Swnj short sc_lastcmd; /* last command to handle direction changes */ 992928Swnj #endif 100*3095Swnj u_short sc_dens; /* prototype command with density info */ 101*3095Swnj } te_softc[NTM]; 1021919Swnj 1032608Swnj /* 104*3095Swnj * States for um->um_tab.b_active, the per controller state flag. 105*3095Swnj * This is used to sequence control in the driver. 1062608Swnj */ 1071919Swnj #define SSEEK 1 /* seeking */ 1081919Swnj #define SIO 2 /* doing seq i/o */ 1091919Swnj #define SCOM 3 /* sending control command */ 1102608Swnj #define SREW 4 /* sending a drive rewind */ 1111919Swnj 1122426Skre /* 1132426Skre * Determine if there is a controller for 1142426Skre * a tm at address reg. Our goal is to make the 1152426Skre * device interrupt. 1162426Skre */ 1172608Swnj tmprobe(reg) 1182396Swnj caddr_t reg; 1192396Swnj { 120*3095Swnj register int br, cvec; /* must be r11,r10; value-result */ 1212426Skre 1222608Swnj #ifdef lint 1232608Swnj br = 0; br = cvec; cvec = br; 1242608Swnj #endif 1252608Swnj ((struct device *)reg)->tmcs = TM_IE; 1262396Swnj /* 1272630Swnj * If this is a tm11, it ought to have interrupted 1282396Swnj * by now, if it isn't (ie: it is a ts04) then we just 1292458Swnj * hope that it didn't interrupt, so autoconf will ignore it. 1302458Swnj * Just in case, we will reference one 1312396Swnj * of the more distant registers, and hope for a machine 1322458Swnj * check, or similar disaster if this is a ts. 1332471Swnj * 1342471Swnj * Note: on an 11/780, badaddr will just generate 1352471Swnj * a uba error for a ts; but our caller will notice that 1362471Swnj * so we won't check for it. 1372396Swnj */ 1382396Swnj if (badaddr(&((struct device *)reg)->tmrd, 2)) 1392458Swnj return (0); 1402458Swnj return (1); 1412396Swnj } 1422396Swnj 1432608Swnj /* 1442608Swnj * Due to a design flaw, we cannot ascertain if the tape 1452608Swnj * exists or not unless it is on line - ie: unless a tape is 1462608Swnj * mounted. This is too servere a restriction to bear, 1472608Swnj * so all units are assumed to exist. 1482608Swnj */ 1492608Swnj /*ARGSUSED*/ 1502574Swnj tmslave(ui, reg) 1512982Swnj struct uba_device *ui; 1522396Swnj caddr_t reg; 1532396Swnj { 1542458Swnj 1552458Swnj return (1); 1562396Swnj } 1572396Swnj 1582608Swnj /* 159*3095Swnj * Record attachment of the unit to the controller. 1602608Swnj */ 1612608Swnj /*ARGSUSED*/ 1622608Swnj tmattach(ui) 1632982Swnj struct uba_device *ui; 1642608Swnj { 1652608Swnj 166*3095Swnj /* 167*3095Swnj * Tetotm is used in TMUNIT to index the ctmbuf and rtmbuf 168*3095Swnj * arrays given a te unit number. 169*3095Swnj */ 170*3095Swnj tetotm[ui->ui_unit] = ui->ui_mi->um_ctlr; 1712608Swnj } 1722608Swnj 1732608Swnj /* 1742608Swnj * Open the device. Tapes are unique open 1752608Swnj * devices, so we refuse if it is already open. 1762608Swnj * We also check that a tape is available, and 177*3095Swnj * don't block waiting here; if you want to wait 178*3095Swnj * for a tape you should timeout in user code. 1792608Swnj */ 1801919Swnj tmopen(dev, flag) 1811919Swnj dev_t dev; 1821919Swnj int flag; 1831919Swnj { 184*3095Swnj register int teunit; 1852982Swnj register struct uba_device *ui; 186*3095Swnj register struct te_softc *sc; 187*3095Swnj int dens; 1881919Swnj 189*3095Swnj teunit = TEUNIT(dev); 190*3095Swnj if (teunit>=NTE || (sc = &te_softc[teunit])->sc_openf || 191*3095Swnj (ui = tedinfo[teunit]) == 0 || ui->ui_alive == 0) { 1922608Swnj u.u_error = ENXIO; 1931919Swnj return; 1941919Swnj } 1952608Swnj tmcommand(dev, TM_SENSE, 1); 196*3095Swnj dens = TM_IE | TM_GO | (ui->ui_slave << 8); 197*3095Swnj if ((minor(dev) & T_1600BPI) == 0) 198*3095Swnj dens |= TM_D800; 199*3095Swnj if ((sc->sc_erreg&(TMER_SELR|TMER_TUR)) != (TMER_SELR|TMER_TUR) || 200*3095Swnj (sc->sc_erreg&TMER_BOT) == 0 && (flag&FWRITE) && 201*3095Swnj dens != sc->sc_dens || 202*3095Swnj (flag&(FREAD|FWRITE)) == FWRITE && sc->sc_erreg&TMER_WRL) { 203*3095Swnj /* 204*3095Swnj * Not online or density switch in mid-tape or write locked. 205*3095Swnj */ 2062471Swnj u.u_error = EIO; 2072608Swnj return; 2081919Swnj } 2092608Swnj sc->sc_openf = 1; 2102471Swnj sc->sc_blkno = (daddr_t)0; 2112471Swnj sc->sc_nxrec = INF; 2122608Swnj sc->sc_lastiow = 0; 213*3095Swnj sc->sc_dens = dens; 2141919Swnj } 2151919Swnj 2162608Swnj /* 2172608Swnj * Close tape device. 2182608Swnj * 2192608Swnj * If tape was open for writing or last operation was 2202608Swnj * a write, then write two EOF's and backspace over the last one. 2212608Swnj * Unless this is a non-rewinding special file, rewind the tape. 2222608Swnj * Make the tape available to others. 2232608Swnj */ 2241919Swnj tmclose(dev, flag) 2251919Swnj register dev_t dev; 2261919Swnj register flag; 2271919Swnj { 228*3095Swnj register struct te_softc *sc = &te_softc[TEUNIT(dev)]; 2291919Swnj 2302608Swnj if (flag == FWRITE || (flag&FWRITE) && sc->sc_lastiow) { 2312608Swnj tmcommand(dev, TM_WEOF, 1); 2322608Swnj tmcommand(dev, TM_WEOF, 1); 2332608Swnj tmcommand(dev, TM_SREV, 1); 2341919Swnj } 2351919Swnj if ((minor(dev)&T_NOREWIND) == 0) 236*3095Swnj /* 237*3095Swnj * 0 count means don't hang waiting for rewind complete 238*3095Swnj * rather ctmbuf stays busy until the operation completes 239*3095Swnj * preventing further opens from completing by 240*3095Swnj * preventing a TM_SENSE from completing. 241*3095Swnj */ 242*3095Swnj tmcommand(dev, TM_REW, 0); 2432471Swnj sc->sc_openf = 0; 2441919Swnj } 2451919Swnj 2462608Swnj /* 2472608Swnj * Execute a command on the tape drive 2482608Swnj * a specified number of times. 2492608Swnj */ 2502574Swnj tmcommand(dev, com, count) 2511919Swnj dev_t dev; 2521919Swnj int com, count; 2531919Swnj { 2541919Swnj register struct buf *bp; 2551919Swnj 2562608Swnj bp = &ctmbuf[TMUNIT(dev)]; 2571919Swnj (void) spl5(); 2581919Swnj while (bp->b_flags&B_BUSY) { 259*3095Swnj /* 260*3095Swnj * This special check is because B_BUSY never 261*3095Swnj * gets cleared in the non-waiting rewind case. 262*3095Swnj */ 263*3095Swnj if (bp->b_command == TM_REW && bp->b_repcnt == 0 && 264*3095Swnj (bp->b_flags&B_DONE)) 265*3095Swnj break; 2661919Swnj bp->b_flags |= B_WANTED; 2671919Swnj sleep((caddr_t)bp, PRIBIO); 2681919Swnj } 2691919Swnj bp->b_flags = B_BUSY|B_READ; 2701919Swnj (void) spl0(); 2711919Swnj bp->b_dev = dev; 2721919Swnj bp->b_repcnt = -count; 2731919Swnj bp->b_command = com; 2741919Swnj bp->b_blkno = 0; 2751919Swnj tmstrategy(bp); 276*3095Swnj /* 277*3095Swnj * In case of rewind from close, don't wait. 278*3095Swnj * This is the only case where count can be 0. 279*3095Swnj */ 280*3095Swnj if (count == 0) 281*3095Swnj return; 2821919Swnj iowait(bp); 2831919Swnj if (bp->b_flags&B_WANTED) 2841919Swnj wakeup((caddr_t)bp); 2851919Swnj bp->b_flags &= B_ERROR; 2861919Swnj } 2871919Swnj 2882608Swnj /* 289*3095Swnj * Queue a tape operation. 2902608Swnj */ 2911919Swnj tmstrategy(bp) 2921919Swnj register struct buf *bp; 2931919Swnj { 294*3095Swnj int teunit = TEUNIT(bp->b_dev); 2952982Swnj register struct uba_ctlr *um; 2962608Swnj register struct buf *dp; 297*3095Swnj register struct te_softc *sc = &te_softc[teunit]; 2981919Swnj 2992608Swnj /* 3002608Swnj * Put transfer at end of unit queue 3012608Swnj */ 302*3095Swnj dp = &teutab[teunit]; 3031919Swnj bp->av_forw = NULL; 3041919Swnj (void) spl5(); 3052608Swnj if (dp->b_actf == NULL) { 3062608Swnj dp->b_actf = bp; 3072608Swnj /* 3082608Swnj * Transport not already active... 3092608Swnj * put at end of controller queue. 3102608Swnj */ 3112608Swnj dp->b_forw = NULL; 312*3095Swnj um = tedinfo[teunit]->ui_mi; 3132608Swnj if (um->um_tab.b_actf == NULL) 3142608Swnj um->um_tab.b_actf = dp; 3152608Swnj else 3162608Swnj um->um_tab.b_actl->b_forw = dp; 3172608Swnj um->um_tab.b_actl = dp; 3182608Swnj } else 3192608Swnj dp->b_actl->av_forw = bp; 3202608Swnj dp->b_actl = bp; 3212608Swnj /* 3222608Swnj * If the controller is not busy, get 3232608Swnj * it going. 3242608Swnj */ 3252608Swnj if (um->um_tab.b_active == 0) 3262608Swnj tmstart(um); 3271919Swnj (void) spl0(); 3281919Swnj } 3291919Swnj 3302608Swnj /* 3312608Swnj * Start activity on a tm controller. 3322608Swnj */ 3332608Swnj tmstart(um) 3342982Swnj register struct uba_ctlr *um; 3351919Swnj { 3362608Swnj register struct buf *bp, *dp; 3372608Swnj register struct device *addr = (struct device *)um->um_addr; 338*3095Swnj register struct te_softc *sc; 3392982Swnj register struct uba_device *ui; 340*3095Swnj int teunit, cmd; 3412471Swnj daddr_t blkno; 3421919Swnj 3432608Swnj /* 3442608Swnj * Look for an idle transport on the controller. 3452608Swnj */ 3461919Swnj loop: 3472608Swnj if ((dp = um->um_tab.b_actf) == NULL) 3481919Swnj return; 3492608Swnj if ((bp = dp->b_actf) == NULL) { 3502608Swnj um->um_tab.b_actf = dp->b_forw; 3512608Swnj goto loop; 3522608Swnj } 353*3095Swnj teunit = TEUNIT(bp->b_dev); 354*3095Swnj ui = tedinfo[teunit]; 3552608Swnj /* 3562608Swnj * Record pre-transfer status (e.g. for TM_SENSE) 3572608Swnj */ 358*3095Swnj sc = &te_softc[teunit]; 3592608Swnj addr = (struct device *)um->um_addr; 3602608Swnj addr->tmcs = (ui->ui_slave << 8); 3612471Swnj sc->sc_dsreg = addr->tmcs; 3622471Swnj sc->sc_erreg = addr->tmer; 3632471Swnj sc->sc_resid = addr->tmbc; 3642608Swnj /* 3652608Swnj * Default is that last command was NOT a write command; 3662608Swnj * if we do a write command we will notice this in tmintr(). 3672608Swnj */ 3682608Swnj sc->sc_lastiow = 1; 3692608Swnj if (sc->sc_openf < 0 || (addr->tmcs&TM_CUR) == 0) { 3702608Swnj /* 371*3095Swnj * Have had a hard error on a non-raw tape 372*3095Swnj * or the tape unit is now unavailable 373*3095Swnj * (e.g. taken off line). 3742608Swnj */ 3752608Swnj bp->b_flags |= B_ERROR; 3761919Swnj goto next; 3771919Swnj } 378*3095Swnj if (bp == &ctmbuf[TMUNIT(bp->b_dev)]) { 379*3095Swnj /* 380*3095Swnj * Execute control operation with the specified count. 381*3095Swnj */ 3822608Swnj if (bp->b_command == TM_SENSE) 3832608Swnj goto next; 3842608Swnj um->um_tab.b_active = 3852608Swnj bp->b_command == TM_REW ? SREW : SCOM; 3862608Swnj if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV) 3872608Swnj addr->tmbc = bp->b_repcnt; 3882670Swnj goto dobpcmd; 3892608Swnj } 3902608Swnj /* 391*3095Swnj * The following checks handle boundary cases for operation 392*3095Swnj * on non-raw tapes. On raw tapes the initialization of 393*3095Swnj * sc->sc_nxrec by tmphys causes them to be skipped normally 394*3095Swnj * (except in the case of retries). 395*3095Swnj */ 396*3095Swnj if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) { 397*3095Swnj /* 398*3095Swnj * Can't read past known end-of-file. 399*3095Swnj */ 400*3095Swnj bp->b_flags |= B_ERROR; 401*3095Swnj bp->b_error = ENXIO; 402*3095Swnj goto next; 403*3095Swnj } 404*3095Swnj if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && 405*3095Swnj bp->b_flags&B_READ) { 406*3095Swnj /* 407*3095Swnj * Reading at end of file returns 0 bytes. 408*3095Swnj */ 409*3095Swnj bp->b_resid = bp->b_bcount; 410*3095Swnj clrbuf(bp); 411*3095Swnj goto next; 412*3095Swnj } 413*3095Swnj if ((bp->b_flags&B_READ) == 0) 414*3095Swnj /* 415*3095Swnj * Writing sets EOF 416*3095Swnj */ 417*3095Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1; 418*3095Swnj /* 4192608Swnj * If the data transfer command is in the correct place, 4202608Swnj * set up all the registers except the csr, and give 4212608Swnj * control over to the UNIBUS adapter routines, to 4222608Swnj * wait for resources to start the i/o. 4232608Swnj */ 4242471Swnj if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) { 4252396Swnj addr->tmbc = -bp->b_bcount; 4261919Swnj if ((bp->b_flags&B_READ) == 0) { 4272471Swnj if (um->um_tab.b_errcnt) 428*3095Swnj cmd = TM_WIRG; 4291919Swnj else 430*3095Swnj cmd = TM_WCOM; 4311919Swnj } else 432*3095Swnj cmd = TM_RCOM; 4332471Swnj um->um_tab.b_active = SIO; 434*3095Swnj um->um_cmd = sc->sc_dens|cmd; 4352928Swnj #ifdef notdef 4362670Swnj if (tmreverseop(sc->sc_lastcmd)) 437*3095Swnj while (addr->tmer & TMER_SDWN) 4382670Swnj tmgapsdcnt++; 4392670Swnj sc->sc_lastcmd = TM_RCOM; /* will serve */ 4402928Swnj #endif 4412574Swnj ubago(ui); 4421919Swnj return; 4431919Swnj } 4442608Swnj /* 445*3095Swnj * Tape positioned incorrectly; 446*3095Swnj * set to seek forwards or backwards to the correct spot. 447*3095Swnj * This happens for raw tapes only on error retries. 4482608Swnj */ 4492471Swnj um->um_tab.b_active = SSEEK; 4501919Swnj if (blkno < dbtofsb(bp->b_blkno)) { 4512670Swnj bp->b_command = TM_SFORW; 4522396Swnj addr->tmbc = blkno - dbtofsb(bp->b_blkno); 4531919Swnj } else { 4542670Swnj bp->b_command = TM_SREV; 4552396Swnj addr->tmbc = dbtofsb(bp->b_blkno) - blkno; 4561919Swnj } 4572670Swnj dobpcmd: 4582928Swnj #ifdef notdef 459*3095Swnj /* 460*3095Swnj * It is strictly necessary to wait for the tape 461*3095Swnj * to stop before changing directions, but the TC11 462*3095Swnj * handles this for us. 463*3095Swnj */ 4642670Swnj if (tmreverseop(sc->sc_lastcmd) != tmreverseop(bp->b_command)) 4652670Swnj while (addr->tmer & TM_SDWN) 4662670Swnj tmgapsdcnt++; 4672670Swnj sc->sc_lastcmd = bp->b_command; 4682928Swnj #endif 469*3095Swnj /* 470*3095Swnj * Do the command in bp. 471*3095Swnj */ 472*3095Swnj addr->tmcs = (sc->sc_dens | bp->b_command); 4731919Swnj return; 4741919Swnj 4751919Swnj next: 4762608Swnj /* 4772608Swnj * Done with this operation due to error or 4782608Swnj * the fact that it doesn't do anything. 4792608Swnj * Release UBA resources (if any), dequeue 4802608Swnj * the transfer and continue processing this slave. 4812608Swnj */ 4822608Swnj if (um->um_ubinfo) 4832617Swnj ubadone(um); 4842608Swnj um->um_tab.b_errcnt = 0; 4852608Swnj dp->b_actf = bp->av_forw; 4861919Swnj iodone(bp); 4871919Swnj goto loop; 4881919Swnj } 4891919Swnj 4902608Swnj /* 4912608Swnj * The UNIBUS resources we needed have been 4922608Swnj * allocated to us; start the device. 4932608Swnj */ 4942574Swnj tmdgo(um) 4952982Swnj register struct uba_ctlr *um; 4961919Swnj { 4972574Swnj register struct device *addr = (struct device *)um->um_addr; 4982471Swnj 4992574Swnj addr->tmba = um->um_ubinfo; 5002574Swnj addr->tmcs = um->um_cmd | ((um->um_ubinfo >> 12) & 0x30); 5012396Swnj } 5022396Swnj 5032608Swnj /* 5042608Swnj * Tm interrupt routine. 5052608Swnj */ 5062471Swnj /*ARGSUSED*/ 5072630Swnj tmintr(tm11) 5082630Swnj int tm11; 5092396Swnj { 5102608Swnj struct buf *dp; 5111919Swnj register struct buf *bp; 5122982Swnj register struct uba_ctlr *um = tmminfo[tm11]; 513*3095Swnj register struct device *addr; 514*3095Swnj register struct te_softc *sc; 515*3095Swnj int teunit; 5161919Swnj register state; 5171919Swnj 518*3095Swnj if ((dp = um->um_tab.b_actf) == NULL) 519*3095Swnj return; 520*3095Swnj bp = dp->b_actf; 521*3095Swnj teunit = TEUNIT(bp->b_dev); 522*3095Swnj addr = (struct device *)tedinfo[teunit]->ui_addr; 5232608Swnj /* 5242608Swnj * If last command was a rewind, and tape is still 5252608Swnj * rewinding, wait for the rewind complete interrupt. 5262608Swnj */ 5272608Swnj if (um->um_tab.b_active == SREW) { 5282608Swnj um->um_tab.b_active = SCOM; 529*3095Swnj if (addr->tmer&TMER_RWS) 5302608Swnj return; 5311919Swnj } 5322608Swnj /* 5332608Swnj * An operation completed... record status 5342608Swnj */ 535*3095Swnj sc = &te_softc[teunit]; 5362471Swnj sc->sc_dsreg = addr->tmcs; 5372471Swnj sc->sc_erreg = addr->tmer; 5382471Swnj sc->sc_resid = addr->tmbc; 5391919Swnj if ((bp->b_flags & B_READ) == 0) 5402608Swnj sc->sc_lastiow = 1; 5412471Swnj state = um->um_tab.b_active; 5422471Swnj um->um_tab.b_active = 0; 5432608Swnj /* 5442608Swnj * Check for errors. 5452608Swnj */ 5462608Swnj if (addr->tmcs&TM_ERR) { 547*3095Swnj while (addr->tmer & TMER_SDWN) 5481919Swnj ; /* await settle down */ 5492608Swnj /* 550*3095Swnj * If we hit the end of the tape file, update our position. 5512608Swnj */ 552*3095Swnj if (addr->tmer&TMER_EOF) { 5532608Swnj tmseteof(bp); /* set blkno and nxrec */ 5542608Swnj state = SCOM; /* force completion */ 5552608Swnj /* 5562608Swnj * Stuff bc so it will be unstuffed correctly 5572608Swnj * later to get resid. 5582608Swnj */ 5592396Swnj addr->tmbc = -bp->b_bcount; 5602608Swnj goto opdone; 5611919Swnj } 5622608Swnj /* 563*3095Swnj * If we were reading raw tape and the only error was that the 564*3095Swnj * record was too long, then we don't consider this an error. 5652608Swnj */ 566*3095Swnj if (bp == &rtmbuf[TMUNIT(bp->b_dev)] && (bp->b_flags&B_READ) && 567*3095Swnj (addr->tmer&(TMER_HARD|TMER_SOFT)) == TMER_RLE) 5682608Swnj goto ignoreerr; 5692608Swnj /* 5702608Swnj * If error is not hard, and this was an i/o operation 5712608Swnj * retry up to 8 times. 5722608Swnj */ 573*3095Swnj if ((addr->tmer&TMER_HARD)==0 && state==SIO) { 5742471Swnj if (++um->um_tab.b_errcnt < 7) { 5752471Swnj sc->sc_blkno++; 5762617Swnj ubadone(um); 5772608Swnj goto opcont; 5781919Swnj } 5792608Swnj } else 5802608Swnj /* 5812608Swnj * Hard or non-i/o errors on non-raw tape 5822608Swnj * cause it to close. 5832608Swnj */ 584*3095Swnj if (sc->sc_openf>0 && bp != &rtmbuf[TMUNIT(bp->b_dev)]) 5852608Swnj sc->sc_openf = -1; 5862608Swnj /* 5872608Swnj * Couldn't recover error 5882608Swnj */ 5892928Swnj printf("te%d: hard error bn%d er=%b\n", minor(bp->b_dev)&03, 590*3095Swnj bp->b_blkno, sc->sc_erreg, TMER_BITS); 5911919Swnj bp->b_flags |= B_ERROR; 5922608Swnj goto opdone; 5931919Swnj } 5942608Swnj /* 5952608Swnj * Advance tape control FSM. 5962608Swnj */ 5972608Swnj ignoreerr: 5981919Swnj switch (state) { 5991919Swnj 6001919Swnj case SIO: 6012608Swnj /* 6022608Swnj * Read/write increments tape block number 6032608Swnj */ 6042471Swnj sc->sc_blkno++; 6052608Swnj goto opdone; 6061919Swnj 6071919Swnj case SCOM: 6082608Swnj /* 609*3095Swnj * For forward/backward space record update current position. 6102608Swnj */ 611*3095Swnj if (bp == &ctmbuf[TMUNIT(bp->b_dev)]) 6122608Swnj switch (bp->b_command) { 6131919Swnj 6142608Swnj case TM_SFORW: 6152608Swnj sc->sc_blkno -= bp->b_repcnt; 616*3095Swnj break; 6171919Swnj 6182608Swnj case TM_SREV: 6192608Swnj sc->sc_blkno += bp->b_repcnt; 620*3095Swnj break; 6211919Swnj } 622*3095Swnj goto opdone; 6231919Swnj 6241919Swnj case SSEEK: 6252471Swnj sc->sc_blkno = dbtofsb(bp->b_blkno); 6262608Swnj goto opcont; 6271919Swnj 6281919Swnj default: 6292608Swnj panic("tmintr"); 6302608Swnj } 6312608Swnj opdone: 6322608Swnj /* 6332608Swnj * Reset error count and remove 6342608Swnj * from device queue. 6352608Swnj */ 6362608Swnj um->um_tab.b_errcnt = 0; 6372608Swnj dp->b_actf = bp->av_forw; 6382608Swnj bp->b_resid = -addr->tmbc; 6392617Swnj ubadone(um); 6402608Swnj iodone(bp); 6412608Swnj /* 6422608Swnj * Circulate slave to end of controller 6432608Swnj * queue to give other slaves a chance. 6442608Swnj */ 6452608Swnj um->um_tab.b_actf = dp->b_forw; 6462608Swnj if (dp->b_actf) { 6472608Swnj dp->b_forw = NULL; 6482608Swnj if (um->um_tab.b_actf == NULL) 6492608Swnj um->um_tab.b_actf = dp; 6502608Swnj else 6512608Swnj um->um_tab.b_actl->b_forw = dp; 6522608Swnj um->um_tab.b_actl = dp; 6532608Swnj } 6542608Swnj if (um->um_tab.b_actf == 0) 6551919Swnj return; 6562608Swnj opcont: 6572608Swnj tmstart(um); 6581919Swnj } 6591919Swnj 6601919Swnj tmseteof(bp) 6611919Swnj register struct buf *bp; 6621919Swnj { 663*3095Swnj register int teunit = TEUNIT(bp->b_dev); 6642396Swnj register struct device *addr = 665*3095Swnj (struct device *)tedinfo[teunit]->ui_addr; 666*3095Swnj register struct te_softc *sc = &te_softc[teunit]; 6671919Swnj 668*3095Swnj if (bp == &ctmbuf[TMUNIT(bp->b_dev)]) { 6692471Swnj if (sc->sc_blkno > dbtofsb(bp->b_blkno)) { 6701919Swnj /* reversing */ 6712471Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno) - addr->tmbc; 6722471Swnj sc->sc_blkno = sc->sc_nxrec; 6731919Swnj } else { 6741919Swnj /* spacing forward */ 6752471Swnj sc->sc_blkno = dbtofsb(bp->b_blkno) + addr->tmbc; 6762471Swnj sc->sc_nxrec = sc->sc_blkno - 1; 6771919Swnj } 6781919Swnj return; 6791919Swnj } 6801919Swnj /* eof on read */ 6812471Swnj sc->sc_nxrec = dbtofsb(bp->b_blkno); 6821919Swnj } 6831919Swnj 6841919Swnj tmread(dev) 6852608Swnj dev_t dev; 6861919Swnj { 6871919Swnj 6881919Swnj tmphys(dev); 6892982Swnj if (u.u_error) 6902982Swnj return; 6912608Swnj physio(tmstrategy, &rtmbuf[TMUNIT(dev)], dev, B_READ, minphys); 6921919Swnj } 6931919Swnj 6941919Swnj tmwrite(dev) 6952608Swnj dev_t dev; 6961919Swnj { 6971919Swnj 6981919Swnj tmphys(dev); 6992982Swnj if (u.u_error) 7002982Swnj return; 7012608Swnj physio(tmstrategy, &rtmbuf[TMUNIT(dev)], dev, B_WRITE, minphys); 7021919Swnj } 7031919Swnj 704*3095Swnj /* 705*3095Swnj * Check that a raw device exists. 706*3095Swnj * If it does, set up sc_blkno and sc_nxrec 707*3095Swnj * so that the tape will appear positioned correctly. 708*3095Swnj */ 7091919Swnj tmphys(dev) 7102608Swnj dev_t dev; 7111919Swnj { 712*3095Swnj register int teunit = TEUNIT(dev); 7131919Swnj register daddr_t a; 714*3095Swnj register struct te_softc *sc; 715*3095Swnj register struct uba_device *ui; 7161919Swnj 717*3095Swnj if (teunit >= NTE || (ui=tedinfo[teunit]) == 0 || ui->ui_alive == 0) { 7182982Swnj u.u_error = ENXIO; 7192982Swnj return; 7202982Swnj } 721*3095Swnj sc = &te_softc[teunit]; 7221919Swnj a = dbtofsb(u.u_offset >> 9); 7232471Swnj sc->sc_blkno = a; 7242471Swnj sc->sc_nxrec = a + 1; 7251919Swnj } 7261919Swnj 7272608Swnj tmreset(uban) 7282608Swnj int uban; 7292608Swnj { 7302982Swnj register struct uba_ctlr *um; 731*3095Swnj register tm11, teunit; 7322982Swnj register struct uba_device *ui; 7332608Swnj register struct buf *dp; 7342608Swnj 7352630Swnj for (tm11 = 0; tm11 < NTM; tm11++) { 7362630Swnj if ((um = tmminfo[tm11]) == 0 || um->um_alive == 0 || 7372608Swnj um->um_ubanum != uban) 7382608Swnj continue; 7392928Swnj printf(" tm%d", tm11); 7402608Swnj um->um_tab.b_active = 0; 7412608Swnj um->um_tab.b_actf = um->um_tab.b_actl = 0; 7422608Swnj if (um->um_ubinfo) { 7432608Swnj printf("<%d>", (um->um_ubinfo>>28)&0xf); 7442617Swnj ubadone(um); 7452608Swnj } 7462608Swnj ((struct device *)(um->um_addr))->tmcs = TM_DCLR; 747*3095Swnj for (teunit = 0; teunit < NTE; teunit++) { 748*3095Swnj if ((ui = tedinfo[teunit]) == 0 || ui->ui_mi != um || 749*3095Swnj ui->ui_alive == 0) 7502608Swnj continue; 751*3095Swnj dp = &teutab[teunit]; 7522608Swnj dp->b_active = 0; 7532608Swnj dp->b_forw = 0; 7542608Swnj if (um->um_tab.b_actf == NULL) 7552608Swnj um->um_tab.b_actf = dp; 7562608Swnj else 7572608Swnj um->um_tab.b_actl->b_forw = dp; 7582608Swnj um->um_tab.b_actl = dp; 759*3095Swnj te_softc[teunit].sc_openf = -1; 7602608Swnj } 7612608Swnj tmstart(um); 7622608Swnj } 7632608Swnj } 7642608Swnj 7651919Swnj /*ARGSUSED*/ 7661919Swnj tmioctl(dev, cmd, addr, flag) 7671919Swnj caddr_t addr; 7681919Swnj dev_t dev; 7691919Swnj { 770*3095Swnj int teunit = TEUNIT(dev); 771*3095Swnj register struct te_softc *sc = &te_softc[teunit]; 772*3095Swnj register struct buf *bp = &ctmbuf[TMUNIT(dev)]; 7731919Swnj register callcount; 7741919Swnj int fcount; 7751919Swnj struct mtop mtop; 7761919Swnj struct mtget mtget; 7771919Swnj /* we depend of the values and order of the MT codes here */ 7782608Swnj static tmops[] = 7792608Swnj {TM_WEOF,TM_SFORW,TM_SREV,TM_SFORW,TM_SREV,TM_REW,TM_OFFL,TM_SENSE}; 7801919Swnj 7812608Swnj switch (cmd) { 7821919Swnj case MTIOCTOP: /* tape operation */ 7831919Swnj if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) { 7841919Swnj u.u_error = EFAULT; 7851919Swnj return; 7861919Swnj } 7871919Swnj switch(mtop.mt_op) { 7882608Swnj case MTWEOF: 7891919Swnj callcount = mtop.mt_count; 7902608Swnj fcount = 1; 7912608Swnj break; 7922608Swnj case MTFSF: case MTBSF: 7932608Swnj callcount = mtop.mt_count; 7941919Swnj fcount = INF; 7951919Swnj break; 7961919Swnj case MTFSR: case MTBSR: 7971919Swnj callcount = 1; 7981919Swnj fcount = mtop.mt_count; 7991919Swnj break; 8002324Skre case MTREW: case MTOFFL: case MTNOP: 8011919Swnj callcount = 1; 8021919Swnj fcount = 1; 8031919Swnj break; 8041919Swnj default: 8051919Swnj u.u_error = ENXIO; 8061919Swnj return; 8071919Swnj } 8082608Swnj if (callcount <= 0 || fcount <= 0) { 8091919Swnj u.u_error = ENXIO; 8102608Swnj return; 8112608Swnj } 8122608Swnj while (--callcount >= 0) { 8132574Swnj tmcommand(dev, tmops[mtop.mt_op], fcount); 8141919Swnj if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) && 8152608Swnj bp->b_resid) { 8161919Swnj u.u_error = EIO; 8171919Swnj break; 8181919Swnj } 819*3095Swnj if ((bp->b_flags&B_ERROR) || sc->sc_erreg&TMER_BOT) 8201919Swnj break; 8211919Swnj } 8222608Swnj geterror(bp); 8231919Swnj return; 8241919Swnj case MTIOCGET: 8252471Swnj mtget.mt_dsreg = sc->sc_dsreg; 8262471Swnj mtget.mt_erreg = sc->sc_erreg; 8272471Swnj mtget.mt_resid = sc->sc_resid; 8281919Swnj if (copyout((caddr_t)&mtget, addr, sizeof(mtget))) 8291919Swnj u.u_error = EFAULT; 8301919Swnj return; 8311919Swnj default: 8321919Swnj u.u_error = ENXIO; 8331919Swnj } 8341919Swnj } 8351919Swnj 8361919Swnj #define DBSIZE 20 8371919Swnj 8382363Swnj tmdump() 8392363Swnj { 8402982Swnj register struct uba_device *ui; 8412396Swnj register struct uba_regs *up; 8422396Swnj register struct device *addr; 8432426Skre int blk, num; 8442426Skre int start; 8451919Swnj 8462426Skre start = 0; 8472426Skre num = maxfree; 8482426Skre #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 849*3095Swnj if (tedinfo[0] == 0) 8502887Swnj return (ENXIO); 851*3095Swnj ui = phys(tedinfo[0], struct uba_device *); 8522396Swnj up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba; 8532396Swnj #if VAX780 8542396Swnj if (cpu == VAX_780) 8552396Swnj ubainit(up); 8561919Swnj #endif 8572324Skre DELAY(1000000); 8582396Swnj addr = (struct device *)ui->ui_physaddr; 8592396Swnj tmwait(addr); 8602608Swnj addr->tmcs = TM_DCLR | TM_GO; 8611919Swnj while (num > 0) { 8621919Swnj blk = num > DBSIZE ? DBSIZE : num; 8632396Swnj tmdwrite(start, blk, addr, up); 8641919Swnj start += blk; 8651919Swnj num -= blk; 8661919Swnj } 8672426Skre tmeof(addr); 8682426Skre tmeof(addr); 8692426Skre tmwait(addr); 8702887Swnj if (addr->tmcs&TM_ERR) 8712887Swnj return (EIO); 8722608Swnj addr->tmcs = TM_REW | TM_GO; 8732471Swnj tmwait(addr); 8742363Swnj return (0); 8751919Swnj } 8761919Swnj 8772608Swnj tmdwrite(dbuf, num, addr, up) 8782608Swnj register dbuf, num; 8792396Swnj register struct device *addr; 8802396Swnj struct uba_regs *up; 8811919Swnj { 8822396Swnj register struct pte *io; 8832396Swnj register int npf; 8841928Swnj 8852396Swnj tmwait(addr); 8862396Swnj io = up->uba_map; 8871919Swnj npf = num+1; 8881928Swnj while (--npf != 0) 8892982Swnj *(int *)io++ = (dbuf++ | (1<<UBAMR_DPSHIFT) | UBAMR_MRV); 8902396Swnj *(int *)io = 0; 8912396Swnj addr->tmbc = -(num*NBPG); 8922396Swnj addr->tmba = 0; 8932608Swnj addr->tmcs = TM_WCOM | TM_GO; 8941919Swnj } 8951919Swnj 8962396Swnj tmwait(addr) 8972396Swnj register struct device *addr; 8981919Swnj { 8991928Swnj register s; 9001919Swnj 9011919Swnj do 9022396Swnj s = addr->tmcs; 9032608Swnj while ((s & TM_CUR) == 0); 9041919Swnj } 9051919Swnj 9062396Swnj tmeof(addr) 9072396Swnj struct device *addr; 9081919Swnj { 9091919Swnj 9102396Swnj tmwait(addr); 9112608Swnj addr->tmcs = TM_WEOF | TM_GO; 9121919Swnj } 9131919Swnj #endif 914