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