xref: /csrg-svn/sys/hp300/stand/ct.c (revision 41488)
1*41488Smckusick /*
2*41488Smckusick  * Copyright (c) 1982, 1990 The Regents of the University of California.
3*41488Smckusick  * All rights reserved.
4*41488Smckusick  *
5*41488Smckusick  * %sccs.include.redist.c%
6*41488Smckusick  *
7*41488Smckusick  *	@(#)ct.c	7.1 (Berkeley) 05/08/90
8*41488Smckusick  */
9*41488Smckusick 
10*41488Smckusick /*
11*41488Smckusick  * CS80 tape driver
12*41488Smckusick  */
13*41488Smckusick #include "../sys/types.h"
14*41488Smckusick #include "../hpdev/ctreg.h"
15*41488Smckusick 
16*41488Smckusick #include "saio.h"
17*41488Smckusick #include "samachdep.h"
18*41488Smckusick 
19*41488Smckusick struct	ct_iocmd ct_ioc;
20*41488Smckusick struct	ct_rscmd ct_rsc;
21*41488Smckusick struct	ct_stat ct_stat;
22*41488Smckusick struct	ct_ssmcmd ct_ssmc;
23*41488Smckusick 
24*41488Smckusick struct	ct_softc {
25*41488Smckusick 	char	sc_retry;
26*41488Smckusick 	char	sc_alive;
27*41488Smckusick 	short	sc_punit;
28*41488Smckusick 	int	sc_blkno;
29*41488Smckusick } ct_softc[NCT];
30*41488Smckusick 
31*41488Smckusick #define	CTRETRY		5
32*41488Smckusick #define	MTFSF		10
33*41488Smckusick #define	MTREW		11
34*41488Smckusick 
35*41488Smckusick struct	ctinfo {
36*41488Smckusick 	short	hwid;
37*41488Smckusick 	short	punit;
38*41488Smckusick } ctinfo[] = {
39*41488Smckusick 	CT7946ID,	1,
40*41488Smckusick 	CT7912PID,	1,
41*41488Smckusick 	CT7914PID,	1,
42*41488Smckusick 	CT9144ID,	0,
43*41488Smckusick 	CT9145ID,	0,
44*41488Smckusick };
45*41488Smckusick int	nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
46*41488Smckusick 
47*41488Smckusick ctinit(unit)
48*41488Smckusick 	register int unit;
49*41488Smckusick {
50*41488Smckusick 	register struct ct_softc *rs = &ct_softc[unit];
51*41488Smckusick 	u_char stat;
52*41488Smckusick 	register int type;
53*41488Smckusick 
54*41488Smckusick 	if (hpibrecv(unit, C_QSTAT, &stat, 1) != 1 || stat)
55*41488Smckusick 		return (0);
56*41488Smckusick 	if (ctident(unit) < 0)
57*41488Smckusick 		return (0);
58*41488Smckusick 	ct_ssmc.unit = C_SUNIT(rs->sc_punit);
59*41488Smckusick 	ct_ssmc.cmd = C_SSM;
60*41488Smckusick 	ct_ssmc.fefm = FEF_MASK;
61*41488Smckusick 	ct_ssmc.refm = REF_MASK;
62*41488Smckusick 	ct_ssmc.aefm = AEF_MASK;
63*41488Smckusick 	ct_ssmc.iefm = IEF_MASK;
64*41488Smckusick 	hpibsend(unit, C_CMD, &ct_ssmc, sizeof(ct_ssmc));
65*41488Smckusick 	hpibswait(unit);
66*41488Smckusick 	hpibrecv(unit, C_QSTAT, &stat, 1);
67*41488Smckusick 	rs->sc_alive = 1;
68*41488Smckusick 	return (1);
69*41488Smckusick }
70*41488Smckusick 
71*41488Smckusick ctident(unit)
72*41488Smckusick 	int unit;
73*41488Smckusick {
74*41488Smckusick 	struct ct_describe desc;
75*41488Smckusick 	u_char stat, cmd[3];
76*41488Smckusick 	char name[7];
77*41488Smckusick 	int id, i;
78*41488Smckusick 
79*41488Smckusick 	id = hpibid(unit);
80*41488Smckusick 	if ((id & 0x200) == 0)
81*41488Smckusick 		return(-1);
82*41488Smckusick 	for (i = 0; i < nctinfo; i++)
83*41488Smckusick 		if (id == ctinfo[i].hwid)
84*41488Smckusick 			break;
85*41488Smckusick 	if (i == nctinfo)
86*41488Smckusick 		return(-1);
87*41488Smckusick 	ct_softc[unit].sc_punit = ctinfo[i].punit;
88*41488Smckusick 	id = i;
89*41488Smckusick 
90*41488Smckusick 	/*
91*41488Smckusick 	 * Collect device description.
92*41488Smckusick 	 * Right now we only need this to differentiate 7945 from 7946.
93*41488Smckusick 	 * Note that we always issue the describe command to unit 0.
94*41488Smckusick 	 */
95*41488Smckusick 	cmd[0] = C_SUNIT(0);
96*41488Smckusick 	cmd[1] = C_SVOL(0);
97*41488Smckusick 	cmd[2] = C_DESC;
98*41488Smckusick 	hpibsend(unit, C_CMD, cmd, sizeof(cmd));
99*41488Smckusick 	hpibrecv(unit, C_EXEC, &desc, 37);
100*41488Smckusick 	hpibrecv(unit, C_QSTAT, &stat, sizeof(stat));
101*41488Smckusick 	bzero(name, sizeof(name));
102*41488Smckusick 	if (!stat) {
103*41488Smckusick 		register int n = desc.d_name;
104*41488Smckusick 		for (i = 5; i >= 0; i--) {
105*41488Smckusick 			name[i] = (n & 0xf) + '0';
106*41488Smckusick 			n >>= 4;
107*41488Smckusick 		}
108*41488Smckusick 	}
109*41488Smckusick 	switch (ctinfo[id].hwid) {
110*41488Smckusick 	case CT7946ID:
111*41488Smckusick 		if (bcmp(name, "079450", 6) == 0)
112*41488Smckusick 			id = -1;		/* not really a 7946 */
113*41488Smckusick 		break;
114*41488Smckusick 	default:
115*41488Smckusick 		break;
116*41488Smckusick 	}
117*41488Smckusick 	return(id);
118*41488Smckusick }
119*41488Smckusick 
120*41488Smckusick ctopen(io)
121*41488Smckusick 	struct iob *io;
122*41488Smckusick {
123*41488Smckusick 	register int unit = io->i_unit;
124*41488Smckusick 	register struct ct_softc *rs = &ct_softc[unit];
125*41488Smckusick 	register int skip;
126*41488Smckusick 
127*41488Smckusick 	if (hpibalive(unit) == 0)
128*41488Smckusick 		_stop("ct controller not configured");
129*41488Smckusick 	if (rs->sc_alive == 0)
130*41488Smckusick 		if (ctinit(unit) == 0)
131*41488Smckusick 			_stop("ct init failed");
132*41488Smckusick 	ctstrategy(io, MTREW);
133*41488Smckusick 	skip = io->i_boff;
134*41488Smckusick 	while (skip--)
135*41488Smckusick 		ctstrategy(io, MTFSF);
136*41488Smckusick }
137*41488Smckusick 
138*41488Smckusick ctclose(io)
139*41488Smckusick 	struct iob *io;
140*41488Smckusick {
141*41488Smckusick 	ctstrategy(io, MTREW);
142*41488Smckusick }
143*41488Smckusick 
144*41488Smckusick ctstrategy(io, func)
145*41488Smckusick 	register struct iob *io;
146*41488Smckusick 	register int func;
147*41488Smckusick {
148*41488Smckusick 	register int unit = io->i_unit;
149*41488Smckusick 	register struct ct_softc *rs = &ct_softc[unit];
150*41488Smckusick 	char stat;
151*41488Smckusick 
152*41488Smckusick 	rs->sc_retry = 0;
153*41488Smckusick 	ct_ioc.unit = C_SUNIT(rs->sc_punit);
154*41488Smckusick 	ct_ioc.saddr = C_SADDR;
155*41488Smckusick 	ct_ioc.nop2 = C_NOP;
156*41488Smckusick 	ct_ioc.slen = C_SLEN;
157*41488Smckusick 	ct_ioc.nop3 = C_NOP;
158*41488Smckusick top:
159*41488Smckusick 	if (func == READ) {
160*41488Smckusick 		ct_ioc.cmd = C_READ;
161*41488Smckusick 		ct_ioc.addr = rs->sc_blkno;
162*41488Smckusick 		ct_ioc.len = io->i_cc;
163*41488Smckusick 	}
164*41488Smckusick 	else if (func == WRITE) {
165*41488Smckusick 		ct_ioc.cmd = C_WRITE;
166*41488Smckusick 		ct_ioc.addr = rs->sc_blkno;
167*41488Smckusick 		ct_ioc.len = io->i_cc;
168*41488Smckusick 	}
169*41488Smckusick 	else if (func == MTFSF) {
170*41488Smckusick 		ct_ioc.cmd = C_READ;
171*41488Smckusick 		ct_ioc.addr = rs->sc_blkno;
172*41488Smckusick 		ct_ioc.len = io->i_cc = MAXBSIZE;
173*41488Smckusick 		io->i_ma = io->i_buf;
174*41488Smckusick 	}
175*41488Smckusick 	else {
176*41488Smckusick 		ct_ioc.cmd = C_READ;
177*41488Smckusick 		ct_ioc.addr = 0;
178*41488Smckusick 		ct_ioc.len = 0;
179*41488Smckusick 		rs->sc_blkno = 0;
180*41488Smckusick 		io->i_cc = 0;
181*41488Smckusick 	}
182*41488Smckusick retry:
183*41488Smckusick 	hpibsend(unit, C_CMD, &ct_ioc, sizeof(ct_ioc));
184*41488Smckusick 	if (func != MTREW) {
185*41488Smckusick 		hpibswait(unit);
186*41488Smckusick 		hpibgo(unit, C_EXEC, io->i_ma, io->i_cc,
187*41488Smckusick 			func != WRITE ? READ : WRITE);
188*41488Smckusick 		hpibswait(unit);
189*41488Smckusick 	}
190*41488Smckusick 	else {
191*41488Smckusick 		while (hpibswait(unit) < 0)
192*41488Smckusick 			;
193*41488Smckusick 	}
194*41488Smckusick 	hpibrecv(unit, C_QSTAT, &stat, 1);
195*41488Smckusick 	if (stat) {
196*41488Smckusick 		stat = cterror(unit);
197*41488Smckusick 		if (stat == 0)
198*41488Smckusick 			return (-1);
199*41488Smckusick 		if (stat == 2)
200*41488Smckusick 			return (0);
201*41488Smckusick 		if (++rs->sc_retry > CTRETRY)
202*41488Smckusick 			return (-1);
203*41488Smckusick 		else
204*41488Smckusick 			goto retry;
205*41488Smckusick 	}
206*41488Smckusick 	rs->sc_blkno += CTBTOK(io->i_cc);
207*41488Smckusick 	if (func == MTFSF)
208*41488Smckusick 		goto top;
209*41488Smckusick 	return (io->i_cc);
210*41488Smckusick }
211*41488Smckusick 
212*41488Smckusick cterror(unit)
213*41488Smckusick 	register int unit;
214*41488Smckusick {
215*41488Smckusick 	register struct ct_softc *ct = &ct_softc[unit];
216*41488Smckusick 	char stat;
217*41488Smckusick 
218*41488Smckusick 	ct_rsc.unit = C_SUNIT(ct->sc_punit);
219*41488Smckusick 	ct_rsc.cmd = C_STATUS;
220*41488Smckusick 	hpibsend(unit, C_CMD, &ct_rsc, sizeof(ct_rsc));
221*41488Smckusick 	hpibrecv(unit, C_EXEC, &ct_stat, sizeof(ct_stat));
222*41488Smckusick 	hpibrecv(unit, C_QSTAT, &stat, 1);
223*41488Smckusick 	if (stat) {
224*41488Smckusick 		printf("ct%d: request status fail %d\n", unit, stat);
225*41488Smckusick 		return(0);
226*41488Smckusick 	}
227*41488Smckusick 	if (ct_stat.c_aef & AEF_EOF) {
228*41488Smckusick 		/* 9145 drives don't increment block number at EOF */
229*41488Smckusick 		if ((ct_stat.c_blk - ct->sc_blkno) == 0)
230*41488Smckusick 			ct->sc_blkno++;
231*41488Smckusick 		else
232*41488Smckusick 			ct->sc_blkno = ct_stat.c_blk;
233*41488Smckusick 		return (2);
234*41488Smckusick 	}
235*41488Smckusick 	printf("ct%d err: vu 0x%x, pend 0x%x, bn%d", unit,
236*41488Smckusick 		ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk);
237*41488Smckusick 	printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref,
238*41488Smckusick 		ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief);
239*41488Smckusick 	return (1);
240*41488Smckusick }
241