141480Smckusick /* 263151Sbostic * Copyright (c) 1982, 1990, 1993 363151Sbostic * The Regents of the University of California. All rights reserved. 441480Smckusick * 541480Smckusick * %sccs.include.redist.c% 641480Smckusick * 7*65638Sbostic * @(#)ct.c 8.2 (Berkeley) 01/12/94 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; 279*65638Sbostic int flag; 28041480Smckusick { 28141480Smckusick register struct ct_softc *sc = &ct_softc[UNIT(dev)]; 28241480Smckusick 28341480Smckusick if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) && 28441480Smckusick (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */ 28541480Smckusick ctcommand(dev, MTWEOF, 2); 28641480Smckusick ctcommand(dev, MTBSR, 1); 28741480Smckusick if (sc->sc_eofp == EOFS - 1) 28841480Smckusick sc->sc_eofs[EOFS - 1]--; 28941480Smckusick else 29041480Smckusick sc->sc_eofp--; 29141480Smckusick #ifdef DEBUG 29241480Smckusick if(ctdebug & CT_BSF) 29341480Smckusick printf("ct%d: ctclose backup eofs prt %d blk %d\n", 29441480Smckusick UNIT(dev), sc->sc_eofp, sc->sc_eofs[sc->sc_eofp]); 29541480Smckusick #endif 29641480Smckusick } 29741480Smckusick if ((minor(dev) & CT_NOREW) == 0) 29841480Smckusick ctcommand(dev, MTREW, 1); 29941480Smckusick sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN); 30049132Skarels tprintf_close(sc->sc_tpr); 30141480Smckusick #ifdef DEBUG 30241480Smckusick if (ctdebug & CDB_FILES) 30341480Smckusick printf("ctclose: flags %x\n", sc->sc_flags); 30441480Smckusick #endif 30541480Smckusick return(0); /* XXX */ 30641480Smckusick } 30741480Smckusick 30841480Smckusick ctcommand(dev, cmd, cnt) 30941480Smckusick dev_t dev; 310*65638Sbostic int cmd; 31141480Smckusick register int cnt; 31241480Smckusick { 31341480Smckusick register struct ct_softc *sc = &ct_softc[UNIT(dev)]; 31441480Smckusick register struct buf *bp = &ctbuf[UNIT(dev)]; 31541480Smckusick register struct buf *nbp = 0; 31641480Smckusick 31741480Smckusick if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) { 31841480Smckusick cnt = sc->sc_eofs[EOFS - 1] - cnt; 31941480Smckusick ctcommand(dev, MTREW, 1); 32041480Smckusick ctcommand(dev, MTFSF, cnt); 32141480Smckusick cnt = 2; 32241480Smckusick cmd = MTBSR; 32341480Smckusick } 32441480Smckusick 32541480Smckusick if (cmd == MTBSF && sc->sc_eofp - cnt < 0) { 32641480Smckusick cnt = 1; 32741480Smckusick cmd = MTREW; 32841480Smckusick } 32941480Smckusick 33041480Smckusick sc->sc_flags |= CTF_CMD; 33141480Smckusick sc->sc_bp = bp; 33241480Smckusick sc->sc_cmd = cmd; 33341480Smckusick bp->b_dev = dev; 33441480Smckusick if (cmd == MTFSF) { 33541480Smckusick nbp = (struct buf *)geteblk(MAXBSIZE); 33641480Smckusick bp->b_un.b_addr = nbp->b_un.b_addr; 33741480Smckusick bp->b_bcount = MAXBSIZE; 33841480Smckusick } 33941480Smckusick again: 34041480Smckusick bp->b_flags = B_BUSY; 34141480Smckusick if (cmd == MTBSF) { 34241480Smckusick sc->sc_blkno = sc->sc_eofs[sc->sc_eofp]; 34341480Smckusick sc->sc_eofp--; 34441480Smckusick #ifdef DEBUG 34541480Smckusick if (ctdebug & CT_BSF) 34641480Smckusick printf("ct%d: backup eof pos %d blk %d\n", 34741480Smckusick UNIT(dev), sc->sc_eofp, 34841480Smckusick sc->sc_eofs[sc->sc_eofp]); 34941480Smckusick #endif 35041480Smckusick } 35141480Smckusick ctstrategy(bp); 35241480Smckusick iowait(bp); 35341480Smckusick if (--cnt > 0) 35441480Smckusick goto again; 35541480Smckusick bp->b_flags = 0; 35641480Smckusick sc->sc_flags &= ~CTF_CMD; 35741480Smckusick if (nbp) 35841480Smckusick brelse(nbp); 35941480Smckusick } 36041480Smckusick 36141480Smckusick ctstrategy(bp) 36241480Smckusick register struct buf *bp; 36341480Smckusick { 36441480Smckusick register struct buf *dp; 36541480Smckusick register int s, unit; 36641480Smckusick 36741480Smckusick unit = UNIT(bp->b_dev); 36841480Smckusick dp = &cttab[unit]; 36956388Smckusick bp->b_actf = NULL; 37041480Smckusick s = splbio(); 37156388Smckusick bp->b_actb = dp->b_actb; 37256388Smckusick *dp->b_actb = bp; 37356388Smckusick dp->b_actb = &bp->b_actf; 37441480Smckusick if (dp->b_active == 0) { 37541480Smckusick dp->b_active = 1; 37641480Smckusick ctustart(unit); 37741480Smckusick } 37841480Smckusick splx(s); 37941480Smckusick } 38041480Smckusick 38141480Smckusick ctustart(unit) 38241480Smckusick register int unit; 38341480Smckusick { 38441480Smckusick register struct ct_softc *sc = &ct_softc[unit]; 38541480Smckusick register struct buf *bp; 38641480Smckusick 38741480Smckusick bp = cttab[unit].b_actf; 38841480Smckusick sc->sc_addr = bp->b_un.b_addr; 38941480Smckusick sc->sc_resid = bp->b_bcount; 39041480Smckusick if (hpibreq(&sc->sc_dq)) 39141480Smckusick ctstart(unit); 39241480Smckusick } 39341480Smckusick 39441480Smckusick ctstart(unit) 39541480Smckusick register int unit; 39641480Smckusick { 39741480Smckusick register struct ct_softc *sc = &ct_softc[unit]; 39856388Smckusick register struct buf *bp, *dp; 39941480Smckusick register int i; 40041480Smckusick 40141480Smckusick bp = cttab[unit].b_actf; 40241480Smckusick again: 40341480Smckusick if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) { 40441480Smckusick switch(sc->sc_cmd) { 40541480Smckusick 40641480Smckusick case MTFSF: 40741480Smckusick bp->b_flags |= B_READ; 40841480Smckusick goto mustio; 40941480Smckusick 41041480Smckusick case MTBSF: 41141480Smckusick goto gotaddr; 41241480Smckusick 41341480Smckusick case MTOFFL: 41441480Smckusick sc->sc_blkno = 0; 41541480Smckusick sc->sc_ul.unit = C_SUNIT(sc->sc_punit); 41641480Smckusick sc->sc_ul.cmd = C_UNLOAD; 41741480Smckusick hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 41841480Smckusick C_CMD, &sc->sc_ul, sizeof(sc->sc_ul)); 41941480Smckusick break; 42041480Smckusick 42141480Smckusick case MTWEOF: 42241480Smckusick sc->sc_blkno++; 42341480Smckusick sc->sc_flags |= CTF_WRT; 42441480Smckusick sc->sc_wfm.unit = C_SUNIT(sc->sc_punit); 42541480Smckusick sc->sc_wfm.cmd = C_WFM; 42641480Smckusick hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 42741480Smckusick C_CMD, &sc->sc_wfm, sizeof(sc->sc_wfm)); 42841480Smckusick ctaddeof(unit); 42941480Smckusick break; 43041480Smckusick 43141480Smckusick case MTBSR: 43241480Smckusick sc->sc_blkno--; 43341480Smckusick goto gotaddr; 43441480Smckusick 43541480Smckusick case MTFSR: 43641480Smckusick sc->sc_blkno++; 43741480Smckusick goto gotaddr; 43841480Smckusick 43941480Smckusick case MTREW: 44041480Smckusick sc->sc_blkno = 0; 44141480Smckusick #ifdef DEBUG 44241480Smckusick if(ctdebug & CT_BSF) 44341480Smckusick printf("ct%d: clearing eofs\n", unit); 44441480Smckusick #endif 44541480Smckusick for (i=0; i<EOFS; i++) 44641480Smckusick sc->sc_eofs[i] = 0; 44741480Smckusick sc->sc_eofp = 0; 44841480Smckusick 44941480Smckusick gotaddr: 45041480Smckusick sc->sc_ioc.saddr = C_SADDR; 45141480Smckusick sc->sc_ioc.addr0 = 0; 45241480Smckusick sc->sc_ioc.addr = sc->sc_blkno; 45341480Smckusick sc->sc_ioc.unit = C_SUNIT(sc->sc_punit); 45441480Smckusick sc->sc_ioc.nop2 = C_NOP; 45541480Smckusick sc->sc_ioc.slen = C_SLEN; 45641480Smckusick sc->sc_ioc.len = 0; 45741480Smckusick sc->sc_ioc.nop3 = C_NOP; 45841480Smckusick sc->sc_ioc.cmd = C_READ; 45941480Smckusick hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, 46041480Smckusick C_CMD, &sc->sc_ioc, sizeof(sc->sc_ioc)); 46141480Smckusick break; 46241480Smckusick } 46341480Smckusick } 46441480Smckusick else { 46541480Smckusick mustio: 46641480Smckusick if ((bp->b_flags & B_READ) && 46741480Smckusick sc->sc_flags & (CTF_BEOF|CTF_EOT)) { 46841480Smckusick #ifdef DEBUG 46941480Smckusick if (ctdebug & CDB_FILES) 47041480Smckusick printf("ctstart: before flags %x\n", sc->sc_flags); 47141480Smckusick #endif 47241480Smckusick if (sc->sc_flags & CTF_BEOF) { 47341480Smckusick sc->sc_flags &= ~CTF_BEOF; 47441480Smckusick sc->sc_flags |= CTF_AEOF; 47541480Smckusick #ifdef DEBUG 47641480Smckusick if (ctdebug & CDB_FILES) 47741480Smckusick printf("ctstart: after flags %x\n", sc->sc_flags); 47841480Smckusick #endif 47941480Smckusick } 48041480Smckusick bp->b_resid = bp->b_bcount; 48141480Smckusick iodone(bp); 48241480Smckusick hpibfree(&sc->sc_dq); 48356388Smckusick if (dp = bp->b_actf) 48456388Smckusick dp->b_actb = bp->b_actb; 48556388Smckusick else 48656388Smckusick cttab[unit].b_actb = bp->b_actb; 48756388Smckusick *bp->b_actb = dp; 48856388Smckusick if ((bp = dp) == NULL) { 48941480Smckusick cttab[unit].b_active = 0; 49041480Smckusick return; 49141480Smckusick } 49241480Smckusick sc->sc_addr = bp->b_un.b_addr; 49341480Smckusick sc->sc_resid = bp->b_bcount; 49441480Smckusick if (hpibreq(&sc->sc_dq)) 49541480Smckusick goto again; 49641480Smckusick return; 49741480Smckusick } 49841480Smckusick sc->sc_flags |= CTF_IO; 49941480Smckusick sc->sc_ioc.unit = C_SUNIT(sc->sc_punit); 50041480Smckusick sc->sc_ioc.saddr = C_SADDR; 50141480Smckusick sc->sc_ioc.addr0 = 0; 50241480Smckusick sc->sc_ioc.addr = sc->sc_blkno; 50341480Smckusick sc->sc_ioc.nop2 = C_NOP; 50441480Smckusick sc->sc_ioc.slen = C_SLEN; 50541480Smckusick sc->sc_ioc.len = sc->sc_resid; 50641480Smckusick sc->sc_ioc.nop3 = C_NOP; 50741480Smckusick if (bp->b_flags & B_READ) 50841480Smckusick sc->sc_ioc.cmd = C_READ; 50941480Smckusick else { 51041480Smckusick sc->sc_ioc.cmd = C_WRITE; 51141480Smckusick sc->sc_flags |= (CTF_WRT | CTF_WRTTN); 51241480Smckusick } 51341480Smckusick hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD, 51441480Smckusick &sc->sc_ioc, sizeof(sc->sc_ioc)); 51541480Smckusick } 51641480Smckusick hpibawait(sc->sc_hd->hp_ctlr); 51741480Smckusick } 51841480Smckusick 51941480Smckusick ctgo(unit) 52041480Smckusick register int unit; 52141480Smckusick { 52241480Smckusick register struct ct_softc *sc = &ct_softc[unit]; 52341480Smckusick register struct buf *bp; 52441480Smckusick 52541480Smckusick bp = cttab[unit].b_actf; 52641480Smckusick hpibgo(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC, 52741480Smckusick sc->sc_addr, sc->sc_resid, bp->b_flags & B_READ); 52841480Smckusick } 52941480Smckusick 53041480Smckusick /* 53141480Smckusick * Hideous grue to handle EOF/EOT (mostly for reads) 53241480Smckusick */ 53341480Smckusick cteof(sc, bp) 53441480Smckusick register struct ct_softc *sc; 53541480Smckusick register struct buf *bp; 53641480Smckusick { 53741480Smckusick long blks; 53841480Smckusick 53941480Smckusick /* 54041480Smckusick * EOT on a write is an error. 54141480Smckusick */ 54241480Smckusick if ((bp->b_flags & B_READ) == 0) { 54341480Smckusick bp->b_resid = bp->b_bcount; 54441480Smckusick bp->b_flags |= B_ERROR; 54541480Smckusick bp->b_error = ENOSPC; 54641480Smckusick sc->sc_flags |= CTF_EOT; 54741480Smckusick return; 54841480Smckusick } 54941480Smckusick /* 55041480Smckusick * Use returned block position to determine how many blocks 55141480Smckusick * we really read and update b_resid. 55241480Smckusick */ 55341480Smckusick blks = sc->sc_stat.c_blk - sc->sc_blkno - 1; 55441480Smckusick #ifdef DEBUG 55541480Smckusick if (ctdebug & CDB_FILES) 55641480Smckusick printf("cteof: bc %d oblk %d nblk %d read %d, resid %d\n", 55741480Smckusick bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk, 55841480Smckusick blks, bp->b_bcount - CTKTOB(blks)); 55941480Smckusick #endif 56041480Smckusick if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */ 56141480Smckusick blks = 0; 56241480Smckusick sc->sc_blkno++; 56341480Smckusick } 56441480Smckusick else { 56541480Smckusick sc->sc_blkno = sc->sc_stat.c_blk; 56641480Smckusick } 56741480Smckusick bp->b_resid = bp->b_bcount - CTKTOB(blks); 56841480Smckusick /* 56941480Smckusick * If we are at physical EOV or were after an EOF, 57041480Smckusick * we are now at logical EOT. 57141480Smckusick */ 57241480Smckusick if ((sc->sc_stat.c_aef & AEF_EOV) || 57341480Smckusick (sc->sc_flags & CTF_AEOF)) { 57441480Smckusick sc->sc_flags |= CTF_EOT; 57541480Smckusick sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF); 57641480Smckusick } 57741480Smckusick /* 57841480Smckusick * If we were before an EOF or we have just completed a FSF, 57941480Smckusick * we are now after EOF. 58041480Smckusick */ 58141480Smckusick else if ((sc->sc_flags & CTF_BEOF) || 58241480Smckusick (sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF) { 58341480Smckusick sc->sc_flags |= CTF_AEOF; 58441480Smckusick sc->sc_flags &= ~CTF_BEOF; 58541480Smckusick } 58641480Smckusick /* 58741480Smckusick * Otherwise if we read something we are now before EOF 58841480Smckusick * (and no longer after EOF). 58941480Smckusick */ 59041480Smckusick else if (blks) { 59141480Smckusick sc->sc_flags |= CTF_BEOF; 59241480Smckusick sc->sc_flags &= ~CTF_AEOF; 59341480Smckusick } 59441480Smckusick /* 59541480Smckusick * Finally, if we didn't read anything we just passed an EOF 59641480Smckusick */ 59741480Smckusick else 59841480Smckusick sc->sc_flags |= CTF_AEOF; 59941480Smckusick #ifdef DEBUG 60041480Smckusick if (ctdebug & CDB_FILES) 60141480Smckusick printf("cteof: leaving flags %x\n", sc->sc_flags); 60241480Smckusick #endif 60341480Smckusick } 60441480Smckusick 60541480Smckusick ctintr(unit) 60641480Smckusick register int unit; 60741480Smckusick { 60841480Smckusick register struct ct_softc *sc = &ct_softc[unit]; 60956388Smckusick register struct buf *bp, *dp; 61041480Smckusick u_char stat; 61141480Smckusick 61241480Smckusick bp = cttab[unit].b_actf; 61341480Smckusick if (bp == NULL) { 61441480Smckusick printf("ct%d: bp == NULL\n", unit); 61541480Smckusick return; 61641480Smckusick } 61741480Smckusick if (sc->sc_flags & CTF_IO) { 61841480Smckusick sc->sc_flags &= ~CTF_IO; 61941480Smckusick if (hpibustart(sc->sc_hd->hp_ctlr)) 62041480Smckusick ctgo(unit); 62141480Smckusick return; 62241480Smckusick } 62341480Smckusick if ((sc->sc_flags & CTF_STATWAIT) == 0) { 62441480Smckusick if (hpibpptest(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave) == 0) { 62541480Smckusick sc->sc_flags |= CTF_STATWAIT; 62641480Smckusick hpibawait(sc->sc_hd->hp_ctlr); 62741480Smckusick return; 62841480Smckusick } 62941480Smckusick } else 63041480Smckusick sc->sc_flags &= ~CTF_STATWAIT; 63141480Smckusick hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, &stat, 1); 63241480Smckusick #ifdef DEBUG 63341480Smckusick if (ctdebug & CDB_FILES) 63441480Smckusick printf("ctintr: before flags %x\n", sc->sc_flags); 63541480Smckusick #endif 63641480Smckusick if (stat) { 63741480Smckusick sc->sc_rsc.unit = C_SUNIT(sc->sc_punit); 63841480Smckusick sc->sc_rsc.cmd = C_STATUS; 63941480Smckusick hpibsend(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_CMD, 64041480Smckusick &sc->sc_rsc, sizeof(sc->sc_rsc)); 64141480Smckusick hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_EXEC, 64241480Smckusick &sc->sc_stat, sizeof(sc->sc_stat)); 64341480Smckusick hpibrecv(sc->sc_hd->hp_ctlr, sc->sc_hd->hp_slave, C_QSTAT, 64441480Smckusick &stat, 1); 64541480Smckusick #ifdef DEBUG 64641480Smckusick if (ctdebug & CDB_FILES) 64741480Smckusick printf("ctintr: return stat 0x%x, A%x F%x blk %d\n", 64841480Smckusick stat, sc->sc_stat.c_aef, 64941480Smckusick sc->sc_stat.c_fef, sc->sc_stat.c_blk); 65041480Smckusick #endif 65141480Smckusick if (stat == 0) { 65241480Smckusick if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) { 65341480Smckusick cteof(sc, bp); 65441480Smckusick ctaddeof(unit); 65541480Smckusick goto done; 65641480Smckusick } 65741480Smckusick if (sc->sc_stat.c_fef & FEF_PF) { 65841480Smckusick ctreset(sc, sc->sc_hd); 65941480Smckusick ctstart(unit); 66041480Smckusick return; 66141480Smckusick } 66241480Smckusick if (sc->sc_stat.c_fef & FEF_REXMT) { 66341480Smckusick ctstart(unit); 66441480Smckusick return; 66541480Smckusick } 66641480Smckusick if (sc->sc_stat.c_aef & 0x5800) { 66741480Smckusick if (sc->sc_stat.c_aef & 0x4000) 66849132Skarels tprintf(sc->sc_tpr, 66941480Smckusick "ct%d: uninitialized media\n", 67041480Smckusick unit); 67141480Smckusick if (sc->sc_stat.c_aef & 0x1000) 67249132Skarels tprintf(sc->sc_tpr, 67341480Smckusick "ct%d: not ready\n", unit); 67441480Smckusick if (sc->sc_stat.c_aef & 0x0800) 67549132Skarels tprintf(sc->sc_tpr, 67641480Smckusick "ct%d: write protect\n", unit); 67741480Smckusick } else { 67841480Smckusick printf("ct%d err: v%d u%d ru%d bn%d, ", 67941480Smckusick unit, 68041480Smckusick (sc->sc_stat.c_vu>>4)&0xF, 68141480Smckusick sc->sc_stat.c_vu&0xF, 68241480Smckusick sc->sc_stat.c_pend, 68341480Smckusick sc->sc_stat.c_blk); 68441480Smckusick printf("R0x%x F0x%x A0x%x I0x%x\n", 68541480Smckusick sc->sc_stat.c_ref, 68641480Smckusick sc->sc_stat.c_fef, 68741480Smckusick sc->sc_stat.c_aef, 68841480Smckusick sc->sc_stat.c_ief); 68941480Smckusick } 69041480Smckusick } else 69141480Smckusick printf("ct%d: request status failed\n", unit); 69241480Smckusick bp->b_flags |= B_ERROR; 69341480Smckusick bp->b_error = EIO; 69441480Smckusick goto done; 69541480Smckusick } else 69641480Smckusick bp->b_resid = 0; 69741480Smckusick if (sc->sc_flags & CTF_CMD) { 69841480Smckusick switch (sc->sc_cmd) { 69941480Smckusick case MTFSF: 70041480Smckusick sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF); 70141480Smckusick sc->sc_blkno += CTBTOK(sc->sc_resid); 70241480Smckusick ctstart(unit); 70341480Smckusick return; 70441480Smckusick case MTBSF: 70541480Smckusick sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT); 70641480Smckusick break; 70741480Smckusick case MTBSR: 70841480Smckusick sc->sc_flags &= ~CTF_BEOF; 70941480Smckusick if (sc->sc_flags & CTF_EOT) { 71041480Smckusick sc->sc_flags |= CTF_AEOF; 71141480Smckusick sc->sc_flags &= ~CTF_EOT; 71241480Smckusick } else if (sc->sc_flags & CTF_AEOF) { 71341480Smckusick sc->sc_flags |= CTF_BEOF; 71441480Smckusick sc->sc_flags &= ~CTF_AEOF; 71541480Smckusick } 71641480Smckusick break; 71741480Smckusick case MTWEOF: 71841480Smckusick sc->sc_flags &= ~CTF_BEOF; 71941480Smckusick if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) { 72041480Smckusick sc->sc_flags |= CTF_EOT; 72141480Smckusick sc->sc_flags &= ~CTF_AEOF; 72241480Smckusick } else 72341480Smckusick sc->sc_flags |= CTF_AEOF; 72441480Smckusick break; 72541480Smckusick case MTREW: 72641480Smckusick case MTOFFL: 72741480Smckusick sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT); 72841480Smckusick break; 72941480Smckusick } 73041480Smckusick } else { 73141480Smckusick sc->sc_flags &= ~CTF_AEOF; 73241480Smckusick sc->sc_blkno += CTBTOK(sc->sc_resid); 73341480Smckusick } 73441480Smckusick done: 73541480Smckusick #ifdef DEBUG 73641480Smckusick if (ctdebug & CDB_FILES) 73741480Smckusick printf("ctintr: after flags %x\n", sc->sc_flags); 73841480Smckusick #endif 73956388Smckusick if (dp = bp->b_actf) 74056388Smckusick dp->b_actb = bp->b_actb; 74156388Smckusick else 74256388Smckusick cttab[unit].b_actb = bp->b_actb; 74356388Smckusick *bp->b_actb = dp; 74441480Smckusick iodone(bp); 74541480Smckusick hpibfree(&sc->sc_dq); 74641480Smckusick if (cttab[unit].b_actf == NULL) { 74741480Smckusick cttab[unit].b_active = 0; 74841480Smckusick return; 74941480Smckusick } 75041480Smckusick ctustart(unit); 75141480Smckusick } 75241480Smckusick 75341480Smckusick ctread(dev, uio) 75441480Smckusick dev_t dev; 75541480Smckusick struct uio *uio; 75641480Smckusick { 75741480Smckusick register int unit = UNIT(dev); 75841480Smckusick 75941480Smckusick return(physio(ctstrategy, &ctbuf[unit], dev, B_READ, minphys, uio)); 76041480Smckusick } 76141480Smckusick 76241480Smckusick ctwrite(dev, uio) 76341480Smckusick dev_t dev; 76441480Smckusick struct uio *uio; 76541480Smckusick { 76641480Smckusick register int unit = UNIT(dev); 76741480Smckusick 76841480Smckusick return(physio(ctstrategy, &ctbuf[unit], dev, B_WRITE, minphys, uio)); 76941480Smckusick } 77041480Smckusick 77141480Smckusick /*ARGSUSED*/ 77241480Smckusick ctioctl(dev, cmd, data, flag) 77341480Smckusick dev_t dev; 774*65638Sbostic int cmd, flag; 77541480Smckusick caddr_t data; 77641480Smckusick { 77741480Smckusick register struct mtop *op; 77841480Smckusick register int cnt; 77941480Smckusick 78041480Smckusick switch (cmd) { 78141480Smckusick 78241480Smckusick case MTIOCTOP: 78341480Smckusick op = (struct mtop *)data; 78441480Smckusick switch(op->mt_op) { 78541480Smckusick 78641480Smckusick case MTWEOF: 78741480Smckusick case MTFSF: 78841480Smckusick case MTBSR: 78941480Smckusick case MTBSF: 79041480Smckusick case MTFSR: 79141480Smckusick cnt = op->mt_count; 79241480Smckusick break; 79341480Smckusick 79441480Smckusick case MTREW: 79541480Smckusick case MTOFFL: 79641480Smckusick cnt = 1; 79741480Smckusick break; 79841480Smckusick 79941480Smckusick default: 80041480Smckusick return(EINVAL); 80141480Smckusick } 80241480Smckusick ctcommand(dev, op->mt_op, cnt); 80341480Smckusick break; 80441480Smckusick 80541480Smckusick case MTIOCGET: 80641480Smckusick break; 80741480Smckusick 80841480Smckusick default: 80941480Smckusick return(EINVAL); 81041480Smckusick } 81141480Smckusick return(0); 81241480Smckusick } 81341480Smckusick 81441480Smckusick /*ARGSUSED*/ 81541480Smckusick ctdump(dev) 81641480Smckusick dev_t dev; 81741480Smckusick { 81841480Smckusick return(ENXIO); 81941480Smckusick } 82041480Smckusick 82141480Smckusick ctaddeof(unit) 82241480Smckusick int unit; 82341480Smckusick { 82441480Smckusick register struct ct_softc *sc = &ct_softc[unit]; 82541480Smckusick 82641480Smckusick if (sc->sc_eofp == EOFS - 1) 82741480Smckusick sc->sc_eofs[EOFS - 1]++; 82841480Smckusick else { 82941480Smckusick sc->sc_eofp++; 83041480Smckusick if (sc->sc_eofp == EOFS - 1) 83141480Smckusick sc->sc_eofs[EOFS - 1] = EOFS; 83241480Smckusick else 83341480Smckusick /* save blkno */ 83441480Smckusick sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1; 83541480Smckusick } 83641480Smckusick #ifdef DEBUG 83741480Smckusick if (ctdebug & CT_BSF) 83841480Smckusick printf("ct%d: add eof pos %d blk %d\n", 83941480Smckusick unit, sc->sc_eofp, 84041480Smckusick sc->sc_eofs[sc->sc_eofp]); 84141480Smckusick #endif 84241480Smckusick } 84341480Smckusick #endif 844