xref: /csrg-svn/sys/tahoe/stand/vdformat/io.c (revision 31318)
129532Ssam #ifndef lint
2*31318Ssam static char sccsid[] = "@(#)io.c	1.4 (Berkeley/CCI) 06/01/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 {
2929532Ssam 	int	tokens[10];
3029981Skarels 	int	didmsg = 0;
3129532Ssam 
3229981Skarels 	wait_for_char = 0;
3329532Ssam 	vdtimeout = wait*1000*1000;
3429532Ssam 	uncache(&(dcb.operrsta));
35*31318Ssam 	while (!((dcb.operrsta) & (DCBS_DONE | DCBS_ABORT))) {
3629981Skarels 		if (input()) {
3729532Ssam 			get_text_cmd(nul_table, tokens);
3829981Skarels 			if (didmsg == 0 && kill_processes == true) {
3929981Skarels 				didmsg = 1;
4029532Ssam 				indent();
4129532Ssam 				print(clean_up);
4229532Ssam 				exdent(1);
4329532Ssam 			}
4429532Ssam 		}
4529532Ssam 		vdtimeout--;
4629532Ssam 		uncache(&(dcb.operrsta));
4729532Ssam 		if (vdtimeout <= 0) {
48*31318Ssam 			if(C_INFO.type == VDTYPE_VDDC)
4929532Ssam 				printf("\nVDDC");
5029532Ssam 			else
5129532Ssam 				printf("\nSMD-E");
5229532Ssam 			printf(": Controller timeout");
53*31318Ssam 			VDABORT(C_INFO.addr, C_INFO.type);
5429532Ssam 			DELAY(30000);
5529532Ssam 			break;
5629532Ssam 		}
5729532Ssam 	}
5829532Ssam 	if((vdtimeout > 0)) {
59*31318Ssam 		if(C_INFO.type == VDTYPE_SMDE) {
60*31318Ssam 			uncache(&(C_INFO.addr->vdcsr));
61*31318Ssam 			while(C_INFO.addr->vdcsr & CS_GO) {
6229532Ssam 				DELAY(50);
63*31318Ssam 				uncache(&(C_INFO.addr->vdcsr));
6429532Ssam 			}
6529532Ssam 		}
6629532Ssam 		DELAY(500);
6729532Ssam 	}
68*31318Ssam 	if((dcb.opcode == VDOP_RD) || (dcb.opcode == VDOP_RDRAW))
6929981Skarels 		mtpr(PADC, 0);
7029532Ssam 	uncache(&(dcb.operrsta));
7129981Skarels 	uncache(&(dcb.err_code));
7229981Skarels 	wait_for_char = 1;
7329532Ssam }
7429532Ssam 
7529532Ssam 
7629532Ssam /*
7729532Ssam **	Access_with_no_trailer is used to perform controller functions which
7829532Ssam ** require no data movement.
7929532Ssam */
8029532Ssam 
8129532Ssam access_with_no_trailer(function, wait_time)
8229532Ssam int	function, wait_time;
8329532Ssam {
8429532Ssam 	dcb.opcode = function;		/* command */
85*31318Ssam 	dcb.intflg = DCBINT_NONE;
86*31318Ssam 	dcb.nxtdcb = (struct dcb *)0;	/* end of chain */
8729532Ssam 	dcb.operrsta  = 0;
88*31318Ssam 	dcb.devselect = (function == VDOP_START) ? 0 : (char)cur.drive;
8929532Ssam 	dcb.trailcnt = (char)0;
90*31318Ssam 	mdcb.mdcb_head = &dcb;
91*31318Ssam 	mdcb.mdcb_status = 0;
92*31318Ssam 	VDGO(C_INFO.addr, (u_long)&mdcb, C_INFO.type);
9329532Ssam 	poll(wait_time);
9429532Ssam 	if(vdtimeout <= 0) {
9529532Ssam 		printf(" during startup operation.\n");
9629532Ssam 		_longjmp(abort_environ, 1);
9729532Ssam 	}
9829532Ssam 	return dcb.operrsta;
9929532Ssam }
10029532Ssam 
10129532Ssam 
10229532Ssam /*
10329532Ssam **	access_dsk is used by other routines to do reads and writes to the disk.
10429532Ssam ** The status of the read / write is returned to the caller for processing.
10529532Ssam */
10629532Ssam 
10729532Ssam access_dsk(buf, dskaddr, func, count, wait)
10829532Ssam char	*buf;
10929532Ssam dskadr	*dskaddr;
11029532Ssam int	func, count, wait;
11129532Ssam {
11229532Ssam 	cur.daddr.cylinder = dskaddr->cylinder;
11329532Ssam 	cur.daddr.track = dskaddr->track;
11429981Skarels 	wait_for_char = 0;
11529532Ssam 	dcb.opcode = func;		/* format sector command */
116*31318Ssam 	dcb.intflg = DCBINT_NONE;
117*31318Ssam 	dcb.nxtdcb = (struct dcb *)0;	/* end of chain */
11829532Ssam 	dcb.operrsta  = 0;
11929532Ssam 	dcb.devselect = (char)cur.drive;
120*31318Ssam 	if(func == VDOP_SEEK) {
121*31318Ssam 		dcb.trailcnt = (char)(sizeof(struct trseek) / sizeof(long));
12229532Ssam 		dcb.trail.sktrail.skaddr.cylinder = dskaddr->cylinder;
12329532Ssam 		dcb.trail.sktrail.skaddr.track = dskaddr->track;
12429532Ssam 		dcb.trail.sktrail.skaddr.sector = dskaddr->sector;
12529532Ssam 	}
12629532Ssam 	else {
127*31318Ssam 		dcb.trailcnt = (char)(sizeof(struct trrw) / sizeof(long));
128*31318Ssam 		dcb.trail.rwtrail.memadr = (u_long)buf;
12929532Ssam 		dcb.trail.rwtrail.wcount=count*(SECSIZ/sizeof(short));
13029532Ssam 		dcb.trail.rwtrail.disk.cylinder = dskaddr->cylinder;
13129532Ssam 		dcb.trail.rwtrail.disk.track = dskaddr->track;
13229532Ssam 		dcb.trail.rwtrail.disk.sector = dskaddr->sector;
13329532Ssam 	}
134*31318Ssam 	mdcb.mdcb_head = &dcb;
135*31318Ssam 	mdcb.mdcb_status = 0;
136*31318Ssam 	VDGO(C_INFO.addr, (u_long)&mdcb, C_INFO.type);
13729532Ssam 	if(wait) {
13829532Ssam 		poll(2*60);
13929532Ssam 		if(vdtimeout <= 0) {
14029532Ssam 			printf(" in access_dsk.\n");
14129532Ssam 			_longjmp(abort_environ, 1);
14229532Ssam 		}
14329532Ssam 	}
14429981Skarels 	wait_for_char = 1;
14529532Ssam 	return dcb.operrsta;
14629532Ssam }
14729532Ssam 
14829532Ssam 
14929532Ssam /*
15029532Ssam **	Spin_up_drive starts the drives on a controller and waits around for
15129532Ssam ** the drive to spin up if it is not already spinning.
15229532Ssam */
15329532Ssam 
15429532Ssam spin_up_drive()
15529532Ssam {
156*31318Ssam 	VDRESET(C_INFO.addr, C_INFO.type);
157*31318Ssam 	if(C_INFO.type == VDTYPE_SMDE) {
158*31318Ssam 		C_INFO.addr->vdcsr =  0;
159*31318Ssam 		C_INFO.addr->vdtcf_mdcb =  AM_ENPDA;
160*31318Ssam 		C_INFO.addr->vdtcf_dcb =  AM_ENPDA;
161*31318Ssam 		C_INFO.addr->vdtcf_trail =  AM_ENPDA;
162*31318Ssam 		C_INFO.addr->vdtcf_data =  AM_ENPDA;
163*31318Ssam 		C_INFO.addr->vdccf = CCF_SEN | 0x8 | CCF_STS |
16429532Ssam 		    XMD_32BIT | BSZ_16WRD | CCF_ERR |
16529532Ssam 		    CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE;
16629532Ssam 	}
167*31318Ssam 	access_with_no_trailer(VDOP_INIT, 10);
168*31318Ssam 	access_with_no_trailer(VDOP_DIAG, 20);
16929532Ssam 	configure_drive(0);
17029532Ssam }
17129532Ssam 
17229532Ssam /*
17329532Ssam **	Configure_drive tells the controller what kind of drive is attached
17429532Ssam ** on a particular line.
17529532Ssam */
17629532Ssam 
17729532Ssam configure_drive(pass)
17829532Ssam int	pass;
17929532Ssam {
180*31318Ssam 	dcb.opcode = VDOP_CONFIG;		/* command */
181*31318Ssam 	dcb.intflg = DCBINT_NONE;
182*31318Ssam 	dcb.nxtdcb = (struct dcb *)0;	/* end of chain */
18329532Ssam 	dcb.operrsta  = 0;
18429532Ssam 	dcb.devselect = (char)cur.drive;
18529532Ssam 	dcb.trail.rstrail.ncyl = CURRENT->vc_ncyl;
18629532Ssam 	dcb.trail.rstrail.nsurfaces = CURRENT->vc_ntrak;
187*31318Ssam 	if(C_INFO.type == VDTYPE_VDDC)
18829532Ssam 		dcb.trailcnt = (char)2;
18929532Ssam 	else {
19029532Ssam 		dcb.trailcnt = (char)4;
19129532Ssam 		dcb.trail.rstrail.nsectors = CURRENT->vc_nsec;
19229532Ssam 		dcb.trail.rstrail.slip_sec = CURRENT->vc_nslip;
19329532Ssam 		dcb.trail.rstrail.recovery = 0x00;
194*31318Ssam 		C_INFO.addr->vdcylskew = (*C_INFO.cylinder_skew)();
195*31318Ssam 		C_INFO.addr->vdtrackskew = (*C_INFO.track_skew)();
19629532Ssam 	}
197*31318Ssam 	mdcb.mdcb_head = &dcb;
198*31318Ssam 	mdcb.mdcb_status = 0;
199*31318Ssam 	VDGO(C_INFO.addr, (u_long)&mdcb, C_INFO.type);
20029532Ssam 	poll(5);
20129532Ssam 	if(vdtimeout <= 0) {
20229532Ssam 		printf(" during drive configuration.\n");
20329532Ssam 		_longjmp(abort_environ, 1);
20429532Ssam 	}
205*31318Ssam 	if(dcb.operrsta & (DCBS_OCYL | DCBS_NRDY)) {
20629532Ssam 		if(pass) {
20729532Ssam 			printf("\nDrive failed to start!\n\n");
20829532Ssam 			_longjmp(abort_environ, -1);
20929532Ssam 		}
21029981Skarels 		printf("\ndrive not ready, attempting to spin up...");
211*31318Ssam 		access_with_no_trailer(VDOP_START, (cur.drive * 6) + 62);
21229532Ssam 		DELAY((cur.drive * 5500000) + 62000000);
21329981Skarels 		printf(" retrying drive configuration\n");
21429532Ssam 		configure_drive(1);
21529532Ssam 	}
21629532Ssam }
21729532Ssam 
21829532Ssam 
21929532Ssam /*
22029532Ssam ** 	data_ok checks an error status word for bit patterns
22129532Ssam **  associated with error conditions from the VDDC controller.  If a hardware
22229532Ssam **  error is present then the problem is reported on the console and the program
22329532Ssam **  is halted.  If a data error is present the a zero is returned.
22429532Ssam **  If everything is OK then a 1 is returned.
22529532Ssam */
22629532Ssam 
22729532Ssam data_ok()
22829532Ssam {
22929532Ssam 	register int	status = dcb.operrsta;
23029532Ssam 
23129532Ssam 	if(status & HARD_ERROR){
232*31318Ssam 		if(status & DCBS_NRDY)
23329532Ssam 			printf("\nDrive is not ready!");
234*31318Ssam 		else if(status & DCBS_IVA)
23529532Ssam 			printf("\nInvalid disk address issued!");
236*31318Ssam 		else if(status & DCBS_NEM)
23729532Ssam 			printf("\nNon-existent memory error!");
238*31318Ssam 		else if(status & DCBS_DPE)
23929532Ssam 			printf("\nMain memory parity error!");
240*31318Ssam 		else if(status & DCBS_OAB)
24129532Ssam 			printf("\nCPU aborted operation!");
242*31318Ssam 		else if(status & DCBS_WPT)
24329532Ssam 			printf("\nDrive is write protected!");
244*31318Ssam 		else if(status & DCBS_SKI)
24529532Ssam 			printf("\nDisk seek error!");
246*31318Ssam 		else if(status & DCBS_CHE)
24729532Ssam 			printf("\nController hardware error!");
24829532Ssam 		else
24929532Ssam 			printf("\nNot on cylinder error!");
25029532Ssam 		printf("   Status = 0x%lx", status);
251*31318Ssam 		if(C_INFO.type == VDTYPE_SMDE)
25229532Ssam 			printf("  Error code =  0x%x", dcb.err_code & 0xff);
25329532Ssam 		printf("\n");
25429532Ssam 		printf("cylinder = %d, track = %d,", dcb.err_cyl, dcb.err_trk);
25529532Ssam 		printf(" sector = %d, op = 0x%x\n", dcb.err_sec, dcb.opcode);
25629532Ssam 		reset_controller();
25729532Ssam 		dcb.operrsta &= HEADER_ERROR;
25829532Ssam 	}
25929532Ssam 	return (int)(!(status & (DATA_ERROR | HEADER_ERROR)));
26029532Ssam }
26129532Ssam 
26229532Ssam 
26329532Ssam /*
26429532Ssam **
26529532Ssam */
26629532Ssam 
26729532Ssam reset_controller()
26829532Ssam {
26929532Ssam 	printf("Resetting controller.  Please wait...\n");
27029532Ssam 	spin_up_drive();
27129532Ssam 	printf("Controller was reset successfully.\n");
27229532Ssam }
27329532Ssam 
27429532Ssam /*
27529532Ssam **
27629532Ssam */
27729532Ssam 
27829532Ssam static	int	indent_count;
27929532Ssam 
28029532Ssam 
28129532Ssam /*
28229532Ssam **
28329532Ssam */
28429532Ssam 
28529532Ssam indent()
28629532Ssam {
28729532Ssam 	indent_count += 2;
28829532Ssam }
28929532Ssam 
29029532Ssam 
29129532Ssam /*
29229532Ssam **
29329532Ssam */
29429532Ssam 
29529532Ssam exdent(count)
29629532Ssam int	count;
29729532Ssam {
29829532Ssam 	if(count == -1)
29929532Ssam 		indent_count = 0;
30029532Ssam 	else
30129532Ssam 		indent_count -= count * 2;
30229532Ssam 	if(indent_count < 0)
30329532Ssam 			indent_count = 0;
30429532Ssam }
30529532Ssam 
30629532Ssam 
30729532Ssam /*
30829532Ssam **
30929532Ssam */
31029532Ssam /*VARARGS1*/
31129532Ssam print(par0, par1, par2, par3, par4, par5, par6)
31229532Ssam char	*par0, *par1, *par2, *par3, *par4, *par5, *par6;
31329532Ssam {
31429532Ssam 	register int	count = indent_count;
31529532Ssam 
31629532Ssam 	while(count--)
31729532Ssam 		printf(" ");
31829532Ssam 	printf(par0, par1, par2, par3, par4, par5, par6);
31929532Ssam 	DELAY((strlen(par0) + 20) * 9000);
32029532Ssam }
321