xref: /csrg-svn/sys/vax/stand/format.c (revision 23251)
1*23251Smckusick /*
2*23251Smckusick  * Copyright (c) 1980 Regents of the University of California.
3*23251Smckusick  * All rights reserved.  The Berkeley software License Agreement
4*23251Smckusick  * specifies the terms and conditions for redistribution.
5*23251Smckusick  */
611367Ssam 
7*23251Smckusick #ifndef lint
8*23251Smckusick char copyright[] =
9*23251Smckusick "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10*23251Smckusick  All rights reserved.\n";
11*23251Smckusick #endif not lint
1215051Skarels 
13*23251Smckusick #ifndef lint
14*23251Smckusick static char sccsid[] = "@(#)format.c	6.5 (Berkeley) 06/08/85";
15*23251Smckusick #endif not lint
16*23251Smckusick 
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.
2111367Ssam  */
2211367Ssam #include "../h/param.h"
2311367Ssam #include "../h/fs.h"
2411367Ssam #include "../h/inode.h"
2511367Ssam #include "../h/dkbad.h"
2611367Ssam #include "../h/vmmac.h"
2711367Ssam 
2811367Ssam #include "saio.h"
2911367Ssam #include "savax.h"
3011367Ssam 
3111367Ssam #define MAXBADDESC	126		/* size of bad block table */
3211367Ssam #define CHUNK		48		/* max # of sectors/io operation */
3311367Ssam #define SECTSIZ		512		/* standard sector size */
3411367Ssam #define HDRSIZ		4		/* number of bytes in sector header */
3511367Ssam 
3611367Ssam #define SSERR		0
3711367Ssam #define BSERR		1
3811367Ssam 
3911367Ssam #define SSDEV		((ioctl(iob[fd-3], SAIOSSDEV, (char *)0) == 0))
4011367Ssam 
4111367Ssam struct sector {
4211367Ssam 	u_short	header1;
4311367Ssam 	u_short header2;
4411367Ssam 	char	buf[SECTSIZ];
4511367Ssam };
4611367Ssam 
4711367Ssam struct	dkbad dkbad;		/* bad sector table */
4811367Ssam struct	dkbad sstab;		/* skip sector table */
4911367Ssam 
5011367Ssam #define	NERRORS		6
5111371Ssam static char *
5211371Ssam errornames[NERRORS] = {
5315009Skarels #define	FE_BSE		0
5415009Skarels 	"Bad sector",
5515009Skarels #define	FE_WCE		1
5611367Ssam 	"Write check",
5711367Ssam #define	FE_ECC		2
5811367Ssam 	"ECC",
5911367Ssam #define	FE_HARD		3
6011367Ssam 	"Other hard",
6111367Ssam #define	FE_TOTAL	4
6211367Ssam 	"Total",
6311367Ssam #define	FE_SSE		5
6411367Ssam 	"Skip sector",
6511367Ssam };
6611367Ssam 
6711367Ssam int	errors[NERRORS];	/* histogram of errors */
6811371Ssam int	pattern;
6911367Ssam 
7015051Skarels /*
7115051Skarels  * Purdue/EE severe burnin patterns.
7215051Skarels  */
7315051Skarels unsigned short ppat[] = {
7417426Skarels 0xf00f, 0xec6d, 0031463,0070707,0133333,0155555,0161616,0143434,
7515051Skarels 0107070,0016161,0034343,0044444,0022222,0111111,0125252, 052525,
7615051Skarels 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252,
7715051Skarels #ifndef	SHORTPASS
7815051Skarels 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252,
7915051Skarels  052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525,
8015051Skarels #endif
8115051Skarels  052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525
8215051Skarels  };
8315051Skarels 
8415051Skarels #define	NPT	(sizeof (ppat) / sizeof (short))
8517426Skarels int	maxpass, npat;	/* subscript to ppat[] */
8615051Skarels int	severe;		/* nz if running "severe" burnin */
8715051Skarels int	nbads;		/* subscript for bads */
8815051Skarels long	bads[MAXBADDESC]; /* Bad blocks accumulated */
8915051Skarels 
9011367Ssam char	*malloc();
9115051Skarels int	qcompar();
9211367Ssam char	*prompt();
9311367Ssam extern	int end;
9411367Ssam 
9511367Ssam main()
9611367Ssam {
9711367Ssam 	register int sector, sn;
9815051Skarels 	int lastsector, tracksize, rtracksize;
9911367Ssam 	int unit, fd, resid, i, trk, cyl, debug;
10011367Ssam 	struct st st;
10111367Ssam 	struct sector *bp, *cbp;
10215051Skarels 	char *rbp, *rcbp;
10317426Skarels 	int pass;
10411367Ssam 	char *cp;
10511367Ssam 
10611367Ssam 	printf("Disk format/check utility\n\n");
10711367Ssam 
10811367Ssam again:
10915051Skarels 	nbads = 0;
11015051Skarels 	cp = prompt("Enable debugging (0=none, 1=bse, 2=ecc, 3=bse+ecc)? ");
11111367Ssam 	debug = atoi(cp);
11211367Ssam 	if (debug < 0)
11311367Ssam 		debug = 0;
11411367Ssam 	for (i = 0; i < NERRORS; i++)
11511367Ssam 		errors[i] = 0;
11611367Ssam 	fd = getdevice();
11711367Ssam 	ioctl(fd, SAIODEVDATA, &st);
11811367Ssam 	printf("Device data: #cylinders=%d, #tracks=%d, #sectors=%d\n",
11911367Ssam 	  st.ncyl, st.ntrak, st.nsect);
12011371Ssam 	if (getpattern())
12111367Ssam 		goto again;
12211367Ssam 	printf("Start formatting...make sure the drive is online\n");
12315051Skarels 	if (severe)
12415051Skarels 		ioctl(fd, SAIOSEVRE, (char *) 0);
12511367Ssam 	ioctl(fd, SAIONOBAD, (char *)0);
12611367Ssam 	ioctl(fd, SAIOECCLIM, (char *)0);
12711367Ssam 	ioctl(fd, SAIODEBUG, (char *)debug);
12811367Ssam 	if (SSDEV) {
12915051Skarels 		if (severe) {
13015051Skarels 			printf("Severe burnin doesn't work with RM80 yet\n");
13115051Skarels 			exit(1);
13215051Skarels 		}
13311367Ssam 		ioctl(fd, SAIOSSI, (char *)0);	/* set skip sector inhibit */
13411367Ssam 		st.nsect++;
13511367Ssam 		st.nspc += st.ntrak;
13611367Ssam 	}
13711367Ssam 	tracksize = sizeof (struct sector) * st.nsect;
13815051Skarels 	rtracksize = SECTSIZ * st.nsect;
13911367Ssam 	bp = (struct sector *)malloc(tracksize);
14015051Skarels 	rbp = malloc(rtracksize);
14117426Skarels 	pass = 0;
14217426Skarels 	npat = 0;
14317426Skarels more:
14417426Skarels 	for (; pass < maxpass; pass++) {
14515051Skarels 		if (severe)
14615051Skarels 			printf("Begin pass %d\n", pass);
14715051Skarels 		bufinit(bp, tracksize);
14815051Skarels 		if (severe)
14915051Skarels 			npat++;
15011367Ssam 		/*
15115051Skarels 		 * Begin check, for each track,
15211367Ssam 		 *
15315051Skarels 		 * 1) Write header and test pattern.
15415051Skarels 		 * 2) Read data.  Hardware checks header and data ECC.
15517426Skarels 		 *    Read data (esp on Eagles) is much faster than write check.
15611367Ssam 		 */
15715051Skarels 		lastsector = st.nspc * st.ncyl;
15815051Skarels 		for (sector = 0; sector < lastsector; sector += st.nsect) {
15915051Skarels 			cyl = sector / st.nspc;
16015051Skarels 			trk = (sector % st.nspc) / st.nsect;
16115051Skarels 			for (i = 0; i < st.nsect; i++) {
16215051Skarels 				bp[i].header1 =
16315051Skarels 					(u_short) cyl | HDR1_FMT22 | HDR1_OKSCT;
16415051Skarels 				bp[i].header2 = ((u_short)trk << 8) + i;
16515051Skarels 			}
16615051Skarels 			if (sector && (sector % (st.nspc * 100)) == 0)
16715051Skarels 				printf("cylinder %d\n", cyl);
16815051Skarels 			/*
16915051Skarels 			 * Try and write the headers and data patterns into
17015051Skarels 			 * each sector in the track.  Continue until such
17115051Skarels 			 * we're done, or until there's less than a sector's
17215051Skarels 			 * worth of data to transfer.
17315051Skarels 			 *
17415051Skarels 			 * The lseek call is necessary because of
17515051Skarels 			 * the odd sector size (516 bytes)
17615051Skarels 			 */
17715051Skarels 			for (resid = tracksize, cbp = bp, sn = sector;;) {
17815051Skarels 				int cc;
17911367Ssam 
18015051Skarels 				lseek(fd, sn * SECTSIZ, 0);
18115051Skarels 				ioctl(fd, SAIOHDR, (char *)0);
18215051Skarels 				cc = write(fd, cbp, resid);
18315051Skarels 				if (cc == resid)
18415051Skarels 					break;
18515051Skarels 				/*
18615051Skarels 				 * Don't record errors during write,
18715051Skarels 				 * all errors will be found during
18815051Skarels 				 * writecheck performed below.
18915051Skarels 				 */
19015051Skarels 				sn = iob[fd - 3].i_errblk;
19115051Skarels 				cbp += sn - sector;
19215051Skarels 				resid -= (sn - sector) * sizeof (struct sector);
19315051Skarels 				if (resid < sizeof (struct sector))
19415051Skarels 					break;
19515051Skarels 			}
19611367Ssam 			/*
19715051Skarels 			 * Read test patterns.
19815051Skarels 			 * Retry remainder of track on error until
19915051Skarels 			 * we're done, or until there's less than a
20015051Skarels 			 * sector to verify.
20111367Ssam 			 */
20215051Skarels 			for (resid = rtracksize, rcbp = rbp, sn = sector;;) {
20315051Skarels 				int cc;
20411367Ssam 
20515051Skarels 				lseek(fd, sn * SECTSIZ, 0);
20615051Skarels 				cc = read(fd, rcbp, resid);
20715051Skarels 				if (cc == resid)
20815051Skarels 					break;
20915051Skarels 				sn = iob[fd-3].i_errblk;
21015051Skarels 				printf("sector %d, read error\n", sn);
21115051Skarels 				if (recorderror(fd, sn, &st) < 0 && pass > 0)
21215051Skarels 					goto out;
21315051Skarels 				/* advance past bad sector */
21415051Skarels 				sn++;
21515051Skarels 				rcbp += sn - sector;
21615051Skarels 				resid -= ((sn - sector) * SECTSIZ);
21715051Skarels 				if (resid < SECTSIZ)
21815051Skarels 					break;
21915051Skarels 			}
22011367Ssam 		}
22111367Ssam 	}
22211367Ssam 	/*
22311367Ssam 	 * Checking finished.
22411367Ssam 	 */
22515051Skarels out:
22617426Skarels 	if (errors[FE_TOTAL] || errors[FE_SSE]) {
22717426Skarels 		printf("Errors:\n");
22817426Skarels 		for (i = 0; i < NERRORS; i++)
22917426Skarels 			printf("%s: %d\n", errornames[i], errors[i]);
23017426Skarels 		printf("Total of %d hard errors found\n",
23117426Skarels 			errors[FE_TOTAL] + errors[FE_SSE]);
23217426Skarels 	}
23317426Skarels 	if (severe && maxpass < NPT) {
23417426Skarels 		cp = prompt("More passes? (0 or number) ");
23517426Skarels 		maxpass = atoi(cp);
23617426Skarels 		if (maxpass > 0) {
23717426Skarels 			maxpass += pass;
23817426Skarels 			goto more;
23917426Skarels 		}
24017426Skarels 	}
24115051Skarels 	if (severe && nbads) {
24215051Skarels 		/*
24315051Skarels 		 * Sort bads and insert in bad block table.
24415051Skarels 		 */
24515051Skarels 		qsort(bads, nbads, sizeof (long), qcompar);
24615051Skarels 		severe = 0;
24717426Skarels 		errno = 0;
24817426Skarels 		for (i = 0; i < nbads; i++)
24915051Skarels 			recorderror(fd, bads[i], &st);
25015051Skarels 		severe++;
25115051Skarels 	}
25211367Ssam 	if (errors[FE_TOTAL] || errors[FE_SSE]) {
25311367Ssam 		/* change the headers of all the bad sectors */
25411367Ssam 		writebb(fd, errors[FE_SSE], &sstab, &st, SSERR);
25511367Ssam 		writebb(fd, errors[FE_TOTAL], &dkbad, &st, BSERR);
25611367Ssam 	}
25711367Ssam 	while (errors[FE_TOTAL] < MAXBADDESC) {
25811367Ssam 		int i = errors[FE_TOTAL]++;
25911367Ssam 
26011367Ssam 		dkbad.bt_bad[i].bt_cyl = -1;
26111367Ssam 		dkbad.bt_bad[i].bt_trksec = -1;
26211367Ssam 	}
26311367Ssam 	printf("\nWriting bad sector table at sector #%d\n",
26411367Ssam 		st.ncyl * st.nspc - st.nsect);
26511367Ssam 	/* place on disk */
26611367Ssam 	for (i = 0; i < 10; i += 2) {
26711367Ssam 		lseek(fd, SECTSIZ * (st.ncyl * st.nspc - st.nsect + i), 0);
26811367Ssam 		write(fd, &dkbad, sizeof (dkbad));
26911367Ssam 	}
27011367Ssam 	printf("Done\n");
27111367Ssam 	ioctl(fd,SAIONOSSI,(char *)0);
27211367Ssam 	close(fd);
27311367Ssam #ifndef JUSTEXIT
27411367Ssam 	goto again;
27511367Ssam #endif
27611367Ssam }
27711367Ssam 
27815051Skarels qcompar(l1, l2)
27915051Skarels register long *l1, *l2;
28015051Skarels {
28115051Skarels 	if (*l1 < *l2)
28215051Skarels 		return(-1);
28315051Skarels 	if (*l1 == *l2)
28415051Skarels 		return(0);
28515051Skarels 	return(1);
28615051Skarels }
28715051Skarels 
28811367Ssam /*
28911367Ssam  * Write out the bad blocks.
29011367Ssam  */
29111367Ssam writebb(fd, nsects, dbad, st, sw)
29211367Ssam 	int nsects, fd;
29311367Ssam 	struct dkbad *dbad;
29411367Ssam 	register struct st *st;
29511367Ssam {
29611367Ssam 	struct sector bb_buf; /* buffer for one sector plus 4 byte header */
29711367Ssam 	register int i;
29811367Ssam 	int bn, j;
29911367Ssam 	struct bt_bad *btp;
30011367Ssam 
30111367Ssam 	for (i = 0; i < nsects; i++) {
30211367Ssam 		btp = &dbad->bt_bad[i];
30311367Ssam 		if (sw == BSERR) {
30411367Ssam 			bb_buf.header1 = HDR1_FMT22|btp->bt_cyl;
30511367Ssam 			if (SSDEV)
30611367Ssam 				bb_buf.header1 |= HDR1_SSF;
30711367Ssam 		} else
30811367Ssam 			bb_buf.header1 =
30911367Ssam 			       btp->bt_cyl | HDR1_FMT22 | HDR1_SSF | HDR1_OKSCT;
31011367Ssam 		bb_buf.header2 = btp->bt_trksec;
31111367Ssam 		bn = st->nspc * btp->bt_cyl +
31211367Ssam 		     st->nsect * (btp->bt_trksec >> 8) +
31315009Skarels 		     (btp->bt_trksec & 0xff);
31411367Ssam 		lseek(fd, bn * SECTSIZ, 0);
31511367Ssam 		ioctl(fd, SAIOHDR, (char *)0);
31611367Ssam 		write(fd, &bb_buf, sizeof (bb_buf));
31711367Ssam 		if (!SSDEV)
31811367Ssam 			continue;
31911367Ssam 		/*
32011367Ssam 		 * If skip sector, mark all remaining
32111367Ssam 		 * sectors on the track.
32211367Ssam 		 */
32315009Skarels 		for (j = (btp->bt_trksec & 0xff) + 1; j < st->nsect; j++) {
32411367Ssam 			bb_buf.header1 = j | HDR1_FMT22 | HDR1_SSF;
32511367Ssam 			ioctl(fd, SAIOHDR, (char *)0);
32611367Ssam 			write(fd, &bb_buf, sizeof (bb_buf));
32711367Ssam 		}
32811367Ssam 	}
32911367Ssam }
33011367Ssam 
33111367Ssam /*
33211367Ssam  * Record an error, and if there's room, put
33311367Ssam  * it in the appropriate bad sector table.
33415051Skarels  *
33515051Skarels  * If severe burnin store block in a list after making sure
33615051Skarels  * we have not already found it on a prev pass.
33711367Ssam  */
33811367Ssam recorderror(fd, bn, st)
33911367Ssam 	int fd, bn;
34011367Ssam 	register struct st *st;
34111367Ssam {
34211367Ssam 	int cn, tn, sn, strk;
34315051Skarels 	register i;
34411367Ssam 
34515051Skarels 
34615051Skarels 	if (severe) {
34715051Skarels 		for (i = 0; i < nbads; i++)
34815051Skarels 			if (bads[i] == bn)
34915051Skarels 				return(0);	/* bn already flagged */
35015051Skarels 		if (nbads >= MAXBADDESC) {
35115051Skarels 			printf("Bad sector table full, burnin terminating\n");
35215051Skarels 			return(-1);
35315051Skarels 		}
35415051Skarels 		bads[nbads++] = bn;
35517426Skarels 		if (errno < EBSE || errno > EHER)
35617426Skarels 			return(0);
35717426Skarels 		errno -= EBSE;
35817426Skarels 		errors[errno]++;
35915051Skarels 		return(0);
36015051Skarels 	}
36117426Skarels 	if (errno >= EBSE && errno <= EHER) {
36217426Skarels 		if (errors[FE_TOTAL] >= MAXBADDESC) {
36317426Skarels 			printf("Too many bad sectors\n");
36417426Skarels 			return(-1);
36517426Skarels 		}
36617426Skarels 		if (errors[FE_SSE] >= MAXBADDESC) {
36717426Skarels 			printf("Too many skip sector errors\n");
36817426Skarels 			return(-1);
36917426Skarels 		}
37017426Skarels 		errno -= EBSE;
37117426Skarels 		errors[errno]++;
37211367Ssam 	}
37311367Ssam 	cn = bn / st->nspc;
37411367Ssam 	sn = bn % st->nspc;
37511367Ssam 	tn = sn / st->nsect;
37611367Ssam 	sn %= st->nsect;
37711367Ssam 	if (SSDEV) {		/* if drive has skip sector capability */
37811367Ssam 		int ss = errors[FE_SSE]++;
37911367Ssam 
38011367Ssam 		if (ss)
38111367Ssam 			strk = sstab.bt_bad[ss - 1].bt_trksec >> 8;
38211367Ssam 		else
38311367Ssam 			strk = -1;
38411367Ssam 		if (tn != strk) {	  /* only one skip sector/track */
38511367Ssam 			sstab.bt_bad[ss].bt_cyl = cn;
38611367Ssam 			sstab.bt_bad[ss].bt_trksec = (tn<<8) + sn;
38711367Ssam 			return;
38811367Ssam 		}
38911367Ssam 		cn = -cn;
39011367Ssam 	}
39111367Ssam 	/* record the bad sector address and continue */
39215009Skarels 	dkbad.bt_bad[errors[FE_TOTAL]].bt_cyl = cn;
39311367Ssam 	dkbad.bt_bad[errors[FE_TOTAL]++].bt_trksec = (tn << 8) + sn;
39415051Skarels 	return(0);
39511367Ssam }
39611367Ssam 
39711367Ssam /*
39811367Ssam  * Allocate memory on a page-aligned address.
39911367Ssam  * Round allocated chunk to a page multiple to
40011367Ssam  * ease next request.
40111367Ssam  */
40211367Ssam char *
40311367Ssam malloc(size)
40411367Ssam 	int size;
40511367Ssam {
40611367Ssam 	char *result;
40711367Ssam 	static caddr_t last = 0;
40811367Ssam 
40911367Ssam 	if (last == 0)
41011367Ssam 		last = (caddr_t)(((int)&end + 511) & ~0x1ff);
41111367Ssam 	size = (size + 511) & ~0x1ff;
41211367Ssam 	result = (char *)last;
41311367Ssam 	last += size;
41411367Ssam 	return (result);
41511367Ssam }
41611367Ssam 
41711367Ssam /*
41811367Ssam  * Prompt and verify a device name from the user.
41911367Ssam  */
42011367Ssam getdevice()
42111367Ssam {
42211367Ssam 	register char *cp;
42311367Ssam 	register struct devsw *dp;
42411367Ssam 	int fd;
42511367Ssam 
42611367Ssam top:
42711367Ssam 	cp = prompt("Device to format? ");
42811367Ssam 	if ((fd = open(cp, 2)) < 0) {
42911367Ssam 		printf("Known devices are: ");
43011367Ssam 		for (dp = devsw; dp->dv_name; dp++)
43111367Ssam 			printf("%s ",dp->dv_name);
43211367Ssam 		printf("\n");
43311367Ssam 		goto top;
43411367Ssam 	}
43515051Skarels 	printf("Formatting drive %c%c%d on adaptor %d: ",
43615051Skarels 		cp[0], cp[1], iob[fd - 3].i_unit % 8, iob[fd - 3].i_unit / 8);
43711367Ssam 	cp = prompt("verify (yes/no)? ");
43811367Ssam 	while (*cp != 'y' && *cp != 'n')
43911367Ssam 		cp = prompt("Huh, yes or no? ");
44011367Ssam 	if (*cp == 'y')
44111367Ssam 		return (fd);
44211367Ssam 	goto top;
44311367Ssam }
44411367Ssam 
44511371Ssam static struct pattern {
44611371Ssam 	long	pa_value;
44711371Ssam 	char	*pa_name;
44811371Ssam } pat[] = {
44911371Ssam 	{ 0xf00ff00f, 	"RH750 worst case" },
45011371Ssam 	{ 0xec6dec6d,	"media worst case" },
45111371Ssam 	{ 0xa5a5a5a5,	"alternate 1's and 0's" },
45217426Skarels 	{ 0xFFFFFFFF,	"Severe burnin (up to 48 passes)" },
45311371Ssam 	{ 0, 0 },
45411371Ssam };
45511371Ssam 
45611371Ssam getpattern()
45711371Ssam {
45811371Ssam 	register struct pattern *p;
45911371Ssam 	int npatterns;
46011371Ssam 	char *cp;
46111371Ssam 
46211371Ssam 	printf("Available test patterns are:\n");
46311371Ssam 	for (p = pat; p->pa_value; p++)
46411371Ssam 		printf("\t%d - (%x) %s\n", (p - pat) + 1,
46511371Ssam 		  p->pa_value & 0xffff, p->pa_name);
46611371Ssam 	npatterns = p - pat;
46711371Ssam 	cp = prompt("Pattern (one of the above, other to restart)? ");
46811371Ssam 	pattern = atoi(cp) - 1;
46917426Skarels 	if (pattern < 0 || pattern >= npatterns)
47017426Skarels 		return(1);
47115051Skarels 	severe = 0;
47217426Skarels 	maxpass = 1;
47317426Skarels 	if (pat[pattern].pa_value == -1) {
47415051Skarels 		severe = 1;
47517426Skarels 		cp = prompt("How many passes (up to 48)? ");
47617426Skarels 		maxpass = atoi(cp);
47717426Skarels 		if (maxpass > NPT)
47817426Skarels 			maxpass = NPT;
47917426Skarels 	}
48017426Skarels 	return (0);
48111371Ssam }
48211371Ssam 
48311371Ssam struct xsect {
48411371Ssam 	u_short	hd1;
48511371Ssam 	u_short	hd2;
48611371Ssam 	long	buf[128];
48711371Ssam };
48811371Ssam 
48911371Ssam /*
49011371Ssam  * Initialize the buffer with the requested pattern.
49111371Ssam  */
49211371Ssam bufinit(bp, size)
49311371Ssam 	register struct xsect *bp;
49411371Ssam 	int size;
49511371Ssam {
49611371Ssam 	register struct pattern *pptr;
49711371Ssam 	register long *pp, *last;
49811371Ssam 	register struct xsect *lastbuf;
49915051Skarels 	int patt;
50011371Ssam 
50111371Ssam 	size /= sizeof (struct sector);
50211371Ssam 	lastbuf = bp + size;
50315051Skarels 	if (severe) {
50415051Skarels 		patt = ppat[npat] | ((long)ppat[npat] << 16);
50515051Skarels 		printf("Write pattern 0x%x\n", patt&0xffff);
50615051Skarels 	} else {
50715051Skarels 		pptr = &pat[pattern];
50815051Skarels 		patt = pptr->pa_value;
50915051Skarels 	}
51011371Ssam 	while (bp < lastbuf) {
51111371Ssam 		last = &bp->buf[128];
51211371Ssam 		for (pp = bp->buf; pp < last; pp++)
51315051Skarels 			*pp = patt;
51411371Ssam 		bp++;
51511371Ssam 	}
51611371Ssam }
51711371Ssam 
51811367Ssam char *
51911367Ssam prompt(msg)
52011367Ssam 	char *msg;
52111367Ssam {
52211367Ssam 	static char buf[132];
52311367Ssam 
52411367Ssam 	printf("%s", msg);
52511367Ssam 	gets(buf);
52611367Ssam 	return (buf);
52711367Ssam }
528