|
|
1.1 root 1: /* cy.c Tahoe version Mar 1983. */
2:
3: /*
4: * Cypher tape driver. Stand alone version.
5: *
6: */
7: #include "../h/param.h"
8: #include "../h/inode.h"
9: #include "../h/fs.h"
10: #include "../machine/pte.h"
11: #include "../machine/mtpr.h"
12: #include "../stand/saio.h"
13: #include "../stand/cyvar.h"
14:
15: long cystd[] = { 0xf4000, 0 };
16:
17: struct scp /* SYSTEM CONFIGURATION POINTER */
18: {
19: char sysbus ; /* width of system buss 0=8;1=16 */
20: char nu1 ;
21: char pt_scb[4] ; /* pointer to ->SYSTEM CONFIGURATION BLOCK */
22: };
23:
24: struct scp * SCP; /* absolute address - jumpered on the controller */
25: /* set to 0xC06 for Tahoe */
26:
27: struct scb /* SYSTEM CONFIGUREATION BLOCK */
28: {
29: char sysblk[1] ; /* 0x03 fixed value code */
30: char nu2[1] ;
31: char pt_ccb[4] ; /* pointer to ->CHANNEL CONTROL BLOCK */
32: }scb;
33:
34: struct ccb /* CHANNEL CONTROL BLOCK */
35: {
36: char ccw[1] ; /* 0x11 normal; 0x09 clear non_vect interrupt */
37: char gate[1] ; /* This is "the" GATE */
38: char pt_tpb[4] ; /* pointer to ->TAPE OPERATION BLOCK or MOVE BLOCK */
39: }ccb;
40:
41: struct tpb /* TAPE OPERATIONS PARAMETER BLOCK */
42: {
43: long cmd ; /* COMMAND (input) */
44: char control[2] ; /* CONTROL (input) */
45: short count ; /* RETURN COUNT (output) */
46: short size ; /* BUFFER SIZE (input/output) */
47: short rec_over ; /* RECORDS/OVERRUN (input/output) */
48: char pt_data[4] ; /* pointer to ->SOURCE/DEST (input) */
49: char status[2] ; /* STATUS (output) */
50: char pt_link[4] ; /* pointer to ->INTERRUPT/PARAMETER BLOCK (input) */
51: } tpb;
52:
53: struct tpb cycool /* tape parameter block to clear interrupts */
54: = {
55: 0L, /* command */
56: 0,0, /* control */
57: 0, /* count */
58: 0, /* size */
59: 0, /* rec_over */
60: 0,0,0,0, /* pt_data */
61: 0,0, /* status */
62: 0,0,0,0 /* pt_link */
63: } ;
64: int cyblksiz = 1024; /* foreign tape size as found in open routine */
65: long cyblock; /* next block number for i/o */
66: /*
67: * Reset the controller.
68: */
69: cyopen(io)
70: register struct iob *io;
71: {
72: register ctlradr;
73:
74: ctlradr = cystd[0] + IOBASE;
75: SCP = (struct scp *)0xc06; /* absolute - for setup */
76: TM_RESET(ctlradr,0xff); /* reset the controller */
77: /*
78: * Initialize the system configuration pointer
79: */
80: SCP->sysbus = 1; /* system width = 16 bits. */
81: /* initialize the pointer to the system configuration block */
82: set_pointer((long)&scb.sysblk[0],(char *)SCP->pt_scb);
83: /*
84: * Initialize the system configuration block.
85: */
86: scb.sysblk[0] = 0x3; /* fixed value */
87: /* initialize the pointer to the channel control block */
88: set_pointer((long)&ccb.ccw[0],(char *)scb.pt_ccb);
89: /*
90: * Initialize the channel control block.
91: */
92: ccb.ccw[0] = 0x11; /* normal interrupts */
93: /* initialize the pointer to the tape parameter block */
94: set_pointer((long)&tpb,(char *)ccb.pt_tpb);
95: /*
96: * set the command to be NO_OP.
97: */
98: tpb.cmd = NO_OP;
99: tpb.control[0] = CW_BL; /* TPB not used on first attention */
100: tpb.control[1] = CW_16bits;
101: ccb.gate[0] = GATE_CLOSED;
102: TM_ATTENTION(ctlradr, 0xff); /* execute! */
103: cywait(10*1000);
104: /*
105: * set the command to be CONFIGURE.
106: */
107: tpb.cmd = CONFIG;
108: tpb.control[0] = CW_BL; /* NO interrupt on completion */
109: tpb.control[1] = CW_16bits;
110: tpb.status[0] = tpb.status[1] = 0;
111: ccb.gate[0] = GATE_CLOSED;
112: TM_ATTENTION(ctlradr, 0xff); /* execute! */
113: cywait(10*1000);
114: uncache (&tpb.status[1]) ;
115: if (tpb.status[1] & CS_ERm) {
116: printf("Cypher initialization error!\n");
117: cy_decode_error(tpb.status[1]&CS_ERm);
118: _stop("");
119: }
120: if(cycmd(io,REWD_TA) == -1)
121: _stop("Rewind failed!\n");
122: while(io->i_boff > 0) {
123: if(cycmd(io,SPAC_FM) == -1)
124: _stop("cy: seek failure!\n");
125: io->i_boff--;
126: }
127: #ifdef NOBLOCK
128: if (io->i_flgs & F_READ) {
129: if((cyblksiz = cycmd(io,READ_FO)) == -1)
130: _stop("Read foriegn tape failed!\n");
131: if(cycmd(io,REWD_TA) == -1)
132: _stop("Rewind after read failed\n");
133: }
134: #endif
135: }
136:
137: /* if tape was open for writing write a file mark */
138: cyclose(io)
139: register struct iob *io;
140: {
141: if (io->i_flgs & F_WRITE) cycmd(io,WRITE_FMARK);
142: cycmd(io,REWD_TA);
143: cyblock = 0;
144: }
145:
146: cystrategy(io,func)
147: register struct iob *io;
148: register long func;
149: {
150:
151: #ifndef NOBLOCK
152: if ((func != SPACE) && (func != REWD_TA) && (io->i_bn != cyblock)) {
153: cycmd(io,SPACE);
154: tpb.rec_over = 0;
155: }
156: if(func==READ || func==WRITE) {
157: struct iob liob;
158: register struct iob *lio = &liob;
159: register count;
160:
161: liob = *io;
162: while(lio->i_cc > 0) {
163: if((count = cycmd(lio, func)) == 0)
164: return(-1);
165: lio->i_cc -= count;
166: lio->i_ma += count;
167: }
168: return(io->i_cc);
169: }
170: #endif
171: return(cycmd(io, func));
172: }
173:
174: cycmd(io,func)
175: register struct iob *io;
176: long func;
177: {
178: register ctlradr;
179: short j;
180:
181: ctlradr = cystd[0] + IOBASE;
182: cywait(9000);
183: if (func == READ) func = READ_TA;
184: else if (func == WRITE) func = WRIT_TA;
185: else if (func == WRITE_FMARK) func = WRIT_FM;
186: tpb.cmd = func;
187: uncache(&ccb.gate[0]);
188: while(ccb.gate[0] == GATE_CLOSED)
189: uncache(&ccb.gate[0]);
190: ccb.gate[0] = GATE_CLOSED;
191: tpb.control[0] = CW_BL;
192: tpb.control[1] = CW_16bits;
193: tpb.status[0] = tpb.status[1] = 0;
194: tpb.count = 0;
195: set_pointer((long)&tpb,(char *)ccb.pt_tpb);
196: switch (func)
197: {
198: case READ_TA:
199: if (io->i_cc > cyblksiz)
200: tpb.size = TM_SHORT(cyblksiz);
201: else tpb.size = TM_SHORT(io->i_cc);
202: set_pointer((long)io->i_ma,(char *)tpb.pt_data);
203: cyblock += 1;
204: break;
205: case WRIT_TA:
206: tpb.size = TM_SHORT(io->i_cc);
207: set_pointer((long)io->i_ma,(char *)tpb.pt_data);
208: cyblock += 1;
209: break;
210: case SPACE:
211: if ((j = io->i_bn - cyblock) < 0) {
212: j = -j;
213: tpb.control[1] |= CW_R;
214: cyblock -= j;
215: }
216: else
217: cyblock += j;
218: tpb.rec_over = TM_SHORT(j);
219: break;
220: case REWD_TA:
221: cyblock = 0;
222: break;
223: }
224: TM_ATTENTION(ctlradr, 0xff); /* execute! */
225: if (func == REWD_TA || func == SPACE) {
226: cywait(60*5*1000);
227: }
228: else cywait(10*1000);
229: /*
230: * First we clear the interrupt and close the gate.
231: */
232: mtpr (0, PADC);
233: ccb.gate[0] = GATE_CLOSED;
234: set_pointer((int)&cycool,(char *)ccb.pt_tpb);
235: cycool.cmd = NO_OP; /* no operation */
236: cycool.control[0] = CW_BL; /* No INTERRUPTS */
237: cycool.control[1] = 0;
238: TM_ATTENTION(ctlradr,0xff); /* cool it ! */
239: cywait(20000);
240: uncache (&tpb.status[1] ) ;
241: if (tpb.status[1] & CS_ERm) {
242: cy_decode_error(tpb.status[1]&CS_ERm);
243: return -1;
244: }
245: uncache (&tpb.count);
246: return((long)TM_SHORT(tpb.count));
247: }
248:
249:
250:
251: cyprint_error(message)
252: register char *message;
253: {
254: printf("cy0: %s.\n", message);
255: }
256:
257: /*
258: */
259:
260: cy_decode_error(status)
261: register int status;
262: {
263: switch(status) {
264: case ER_TO1:
265: case ER_TO2:
266: case ER_TO3:
267: case ER_TO4:
268: case ER_TO5:
269: cyprint_error("Drive timed out during transfer");
270: break;
271: case ER_TO6:
272: cyprint_error("Non-existant system memory reference");
273: break;
274: case ER_DIAG:
275: case ER_JUMP:
276: cyprint_error("Controller micro diagnostics failed");
277: break;
278: case ER_HARD:
279: cyprint_error("Unrecoverble media error");
280: break;
281: case ER_TOF:
282: if (tpb.cmd == WRIT_TA)
283: cyprint_error("Unsatisfactory media");
284: break;
285: case ER_FIFO:
286: cyprint_error("Data transfer over run");
287: break;
288: case ER_TRN:
289: cyprint_error("Drive is not ready");
290: break;
291: case ER_PRO:
292: cyprint_error("Tape is write protected");
293: break;
294: case ER_PSUM:
295: cyprint_error("Checksum error in controller proms");
296: break;
297: case ER_PARI:
298: cyprint_error("Unrecoverable tape parity error");
299: break;
300: case ER_BLAN:
301: cyprint_error("Blank tape found where data was expected");
302: break;
303: case ER_ER:
304: cyprint_error("Unrecoverble hardware error");
305: default:
306: break;
307: }
308: }
309:
310:
311: long
312: cywait(timeout)
313: long timeout;
314: {
315: long dummy;
316:
317: uncache (&ccb.gate[0]) ;
318: while (ccb.gate[0] != GATE_OPEN) {
319: uncache (&ccb.gate[0]) ;
320: DELAY(1000);
321: if (--timeout == 0) {
322: cyprint_error("Transfer timeout");
323: _stop("");
324: }
325: }
326: }
327:
328: /*
329: * Set a TAPEMASTER pointer (first parameter), into the
330: * 4 bytes array pointed by the second parameter.
331: */
332: set_pointer(pointer,dest)
333: long pointer;
334: char * dest;
335: {
336: *dest++ = pointer & 0xff; /* low byte - offset */
337: *dest++ = (pointer >> 8) & 0xff; /* high byte - offset */
338: *dest++ = 0;
339: *dest = (pointer & 0xf0000) >> 12; /* base */
340: }
341:
342: movow(word, destination)
343: long word, destination;
344: {
345: asm("movow 6(fp),*8(fp);");
346: }
347:
348: movob(byte, destination)
349: long byte, destination;
350: {
351: asm("movob 7(fp),*8(fp);");
352: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.