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