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