|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
33: * @(#)ct.c 7.3 (Berkeley) 5/5/91
34: */
35:
36: /*
37: * CS80 tape driver
38: */
39: #include <sys/param.h>
40: #include "../dev/ctreg.h"
41:
42: #include "saio.h"
43: #include "samachdep.h"
44:
45: struct ct_iocmd ct_ioc;
46: struct ct_rscmd ct_rsc;
47: struct ct_stat ct_stat;
48: struct ct_ssmcmd ct_ssmc;
49:
50: struct ct_softc {
51: char sc_retry;
52: char sc_alive;
53: short sc_punit;
54: int sc_blkno;
55: } ct_softc[NCT];
56:
57: #define CTRETRY 5
58: #define MTFSF 10
59: #define MTREW 11
60:
61: struct ctinfo {
62: short hwid;
63: short punit;
64: } ctinfo[] = {
65: CT7946ID, 1,
66: CT7912PID, 1,
67: CT7914PID, 1,
68: CT9144ID, 0,
69: CT9145ID, 0,
70: };
71: int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
72:
73: ctinit(unit)
74: register int unit;
75: {
76: register struct ct_softc *rs = &ct_softc[unit];
77: u_char stat;
78: register int type;
79:
80: if (hpibrecv(unit, C_QSTAT, &stat, 1) != 1 || stat)
81: return (0);
82: if (ctident(unit) < 0)
83: return (0);
84: ct_ssmc.unit = C_SUNIT(rs->sc_punit);
85: ct_ssmc.cmd = C_SSM;
86: ct_ssmc.fefm = FEF_MASK;
87: ct_ssmc.refm = REF_MASK;
88: ct_ssmc.aefm = AEF_MASK;
89: ct_ssmc.iefm = IEF_MASK;
90: hpibsend(unit, C_CMD, &ct_ssmc, sizeof(ct_ssmc));
91: hpibswait(unit);
92: hpibrecv(unit, C_QSTAT, &stat, 1);
93: rs->sc_alive = 1;
94: return (1);
95: }
96:
97: ctident(unit)
98: int unit;
99: {
100: struct ct_describe desc;
101: u_char stat, cmd[3];
102: char name[7];
103: int id, i;
104:
105: id = hpibid(unit);
106: if ((id & 0x200) == 0)
107: return(-1);
108: for (i = 0; i < nctinfo; i++)
109: if (id == ctinfo[i].hwid)
110: break;
111: if (i == nctinfo)
112: return(-1);
113: ct_softc[unit].sc_punit = ctinfo[i].punit;
114: id = i;
115:
116: /*
117: * Collect device description.
118: * Right now we only need this to differentiate 7945 from 7946.
119: * Note that we always issue the describe command to unit 0.
120: */
121: cmd[0] = C_SUNIT(0);
122: cmd[1] = C_SVOL(0);
123: cmd[2] = C_DESC;
124: hpibsend(unit, C_CMD, cmd, sizeof(cmd));
125: hpibrecv(unit, C_EXEC, &desc, 37);
126: hpibrecv(unit, C_QSTAT, &stat, sizeof(stat));
127: bzero(name, sizeof(name));
128: if (!stat) {
129: register int n = desc.d_name;
130: for (i = 5; i >= 0; i--) {
131: name[i] = (n & 0xf) + '0';
132: n >>= 4;
133: }
134: }
135: switch (ctinfo[id].hwid) {
136: case CT7946ID:
137: if (bcmp(name, "079450", 6) == 0)
138: id = -1; /* not really a 7946 */
139: break;
140: default:
141: break;
142: }
143: return(id);
144: }
145:
146: ctopen(io)
147: struct iob *io;
148: {
149: register int unit = io->i_unit;
150: register struct ct_softc *rs = &ct_softc[unit];
151: register int skip;
152:
153: if (hpibalive(unit) == 0)
154: _stop("ct controller not configured");
155: if (rs->sc_alive == 0)
156: if (ctinit(unit) == 0)
157: _stop("ct init failed");
158: ctstrategy(io, MTREW);
159: skip = io->i_boff;
160: while (skip--)
161: ctstrategy(io, MTFSF);
162: }
163:
164: ctclose(io)
165: struct iob *io;
166: {
167: ctstrategy(io, MTREW);
168: }
169:
170: ctstrategy(io, func)
171: register struct iob *io;
172: register int func;
173: {
174: register int unit = io->i_unit;
175: register struct ct_softc *rs = &ct_softc[unit];
176: char stat;
177:
178: rs->sc_retry = 0;
179: ct_ioc.unit = C_SUNIT(rs->sc_punit);
180: ct_ioc.saddr = C_SADDR;
181: ct_ioc.nop2 = C_NOP;
182: ct_ioc.slen = C_SLEN;
183: ct_ioc.nop3 = C_NOP;
184: top:
185: if (func == F_READ) {
186: ct_ioc.cmd = C_READ;
187: ct_ioc.addr = rs->sc_blkno;
188: ct_ioc.len = io->i_cc;
189: }
190: else if (func == F_WRITE) {
191: ct_ioc.cmd = C_WRITE;
192: ct_ioc.addr = rs->sc_blkno;
193: ct_ioc.len = io->i_cc;
194: }
195: else if (func == MTFSF) {
196: ct_ioc.cmd = C_READ;
197: ct_ioc.addr = rs->sc_blkno;
198: ct_ioc.len = io->i_cc = MAXBSIZE;
199: io->i_ma = io->i_buf;
200: }
201: else {
202: ct_ioc.cmd = C_READ;
203: ct_ioc.addr = 0;
204: ct_ioc.len = 0;
205: rs->sc_blkno = 0;
206: io->i_cc = 0;
207: }
208: retry:
209: hpibsend(unit, C_CMD, &ct_ioc, sizeof(ct_ioc));
210: if (func != MTREW) {
211: hpibswait(unit);
212: hpibgo(unit, C_EXEC, io->i_ma, io->i_cc,
213: func != F_WRITE ? F_READ : F_WRITE);
214: hpibswait(unit);
215: }
216: else {
217: while (hpibswait(unit) < 0)
218: ;
219: }
220: hpibrecv(unit, C_QSTAT, &stat, 1);
221: if (stat) {
222: stat = cterror(unit);
223: if (stat == 0)
224: return (-1);
225: if (stat == 2)
226: return (0);
227: if (++rs->sc_retry > CTRETRY)
228: return (-1);
229: else
230: goto retry;
231: }
232: rs->sc_blkno += CTBTOK(io->i_cc);
233: if (func == MTFSF)
234: goto top;
235: return (io->i_cc);
236: }
237:
238: cterror(unit)
239: register int unit;
240: {
241: register struct ct_softc *ct = &ct_softc[unit];
242: char stat;
243:
244: ct_rsc.unit = C_SUNIT(ct->sc_punit);
245: ct_rsc.cmd = C_STATUS;
246: hpibsend(unit, C_CMD, &ct_rsc, sizeof(ct_rsc));
247: hpibrecv(unit, C_EXEC, &ct_stat, sizeof(ct_stat));
248: hpibrecv(unit, C_QSTAT, &stat, 1);
249: if (stat) {
250: printf("ct%d: request status fail %d\n", unit, stat);
251: return(0);
252: }
253: if (ct_stat.c_aef & AEF_EOF) {
254: /* 9145 drives don't increment block number at EOF */
255: if ((ct_stat.c_blk - ct->sc_blkno) == 0)
256: ct->sc_blkno++;
257: else
258: ct->sc_blkno = ct_stat.c_blk;
259: return (2);
260: }
261: printf("ct%d err: vu 0x%x, pend 0x%x, bn%d", unit,
262: ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk);
263: printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref,
264: ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief);
265: return (1);
266: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.