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