xref: /csrg-svn/sys/hp300/stand/ct.c (revision 55897)
141488Smckusick /*
241488Smckusick  * Copyright (c) 1982, 1990 The Regents of the University of California.
341488Smckusick  * All rights reserved.
441488Smckusick  *
541488Smckusick  * %sccs.include.redist.c%
641488Smckusick  *
7*55897Shibler  *	@(#)ct.c	7.5 (Berkeley) 08/14/92
841488Smckusick  */
941488Smckusick 
1041488Smckusick /*
1141488Smckusick  * CS80 tape driver
1241488Smckusick  */
1354073Shibler #include "sys/param.h"
1445790Sbostic #include "../dev/ctreg.h"
1541488Smckusick 
1641488Smckusick #include "saio.h"
1741488Smckusick #include "samachdep.h"
1841488Smckusick 
1941488Smckusick struct	ct_iocmd ct_ioc;
2041488Smckusick struct	ct_rscmd ct_rsc;
2141488Smckusick struct	ct_stat ct_stat;
2241488Smckusick struct	ct_ssmcmd ct_ssmc;
2341488Smckusick 
2441488Smckusick struct	ct_softc {
2541488Smckusick 	char	sc_retry;
2641488Smckusick 	char	sc_alive;
2741488Smckusick 	short	sc_punit;
2841488Smckusick 	int	sc_blkno;
2954073Shibler } ct_softc[NHPIB][NCT];
3041488Smckusick 
3141488Smckusick #define	CTRETRY		5
3241488Smckusick #define	MTFSF		10
3341488Smckusick #define	MTREW		11
3441488Smckusick 
3541488Smckusick struct	ctinfo {
3641488Smckusick 	short	hwid;
3741488Smckusick 	short	punit;
3841488Smckusick } ctinfo[] = {
3941488Smckusick 	CT7946ID,	1,
4041488Smckusick 	CT7912PID,	1,
4141488Smckusick 	CT7914PID,	1,
4241488Smckusick 	CT9144ID,	0,
4341488Smckusick 	CT9145ID,	0,
4441488Smckusick };
4541488Smckusick int	nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
4641488Smckusick 
4754073Shibler ctinit(ctlr, unit)
4854073Shibler 	register int ctlr, unit;
4941488Smckusick {
5054073Shibler 	register struct ct_softc *rs = &ct_softc[ctlr][unit];
5141488Smckusick 	u_char stat;
5241488Smckusick 	register int type;
5341488Smckusick 
5454073Shibler 	if (hpibrecv(ctlr, unit, C_QSTAT, &stat, 1) != 1 || stat)
5541488Smckusick 		return (0);
5654073Shibler 	if (ctident(ctlr, unit) < 0)
5741488Smckusick 		return (0);
5841488Smckusick 	ct_ssmc.unit = C_SUNIT(rs->sc_punit);
5941488Smckusick 	ct_ssmc.cmd = C_SSM;
6041488Smckusick 	ct_ssmc.fefm = FEF_MASK;
6141488Smckusick 	ct_ssmc.refm = REF_MASK;
6241488Smckusick 	ct_ssmc.aefm = AEF_MASK;
6341488Smckusick 	ct_ssmc.iefm = IEF_MASK;
6454073Shibler 	hpibsend(ctlr, unit, C_CMD, &ct_ssmc, sizeof(ct_ssmc));
6554073Shibler 	hpibswait(ctlr, unit);
6654073Shibler 	hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
6741488Smckusick 	rs->sc_alive = 1;
6841488Smckusick 	return (1);
6941488Smckusick }
7041488Smckusick 
7154073Shibler ctident(ctlr, unit)
7254073Shibler 	int ctlr, unit;
7341488Smckusick {
7441488Smckusick 	struct ct_describe desc;
7541488Smckusick 	u_char stat, cmd[3];
7641488Smckusick 	char name[7];
7741488Smckusick 	int id, i;
7841488Smckusick 
7954073Shibler 	id = hpibid(ctlr, unit);
8041488Smckusick 	if ((id & 0x200) == 0)
8141488Smckusick 		return(-1);
8241488Smckusick 	for (i = 0; i < nctinfo; i++)
8341488Smckusick 		if (id == ctinfo[i].hwid)
8441488Smckusick 			break;
8541488Smckusick 	if (i == nctinfo)
8641488Smckusick 		return(-1);
8754073Shibler 	ct_softc[ctlr][unit].sc_punit = ctinfo[i].punit;
8841488Smckusick 	id = i;
8941488Smckusick 
9041488Smckusick 	/*
9141488Smckusick 	 * Collect device description.
9241488Smckusick 	 * Right now we only need this to differentiate 7945 from 7946.
9341488Smckusick 	 * Note that we always issue the describe command to unit 0.
9441488Smckusick 	 */
9541488Smckusick 	cmd[0] = C_SUNIT(0);
9641488Smckusick 	cmd[1] = C_SVOL(0);
9741488Smckusick 	cmd[2] = C_DESC;
9854073Shibler 	hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd));
9954073Shibler 	hpibrecv(ctlr, unit, C_EXEC, &desc, 37);
10054073Shibler 	hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat));
10141488Smckusick 	bzero(name, sizeof(name));
10241488Smckusick 	if (!stat) {
10341488Smckusick 		register int n = desc.d_name;
10441488Smckusick 		for (i = 5; i >= 0; i--) {
10541488Smckusick 			name[i] = (n & 0xf) + '0';
10641488Smckusick 			n >>= 4;
10741488Smckusick 		}
10841488Smckusick 	}
10941488Smckusick 	switch (ctinfo[id].hwid) {
11041488Smckusick 	case CT7946ID:
11141488Smckusick 		if (bcmp(name, "079450", 6) == 0)
11241488Smckusick 			id = -1;		/* not really a 7946 */
11341488Smckusick 		break;
11441488Smckusick 	default:
11541488Smckusick 		break;
11641488Smckusick 	}
11741488Smckusick 	return(id);
11841488Smckusick }
11941488Smckusick 
12041488Smckusick ctopen(io)
12141488Smckusick 	struct iob *io;
12241488Smckusick {
12354073Shibler 	register struct ct_softc *rs;
12454073Shibler 	register int unit, ctlr;
12541488Smckusick 	register int skip;
12641488Smckusick 
12754073Shibler 	devconvert(io);
12854073Shibler 
12954073Shibler 	ctlr = io->i_adapt;
13054073Shibler 	if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
13154073Shibler 		return(EADAPT);
13254073Shibler 	unit = io->i_ctlr;
13354073Shibler 	if (unit >= NCT)
13454073Shibler 		return(ECTLR);
13541488Smckusick 	if (rs->sc_alive == 0)
13654073Shibler 		if (ctinit(ctlr, unit) == 0)
13754073Shibler 			return(ENXIO);
13841488Smckusick 	ctstrategy(io, MTREW);
13954073Shibler 	skip = io->i_part;
14041488Smckusick 	while (skip--)
14141488Smckusick 		ctstrategy(io, MTFSF);
142*55897Shibler 	return(0);
14341488Smckusick }
14441488Smckusick 
14541488Smckusick ctclose(io)
14641488Smckusick 	struct iob *io;
14741488Smckusick {
14841488Smckusick 	ctstrategy(io, MTREW);
14941488Smckusick }
15041488Smckusick 
15141488Smckusick ctstrategy(io, func)
15241488Smckusick 	register struct iob *io;
15341488Smckusick 	register int func;
15441488Smckusick {
15554073Shibler 	register int ctlr = io->i_adapt;
15654073Shibler 	register int unit = io->i_ctlr;
15754073Shibler 	register struct ct_softc *rs = &ct_softc[ctlr][unit];
15841488Smckusick 	char stat;
15941488Smckusick 
160*55897Shibler 	if (io->i_cc == 0 && (func == F_READ || func == F_WRITE))
161*55897Shibler 		return(0);
162*55897Shibler 
16341488Smckusick 	rs->sc_retry = 0;
16441488Smckusick 	ct_ioc.unit = C_SUNIT(rs->sc_punit);
16541488Smckusick 	ct_ioc.saddr = C_SADDR;
16641488Smckusick 	ct_ioc.nop2 = C_NOP;
16741488Smckusick 	ct_ioc.slen = C_SLEN;
16841488Smckusick 	ct_ioc.nop3 = C_NOP;
16941488Smckusick top:
17049154Sbostic 	if (func == F_READ) {
17141488Smckusick 		ct_ioc.cmd = C_READ;
17241488Smckusick 		ct_ioc.addr = rs->sc_blkno;
17341488Smckusick 		ct_ioc.len = io->i_cc;
17441488Smckusick 	}
17549154Sbostic 	else if (func == F_WRITE) {
17641488Smckusick 		ct_ioc.cmd = C_WRITE;
17741488Smckusick 		ct_ioc.addr = rs->sc_blkno;
17841488Smckusick 		ct_ioc.len = io->i_cc;
17941488Smckusick 	}
18041488Smckusick 	else if (func == MTFSF) {
18141488Smckusick 		ct_ioc.cmd = C_READ;
18241488Smckusick 		ct_ioc.addr = rs->sc_blkno;
18341488Smckusick 		ct_ioc.len = io->i_cc = MAXBSIZE;
18441488Smckusick 		io->i_ma = io->i_buf;
18541488Smckusick 	}
18641488Smckusick 	else {
18741488Smckusick 		ct_ioc.cmd = C_READ;
18841488Smckusick 		ct_ioc.addr = 0;
18941488Smckusick 		ct_ioc.len = 0;
19041488Smckusick 		rs->sc_blkno = 0;
19141488Smckusick 		io->i_cc = 0;
19241488Smckusick 	}
19341488Smckusick retry:
19454073Shibler 	hpibsend(ctlr, unit, C_CMD, &ct_ioc, sizeof(ct_ioc));
19541488Smckusick 	if (func != MTREW) {
19654073Shibler 		hpibswait(ctlr, unit);
19754073Shibler 		hpibgo(ctlr, unit, C_EXEC, io->i_ma, io->i_cc,
19849154Sbostic 			func != F_WRITE ? F_READ : F_WRITE);
19954073Shibler 		hpibswait(ctlr, unit);
20054073Shibler 	} else {
20154073Shibler 		while (hpibswait(ctlr, unit) < 0)
20241488Smckusick 			;
20341488Smckusick 	}
20454073Shibler 	hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
20541488Smckusick 	if (stat) {
20654073Shibler 		stat = cterror(ctlr, unit);
20741488Smckusick 		if (stat == 0)
20841488Smckusick 			return (-1);
20941488Smckusick 		if (stat == 2)
21041488Smckusick 			return (0);
21141488Smckusick 		if (++rs->sc_retry > CTRETRY)
21241488Smckusick 			return (-1);
21354073Shibler 		goto retry;
21441488Smckusick 	}
21541488Smckusick 	rs->sc_blkno += CTBTOK(io->i_cc);
21641488Smckusick 	if (func == MTFSF)
21741488Smckusick 		goto top;
21841488Smckusick 	return (io->i_cc);
21941488Smckusick }
22041488Smckusick 
22154073Shibler cterror(ctlr, unit)
22254073Shibler 	register int ctlr, unit;
22341488Smckusick {
22454073Shibler 	register struct ct_softc *rs = &ct_softc[ctlr][unit];
22541488Smckusick 	char stat;
22641488Smckusick 
22754073Shibler 	ct_rsc.unit = C_SUNIT(rs->sc_punit);
22841488Smckusick 	ct_rsc.cmd = C_STATUS;
22954073Shibler 	hpibsend(ctlr, unit, C_CMD, &ct_rsc, sizeof(ct_rsc));
23054073Shibler 	hpibrecv(ctlr, unit, C_EXEC, &ct_stat, sizeof(ct_stat));
23154073Shibler 	hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
23241488Smckusick 	if (stat) {
23341488Smckusick 		printf("ct%d: request status fail %d\n", unit, stat);
23441488Smckusick 		return(0);
23541488Smckusick 	}
23641488Smckusick 	if (ct_stat.c_aef & AEF_EOF) {
23741488Smckusick 		/* 9145 drives don't increment block number at EOF */
23854073Shibler 		if ((ct_stat.c_blk - rs->sc_blkno) == 0)
23954073Shibler 			rs->sc_blkno++;
24041488Smckusick 		else
24154073Shibler 			rs->sc_blkno = ct_stat.c_blk;
24241488Smckusick 		return (2);
24341488Smckusick 	}
24441488Smckusick 	printf("ct%d err: vu 0x%x, pend 0x%x, bn%d", unit,
24541488Smckusick 		ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk);
24641488Smckusick 	printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref,
24741488Smckusick 		ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief);
24841488Smckusick 	return (1);
24941488Smckusick }
250