ct.c revision 1.1.60.1 1 /* $NetBSD: ct.c,v 1.1.60.1 2004/08/03 10:34:37 skrll 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