xref: /csrg-svn/sys/tahoe/stand/vdformat/io.c (revision 29981)
1 #ifndef lint
2 static char sccsid[] = "@(#)io.c	1.2 (Berkeley/CCI) 11/04/86";
3 #endif
4 
5 #include	"vdfmt.h"
6 #include	"cmd.h"
7 
8 
9 /*
10 **
11 */
12 
13 static cmd_text_element	nul_table[] = {
14 	{ 0,	"",	"" }
15 };
16 
17 int wait_for_char;
18 char	*clean_up = "Cleaning up...  Please wait.\n";
19 
20 
21 /*
22 **
23 */
24 
25 poll(wait)
26 int	wait;
27 {
28 	int	tokens[10];
29 	int	didmsg = 0;
30 
31 	wait_for_char = 0;
32 	vdtimeout = wait*1000*1000;
33 	uncache(&(dcb.operrsta));
34 	while (!((dcb.operrsta) & (DCBCMP | DCBABT))) {
35 		if (input()) {
36 			get_text_cmd(nul_table, tokens);
37 			if (didmsg == 0 && kill_processes == true) {
38 				didmsg = 1;
39 				indent();
40 				print(clean_up);
41 				exdent(1);
42 			}
43 		}
44 		vdtimeout--;
45 		uncache(&(dcb.operrsta));
46 		if (vdtimeout <= 0) {
47 			if(C_INFO.type == SMDCTLR)
48 				printf("\nVDDC");
49 			else
50 				printf("\nSMD-E");
51 			printf(": Controller timeout");
52 			VDDC_ABORT(C_INFO.addr, C_INFO.type);
53 			DELAY(30000);
54 			break;
55 		}
56 	}
57 	if((vdtimeout > 0)) {
58 		if(C_INFO.type == SMD_ECTLR) {
59 			uncache(&(C_INFO.addr->cdr_csr));
60 			while(C_INFO.addr->cdr_csr & CS_GO) {
61 				DELAY(50);
62 				uncache(&(C_INFO.addr->cdr_csr));
63 			}
64 		}
65 		DELAY(500);
66 	}
67 	if((dcb.opcode == RD) || (dcb.opcode == RD_RAW))
68 		mtpr(PADC, 0);
69 	uncache(&(dcb.operrsta));
70 	uncache(&(dcb.err_code));
71 	wait_for_char = 1;
72 }
73 
74 
75 /*
76 **	Access_with_no_trailer is used to perform controller functions which
77 ** require no data movement.
78 */
79 
80 access_with_no_trailer(function, wait_time)
81 int	function, wait_time;
82 {
83 	dcb.opcode = function;		/* command */
84 	dcb.intflg = NOINT;
85 	dcb.nxtdcb = (fmt_dcb *)0;	/* end of chain */
86 	dcb.operrsta  = 0;
87 	dcb.devselect = (function == VDSTART) ? 0 : (char)cur.drive;
88 	dcb.trailcnt = (char)0;
89 	mdcb.firstdcb = &dcb;
90 	mdcb.vddcstat = 0;
91 	VDDC_ATTENTION(C_INFO.addr, &mdcb, C_INFO.type);
92 	poll(wait_time);
93 	if(vdtimeout <= 0) {
94 		printf(" during startup operation.\n");
95 		_longjmp(abort_environ, 1);
96 	}
97 	return dcb.operrsta;
98 }
99 
100 
101 /*
102 **	access_dsk is used by other routines to do reads and writes to the disk.
103 ** The status of the read / write is returned to the caller for processing.
104 */
105 
106 access_dsk(buf, dskaddr, func, count, wait)
107 char	*buf;
108 dskadr	*dskaddr;
109 int	func, count, wait;
110 {
111 	cur.daddr.cylinder = dskaddr->cylinder;
112 	cur.daddr.track = dskaddr->track;
113 	wait_for_char = 0;
114 	dcb.opcode = func;		/* format sector command */
115 	dcb.intflg = NOINT;
116 	dcb.nxtdcb = (fmt_dcb *)0;	/* end of chain */
117 	dcb.operrsta  = 0;
118 	dcb.devselect = (char)cur.drive;
119 	if(func == SEEK) {
120 		dcb.trailcnt = (char)(sizeof(trseek) / sizeof(long));
121 		dcb.trail.sktrail.skaddr.cylinder = dskaddr->cylinder;
122 		dcb.trail.sktrail.skaddr.track = dskaddr->track;
123 		dcb.trail.sktrail.skaddr.sector = dskaddr->sector;
124 	}
125 	else {
126 		dcb.trailcnt = (char)(sizeof(trrw) / sizeof(long));
127 		dcb.trail.rwtrail.memadr = buf;
128 		dcb.trail.rwtrail.wcount=count*(SECSIZ/sizeof(short));
129 		dcb.trail.rwtrail.disk.cylinder = dskaddr->cylinder;
130 		dcb.trail.rwtrail.disk.track = dskaddr->track;
131 		dcb.trail.rwtrail.disk.sector = dskaddr->sector;
132 	}
133 	mdcb.firstdcb = &dcb;
134 	mdcb.vddcstat = 0;
135 	VDDC_ATTENTION(C_INFO.addr, &mdcb, C_INFO.type);
136 	if(wait) {
137 		poll(2*60);
138 		if(vdtimeout <= 0) {
139 			printf(" in access_dsk.\n");
140 			_longjmp(abort_environ, 1);
141 		}
142 	}
143 	wait_for_char = 1;
144 	return dcb.operrsta;
145 }
146 
147 
148 /*
149 **	Spin_up_drive starts the drives on a controller and waits around for
150 ** the drive to spin up if it is not already spinning.
151 */
152 
153 spin_up_drive()
154 {
155 	VDDC_RESET(C_INFO.addr, C_INFO.type);
156 	if(C_INFO.type == SMD_ECTLR) {
157 		C_INFO.addr->cdr_csr =  0;
158 		C_INFO.addr->mdcb_tcf =  AM_ENPDA;
159 		C_INFO.addr->dcb_tcf =  AM_ENPDA;
160 		C_INFO.addr->trail_tcf =  AM_ENPDA;
161 		C_INFO.addr->data_tcf =  AM_ENPDA;
162 		C_INFO.addr->cdr_ccf = CCF_SEN | 0x8 | CCF_STS |
163 		    XMD_32BIT | BSZ_16WRD | CCF_ERR |
164 		    CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE;
165 	}
166 	access_with_no_trailer(INIT, 10);
167 	access_with_no_trailer(DIAG, 20);
168 	configure_drive(0);
169 }
170 
171 /*
172 **	Configure_drive tells the controller what kind of drive is attached
173 ** on a particular line.
174 */
175 
176 configure_drive(pass)
177 int	pass;
178 {
179 	dcb.opcode = RSTCFG;		/* command */
180 	dcb.intflg = NOINT;
181 	dcb.nxtdcb = (fmt_dcb *)0;	/* end of chain */
182 	dcb.operrsta  = 0;
183 	dcb.devselect = (char)cur.drive;
184 	dcb.trail.rstrail.ncyl = CURRENT->vc_ncyl;
185 	dcb.trail.rstrail.nsurfaces = CURRENT->vc_ntrak;
186 	if(C_INFO.type == SMDCTLR)
187 		dcb.trailcnt = (char)2;
188 	else {
189 		dcb.trailcnt = (char)4;
190 		dcb.trail.rstrail.nsectors = CURRENT->vc_nsec;
191 		dcb.trail.rstrail.slip_sec = CURRENT->vc_nslip;
192 		dcb.trail.rstrail.recovery = 0x00;
193 		C_INFO.addr->cyl_skew = (*C_INFO.cylinder_skew)();
194 		C_INFO.addr->trk_skew = (*C_INFO.track_skew)();
195 	}
196 	mdcb.firstdcb = &dcb;
197 	mdcb.vddcstat = 0;
198 	VDDC_ATTENTION(C_INFO.addr, &mdcb, C_INFO.type);
199 	poll(5);
200 	if(vdtimeout <= 0) {
201 		printf(" during drive configuration.\n");
202 		_longjmp(abort_environ, 1);
203 	}
204 	if(dcb.operrsta & (NOTCYLERR | DRVNRDY)) {
205 		if(pass) {
206 			printf("\nDrive failed to start!\n\n");
207 			_longjmp(abort_environ, -1);
208 		}
209 		printf("\ndrive not ready, attempting to spin up...");
210 		access_with_no_trailer(VDSTART, (cur.drive * 6) + 62);
211 		DELAY((cur.drive * 5500000) + 62000000);
212 		printf(" retrying drive configuration\n");
213 		configure_drive(1);
214 	}
215 }
216 
217 
218 /*
219 ** 	data_ok checks an error status word for bit patterns
220 **  associated with error conditions from the VDDC controller.  If a hardware
221 **  error is present then the problem is reported on the console and the program
222 **  is halted.  If a data error is present the a zero is returned.
223 **  If everything is OK then a 1 is returned.
224 */
225 
226 data_ok()
227 {
228 	register int	status = dcb.operrsta;
229 
230 	if(status & HARD_ERROR){
231 		if(status & DRVNRDY)
232 			printf("\nDrive is not ready!");
233 		else if(status & INVDADR)
234 			printf("\nInvalid disk address issued!");
235 		else if(status & DNEMEM)
236 			printf("\nNon-existent memory error!");
237 		else if(status & PARERR)
238 			printf("\nMain memory parity error!");
239 		else if(status & OPABRT)
240 			printf("\nCPU aborted operation!");
241 		else if(status & WPTERR)
242 			printf("\nDrive is write protected!");
243 		else if(status & DSEEKERR)
244 			printf("\nDisk seek error!");
245 		else if(status & CTLRERR)
246 			printf("\nController hardware error!");
247 		else
248 			printf("\nNot on cylinder error!");
249 		printf("   Status = 0x%lx", status);
250 		if(C_INFO.type == SMD_ECTLR)
251 			printf("  Error code =  0x%x", dcb.err_code & 0xff);
252 		printf("\n");
253 		printf("cylinder = %d, track = %d,", dcb.err_cyl, dcb.err_trk);
254 		printf(" sector = %d, op = 0x%x\n", dcb.err_sec, dcb.opcode);
255 		reset_controller();
256 		dcb.operrsta &= HEADER_ERROR;
257 	}
258 	return (int)(!(status & (DATA_ERROR | HEADER_ERROR)));
259 }
260 
261 
262 /*
263 **
264 */
265 
266 reset_controller()
267 {
268 	printf("Resetting controller.  Please wait...\n");
269 	spin_up_drive();
270 	printf("Controller was reset successfully.\n");
271 }
272 
273 /*
274 **
275 */
276 
277 static	int	indent_count;
278 
279 
280 /*
281 **
282 */
283 
284 indent()
285 {
286 	indent_count += 2;
287 }
288 
289 
290 /*
291 **
292 */
293 
294 exdent(count)
295 int	count;
296 {
297 	if(count == -1)
298 		indent_count = 0;
299 	else
300 		indent_count -= count * 2;
301 	if(indent_count < 0)
302 			indent_count = 0;
303 }
304 
305 
306 /*
307 **
308 */
309 /*VARARGS1*/
310 print(par0, par1, par2, par3, par4, par5, par6)
311 char	*par0, *par1, *par2, *par3, *par4, *par5, *par6;
312 {
313 	register int	count = indent_count;
314 
315 	while(count--)
316 		printf(" ");
317 	printf(par0, par1, par2, par3, par4, par5, par6);
318 	DELAY((strlen(par0) + 20) * 9000);
319 }
320