xref: /netbsd-src/sys/arch/hp300/stand/common/ct.c (revision de1dfb1250df962f1ff3a011772cf58e605aed11)
1 /*	$NetBSD: ct.c,v 1.3 2003/11/14 16:52:40 tsutsui Exp $	*/
2 
3 /*
4  * Copyright (c) 1982, 1990, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  *	@(#)ct.c	8.1 (Berkeley) 7/15/93
32  */
33 
34 /*
35  * CS80 tape driver
36  */
37 #include <sys/param.h>
38 
39 #include <machine/stdarg.h>
40 
41 #include <hp300/dev/ctreg.h>
42 
43 #include <lib/libsa/stand.h>
44 #include <hp300/stand/common/conf.h>
45 #include <hp300/stand/common/hpibvar.h>
46 #include <hp300/stand/common/samachdep.h>
47 
48 struct	ct_iocmd ct_ioc;
49 struct	ct_rscmd ct_rsc;
50 struct	ct_stat ct_stat;
51 struct	ct_ssmcmd ct_ssmc;
52 
53 struct	ct_softc {
54 	int	sc_ctlr;
55 	int	sc_unit;
56 	char	sc_retry;
57 	char	sc_alive;
58 	short	sc_punit;
59 	int	sc_blkno;
60 } ct_softc[NHPIB][NCT];
61 
62 #define	CTRETRY		5
63 #define	MTFSF		10
64 #define	MTREW		11
65 
66 char ctio_buf[MAXBSIZE];
67 
68 struct	ctinfo {
69 	short	hwid;
70 	short	punit;
71 } ctinfo[] = {
72 	{ CT7946ID,	1 },
73 	{ CT7912PID,	1 },
74 	{ CT7914PID,	1 },
75 	{ CT9144ID,	0 },
76 	{ CT9145ID,	0 },
77 };
78 int	nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
79 
80 static int ctinit(int, int);
81 static int ctident(int, int);
82 static int cterror(int, int);
83 
84 int
85 ctinit(ctlr, unit)
86 	int ctlr, unit;
87 {
88 	struct ct_softc *rs = &ct_softc[ctlr][unit];
89 	u_char stat;
90 
91 	if (hpibrecv(ctlr, unit, C_QSTAT, &stat, 1) != 1 || stat)
92 		return 0;
93 	if (ctident(ctlr, unit) < 0)
94 		return 0;
95 	memset(&ct_ssmc, 0, sizeof(ct_ssmc));
96 	ct_ssmc.unit = C_SUNIT(rs->sc_punit);
97 	ct_ssmc.cmd = C_SSM;
98 	ct_ssmc.fefm = FEF_MASK;
99 	ct_ssmc.refm = REF_MASK;
100 	ct_ssmc.aefm = AEF_MASK;
101 	ct_ssmc.iefm = IEF_MASK;
102 	hpibsend(ctlr, unit, C_CMD, (char *)&ct_ssmc, sizeof(ct_ssmc));
103 	hpibswait(ctlr, unit);
104 	hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
105 	rs->sc_alive = 1;
106 	return 1;
107 }
108 
109 int
110 ctident(ctlr, unit)
111 	int ctlr, unit;
112 {
113 	struct ct_describe desc;
114 	u_char stat, cmd[3];
115 	char name[7];
116 	int id, i;
117 
118 	id = hpibid(ctlr, unit);
119 	if ((id & 0x200) == 0)
120 		return -1;
121 	for (i = 0; i < nctinfo; i++)
122 		if (id == ctinfo[i].hwid)
123 			break;
124 	if (i == nctinfo)
125 		return -1;
126 	ct_softc[ctlr][unit].sc_punit = ctinfo[i].punit;
127 	id = i;
128 
129 	/*
130 	 * Collect device description.
131 	 * Right now we only need this to differentiate 7945 from 7946.
132 	 * Note that we always issue the describe command to unit 0.
133 	 */
134 	cmd[0] = C_SUNIT(0);
135 	cmd[1] = C_SVOL(0);
136 	cmd[2] = C_DESC;
137 	hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd));
138 	hpibrecv(ctlr, unit, C_EXEC, (char *)&desc, 37);
139 	hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat));
140 	memset(name, 0, sizeof(name));
141 	if (!stat) {
142 		int n = desc.d_name;
143 		for (i = 5; i >= 0; i--) {
144 			name[i] = (n & 0xf) + '0';
145 			n >>= 4;
146 		}
147 	}
148 	switch (ctinfo[id].hwid) {
149 	case CT7946ID:
150 		if (memcmp(name, "079450", 6) == 0)
151 			id = -1;		/* not really a 7946 */
152 		break;
153 	default:
154 		break;
155 	}
156 	return id;
157 }
158 
159 int
160 ctpunit(ctlr, slave, punit)
161 	int ctlr, slave, *punit;
162 {
163 	struct ct_softc *rs;
164 
165 	if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
166 		return EADAPT;
167 	if (slave >= NCT)
168 		return ECTLR;
169 	rs = &ct_softc[ctlr][slave];
170 
171 	if (rs->sc_alive == 0)
172 		return ENXIO;
173 
174 	*punit = rs->sc_punit;
175 	return 0;
176 }
177 
178 int
179 ctopen(struct open_file *f, ...)
180 {
181 	va_list ap;
182 	int ctlr, unit, part;
183 	struct ct_softc *rs;
184 	int skip;
185 	size_t resid;
186 
187 	va_start(ap, f);
188 	ctlr = va_arg(ap, int);
189 	unit = va_arg(ap, int);
190 	part = va_arg(ap, int);
191 	va_end(ap);
192 
193 	if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
194 		return EADAPT;
195 	if (unit >= NCT)
196 		return ECTLR;
197 	rs = &ct_softc[ctlr][unit];
198 	rs->sc_blkno = 0;
199 	rs->sc_unit = unit;
200 	rs->sc_ctlr = ctlr;
201 	if (rs->sc_alive == 0)
202 		if (ctinit(ctlr, unit) == 0)
203 			return ENXIO;
204 	f->f_devdata = (void *)rs;
205 	ctstrategy(f->f_devdata, MTREW, 0, 0, ctio_buf, &resid);
206 	skip = part;
207 	while (skip--)
208 		ctstrategy(f->f_devdata, MTFSF, 0, 0, ctio_buf, &resid);
209 	return 0;
210 }
211 
212 int
213 ctclose(f)
214 	struct open_file *f;
215 {
216 	size_t resid;
217 
218 	ctstrategy(f->f_devdata, MTREW, 0, 0, ctio_buf, &resid);
219 	return 0;
220 }
221 
222 int
223 ctstrategy(devdata, func, dblk, size, v_buf, rsize)
224 	void *devdata;
225 	int func;
226 	daddr_t dblk;
227 	size_t size;
228 	void *v_buf;
229 	size_t *rsize;
230 {
231 	struct ct_softc *rs = devdata;
232 	char *buf = v_buf;
233 	int ctlr = rs->sc_ctlr;
234 	int unit = rs->sc_unit;
235 	char stat;
236 
237 	if (size == 0 && (func == F_READ || func == F_WRITE))
238 		return 0;
239 
240 	rs->sc_retry = 0;
241 	memset(&ct_ioc, 0, sizeof(ct_ioc));
242 	ct_ioc.unit = C_SUNIT(rs->sc_punit);
243 	ct_ioc.saddr = C_SADDR;
244 	ct_ioc.nop2 = C_NOP;
245 	ct_ioc.slen = C_SLEN;
246 	ct_ioc.nop3 = C_NOP;
247 top:
248 	if (func == F_READ) {
249 		ct_ioc.cmd = C_READ;
250 		ct_ioc.addr = rs->sc_blkno;
251 		ct_ioc.len = size;
252 	}
253 	else if (func == F_WRITE) {
254 		ct_ioc.cmd = C_WRITE;
255 		ct_ioc.addr = rs->sc_blkno;
256 		ct_ioc.len = size;
257 	}
258 	else if (func == MTFSF) {
259 		ct_ioc.cmd = C_READ;
260 		ct_ioc.addr = rs->sc_blkno;
261 		ct_ioc.len = size = MAXBSIZE;
262 	}
263 	else {
264 		ct_ioc.cmd = C_READ;
265 		ct_ioc.addr = 0;
266 		ct_ioc.len = 0;
267 		rs->sc_blkno = 0;
268 		size = 0;
269 	}
270 retry:
271 	hpibsend(ctlr, unit, C_CMD, (char *)&ct_ioc, sizeof(ct_ioc));
272 	if (func != MTREW) {
273 		hpibswait(ctlr, unit);
274 		hpibgo(ctlr, unit, C_EXEC, buf, size,
275 			func != F_WRITE ? F_READ : F_WRITE);
276 		hpibswait(ctlr, unit);
277 	} else {
278 		while (hpibswait(ctlr, unit) < 0)
279 			;
280 	}
281 	hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
282 	if (stat) {
283 		stat = cterror(ctlr, unit);
284 		if (stat == 0)
285 			return -1;
286 		if (stat == 2)
287 			return 0;
288 		if (++rs->sc_retry > CTRETRY)
289 			return -1;
290 		goto retry;
291 	}
292 	rs->sc_blkno += CTBTOK(size);
293 	if (func == MTFSF)
294 		goto top;
295 	*rsize = size;
296 
297 	return 0;
298 }
299 
300 int
301 cterror(ctlr, unit)
302 	int ctlr, unit;
303 {
304 	struct ct_softc *rs = &ct_softc[ctlr][unit];
305 	char stat;
306 
307 	memset(&ct_rsc, 0, sizeof(ct_rsc));
308 	memset(&ct_stat, 0, sizeof(ct_stat));
309 	ct_rsc.unit = C_SUNIT(rs->sc_punit);
310 	ct_rsc.cmd = C_STATUS;
311 	hpibsend(ctlr, unit, C_CMD, (char *)&ct_rsc, sizeof(ct_rsc));
312 	hpibrecv(ctlr, unit, C_EXEC, (char *)&ct_stat, sizeof(ct_stat));
313 	hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
314 	if (stat) {
315 		printf("ct%d: request status fail %d\n", unit, stat);
316 		return 0;
317 	}
318 	if (ct_stat.c_aef & AEF_EOF) {
319 		/* 9145 drives don't increment block number at EOF */
320 		if ((ct_stat.c_blk - rs->sc_blkno) == 0)
321 			rs->sc_blkno++;
322 		else
323 			rs->sc_blkno = ct_stat.c_blk;
324 		return 2;
325 	}
326 	printf("ct%d err: vu 0x%x, pend 0x%x, bn%ld", unit,
327 	    ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk);
328 	printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref,
329 	    ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief);
330 	return 1;
331 }
332