xref: /csrg-svn/sys/vax/stand/format.c (revision 25212)
123251Smckusick /*
223251Smckusick  * Copyright (c) 1980 Regents of the University of California.
323251Smckusick  * All rights reserved.  The Berkeley software License Agreement
423251Smckusick  * specifies the terms and conditions for redistribution.
523251Smckusick  */
611367Ssam 
723251Smckusick #ifndef lint
823251Smckusick char copyright[] =
923251Smckusick "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1023251Smckusick  All rights reserved.\n";
1123251Smckusick #endif not lint
1215051Skarels 
1323251Smckusick #ifndef lint
14*25212Skarels static char sccsid[] = "@(#)format.c	6.6 (Berkeley) 10/15/85";
1523251Smckusick #endif not lint
1623251Smckusick 
17*25212Skarels 
1811367Ssam /*
1911367Ssam  * Standalone program to do media checking
2011367Ssam  * and record bad block information on any
2115009Skarels  * disk with the appropriate driver and RM03-style headers.
22*25212Skarels  * TODO:
23*25212Skarels  *	add new bad sectors to bad-sector table when formatting by track
24*25212Skarels  *		(rearranging replacements ala bad144 -a)
25*25212Skarels  *	multi-pass format for disks with skip-sector capability
2611367Ssam  */
2711367Ssam #include "../h/param.h"
2811367Ssam #include "../h/fs.h"
2911367Ssam #include "../h/inode.h"
3011367Ssam #include "../h/dkbad.h"
3111367Ssam #include "../h/vmmac.h"
3211367Ssam 
3311367Ssam #include "saio.h"
3411367Ssam #include "savax.h"
3511367Ssam 
3611367Ssam #define MAXBADDESC	126		/* size of bad block table */
3711367Ssam #define CHUNK		48		/* max # of sectors/io operation */
3811367Ssam #define SECTSIZ		512		/* standard sector size */
3911367Ssam #define HDRSIZ		4		/* number of bytes in sector header */
4011367Ssam 
4111367Ssam #define SSERR		0
4211367Ssam #define BSERR		1
4311367Ssam 
4411367Ssam #define SSDEV		((ioctl(iob[fd-3], SAIOSSDEV, (char *)0) == 0))
4511367Ssam 
4611367Ssam struct sector {
4711367Ssam 	u_short	header1;
4811367Ssam 	u_short header2;
4911367Ssam 	char	buf[SECTSIZ];
5011367Ssam };
5111367Ssam 
5211367Ssam struct	dkbad dkbad;		/* bad sector table */
5311367Ssam struct	dkbad sstab;		/* skip sector table */
5411367Ssam 
5511367Ssam #define	NERRORS		6
5611371Ssam static char *
5711371Ssam errornames[NERRORS] = {
5815009Skarels #define	FE_BSE		0
5915009Skarels 	"Bad sector",
6015009Skarels #define	FE_WCE		1
6111367Ssam 	"Write check",
6211367Ssam #define	FE_ECC		2
6311367Ssam 	"ECC",
6411367Ssam #define	FE_HARD		3
6511367Ssam 	"Other hard",
6611367Ssam #define	FE_TOTAL	4
6711367Ssam 	"Total",
6811367Ssam #define	FE_SSE		5
6911367Ssam 	"Skip sector",
7011367Ssam };
7111367Ssam 
7211367Ssam int	errors[NERRORS];	/* histogram of errors */
7311371Ssam int	pattern;
7411367Ssam 
7515051Skarels /*
7615051Skarels  * Purdue/EE severe burnin patterns.
7715051Skarels  */
7815051Skarels unsigned short ppat[] = {
7917426Skarels 0xf00f, 0xec6d, 0031463,0070707,0133333,0155555,0161616,0143434,
8015051Skarels 0107070,0016161,0034343,0044444,0022222,0111111,0125252, 052525,
8115051Skarels 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252,
8215051Skarels #ifndef	SHORTPASS
8315051Skarels 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252,
8415051Skarels  052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525,
8515051Skarels #endif
8615051Skarels  052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525
8715051Skarels  };
8815051Skarels 
8915051Skarels #define	NPT	(sizeof (ppat) / sizeof (short))
9017426Skarels int	maxpass, npat;	/* subscript to ppat[] */
9115051Skarels int	severe;		/* nz if running "severe" burnin */
92*25212Skarels int	startcyl, endcyl, starttrack, endtrack;
9315051Skarels int	nbads;		/* subscript for bads */
9415051Skarels long	bads[MAXBADDESC]; /* Bad blocks accumulated */
9515051Skarels 
9611367Ssam char	*malloc();
9715051Skarels int	qcompar();
9811367Ssam char	*prompt();
99*25212Skarels daddr_t	badsn();
10011367Ssam extern	int end;
10111367Ssam 
10211367Ssam main()
10311367Ssam {
10411367Ssam 	register int sector, sn;
10515051Skarels 	int lastsector, tracksize, rtracksize;
10611367Ssam 	int unit, fd, resid, i, trk, cyl, debug;
10711367Ssam 	struct st st;
10811367Ssam 	struct sector *bp, *cbp;
10915051Skarels 	char *rbp, *rcbp;
11017426Skarels 	int pass;
11111367Ssam 	char *cp;
11211367Ssam 
11311367Ssam 	printf("Disk format/check utility\n\n");
11411367Ssam 
11511367Ssam again:
11615051Skarels 	nbads = 0;
11715051Skarels 	cp = prompt("Enable debugging (0=none, 1=bse, 2=ecc, 3=bse+ecc)? ");
11811367Ssam 	debug = atoi(cp);
11911367Ssam 	if (debug < 0)
12011367Ssam 		debug = 0;
12111367Ssam 	for (i = 0; i < NERRORS; i++)
12211367Ssam 		errors[i] = 0;
12311367Ssam 	fd = getdevice();
12411367Ssam 	ioctl(fd, SAIODEVDATA, &st);
12511367Ssam 	printf("Device data: #cylinders=%d, #tracks=%d, #sectors=%d\n",
12611367Ssam 	  st.ncyl, st.ntrak, st.nsect);
127*25212Skarels 	getrange(&st);
12811371Ssam 	if (getpattern())
12911367Ssam 		goto again;
13011367Ssam 	printf("Start formatting...make sure the drive is online\n");
13115051Skarels 	if (severe)
13215051Skarels 		ioctl(fd, SAIOSEVRE, (char *) 0);
13311367Ssam 	ioctl(fd, SAIONOBAD, (char *)0);
13411367Ssam 	ioctl(fd, SAIOECCLIM, (char *)0);
13511367Ssam 	ioctl(fd, SAIODEBUG, (char *)debug);
13611367Ssam 	if (SSDEV) {
13715051Skarels 		if (severe) {
13815051Skarels 			printf("Severe burnin doesn't work with RM80 yet\n");
13915051Skarels 			exit(1);
14015051Skarels 		}
14111367Ssam 		ioctl(fd, SAIOSSI, (char *)0);	/* set skip sector inhibit */
14211367Ssam 		st.nsect++;
14311367Ssam 		st.nspc += st.ntrak;
14411367Ssam 	}
14511367Ssam 	tracksize = sizeof (struct sector) * st.nsect;
14615051Skarels 	rtracksize = SECTSIZ * st.nsect;
14711367Ssam 	bp = (struct sector *)malloc(tracksize);
14815051Skarels 	rbp = malloc(rtracksize);
14917426Skarels 	pass = 0;
15017426Skarels 	npat = 0;
15117426Skarels more:
15217426Skarels 	for (; pass < maxpass; pass++) {
15315051Skarels 		if (severe)
15415051Skarels 			printf("Begin pass %d\n", pass);
15515051Skarels 		bufinit(bp, tracksize);
15615051Skarels 		if (severe)
15715051Skarels 			npat++;
15811367Ssam 		/*
15915051Skarels 		 * Begin check, for each track,
16011367Ssam 		 *
16115051Skarels 		 * 1) Write header and test pattern.
16215051Skarels 		 * 2) Read data.  Hardware checks header and data ECC.
16317426Skarels 		 *    Read data (esp on Eagles) is much faster than write check.
16411367Ssam 		 */
165*25212Skarels 		sector = ((startcyl * st.ntrak) + starttrack) * st.nsect;
166*25212Skarels 		lastsector = ((endcyl * st.ntrak) + endtrack) * st.nsect
167*25212Skarels 			+ st.nsect;
168*25212Skarels 		for ( ; sector < lastsector; sector += st.nsect) {
16915051Skarels 			cyl = sector / st.nspc;
17015051Skarels 			trk = (sector % st.nspc) / st.nsect;
17115051Skarels 			for (i = 0; i < st.nsect; i++) {
17215051Skarels 				bp[i].header1 =
17315051Skarels 					(u_short) cyl | HDR1_FMT22 | HDR1_OKSCT;
17415051Skarels 				bp[i].header2 = ((u_short)trk << 8) + i;
17515051Skarels 			}
17615051Skarels 			if (sector && (sector % (st.nspc * 100)) == 0)
17715051Skarels 				printf("cylinder %d\n", cyl);
17815051Skarels 			/*
17915051Skarels 			 * Try and write the headers and data patterns into
18015051Skarels 			 * each sector in the track.  Continue until such
18115051Skarels 			 * we're done, or until there's less than a sector's
18215051Skarels 			 * worth of data to transfer.
18315051Skarels 			 *
18415051Skarels 			 * The lseek call is necessary because of
18515051Skarels 			 * the odd sector size (516 bytes)
18615051Skarels 			 */
18715051Skarels 			for (resid = tracksize, cbp = bp, sn = sector;;) {
18815051Skarels 				int cc;
18911367Ssam 
19015051Skarels 				lseek(fd, sn * SECTSIZ, 0);
19115051Skarels 				ioctl(fd, SAIOHDR, (char *)0);
19215051Skarels 				cc = write(fd, cbp, resid);
19315051Skarels 				if (cc == resid)
19415051Skarels 					break;
19515051Skarels 				/*
19615051Skarels 				 * Don't record errors during write,
19715051Skarels 				 * all errors will be found during
19815051Skarels 				 * writecheck performed below.
19915051Skarels 				 */
20015051Skarels 				sn = iob[fd - 3].i_errblk;
20115051Skarels 				cbp += sn - sector;
20215051Skarels 				resid -= (sn - sector) * sizeof (struct sector);
20315051Skarels 				if (resid < sizeof (struct sector))
20415051Skarels 					break;
20515051Skarels 			}
20611367Ssam 			/*
20715051Skarels 			 * Read test patterns.
20815051Skarels 			 * Retry remainder of track on error until
20915051Skarels 			 * we're done, or until there's less than a
21015051Skarels 			 * sector to verify.
21111367Ssam 			 */
21215051Skarels 			for (resid = rtracksize, rcbp = rbp, sn = sector;;) {
21315051Skarels 				int cc;
21411367Ssam 
21515051Skarels 				lseek(fd, sn * SECTSIZ, 0);
21615051Skarels 				cc = read(fd, rcbp, resid);
21715051Skarels 				if (cc == resid)
21815051Skarels 					break;
21915051Skarels 				sn = iob[fd-3].i_errblk;
22015051Skarels 				printf("sector %d, read error\n", sn);
22115051Skarels 				if (recorderror(fd, sn, &st) < 0 && pass > 0)
22215051Skarels 					goto out;
22315051Skarels 				/* advance past bad sector */
22415051Skarels 				sn++;
22515051Skarels 				rcbp += sn - sector;
22615051Skarels 				resid -= ((sn - sector) * SECTSIZ);
22715051Skarels 				if (resid < SECTSIZ)
22815051Skarels 					break;
22915051Skarels 			}
23011367Ssam 		}
23111367Ssam 	}
23211367Ssam 	/*
23311367Ssam 	 * Checking finished.
23411367Ssam 	 */
23515051Skarels out:
23617426Skarels 	if (errors[FE_TOTAL] || errors[FE_SSE]) {
23717426Skarels 		printf("Errors:\n");
23817426Skarels 		for (i = 0; i < NERRORS; i++)
23917426Skarels 			printf("%s: %d\n", errornames[i], errors[i]);
240*25212Skarels 		printf("Total of %d hard errors revectored\n",
24117426Skarels 			errors[FE_TOTAL] + errors[FE_SSE]);
24217426Skarels 	}
24317426Skarels 	if (severe && maxpass < NPT) {
24417426Skarels 		cp = prompt("More passes? (0 or number) ");
24517426Skarels 		maxpass = atoi(cp);
24617426Skarels 		if (maxpass > 0) {
24717426Skarels 			maxpass += pass;
24817426Skarels 			goto more;
24917426Skarels 		}
25017426Skarels 	}
25115051Skarels 	if (severe && nbads) {
25215051Skarels 		/*
25315051Skarels 		 * Sort bads and insert in bad block table.
25415051Skarels 		 */
25515051Skarels 		qsort(bads, nbads, sizeof (long), qcompar);
25615051Skarels 		severe = 0;
25717426Skarels 		errno = 0;
25817426Skarels 		for (i = 0; i < nbads; i++)
25915051Skarels 			recorderror(fd, bads[i], &st);
26015051Skarels 		severe++;
26115051Skarels 	}
26211367Ssam 	if (errors[FE_TOTAL] || errors[FE_SSE]) {
26311367Ssam 		/* change the headers of all the bad sectors */
26411367Ssam 		writebb(fd, errors[FE_SSE], &sstab, &st, SSERR);
26511367Ssam 		writebb(fd, errors[FE_TOTAL], &dkbad, &st, BSERR);
26611367Ssam 	}
267*25212Skarels 	if (endcyl == st.ncyl - 1 &&
268*25212Skarels 	    (startcyl < st.ncyl - 1 || starttrack == 0)) {
269*25212Skarels 		while (errors[FE_TOTAL] < MAXBADDESC) {
270*25212Skarels 			int i = errors[FE_TOTAL]++;
27111367Ssam 
272*25212Skarels 			dkbad.bt_bad[i].bt_cyl = -1;
273*25212Skarels 			dkbad.bt_bad[i].bt_trksec = -1;
274*25212Skarels 		}
275*25212Skarels 		printf("\nWriting bad sector table at sector #%d\n",
276*25212Skarels 			st.ncyl * st.nspc - st.nsect);
277*25212Skarels 		/* place on disk */
278*25212Skarels 		for (i = 0; i < 10 && i < st.nsect; i += 2) {
279*25212Skarels 			lseek(fd, SECTSIZ * (st.ncyl * st.nspc - st.nsect + i), 0);
280*25212Skarels 			write(fd, &dkbad, sizeof (dkbad));
281*25212Skarels 		}
282*25212Skarels 	} else if (errors[FE_TOTAL]) {
283*25212Skarels 		struct bt_bad *bt;
284*25212Skarels 
285*25212Skarels 		printf("New bad sectors (not added to table):\n");
286*25212Skarels 		bt = dkbad.bt_bad;
287*25212Skarels 		for (i = 0; i < errors[FE_TOTAL]; i++) {
288*25212Skarels 			printf("sn %d (cn=%d, tn=%d, sn=%d)\n", badsn(bt, st),
289*25212Skarels 			    bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff);
290*25212Skarels 			bt++;
291*25212Skarels 		}
29211367Ssam 	}
29311367Ssam 	printf("Done\n");
29411367Ssam 	ioctl(fd,SAIONOSSI,(char *)0);
29511367Ssam 	close(fd);
29611367Ssam #ifndef JUSTEXIT
29711367Ssam 	goto again;
29811367Ssam #endif
29911367Ssam }
30011367Ssam 
30115051Skarels qcompar(l1, l2)
30215051Skarels register long *l1, *l2;
30315051Skarels {
30415051Skarels 	if (*l1 < *l2)
30515051Skarels 		return(-1);
30615051Skarels 	if (*l1 == *l2)
30715051Skarels 		return(0);
30815051Skarels 	return(1);
30915051Skarels }
31015051Skarels 
311*25212Skarels daddr_t
312*25212Skarels badsn(bt, st)
313*25212Skarels 	register struct bt_bad *bt;
314*25212Skarels 	register struct st *st;
315*25212Skarels {
316*25212Skarels 	return ((bt->bt_cyl*st->ntrak + (bt->bt_trksec>>8)) * st->nsect
317*25212Skarels 		+ (bt->bt_trksec&0xff));
318*25212Skarels }
319*25212Skarels 
32011367Ssam /*
321*25212Skarels  * Mark the bad/skipped sectors.
322*25212Skarels  * Bad sectors on skip-sector devices are assumed to be skipped also.
32311367Ssam  */
32411367Ssam writebb(fd, nsects, dbad, st, sw)
32511367Ssam 	int nsects, fd;
32611367Ssam 	struct dkbad *dbad;
32711367Ssam 	register struct st *st;
32811367Ssam {
32911367Ssam 	struct sector bb_buf; /* buffer for one sector plus 4 byte header */
33011367Ssam 	register int i;
33111367Ssam 	int bn, j;
33211367Ssam 	struct bt_bad *btp;
33311367Ssam 
33411367Ssam 	for (i = 0; i < nsects; i++) {
33511367Ssam 		btp = &dbad->bt_bad[i];
33611367Ssam 		if (sw == BSERR) {
33711367Ssam 			bb_buf.header1 = HDR1_FMT22|btp->bt_cyl;
33811367Ssam 			if (SSDEV)
33911367Ssam 				bb_buf.header1 |= HDR1_SSF;
34011367Ssam 		} else
34111367Ssam 			bb_buf.header1 =
34211367Ssam 			       btp->bt_cyl | HDR1_FMT22 | HDR1_SSF | HDR1_OKSCT;
34311367Ssam 		bb_buf.header2 = btp->bt_trksec;
34411367Ssam 		bn = st->nspc * btp->bt_cyl +
34511367Ssam 		     st->nsect * (btp->bt_trksec >> 8) +
34615009Skarels 		     (btp->bt_trksec & 0xff);
34711367Ssam 		lseek(fd, bn * SECTSIZ, 0);
34811367Ssam 		ioctl(fd, SAIOHDR, (char *)0);
34911367Ssam 		write(fd, &bb_buf, sizeof (bb_buf));
35011367Ssam 		if (!SSDEV)
35111367Ssam 			continue;
35211367Ssam 		/*
35311367Ssam 		 * If skip sector, mark all remaining
35411367Ssam 		 * sectors on the track.
35511367Ssam 		 */
356*25212Skarels 		for (j = (btp->bt_trksec & 0xff) + 1, bn++;
357*25212Skarels 		    j <= st->nsect; j++, bn++) {
358*25212Skarels 			bb_buf.header2 = j | (btp->bt_trksec & 0xff00);
359*25212Skarels 			lseek(fd, bn * SECTSIZ, 0);
36011367Ssam 			ioctl(fd, SAIOHDR, (char *)0);
36111367Ssam 			write(fd, &bb_buf, sizeof (bb_buf));
36211367Ssam 		}
36311367Ssam 	}
36411367Ssam }
36511367Ssam 
36611367Ssam /*
36711367Ssam  * Record an error, and if there's room, put
36811367Ssam  * it in the appropriate bad sector table.
36915051Skarels  *
37015051Skarels  * If severe burnin store block in a list after making sure
37115051Skarels  * we have not already found it on a prev pass.
37211367Ssam  */
37311367Ssam recorderror(fd, bn, st)
37411367Ssam 	int fd, bn;
37511367Ssam 	register struct st *st;
37611367Ssam {
377*25212Skarels 	int cn, tn, sn;
37815051Skarels 	register i;
37911367Ssam 
38015051Skarels 
38115051Skarels 	if (severe) {
38215051Skarels 		for (i = 0; i < nbads; i++)
38315051Skarels 			if (bads[i] == bn)
38415051Skarels 				return(0);	/* bn already flagged */
38515051Skarels 		if (nbads >= MAXBADDESC) {
386*25212Skarels 			printf("Bad sector table full, format terminating\n");
38715051Skarels 			return(-1);
38815051Skarels 		}
38915051Skarels 		bads[nbads++] = bn;
39017426Skarels 		if (errno < EBSE || errno > EHER)
39117426Skarels 			return(0);
39217426Skarels 		errno -= EBSE;
39317426Skarels 		errors[errno]++;
39415051Skarels 		return(0);
39515051Skarels 	}
39617426Skarels 	if (errno >= EBSE && errno <= EHER) {
39717426Skarels 		errno -= EBSE;
39817426Skarels 		errors[errno]++;
39911367Ssam 	}
40011367Ssam 	cn = bn / st->nspc;
40111367Ssam 	sn = bn % st->nspc;
40211367Ssam 	tn = sn / st->nsect;
40311367Ssam 	sn %= st->nsect;
40411367Ssam 	if (SSDEV) {		/* if drive has skip sector capability */
405*25212Skarels 		int ss = errors[FE_SSE];
40611367Ssam 
407*25212Skarels 		if (errors[FE_SSE] >= MAXBADDESC) {
408*25212Skarels 			/* this is bogus, we don't maintain skip sector table */
409*25212Skarels 			printf("Too many skip sector errors\n");
410*25212Skarels 			return(-1);
411*25212Skarels 		}
412*25212Skarels 		  /* only one skip sector/track */
413*25212Skarels 		if (ss == 0 ||
414*25212Skarels 		    tn != (sstab.bt_bad[ss - 1].bt_trksec >> 8) ||
415*25212Skarels 		    cn != sstab.bt_bad[ss - 1].bt_cyl) {
41611367Ssam 			sstab.bt_bad[ss].bt_cyl = cn;
41711367Ssam 			sstab.bt_bad[ss].bt_trksec = (tn<<8) + sn;
418*25212Skarels 			errors[FE_SSE]++;
419*25212Skarels 			return(0);
42011367Ssam 		}
42111367Ssam 	}
422*25212Skarels 	if (errors[FE_TOTAL] >= MAXBADDESC) {
423*25212Skarels 		printf("Too many bad sectors\n");
424*25212Skarels 		return(-1);
425*25212Skarels 	}
42611367Ssam 	/* record the bad sector address and continue */
42715009Skarels 	dkbad.bt_bad[errors[FE_TOTAL]].bt_cyl = cn;
42811367Ssam 	dkbad.bt_bad[errors[FE_TOTAL]++].bt_trksec = (tn << 8) + sn;
42915051Skarels 	return(0);
43011367Ssam }
43111367Ssam 
43211367Ssam /*
43311367Ssam  * Allocate memory on a page-aligned address.
43411367Ssam  * Round allocated chunk to a page multiple to
43511367Ssam  * ease next request.
43611367Ssam  */
43711367Ssam char *
43811367Ssam malloc(size)
43911367Ssam 	int size;
44011367Ssam {
44111367Ssam 	char *result;
44211367Ssam 	static caddr_t last = 0;
44311367Ssam 
44411367Ssam 	if (last == 0)
44511367Ssam 		last = (caddr_t)(((int)&end + 511) & ~0x1ff);
44611367Ssam 	size = (size + 511) & ~0x1ff;
44711367Ssam 	result = (char *)last;
44811367Ssam 	last += size;
44911367Ssam 	return (result);
45011367Ssam }
45111367Ssam 
45211367Ssam /*
45311367Ssam  * Prompt and verify a device name from the user.
45411367Ssam  */
45511367Ssam getdevice()
45611367Ssam {
45711367Ssam 	register char *cp;
45811367Ssam 	register struct devsw *dp;
45911367Ssam 	int fd;
46011367Ssam 
46111367Ssam top:
46211367Ssam 	cp = prompt("Device to format? ");
46311367Ssam 	if ((fd = open(cp, 2)) < 0) {
46411367Ssam 		printf("Known devices are: ");
46511367Ssam 		for (dp = devsw; dp->dv_name; dp++)
46611367Ssam 			printf("%s ",dp->dv_name);
46711367Ssam 		printf("\n");
46811367Ssam 		goto top;
46911367Ssam 	}
47015051Skarels 	printf("Formatting drive %c%c%d on adaptor %d: ",
47115051Skarels 		cp[0], cp[1], iob[fd - 3].i_unit % 8, iob[fd - 3].i_unit / 8);
47211367Ssam 	cp = prompt("verify (yes/no)? ");
47311367Ssam 	while (*cp != 'y' && *cp != 'n')
47411367Ssam 		cp = prompt("Huh, yes or no? ");
47511367Ssam 	if (*cp == 'y')
47611367Ssam 		return (fd);
47711367Ssam 	goto top;
47811367Ssam }
47911367Ssam 
480*25212Skarels /*
481*25212Skarels  * Find range of tracks to format.
482*25212Skarels  */
483*25212Skarels getrange(st)
484*25212Skarels 	struct st *st;
485*25212Skarels {
486*25212Skarels 	startcyl = getnum("Starting cylinder", 0, st->ncyl - 1, 0);
487*25212Skarels 	endcyl = getnum("Ending cylinder", 0, st->ncyl - 1, st->ncyl - 1);
488*25212Skarels 	starttrack = getnum("Starting track", 0, st->ntrak - 1, 0);
489*25212Skarels 	endtrack = getnum("Ending track", 0, st->ntrak - 1, st->ntrak - 1);
490*25212Skarels }
491*25212Skarels 
492*25212Skarels getnum(s, low, high, dflt)
493*25212Skarels {
494*25212Skarels 	char buf[132];
495*25212Skarels 	unsigned val;
496*25212Skarels 
497*25212Skarels 	while (1) {
498*25212Skarels 		printf("%s (%d): ", s, dflt);
499*25212Skarels 		gets(buf);
500*25212Skarels 		if (buf[0] == 0)
501*25212Skarels 			return (dflt);
502*25212Skarels 		val = atoi(buf);
503*25212Skarels 		if (val >= low && val <= high)
504*25212Skarels 			return ((int)val);
505*25212Skarels 		printf("Value must be in range [%d,%d]\n", low, high);
506*25212Skarels 	}
507*25212Skarels }
508*25212Skarels 
50911371Ssam static struct pattern {
51011371Ssam 	long	pa_value;
51111371Ssam 	char	*pa_name;
51211371Ssam } pat[] = {
51311371Ssam 	{ 0xf00ff00f, 	"RH750 worst case" },
51411371Ssam 	{ 0xec6dec6d,	"media worst case" },
51511371Ssam 	{ 0xa5a5a5a5,	"alternate 1's and 0's" },
51617426Skarels 	{ 0xFFFFFFFF,	"Severe burnin (up to 48 passes)" },
51711371Ssam 	{ 0, 0 },
51811371Ssam };
51911371Ssam 
52011371Ssam getpattern()
52111371Ssam {
52211371Ssam 	register struct pattern *p;
52311371Ssam 	int npatterns;
52411371Ssam 	char *cp;
52511371Ssam 
52611371Ssam 	printf("Available test patterns are:\n");
52711371Ssam 	for (p = pat; p->pa_value; p++)
52811371Ssam 		printf("\t%d - (%x) %s\n", (p - pat) + 1,
52911371Ssam 		  p->pa_value & 0xffff, p->pa_name);
53011371Ssam 	npatterns = p - pat;
53111371Ssam 	cp = prompt("Pattern (one of the above, other to restart)? ");
53211371Ssam 	pattern = atoi(cp) - 1;
53317426Skarels 	if (pattern < 0 || pattern >= npatterns)
53417426Skarels 		return(1);
53515051Skarels 	severe = 0;
53617426Skarels 	maxpass = 1;
53717426Skarels 	if (pat[pattern].pa_value == -1) {
53815051Skarels 		severe = 1;
53917426Skarels 		cp = prompt("How many passes (up to 48)? ");
54017426Skarels 		maxpass = atoi(cp);
54117426Skarels 		if (maxpass > NPT)
54217426Skarels 			maxpass = NPT;
54317426Skarels 	}
54417426Skarels 	return (0);
54511371Ssam }
54611371Ssam 
54711371Ssam struct xsect {
54811371Ssam 	u_short	hd1;
54911371Ssam 	u_short	hd2;
55011371Ssam 	long	buf[128];
55111371Ssam };
55211371Ssam 
55311371Ssam /*
55411371Ssam  * Initialize the buffer with the requested pattern.
55511371Ssam  */
55611371Ssam bufinit(bp, size)
55711371Ssam 	register struct xsect *bp;
55811371Ssam 	int size;
55911371Ssam {
56011371Ssam 	register struct pattern *pptr;
56111371Ssam 	register long *pp, *last;
56211371Ssam 	register struct xsect *lastbuf;
56315051Skarels 	int patt;
56411371Ssam 
56511371Ssam 	size /= sizeof (struct sector);
56611371Ssam 	lastbuf = bp + size;
56715051Skarels 	if (severe) {
56815051Skarels 		patt = ppat[npat] | ((long)ppat[npat] << 16);
56915051Skarels 		printf("Write pattern 0x%x\n", patt&0xffff);
57015051Skarels 	} else {
57115051Skarels 		pptr = &pat[pattern];
57215051Skarels 		patt = pptr->pa_value;
57315051Skarels 	}
57411371Ssam 	while (bp < lastbuf) {
57511371Ssam 		last = &bp->buf[128];
57611371Ssam 		for (pp = bp->buf; pp < last; pp++)
57715051Skarels 			*pp = patt;
57811371Ssam 		bp++;
57911371Ssam 	}
58011371Ssam }
58111371Ssam 
58211367Ssam char *
58311367Ssam prompt(msg)
58411367Ssam 	char *msg;
58511367Ssam {
58611367Ssam 	static char buf[132];
58711367Ssam 
58811367Ssam 	printf("%s", msg);
58911367Ssam 	gets(buf);
59011367Ssam 	return (buf);
59111367Ssam }
592