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*34518Skarels static char sccsid[] = "@(#)format.c 7.4 (Berkeley) 05/27/88"; 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 */ 2633553Skarels #include "param.h" 2733553Skarels #include "fs.h" 2833553Skarels #include "inode.h" 2933553Skarels #include "dkbad.h" 3033553Skarels #include "vmmac.h" 3133648Sbostic #include "disklabel.h" 3211367Ssam 3333648Sbostic #include "../vax/cpu.h" 3433648Sbostic #include "../vax/mtpr.h" 3533648Sbostic 3611367Ssam #include "saio.h" 3711367Ssam #include "savax.h" 3811367Ssam 3911367Ssam #define MAXBADDESC 126 /* size of bad block table */ 4011367Ssam #define CHUNK 48 /* max # of sectors/io operation */ 4111367Ssam #define SECTSIZ 512 /* standard sector size */ 4211367Ssam #define HDRSIZ 4 /* number of bytes in sector header */ 4311367Ssam 4411367Ssam #define SSERR 0 4511367Ssam #define BSERR 1 4611367Ssam 4725438Skarels #define SSDEV(fd) (ioctl((fd), SAIOSSDEV, (char *)0) == 0) 4825438Skarels #define MAXECCBITS 3 4911367Ssam 5011367Ssam struct sector { 5111367Ssam u_short header1; 5211367Ssam u_short header2; 5311367Ssam char buf[SECTSIZ]; 5411367Ssam }; 5511367Ssam 5611367Ssam struct dkbad dkbad; /* bad sector table */ 5725438Skarels struct dkbad oldbad; /* old bad sector table */ 5811367Ssam struct dkbad sstab; /* skip sector table */ 5911367Ssam 6011367Ssam #define NERRORS 6 6111371Ssam static char * 6211371Ssam errornames[NERRORS] = { 6315009Skarels #define FE_BSE 0 6415009Skarels "Bad sector", 6515009Skarels #define FE_WCE 1 6611367Ssam "Write check", 6711367Ssam #define FE_ECC 2 6825438Skarels "Hard ECC", 6911367Ssam #define FE_HARD 3 7011367Ssam "Other hard", 7111367Ssam #define FE_TOTAL 4 7225438Skarels "Marked bad", 7311367Ssam #define FE_SSE 5 7425438Skarels "Skipped", 7511367Ssam }; 7611367Ssam 7711367Ssam int errors[NERRORS]; /* histogram of errors */ 7811371Ssam int pattern; 7925438Skarels int maxeccbits; 8011367Ssam 8115051Skarels /* 8215051Skarels * Purdue/EE severe burnin patterns. 8315051Skarels */ 8415051Skarels unsigned short ppat[] = { 8517426Skarels 0xf00f, 0xec6d, 0031463,0070707,0133333,0155555,0161616,0143434, 8615051Skarels 0107070,0016161,0034343,0044444,0022222,0111111,0125252, 052525, 8715051Skarels 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252, 8815051Skarels #ifndef SHORTPASS 8915051Skarels 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252, 9015051Skarels 052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525, 9115051Skarels #endif 9215051Skarels 052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525 9315051Skarels }; 9415051Skarels 9515051Skarels #define NPT (sizeof (ppat) / sizeof (short)) 9617426Skarels int maxpass, npat; /* subscript to ppat[] */ 9715051Skarels int severe; /* nz if running "severe" burnin */ 9825438Skarels int ssdev; /* device supports skip sectors */ 9925212Skarels int startcyl, endcyl, starttrack, endtrack; 10025438Skarels int nbads; /* subscript for bads */ 10125438Skarels daddr_t bads[2*MAXBADDESC]; /* Bad blocks accumulated */ 10215051Skarels 10311367Ssam char *malloc(); 10415051Skarels int qcompar(); 10511367Ssam char *prompt(); 10625212Skarels daddr_t badsn(); 10711367Ssam extern int end; 10811367Ssam 10911367Ssam main() 11011367Ssam { 11133648Sbostic register struct sector *hdr; 11233648Sbostic register int sector, sn, i; 11333648Sbostic struct disklabel dl; 11433648Sbostic struct sector *bp, *cbp; 11515051Skarels int lastsector, tracksize, rtracksize; 11633648Sbostic int unit, fd, resid, trk, cyl, debug, pass; 11733648Sbostic char *cp, *rbp, *rcbp; 11811367Ssam 11911367Ssam printf("Disk format/check utility\n\n"); 12011367Ssam 12133648Sbostic /* enable the cache, as every little bit helps */ 12233648Sbostic switch (cpu) { 12333648Sbostic case VAX_8600: 12433648Sbostic mtpr(CSWP, 3); 12533648Sbostic break; 12633648Sbostic case VAX_8200: 12733648Sbostic case VAX_750: 12833648Sbostic mtpr(CADR, 0); 12933648Sbostic break; 13033648Sbostic case VAX_780: 13133648Sbostic mtpr(SBIMT, 0x200000); 13233648Sbostic break; 13333648Sbostic } 13433648Sbostic 13511367Ssam again: 13615051Skarels nbads = 0; 13715051Skarels cp = prompt("Enable debugging (0=none, 1=bse, 2=ecc, 3=bse+ecc)? "); 13811367Ssam debug = atoi(cp); 13911367Ssam if (debug < 0) 14011367Ssam debug = 0; 14111367Ssam for (i = 0; i < NERRORS; i++) 14211367Ssam errors[i] = 0; 14311367Ssam fd = getdevice(); 14433648Sbostic ioctl(fd, SAIODEVDATA, &dl); 14511367Ssam printf("Device data: #cylinders=%d, #tracks=%d, #sectors=%d\n", 14633648Sbostic dl.d_ncylinders, dl.d_ntracks, dl.d_nsectors); 14725438Skarels ssdev = SSDEV(fd); 14825438Skarels if (ssdev) { 14925438Skarels ioctl(fd, SAIOSSI, (char *)0); /* set skip sector inhibit */ 15033648Sbostic dl.d_nsectors++; 15133648Sbostic dl.d_secpercyl += dl.d_ntracks; 15225438Skarels printf("(not counting skip-sector replacement)\n"); 15325438Skarels } 15433648Sbostic getrange(&dl); 15511371Ssam if (getpattern()) 15611367Ssam goto again; 15711367Ssam printf("Start formatting...make sure the drive is online\n"); 15811367Ssam ioctl(fd, SAIONOBAD, (char *)0); 15925438Skarels ioctl(fd, SAIORETRIES, (char *)0); 16025438Skarels ioctl(fd, SAIOECCLIM, (char *)maxeccbits); 16111367Ssam ioctl(fd, SAIODEBUG, (char *)debug); 16233648Sbostic tracksize = sizeof (struct sector) * dl.d_nsectors; 16333648Sbostic rtracksize = SECTSIZ * dl.d_nsectors; 16411367Ssam bp = (struct sector *)malloc(tracksize); 16515051Skarels rbp = malloc(rtracksize); 16617426Skarels pass = 0; 16717426Skarels npat = 0; 16817426Skarels more: 16917426Skarels for (; pass < maxpass; pass++) { 17015051Skarels if (severe) 17115051Skarels printf("Begin pass %d\n", pass); 17215051Skarels bufinit(bp, tracksize); 17315051Skarels if (severe) 17415051Skarels npat++; 17511367Ssam /* 17615051Skarels * Begin check, for each track, 17711367Ssam * 17815051Skarels * 1) Write header and test pattern. 17915051Skarels * 2) Read data. Hardware checks header and data ECC. 18017426Skarels * Read data (esp on Eagles) is much faster than write check. 18111367Ssam */ 18233648Sbostic sector = ((startcyl * dl.d_ntracks) + starttrack) * 18333648Sbostic dl.d_nsectors; 18433648Sbostic lastsector = ((endcyl * dl.d_ntracks) + endtrack) * 18533648Sbostic dl.d_nsectors + dl.d_nsectors; 18633648Sbostic for ( ; sector < lastsector; sector += dl.d_nsectors) { 18733648Sbostic cyl = sector / dl.d_secpercyl; 18833648Sbostic trk = ((sector % dl.d_secpercyl) / dl.d_nsectors) << 8; 18933648Sbostic for (i = 0, hdr = bp; i < dl.d_nsectors; i++, hdr++) { 19033648Sbostic hdr->header1 = cyl | HDR1_FMT22 | HDR1_OKSCT; 19133648Sbostic hdr->header2 = trk + i; 19215051Skarels } 19333648Sbostic if (sector && (sector % (dl.d_secpercyl * 50)) == 0) 19415051Skarels printf("cylinder %d\n", cyl); 19515051Skarels /* 19615051Skarels * Try and write the headers and data patterns into 19715051Skarels * each sector in the track. Continue until such 19815051Skarels * we're done, or until there's less than a sector's 19915051Skarels * worth of data to transfer. 20015051Skarels * 20115051Skarels * The lseek call is necessary because of 20215051Skarels * the odd sector size (516 bytes) 20315051Skarels */ 20415051Skarels for (resid = tracksize, cbp = bp, sn = sector;;) { 20533648Sbostic register int cc; 20611367Ssam 20733553Skarels lseek(fd, sn * SECTSIZ, L_SET); 20815051Skarels ioctl(fd, SAIOHDR, (char *)0); 20915051Skarels cc = write(fd, cbp, resid); 21015051Skarels if (cc == resid) 21115051Skarels break; 21215051Skarels /* 21315051Skarels * Don't record errors during write, 21415051Skarels * all errors will be found during 21525438Skarels * check performed below. 21615051Skarels */ 21715051Skarels sn = iob[fd - 3].i_errblk; 21815051Skarels cbp += sn - sector; 21915051Skarels resid -= (sn - sector) * sizeof (struct sector); 22015051Skarels if (resid < sizeof (struct sector)) 22115051Skarels break; 22215051Skarels } 22311367Ssam /* 22415051Skarels * Read test patterns. 22515051Skarels * Retry remainder of track on error until 22615051Skarels * we're done, or until there's less than a 22715051Skarels * sector to verify. 22811367Ssam */ 22915051Skarels for (resid = rtracksize, rcbp = rbp, sn = sector;;) { 23033648Sbostic register int cc, rsn; 23111367Ssam 23233553Skarels lseek(fd, sn * SECTSIZ, L_SET); 23315051Skarels cc = read(fd, rcbp, resid); 23415051Skarels if (cc == resid) 23515051Skarels break; 23615051Skarels sn = iob[fd-3].i_errblk; 23725438Skarels if (ssdev) { 23833648Sbostic rsn = sn - (sn / dl.d_nsectors); 23925438Skarels printf("data "); 24025438Skarels } else 24125438Skarels rsn = sn; 24225438Skarels printf("sector %d, read error\n\n", rsn); 24333648Sbostic if (recorderror(fd, sn, &dl) < 0 && pass > 0) 24415051Skarels goto out; 24515051Skarels /* advance past bad sector */ 24615051Skarels sn++; 24725438Skarels resid = rtracksize - ((sn - sector) * SECTSIZ); 24825438Skarels rcbp = rbp + ((sn - sector) * SECTSIZ); 24915051Skarels if (resid < SECTSIZ) 25015051Skarels break; 25115051Skarels } 25211367Ssam } 25311367Ssam } 25411367Ssam /* 25511367Ssam * Checking finished. 25611367Ssam */ 25715051Skarels out: 25817426Skarels if (severe && maxpass < NPT) { 25917426Skarels cp = prompt("More passes? (0 or number) "); 26017426Skarels maxpass = atoi(cp); 26117426Skarels if (maxpass > 0) { 26217426Skarels maxpass += pass; 26317426Skarels goto more; 26417426Skarels } 26517426Skarels } 26615051Skarels if (severe && nbads) { 26715051Skarels /* 26815051Skarels * Sort bads and insert in bad block table. 26915051Skarels */ 27025438Skarels qsort(bads, nbads, sizeof (daddr_t), qcompar); 27115051Skarels severe = 0; 27217426Skarels errno = 0; 27317426Skarels for (i = 0; i < nbads; i++) 27433648Sbostic recorderror(fd, bads[i], &dl); 27515051Skarels severe++; 27615051Skarels } 27711367Ssam if (errors[FE_TOTAL] || errors[FE_SSE]) { 27811367Ssam /* change the headers of all the bad sectors */ 27933648Sbostic writebb(fd, errors[FE_SSE], &sstab, &dl, SSERR); 28033648Sbostic writebb(fd, errors[FE_TOTAL], &dkbad, &dl, BSERR); 28111367Ssam } 28225438Skarels if (errors[FE_TOTAL] || errors[FE_SSE]) { 28325438Skarels printf("Errors:\n"); 28425438Skarels for (i = 0; i < NERRORS; i++) 28525438Skarels printf("%s: %d\n", errornames[i], errors[i]); 28625438Skarels printf("Total of %d hard errors revectored\n", 28725438Skarels errors[FE_TOTAL] + errors[FE_SSE]); 28825438Skarels } 28933648Sbostic if (endcyl == dl.d_ncylinders - 1 && 29033648Sbostic (startcyl < dl.d_ncylinders - 1 || starttrack == 0)) { 29125212Skarels while (errors[FE_TOTAL] < MAXBADDESC) { 29225212Skarels int i = errors[FE_TOTAL]++; 29311367Ssam 29425212Skarels dkbad.bt_bad[i].bt_cyl = -1; 29525212Skarels dkbad.bt_bad[i].bt_trksec = -1; 29625212Skarels } 29725212Skarels printf("\nWriting bad sector table at sector #%d\n", 29833648Sbostic dl.d_ncylinders * dl.d_secpercyl - dl.d_nsectors); 29925212Skarels /* place on disk */ 30033648Sbostic for (i = 0; i < 10 && i < dl.d_nsectors; i += 2) { 30133648Sbostic lseek(fd, SECTSIZ * (dl.d_ncylinders * 30233648Sbostic dl.d_secpercyl - dl.d_nsectors + i), 0); 30325212Skarels write(fd, &dkbad, sizeof (dkbad)); 30425212Skarels } 30525212Skarels } else if (errors[FE_TOTAL]) { 30625212Skarels struct bt_bad *bt; 30725212Skarels 30825212Skarels printf("New bad sectors (not added to table):\n"); 30925212Skarels bt = dkbad.bt_bad; 31025212Skarels for (i = 0; i < errors[FE_TOTAL]; i++) { 31133648Sbostic printf("bn %d (cn=%d, tn=%d, sn=%d)\n", badsn(bt, &dl), 31225212Skarels bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff); 31325212Skarels bt++; 31425212Skarels } 31511367Ssam } 31611367Ssam printf("Done\n"); 31711367Ssam ioctl(fd,SAIONOSSI,(char *)0); 31811367Ssam close(fd); 31911367Ssam #ifndef JUSTEXIT 32011367Ssam goto again; 32111367Ssam #endif 32211367Ssam } 32311367Ssam 32415051Skarels qcompar(l1, l2) 32525438Skarels register daddr_t *l1, *l2; 32615051Skarels { 32715051Skarels if (*l1 < *l2) 32815051Skarels return(-1); 32915051Skarels if (*l1 == *l2) 33015051Skarels return(0); 33115051Skarels return(1); 33215051Skarels } 33315051Skarels 33425212Skarels daddr_t 33533648Sbostic badsn(bt, lp) 33625212Skarels register struct bt_bad *bt; 33733648Sbostic register struct disklabel *lp; 33825212Skarels { 33933648Sbostic register int ssoff = ssdev ? 1 : 0; 34025438Skarels 34133648Sbostic return ((bt->bt_cyl * lp->d_ntracks + (bt->bt_trksec >> 8)) * 34233648Sbostic (lp->d_nsectors - ssoff) + (bt->bt_trksec & 0xff) - ssoff); 34325212Skarels } 34425212Skarels 34511367Ssam /* 34625212Skarels * Mark the bad/skipped sectors. 34725438Skarels * Bad sectors on skip-sector devices are assumed to be skipped also, 34825438Skarels * and must be done after the (earlier) first skipped sector. 34911367Ssam */ 35033648Sbostic writebb(fd, nsects, dbad, lp, sw) 35111367Ssam int nsects, fd; 35211367Ssam struct dkbad *dbad; 35333648Sbostic register struct disklabel *lp; 35411367Ssam { 35511367Ssam struct sector bb_buf; /* buffer for one sector plus 4 byte header */ 35611367Ssam register int i; 35711367Ssam int bn, j; 35811367Ssam struct bt_bad *btp; 35911367Ssam 36011367Ssam for (i = 0; i < nsects; i++) { 36111367Ssam btp = &dbad->bt_bad[i]; 36211367Ssam if (sw == BSERR) { 36311367Ssam bb_buf.header1 = HDR1_FMT22|btp->bt_cyl; 36425438Skarels if (ssdev) 36511367Ssam bb_buf.header1 |= HDR1_SSF; 36611367Ssam } else 36711367Ssam bb_buf.header1 = 36811367Ssam btp->bt_cyl | HDR1_FMT22 | HDR1_SSF | HDR1_OKSCT; 36911367Ssam bb_buf.header2 = btp->bt_trksec; 37033648Sbostic bn = lp->d_secpercyl * btp->bt_cyl + 37133648Sbostic lp->d_nsectors * (btp->bt_trksec >> 8) + 37215009Skarels (btp->bt_trksec & 0xff); 37333553Skarels lseek(fd, bn * SECTSIZ, L_SET); 37411367Ssam ioctl(fd, SAIOHDR, (char *)0); 37511367Ssam write(fd, &bb_buf, sizeof (bb_buf)); 37611367Ssam /* 37711367Ssam * If skip sector, mark all remaining 37811367Ssam * sectors on the track. 37911367Ssam */ 38025438Skarels if (sw == SSERR) { 38125438Skarels for (j = (btp->bt_trksec & 0xff) + 1, bn++; 38233648Sbostic j < lp->d_nsectors; j++, bn++) { 38325438Skarels bb_buf.header2 = j | (btp->bt_trksec & 0xff00); 38433553Skarels lseek(fd, bn * SECTSIZ, L_SET); 38525438Skarels ioctl(fd, SAIOHDR, (char *)0); 38625438Skarels write(fd, &bb_buf, sizeof (bb_buf)); 38725438Skarels } 38811367Ssam } 38911367Ssam } 39011367Ssam } 39111367Ssam 39211367Ssam /* 39311367Ssam * Record an error, and if there's room, put 39411367Ssam * it in the appropriate bad sector table. 39515051Skarels * 39615051Skarels * If severe burnin store block in a list after making sure 39715051Skarels * we have not already found it on a prev pass. 39811367Ssam */ 39933648Sbostic recorderror(fd, bn, lp) 40011367Ssam int fd, bn; 40133648Sbostic register struct disklabel *lp; 40211367Ssam { 40325212Skarels int cn, tn, sn; 40433648Sbostic register int i; 40511367Ssam 40615051Skarels if (severe) { 40715051Skarels for (i = 0; i < nbads; i++) 40815051Skarels if (bads[i] == bn) 40915051Skarels return(0); /* bn already flagged */ 41025438Skarels if (nbads >= (ssdev ? 2 * MAXBADDESC : MAXBADDESC)) { 41125212Skarels printf("Bad sector table full, format terminating\n"); 41215051Skarels return(-1); 41315051Skarels } 41415051Skarels bads[nbads++] = bn; 41517426Skarels if (errno < EBSE || errno > EHER) 41617426Skarels return(0); 41717426Skarels errno -= EBSE; 41817426Skarels errors[errno]++; 41915051Skarels return(0); 42015051Skarels } 42117426Skarels if (errno >= EBSE && errno <= EHER) { 42217426Skarels errno -= EBSE; 42317426Skarels errors[errno]++; 42411367Ssam } 42533648Sbostic cn = bn / lp->d_secpercyl; 42633648Sbostic sn = bn % lp->d_secpercyl; 42733648Sbostic tn = sn / lp->d_nsectors; 42833648Sbostic sn %= lp->d_nsectors; 42925438Skarels if (ssdev) { /* if drive has skip sector capability */ 43025212Skarels int ss = errors[FE_SSE]; 43111367Ssam 43225212Skarels if (errors[FE_SSE] >= MAXBADDESC) { 43325212Skarels /* this is bogus, we don't maintain skip sector table */ 43425212Skarels printf("Too many skip sector errors\n"); 43525212Skarels return(-1); 43625212Skarels } 43725212Skarels /* only one skip sector/track */ 43825212Skarels if (ss == 0 || 43925212Skarels tn != (sstab.bt_bad[ss - 1].bt_trksec >> 8) || 44025212Skarels cn != sstab.bt_bad[ss - 1].bt_cyl) { 44125438Skarels /* 44225438Skarels * Don't bother with skipping the extra sector 44325438Skarels * at the end of the track. 44425438Skarels */ 44533648Sbostic if (sn == lp->d_nsectors - 1) 44625438Skarels return(0); 44711367Ssam sstab.bt_bad[ss].bt_cyl = cn; 44811367Ssam sstab.bt_bad[ss].bt_trksec = (tn<<8) + sn; 44925212Skarels errors[FE_SSE]++; 45025212Skarels return(0); 45111367Ssam } 45211367Ssam } 45325212Skarels if (errors[FE_TOTAL] >= MAXBADDESC) { 45425212Skarels printf("Too many bad sectors\n"); 45525212Skarels return(-1); 45625212Skarels } 45711367Ssam /* record the bad sector address and continue */ 45815009Skarels dkbad.bt_bad[errors[FE_TOTAL]].bt_cyl = cn; 45911367Ssam dkbad.bt_bad[errors[FE_TOTAL]++].bt_trksec = (tn << 8) + sn; 46015051Skarels return(0); 46111367Ssam } 46211367Ssam 46311367Ssam /* 46411367Ssam * Allocate memory on a page-aligned address. 46511367Ssam * Round allocated chunk to a page multiple to 46611367Ssam * ease next request. 46711367Ssam */ 46811367Ssam char * 46911367Ssam malloc(size) 47011367Ssam int size; 47111367Ssam { 47211367Ssam char *result; 47311367Ssam static caddr_t last = 0; 47411367Ssam 47511367Ssam if (last == 0) 47611367Ssam last = (caddr_t)(((int)&end + 511) & ~0x1ff); 47711367Ssam size = (size + 511) & ~0x1ff; 47811367Ssam result = (char *)last; 47911367Ssam last += size; 48011367Ssam return (result); 48111367Ssam } 48211367Ssam 48311367Ssam /* 48411367Ssam * Prompt and verify a device name from the user. 48511367Ssam */ 48611367Ssam getdevice() 48711367Ssam { 48811367Ssam register char *cp; 48911367Ssam int fd; 49011367Ssam 49111367Ssam top: 49233553Skarels do { 493*34518Skarels printf( 494*34518Skarels "Enter device name as \"type(adaptor,controller,drive,0)\"\n"); 49533553Skarels cp = prompt("Device to format? "); 49633553Skarels } while ((fd = open(cp, 2)) < 0); 497*34518Skarels printf("Formatting %c%c drive %d on controller %d, adaptor %d: ", 498*34518Skarels cp[0], cp[1], iob[fd - 3].i_unit, 499*34518Skarels iob[fd - 3].i_ctlr, iob[fd - 3].i_adapt); 50011367Ssam cp = prompt("verify (yes/no)? "); 50111367Ssam while (*cp != 'y' && *cp != 'n') 50211367Ssam cp = prompt("Huh, yes or no? "); 50311367Ssam if (*cp == 'y') 50411367Ssam return (fd); 50511367Ssam goto top; 50611367Ssam } 50711367Ssam 50825212Skarels /* 50925212Skarels * Find range of tracks to format. 51025212Skarels */ 51133648Sbostic getrange(lp) 51233648Sbostic register struct disklabel *lp; 51325212Skarels { 51433648Sbostic startcyl = getnum("Starting cylinder", 0, lp->d_ncylinders - 1, 0); 51533648Sbostic starttrack = getnum("Starting track", 0, lp->d_ntracks - 1, 0); 51633648Sbostic endcyl = getnum("Ending cylinder", 0, lp->d_ncylinders - 1, 51733648Sbostic lp->d_ncylinders - 1); 51833648Sbostic endtrack = getnum("Ending track", 0, lp->d_ntracks - 1, 51933648Sbostic lp->d_ntracks - 1); 52025212Skarels } 52125212Skarels 52225212Skarels getnum(s, low, high, dflt) 52333648Sbostic int s, low, high, dflt; 52425212Skarels { 52525212Skarels char buf[132]; 52633648Sbostic u_int val; 52725212Skarels 52833648Sbostic for(;;) { 52925212Skarels printf("%s (%d): ", s, dflt); 53025212Skarels gets(buf); 53125212Skarels if (buf[0] == 0) 53225212Skarels return (dflt); 53325212Skarels val = atoi(buf); 53425212Skarels if (val >= low && val <= high) 53525212Skarels return ((int)val); 53625212Skarels printf("Value must be in range [%d,%d]\n", low, high); 53725212Skarels } 53825212Skarels } 53925212Skarels 54011371Ssam static struct pattern { 54111371Ssam long pa_value; 54211371Ssam char *pa_name; 54311371Ssam } pat[] = { 54411371Ssam { 0xf00ff00f, "RH750 worst case" }, 54511371Ssam { 0xec6dec6d, "media worst case" }, 54611371Ssam { 0xa5a5a5a5, "alternate 1's and 0's" }, 54717426Skarels { 0xFFFFFFFF, "Severe burnin (up to 48 passes)" }, 54811371Ssam { 0, 0 }, 54911371Ssam }; 55011371Ssam 55111371Ssam getpattern() 55211371Ssam { 55311371Ssam register struct pattern *p; 55411371Ssam int npatterns; 55511371Ssam char *cp; 55611371Ssam 55711371Ssam printf("Available test patterns are:\n"); 55811371Ssam for (p = pat; p->pa_value; p++) 55911371Ssam printf("\t%d - (%x) %s\n", (p - pat) + 1, 56011371Ssam p->pa_value & 0xffff, p->pa_name); 56111371Ssam npatterns = p - pat; 56211371Ssam cp = prompt("Pattern (one of the above, other to restart)? "); 56311371Ssam pattern = atoi(cp) - 1; 56417426Skarels if (pattern < 0 || pattern >= npatterns) 56517426Skarels return(1); 56615051Skarels severe = 0; 56717426Skarels maxpass = 1; 56817426Skarels if (pat[pattern].pa_value == -1) { 56915051Skarels severe = 1; 57017426Skarels cp = prompt("How many passes (up to 48)? "); 57117426Skarels maxpass = atoi(cp); 57217426Skarels if (maxpass > NPT) 57317426Skarels maxpass = NPT; 57417426Skarels } 57525438Skarels maxeccbits = getnum( 57625438Skarels "Maximum number of bit errors to allow for soft ECC", 57725438Skarels 0, 11, MAXECCBITS); 57817426Skarels return (0); 57911371Ssam } 58011371Ssam 58111371Ssam struct xsect { 58211371Ssam u_short hd1; 58311371Ssam u_short hd2; 58411371Ssam long buf[128]; 58511371Ssam }; 58611371Ssam 58711371Ssam /* 58811371Ssam * Initialize the buffer with the requested pattern. 58911371Ssam */ 59011371Ssam bufinit(bp, size) 59111371Ssam register struct xsect *bp; 59211371Ssam int size; 59311371Ssam { 59411371Ssam register struct pattern *pptr; 59511371Ssam register long *pp, *last; 59611371Ssam register struct xsect *lastbuf; 59715051Skarels int patt; 59811371Ssam 59911371Ssam size /= sizeof (struct sector); 60011371Ssam lastbuf = bp + size; 60115051Skarels if (severe) { 60215051Skarels patt = ppat[npat] | ((long)ppat[npat] << 16); 60315051Skarels printf("Write pattern 0x%x\n", patt&0xffff); 60415051Skarels } else { 60515051Skarels pptr = &pat[pattern]; 60615051Skarels patt = pptr->pa_value; 60715051Skarels } 60811371Ssam while (bp < lastbuf) { 60911371Ssam last = &bp->buf[128]; 61011371Ssam for (pp = bp->buf; pp < last; pp++) 61115051Skarels *pp = patt; 61211371Ssam bp++; 61311371Ssam } 61411371Ssam } 61511371Ssam 61611367Ssam char * 61711367Ssam prompt(msg) 61811367Ssam char *msg; 61911367Ssam { 62011367Ssam static char buf[132]; 62111367Ssam 62211367Ssam printf("%s", msg); 62311367Ssam gets(buf); 62411367Ssam return (buf); 62511367Ssam } 626