No empty .Rs/.Re
[netbsd-mini2440.git] / sys / arch / hp300 / stand / common / ct.c
blob9892333d7e27ceb586561c4061185e80e8fe76bb
1 /* $NetBSD: ct.c,v 1.5 2005/12/11 12:17:19 christos Exp $ */
3 /*
4 * Copyright (c) 1982, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
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.
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.
31 * @(#)ct.c 8.1 (Berkeley) 7/15/93
35 * CS80 tape driver
37 #include <sys/param.h>
39 #include <machine/stdarg.h>
41 #include <hp300/dev/ctreg.h>
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>
48 struct ct_iocmd ct_ioc;
49 struct ct_rscmd ct_rsc;
50 struct ct_stat ct_stat;
51 struct ct_ssmcmd ct_ssmc;
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];
62 #define CTRETRY 5
63 #define MTFSF 10
64 #define MTREW 11
66 char ctio_buf[MAXBSIZE];
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 },
78 int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
80 static int ctinit(int, int);
81 static int ctident(int, int);
82 static int cterror(int, int);
84 int
85 ctinit(int ctlr, int unit)
87 struct ct_softc *rs = &ct_softc[ctlr][unit];
88 uint8_t stat;
90 if (hpibrecv(ctlr, unit, C_QSTAT, &stat, 1) != 1 || stat)
91 return 0;
92 if (ctident(ctlr, unit) < 0)
93 return 0;
94 memset(&ct_ssmc, 0, sizeof(ct_ssmc));
95 ct_ssmc.unit = C_SUNIT(rs->sc_punit);
96 ct_ssmc.cmd = C_SSM;
97 ct_ssmc.fefm = FEF_MASK;
98 ct_ssmc.refm = REF_MASK;
99 ct_ssmc.aefm = AEF_MASK;
100 ct_ssmc.iefm = IEF_MASK;
101 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&ct_ssmc, sizeof(ct_ssmc));
102 hpibswait(ctlr, unit);
103 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
104 rs->sc_alive = 1;
105 return 1;
109 ctident(int ctlr, int unit)
111 struct ct_describe desc;
112 uint8_t stat, cmd[3];
113 char name[7];
114 int id, i;
116 id = hpibid(ctlr, unit);
117 if ((id & 0x200) == 0)
118 return -1;
119 for (i = 0; i < nctinfo; i++)
120 if (id == ctinfo[i].hwid)
121 break;
122 if (i == nctinfo)
123 return -1;
124 ct_softc[ctlr][unit].sc_punit = ctinfo[i].punit;
125 id = i;
128 * Collect device description.
129 * Right now we only need this to differentiate 7945 from 7946.
130 * Note that we always issue the describe command to unit 0.
132 cmd[0] = C_SUNIT(0);
133 cmd[1] = C_SVOL(0);
134 cmd[2] = C_DESC;
135 hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd));
136 hpibrecv(ctlr, unit, C_EXEC, (uint8_t *)&desc, 37);
137 hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat));
138 memset(name, 0, sizeof(name));
139 if (!stat) {
140 int n = desc.d_name;
141 for (i = 5; i >= 0; i--) {
142 name[i] = (n & 0xf) + '0';
143 n >>= 4;
146 switch (ctinfo[id].hwid) {
147 case CT7946ID:
148 if (memcmp(name, "079450", 6) == 0)
149 id = -1; /* not really a 7946 */
150 break;
151 default:
152 break;
154 return id;
158 ctpunit(int ctlr, int slave, int *punit)
160 struct ct_softc *rs;
162 if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
163 return EADAPT;
164 if (slave >= NCT)
165 return ECTLR;
166 rs = &ct_softc[ctlr][slave];
168 if (rs->sc_alive == 0)
169 return ENXIO;
171 *punit = rs->sc_punit;
172 return 0;
176 ctopen(struct open_file *f, ...)
178 va_list ap;
179 int ctlr, unit, part;
180 struct ct_softc *rs;
181 int skip;
182 size_t resid;
184 va_start(ap, f);
185 ctlr = va_arg(ap, int);
186 unit = va_arg(ap, int);
187 part = va_arg(ap, int);
188 va_end(ap);
190 if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
191 return EADAPT;
192 if (unit >= NCT)
193 return ECTLR;
194 rs = &ct_softc[ctlr][unit];
195 rs->sc_blkno = 0;
196 rs->sc_unit = unit;
197 rs->sc_ctlr = ctlr;
198 if (rs->sc_alive == 0)
199 if (ctinit(ctlr, unit) == 0)
200 return ENXIO;
201 f->f_devdata = (void *)rs;
202 ctstrategy(f->f_devdata, MTREW, 0, 0, ctio_buf, &resid);
203 skip = part;
204 while (skip--)
205 ctstrategy(f->f_devdata, MTFSF, 0, 0, ctio_buf, &resid);
206 return 0;
210 ctclose(struct open_file *f)
212 size_t resid;
214 ctstrategy(f->f_devdata, MTREW, 0, 0, ctio_buf, &resid);
215 return 0;
219 ctstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *v_buf,
220 size_t *rsize)
222 struct ct_softc *rs = devdata;
223 uint8_t *buf = v_buf;
224 int ctlr = rs->sc_ctlr;
225 int unit = rs->sc_unit;
226 uint8_t stat;
228 if (size == 0 && (func == F_READ || func == F_WRITE))
229 return 0;
231 rs->sc_retry = 0;
232 memset(&ct_ioc, 0, sizeof(ct_ioc));
233 ct_ioc.unit = C_SUNIT(rs->sc_punit);
234 ct_ioc.saddr = C_SADDR;
235 ct_ioc.nop2 = C_NOP;
236 ct_ioc.slen = C_SLEN;
237 ct_ioc.nop3 = C_NOP;
238 top:
239 if (func == F_READ) {
240 ct_ioc.cmd = C_READ;
241 ct_ioc.addr = rs->sc_blkno;
242 ct_ioc.len = size;
244 else if (func == F_WRITE) {
245 ct_ioc.cmd = C_WRITE;
246 ct_ioc.addr = rs->sc_blkno;
247 ct_ioc.len = size;
249 else if (func == MTFSF) {
250 ct_ioc.cmd = C_READ;
251 ct_ioc.addr = rs->sc_blkno;
252 ct_ioc.len = size = MAXBSIZE;
254 else {
255 ct_ioc.cmd = C_READ;
256 ct_ioc.addr = 0;
257 ct_ioc.len = 0;
258 rs->sc_blkno = 0;
259 size = 0;
261 retry:
262 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&ct_ioc, sizeof(ct_ioc));
263 if (func != MTREW) {
264 hpibswait(ctlr, unit);
265 hpibgo(ctlr, unit, C_EXEC, buf, size,
266 func != F_WRITE ? F_READ : F_WRITE);
267 hpibswait(ctlr, unit);
268 } else {
269 while (hpibswait(ctlr, unit) < 0)
272 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
273 if (stat) {
274 stat = cterror(ctlr, unit);
275 if (stat == 0)
276 return -1;
277 if (stat == 2)
278 return 0;
279 if (++rs->sc_retry > CTRETRY)
280 return -1;
281 goto retry;
283 rs->sc_blkno += CTBTOK(size);
284 if (func == MTFSF)
285 goto top;
286 *rsize = size;
288 return 0;
292 cterror(int ctlr, int unit)
294 struct ct_softc *rs = &ct_softc[ctlr][unit];
295 uint8_t stat;
297 memset(&ct_rsc, 0, sizeof(ct_rsc));
298 memset(&ct_stat, 0, sizeof(ct_stat));
299 ct_rsc.unit = C_SUNIT(rs->sc_punit);
300 ct_rsc.cmd = C_STATUS;
301 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&ct_rsc, sizeof(ct_rsc));
302 hpibrecv(ctlr, unit, C_EXEC, (uint8_t *)&ct_stat, sizeof(ct_stat));
303 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
304 if (stat) {
305 printf("ct%d: request status fail %d\n", unit, stat);
306 return 0;
308 if (ct_stat.c_aef & AEF_EOF) {
309 /* 9145 drives don't increment block number at EOF */
310 if ((ct_stat.c_blk - rs->sc_blkno) == 0)
311 rs->sc_blkno++;
312 else
313 rs->sc_blkno = ct_stat.c_blk;
314 return 2;
316 printf("ct%d err: vu 0x%x, pend 0x%x, bn%ld", unit,
317 ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk);
318 printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref,
319 ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief);
320 return 1;