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