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