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