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