141488Smckusick /*
2*63824Sbostic * Copyright (c) 1982, 1990, 1993
3*63824Sbostic * The Regents of the University of California. All rights reserved.
441488Smckusick *
541488Smckusick * %sccs.include.redist.c%
641488Smckusick *
7*63824Sbostic * @(#)ct.c 8.1 (Berkeley) 07/15/93
841488Smckusick */
941488Smckusick
1041488Smckusick /*
1141488Smckusick * CS80 tape driver
1241488Smckusick */
1356510Sbostic #include <sys/param.h>
1441488Smckusick
1556510Sbostic #include <hp300/dev/ctreg.h>
1641488Smckusick
1760329Smckusick #include <stand.att/saio.h>
1856510Sbostic #include <hp300/stand/samachdep.h>
1956510Sbostic
2041488Smckusick struct ct_iocmd ct_ioc;
2141488Smckusick struct ct_rscmd ct_rsc;
2241488Smckusick struct ct_stat ct_stat;
2341488Smckusick struct ct_ssmcmd ct_ssmc;
2441488Smckusick
2541488Smckusick struct ct_softc {
2641488Smckusick char sc_retry;
2741488Smckusick char sc_alive;
2841488Smckusick short sc_punit;
2941488Smckusick int sc_blkno;
3054073Shibler } ct_softc[NHPIB][NCT];
3141488Smckusick
3241488Smckusick #define CTRETRY 5
3341488Smckusick #define MTFSF 10
3441488Smckusick #define MTREW 11
3541488Smckusick
3641488Smckusick struct ctinfo {
3741488Smckusick short hwid;
3841488Smckusick short punit;
3941488Smckusick } ctinfo[] = {
4041488Smckusick CT7946ID, 1,
4141488Smckusick CT7912PID, 1,
4241488Smckusick CT7914PID, 1,
4341488Smckusick CT9144ID, 0,
4441488Smckusick CT9145ID, 0,
4541488Smckusick };
4641488Smckusick int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
4741488Smckusick
ctinit(ctlr,unit)4854073Shibler ctinit(ctlr, unit)
4954073Shibler register int ctlr, unit;
5041488Smckusick {
5154073Shibler register struct ct_softc *rs = &ct_softc[ctlr][unit];
5241488Smckusick u_char stat;
5341488Smckusick register int type;
5441488Smckusick
5554073Shibler if (hpibrecv(ctlr, unit, C_QSTAT, &stat, 1) != 1 || stat)
5641488Smckusick return (0);
5754073Shibler if (ctident(ctlr, unit) < 0)
5841488Smckusick return (0);
5941488Smckusick ct_ssmc.unit = C_SUNIT(rs->sc_punit);
6041488Smckusick ct_ssmc.cmd = C_SSM;
6141488Smckusick ct_ssmc.fefm = FEF_MASK;
6241488Smckusick ct_ssmc.refm = REF_MASK;
6341488Smckusick ct_ssmc.aefm = AEF_MASK;
6441488Smckusick ct_ssmc.iefm = IEF_MASK;
6554073Shibler hpibsend(ctlr, unit, C_CMD, &ct_ssmc, sizeof(ct_ssmc));
6654073Shibler hpibswait(ctlr, unit);
6754073Shibler hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
6841488Smckusick rs->sc_alive = 1;
6941488Smckusick return (1);
7041488Smckusick }
7141488Smckusick
ctident(ctlr,unit)7254073Shibler ctident(ctlr, unit)
7354073Shibler int ctlr, unit;
7441488Smckusick {
7541488Smckusick struct ct_describe desc;
7641488Smckusick u_char stat, cmd[3];
7741488Smckusick char name[7];
7841488Smckusick int id, i;
7941488Smckusick
8054073Shibler id = hpibid(ctlr, unit);
8141488Smckusick if ((id & 0x200) == 0)
8241488Smckusick return(-1);
8341488Smckusick for (i = 0; i < nctinfo; i++)
8441488Smckusick if (id == ctinfo[i].hwid)
8541488Smckusick break;
8641488Smckusick if (i == nctinfo)
8741488Smckusick return(-1);
8854073Shibler ct_softc[ctlr][unit].sc_punit = ctinfo[i].punit;
8941488Smckusick id = i;
9041488Smckusick
9141488Smckusick /*
9241488Smckusick * Collect device description.
9341488Smckusick * Right now we only need this to differentiate 7945 from 7946.
9441488Smckusick * Note that we always issue the describe command to unit 0.
9541488Smckusick */
9641488Smckusick cmd[0] = C_SUNIT(0);
9741488Smckusick cmd[1] = C_SVOL(0);
9841488Smckusick cmd[2] = C_DESC;
9954073Shibler hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd));
10054073Shibler hpibrecv(ctlr, unit, C_EXEC, &desc, 37);
10154073Shibler hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat));
10241488Smckusick bzero(name, sizeof(name));
10341488Smckusick if (!stat) {
10441488Smckusick register int n = desc.d_name;
10541488Smckusick for (i = 5; i >= 0; i--) {
10641488Smckusick name[i] = (n & 0xf) + '0';
10741488Smckusick n >>= 4;
10841488Smckusick }
10941488Smckusick }
11041488Smckusick switch (ctinfo[id].hwid) {
11141488Smckusick case CT7946ID:
11241488Smckusick if (bcmp(name, "079450", 6) == 0)
11341488Smckusick id = -1; /* not really a 7946 */
11441488Smckusick break;
11541488Smckusick default:
11641488Smckusick break;
11741488Smckusick }
11841488Smckusick return(id);
11941488Smckusick }
12041488Smckusick
12141488Smckusick ctopen(io)
12241488Smckusick struct iob *io;
12341488Smckusick {
12454073Shibler register struct ct_softc *rs;
12554073Shibler register int unit, ctlr;
12641488Smckusick register int skip;
12741488Smckusick
12854073Shibler devconvert(io);
12954073Shibler
13054073Shibler ctlr = io->i_adapt;
13154073Shibler if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
13254073Shibler return(EADAPT);
13354073Shibler unit = io->i_ctlr;
13454073Shibler if (unit >= NCT)
13554073Shibler return(ECTLR);
13663809Shibler rs = &ct_softc[ctlr][unit];
13741488Smckusick if (rs->sc_alive == 0)
13854073Shibler if (ctinit(ctlr, unit) == 0)
13954073Shibler return(ENXIO);
14041488Smckusick ctstrategy(io, MTREW);
14154073Shibler skip = io->i_part;
14241488Smckusick while (skip--)
14341488Smckusick ctstrategy(io, MTFSF);
14455897Shibler return(0);
14541488Smckusick }
14641488Smckusick
14741488Smckusick ctclose(io)
14841488Smckusick struct iob *io;
14941488Smckusick {
15041488Smckusick ctstrategy(io, MTREW);
15141488Smckusick }
15241488Smckusick
ctstrategy(io,func)15341488Smckusick ctstrategy(io, func)
15441488Smckusick register struct iob *io;
15541488Smckusick register int func;
15641488Smckusick {
15754073Shibler register int ctlr = io->i_adapt;
15854073Shibler register int unit = io->i_ctlr;
15954073Shibler register struct ct_softc *rs = &ct_softc[ctlr][unit];
16041488Smckusick char stat;
16141488Smckusick
16255897Shibler if (io->i_cc == 0 && (func == F_READ || func == F_WRITE))
16355897Shibler return(0);
16455897Shibler
16541488Smckusick rs->sc_retry = 0;
16641488Smckusick ct_ioc.unit = C_SUNIT(rs->sc_punit);
16741488Smckusick ct_ioc.saddr = C_SADDR;
16841488Smckusick ct_ioc.nop2 = C_NOP;
16941488Smckusick ct_ioc.slen = C_SLEN;
17041488Smckusick ct_ioc.nop3 = C_NOP;
17141488Smckusick top:
17249154Sbostic if (func == F_READ) {
17341488Smckusick ct_ioc.cmd = C_READ;
17441488Smckusick ct_ioc.addr = rs->sc_blkno;
17541488Smckusick ct_ioc.len = io->i_cc;
17641488Smckusick }
17749154Sbostic else if (func == F_WRITE) {
17841488Smckusick ct_ioc.cmd = C_WRITE;
17941488Smckusick ct_ioc.addr = rs->sc_blkno;
18041488Smckusick ct_ioc.len = io->i_cc;
18141488Smckusick }
18241488Smckusick else if (func == MTFSF) {
18341488Smckusick ct_ioc.cmd = C_READ;
18441488Smckusick ct_ioc.addr = rs->sc_blkno;
18541488Smckusick ct_ioc.len = io->i_cc = MAXBSIZE;
18641488Smckusick io->i_ma = io->i_buf;
18741488Smckusick }
18841488Smckusick else {
18941488Smckusick ct_ioc.cmd = C_READ;
19041488Smckusick ct_ioc.addr = 0;
19141488Smckusick ct_ioc.len = 0;
19241488Smckusick rs->sc_blkno = 0;
19341488Smckusick io->i_cc = 0;
19441488Smckusick }
19541488Smckusick retry:
19654073Shibler hpibsend(ctlr, unit, C_CMD, &ct_ioc, sizeof(ct_ioc));
19741488Smckusick if (func != MTREW) {
19854073Shibler hpibswait(ctlr, unit);
19954073Shibler hpibgo(ctlr, unit, C_EXEC, io->i_ma, io->i_cc,
20049154Sbostic func != F_WRITE ? F_READ : F_WRITE);
20154073Shibler hpibswait(ctlr, unit);
20254073Shibler } else {
20354073Shibler while (hpibswait(ctlr, unit) < 0)
20441488Smckusick ;
20541488Smckusick }
20654073Shibler hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
20741488Smckusick if (stat) {
20854073Shibler stat = cterror(ctlr, unit);
20941488Smckusick if (stat == 0)
21041488Smckusick return (-1);
21141488Smckusick if (stat == 2)
21241488Smckusick return (0);
21341488Smckusick if (++rs->sc_retry > CTRETRY)
21441488Smckusick return (-1);
21554073Shibler goto retry;
21641488Smckusick }
21741488Smckusick rs->sc_blkno += CTBTOK(io->i_cc);
21841488Smckusick if (func == MTFSF)
21941488Smckusick goto top;
22041488Smckusick return (io->i_cc);
22141488Smckusick }
22241488Smckusick
cterror(ctlr,unit)22354073Shibler cterror(ctlr, unit)
22454073Shibler register int ctlr, unit;
22541488Smckusick {
22654073Shibler register struct ct_softc *rs = &ct_softc[ctlr][unit];
22741488Smckusick char stat;
22841488Smckusick
22954073Shibler ct_rsc.unit = C_SUNIT(rs->sc_punit);
23041488Smckusick ct_rsc.cmd = C_STATUS;
23154073Shibler hpibsend(ctlr, unit, C_CMD, &ct_rsc, sizeof(ct_rsc));
23254073Shibler hpibrecv(ctlr, unit, C_EXEC, &ct_stat, sizeof(ct_stat));
23354073Shibler hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
23441488Smckusick if (stat) {
23541488Smckusick printf("ct%d: request status fail %d\n", unit, stat);
23641488Smckusick return(0);
23741488Smckusick }
23841488Smckusick if (ct_stat.c_aef & AEF_EOF) {
23941488Smckusick /* 9145 drives don't increment block number at EOF */
24054073Shibler if ((ct_stat.c_blk - rs->sc_blkno) == 0)
24154073Shibler rs->sc_blkno++;
24241488Smckusick else
24354073Shibler rs->sc_blkno = ct_stat.c_blk;
24441488Smckusick return (2);
24541488Smckusick }
24641488Smckusick printf("ct%d err: vu 0x%x, pend 0x%x, bn%d", unit,
24741488Smckusick ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk);
24841488Smckusick printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref,
24941488Smckusick ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief);
25041488Smckusick return (1);
25141488Smckusick }
252