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