1 /* $NetBSD: ct.c,v 1.8 2021/07/05 14:51:23 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 <hp300/dev/ctreg.h>
40
41 #include <lib/libsa/stand.h>
42 #include <hp300/stand/common/conf.h>
43 #include <hp300/stand/common/hpibvar.h>
44 #include <hp300/stand/common/samachdep.h>
45
46 struct ct_iocmd ct_ioc;
47 struct ct_rscmd ct_rsc;
48 struct ct_stat ct_stat;
49 struct ct_ssmcmd ct_ssmc;
50
51 struct ct_softc {
52 int sc_ctlr;
53 int sc_unit;
54 char sc_retry;
55 char sc_alive;
56 short sc_punit;
57 int sc_blkno;
58 } ct_softc[NHPIB][NCT];
59
60 #define CTRETRY 5
61 #define MTFSF 10
62 #define MTREW 11
63
64 char ctio_buf[MAXBSIZE];
65
66 struct ctinfo {
67 short hwid;
68 short punit;
69 } ctinfo[] = {
70 { CT7946ID, 1 },
71 { CT7912PID, 1 },
72 { CT7914PID, 1 },
73 { CT9144ID, 0 },
74 { CT9145ID, 0 },
75 };
76 int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
77
78 static int ctinit(int, int);
79 static int ctident(int, int);
80 static int cterror(int, int);
81
82 int
ctinit(int ctlr,int unit)83 ctinit(int ctlr, int unit)
84 {
85 struct ct_softc *rs = &ct_softc[ctlr][unit];
86 uint8_t stat;
87
88 if (hpibrecv(ctlr, unit, C_QSTAT, &stat, 1) != 1 || stat)
89 return 0;
90 if (ctident(ctlr, unit) < 0)
91 return 0;
92 memset(&ct_ssmc, 0, sizeof(ct_ssmc));
93 ct_ssmc.unit = C_SUNIT(rs->sc_punit);
94 ct_ssmc.cmd = C_SSM;
95 ct_ssmc.fefm = FEF_MASK;
96 ct_ssmc.refm = REF_MASK;
97 ct_ssmc.aefm = AEF_MASK;
98 ct_ssmc.iefm = IEF_MASK;
99 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&ct_ssmc, sizeof(ct_ssmc));
100 hpibswait(ctlr, unit);
101 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
102 rs->sc_alive = 1;
103 return 1;
104 }
105
106 int
ctident(int ctlr,int unit)107 ctident(int ctlr, int unit)
108 {
109 struct cs80_describe desc;
110 uint8_t stat, cmd[3];
111 char name[7];
112 int id, i;
113
114 id = hpibid(ctlr, unit);
115 if ((id & 0x200) == 0)
116 return -1;
117 for (i = 0; i < nctinfo; i++)
118 if (id == ctinfo[i].hwid)
119 break;
120 if (i == nctinfo)
121 return -1;
122 ct_softc[ctlr][unit].sc_punit = ctinfo[i].punit;
123 id = i;
124
125 /*
126 * Collect device description.
127 * Right now we only need this to differentiate 7945 from 7946.
128 * Note that we always issue the describe command to unit 0.
129 */
130 cmd[0] = C_SUNIT(0);
131 cmd[1] = C_SVOL(0);
132 cmd[2] = C_DESC;
133 hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd));
134 hpibrecv(ctlr, unit, C_EXEC, (uint8_t *)&desc, sizeof(desc));
135 hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat));
136 memset(name, 0, sizeof(name));
137 if (!stat) {
138 int n = desc.d_name;
139 for (i = 5; i >= 0; i--) {
140 name[i] = (n & 0xf) + '0';
141 n >>= 4;
142 }
143 }
144 switch (ctinfo[id].hwid) {
145 case CT7946ID:
146 if (memcmp(name, "079450", 6) == 0)
147 id = -1; /* not really a 7946 */
148 break;
149 default:
150 break;
151 }
152 return id;
153 }
154
155 int
ctpunit(int ctlr,int slave,int * punit)156 ctpunit(int ctlr, int slave, int *punit)
157 {
158 struct ct_softc *rs;
159
160 if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
161 return EADAPT;
162 if (slave >= NCT)
163 return ECTLR;
164 rs = &ct_softc[ctlr][slave];
165
166 if (rs->sc_alive == 0)
167 return ENXIO;
168
169 *punit = rs->sc_punit;
170 return 0;
171 }
172
173 int
ctopen(struct open_file * f,...)174 ctopen(struct open_file *f, ...)
175 {
176 va_list ap;
177 int ctlr, unit, part;
178 struct ct_softc *rs;
179 int skip;
180 size_t resid;
181
182 va_start(ap, f);
183 ctlr = va_arg(ap, int);
184 unit = va_arg(ap, int);
185 part = va_arg(ap, int);
186 va_end(ap);
187
188 if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
189 return EADAPT;
190 if (unit >= NCT)
191 return ECTLR;
192 rs = &ct_softc[ctlr][unit];
193 rs->sc_blkno = 0;
194 rs->sc_unit = unit;
195 rs->sc_ctlr = ctlr;
196 if (rs->sc_alive == 0)
197 if (ctinit(ctlr, unit) == 0)
198 return ENXIO;
199 f->f_devdata = (void *)rs;
200 ctstrategy(f->f_devdata, MTREW, 0, 0, ctio_buf, &resid);
201 skip = part;
202 while (skip--)
203 ctstrategy(f->f_devdata, MTFSF, 0, 0, ctio_buf, &resid);
204 return 0;
205 }
206
207 int
ctclose(struct open_file * f)208 ctclose(struct open_file *f)
209 {
210 size_t resid;
211
212 ctstrategy(f->f_devdata, MTREW, 0, 0, ctio_buf, &resid);
213 return 0;
214 }
215
216 int
ctstrategy(void * devdata,int func,daddr_t dblk,size_t size,void * v_buf,size_t * rsize)217 ctstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *v_buf,
218 size_t *rsize)
219 {
220 struct ct_softc *rs = devdata;
221 uint8_t *buf = v_buf;
222 int ctlr = rs->sc_ctlr;
223 int unit = rs->sc_unit;
224 uint8_t stat;
225
226 if (size == 0 && (func == F_READ || func == F_WRITE))
227 return 0;
228
229 rs->sc_retry = 0;
230 memset(&ct_ioc, 0, sizeof(ct_ioc));
231 ct_ioc.unit = C_SUNIT(rs->sc_punit);
232 ct_ioc.saddr = C_SADDR;
233 ct_ioc.nop2 = C_NOP;
234 ct_ioc.slen = C_SLEN;
235 ct_ioc.nop3 = C_NOP;
236 top:
237 if (func == F_READ) {
238 ct_ioc.cmd = C_READ;
239 ct_ioc.addr = rs->sc_blkno;
240 ct_ioc.len = size;
241 }
242 else if (func == F_WRITE) {
243 ct_ioc.cmd = C_WRITE;
244 ct_ioc.addr = rs->sc_blkno;
245 ct_ioc.len = size;
246 }
247 else if (func == MTFSF) {
248 ct_ioc.cmd = C_READ;
249 ct_ioc.addr = rs->sc_blkno;
250 ct_ioc.len = size = MAXBSIZE;
251 }
252 else {
253 ct_ioc.cmd = C_READ;
254 ct_ioc.addr = 0;
255 ct_ioc.len = 0;
256 rs->sc_blkno = 0;
257 size = 0;
258 }
259 retry:
260 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&ct_ioc, sizeof(ct_ioc));
261 if (func != MTREW) {
262 hpibswait(ctlr, unit);
263 hpibgo(ctlr, unit, C_EXEC, buf, size,
264 func != F_WRITE ? F_READ : F_WRITE);
265 hpibswait(ctlr, unit);
266 } else {
267 while (hpibswait(ctlr, unit) < 0)
268 ;
269 }
270 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
271 if (stat) {
272 stat = cterror(ctlr, unit);
273 if (stat == 0)
274 return -1;
275 if (stat == 2)
276 return 0;
277 if (++rs->sc_retry > CTRETRY)
278 return -1;
279 goto retry;
280 }
281 rs->sc_blkno += CTBTOK(size);
282 if (func == MTFSF)
283 goto top;
284 *rsize = size;
285
286 return 0;
287 }
288
289 int
cterror(int ctlr,int unit)290 cterror(int ctlr, int unit)
291 {
292 struct ct_softc *rs = &ct_softc[ctlr][unit];
293 uint8_t stat;
294
295 memset(&ct_rsc, 0, sizeof(ct_rsc));
296 memset(&ct_stat, 0, sizeof(ct_stat));
297 ct_rsc.unit = C_SUNIT(rs->sc_punit);
298 ct_rsc.cmd = C_STATUS;
299 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&ct_rsc, sizeof(ct_rsc));
300 hpibrecv(ctlr, unit, C_EXEC, (uint8_t *)&ct_stat, sizeof(ct_stat));
301 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
302 if (stat) {
303 printf("ct%d: request status fail %d\n", unit, stat);
304 return 0;
305 }
306 if (ct_stat.c_aef & AEF_EOF) {
307 /* 9145 drives don't increment block number at EOF */
308 if ((ct_stat.c_blk - rs->sc_blkno) == 0)
309 rs->sc_blkno++;
310 else
311 rs->sc_blkno = ct_stat.c_blk;
312 return 2;
313 }
314 printf("ct%d err: vu 0x%x, pend 0x%x, bn%ld", unit,
315 ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk);
316 printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref,
317 ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief);
318 return 1;
319 }
320