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*25438Skarels static char sccsid[] = "@(#)format.c 6.7 (Berkeley) 11/08/85"; 1523251Smckusick #endif not lint 1623251Smckusick 1725212Skarels 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. 2225212Skarels * TODO: 2325212Skarels * add new bad sectors to bad-sector table when formatting by track 2425212Skarels * (rearranging replacements ala bad144 -a) 2525212Skarels * 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 44*25438Skarels #define SSDEV(fd) (ioctl((fd), SAIOSSDEV, (char *)0) == 0) 45*25438Skarels #define MAXECCBITS 3 4611367Ssam 4711367Ssam struct sector { 4811367Ssam u_short header1; 4911367Ssam u_short header2; 5011367Ssam char buf[SECTSIZ]; 5111367Ssam }; 5211367Ssam 5311367Ssam struct dkbad dkbad; /* bad sector table */ 54*25438Skarels struct dkbad oldbad; /* old bad sector table */ 5511367Ssam struct dkbad sstab; /* skip sector table */ 5611367Ssam 5711367Ssam #define NERRORS 6 5811371Ssam static char * 5911371Ssam errornames[NERRORS] = { 6015009Skarels #define FE_BSE 0 6115009Skarels "Bad sector", 6215009Skarels #define FE_WCE 1 6311367Ssam "Write check", 6411367Ssam #define FE_ECC 2 65*25438Skarels "Hard ECC", 6611367Ssam #define FE_HARD 3 6711367Ssam "Other hard", 6811367Ssam #define FE_TOTAL 4 69*25438Skarels "Marked bad", 7011367Ssam #define FE_SSE 5 71*25438Skarels "Skipped", 7211367Ssam }; 7311367Ssam 7411367Ssam int errors[NERRORS]; /* histogram of errors */ 7511371Ssam int pattern; 76*25438Skarels int maxeccbits; 7711367Ssam 7815051Skarels /* 7915051Skarels * Purdue/EE severe burnin patterns. 8015051Skarels */ 8115051Skarels unsigned short ppat[] = { 8217426Skarels 0xf00f, 0xec6d, 0031463,0070707,0133333,0155555,0161616,0143434, 8315051Skarels 0107070,0016161,0034343,0044444,0022222,0111111,0125252, 052525, 8415051Skarels 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252, 8515051Skarels #ifndef SHORTPASS 8615051Skarels 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252, 8715051Skarels 052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525, 8815051Skarels #endif 8915051Skarels 052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525 9015051Skarels }; 9115051Skarels 9215051Skarels #define NPT (sizeof (ppat) / sizeof (short)) 9317426Skarels int maxpass, npat; /* subscript to ppat[] */ 9415051Skarels int severe; /* nz if running "severe" burnin */ 95*25438Skarels int ssdev; /* device supports skip sectors */ 9625212Skarels int startcyl, endcyl, starttrack, endtrack; 97*25438Skarels int nbads; /* subscript for bads */ 98*25438Skarels daddr_t bads[2*MAXBADDESC]; /* Bad blocks accumulated */ 9915051Skarels 10011367Ssam char *malloc(); 10115051Skarels int qcompar(); 10211367Ssam char *prompt(); 10325212Skarels daddr_t badsn(); 10411367Ssam extern int end; 10511367Ssam 10611367Ssam main() 10711367Ssam { 10811367Ssam register int sector, sn; 10915051Skarels int lastsector, tracksize, rtracksize; 11011367Ssam int unit, fd, resid, i, trk, cyl, debug; 11111367Ssam struct st st; 11211367Ssam struct sector *bp, *cbp; 11315051Skarels char *rbp, *rcbp; 11417426Skarels int pass; 11511367Ssam char *cp; 11611367Ssam 11711367Ssam printf("Disk format/check utility\n\n"); 11811367Ssam 11911367Ssam again: 12015051Skarels nbads = 0; 12115051Skarels cp = prompt("Enable debugging (0=none, 1=bse, 2=ecc, 3=bse+ecc)? "); 12211367Ssam debug = atoi(cp); 12311367Ssam if (debug < 0) 12411367Ssam debug = 0; 12511367Ssam for (i = 0; i < NERRORS; i++) 12611367Ssam errors[i] = 0; 12711367Ssam fd = getdevice(); 12811367Ssam ioctl(fd, SAIODEVDATA, &st); 12911367Ssam printf("Device data: #cylinders=%d, #tracks=%d, #sectors=%d\n", 13011367Ssam st.ncyl, st.ntrak, st.nsect); 131*25438Skarels ssdev = SSDEV(fd); 132*25438Skarels if (ssdev) { 133*25438Skarels ioctl(fd, SAIOSSI, (char *)0); /* set skip sector inhibit */ 134*25438Skarels st.nsect++; 135*25438Skarels st.nspc += st.ntrak; 136*25438Skarels printf("(not counting skip-sector replacement)\n"); 137*25438Skarels } 13825212Skarels getrange(&st); 13911371Ssam if (getpattern()) 14011367Ssam goto again; 14111367Ssam printf("Start formatting...make sure the drive is online\n"); 14211367Ssam ioctl(fd, SAIONOBAD, (char *)0); 143*25438Skarels ioctl(fd, SAIORETRIES, (char *)0); 144*25438Skarels ioctl(fd, SAIOECCLIM, (char *)maxeccbits); 14511367Ssam ioctl(fd, SAIODEBUG, (char *)debug); 14611367Ssam tracksize = sizeof (struct sector) * st.nsect; 14715051Skarels rtracksize = SECTSIZ * st.nsect; 14811367Ssam bp = (struct sector *)malloc(tracksize); 14915051Skarels rbp = malloc(rtracksize); 15017426Skarels pass = 0; 15117426Skarels npat = 0; 15217426Skarels more: 15317426Skarels for (; pass < maxpass; pass++) { 15415051Skarels if (severe) 15515051Skarels printf("Begin pass %d\n", pass); 15615051Skarels bufinit(bp, tracksize); 15715051Skarels if (severe) 15815051Skarels npat++; 15911367Ssam /* 16015051Skarels * Begin check, for each track, 16111367Ssam * 16215051Skarels * 1) Write header and test pattern. 16315051Skarels * 2) Read data. Hardware checks header and data ECC. 16417426Skarels * Read data (esp on Eagles) is much faster than write check. 16511367Ssam */ 16625212Skarels sector = ((startcyl * st.ntrak) + starttrack) * st.nsect; 16725212Skarels lastsector = ((endcyl * st.ntrak) + endtrack) * st.nsect 16825212Skarels + st.nsect; 16925212Skarels for ( ; sector < lastsector; sector += st.nsect) { 17015051Skarels cyl = sector / st.nspc; 17115051Skarels trk = (sector % st.nspc) / st.nsect; 17215051Skarels for (i = 0; i < st.nsect; i++) { 17315051Skarels bp[i].header1 = 17415051Skarels (u_short) cyl | HDR1_FMT22 | HDR1_OKSCT; 17515051Skarels bp[i].header2 = ((u_short)trk << 8) + i; 17615051Skarels } 17715051Skarels if (sector && (sector % (st.nspc * 100)) == 0) 17815051Skarels printf("cylinder %d\n", cyl); 17915051Skarels /* 18015051Skarels * Try and write the headers and data patterns into 18115051Skarels * each sector in the track. Continue until such 18215051Skarels * we're done, or until there's less than a sector's 18315051Skarels * worth of data to transfer. 18415051Skarels * 18515051Skarels * The lseek call is necessary because of 18615051Skarels * the odd sector size (516 bytes) 18715051Skarels */ 18815051Skarels for (resid = tracksize, cbp = bp, sn = sector;;) { 18915051Skarels int cc; 19011367Ssam 19115051Skarels lseek(fd, sn * SECTSIZ, 0); 19215051Skarels ioctl(fd, SAIOHDR, (char *)0); 19315051Skarels cc = write(fd, cbp, resid); 19415051Skarels if (cc == resid) 19515051Skarels break; 19615051Skarels /* 19715051Skarels * Don't record errors during write, 19815051Skarels * all errors will be found during 199*25438Skarels * check performed below. 20015051Skarels */ 20115051Skarels sn = iob[fd - 3].i_errblk; 20215051Skarels cbp += sn - sector; 20315051Skarels resid -= (sn - sector) * sizeof (struct sector); 20415051Skarels if (resid < sizeof (struct sector)) 20515051Skarels break; 20615051Skarels } 20711367Ssam /* 20815051Skarels * Read test patterns. 20915051Skarels * Retry remainder of track on error until 21015051Skarels * we're done, or until there's less than a 21115051Skarels * sector to verify. 21211367Ssam */ 21315051Skarels for (resid = rtracksize, rcbp = rbp, sn = sector;;) { 214*25438Skarels int cc, rsn; 21511367Ssam 21615051Skarels lseek(fd, sn * SECTSIZ, 0); 21715051Skarels cc = read(fd, rcbp, resid); 21815051Skarels if (cc == resid) 21915051Skarels break; 22015051Skarels sn = iob[fd-3].i_errblk; 221*25438Skarels if (ssdev) { 222*25438Skarels rsn = sn - (sn / st.nsect); 223*25438Skarels printf("data "); 224*25438Skarels } else 225*25438Skarels rsn = sn; 226*25438Skarels printf("sector %d, read error\n\n", rsn); 22715051Skarels if (recorderror(fd, sn, &st) < 0 && pass > 0) 22815051Skarels goto out; 22915051Skarels /* advance past bad sector */ 23015051Skarels sn++; 231*25438Skarels resid = rtracksize - ((sn - sector) * SECTSIZ); 232*25438Skarels rcbp = rbp + ((sn - sector) * SECTSIZ); 23315051Skarels if (resid < SECTSIZ) 23415051Skarels break; 23515051Skarels } 23611367Ssam } 23711367Ssam } 23811367Ssam /* 23911367Ssam * Checking finished. 24011367Ssam */ 24115051Skarels out: 24217426Skarels if (severe && maxpass < NPT) { 24317426Skarels cp = prompt("More passes? (0 or number) "); 24417426Skarels maxpass = atoi(cp); 24517426Skarels if (maxpass > 0) { 24617426Skarels maxpass += pass; 24717426Skarels goto more; 24817426Skarels } 24917426Skarels } 25015051Skarels if (severe && nbads) { 25115051Skarels /* 25215051Skarels * Sort bads and insert in bad block table. 25315051Skarels */ 254*25438Skarels qsort(bads, nbads, sizeof (daddr_t), qcompar); 25515051Skarels severe = 0; 25617426Skarels errno = 0; 25717426Skarels for (i = 0; i < nbads; i++) 25815051Skarels recorderror(fd, bads[i], &st); 25915051Skarels severe++; 26015051Skarels } 26111367Ssam if (errors[FE_TOTAL] || errors[FE_SSE]) { 26211367Ssam /* change the headers of all the bad sectors */ 26311367Ssam writebb(fd, errors[FE_SSE], &sstab, &st, SSERR); 26411367Ssam writebb(fd, errors[FE_TOTAL], &dkbad, &st, BSERR); 26511367Ssam } 266*25438Skarels if (errors[FE_TOTAL] || errors[FE_SSE]) { 267*25438Skarels printf("Errors:\n"); 268*25438Skarels for (i = 0; i < NERRORS; i++) 269*25438Skarels printf("%s: %d\n", errornames[i], errors[i]); 270*25438Skarels printf("Total of %d hard errors revectored\n", 271*25438Skarels errors[FE_TOTAL] + errors[FE_SSE]); 272*25438Skarels } 27325212Skarels if (endcyl == st.ncyl - 1 && 27425212Skarels (startcyl < st.ncyl - 1 || starttrack == 0)) { 27525212Skarels while (errors[FE_TOTAL] < MAXBADDESC) { 27625212Skarels int i = errors[FE_TOTAL]++; 27711367Ssam 27825212Skarels dkbad.bt_bad[i].bt_cyl = -1; 27925212Skarels dkbad.bt_bad[i].bt_trksec = -1; 28025212Skarels } 28125212Skarels printf("\nWriting bad sector table at sector #%d\n", 28225212Skarels st.ncyl * st.nspc - st.nsect); 28325212Skarels /* place on disk */ 28425212Skarels for (i = 0; i < 10 && i < st.nsect; i += 2) { 28525212Skarels lseek(fd, SECTSIZ * (st.ncyl * st.nspc - st.nsect + i), 0); 28625212Skarels write(fd, &dkbad, sizeof (dkbad)); 28725212Skarels } 28825212Skarels } else if (errors[FE_TOTAL]) { 28925212Skarels struct bt_bad *bt; 29025212Skarels 29125212Skarels printf("New bad sectors (not added to table):\n"); 29225212Skarels bt = dkbad.bt_bad; 29325212Skarels for (i = 0; i < errors[FE_TOTAL]; i++) { 294*25438Skarels printf("bn %d (cn=%d, tn=%d, sn=%d)\n", badsn(bt, &st), 29525212Skarels bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff); 29625212Skarels bt++; 29725212Skarels } 29811367Ssam } 29911367Ssam printf("Done\n"); 30011367Ssam ioctl(fd,SAIONOSSI,(char *)0); 30111367Ssam close(fd); 30211367Ssam #ifndef JUSTEXIT 30311367Ssam goto again; 30411367Ssam #endif 30511367Ssam } 30611367Ssam 30715051Skarels qcompar(l1, l2) 308*25438Skarels register daddr_t *l1, *l2; 30915051Skarels { 31015051Skarels if (*l1 < *l2) 31115051Skarels return(-1); 31215051Skarels if (*l1 == *l2) 31315051Skarels return(0); 31415051Skarels return(1); 31515051Skarels } 31615051Skarels 31725212Skarels daddr_t 31825212Skarels badsn(bt, st) 31925212Skarels register struct bt_bad *bt; 32025212Skarels register struct st *st; 32125212Skarels { 322*25438Skarels 323*25438Skarels if (ssdev) 324*25438Skarels return ((bt->bt_cyl * st->ntrak + (bt->bt_trksec>>8)) * 325*25438Skarels (st->nsect - 1) + (bt->bt_trksec&0xff)) - 1; 326*25438Skarels else 327*25438Skarels return ((bt->bt_cyl*st->ntrak + (bt->bt_trksec>>8)) * st->nsect 32825212Skarels + (bt->bt_trksec&0xff)); 32925212Skarels } 33025212Skarels 33111367Ssam /* 33225212Skarels * Mark the bad/skipped sectors. 333*25438Skarels * Bad sectors on skip-sector devices are assumed to be skipped also, 334*25438Skarels * and must be done after the (earlier) first skipped sector. 33511367Ssam */ 33611367Ssam writebb(fd, nsects, dbad, st, sw) 33711367Ssam int nsects, fd; 33811367Ssam struct dkbad *dbad; 33911367Ssam register struct st *st; 34011367Ssam { 34111367Ssam struct sector bb_buf; /* buffer for one sector plus 4 byte header */ 34211367Ssam register int i; 34311367Ssam int bn, j; 34411367Ssam struct bt_bad *btp; 34511367Ssam 34611367Ssam for (i = 0; i < nsects; i++) { 34711367Ssam btp = &dbad->bt_bad[i]; 34811367Ssam if (sw == BSERR) { 34911367Ssam bb_buf.header1 = HDR1_FMT22|btp->bt_cyl; 350*25438Skarels if (ssdev) 35111367Ssam bb_buf.header1 |= HDR1_SSF; 35211367Ssam } else 35311367Ssam bb_buf.header1 = 35411367Ssam btp->bt_cyl | HDR1_FMT22 | HDR1_SSF | HDR1_OKSCT; 35511367Ssam bb_buf.header2 = btp->bt_trksec; 35611367Ssam bn = st->nspc * btp->bt_cyl + 35711367Ssam st->nsect * (btp->bt_trksec >> 8) + 35815009Skarels (btp->bt_trksec & 0xff); 35911367Ssam lseek(fd, bn * SECTSIZ, 0); 36011367Ssam ioctl(fd, SAIOHDR, (char *)0); 36111367Ssam write(fd, &bb_buf, sizeof (bb_buf)); 36211367Ssam /* 36311367Ssam * If skip sector, mark all remaining 36411367Ssam * sectors on the track. 36511367Ssam */ 366*25438Skarels if (sw == SSERR) { 367*25438Skarels for (j = (btp->bt_trksec & 0xff) + 1, bn++; 368*25438Skarels j < st->nsect; j++, bn++) { 369*25438Skarels bb_buf.header2 = j | (btp->bt_trksec & 0xff00); 370*25438Skarels lseek(fd, bn * SECTSIZ, 0); 371*25438Skarels ioctl(fd, SAIOHDR, (char *)0); 372*25438Skarels write(fd, &bb_buf, sizeof (bb_buf)); 373*25438Skarels } 37411367Ssam } 37511367Ssam } 37611367Ssam } 37711367Ssam 37811367Ssam /* 37911367Ssam * Record an error, and if there's room, put 38011367Ssam * it in the appropriate bad sector table. 38115051Skarels * 38215051Skarels * If severe burnin store block in a list after making sure 38315051Skarels * we have not already found it on a prev pass. 38411367Ssam */ 38511367Ssam recorderror(fd, bn, st) 38611367Ssam int fd, bn; 38711367Ssam register struct st *st; 38811367Ssam { 38925212Skarels int cn, tn, sn; 39015051Skarels register i; 39111367Ssam 39215051Skarels 39315051Skarels if (severe) { 39415051Skarels for (i = 0; i < nbads; i++) 39515051Skarels if (bads[i] == bn) 39615051Skarels return(0); /* bn already flagged */ 397*25438Skarels if (nbads >= (ssdev ? 2 * MAXBADDESC : MAXBADDESC)) { 39825212Skarels printf("Bad sector table full, format terminating\n"); 39915051Skarels return(-1); 40015051Skarels } 40115051Skarels bads[nbads++] = bn; 40217426Skarels if (errno < EBSE || errno > EHER) 40317426Skarels return(0); 40417426Skarels errno -= EBSE; 40517426Skarels errors[errno]++; 40615051Skarels return(0); 40715051Skarels } 40817426Skarels if (errno >= EBSE && errno <= EHER) { 40917426Skarels errno -= EBSE; 41017426Skarels errors[errno]++; 41111367Ssam } 41211367Ssam cn = bn / st->nspc; 41311367Ssam sn = bn % st->nspc; 41411367Ssam tn = sn / st->nsect; 41511367Ssam sn %= st->nsect; 416*25438Skarels if (ssdev) { /* if drive has skip sector capability */ 41725212Skarels int ss = errors[FE_SSE]; 41811367Ssam 41925212Skarels if (errors[FE_SSE] >= MAXBADDESC) { 42025212Skarels /* this is bogus, we don't maintain skip sector table */ 42125212Skarels printf("Too many skip sector errors\n"); 42225212Skarels return(-1); 42325212Skarels } 42425212Skarels /* only one skip sector/track */ 42525212Skarels if (ss == 0 || 42625212Skarels tn != (sstab.bt_bad[ss - 1].bt_trksec >> 8) || 42725212Skarels cn != sstab.bt_bad[ss - 1].bt_cyl) { 428*25438Skarels /* 429*25438Skarels * Don't bother with skipping the extra sector 430*25438Skarels * at the end of the track. 431*25438Skarels */ 432*25438Skarels if (sn == st->nsect - 1) 433*25438Skarels return(0); 43411367Ssam sstab.bt_bad[ss].bt_cyl = cn; 43511367Ssam sstab.bt_bad[ss].bt_trksec = (tn<<8) + sn; 43625212Skarels errors[FE_SSE]++; 43725212Skarels return(0); 43811367Ssam } 43911367Ssam } 44025212Skarels if (errors[FE_TOTAL] >= MAXBADDESC) { 44125212Skarels printf("Too many bad sectors\n"); 44225212Skarels return(-1); 44325212Skarels } 44411367Ssam /* record the bad sector address and continue */ 44515009Skarels dkbad.bt_bad[errors[FE_TOTAL]].bt_cyl = cn; 44611367Ssam dkbad.bt_bad[errors[FE_TOTAL]++].bt_trksec = (tn << 8) + sn; 44715051Skarels return(0); 44811367Ssam } 44911367Ssam 45011367Ssam /* 45111367Ssam * Allocate memory on a page-aligned address. 45211367Ssam * Round allocated chunk to a page multiple to 45311367Ssam * ease next request. 45411367Ssam */ 45511367Ssam char * 45611367Ssam malloc(size) 45711367Ssam int size; 45811367Ssam { 45911367Ssam char *result; 46011367Ssam static caddr_t last = 0; 46111367Ssam 46211367Ssam if (last == 0) 46311367Ssam last = (caddr_t)(((int)&end + 511) & ~0x1ff); 46411367Ssam size = (size + 511) & ~0x1ff; 46511367Ssam result = (char *)last; 46611367Ssam last += size; 46711367Ssam return (result); 46811367Ssam } 46911367Ssam 47011367Ssam /* 47111367Ssam * Prompt and verify a device name from the user. 47211367Ssam */ 47311367Ssam getdevice() 47411367Ssam { 47511367Ssam register char *cp; 47611367Ssam register struct devsw *dp; 47711367Ssam int fd; 47811367Ssam 47911367Ssam top: 48011367Ssam cp = prompt("Device to format? "); 48111367Ssam if ((fd = open(cp, 2)) < 0) { 48211367Ssam printf("Known devices are: "); 48311367Ssam for (dp = devsw; dp->dv_name; dp++) 48411367Ssam printf("%s ",dp->dv_name); 48511367Ssam printf("\n"); 48611367Ssam goto top; 48711367Ssam } 48815051Skarels printf("Formatting drive %c%c%d on adaptor %d: ", 48915051Skarels cp[0], cp[1], iob[fd - 3].i_unit % 8, iob[fd - 3].i_unit / 8); 49011367Ssam cp = prompt("verify (yes/no)? "); 49111367Ssam while (*cp != 'y' && *cp != 'n') 49211367Ssam cp = prompt("Huh, yes or no? "); 49311367Ssam if (*cp == 'y') 49411367Ssam return (fd); 49511367Ssam goto top; 49611367Ssam } 49711367Ssam 49825212Skarels /* 49925212Skarels * Find range of tracks to format. 50025212Skarels */ 50125212Skarels getrange(st) 50225212Skarels struct st *st; 50325212Skarels { 50425212Skarels startcyl = getnum("Starting cylinder", 0, st->ncyl - 1, 0); 505*25438Skarels starttrack = getnum("Starting track", 0, st->ntrak - 1, 0); 50625212Skarels endcyl = getnum("Ending cylinder", 0, st->ncyl - 1, st->ncyl - 1); 50725212Skarels endtrack = getnum("Ending track", 0, st->ntrak - 1, st->ntrak - 1); 50825212Skarels } 50925212Skarels 51025212Skarels getnum(s, low, high, dflt) 51125212Skarels { 51225212Skarels char buf[132]; 51325212Skarels unsigned val; 51425212Skarels 51525212Skarels while (1) { 51625212Skarels printf("%s (%d): ", s, dflt); 51725212Skarels gets(buf); 51825212Skarels if (buf[0] == 0) 51925212Skarels return (dflt); 52025212Skarels val = atoi(buf); 52125212Skarels if (val >= low && val <= high) 52225212Skarels return ((int)val); 52325212Skarels printf("Value must be in range [%d,%d]\n", low, high); 52425212Skarels } 52525212Skarels } 52625212Skarels 52711371Ssam static struct pattern { 52811371Ssam long pa_value; 52911371Ssam char *pa_name; 53011371Ssam } pat[] = { 53111371Ssam { 0xf00ff00f, "RH750 worst case" }, 53211371Ssam { 0xec6dec6d, "media worst case" }, 53311371Ssam { 0xa5a5a5a5, "alternate 1's and 0's" }, 53417426Skarels { 0xFFFFFFFF, "Severe burnin (up to 48 passes)" }, 53511371Ssam { 0, 0 }, 53611371Ssam }; 53711371Ssam 53811371Ssam getpattern() 53911371Ssam { 54011371Ssam register struct pattern *p; 54111371Ssam int npatterns; 54211371Ssam char *cp; 54311371Ssam 54411371Ssam printf("Available test patterns are:\n"); 54511371Ssam for (p = pat; p->pa_value; p++) 54611371Ssam printf("\t%d - (%x) %s\n", (p - pat) + 1, 54711371Ssam p->pa_value & 0xffff, p->pa_name); 54811371Ssam npatterns = p - pat; 54911371Ssam cp = prompt("Pattern (one of the above, other to restart)? "); 55011371Ssam pattern = atoi(cp) - 1; 55117426Skarels if (pattern < 0 || pattern >= npatterns) 55217426Skarels return(1); 55315051Skarels severe = 0; 55417426Skarels maxpass = 1; 55517426Skarels if (pat[pattern].pa_value == -1) { 55615051Skarels severe = 1; 55717426Skarels cp = prompt("How many passes (up to 48)? "); 55817426Skarels maxpass = atoi(cp); 55917426Skarels if (maxpass > NPT) 56017426Skarels maxpass = NPT; 56117426Skarels } 562*25438Skarels maxeccbits = getnum( 563*25438Skarels "Maximum number of bit errors to allow for soft ECC", 564*25438Skarels 0, 11, MAXECCBITS); 56517426Skarels return (0); 56611371Ssam } 56711371Ssam 56811371Ssam struct xsect { 56911371Ssam u_short hd1; 57011371Ssam u_short hd2; 57111371Ssam long buf[128]; 57211371Ssam }; 57311371Ssam 57411371Ssam /* 57511371Ssam * Initialize the buffer with the requested pattern. 57611371Ssam */ 57711371Ssam bufinit(bp, size) 57811371Ssam register struct xsect *bp; 57911371Ssam int size; 58011371Ssam { 58111371Ssam register struct pattern *pptr; 58211371Ssam register long *pp, *last; 58311371Ssam register struct xsect *lastbuf; 58415051Skarels int patt; 58511371Ssam 58611371Ssam size /= sizeof (struct sector); 58711371Ssam lastbuf = bp + size; 58815051Skarels if (severe) { 58915051Skarels patt = ppat[npat] | ((long)ppat[npat] << 16); 59015051Skarels printf("Write pattern 0x%x\n", patt&0xffff); 59115051Skarels } else { 59215051Skarels pptr = &pat[pattern]; 59315051Skarels patt = pptr->pa_value; 59415051Skarels } 59511371Ssam while (bp < lastbuf) { 59611371Ssam last = &bp->buf[128]; 59711371Ssam for (pp = bp->buf; pp < last; pp++) 59815051Skarels *pp = patt; 59911371Ssam bp++; 60011371Ssam } 60111371Ssam } 60211371Ssam 60311367Ssam char * 60411367Ssam prompt(msg) 60511367Ssam char *msg; 60611367Ssam { 60711367Ssam static char buf[132]; 60811367Ssam 60911367Ssam printf("%s", msg); 61011367Ssam gets(buf); 61111367Ssam return (buf); 61211367Ssam } 613