new copyright notice
[unix-history] / usr / src / sys / tahoe / stand / cy.c
CommitLineData
ec3296ac 1/* cy.c 7.9 90/06/22 */
7af8ee60
SL
2
3/*
4 * Cypher tape driver. Stand alone version.
7af8ee60 5 */
c18e27ed
KM
6#include "machine/pte.h"
7#include "machine/mtpr.h"
7af8ee60 8
ec3296ac
BJ
9#include "sys/param.h"
10#include "sys/time.h"
11#include "sys/vnode.h"
12#include "ufs/inode.h"
13#include "ufs/fs.h"
7af8ee60
SL
14
15#include "saio.h"
7af8ee60 16
d0ab68f5 17#define CYERROR
ec3296ac
BJ
18#include "tahoevba/cyreg.h"
19#include "tahoevba/vbaparam.h"
1a9cb196 20
d0ab68f5
MK
21/*
22 * NB: this driver assumes unit 0 throughout.
23 */
7af8ee60 24long cystd[] = { 0xf4000, 0 };
1a9cb196 25#define CYADDR(i) (cystd[i] + (int)VBIOBASE)
7af8ee60 26
d0ab68f5
MK
27struct cyscp *cyscp[] = { (struct cyscp *)0xc06, (struct cyscp *)0 };
28#define CYSCP(i) (cyscp[i])
7af8ee60 29
d0ab68f5
MK
30struct cyscp *SCP;
31struct cyscb scb;
32struct cyccb ccb;
33struct cytpb tpb;
34struct cytpb cycool; /* tape parameter block to clear interrupts */
35#ifdef notdef
ffabdd40 36int cyblocksize = 1024; /* foreign tape size as found in open routine */
d0ab68f5
MK
37#endif
38int cybufsize; /* controller buffer size */
ffabdd40
SL
39long cyblock; /* next block number for i/o */
40
7af8ee60
SL
41/*
42 * Reset the controller.
43 */
44cyopen(io)
45 register struct iob *io;
46{
ffabdd40 47 register ctlradr = CYADDR(0);
cb69d88e 48 register int skip;
7af8ee60 49
cb69d88e
KB
50 if ((u_int)io->i_adapt)
51 return (EADAPT);
52 if ((u_int)io->i_ctlr)
53 return (ECTLR);
d0ab68f5
MK
54 SCP = CYSCP(0); /* absolute - for setup */
55 CY_RESET(ctlradr); /* reset the controller */
7af8ee60
SL
56 /*
57 * Initialize the system configuration pointer
58 */
d0ab68f5
MK
59 SCP->csp_buswidth = 1; /* system width = 16 bits. */
60 SCP->csp_unused = 0;
7af8ee60 61 /* initialize the pointer to the system configuration block */
d0ab68f5 62 cyldmba(SCP->csp_scb, (caddr_t)&scb);
7af8ee60
SL
63 /*
64 * Initialize the system configuration block.
65 */
d0ab68f5 66 scb.csb_fixed = CSB_FIXED; /* fixed value */
7af8ee60 67 /* initialize the pointer to the channel control block */
d0ab68f5 68 cyldmba(scb.csb_ccb, (caddr_t)&ccb);
7af8ee60
SL
69 /*
70 * Initialize the channel control block.
71 */
d0ab68f5 72 ccb.cbcw = CBCW_IE; /* normal interrupts */
7af8ee60 73 /* initialize the pointer to the tape parameter block */
d0ab68f5
MK
74 cyldmba(ccb.cbtpb, (caddr_t)&tpb);
75 /*
76 * set the command to be CY_NOP.
77 */
78 tpb.tpcmd = CY_NOP;
7af8ee60 79 /*
d0ab68f5 80 * TPB not used on first attention
7af8ee60 81 */
d0ab68f5
MK
82 tpb.tpcontrol = CYCW_LOCK | CYCW_16BITS;
83 ccb.cbgate = GATE_CLOSED;
84 CY_GO(ctlradr); /* execute! */
7af8ee60
SL
85 cywait(10*1000);
86 /*
d0ab68f5
MK
87 * set the command to be CY_CONFIGURE.
88 * NO interrupt on completion.
7af8ee60 89 */
d0ab68f5
MK
90 tpb.tpcmd = CY_CONFIG;
91 tpb.tpcontrol = CYCW_LOCK | CYCW_16BITS;
92 tpb.tpstatus = 0;
93 ccb.cbgate = GATE_CLOSED;
94 CY_GO(ctlradr); /* execute! */
7af8ee60 95 cywait(10*1000);
d0ab68f5
MK
96 uncache(&tpb.tpstatus);
97 if (tpb.tpstatus & CYS_ERR) {
ffabdd40 98 printf("Cypher initialization error!\n");
44592d9e 99 cy_print_error(tpb.tpcmd, tpb.tpstatus);
aa779056 100 return (ENXIO);
7af8ee60 101 }
d0ab68f5
MK
102 uncache(&tpb.tpcount);
103 cybufsize = tpb.tpcount;
aa779056
MK
104 if (cycmd(io, CY_REW) == -1) {
105 printf("cy%d: Rewind failed!\n", io->i_unit);
106 return (ENXIO);
107 }
cb69d88e 108 for (skip = io->i_part; skip--;)
aa779056
MK
109 if (cycmd(io, CY_FSF) == -1) {
110 printf("cy%d: seek failure!\n", io->i_unit);
111 return (ENXIO);
112 }
d0ab68f5 113#ifdef notdef
7af8ee60
SL
114#ifdef NOBLOCK
115 if (io->i_flgs & F_READ) {
d0ab68f5 116 cyblocksize = cycmd(io, CY_READFORN);
ffabdd40
SL
117 if (cyblocksize == -1)
118 _stop("Read foreign tape failed\n");
119 cyblock++; /* XXX force backspace record */
d0ab68f5 120 if (cycmd(io, CY_SFORW) == -1)
ffabdd40 121 _stop("Backspace after read foreign failed\n");
7af8ee60
SL
122 }
123#endif
d0ab68f5 124#endif
aa779056 125 return (0);
7af8ee60
SL
126}
127
7af8ee60
SL
128cyclose(io)
129 register struct iob *io;
130{
ffabdd40 131
d0ab68f5
MK
132 if (io->i_flgs & F_WRITE) { /* if writing, write file marks */
133 cycmd(io, CY_WEOF);
134 cycmd(io, CY_WEOF);
135 }
136 cycmd(io, CY_REW);
7af8ee60
SL
137}
138
ffabdd40 139cystrategy(io, func)
7af8ee60 140 register struct iob *io;
ffabdd40 141 register func;
7af8ee60 142{
44592d9e 143 register count;
7af8ee60
SL
144
145#ifndef NOBLOCK
d0ab68f5
MK
146 if (func != CY_SFORW && func != CY_REW && io->i_bn != cyblock) {
147 cycmd(io, CY_SFORW);
148 tpb.tprec = 0;
7af8ee60 149 }
ffabdd40 150 if (func == READ || func == WRITE) {
7af8ee60
SL
151 struct iob liob;
152 register struct iob *lio = &liob;
7af8ee60
SL
153
154 liob = *io;
ffabdd40 155 while (lio->i_cc > 0) {
44592d9e
MK
156 if ((count = cycmd(lio, func)) == 0) {
157 printf("cy%d: I/O error bn %d\n",
158 io->i_unit, io->i_bn);
ffabdd40 159 return (-1);
44592d9e 160 }
7af8ee60
SL
161 lio->i_cc -= count;
162 lio->i_ma += count;
163 }
ffabdd40 164 return (io->i_cc);
7af8ee60
SL
165 }
166#endif
44592d9e
MK
167 count = cycmd(io, func);
168 if (count == -1)
169 printf("cy%d: I/O error bn %d\n", io->i_unit, io->i_bn);
170 return (count);
7af8ee60
SL
171}
172
ffabdd40 173cycmd(io, func)
7af8ee60 174 register struct iob *io;
ffabdd40 175 long func;
7af8ee60 176{
ffabdd40
SL
177 register ctlradr = CYADDR(0);
178 int timeout = 0;
d0ab68f5 179 int err;
7af8ee60
SL
180 short j;
181
d0ab68f5 182 cywait(9000); /* shouldn't be needed */
cb69d88e
KB
183#define PACKUNIT(unit) (((unit&1)<<11)|((unit&2)<<9)|((unit&4)>>2))
184 tpb.tpcontrol = CYCW_LOCK | CYCW_16BITS | PACKUNIT(io->i_unit);
d0ab68f5
MK
185 tpb.tpstatus = 0;
186 tpb.tpcount = 0;
187 cyldmba(ccb.cbtpb, (caddr_t)&tpb);
188 tpb.tpcmd = func;
ffabdd40
SL
189 switch (func) {
190 case READ:
d0ab68f5 191#ifdef notdef
ffabdd40 192 if (io->i_cc > cyblocksize)
d0ab68f5 193 tpb.tpsize = htoms(cyblocksize);
ffabdd40 194 else
d0ab68f5
MK
195#endif
196 tpb.tpsize = htoms(io->i_cc);
197 cyldmba(tpb.tpdata, io->i_ma);
198 tpb.tpcmd = CY_RCOM;
ffabdd40 199 cyblock++;
7af8ee60 200 break;
ffabdd40 201 case WRITE:
d0ab68f5
MK
202 tpb.tpcmd = CY_WCOM;
203 tpb.tpsize = htoms(io->i_cc);
204 cyldmba(tpb.tpdata, io->i_ma);
ffabdd40 205 cyblock++;
7af8ee60 206 break;
d0ab68f5 207 case CY_SFORW:
7af8ee60
SL
208 if ((j = io->i_bn - cyblock) < 0) {
209 j = -j;
d0ab68f5 210 tpb.tpcontrol |= CYCW_REV;
7af8ee60 211 cyblock -= j;
ffabdd40 212 } else
7af8ee60 213 cyblock += j;
d0ab68f5 214 tpb.tprec = htoms(j);
ffabdd40 215 timeout = 60*5;
7af8ee60 216 break;
d0ab68f5
MK
217 case CY_FSF:
218 tpb.tprec = htoms(1);
ffabdd40 219 /* fall thru... */
d0ab68f5 220 case CY_REW:
7af8ee60 221 cyblock = 0;
ffabdd40 222 timeout = 60*5;
7af8ee60
SL
223 break;
224 }
d0ab68f5
MK
225 ccb.cbgate = GATE_CLOSED;
226 CY_GO(ctlradr); /* execute! */
ffabdd40
SL
227 if (timeout == 0)
228 timeout = 10;
229 cywait(timeout*1000);
7af8ee60
SL
230 /*
231 * First we clear the interrupt and close the gate.
232 */
233 mtpr(PADC, 0);
d0ab68f5
MK
234 ccb.cbgate = GATE_CLOSED;
235 cyldmba(ccb.cbtpb, (caddr_t)&cycool);
236 cycool.tpcontrol = CYCW_LOCK; /* No INTERRUPTS */
237 CY_GO(ctlradr);
7af8ee60 238 cywait(20000);
d0ab68f5 239 uncache(&tpb.tpstatus);
44592d9e 240 if ((err = (tpb.tpstatus & CYS_ERR)) &&
d0ab68f5 241 err != CYER_FM && (err != CYER_STROBE || tpb.tpcmd != CY_RCOM)) {
44592d9e 242 cy_print_error(tpb.tpcmd, tpb.tpstatus);
ffabdd40
SL
243 io->i_error = EIO;
244 return (-1);
7af8ee60 245 }
d0ab68f5
MK
246 uncache(&tpb.tpcount);
247 return ((int)htoms(tpb.tpcount));
7af8ee60 248}
cb69d88e 249
44592d9e
MK
250cy_print_error(op, status)
251 int op, status;
7af8ee60 252{
d0ab68f5
MK
253 register char *message;
254
255 if ((status & CYS_ERR) < NCYERROR)
256 message = cyerror[status & CYS_ERR];
257 else
258 message = "unknown error";
44592d9e 259 printf("cy0: cmd %x %s, status=%b.\n", op, message, status, CYS_BITS);
7af8ee60
SL
260}
261
7af8ee60 262cywait(timeout)
ffabdd40 263 register timeout;
7af8ee60 264{
ffabdd40 265 do {
7af8ee60 266 DELAY(1000);
d0ab68f5
MK
267 uncache(&ccb.cbgate);
268 } while (ccb.cbgate != GATE_OPEN && --timeout > 0);
ffabdd40
SL
269 if (timeout <= 0)
270 _stop("cy: Transfer timeout");
7af8ee60
SL
271}
272
273/*
d0ab68f5 274 * Load a 20 bit pointer into a Tapemaster pointer.
7af8ee60 275 */
d0ab68f5
MK
276cyldmba(reg, value)
277 register caddr_t reg;
278 caddr_t value;
7af8ee60 279{
d0ab68f5 280 register int v = (int)value;
ffabdd40 281
d0ab68f5
MK
282 *reg++ = v;
283 *reg++ = v >> 8;
284 *reg++ = 0;
285 *reg = (v&0xf0000) >> 12;
7af8ee60 286}