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