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