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