xref: /csrg-svn/sys/tahoe/stand/vdformat/io.c (revision 32662)
129532Ssam #ifndef lint
2*32662Skarels static char sccsid[] = "@(#)io.c	1.5 (Berkeley/CCI) 11/23/87";
329532Ssam #endif
429532Ssam 
529532Ssam #include	"vdfmt.h"
629532Ssam #include	"cmd.h"
729532Ssam 
829532Ssam 
929532Ssam /*
1029532Ssam **
1129532Ssam */
1229532Ssam 
1329532Ssam static cmd_text_element	nul_table[] = {
1429532Ssam 	{ 0,	"",	"" }
1529532Ssam };
1629532Ssam 
1729981Skarels int wait_for_char;
1830324Skarels int vdtimeout;
1929532Ssam char	*clean_up = "Cleaning up...  Please wait.\n";
2029532Ssam 
2129532Ssam 
2229532Ssam /*
2329532Ssam **
2429532Ssam */
2529532Ssam 
2629532Ssam poll(wait)
2729532Ssam int	wait;
2829532Ssam {
29*32662Skarels 	register struct vddevice *addr = C_INFO->addr;
3029532Ssam 	int	tokens[10];
3129981Skarels 	int	didmsg = 0;
3229532Ssam 
3329981Skarels 	wait_for_char = 0;
34*32662Skarels 	vdtimeout = wait*1000;
35*32662Skarels 	for (;;) {
36*32662Skarels 		uncache(&(dcb.operrsta));
37*32662Skarels 		if (dcb.operrsta & (DCBS_DONE | DCBS_ABORT))
38*32662Skarels 			break;
3929981Skarels 		if (input()) {
4029532Ssam 			get_text_cmd(nul_table, tokens);
4129981Skarels 			if (didmsg == 0 && kill_processes == true) {
4229981Skarels 				didmsg = 1;
4329532Ssam 				indent();
4429532Ssam 				print(clean_up);
4529532Ssam 				exdent(1);
4629532Ssam 			}
4729532Ssam 		}
48*32662Skarels 		if (vdtimeout-- <= 0) {
49*32662Skarels 			if(C_INFO->type == VDTYPE_VDDC)
5029532Ssam 				printf("\nVDDC");
5129532Ssam 			else
5229532Ssam 				printf("\nSMD-E");
5329532Ssam 			printf(": Controller timeout");
54*32662Skarels abort:
55*32662Skarels 			VDABORT(addr, C_INFO->type);
5629532Ssam 			DELAY(30000);
5729532Ssam 			break;
5829532Ssam 		}
59*32662Skarels 		DELAY(1000);
6029532Ssam 	}
61*32662Skarels 	if ((vdtimeout > 0)) {
62*32662Skarels 		if (C_INFO->type == VDTYPE_SMDE) {
63*32662Skarels 			for (;;) {
64*32662Skarels 				uncache(&(addr->vdcsr));
65*32662Skarels 				if ((addr->vdcsr & CS_GO) == 0)
66*32662Skarels 					break;
67*32662Skarels 				DELAY(1000);
68*32662Skarels 				if (vdtimeout-- <= 0) {
69*32662Skarels 					printf("\nSMD-E timed out clearing GO");
70*32662Skarels 					goto abort;
71*32662Skarels 				}
7229532Ssam 			}
73*32662Skarels 			DELAY(300);
7429532Ssam 		}
7529532Ssam 		DELAY(500);
7629532Ssam 	}
77*32662Skarels 	DELAY(200);
7831318Ssam 	if((dcb.opcode == VDOP_RD) || (dcb.opcode == VDOP_RDRAW))
7929981Skarels 		mtpr(PADC, 0);
8029532Ssam 	uncache(&(dcb.operrsta));
8129981Skarels 	uncache(&(dcb.err_code));
8229981Skarels 	wait_for_char = 1;
8329532Ssam }
8429532Ssam 
8529532Ssam 
8629532Ssam /*
8729532Ssam **	Access_with_no_trailer is used to perform controller functions which
8829532Ssam ** require no data movement.
8929532Ssam */
9029532Ssam 
9129532Ssam access_with_no_trailer(function, wait_time)
9229532Ssam int	function, wait_time;
9329532Ssam {
9429532Ssam 	dcb.opcode = function;		/* command */
9531318Ssam 	dcb.intflg = DCBINT_NONE;
9631318Ssam 	dcb.nxtdcb = (struct dcb *)0;	/* end of chain */
9729532Ssam 	dcb.operrsta  = 0;
98*32662Skarels 	dcb.devselect = (function == VDOP_START) ? 0 :
99*32662Skarels 	    ((char)cur.drive | lab->d_devflags);
10029532Ssam 	dcb.trailcnt = (char)0;
10131318Ssam 	mdcb.mdcb_head = &dcb;
10231318Ssam 	mdcb.mdcb_status = 0;
103*32662Skarels 	VDGO(C_INFO->addr, (u_long)&mdcb, C_INFO->type);
10429532Ssam 	poll(wait_time);
10529532Ssam 	if(vdtimeout <= 0) {
10629532Ssam 		printf(" during startup operation.\n");
10729532Ssam 		_longjmp(abort_environ, 1);
10829532Ssam 	}
10929532Ssam 	return dcb.operrsta;
11029532Ssam }
11129532Ssam 
112*32662Skarels vread(sn, buf, seccnt)
113*32662Skarels int sn, seccnt;
114*32662Skarels char *buf;
115*32662Skarels {
116*32662Skarels 	return (vrdwr(sn, buf, seccnt, VDOP_RD));
117*32662Skarels }
11829532Ssam 
119*32662Skarels vwrite(sn, buf, seccnt)
120*32662Skarels int sn, seccnt;
121*32662Skarels char *buf;
122*32662Skarels {
123*32662Skarels 	return (vrdwr(sn, buf, seccnt, VDOP_WD));
124*32662Skarels }
125*32662Skarels 
126*32662Skarels vrdwr(sn, buf, seccnt, op)
127*32662Skarels int sn, seccnt, op;
128*32662Skarels char *buf;
129*32662Skarels {
130*32662Skarels 	dskadr	dskaddr;
131*32662Skarels 
132*32662Skarels 	dskaddr.cylinder = sn / lab->d_secpercyl;
133*32662Skarels 	sn %= lab->d_secpercyl;
134*32662Skarels 	dskaddr.track = sn / lab->d_nsectors;
135*32662Skarels 	dskaddr.sector = sn % lab->d_nsectors;
136*32662Skarels 	if (access_dsk(buf, &dskaddr, op, seccnt, 1) & DCBS_HARD)
137*32662Skarels 		return (0);
138*32662Skarels 	return (seccnt);
139*32662Skarels }
140*32662Skarels 
14129532Ssam /*
14229532Ssam **	access_dsk is used by other routines to do reads and writes to the disk.
14329532Ssam ** The status of the read / write is returned to the caller for processing.
14429532Ssam */
14529532Ssam 
14629532Ssam access_dsk(buf, dskaddr, func, count, wait)
14729532Ssam char	*buf;
14829532Ssam dskadr	*dskaddr;
14929532Ssam int	func, count, wait;
15029532Ssam {
15129532Ssam 	cur.daddr.cylinder = dskaddr->cylinder;
15229532Ssam 	cur.daddr.track = dskaddr->track;
15329981Skarels 	wait_for_char = 0;
15429532Ssam 	dcb.opcode = func;		/* format sector command */
15531318Ssam 	dcb.intflg = DCBINT_NONE;
15631318Ssam 	dcb.nxtdcb = (struct dcb *)0;	/* end of chain */
15729532Ssam 	dcb.operrsta  = 0;
158*32662Skarels 	dcb.devselect = (char)cur.drive | lab->d_devflags;
15931318Ssam 	if(func == VDOP_SEEK) {
16031318Ssam 		dcb.trailcnt = (char)(sizeof(struct trseek) / sizeof(long));
16129532Ssam 		dcb.trail.sktrail.skaddr.cylinder = dskaddr->cylinder;
16229532Ssam 		dcb.trail.sktrail.skaddr.track = dskaddr->track;
16329532Ssam 		dcb.trail.sktrail.skaddr.sector = dskaddr->sector;
164*32662Skarels 	} else {
16531318Ssam 		dcb.trailcnt = (char)(sizeof(struct trrw) / sizeof(long));
16631318Ssam 		dcb.trail.rwtrail.memadr = (u_long)buf;
167*32662Skarels 		dcb.trail.rwtrail.wcount=count*(lab->d_secsize/sizeof(short));
16829532Ssam 		dcb.trail.rwtrail.disk.cylinder = dskaddr->cylinder;
16929532Ssam 		dcb.trail.rwtrail.disk.track = dskaddr->track;
17029532Ssam 		dcb.trail.rwtrail.disk.sector = dskaddr->sector;
17129532Ssam 	}
17231318Ssam 	mdcb.mdcb_head = &dcb;
17331318Ssam 	mdcb.mdcb_status = 0;
174*32662Skarels 	VDGO(C_INFO->addr, (u_long)&mdcb, C_INFO->type);
17529532Ssam 	if(wait) {
176*32662Skarels 		poll(10);
17729532Ssam 		if(vdtimeout <= 0) {
17829532Ssam 			printf(" in access_dsk.\n");
17929532Ssam 			_longjmp(abort_environ, 1);
18029532Ssam 		}
18129532Ssam 	}
18229981Skarels 	wait_for_char = 1;
18329532Ssam 	return dcb.operrsta;
18429532Ssam }
18529532Ssam 
18629532Ssam 
18729532Ssam /*
18829532Ssam **	Spin_up_drive starts the drives on a controller and waits around for
18929532Ssam ** the drive to spin up if it is not already spinning.
19029532Ssam */
19129532Ssam 
19229532Ssam spin_up_drive()
19329532Ssam {
194*32662Skarels 	register struct vddevice *addr = C_INFO->addr;
195*32662Skarels 
196*32662Skarels 	VDRESET(addr, C_INFO->type);
197*32662Skarels 	if(C_INFO->type == VDTYPE_SMDE) {
198*32662Skarels 		addr->vdcsr =  0;
199*32662Skarels 		addr->vdtcf_mdcb =  AM_ENPDA;
200*32662Skarels 		addr->vdtcf_dcb =  AM_ENPDA;
201*32662Skarels 		addr->vdtcf_trail =  AM_ENPDA;
202*32662Skarels 		addr->vdtcf_data =  AM_ENPDA;
203*32662Skarels 		addr->vdccf = CCF_SEN | 0x8 | CCF_STS |
20429532Ssam 		    XMD_32BIT | BSZ_16WRD | CCF_ERR |
20529532Ssam 		    CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE;
20629532Ssam 	}
20731318Ssam 	access_with_no_trailer(VDOP_INIT, 10);
20831318Ssam 	access_with_no_trailer(VDOP_DIAG, 20);
20929532Ssam 	configure_drive(0);
21029532Ssam }
21129532Ssam 
21229532Ssam /*
21329532Ssam **	Configure_drive tells the controller what kind of drive is attached
21429532Ssam ** on a particular line.
21529532Ssam */
21629532Ssam 
21729532Ssam configure_drive(pass)
21829532Ssam int	pass;
21929532Ssam {
220*32662Skarels 	register struct vddevice *addr = C_INFO->addr;
221*32662Skarels 	register i;
222*32662Skarels 
223*32662Skarels top:
22431318Ssam 	dcb.opcode = VDOP_CONFIG;		/* command */
22531318Ssam 	dcb.intflg = DCBINT_NONE;
22631318Ssam 	dcb.nxtdcb = (struct dcb *)0;	/* end of chain */
227*32662Skarels 	dcb.operrsta = 0;
228*32662Skarels 	dcb.devselect = cur.drive | lab->d_devflags;
229*32662Skarels 	dcb.trail.rstrail.ncyl = lab->d_ncylinders;
230*32662Skarels 	dcb.trail.rstrail.nsurfaces = lab->d_ntracks;
231*32662Skarels 	if(C_INFO->type == VDTYPE_VDDC)
23229532Ssam 		dcb.trailcnt = (char)2;
23329532Ssam 	else {
234*32662Skarels 		dcb.trailcnt = sizeof (struct treset)/sizeof (long);
235*32662Skarels 		dcb.trail.rstrail.nsectors = lab->d_nsectors;
236*32662Skarels 		dcb.trail.rstrail.slip_sec = lab->d_sparespertrack;
237*32662Skarels 		dcb.trail.rstrail.recovery = VDRF_NONE;
238*32662Skarels 		addr->vdcylskew = lab->d_cylskew;
239*32662Skarels 		addr->vdtrackskew = lab->d_trackskew;
240*32662Skarels /*
241*32662Skarels 		addr->vdsecsize = lab->d_secsize/sizeof(short);
242*32662Skarels */
24329532Ssam 	}
244*32662Skarels printf("devsel %x, ncyl %d, ntrk %d, nsec %d, slip %d, cylskew %d, trackskew %d, secsize %d\n", dcb.devselect, dcb.trail.rstrail.ncyl, dcb.trail.rstrail.nsurfaces, dcb.trail.rstrail.nsectors, dcb.trail.rstrail.slip_sec, lab->d_cylskew, lab->d_trackskew, lab->d_secsize);
24531318Ssam 	mdcb.mdcb_head = &dcb;
24631318Ssam 	mdcb.mdcb_status = 0;
247*32662Skarels 	VDGO(addr, (u_long)&mdcb, C_INFO->type);
24829532Ssam 	poll(5);
24929532Ssam 	if(vdtimeout <= 0) {
25029532Ssam 		printf(" during drive configuration.\n");
251*32662Skarels 		goto bad;
25229532Ssam 	}
253*32662Skarels 	if(dcb.operrsta & VDERR_HARD) {
254*32662Skarels 		if (C_INFO->type == VDTYPE_SMDE) {
255*32662Skarels 			if (lab->d_devflags == 0) {
256*32662Skarels 				lab->d_devflags = VD_ESDI;
257*32662Skarels 				goto top;
258*32662Skarels 			}
259*32662Skarels #ifdef notdef
260*32662Skarels printf("vdstatus %x\n", addr->vdstatus[cur.drive]);
261*32662Skarels 			if ((addr->vdstatus[cur.drive] & STA_US) == 0) {
262*32662Skarels 				printf("Drive not present\n\n");
263*32662Skarels 				goto bad;
264*32662Skarels 			}
265*32662Skarels #endif
266*32662Skarels 		}
267*32662Skarels 		if ((dcb.operrsta & (DCBS_OCYL|DCBS_NRDY)) == 0) {
268*32662Skarels 			printf("drive config error\n");
269*32662Skarels 			goto bad;
270*32662Skarels 		}
27129532Ssam 		if(pass) {
27229532Ssam 			printf("\nDrive failed to start!\n\n");
273*32662Skarels 			goto bad;
27429532Ssam 		}
27529981Skarels 		printf("\ndrive not ready, attempting to spin up...");
276*32662Skarels 		access_with_no_trailer(VDOP_START, 62);
277*32662Skarels 		for (i = 0; i < 620; i++) {
278*32662Skarels 			if (C_INFO->type == VDTYPE_SMDE &&
279*32662Skarels 			    addr->vdstatus[cur.drive] & STA_UR)
280*32662Skarels 				break;
281*32662Skarels 			DELAY(100000);
282*32662Skarels 		}
28329981Skarels 		printf(" retrying drive configuration\n");
284*32662Skarels 		pass++;
285*32662Skarels 		lab->d_devflags = 0;
286*32662Skarels 		goto top;
28729532Ssam 	}
288*32662Skarels 	D_INFO->alive = u_true;
289*32662Skarels 	return;
290*32662Skarels bad:
291*32662Skarels 	D_INFO->alive = u_false;
292*32662Skarels 	_longjmp(abort_environ, -1);
29329532Ssam }
29429532Ssam 
29529532Ssam 
29629532Ssam /*
29729532Ssam ** 	data_ok checks an error status word for bit patterns
29829532Ssam **  associated with error conditions from the VDDC controller.  If a hardware
29929532Ssam **  error is present then the problem is reported on the console and the program
30029532Ssam **  is halted.  If a data error is present the a zero is returned.
30129532Ssam **  If everything is OK then a 1 is returned.
30229532Ssam */
30329532Ssam 
30429532Ssam data_ok()
30529532Ssam {
30629532Ssam 	register int	status = dcb.operrsta;
30729532Ssam 
30829532Ssam 	if(status & HARD_ERROR){
30931318Ssam 		if(status & DCBS_NRDY)
31029532Ssam 			printf("\nDrive is not ready!");
31131318Ssam 		else if(status & DCBS_IVA)
31229532Ssam 			printf("\nInvalid disk address issued!");
31331318Ssam 		else if(status & DCBS_NEM)
31429532Ssam 			printf("\nNon-existent memory error!");
31531318Ssam 		else if(status & DCBS_DPE)
31629532Ssam 			printf("\nMain memory parity error!");
31731318Ssam 		else if(status & DCBS_OAB)
31829532Ssam 			printf("\nCPU aborted operation!");
31931318Ssam 		else if(status & DCBS_WPT)
32029532Ssam 			printf("\nDrive is write protected!");
32131318Ssam 		else if(status & DCBS_SKI)
32229532Ssam 			printf("\nDisk seek error!");
32331318Ssam 		else if(status & DCBS_CHE)
32429532Ssam 			printf("\nController hardware error!");
32529532Ssam 		else
32629532Ssam 			printf("\nNot on cylinder error!");
32729532Ssam 		printf("   Status = 0x%lx", status);
328*32662Skarels 		if(C_INFO->type == VDTYPE_SMDE)
32929532Ssam 			printf("  Error code =  0x%x", dcb.err_code & 0xff);
33029532Ssam 		printf("\n");
33129532Ssam 		printf("cylinder = %d, track = %d,", dcb.err_cyl, dcb.err_trk);
33229532Ssam 		printf(" sector = %d, op = 0x%x\n", dcb.err_sec, dcb.opcode);
33329532Ssam 		reset_controller();
33429532Ssam 		dcb.operrsta &= HEADER_ERROR;
33529532Ssam 	}
33629532Ssam 	return (int)(!(status & (DATA_ERROR | HEADER_ERROR)));
33729532Ssam }
33829532Ssam 
33929532Ssam 
34029532Ssam /*
34129532Ssam **
34229532Ssam */
34329532Ssam 
34429532Ssam reset_controller()
34529532Ssam {
34629532Ssam 	printf("Resetting controller.  Please wait...\n");
34729532Ssam 	spin_up_drive();
34829532Ssam 	printf("Controller was reset successfully.\n");
34929532Ssam }
35029532Ssam 
35129532Ssam /*
35229532Ssam **
35329532Ssam */
35429532Ssam 
35529532Ssam static	int	indent_count;
35629532Ssam 
35729532Ssam 
35829532Ssam /*
35929532Ssam **
36029532Ssam */
36129532Ssam 
36229532Ssam indent()
36329532Ssam {
36429532Ssam 	indent_count += 2;
36529532Ssam }
36629532Ssam 
36729532Ssam 
36829532Ssam /*
36929532Ssam **
37029532Ssam */
37129532Ssam 
37229532Ssam exdent(count)
37329532Ssam int	count;
37429532Ssam {
37529532Ssam 	if(count == -1)
37629532Ssam 		indent_count = 0;
37729532Ssam 	else
37829532Ssam 		indent_count -= count * 2;
37929532Ssam 	if(indent_count < 0)
38029532Ssam 			indent_count = 0;
38129532Ssam }
38229532Ssam 
38329532Ssam 
38429532Ssam /*
38529532Ssam **
38629532Ssam */
38729532Ssam /*VARARGS1*/
38829532Ssam print(par0, par1, par2, par3, par4, par5, par6)
38929532Ssam char	*par0, *par1, *par2, *par3, *par4, *par5, *par6;
39029532Ssam {
39129532Ssam 	register int	count = indent_count;
39229532Ssam 
39329532Ssam 	while(count--)
39429532Ssam 		printf(" ");
39529532Ssam 	printf(par0, par1, par2, par3, par4, par5, par6);
39629532Ssam 	DELAY((strlen(par0) + 20) * 9000);
39729532Ssam }
398