1 /*
2 * Copyright (c) 1982, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7 * @(#)ct.c 8.1 (Berkeley) 07/15/93
8 */
9
10 /*
11 * CS80 tape driver
12 */
13 #include <sys/param.h>
14
15 #include <hp300/dev/ctreg.h>
16
17 #include <stand.att/saio.h>
18 #include <hp300/stand/samachdep.h>
19
20 struct ct_iocmd ct_ioc;
21 struct ct_rscmd ct_rsc;
22 struct ct_stat ct_stat;
23 struct ct_ssmcmd ct_ssmc;
24
25 struct ct_softc {
26 char sc_retry;
27 char sc_alive;
28 short sc_punit;
29 int sc_blkno;
30 } ct_softc[NHPIB][NCT];
31
32 #define CTRETRY 5
33 #define MTFSF 10
34 #define MTREW 11
35
36 struct ctinfo {
37 short hwid;
38 short punit;
39 } ctinfo[] = {
40 CT7946ID, 1,
41 CT7912PID, 1,
42 CT7914PID, 1,
43 CT9144ID, 0,
44 CT9145ID, 0,
45 };
46 int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
47
ctinit(ctlr,unit)48 ctinit(ctlr, unit)
49 register int ctlr, unit;
50 {
51 register struct ct_softc *rs = &ct_softc[ctlr][unit];
52 u_char stat;
53 register int type;
54
55 if (hpibrecv(ctlr, unit, C_QSTAT, &stat, 1) != 1 || stat)
56 return (0);
57 if (ctident(ctlr, unit) < 0)
58 return (0);
59 ct_ssmc.unit = C_SUNIT(rs->sc_punit);
60 ct_ssmc.cmd = C_SSM;
61 ct_ssmc.fefm = FEF_MASK;
62 ct_ssmc.refm = REF_MASK;
63 ct_ssmc.aefm = AEF_MASK;
64 ct_ssmc.iefm = IEF_MASK;
65 hpibsend(ctlr, unit, C_CMD, &ct_ssmc, sizeof(ct_ssmc));
66 hpibswait(ctlr, unit);
67 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
68 rs->sc_alive = 1;
69 return (1);
70 }
71
ctident(ctlr,unit)72 ctident(ctlr, unit)
73 int ctlr, unit;
74 {
75 struct ct_describe desc;
76 u_char stat, cmd[3];
77 char name[7];
78 int id, i;
79
80 id = hpibid(ctlr, unit);
81 if ((id & 0x200) == 0)
82 return(-1);
83 for (i = 0; i < nctinfo; i++)
84 if (id == ctinfo[i].hwid)
85 break;
86 if (i == nctinfo)
87 return(-1);
88 ct_softc[ctlr][unit].sc_punit = ctinfo[i].punit;
89 id = i;
90
91 /*
92 * Collect device description.
93 * Right now we only need this to differentiate 7945 from 7946.
94 * Note that we always issue the describe command to unit 0.
95 */
96 cmd[0] = C_SUNIT(0);
97 cmd[1] = C_SVOL(0);
98 cmd[2] = C_DESC;
99 hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd));
100 hpibrecv(ctlr, unit, C_EXEC, &desc, 37);
101 hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat));
102 bzero(name, sizeof(name));
103 if (!stat) {
104 register int n = desc.d_name;
105 for (i = 5; i >= 0; i--) {
106 name[i] = (n & 0xf) + '0';
107 n >>= 4;
108 }
109 }
110 switch (ctinfo[id].hwid) {
111 case CT7946ID:
112 if (bcmp(name, "079450", 6) == 0)
113 id = -1; /* not really a 7946 */
114 break;
115 default:
116 break;
117 }
118 return(id);
119 }
120
121 ctopen(io)
122 struct iob *io;
123 {
124 register struct ct_softc *rs;
125 register int unit, ctlr;
126 register int skip;
127
128 devconvert(io);
129
130 ctlr = io->i_adapt;
131 if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
132 return(EADAPT);
133 unit = io->i_ctlr;
134 if (unit >= NCT)
135 return(ECTLR);
136 rs = &ct_softc[ctlr][unit];
137 if (rs->sc_alive == 0)
138 if (ctinit(ctlr, unit) == 0)
139 return(ENXIO);
140 ctstrategy(io, MTREW);
141 skip = io->i_part;
142 while (skip--)
143 ctstrategy(io, MTFSF);
144 return(0);
145 }
146
147 ctclose(io)
148 struct iob *io;
149 {
150 ctstrategy(io, MTREW);
151 }
152
ctstrategy(io,func)153 ctstrategy(io, func)
154 register struct iob *io;
155 register int func;
156 {
157 register int ctlr = io->i_adapt;
158 register int unit = io->i_ctlr;
159 register struct ct_softc *rs = &ct_softc[ctlr][unit];
160 char stat;
161
162 if (io->i_cc == 0 && (func == F_READ || func == F_WRITE))
163 return(0);
164
165 rs->sc_retry = 0;
166 ct_ioc.unit = C_SUNIT(rs->sc_punit);
167 ct_ioc.saddr = C_SADDR;
168 ct_ioc.nop2 = C_NOP;
169 ct_ioc.slen = C_SLEN;
170 ct_ioc.nop3 = C_NOP;
171 top:
172 if (func == F_READ) {
173 ct_ioc.cmd = C_READ;
174 ct_ioc.addr = rs->sc_blkno;
175 ct_ioc.len = io->i_cc;
176 }
177 else if (func == F_WRITE) {
178 ct_ioc.cmd = C_WRITE;
179 ct_ioc.addr = rs->sc_blkno;
180 ct_ioc.len = io->i_cc;
181 }
182 else if (func == MTFSF) {
183 ct_ioc.cmd = C_READ;
184 ct_ioc.addr = rs->sc_blkno;
185 ct_ioc.len = io->i_cc = MAXBSIZE;
186 io->i_ma = io->i_buf;
187 }
188 else {
189 ct_ioc.cmd = C_READ;
190 ct_ioc.addr = 0;
191 ct_ioc.len = 0;
192 rs->sc_blkno = 0;
193 io->i_cc = 0;
194 }
195 retry:
196 hpibsend(ctlr, unit, C_CMD, &ct_ioc, sizeof(ct_ioc));
197 if (func != MTREW) {
198 hpibswait(ctlr, unit);
199 hpibgo(ctlr, unit, C_EXEC, io->i_ma, io->i_cc,
200 func != F_WRITE ? F_READ : F_WRITE);
201 hpibswait(ctlr, unit);
202 } else {
203 while (hpibswait(ctlr, unit) < 0)
204 ;
205 }
206 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
207 if (stat) {
208 stat = cterror(ctlr, unit);
209 if (stat == 0)
210 return (-1);
211 if (stat == 2)
212 return (0);
213 if (++rs->sc_retry > CTRETRY)
214 return (-1);
215 goto retry;
216 }
217 rs->sc_blkno += CTBTOK(io->i_cc);
218 if (func == MTFSF)
219 goto top;
220 return (io->i_cc);
221 }
222
cterror(ctlr,unit)223 cterror(ctlr, unit)
224 register int ctlr, unit;
225 {
226 register struct ct_softc *rs = &ct_softc[ctlr][unit];
227 char stat;
228
229 ct_rsc.unit = C_SUNIT(rs->sc_punit);
230 ct_rsc.cmd = C_STATUS;
231 hpibsend(ctlr, unit, C_CMD, &ct_rsc, sizeof(ct_rsc));
232 hpibrecv(ctlr, unit, C_EXEC, &ct_stat, sizeof(ct_stat));
233 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
234 if (stat) {
235 printf("ct%d: request status fail %d\n", unit, stat);
236 return(0);
237 }
238 if (ct_stat.c_aef & AEF_EOF) {
239 /* 9145 drives don't increment block number at EOF */
240 if ((ct_stat.c_blk - rs->sc_blkno) == 0)
241 rs->sc_blkno++;
242 else
243 rs->sc_blkno = ct_stat.c_blk;
244 return (2);
245 }
246 printf("ct%d err: vu 0x%x, pend 0x%x, bn%d", unit,
247 ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk);
248 printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref,
249 ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief);
250 return (1);
251 }
252