141480Smckusick /* 2*63151Sbostic * Copyright (c) 1982, 1990, 1993 3*63151Sbostic * The Regents of the University of California. All rights reserved. 441480Smckusick * 541480Smckusick * %sccs.include.redist.c% 641480Smckusick * 7*63151Sbostic * @(#)ct.c 8.1 (Berkeley) 06/10/93 841480Smckusick */ 941480Smckusick 1041480Smckusick #include "ct.h" 1141480Smckusick #if NCT > 0 1241480Smckusick /* 1341480Smckusick * CS80 cartridge tape driver (9144, 88140, 9145) 1441480Smckusick * 1541480Smckusick * Reminder: 1641480Smckusick * C_CC bit (character count option) when used in the CS/80 command 1741480Smckusick * 'set options' will cause the tape not to stream. 1841480Smckusick * 1941480Smckusick * TODO: 2041480Smckusick * make filesystem compatible 2141480Smckusick * make block mode work according to mtio(4) spec. (if possible) 2241480Smckusick * merge with cs80 disk driver 2341480Smckusick * finish support of 9145 2441480Smckusick */ 2541480Smckusick 2656507Sbostic #include <sys/param.h> 2756507Sbostic #include <sys/buf.h> 2856507Sbostic #include <sys/ioctl.h> 2956507Sbostic #include <sys/mtio.h> 3056507Sbostic #include <sys/tprintf.h> 3156507Sbostic #include <sys/proc.h> 3249132Skarels 3356507Sbostic #include <hp/dev/device.h> 3441480Smckusick 3556507Sbostic #include <hp300/dev/ctreg.h> 3656507Sbostic 3741480Smckusick /* number of eof marks to remember */ 3841480Smckusick #define EOFS 128 3941480Smckusick 4041480Smckusick int ctinit(), ctstart(), ctgo(), ctintr(); 4141480Smckusick struct driver ctdriver = { 4241480Smckusick ctinit, "ct", ctstart, ctgo, ctintr, 4341480Smckusick }; 4441480Smckusick 4541480Smckusick struct ct_softc { 4641480Smckusick struct hp_device *sc_hd; 4741480Smckusick struct ct_iocmd sc_ioc; 4841480Smckusick struct ct_rscmd sc_rsc; 4941480Smckusick struct ct_stat sc_stat; 5041480Smckusick struct ct_ssmcmd sc_ssmc; 5141480Smckusick struct ct_srcmd sc_src; 5241480Smckusick struct ct_soptcmd sc_soptc; 5341480Smckusick struct ct_ulcmd sc_ul; 5441480Smckusick struct ct_wfmcmd sc_wfm; 5541480Smckusick struct ct_clearcmd sc_clear; 5641480Smckusick struct buf *sc_bp; 5741480Smckusick int sc_blkno; 5841480Smckusick int sc_cmd; 5941480Smckusick int sc_resid; 6041480Smckusick char *sc_addr; 6141480Smckusick int sc_flags; 6241480Smckusick short sc_type; 6341480Smckusick short sc_punit; 6449132Skarels tpr_t sc_tpr; 6541480Smckusick struct devqueue sc_dq; 6641480Smckusick int sc_eofp; 6741480Smckusick int sc_eofs[EOFS]; 6841480Smckusick } ct_softc[NCT]; 6941480Smckusick 7041480Smckusick /* flags */ 7141480Smckusick #define CTF_OPEN 0x01 7241480Smckusick #define CTF_ALIVE 0x02 7341480Smckusick #define CTF_WRT 0x04 7441480Smckusick #define CTF_CMD 0x08 7541480Smckusick #define CTF_IO 0x10 7641480Smckusick #define CTF_BEOF 0x20 7741480Smckusick #define CTF_AEOF 0x40 7841480Smckusick #define CTF_EOT 0x80 7941480Smckusick #define CTF_STATWAIT 0x100 8041480Smckusick #define CTF_CANSTREAM 0x200 8141480Smckusick #define CTF_WRTTN 0x400 8241480Smckusick 8341480Smckusick struct ctinfo { 8441480Smckusick short hwid; 8541480Smckusick short punit; 8641480Smckusick char *desc; 8741480Smckusick } ctinfo[] = { 8841480Smckusick CT7946ID, 1, "7946A", 8941480Smckusick CT7912PID, 1, "7912P", 9041480Smckusick CT7914PID, 1, "7914P", 9141480Smckusick CT9144ID, 0, "9144", 9241480Smckusick CT9145ID, 0, "9145", 9341480Smckusick }; 9441480Smckusick int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]); 9541480Smckusick 9641480Smckusick struct buf cttab[NCT]; 9741480Smckusick struct buf ctbuf[NCT]; 9841480Smckusick 9941480Smckusick #define CT_NOREW 4 10041480Smckusick #define CT_STREAM 8 10141480Smckusick #define UNIT(x) (minor(x) & 3) 10241480Smckusick #define ctpunit(x) ((x) & 7) 10341480Smckusick 10441480Smckusick #ifdef DEBUG 10541480Smckusick int ctdebug = 0; 10641480Smckusick #define CDB_FILES 0x01 10741480Smckusick #define CT_BSF 0x02 10841480Smckusick #endif 10941480Smckusick 11041480Smckusick ctinit(hd) 11141480Smckusick register struct hp_device *hd; 11241480Smckusick { 11341480Smckusick register struct ct_softc *sc = &ct_softc[hd->hp_unit]; 11456388Smckusick register struct buf *bp; 11541480Smckusick 11656388Smckusick for (bp = cttab; bp < &cttab[NCT]; bp++) 11756388Smckusick bp->b_actb = &bp->b_actf; 11841480Smckusick sc->sc_hd = hd; 11941480Smckusick sc->sc_punit = ctpunit(hd->hp_flags); 12041480Smckusick if (ctident(sc, hd) < 0) 12141480Smckusick return(0); 12241480Smckusick ctreset(sc, hd); 12341480Smckusick sc->sc_dq.dq_ctlr = hd->hp_ctlr; 12441480Smckusick sc->sc_dq.dq_unit = hd->hp_unit; 12541480Smckusick sc->sc_dq.dq_slave = hd->hp_slave; 12641480Smckusick sc->sc_dq.dq_driver = &ctdriver; 12741480Smckusick sc->sc_flags |= CTF_ALIVE; 12841480Smckusick return(1); 12941480Smckusick } 13041480Smckusick 13141480Smckusick ctident(sc, hd) 13241480Smckusick register struct ct_softc *sc; 13341480Smckusick register struct hp_device *hd; 13441480Smckusick { 13541480Smckusick struct ct_describe desc; 13641480Smckusick u_char stat, cmd[3]; 13741480Smckusick char name[7]; 13841480Smckusick int id, i; 13941480Smckusick 14041480Smckusick /* 14141480Smckusick * Read device id and verify that: 14241480Smckusick * 1. It is a CS80 device 14341480Smckusick * 2. It is one of our recognized tape devices 14441480Smckusick * 3. It has the proper physical unit number 14541480Smckusick */ 14641480Smckusick id = hpibid(hd->hp_ctlr, hd->hp_slave); 14741480Smckusick if ((id & 0x200) == 0) 14841480Smckusick return(-1); 14941480Smckusick for (i = 0; i < nctinfo; i++) 15041480Smckusick if (id == ctinfo[i].hwid) 15141480Smckusick break; 15241480Smckusick if (i == nctinfo || sc->sc_punit != ctinfo[i].punit) 15341480Smckusick return(-1); 15441480Smckusick id = i; 15541480Smckusick 15641480Smckusick /* 15741480Smckusick * Collect device description. 15841480Smckusick * Right now we only need this to differentiate 7945 from 7946. 15941480Smckusick * Note that we always issue the describe command to unit 0. 16041480Smckusick */ 16141480Smckusick cmd[0] = C_SUNIT(0); 16241480Smckusick cmd[1] = C_SVOL(0); 16341480Smckusick cmd[2] = C_DESC; 16441480Smckusick hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, cmd, sizeof(cmd)); 16541480Smckusick hpibrecv(hd->hp_ctlr, hd->hp_slave, C_EXEC, &desc, 37); 16641480Smckusick hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); 16741480Smckusick bzero(name, sizeof(name)); 16841480Smckusick if (!stat) { 16941480Smckusick register int n = desc.d_name; 17041480Smckusick for (i = 5; i >= 0; i--) { 17141480Smckusick name[i] = (n & 0xf) + '0'; 17241480Smckusick n >>= 4; 17341480Smckusick } 17441480Smckusick } 17541480Smckusick switch (ctinfo[id].hwid) { 17641480Smckusick case CT7946ID: 17741480Smckusick if (bcmp(name, "079450", 6) == 0) 17841480Smckusick return(-1); /* not really a 7946 */ 17941480Smckusick /* fall into... */ 18041480Smckusick case CT9144ID: 18141480Smckusick case CT9145ID: 18241480Smckusick sc->sc_type = CT9144; 18341480Smckusick sc->sc_flags |= CTF_CANSTREAM; 18441480Smckusick break; 18541480Smckusick 18641480Smckusick case CT7912PID: 18741480Smckusick case CT7914PID: 18841480Smckusick sc->sc_type = CT88140; 18941480Smckusick break; 19041480Smckusick } 19141480Smckusick printf("ct%d: %s %stape\n", hd->hp_unit, ctinfo[id].desc, 19241480Smckusick (sc->sc_flags & CTF_CANSTREAM) ? "streaming " : " "); 19341480Smckusick return(id); 19441480Smckusick } 19541480Smckusick 19641480Smckusick ctreset(sc, hd) 19741480Smckusick register struct ct_softc *sc; 19841480Smckusick register struct hp_device *hd; 19941480Smckusick { 20041480Smckusick u_char stat; 20141480Smckusick 20241480Smckusick sc->sc_clear.unit = C_SUNIT(sc->sc_punit); 20341480Smckusick sc->sc_clear.cmd = C_CLEAR; 20441480Smckusick hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &sc->sc_clear, 20541480Smckusick sizeof(sc->sc_clear)); 20641480Smckusick hpibswait(hd->hp_ctlr, hd->hp_slave); 20741480Smckusick hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); 20841480Smckusick sc->sc_src.unit = C_SUNIT(CTCTLR); 20941480Smckusick sc->sc_src.nop = C_NOP; 21041480Smckusick sc->sc_src.cmd = C_SREL; 21141480Smckusick sc->sc_src.param = C_REL; 21241480Smckusick hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_src, 21341480Smckusick sizeof(sc->sc_src)); 21441480Smckusick hpibswait(hd->hp_ctlr, hd->hp_slave); 21541480Smckusick hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); 21641480Smckusick sc->sc_ssmc.unit = C_SUNIT(sc->sc_punit); 21741480Smckusick sc->sc_ssmc.cmd = C_SSM; 21841480Smckusick sc->sc_ssmc.refm = REF_MASK; 21941480Smckusick sc->sc_ssmc.fefm = FEF_MASK; 22041480Smckusick sc->sc_ssmc.aefm = AEF_MASK; 22141480Smckusick sc->sc_ssmc.iefm = IEF_MASK; 22241480Smckusick hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_ssmc, 22341480Smckusick sizeof(sc->sc_ssmc)); 22441480Smckusick hpibswait(hd->hp_ctlr, hd->hp_slave); 22541480Smckusick hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); 22641480Smckusick sc->sc_soptc.unit = C_SUNIT(sc->sc_punit); 22741480Smckusick sc->sc_soptc.nop = C_NOP; 22841480Smckusick sc->sc_soptc.cmd = C_SOPT; 22941480Smckusick sc->sc_soptc.opt = C_SPAR; 23041480Smckusick hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &sc->sc_soptc, 23141480Smckusick sizeof(sc->sc_soptc)); 23241480Smckusick hpibswait(hd->hp_ctlr, hd->hp_slave); 23341480Smckusick hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat)); 23441480Smckusick } 23541480Smckusick 23641480Smckusick /*ARGSUSED*/ 23749132Skarels ctopen(dev, flag, type, p) 23841480Smckusick dev_t dev; 23949132Skarels int flag, type; 24049132Skarels struct proc *p; 24141480Smckusick { 24241480Smckusick register struct ct_softc *sc = &ct_softc[UNIT(dev)]; 24341480Smckusick u_char stat; 24441480Smckusick int cc; 24541480Smckusick 24641480Smckusick if (UNIT(dev) >= NCT || (sc->sc_flags & CTF_ALIVE) == 0) 24741480Smckusick return(ENXIO); 24841480Smckusick if (sc->sc_flags & CTF_OPEN) 24941480Smckusick return(EBUSY); 25041480Smckusick sc->sc_soptc.unit = C_SUNIT(sc->sc_punit); 25141480Smckusick sc->sc_soptc.nop = C_NOP; 25241480Smckusick sc->sc_soptc.cmd = C_SOPT; 25341480Smckusick if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM)) 25441480Smckusick sc->sc_soptc.opt = C_SPAR | C_IMRPT; 25541480Smckusick else 25641480Smckusick sc->sc_soptc.opt = C_SPAR; 25741480Smckusick /* 25841480Smckusick * Check the return of hpibsend() and hpibswait(). 25941480Smckusick * Drive could be loading/unloading a tape. If not checked, 26041480Smckusick * driver hangs. 26141480Smckusick */ 26241480Smckusick cc = hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 26341480Smckusick C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc)); 26441480Smckusick if (cc != sizeof(sc->sc_soptc)) 26541480Smckusick return(EBUSY); 26641480Smckusick hpibswait(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave); 26741480Smckusick cc = hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, 26841480Smckusick &stat, sizeof(stat)); 26941480Smckusick if (cc != sizeof(stat)) 27041480Smckusick return(EBUSY); 27149132Skarels sc->sc_tpr = tprintf_open(p); 27241480Smckusick sc->sc_flags |= CTF_OPEN; 27341480Smckusick return(0); 27441480Smckusick } 27541480Smckusick 27641480Smckusick /*ARGSUSED*/ 27741480Smckusick ctclose(dev, flag) 27841480Smckusick dev_t dev; 27941480Smckusick { 28041480Smckusick register struct ct_softc *sc = &ct_softc[UNIT(dev)]; 28141480Smckusick 28241480Smckusick if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) && 28341480Smckusick (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */ 28441480Smckusick ctcommand(dev, MTWEOF, 2); 28541480Smckusick ctcommand(dev, MTBSR, 1); 28641480Smckusick if (sc->sc_eofp == EOFS - 1) 28741480Smckusick sc->sc_eofs[EOFS - 1]--; 28841480Smckusick else 28941480Smckusick sc->sc_eofp--; 29041480Smckusick #ifdef DEBUG 29141480Smckusick if(ctdebug & CT_BSF) 29241480Smckusick printf("ct%d: ctclose backup eofs prt %d blk %d\n", 29341480Smckusick UNIT(dev), sc->sc_eofp, sc->sc_eofs[sc->sc_eofp]); 29441480Smckusick #endif 29541480Smckusick } 29641480Smckusick if ((minor(dev) & CT_NOREW) == 0) 29741480Smckusick ctcommand(dev, MTREW, 1); 29841480Smckusick sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN); 29949132Skarels tprintf_close(sc->sc_tpr); 30041480Smckusick #ifdef DEBUG 30141480Smckusick if (ctdebug & CDB_FILES) 30241480Smckusick printf("ctclose: flags %x\n", sc->sc_flags); 30341480Smckusick #endif 30441480Smckusick return(0); /* XXX */ 30541480Smckusick } 30641480Smckusick 30741480Smckusick ctcommand(dev, cmd, cnt) 30841480Smckusick dev_t dev; 30941480Smckusick register int cnt; 31041480Smckusick { 31141480Smckusick register struct ct_softc *sc = &ct_softc[UNIT(dev)]; 31241480Smckusick register struct buf *bp = &ctbuf[UNIT(dev)]; 31341480Smckusick register struct buf *nbp = 0; 31441480Smckusick 31541480Smckusick if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) { 31641480Smckusick cnt = sc->sc_eofs[EOFS - 1] - cnt; 31741480Smckusick ctcommand(dev, MTREW, 1); 31841480Smckusick ctcommand(dev, MTFSF, cnt); 31941480Smckusick cnt = 2; 32041480Smckusick cmd = MTBSR; 32141480Smckusick } 32241480Smckusick 32341480Smckusick if (cmd == MTBSF && sc->sc_eofp - cnt < 0) { 32441480Smckusick cnt = 1; 32541480Smckusick cmd = MTREW; 32641480Smckusick } 32741480Smckusick 32841480Smckusick sc->sc_flags |= CTF_CMD; 32941480Smckusick sc->sc_bp = bp; 33041480Smckusick sc->sc_cmd = cmd; 33141480Smckusick bp->b_dev = dev; 33241480Smckusick if (cmd == MTFSF) { 33341480Smckusick nbp = (struct buf *)geteblk(MAXBSIZE); 33441480Smckusick bp->b_un.b_addr = nbp->b_un.b_addr; 33541480Smckusick bp->b_bcount = MAXBSIZE; 33641480Smckusick } 33741480Smckusick again: 33841480Smckusick bp->b_flags = B_BUSY; 33941480Smckusick if (cmd == MTBSF) { 34041480Smckusick sc->sc_blkno = sc->sc_eofs[sc->sc_eofp]; 34141480Smckusick sc->sc_eofp--; 34241480Smckusick #ifdef DEBUG 34341480Smckusick if (ctdebug & CT_BSF) 34441480Smckusick printf("ct%d: backup eof pos %d blk %d\n", 34541480Smckusick UNIT(dev), sc->sc_eofp, 34641480Smckusick sc->sc_eofs[sc->sc_eofp]); 34741480Smckusick #endif 34841480Smckusick } 34941480Smckusick ctstrategy(bp); 35041480Smckusick iowait(bp); 35141480Smckusick if (--cnt > 0) 35241480Smckusick goto again; 35341480Smckusick bp->b_flags = 0; 35441480Smckusick sc->sc_flags &= ~CTF_CMD; 35541480Smckusick if (nbp) 35641480Smckusick brelse(nbp); 35741480Smckusick } 35841480Smckusick 35941480Smckusick ctstrategy(bp) 36041480Smckusick register struct buf *bp; 36141480Smckusick { 36241480Smckusick register struct buf *dp; 36341480Smckusick register int s, unit; 36441480Smckusick 36541480Smckusick unit = UNIT(bp->b_dev); 36641480Smckusick dp = &cttab[unit]; 36756388Smckusick bp->b_actf = NULL; 36841480Smckusick s = splbio(); 36956388Smckusick bp->b_actb = dp->b_actb; 37056388Smckusick *dp->b_actb = bp; 37156388Smckusick dp->b_actb = &bp->b_actf; 37241480Smckusick if (dp->b_active == 0) { 37341480Smckusick dp->b_active = 1; 37441480Smckusick ctustart(unit); 37541480Smckusick } 37641480Smckusick splx(s); 37741480Smckusick } 37841480Smckusick 37941480Smckusick ctustart(unit) 38041480Smckusick register int unit; 38141480Smckusick { 38241480Smckusick register struct ct_softc *sc = &ct_softc[unit]; 38341480Smckusick register struct buf *bp; 38441480Smckusick 38541480Smckusick bp = cttab[unit].b_actf; 38641480Smckusick sc->sc_addr = bp->b_un.b_addr; 38741480Smckusick sc->sc_resid = bp->b_bcount; 38841480Smckusick if (hpibreq(&sc->sc_dq)) 38941480Smckusick ctstart(unit); 39041480Smckusick } 39141480Smckusick 39241480Smckusick ctstart(unit) 39341480Smckusick register int unit; 39441480Smckusick { 39541480Smckusick register struct ct_softc *sc = &ct_softc[unit]; 39656388Smckusick register struct buf *bp, *dp; 39741480Smckusick register int i; 39841480Smckusick 39941480Smckusick bp = cttab[unit].b_actf; 40041480Smckusick again: 40141480Smckusick if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) { 40241480Smckusick switch(sc->sc_cmd) { 40341480Smckusick 40441480Smckusick case MTFSF: 40541480Smckusick bp->b_flags |= B_READ; 40641480Smckusick goto mustio; 40741480Smckusick 40841480Smckusick case MTBSF: 40941480Smckusick goto gotaddr; 41041480Smckusick 41141480Smckusick case MTOFFL: 41241480Smckusick sc->sc_blkno = 0; 41341480Smckusick sc->sc_ul.unit = C_SUNIT(sc->sc_punit); 41441480Smckusick sc->sc_ul.cmd = C_UNLOAD; 41541480Smckusick hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 41641480Smckusick C_CMD, &sc->sc_ul, sizeof(sc->sc_ul)); 41741480Smckusick break; 41841480Smckusick 41941480Smckusick case MTWEOF: 42041480Smckusick sc->sc_blkno++; 42141480Smckusick sc->sc_flags |= CTF_WRT; 42241480Smckusick sc->sc_wfm.unit = C_SUNIT(sc->sc_punit); 42341480Smckusick sc->sc_wfm.cmd = C_WFM; 42441480Smckusick hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 42541480Smckusick C_CMD, &sc->sc_wfm, sizeof(sc->sc_wfm)); 42641480Smckusick ctaddeof(unit); 42741480Smckusick break; 42841480Smckusick 42941480Smckusick case MTBSR: 43041480Smckusick sc->sc_blkno--; 43141480Smckusick goto gotaddr; 43241480Smckusick 43341480Smckusick case MTFSR: 43441480Smckusick sc->sc_blkno++; 43541480Smckusick goto gotaddr; 43641480Smckusick 43741480Smckusick case MTREW: 43841480Smckusick sc->sc_blkno = 0; 43941480Smckusick #ifdef DEBUG 44041480Smckusick if(ctdebug & CT_BSF) 44141480Smckusick printf("ct%d: clearing eofs\n", unit); 44241480Smckusick #endif 44341480Smckusick for (i=0; i<EOFS; i++) 44441480Smckusick sc->sc_eofs[i] = 0; 44541480Smckusick sc->sc_eofp = 0; 44641480Smckusick 44741480Smckusick gotaddr: 44841480Smckusick sc->sc_ioc.saddr = C_SADDR; 44941480Smckusick sc->sc_ioc.addr0 = 0; 45041480Smckusick sc->sc_ioc.addr = sc->sc_blkno; 45141480Smckusick sc->sc_ioc.unit = C_SUNIT(sc->sc_punit); 45241480Smckusick sc->sc_ioc.nop2 = C_NOP; 45341480Smckusick sc->sc_ioc.slen = C_SLEN; 45441480Smckusick sc->sc_ioc.len = 0; 45541480Smckusick sc->sc_ioc.nop3 = C_NOP; 45641480Smckusick sc->sc_ioc.cmd = C_READ; 45741480Smckusick hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 45841480Smckusick C_CMD, &sc->sc_ioc, sizeof(sc->sc_ioc)); 45941480Smckusick break; 46041480Smckusick } 46141480Smckusick } 46241480Smckusick else { 46341480Smckusick mustio: 46441480Smckusick if ((bp->b_flags & B_READ) && 46541480Smckusick sc->sc_flags & (CTF_BEOF|CTF_EOT)) { 46641480Smckusick #ifdef DEBUG 46741480Smckusick if (ctdebug & CDB_FILES) 46841480Smckusick printf("ctstart: before flags %x\n", sc->sc_flags); 46941480Smckusick #endif 47041480Smckusick if (sc->sc_flags & CTF_BEOF) { 47141480Smckusick sc->sc_flags &= ~CTF_BEOF; 47241480Smckusick sc->sc_flags |= CTF_AEOF; 47341480Smckusick #ifdef DEBUG 47441480Smckusick if (ctdebug & CDB_FILES) 47541480Smckusick printf("ctstart: after flags %x\n", sc->sc_flags); 47641480Smckusick #endif 47741480Smckusick } 47841480Smckusick bp->b_resid = bp->b_bcount; 47941480Smckusick iodone(bp); 48041480Smckusick hpibfree(&sc->sc_dq); 48156388Smckusick if (dp = bp->b_actf) 48256388Smckusick dp->b_actb = bp->b_actb; 48356388Smckusick else 48456388Smckusick cttab[unit].b_actb = bp->b_actb; 48556388Smckusick *bp->b_actb = dp; 48656388Smckusick if ((bp = dp) == NULL) { 48741480Smckusick cttab[unit].b_active = 0; 48841480Smckusick return; 48941480Smckusick } 49041480Smckusick sc->sc_addr = bp->b_un.b_addr; 49141480Smckusick sc->sc_resid = bp->b_bcount; 49241480Smckusick if (hpibreq(&sc->sc_dq)) 49341480Smckusick goto again; 49441480Smckusick return; 49541480Smckusick } 49641480Smckusick sc->sc_flags |= CTF_IO; 49741480Smckusick sc->sc_ioc.unit = C_SUNIT(sc->sc_punit); 49841480Smckusick sc->sc_ioc.saddr = C_SADDR; 49941480Smckusick sc->sc_ioc.addr0 = 0; 50041480Smckusick sc->sc_ioc.addr = sc->sc_blkno; 50141480Smckusick sc->sc_ioc.nop2 = C_NOP; 50241480Smckusick sc->sc_ioc.slen = C_SLEN; 50341480Smckusick sc->sc_ioc.len = sc->sc_resid; 50441480Smckusick sc->sc_ioc.nop3 = C_NOP; 50541480Smckusick if (bp->b_flags & B_READ) 50641480Smckusick sc->sc_ioc.cmd = C_READ; 50741480Smckusick else { 50841480Smckusick sc->sc_ioc.cmd = C_WRITE; 50941480Smckusick sc->sc_flags |= (CTF_WRT | CTF_WRTTN); 51041480Smckusick } 51141480Smckusick hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD, 51241480Smckusick &sc->sc_ioc, sizeof(sc->sc_ioc)); 51341480Smckusick } 51441480Smckusick hpibawait(sc->sc_hd->hp_ctlr); 51541480Smckusick } 51641480Smckusick 51741480Smckusick ctgo(unit) 51841480Smckusick register int unit; 51941480Smckusick { 52041480Smckusick register struct ct_softc *sc = &ct_softc[unit]; 52141480Smckusick register struct buf *bp; 52241480Smckusick 52341480Smckusick bp = cttab[unit].b_actf; 52441480Smckusick hpibgo(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC, 52541480Smckusick sc->sc_addr, sc->sc_resid, bp->b_flags & B_READ); 52641480Smckusick } 52741480Smckusick 52841480Smckusick /* 52941480Smckusick * Hideous grue to handle EOF/EOT (mostly for reads) 53041480Smckusick */ 53141480Smckusick cteof(sc, bp) 53241480Smckusick register struct ct_softc *sc; 53341480Smckusick register struct buf *bp; 53441480Smckusick { 53541480Smckusick long blks; 53641480Smckusick 53741480Smckusick /* 53841480Smckusick * EOT on a write is an error. 53941480Smckusick */ 54041480Smckusick if ((bp->b_flags & B_READ) == 0) { 54141480Smckusick bp->b_resid = bp->b_bcount; 54241480Smckusick bp->b_flags |= B_ERROR; 54341480Smckusick bp->b_error = ENOSPC; 54441480Smckusick sc->sc_flags |= CTF_EOT; 54541480Smckusick return; 54641480Smckusick } 54741480Smckusick /* 54841480Smckusick * Use returned block position to determine how many blocks 54941480Smckusick * we really read and update b_resid. 55041480Smckusick */ 55141480Smckusick blks = sc->sc_stat.c_blk - sc->sc_blkno - 1; 55241480Smckusick #ifdef DEBUG 55341480Smckusick if (ctdebug & CDB_FILES) 55441480Smckusick printf("cteof: bc %d oblk %d nblk %d read %d, resid %d\n", 55541480Smckusick bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk, 55641480Smckusick blks, bp->b_bcount - CTKTOB(blks)); 55741480Smckusick #endif 55841480Smckusick if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */ 55941480Smckusick blks = 0; 56041480Smckusick sc->sc_blkno++; 56141480Smckusick } 56241480Smckusick else { 56341480Smckusick sc->sc_blkno = sc->sc_stat.c_blk; 56441480Smckusick } 56541480Smckusick bp->b_resid = bp->b_bcount - CTKTOB(blks); 56641480Smckusick /* 56741480Smckusick * If we are at physical EOV or were after an EOF, 56841480Smckusick * we are now at logical EOT. 56941480Smckusick */ 57041480Smckusick if ((sc->sc_stat.c_aef & AEF_EOV) || 57141480Smckusick (sc->sc_flags & CTF_AEOF)) { 57241480Smckusick sc->sc_flags |= CTF_EOT; 57341480Smckusick sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF); 57441480Smckusick } 57541480Smckusick /* 57641480Smckusick * If we were before an EOF or we have just completed a FSF, 57741480Smckusick * we are now after EOF. 57841480Smckusick */ 57941480Smckusick else if ((sc->sc_flags & CTF_BEOF) || 58041480Smckusick (sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF) { 58141480Smckusick sc->sc_flags |= CTF_AEOF; 58241480Smckusick sc->sc_flags &= ~CTF_BEOF; 58341480Smckusick } 58441480Smckusick /* 58541480Smckusick * Otherwise if we read something we are now before EOF 58641480Smckusick * (and no longer after EOF). 58741480Smckusick */ 58841480Smckusick else if (blks) { 58941480Smckusick sc->sc_flags |= CTF_BEOF; 59041480Smckusick sc->sc_flags &= ~CTF_AEOF; 59141480Smckusick } 59241480Smckusick /* 59341480Smckusick * Finally, if we didn't read anything we just passed an EOF 59441480Smckusick */ 59541480Smckusick else 59641480Smckusick sc->sc_flags |= CTF_AEOF; 59741480Smckusick #ifdef DEBUG 59841480Smckusick if (ctdebug & CDB_FILES) 59941480Smckusick printf("cteof: leaving flags %x\n", sc->sc_flags); 60041480Smckusick #endif 60141480Smckusick } 60241480Smckusick 60341480Smckusick ctintr(unit) 60441480Smckusick register int unit; 60541480Smckusick { 60641480Smckusick register struct ct_softc *sc = &ct_softc[unit]; 60756388Smckusick register struct buf *bp, *dp; 60841480Smckusick u_char stat; 60941480Smckusick 61041480Smckusick bp = cttab[unit].b_actf; 61141480Smckusick if (bp == NULL) { 61241480Smckusick printf("ct%d: bp == NULL\n", unit); 61341480Smckusick return; 61441480Smckusick } 61541480Smckusick if (sc->sc_flags & CTF_IO) { 61641480Smckusick sc->sc_flags &= ~CTF_IO; 61741480Smckusick if (hpibustart(sc->sc_hd->hp_ctlr)) 61841480Smckusick ctgo(unit); 61941480Smckusick return; 62041480Smckusick } 62141480Smckusick if ((sc->sc_flags & CTF_STATWAIT) == 0) { 62241480Smckusick if (hpibpptest(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave) == 0) { 62341480Smckusick sc->sc_flags |= CTF_STATWAIT; 62441480Smckusick hpibawait(sc->sc_hd->hp_ctlr); 62541480Smckusick return; 62641480Smckusick } 62741480Smckusick } else 62841480Smckusick sc->sc_flags &= ~CTF_STATWAIT; 62941480Smckusick hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, &stat, 1); 63041480Smckusick #ifdef DEBUG 63141480Smckusick if (ctdebug & CDB_FILES) 63241480Smckusick printf("ctintr: before flags %x\n", sc->sc_flags); 63341480Smckusick #endif 63441480Smckusick if (stat) { 63541480Smckusick sc->sc_rsc.unit = C_SUNIT(sc->sc_punit); 63641480Smckusick sc->sc_rsc.cmd = C_STATUS; 63741480Smckusick hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD, 63841480Smckusick &sc->sc_rsc, sizeof(sc->sc_rsc)); 63941480Smckusick hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC, 64041480Smckusick &sc->sc_stat, sizeof(sc->sc_stat)); 64141480Smckusick hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, 64241480Smckusick &stat, 1); 64341480Smckusick #ifdef DEBUG 64441480Smckusick if (ctdebug & CDB_FILES) 64541480Smckusick printf("ctintr: return stat 0x%x, A%x F%x blk %d\n", 64641480Smckusick stat, sc->sc_stat.c_aef, 64741480Smckusick sc->sc_stat.c_fef, sc->sc_stat.c_blk); 64841480Smckusick #endif 64941480Smckusick if (stat == 0) { 65041480Smckusick if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) { 65141480Smckusick cteof(sc, bp); 65241480Smckusick ctaddeof(unit); 65341480Smckusick goto done; 65441480Smckusick } 65541480Smckusick if (sc->sc_stat.c_fef & FEF_PF) { 65641480Smckusick ctreset(sc, sc->sc_hd); 65741480Smckusick ctstart(unit); 65841480Smckusick return; 65941480Smckusick } 66041480Smckusick if (sc->sc_stat.c_fef & FEF_REXMT) { 66141480Smckusick ctstart(unit); 66241480Smckusick return; 66341480Smckusick } 66441480Smckusick if (sc->sc_stat.c_aef & 0x5800) { 66541480Smckusick if (sc->sc_stat.c_aef & 0x4000) 66649132Skarels tprintf(sc->sc_tpr, 66741480Smckusick "ct%d: uninitialized media\n", 66841480Smckusick unit); 66941480Smckusick if (sc->sc_stat.c_aef & 0x1000) 67049132Skarels tprintf(sc->sc_tpr, 67141480Smckusick "ct%d: not ready\n", unit); 67241480Smckusick if (sc->sc_stat.c_aef & 0x0800) 67349132Skarels tprintf(sc->sc_tpr, 67441480Smckusick "ct%d: write protect\n", unit); 67541480Smckusick } else { 67641480Smckusick printf("ct%d err: v%d u%d ru%d bn%d, ", 67741480Smckusick unit, 67841480Smckusick (sc->sc_stat.c_vu>>4)&0xF, 67941480Smckusick sc->sc_stat.c_vu&0xF, 68041480Smckusick sc->sc_stat.c_pend, 68141480Smckusick sc->sc_stat.c_blk); 68241480Smckusick printf("R0x%x F0x%x A0x%x I0x%x\n", 68341480Smckusick sc->sc_stat.c_ref, 68441480Smckusick sc->sc_stat.c_fef, 68541480Smckusick sc->sc_stat.c_aef, 68641480Smckusick sc->sc_stat.c_ief); 68741480Smckusick } 68841480Smckusick } else 68941480Smckusick printf("ct%d: request status failed\n", unit); 69041480Smckusick bp->b_flags |= B_ERROR; 69141480Smckusick bp->b_error = EIO; 69241480Smckusick goto done; 69341480Smckusick } else 69441480Smckusick bp->b_resid = 0; 69541480Smckusick if (sc->sc_flags & CTF_CMD) { 69641480Smckusick switch (sc->sc_cmd) { 69741480Smckusick case MTFSF: 69841480Smckusick sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF); 69941480Smckusick sc->sc_blkno += CTBTOK(sc->sc_resid); 70041480Smckusick ctstart(unit); 70141480Smckusick return; 70241480Smckusick case MTBSF: 70341480Smckusick sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT); 70441480Smckusick break; 70541480Smckusick case MTBSR: 70641480Smckusick sc->sc_flags &= ~CTF_BEOF; 70741480Smckusick if (sc->sc_flags & CTF_EOT) { 70841480Smckusick sc->sc_flags |= CTF_AEOF; 70941480Smckusick sc->sc_flags &= ~CTF_EOT; 71041480Smckusick } else if (sc->sc_flags & CTF_AEOF) { 71141480Smckusick sc->sc_flags |= CTF_BEOF; 71241480Smckusick sc->sc_flags &= ~CTF_AEOF; 71341480Smckusick } 71441480Smckusick break; 71541480Smckusick case MTWEOF: 71641480Smckusick sc->sc_flags &= ~CTF_BEOF; 71741480Smckusick if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) { 71841480Smckusick sc->sc_flags |= CTF_EOT; 71941480Smckusick sc->sc_flags &= ~CTF_AEOF; 72041480Smckusick } else 72141480Smckusick sc->sc_flags |= CTF_AEOF; 72241480Smckusick break; 72341480Smckusick case MTREW: 72441480Smckusick case MTOFFL: 72541480Smckusick sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT); 72641480Smckusick break; 72741480Smckusick } 72841480Smckusick } else { 72941480Smckusick sc->sc_flags &= ~CTF_AEOF; 73041480Smckusick sc->sc_blkno += CTBTOK(sc->sc_resid); 73141480Smckusick } 73241480Smckusick done: 73341480Smckusick #ifdef DEBUG 73441480Smckusick if (ctdebug & CDB_FILES) 73541480Smckusick printf("ctintr: after flags %x\n", sc->sc_flags); 73641480Smckusick #endif 73756388Smckusick if (dp = bp->b_actf) 73856388Smckusick dp->b_actb = bp->b_actb; 73956388Smckusick else 74056388Smckusick cttab[unit].b_actb = bp->b_actb; 74156388Smckusick *bp->b_actb = dp; 74241480Smckusick iodone(bp); 74341480Smckusick hpibfree(&sc->sc_dq); 74441480Smckusick if (cttab[unit].b_actf == NULL) { 74541480Smckusick cttab[unit].b_active = 0; 74641480Smckusick return; 74741480Smckusick } 74841480Smckusick ctustart(unit); 74941480Smckusick } 75041480Smckusick 75141480Smckusick ctread(dev, uio) 75241480Smckusick dev_t dev; 75341480Smckusick struct uio *uio; 75441480Smckusick { 75541480Smckusick register int unit = UNIT(dev); 75641480Smckusick 75741480Smckusick return(physio(ctstrategy, &ctbuf[unit], dev, B_READ, minphys, uio)); 75841480Smckusick } 75941480Smckusick 76041480Smckusick ctwrite(dev, uio) 76141480Smckusick dev_t dev; 76241480Smckusick struct uio *uio; 76341480Smckusick { 76441480Smckusick register int unit = UNIT(dev); 76541480Smckusick 76641480Smckusick return(physio(ctstrategy, &ctbuf[unit], dev, B_WRITE, minphys, uio)); 76741480Smckusick } 76841480Smckusick 76941480Smckusick /*ARGSUSED*/ 77041480Smckusick ctioctl(dev, cmd, data, flag) 77141480Smckusick dev_t dev; 77241480Smckusick caddr_t data; 77341480Smckusick { 77441480Smckusick register struct mtop *op; 77541480Smckusick register int cnt; 77641480Smckusick 77741480Smckusick switch (cmd) { 77841480Smckusick 77941480Smckusick case MTIOCTOP: 78041480Smckusick op = (struct mtop *)data; 78141480Smckusick switch(op->mt_op) { 78241480Smckusick 78341480Smckusick case MTWEOF: 78441480Smckusick case MTFSF: 78541480Smckusick case MTBSR: 78641480Smckusick case MTBSF: 78741480Smckusick case MTFSR: 78841480Smckusick cnt = op->mt_count; 78941480Smckusick break; 79041480Smckusick 79141480Smckusick case MTREW: 79241480Smckusick case MTOFFL: 79341480Smckusick cnt = 1; 79441480Smckusick break; 79541480Smckusick 79641480Smckusick default: 79741480Smckusick return(EINVAL); 79841480Smckusick } 79941480Smckusick ctcommand(dev, op->mt_op, cnt); 80041480Smckusick break; 80141480Smckusick 80241480Smckusick case MTIOCGET: 80341480Smckusick break; 80441480Smckusick 80541480Smckusick default: 80641480Smckusick return(EINVAL); 80741480Smckusick } 80841480Smckusick return(0); 80941480Smckusick } 81041480Smckusick 81141480Smckusick /*ARGSUSED*/ 81241480Smckusick ctdump(dev) 81341480Smckusick dev_t dev; 81441480Smckusick { 81541480Smckusick return(ENXIO); 81641480Smckusick } 81741480Smckusick 81841480Smckusick ctaddeof(unit) 81941480Smckusick int unit; 82041480Smckusick { 82141480Smckusick register struct ct_softc *sc = &ct_softc[unit]; 82241480Smckusick 82341480Smckusick if (sc->sc_eofp == EOFS - 1) 82441480Smckusick sc->sc_eofs[EOFS - 1]++; 82541480Smckusick else { 82641480Smckusick sc->sc_eofp++; 82741480Smckusick if (sc->sc_eofp == EOFS - 1) 82841480Smckusick sc->sc_eofs[EOFS - 1] = EOFS; 82941480Smckusick else 83041480Smckusick /* save blkno */ 83141480Smckusick sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1; 83241480Smckusick } 83341480Smckusick #ifdef DEBUG 83441480Smckusick if (ctdebug & CT_BSF) 83541480Smckusick printf("ct%d: add eof pos %d blk %d\n", 83641480Smckusick unit, sc->sc_eofp, 83741480Smckusick sc->sc_eofs[sc->sc_eofp]); 83841480Smckusick #endif 83941480Smckusick } 84041480Smckusick #endif 841