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