xref: /csrg-svn/sys/tahoe/stand/vdformat/io.c (revision 34667)
129532Ssam #ifndef lint
2*34667Skarels static char sccsid[] = "@(#)io.c	1.7 (Berkeley/CCI) 06/07/88";
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 
poll(wait)2629532Ssam poll(wait)
2729532Ssam int	wait;
2829532Ssam {
2932662Skarels 	register struct vddevice *addr = C_INFO->addr;
3029532Ssam 	int	tokens[10];
3129532Ssam 
32*34667Skarels 	if (kill_processes == false)
33*34667Skarels 		wait_for_char = 0;
3432662Skarels 	vdtimeout = wait*1000;
3532662Skarels 	for (;;) {
3632662Skarels 		uncache(&(dcb.operrsta));
3732662Skarels 		if (dcb.operrsta & (DCBS_DONE | DCBS_ABORT))
3832662Skarels 			break;
39*34667Skarels 		if (kill_processes == false && input()) {
4029532Ssam 			get_text_cmd(nul_table, tokens);
41*34667Skarels 			if (kill_processes == true) {
4229532Ssam 				indent();
4329532Ssam 				print(clean_up);
4429532Ssam 				exdent(1);
4529532Ssam 			}
4629532Ssam 		}
4732662Skarels 		if (vdtimeout-- <= 0) {
4832662Skarels 			if(C_INFO->type == VDTYPE_VDDC)
4929532Ssam 				printf("\nVDDC");
5029532Ssam 			else
5129532Ssam 				printf("\nSMD-E");
5229532Ssam 			printf(": Controller timeout");
5332662Skarels abort:
5432662Skarels 			VDABORT(addr, C_INFO->type);
5529532Ssam 			DELAY(30000);
5629532Ssam 			break;
5729532Ssam 		}
5832662Skarels 		DELAY(1000);
5929532Ssam 	}
6032662Skarels 	if ((vdtimeout > 0)) {
6132662Skarels 		if (C_INFO->type == VDTYPE_SMDE) {
6232662Skarels 			for (;;) {
6332662Skarels 				uncache(&(addr->vdcsr));
6432662Skarels 				if ((addr->vdcsr & CS_GO) == 0)
6532662Skarels 					break;
6632662Skarels 				DELAY(1000);
6732662Skarels 				if (vdtimeout-- <= 0) {
6832662Skarels 					printf("\nSMD-E timed out clearing GO");
6932662Skarels 					goto abort;
7032662Skarels 				}
7129532Ssam 			}
7232662Skarels 			DELAY(300);
7329532Ssam 		}
7429532Ssam 		DELAY(500);
7529532Ssam 	}
7632662Skarels 	DELAY(200);
7731318Ssam 	if((dcb.opcode == VDOP_RD) || (dcb.opcode == VDOP_RDRAW))
7829981Skarels 		mtpr(PADC, 0);
7929532Ssam 	uncache(&(dcb.operrsta));
8029981Skarels 	uncache(&(dcb.err_code));
8129981Skarels 	wait_for_char = 1;
8229532Ssam }
8329532Ssam 
8429532Ssam 
8529532Ssam /*
8629532Ssam **	Access_with_no_trailer is used to perform controller functions which
8729532Ssam ** require no data movement.
8829532Ssam */
8929532Ssam 
access_with_no_trailer(function,wait_time)9029532Ssam access_with_no_trailer(function, wait_time)
9129532Ssam int	function, wait_time;
9229532Ssam {
9329532Ssam 	dcb.opcode = function;		/* command */
9431318Ssam 	dcb.intflg = DCBINT_NONE;
9531318Ssam 	dcb.nxtdcb = (struct dcb *)0;	/* end of chain */
9629532Ssam 	dcb.operrsta  = 0;
9732662Skarels 	dcb.devselect = (function == VDOP_START) ? 0 :
9832662Skarels 	    ((char)cur.drive | lab->d_devflags);
9929532Ssam 	dcb.trailcnt = (char)0;
10031318Ssam 	mdcb.mdcb_head = &dcb;
10131318Ssam 	mdcb.mdcb_status = 0;
10232662Skarels 	VDGO(C_INFO->addr, (u_long)&mdcb, C_INFO->type);
10329532Ssam 	poll(wait_time);
10429532Ssam 	if(vdtimeout <= 0) {
10529532Ssam 		printf(" during startup operation.\n");
10629532Ssam 		_longjmp(abort_environ, 1);
10729532Ssam 	}
10829532Ssam 	return dcb.operrsta;
10929532Ssam }
11029532Ssam 
vread(sn,buf,seccnt)11132662Skarels vread(sn, buf, seccnt)
11232662Skarels int sn, seccnt;
11332662Skarels char *buf;
11432662Skarels {
115*34667Skarels 	int ret;
116*34667Skarels 
117*34667Skarels 	ret = vrdwr(sn, buf, seccnt, VDOP_RD);
118*34667Skarels 	if (ret == 0)
119*34667Skarels 		vd_error("read");
120*34667Skarels 	return (ret);
12132662Skarels }
12229532Ssam 
vwrite(sn,buf,seccnt)12332662Skarels vwrite(sn, buf, seccnt)
12432662Skarels int sn, seccnt;
12532662Skarels char *buf;
12632662Skarels {
127*34667Skarels 	int ret;
12832662Skarels 
129*34667Skarels 	ret = vrdwr(sn, buf, seccnt, VDOP_WD);
130*34667Skarels 	if (ret == 0)
131*34667Skarels 		vd_error("write");
132*34667Skarels 	return (ret);
133*34667Skarels };
134*34667Skarels 
vrdwr(sn,buf,seccnt,op)13532662Skarels vrdwr(sn, buf, seccnt, op)
13632662Skarels int sn, seccnt, op;
13732662Skarels char *buf;
13832662Skarels {
13932662Skarels 	dskadr	dskaddr;
14032662Skarels 
14132662Skarels 	dskaddr.cylinder = sn / lab->d_secpercyl;
14232662Skarels 	sn %= lab->d_secpercyl;
14332662Skarels 	dskaddr.track = sn / lab->d_nsectors;
14432662Skarels 	dskaddr.sector = sn % lab->d_nsectors;
14532662Skarels 	if (access_dsk(buf, &dskaddr, op, seccnt, 1) & DCBS_HARD)
14632662Skarels 		return (0);
14732662Skarels 	return (seccnt);
14832662Skarels }
14932662Skarels 
15029532Ssam /*
15129532Ssam **	access_dsk is used by other routines to do reads and writes to the disk.
15229532Ssam ** The status of the read / write is returned to the caller for processing.
15329532Ssam */
15429532Ssam 
access_dsk(buf,dskaddr,func,count,wait)15529532Ssam access_dsk(buf, dskaddr, func, count, wait)
15629532Ssam char	*buf;
15729532Ssam dskadr	*dskaddr;
15829532Ssam int	func, count, wait;
15929532Ssam {
16029532Ssam 	cur.daddr.cylinder = dskaddr->cylinder;
16129532Ssam 	cur.daddr.track = dskaddr->track;
16229981Skarels 	wait_for_char = 0;
16329532Ssam 	dcb.opcode = func;		/* format sector command */
16431318Ssam 	dcb.intflg = DCBINT_NONE;
16531318Ssam 	dcb.nxtdcb = (struct dcb *)0;	/* end of chain */
16629532Ssam 	dcb.operrsta  = 0;
16732662Skarels 	dcb.devselect = (char)cur.drive | lab->d_devflags;
16831318Ssam 	if(func == VDOP_SEEK) {
16931318Ssam 		dcb.trailcnt = (char)(sizeof(struct trseek) / sizeof(long));
17029532Ssam 		dcb.trail.sktrail.skaddr.cylinder = dskaddr->cylinder;
17129532Ssam 		dcb.trail.sktrail.skaddr.track = dskaddr->track;
17229532Ssam 		dcb.trail.sktrail.skaddr.sector = dskaddr->sector;
17332662Skarels 	} else {
17431318Ssam 		dcb.trailcnt = (char)(sizeof(struct trrw) / sizeof(long));
17531318Ssam 		dcb.trail.rwtrail.memadr = (u_long)buf;
17632662Skarels 		dcb.trail.rwtrail.wcount=count*(lab->d_secsize/sizeof(short));
17729532Ssam 		dcb.trail.rwtrail.disk.cylinder = dskaddr->cylinder;
17829532Ssam 		dcb.trail.rwtrail.disk.track = dskaddr->track;
17929532Ssam 		dcb.trail.rwtrail.disk.sector = dskaddr->sector;
18029532Ssam 	}
18131318Ssam 	mdcb.mdcb_head = &dcb;
18231318Ssam 	mdcb.mdcb_status = 0;
18332662Skarels 	VDGO(C_INFO->addr, (u_long)&mdcb, C_INFO->type);
18429532Ssam 	if(wait) {
18532662Skarels 		poll(10);
18629532Ssam 		if(vdtimeout <= 0) {
18729532Ssam 			printf(" in access_dsk.\n");
18829532Ssam 			_longjmp(abort_environ, 1);
18929532Ssam 		}
19029532Ssam 	}
19129981Skarels 	wait_for_char = 1;
19229532Ssam 	return dcb.operrsta;
19329532Ssam }
19429532Ssam 
19529532Ssam 
19629532Ssam /*
19729532Ssam **	Spin_up_drive starts the drives on a controller and waits around for
19829532Ssam ** the drive to spin up if it is not already spinning.
19929532Ssam */
20029532Ssam 
spin_up_drive()20129532Ssam spin_up_drive()
20229532Ssam {
20332662Skarels 	register struct vddevice *addr = C_INFO->addr;
20432662Skarels 
20532662Skarels 	VDRESET(addr, C_INFO->type);
20632662Skarels 	if(C_INFO->type == VDTYPE_SMDE) {
20732662Skarels 		addr->vdcsr =  0;
20832662Skarels 		addr->vdtcf_mdcb =  AM_ENPDA;
20932662Skarels 		addr->vdtcf_dcb =  AM_ENPDA;
21032662Skarels 		addr->vdtcf_trail =  AM_ENPDA;
21132662Skarels 		addr->vdtcf_data =  AM_ENPDA;
21232662Skarels 		addr->vdccf = CCF_SEN | 0x8 | CCF_STS |
21329532Ssam 		    XMD_32BIT | BSZ_16WRD | CCF_ERR |
21429532Ssam 		    CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE;
21529532Ssam 	}
21631318Ssam 	access_with_no_trailer(VDOP_INIT, 10);
21731318Ssam 	access_with_no_trailer(VDOP_DIAG, 20);
21829532Ssam 	configure_drive(0);
21929532Ssam }
22029532Ssam 
22129532Ssam /*
22229532Ssam **	Configure_drive tells the controller what kind of drive is attached
22329532Ssam ** on a particular line.
22429532Ssam */
22529532Ssam 
configure_drive(pass)22629532Ssam configure_drive(pass)
22729532Ssam int	pass;
22829532Ssam {
22932662Skarels 	register struct vddevice *addr = C_INFO->addr;
23032662Skarels 	register i;
23132662Skarels 
23232662Skarels top:
23331318Ssam 	dcb.opcode = VDOP_CONFIG;		/* command */
23431318Ssam 	dcb.intflg = DCBINT_NONE;
23531318Ssam 	dcb.nxtdcb = (struct dcb *)0;	/* end of chain */
23632662Skarels 	dcb.operrsta = 0;
23732662Skarels 	dcb.devselect = cur.drive | lab->d_devflags;
23832662Skarels 	dcb.trail.rstrail.ncyl = lab->d_ncylinders;
23932662Skarels 	dcb.trail.rstrail.nsurfaces = lab->d_ntracks;
24032662Skarels 	if(C_INFO->type == VDTYPE_VDDC)
24129532Ssam 		dcb.trailcnt = (char)2;
24229532Ssam 	else {
24332662Skarels 		dcb.trailcnt = sizeof (struct treset)/sizeof (long);
24432662Skarels 		dcb.trail.rstrail.nsectors = lab->d_nsectors;
24532662Skarels 		dcb.trail.rstrail.slip_sec = lab->d_sparespertrack;
24632662Skarels 		dcb.trail.rstrail.recovery = VDRF_NONE;
24732662Skarels 		addr->vdcylskew = lab->d_cylskew;
24832662Skarels 		addr->vdtrackskew = lab->d_trackskew;
24932662Skarels 		addr->vdsecsize = lab->d_secsize/sizeof(short);
25029532Ssam 	}
25131318Ssam 	mdcb.mdcb_head = &dcb;
25231318Ssam 	mdcb.mdcb_status = 0;
25332662Skarels 	VDGO(addr, (u_long)&mdcb, C_INFO->type);
25429532Ssam 	poll(5);
25529532Ssam 	if(vdtimeout <= 0) {
25629532Ssam 		printf(" during drive configuration.\n");
25732662Skarels 		goto bad;
25829532Ssam 	}
25932662Skarels 	if(dcb.operrsta & VDERR_HARD) {
26032662Skarels 		if (C_INFO->type == VDTYPE_SMDE) {
26132662Skarels 			if (lab->d_devflags == 0) {
26232662Skarels 				lab->d_devflags = VD_ESDI;
26332662Skarels 				goto top;
26432662Skarels 			}
26532662Skarels #ifdef notdef
26632662Skarels printf("vdstatus %x\n", addr->vdstatus[cur.drive]);
26732662Skarels 			if ((addr->vdstatus[cur.drive] & STA_US) == 0) {
26832662Skarels 				printf("Drive not present\n\n");
26932662Skarels 				goto bad;
27032662Skarels 			}
27132662Skarels #endif
27232662Skarels 		}
27332662Skarels 		if ((dcb.operrsta & (DCBS_OCYL|DCBS_NRDY)) == 0) {
27432662Skarels 			printf("drive config error\n");
27532662Skarels 			goto bad;
27632662Skarels 		}
27729532Ssam 		if(pass) {
27829532Ssam 			printf("\nDrive failed to start!\n\n");
27932662Skarels 			goto bad;
28029532Ssam 		}
28129981Skarels 		printf("\ndrive not ready, attempting to spin up...");
28232662Skarels 		access_with_no_trailer(VDOP_START, 62);
28332662Skarels 		for (i = 0; i < 620; i++) {
28432662Skarels 			if (C_INFO->type == VDTYPE_SMDE &&
28532662Skarels 			    addr->vdstatus[cur.drive] & STA_UR)
28632662Skarels 				break;
28732662Skarels 			DELAY(100000);
28832662Skarels 		}
28929981Skarels 		printf(" retrying drive configuration\n");
29032662Skarels 		pass++;
29132662Skarels 		lab->d_devflags = 0;
29232662Skarels 		goto top;
29329532Ssam 	}
29432662Skarels 	D_INFO->alive = u_true;
29532662Skarels 	return;
29632662Skarels bad:
29732662Skarels 	D_INFO->alive = u_false;
29832662Skarels 	_longjmp(abort_environ, -1);
29929532Ssam }
30029532Ssam 
30129532Ssam 
30229532Ssam /*
30329532Ssam ** 	data_ok checks an error status word for bit patterns
30429532Ssam **  associated with error conditions from the VDDC controller.  If a hardware
30534557Skarels **  error is present then the problem is reported on the console.
30634557Skarels **  If a data error is present the a zero is returned.
30729532Ssam **  If everything is OK then a 1 is returned.
30829532Ssam */
30929532Ssam 
data_ok()31029532Ssam data_ok()
31129532Ssam {
31229532Ssam 	register int	status = dcb.operrsta;
31329532Ssam 
31429532Ssam 	if(status & HARD_ERROR){
31534557Skarels 		vd_error("data transfer");
31634557Skarels 		printf("  op = 0x%x\n", dcb.opcode);
31729532Ssam 		reset_controller();
31829532Ssam 		dcb.operrsta &= HEADER_ERROR;
31929532Ssam 	}
32029532Ssam 	return (int)(!(status & (DATA_ERROR | HEADER_ERROR)));
32129532Ssam }
32229532Ssam 
vd_error(s)32334557Skarels vd_error(s)
32434557Skarels 	char *s;
32534557Skarels {
32634557Skarels 	register int	status = dcb.operrsta;
32729532Ssam 
328*34667Skarels 	print("%s error at sector %d (cyl %d trk %d sect %d),\n",
329*34667Skarels 	    s, to_sector(cur.daddr), dcb.err_cyl & 0xfff, dcb.err_trk,
33034557Skarels 	    dcb.err_sec);
33134557Skarels 	print("  status=%b", dcb.operrsta, VDERRBITS);
33234557Skarels 	if (C_INFO->type == VDTYPE_SMDE)
33334557Skarels 		printf(", ecode=0x%x", dcb.err_code);
334*34667Skarels 	printf(".\n");
33534557Skarels }
33634557Skarels 
33734557Skarels 
33829532Ssam /*
33929532Ssam **
34029532Ssam */
34129532Ssam 
reset_controller()34229532Ssam reset_controller()
34329532Ssam {
34429532Ssam 	printf("Resetting controller.  Please wait...\n");
34529532Ssam 	spin_up_drive();
34629532Ssam 	printf("Controller was reset successfully.\n");
34729532Ssam }
34829532Ssam 
34929532Ssam /*
35029532Ssam **
35129532Ssam */
35229532Ssam 
35329532Ssam static	int	indent_count;
35429532Ssam 
35529532Ssam 
35629532Ssam /*
35729532Ssam **
35829532Ssam */
35929532Ssam 
indent()36029532Ssam indent()
36129532Ssam {
36229532Ssam 	indent_count += 2;
36329532Ssam }
36429532Ssam 
36529532Ssam 
36629532Ssam /*
36729532Ssam **
36829532Ssam */
36929532Ssam 
exdent(count)37029532Ssam exdent(count)
37129532Ssam int	count;
37229532Ssam {
37329532Ssam 	if(count == -1)
37429532Ssam 		indent_count = 0;
37529532Ssam 	else
37629532Ssam 		indent_count -= count * 2;
37729532Ssam 	if(indent_count < 0)
37829532Ssam 			indent_count = 0;
37929532Ssam }
38029532Ssam 
38129532Ssam 
38229532Ssam /*
38329532Ssam **
38429532Ssam */
38529532Ssam /*VARARGS1*/
print(par0,par1,par2,par3,par4,par5,par6)38629532Ssam print(par0, par1, par2, par3, par4, par5, par6)
38729532Ssam char	*par0, *par1, *par2, *par3, *par4, *par5, *par6;
38829532Ssam {
38929532Ssam 	register int	count = indent_count;
39029532Ssam 
39129532Ssam 	while(count--)
39229532Ssam 		printf(" ");
39329532Ssam 	printf(par0, par1, par2, par3, par4, par5, par6);
39429532Ssam 	DELAY((strlen(par0) + 20) * 9000);
39529532Ssam }
396