xref: /csrg-svn/sys/vax/stand/format.c (revision 45803)
123251Smckusick /*
229297Smckusick  * Copyright (c) 1980, 1986 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[] =
929297Smckusick "@(#) Copyright (c) 1980, 1986 Regents of the University of California.\n\
1023251Smckusick  All rights reserved.\n";
1133648Sbostic #endif /* not lint */
1215051Skarels 
1323251Smckusick #ifndef lint
14*45803Sbostic static char sccsid[] = "@(#)format.c	7.6 (Berkeley) 12/16/90";
1533648Sbostic #endif /* not lint */
1623251Smckusick 
1711367Ssam /*
1811367Ssam  * Standalone program to do media checking
1911367Ssam  * and record bad block information on any
2015009Skarels  * disk with the appropriate driver and RM03-style headers.
2125212Skarels  * TODO:
2225212Skarels  *	add new bad sectors to bad-sector table when formatting by track
2325212Skarels  *		(rearranging replacements ala bad144 -a)
2425212Skarels  *	multi-pass format for disks with skip-sector capability
2511367Ssam  */
26*45803Sbostic #include "sys/param.h"
27*45803Sbostic #include "sys/dkbad.h"
28*45803Sbostic #include "sys/vmmac.h"
29*45803Sbostic #include "sys/disklabel.h"
3011367Ssam 
31*45803Sbostic #include "../include/cpu.h"
32*45803Sbostic #include "../include/mtpr.h"
3333648Sbostic 
34*45803Sbostic #include "stand/saio.h"
3511367Ssam #include "savax.h"
3611367Ssam 
3711367Ssam #define MAXBADDESC	126		/* size of bad block table */
3811367Ssam #define CHUNK		48		/* max # of sectors/io operation */
3911367Ssam #define SECTSIZ		512		/* standard sector size */
4011367Ssam #define HDRSIZ		4		/* number of bytes in sector header */
4111367Ssam 
4211367Ssam #define SSERR		0
4311367Ssam #define BSERR		1
4411367Ssam 
4525438Skarels #define SSDEV(fd)	(ioctl((fd), SAIOSSDEV, (char *)0) == 0)
4625438Skarels #define MAXECCBITS	3
4711367Ssam 
4811367Ssam struct sector {
4911367Ssam 	u_short	header1;
5011367Ssam 	u_short header2;
5111367Ssam 	char	buf[SECTSIZ];
5211367Ssam };
5311367Ssam 
5411367Ssam struct	dkbad dkbad;		/* bad sector table */
5525438Skarels struct	dkbad oldbad;		/* old bad sector table */
5611367Ssam struct	dkbad sstab;		/* skip sector table */
5711367Ssam 
5811367Ssam #define	NERRORS		6
5911371Ssam static char *
6011371Ssam errornames[NERRORS] = {
6115009Skarels #define	FE_BSE		0
6215009Skarels 	"Bad sector",
6315009Skarels #define	FE_WCE		1
6411367Ssam 	"Write check",
6511367Ssam #define	FE_ECC		2
6625438Skarels 	"Hard ECC",
6711367Ssam #define	FE_HARD		3
6811367Ssam 	"Other hard",
6911367Ssam #define	FE_TOTAL	4
7025438Skarels 	"Marked bad",
7111367Ssam #define	FE_SSE		5
7225438Skarels 	"Skipped",
7311367Ssam };
7411367Ssam 
7511367Ssam int	errors[NERRORS];	/* histogram of errors */
7611371Ssam int	pattern;
7725438Skarels int	maxeccbits;
7811367Ssam 
7915051Skarels /*
8015051Skarels  * Purdue/EE severe burnin patterns.
8115051Skarels  */
8215051Skarels unsigned short ppat[] = {
8317426Skarels 0xf00f, 0xec6d, 0031463,0070707,0133333,0155555,0161616,0143434,
8415051Skarels 0107070,0016161,0034343,0044444,0022222,0111111,0125252, 052525,
8515051Skarels 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252,
8615051Skarels #ifndef	SHORTPASS
8715051Skarels 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252,
8815051Skarels  052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525,
8915051Skarels #endif
9015051Skarels  052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525
9115051Skarels  };
9215051Skarels 
9315051Skarels #define	NPT	(sizeof (ppat) / sizeof (short))
9417426Skarels int	maxpass, npat;	/* subscript to ppat[] */
9515051Skarels int	severe;		/* nz if running "severe" burnin */
9625438Skarels int	ssdev;			/* device supports skip sectors */
9725212Skarels int	startcyl, endcyl, starttrack, endtrack;
9825438Skarels int	nbads;			/* subscript for bads */
9925438Skarels daddr_t	bads[2*MAXBADDESC]; 	/* Bad blocks accumulated */
10015051Skarels 
10111367Ssam char	*malloc();
10215051Skarels int	qcompar();
10311367Ssam char	*prompt();
10425212Skarels daddr_t	badsn();
10511367Ssam extern	int end;
10611367Ssam 
main()10711367Ssam main()
10811367Ssam {
10933648Sbostic 	register struct sector *hdr;
11033648Sbostic 	register int sector, sn, i;
11133648Sbostic 	struct disklabel dl;
11233648Sbostic 	struct sector *bp, *cbp;
11315051Skarels 	int lastsector, tracksize, rtracksize;
11433648Sbostic 	int unit, fd, resid, trk, cyl, debug, pass;
11533648Sbostic 	char *cp, *rbp, *rcbp;
11611367Ssam 
11711367Ssam 	printf("Disk format/check utility\n\n");
11811367Ssam 
11933648Sbostic 	/* enable the cache, as every little bit helps */
12033648Sbostic 	switch (cpu) {
12133648Sbostic 	case VAX_8600:
12233648Sbostic 		mtpr(CSWP, 3);
12333648Sbostic 		break;
12433648Sbostic 	case VAX_8200:
12533648Sbostic 	case VAX_750:
12633648Sbostic 		mtpr(CADR, 0);
12733648Sbostic 		break;
12833648Sbostic 	case VAX_780:
12933648Sbostic 		mtpr(SBIMT, 0x200000);
13033648Sbostic 		break;
13133648Sbostic 	}
13233648Sbostic 
13311367Ssam again:
13415051Skarels 	nbads = 0;
13515051Skarels 	cp = prompt("Enable debugging (0=none, 1=bse, 2=ecc, 3=bse+ecc)? ");
13611367Ssam 	debug = atoi(cp);
13711367Ssam 	if (debug < 0)
13811367Ssam 		debug = 0;
13911367Ssam 	for (i = 0; i < NERRORS; i++)
14011367Ssam 		errors[i] = 0;
14111367Ssam 	fd = getdevice();
14233648Sbostic 	ioctl(fd, SAIODEVDATA, &dl);
14311367Ssam 	printf("Device data: #cylinders=%d, #tracks=%d, #sectors=%d\n",
14433648Sbostic 	    dl.d_ncylinders, dl.d_ntracks, dl.d_nsectors);
14525438Skarels 	ssdev = SSDEV(fd);
14625438Skarels 	if (ssdev) {
14725438Skarels 		ioctl(fd, SAIOSSI, (char *)0);	/* set skip sector inhibit */
14833648Sbostic 		dl.d_nsectors++;
14933648Sbostic 		dl.d_secpercyl += dl.d_ntracks;
15025438Skarels 		printf("(not counting skip-sector replacement)\n");
15125438Skarels 	}
15233648Sbostic 	getrange(&dl);
15311371Ssam 	if (getpattern())
15411367Ssam 		goto again;
15511367Ssam 	printf("Start formatting...make sure the drive is online\n");
15611367Ssam 	ioctl(fd, SAIONOBAD, (char *)0);
15725438Skarels 	ioctl(fd, SAIORETRIES, (char *)0);
15825438Skarels 	ioctl(fd, SAIOECCLIM, (char *)maxeccbits);
15911367Ssam 	ioctl(fd, SAIODEBUG, (char *)debug);
16033648Sbostic 	tracksize = sizeof (struct sector) * dl.d_nsectors;
16133648Sbostic 	rtracksize = SECTSIZ * dl.d_nsectors;
16211367Ssam 	bp = (struct sector *)malloc(tracksize);
16315051Skarels 	rbp = malloc(rtracksize);
16417426Skarels 	pass = 0;
16517426Skarels 	npat = 0;
16617426Skarels more:
16717426Skarels 	for (; pass < maxpass; pass++) {
16815051Skarels 		if (severe)
16915051Skarels 			printf("Begin pass %d\n", pass);
17015051Skarels 		bufinit(bp, tracksize);
17115051Skarels 		if (severe)
17215051Skarels 			npat++;
17311367Ssam 		/*
17415051Skarels 		 * Begin check, for each track,
17511367Ssam 		 *
17615051Skarels 		 * 1) Write header and test pattern.
17715051Skarels 		 * 2) Read data.  Hardware checks header and data ECC.
17817426Skarels 		 *    Read data (esp on Eagles) is much faster than write check.
17911367Ssam 		 */
18033648Sbostic 		sector = ((startcyl * dl.d_ntracks) + starttrack) *
18133648Sbostic 			dl.d_nsectors;
18233648Sbostic 		lastsector = ((endcyl * dl.d_ntracks) + endtrack) *
18333648Sbostic 			dl.d_nsectors + dl.d_nsectors;
18433648Sbostic 		for ( ; sector < lastsector; sector += dl.d_nsectors) {
18533648Sbostic 			cyl = sector / dl.d_secpercyl;
18633648Sbostic 			trk = ((sector % dl.d_secpercyl) / dl.d_nsectors) << 8;
18733648Sbostic 			for (i = 0, hdr = bp; i < dl.d_nsectors; i++, hdr++) {
18833648Sbostic 				hdr->header1 = cyl | HDR1_FMT22 | HDR1_OKSCT;
18933648Sbostic 				hdr->header2 = trk + i;
19015051Skarels 			}
19133648Sbostic 			if (sector && (sector % (dl.d_secpercyl * 50)) == 0)
19215051Skarels 				printf("cylinder %d\n", cyl);
19315051Skarels 			/*
19415051Skarels 			 * Try and write the headers and data patterns into
19515051Skarels 			 * each sector in the track.  Continue until such
19615051Skarels 			 * we're done, or until there's less than a sector's
19715051Skarels 			 * worth of data to transfer.
19815051Skarels 			 *
19915051Skarels 			 * The lseek call is necessary because of
20015051Skarels 			 * the odd sector size (516 bytes)
20115051Skarels 			 */
20215051Skarels 			for (resid = tracksize, cbp = bp, sn = sector;;) {
20333648Sbostic 				register int cc;
20411367Ssam 
20533553Skarels 				lseek(fd, sn * SECTSIZ, L_SET);
20615051Skarels 				ioctl(fd, SAIOHDR, (char *)0);
20715051Skarels 				cc = write(fd, cbp, resid);
20815051Skarels 				if (cc == resid)
20915051Skarels 					break;
21015051Skarels 				/*
21115051Skarels 				 * Don't record errors during write,
21215051Skarels 				 * all errors will be found during
21325438Skarels 				 * check performed below.
21415051Skarels 				 */
21515051Skarels 				sn = iob[fd - 3].i_errblk;
21615051Skarels 				cbp += sn - sector;
21715051Skarels 				resid -= (sn - sector) * sizeof (struct sector);
21815051Skarels 				if (resid < sizeof (struct sector))
21915051Skarels 					break;
22015051Skarels 			}
22111367Ssam 			/*
22215051Skarels 			 * Read test patterns.
22315051Skarels 			 * Retry remainder of track on error until
22415051Skarels 			 * we're done, or until there's less than a
22515051Skarels 			 * sector to verify.
22611367Ssam 			 */
22715051Skarels 			for (resid = rtracksize, rcbp = rbp, sn = sector;;) {
22833648Sbostic 				register int cc, rsn;
22911367Ssam 
23033553Skarels 				lseek(fd, sn * SECTSIZ, L_SET);
23115051Skarels 				cc = read(fd, rcbp, resid);
23215051Skarels 				if (cc == resid)
23315051Skarels 					break;
23415051Skarels 				sn = iob[fd-3].i_errblk;
23525438Skarels 				if (ssdev) {
23633648Sbostic 					rsn = sn - (sn / dl.d_nsectors);
23725438Skarels 					printf("data ");
23825438Skarels 				} else
23925438Skarels 					rsn = sn;
24025438Skarels 				printf("sector %d, read error\n\n", rsn);
24133648Sbostic 				if (recorderror(fd, sn, &dl) < 0 && pass > 0)
24215051Skarels 					goto out;
24315051Skarels 				/* advance past bad sector */
24415051Skarels 				sn++;
24525438Skarels 				resid = rtracksize - ((sn - sector) * SECTSIZ);
24625438Skarels 				rcbp = rbp + ((sn - sector) * SECTSIZ);
24715051Skarels 				if (resid < SECTSIZ)
24815051Skarels 					break;
24915051Skarels 			}
25011367Ssam 		}
25111367Ssam 	}
25211367Ssam 	/*
25311367Ssam 	 * Checking finished.
25411367Ssam 	 */
25515051Skarels out:
25617426Skarels 	if (severe && maxpass < NPT) {
25717426Skarels 		cp = prompt("More passes? (0 or number) ");
25817426Skarels 		maxpass = atoi(cp);
25917426Skarels 		if (maxpass > 0) {
26017426Skarels 			maxpass += pass;
26117426Skarels 			goto more;
26217426Skarels 		}
26317426Skarels 	}
26415051Skarels 	if (severe && nbads) {
26515051Skarels 		/*
26615051Skarels 		 * Sort bads and insert in bad block table.
26715051Skarels 		 */
26825438Skarels 		qsort(bads, nbads, sizeof (daddr_t), qcompar);
26915051Skarels 		severe = 0;
27017426Skarels 		errno = 0;
27117426Skarels 		for (i = 0; i < nbads; i++)
27233648Sbostic 			recorderror(fd, bads[i], &dl);
27315051Skarels 		severe++;
27415051Skarels 	}
27511367Ssam 	if (errors[FE_TOTAL] || errors[FE_SSE]) {
27611367Ssam 		/* change the headers of all the bad sectors */
27733648Sbostic 		writebb(fd, errors[FE_SSE], &sstab, &dl, SSERR);
27833648Sbostic 		writebb(fd, errors[FE_TOTAL], &dkbad, &dl, BSERR);
27911367Ssam 	}
28025438Skarels 	if (errors[FE_TOTAL] || errors[FE_SSE]) {
28125438Skarels 		printf("Errors:\n");
28225438Skarels 		for (i = 0; i < NERRORS; i++)
28325438Skarels 			printf("%s: %d\n", errornames[i], errors[i]);
28425438Skarels 		printf("Total of %d hard errors revectored\n",
28525438Skarels 			errors[FE_TOTAL] + errors[FE_SSE]);
28625438Skarels 	}
28733648Sbostic 	if (endcyl == dl.d_ncylinders - 1 &&
28833648Sbostic 	    (startcyl < dl.d_ncylinders - 1 || starttrack == 0)) {
28925212Skarels 		while (errors[FE_TOTAL] < MAXBADDESC) {
29025212Skarels 			int i = errors[FE_TOTAL]++;
29111367Ssam 
29225212Skarels 			dkbad.bt_bad[i].bt_cyl = -1;
29325212Skarels 			dkbad.bt_bad[i].bt_trksec = -1;
29425212Skarels 		}
29525212Skarels 		printf("\nWriting bad sector table at sector #%d\n",
29633648Sbostic 			dl.d_ncylinders * dl.d_secpercyl - dl.d_nsectors);
29725212Skarels 		/* place on disk */
29833648Sbostic 		for (i = 0; i < 10 && i < dl.d_nsectors; i += 2) {
29933648Sbostic 			lseek(fd, SECTSIZ * (dl.d_ncylinders *
30033648Sbostic 				dl.d_secpercyl - dl.d_nsectors + i), 0);
30125212Skarels 			write(fd, &dkbad, sizeof (dkbad));
30225212Skarels 		}
30325212Skarels 	} else if (errors[FE_TOTAL]) {
30425212Skarels 		struct bt_bad *bt;
30525212Skarels 
30625212Skarels 		printf("New bad sectors (not added to table):\n");
30725212Skarels 		bt = dkbad.bt_bad;
30825212Skarels 		for (i = 0; i < errors[FE_TOTAL]; i++) {
30933648Sbostic 			printf("bn %d (cn=%d, tn=%d, sn=%d)\n", badsn(bt, &dl),
31025212Skarels 			    bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff);
31125212Skarels 			bt++;
31225212Skarels 		}
31311367Ssam 	}
31411367Ssam 	printf("Done\n");
31511367Ssam 	ioctl(fd,SAIONOSSI,(char *)0);
31611367Ssam 	close(fd);
31711367Ssam #ifndef JUSTEXIT
31811367Ssam 	goto again;
31911367Ssam #endif
32011367Ssam }
32111367Ssam 
qcompar(l1,l2)32215051Skarels qcompar(l1, l2)
32325438Skarels register daddr_t *l1, *l2;
32415051Skarels {
32515051Skarels 	if (*l1 < *l2)
32615051Skarels 		return(-1);
32715051Skarels 	if (*l1 == *l2)
32815051Skarels 		return(0);
32915051Skarels 	return(1);
33015051Skarels }
33115051Skarels 
33225212Skarels daddr_t
badsn(bt,lp)33333648Sbostic badsn(bt, lp)
33425212Skarels 	register struct bt_bad *bt;
33533648Sbostic 	register struct disklabel *lp;
33625212Skarels {
33733648Sbostic 	register int ssoff = ssdev ? 1 : 0;
33825438Skarels 
33933648Sbostic 	return ((bt->bt_cyl * lp->d_ntracks + (bt->bt_trksec >> 8)) *
34033648Sbostic 		(lp->d_nsectors - ssoff) + (bt->bt_trksec & 0xff) - ssoff);
34125212Skarels }
34225212Skarels 
34311367Ssam /*
34425212Skarels  * Mark the bad/skipped sectors.
34525438Skarels  * Bad sectors on skip-sector devices are assumed to be skipped also,
34625438Skarels  * and must be done after the (earlier) first skipped sector.
34711367Ssam  */
writebb(fd,nsects,dbad,lp,sw)34833648Sbostic writebb(fd, nsects, dbad, lp, sw)
34911367Ssam 	int nsects, fd;
35011367Ssam 	struct dkbad *dbad;
35133648Sbostic 	register struct disklabel *lp;
35211367Ssam {
35311367Ssam 	struct sector bb_buf; /* buffer for one sector plus 4 byte header */
35411367Ssam 	register int i;
35511367Ssam 	int bn, j;
35611367Ssam 	struct bt_bad *btp;
35711367Ssam 
35811367Ssam 	for (i = 0; i < nsects; i++) {
35911367Ssam 		btp = &dbad->bt_bad[i];
36011367Ssam 		if (sw == BSERR) {
36111367Ssam 			bb_buf.header1 = HDR1_FMT22|btp->bt_cyl;
36225438Skarels 			if (ssdev)
36311367Ssam 				bb_buf.header1 |= HDR1_SSF;
36411367Ssam 		} else
36511367Ssam 			bb_buf.header1 =
36611367Ssam 			       btp->bt_cyl | HDR1_FMT22 | HDR1_SSF | HDR1_OKSCT;
36711367Ssam 		bb_buf.header2 = btp->bt_trksec;
36833648Sbostic 		bn = lp->d_secpercyl * btp->bt_cyl +
36933648Sbostic 		     lp->d_nsectors * (btp->bt_trksec >> 8) +
37015009Skarels 		     (btp->bt_trksec & 0xff);
37133553Skarels 		lseek(fd, bn * SECTSIZ, L_SET);
37211367Ssam 		ioctl(fd, SAIOHDR, (char *)0);
37311367Ssam 		write(fd, &bb_buf, sizeof (bb_buf));
37411367Ssam 		/*
37511367Ssam 		 * If skip sector, mark all remaining
37611367Ssam 		 * sectors on the track.
37711367Ssam 		 */
37825438Skarels 		if (sw == SSERR) {
37925438Skarels 			for (j = (btp->bt_trksec & 0xff) + 1, bn++;
38033648Sbostic 			    j < lp->d_nsectors; j++, bn++) {
38125438Skarels 				bb_buf.header2 = j | (btp->bt_trksec & 0xff00);
38233553Skarels 				lseek(fd, bn * SECTSIZ, L_SET);
38325438Skarels 				ioctl(fd, SAIOHDR, (char *)0);
38425438Skarels 				write(fd, &bb_buf, sizeof (bb_buf));
38525438Skarels 			}
38611367Ssam 		}
38711367Ssam 	}
38811367Ssam }
38911367Ssam 
39011367Ssam /*
39111367Ssam  * Record an error, and if there's room, put
39211367Ssam  * it in the appropriate bad sector table.
39315051Skarels  *
39415051Skarels  * If severe burnin store block in a list after making sure
39515051Skarels  * we have not already found it on a prev pass.
39611367Ssam  */
recorderror(fd,bn,lp)39733648Sbostic recorderror(fd, bn, lp)
39811367Ssam 	int fd, bn;
39933648Sbostic 	register struct disklabel *lp;
40011367Ssam {
40125212Skarels 	int cn, tn, sn;
40233648Sbostic 	register int i;
40311367Ssam 
40415051Skarels 	if (severe) {
40515051Skarels 		for (i = 0; i < nbads; i++)
40615051Skarels 			if (bads[i] == bn)
40715051Skarels 				return(0);	/* bn already flagged */
40825438Skarels 		if (nbads >= (ssdev ? 2 * MAXBADDESC : MAXBADDESC)) {
40925212Skarels 			printf("Bad sector table full, format terminating\n");
41015051Skarels 			return(-1);
41115051Skarels 		}
41215051Skarels 		bads[nbads++] = bn;
41317426Skarels 		if (errno < EBSE || errno > EHER)
41417426Skarels 			return(0);
41517426Skarels 		errno -= EBSE;
41617426Skarels 		errors[errno]++;
41715051Skarels 		return(0);
41815051Skarels 	}
41917426Skarels 	if (errno >= EBSE && errno <= EHER) {
42017426Skarels 		errno -= EBSE;
42117426Skarels 		errors[errno]++;
42211367Ssam 	}
42333648Sbostic 	cn = bn / lp->d_secpercyl;
42433648Sbostic 	sn = bn % lp->d_secpercyl;
42533648Sbostic 	tn = sn / lp->d_nsectors;
42633648Sbostic 	sn %= lp->d_nsectors;
42725438Skarels 	if (ssdev) {		/* if drive has skip sector capability */
42825212Skarels 		int ss = errors[FE_SSE];
42911367Ssam 
43025212Skarels 		if (errors[FE_SSE] >= MAXBADDESC) {
43125212Skarels 			/* this is bogus, we don't maintain skip sector table */
43225212Skarels 			printf("Too many skip sector errors\n");
43325212Skarels 			return(-1);
43425212Skarels 		}
43525212Skarels 		  /* only one skip sector/track */
43625212Skarels 		if (ss == 0 ||
43725212Skarels 		    tn != (sstab.bt_bad[ss - 1].bt_trksec >> 8) ||
43825212Skarels 		    cn != sstab.bt_bad[ss - 1].bt_cyl) {
43925438Skarels 			/*
44025438Skarels 			 * Don't bother with skipping the extra sector
44125438Skarels 			 * at the end of the track.
44225438Skarels 			 */
44333648Sbostic 			if (sn == lp->d_nsectors - 1)
44425438Skarels 				return(0);
44511367Ssam 			sstab.bt_bad[ss].bt_cyl = cn;
44611367Ssam 			sstab.bt_bad[ss].bt_trksec = (tn<<8) + sn;
44725212Skarels 			errors[FE_SSE]++;
44825212Skarels 			return(0);
44911367Ssam 		}
45011367Ssam 	}
45125212Skarels 	if (errors[FE_TOTAL] >= MAXBADDESC) {
45225212Skarels 		printf("Too many bad sectors\n");
45325212Skarels 		return(-1);
45425212Skarels 	}
45511367Ssam 	/* record the bad sector address and continue */
45615009Skarels 	dkbad.bt_bad[errors[FE_TOTAL]].bt_cyl = cn;
45711367Ssam 	dkbad.bt_bad[errors[FE_TOTAL]++].bt_trksec = (tn << 8) + sn;
45815051Skarels 	return(0);
45911367Ssam }
46011367Ssam 
46111367Ssam /*
46211367Ssam  * Allocate memory on a page-aligned address.
46311367Ssam  * Round allocated chunk to a page multiple to
46411367Ssam  * ease next request.
46511367Ssam  */
46611367Ssam char *
malloc(size)46711367Ssam malloc(size)
46811367Ssam 	int size;
46911367Ssam {
47011367Ssam 	char *result;
47111367Ssam 	static caddr_t last = 0;
47211367Ssam 
47311367Ssam 	if (last == 0)
47411367Ssam 		last = (caddr_t)(((int)&end + 511) & ~0x1ff);
47511367Ssam 	size = (size + 511) & ~0x1ff;
47611367Ssam 	result = (char *)last;
47711367Ssam 	last += size;
47811367Ssam 	return (result);
47911367Ssam }
48011367Ssam 
48111367Ssam /*
48211367Ssam  * Prompt and verify a device name from the user.
48311367Ssam  */
getdevice()48411367Ssam getdevice()
48511367Ssam {
48611367Ssam 	register char *cp;
48711367Ssam 	int fd;
48811367Ssam 
48911367Ssam top:
49033553Skarels 	do {
49134518Skarels 		printf(
49234518Skarels 		"Enter device name as \"type(adaptor,controller,drive,0)\"\n");
49333553Skarels 		cp = prompt("Device to format? ");
49433553Skarels 	} while ((fd = open(cp, 2)) < 0);
49534518Skarels 	printf("Formatting %c%c drive %d on controller %d, adaptor %d: ",
49634518Skarels 		cp[0], cp[1], iob[fd - 3].i_unit,
49734518Skarels 		iob[fd - 3].i_ctlr, iob[fd - 3].i_adapt);
49811367Ssam 	cp = prompt("verify (yes/no)? ");
49911367Ssam 	while (*cp != 'y' && *cp != 'n')
50011367Ssam 		cp = prompt("Huh, yes or no? ");
50111367Ssam 	if (*cp == 'y')
50211367Ssam 		return (fd);
50311367Ssam 	goto top;
50411367Ssam }
50511367Ssam 
50625212Skarels /*
50725212Skarels  * Find range of tracks to format.
50825212Skarels  */
getrange(lp)50933648Sbostic getrange(lp)
51033648Sbostic 	register struct disklabel *lp;
51125212Skarels {
51233648Sbostic 	startcyl = getnum("Starting cylinder", 0, lp->d_ncylinders - 1, 0);
51333648Sbostic 	starttrack = getnum("Starting track", 0, lp->d_ntracks - 1, 0);
51433648Sbostic 	endcyl = getnum("Ending cylinder", 0, lp->d_ncylinders - 1,
51533648Sbostic 		lp->d_ncylinders - 1);
51633648Sbostic 	endtrack = getnum("Ending track", 0, lp->d_ntracks - 1,
51733648Sbostic 		lp->d_ntracks - 1);
51825212Skarels }
51925212Skarels 
getnum(s,low,high,dflt)52025212Skarels getnum(s, low, high, dflt)
52133648Sbostic 	int s, low, high, dflt;
52225212Skarels {
52325212Skarels 	char buf[132];
52433648Sbostic 	u_int val;
52525212Skarels 
52633648Sbostic 	for(;;) {
52725212Skarels 		printf("%s (%d): ", s, dflt);
52825212Skarels 		gets(buf);
52925212Skarels 		if (buf[0] == 0)
53025212Skarels 			return (dflt);
53125212Skarels 		val = atoi(buf);
53225212Skarels 		if (val >= low && val <= high)
53325212Skarels 			return ((int)val);
53425212Skarels 		printf("Value must be in range [%d,%d]\n", low, high);
53525212Skarels 	}
53625212Skarels }
53725212Skarels 
53811371Ssam static struct pattern {
53911371Ssam 	long	pa_value;
54011371Ssam 	char	*pa_name;
54111371Ssam } pat[] = {
54211371Ssam 	{ 0xf00ff00f, 	"RH750 worst case" },
54311371Ssam 	{ 0xec6dec6d,	"media worst case" },
54411371Ssam 	{ 0xa5a5a5a5,	"alternate 1's and 0's" },
54517426Skarels 	{ 0xFFFFFFFF,	"Severe burnin (up to 48 passes)" },
54611371Ssam 	{ 0, 0 },
54711371Ssam };
54811371Ssam 
getpattern()54911371Ssam getpattern()
55011371Ssam {
55111371Ssam 	register struct pattern *p;
55211371Ssam 	int npatterns;
55311371Ssam 	char *cp;
55411371Ssam 
55511371Ssam 	printf("Available test patterns are:\n");
55611371Ssam 	for (p = pat; p->pa_value; p++)
55711371Ssam 		printf("\t%d - (%x) %s\n", (p - pat) + 1,
55811371Ssam 		  p->pa_value & 0xffff, p->pa_name);
55911371Ssam 	npatterns = p - pat;
56011371Ssam 	cp = prompt("Pattern (one of the above, other to restart)? ");
56111371Ssam 	pattern = atoi(cp) - 1;
56217426Skarels 	if (pattern < 0 || pattern >= npatterns)
56317426Skarels 		return(1);
56415051Skarels 	severe = 0;
56517426Skarels 	maxpass = 1;
56617426Skarels 	if (pat[pattern].pa_value == -1) {
56715051Skarels 		severe = 1;
56817426Skarels 		cp = prompt("How many passes (up to 48)? ");
56917426Skarels 		maxpass = atoi(cp);
57017426Skarels 		if (maxpass > NPT)
57117426Skarels 			maxpass = NPT;
57217426Skarels 	}
57325438Skarels 	maxeccbits = getnum(
57425438Skarels 		"Maximum number of bit errors to allow for soft ECC",
57525438Skarels 		0, 11, MAXECCBITS);
57617426Skarels 	return (0);
57711371Ssam }
57811371Ssam 
57911371Ssam struct xsect {
58011371Ssam 	u_short	hd1;
58111371Ssam 	u_short	hd2;
58211371Ssam 	long	buf[128];
58311371Ssam };
58411371Ssam 
58511371Ssam /*
58611371Ssam  * Initialize the buffer with the requested pattern.
58711371Ssam  */
bufinit(bp,size)58811371Ssam bufinit(bp, size)
58911371Ssam 	register struct xsect *bp;
59011371Ssam 	int size;
59111371Ssam {
59211371Ssam 	register struct pattern *pptr;
59311371Ssam 	register long *pp, *last;
59411371Ssam 	register struct xsect *lastbuf;
59515051Skarels 	int patt;
59611371Ssam 
59711371Ssam 	size /= sizeof (struct sector);
59811371Ssam 	lastbuf = bp + size;
59915051Skarels 	if (severe) {
60015051Skarels 		patt = ppat[npat] | ((long)ppat[npat] << 16);
60115051Skarels 		printf("Write pattern 0x%x\n", patt&0xffff);
60215051Skarels 	} else {
60315051Skarels 		pptr = &pat[pattern];
60415051Skarels 		patt = pptr->pa_value;
60515051Skarels 	}
60611371Ssam 	while (bp < lastbuf) {
60711371Ssam 		last = &bp->buf[128];
60811371Ssam 		for (pp = bp->buf; pp < last; pp++)
60915051Skarels 			*pp = patt;
61011371Ssam 		bp++;
61111371Ssam 	}
61211371Ssam }
61311371Ssam 
61411367Ssam char *
prompt(msg)61511367Ssam prompt(msg)
61611367Ssam 	char *msg;
61711367Ssam {
61811367Ssam 	static char buf[132];
61911367Ssam 
62011367Ssam 	printf("%s", msg);
62111367Ssam 	gets(buf);
62211367Ssam 	return (buf);
62311367Ssam }
624