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