Annotation of 42BSD/sys/stand/format.c, revision 1.1

1.1     ! root        1: /*     format.c        6.3     83/09/23        */
        !             2: 
        !             3: 
        !             4: /* 
        !             5:  * Standalone program to do media checking
        !             6:  * and record bad block information on any 
        !             7:  * disk with the appropriate driver and RM03-style headers.
        !             8:  */
        !             9: #include "../h/param.h"
        !            10: #include "../h/fs.h"
        !            11: #include "../h/inode.h"
        !            12: #include "../h/dkbad.h"
        !            13: #include "../h/vmmac.h"
        !            14: 
        !            15: #include "saio.h"
        !            16: #include "savax.h"
        !            17: 
        !            18: #define MAXBADDESC     126             /* size of bad block table */
        !            19: #define CHUNK          48              /* max # of sectors/io operation */
        !            20: #define SECTSIZ                512             /* standard sector size */
        !            21: #define HDRSIZ         4               /* number of bytes in sector header */
        !            22: 
        !            23: #define SSERR          0
        !            24: #define BSERR          1
        !            25: 
        !            26: #define SSDEV          ((ioctl(iob[fd-3], SAIOSSDEV, (char *)0) == 0))
        !            27: 
        !            28: struct sector {
        !            29:        u_short header1;
        !            30:        u_short header2;
        !            31:        char    buf[SECTSIZ];
        !            32: };
        !            33: 
        !            34: struct dkbad dkbad;            /* bad sector table */
        !            35: struct dkbad sstab;            /* skip sector table */
        !            36: 
        !            37: #define        NERRORS         6
        !            38: static char *
        !            39: errornames[NERRORS] = {
        !            40: #define        FE_BSE          0
        !            41:        "Bad sector",
        !            42: #define        FE_WCE          1
        !            43:        "Write check",
        !            44: #define        FE_ECC          2
        !            45:        "ECC",
        !            46: #define        FE_HARD         3
        !            47:        "Other hard",
        !            48: #define        FE_TOTAL        4
        !            49:        "Total",
        !            50: #define        FE_SSE          5
        !            51:        "Skip sector",
        !            52: };
        !            53: 
        !            54: int    errors[NERRORS];        /* histogram of errors */
        !            55: int    pattern;
        !            56: 
        !            57: /*
        !            58:  * Purdue/EE severe burnin patterns.
        !            59:  */
        !            60: unsigned short ppat[] = {
        !            61: 0031463,0070707,0133333,0155555,0161616,0143434,
        !            62: 0107070,0016161,0034343,0044444,0022222,0111111,0125252, 052525,
        !            63: 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252,
        !            64: #ifndef        SHORTPASS
        !            65: 0125252,0125252,0125252,0125252,0125252,0125252,0125252,0125252,
        !            66:  052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525,
        !            67: #endif
        !            68:  052525, 052525, 052525, 052525, 052525, 052525, 052525, 052525
        !            69:  };
        !            70: 
        !            71: #define        NPT     (sizeof (ppat) / sizeof (short))
        !            72: int    npat;           /* subscript to ppat[] */
        !            73: int    severe;         /* nz if running "severe" burnin */
        !            74: int    nbads;          /* subscript for bads */
        !            75: long   bads[MAXBADDESC]; /* Bad blocks accumulated */
        !            76: 
        !            77: char   *malloc();
        !            78: int    qcompar();
        !            79: char   *prompt();
        !            80: extern int end;
        !            81: 
        !            82: main()
        !            83: {
        !            84:        register int sector, sn;
        !            85:        int lastsector, tracksize, rtracksize;
        !            86:        int unit, fd, resid, i, trk, cyl, debug;
        !            87:        struct st st;
        !            88:        struct sector *bp, *cbp;
        !            89:        char *rbp, *rcbp;
        !            90:        int pass, maxpass;
        !            91:        char *cp;
        !            92: 
        !            93:        printf("Disk format/check utility\n\n");
        !            94: 
        !            95: again:
        !            96:        nbads = 0;
        !            97:        cp = prompt("Enable debugging (0=none, 1=bse, 2=ecc, 3=bse+ecc)? ");
        !            98:        debug = atoi(cp);
        !            99:        if (debug < 0)
        !           100:                debug = 0;
        !           101:        for (i = 0; i < NERRORS; i++)
        !           102:                errors[i] = 0;
        !           103:        fd = getdevice();
        !           104:        ioctl(fd, SAIODEVDATA, &st);
        !           105:        printf("Device data: #cylinders=%d, #tracks=%d, #sectors=%d\n",
        !           106:          st.ncyl, st.ntrak, st.nsect);
        !           107:        if (getpattern())
        !           108:                goto again;
        !           109:        printf("Start formatting...make sure the drive is online\n");
        !           110:        if (severe)
        !           111:                ioctl(fd, SAIOSEVRE, (char *) 0);
        !           112:        ioctl(fd, SAIONOBAD, (char *)0);
        !           113:        ioctl(fd, SAIOECCLIM, (char *)0);
        !           114:        ioctl(fd, SAIODEBUG, (char *)debug);
        !           115:        if (SSDEV) {
        !           116:                if (severe) {
        !           117:                        printf("Severe burnin doesn't work with RM80 yet\n");
        !           118:                        exit(1);
        !           119:                }
        !           120:                ioctl(fd, SAIOSSI, (char *)0);  /* set skip sector inhibit */
        !           121:                st.nsect++;
        !           122:                st.nspc += st.ntrak;
        !           123:        }
        !           124:        tracksize = sizeof (struct sector) * st.nsect;
        !           125:        rtracksize = SECTSIZ * st.nsect;
        !           126:        bp = (struct sector *)malloc(tracksize);
        !           127:        rbp = malloc(rtracksize);
        !           128:        if (severe) {
        !           129:                npat = 0;
        !           130:                maxpass = NPT;
        !           131:        } else
        !           132:                maxpass = 1;
        !           133:        for (pass = 0; pass < maxpass; pass++) {
        !           134:                if (severe)
        !           135:                        printf("Begin pass %d\n", pass);
        !           136:                bufinit(bp, tracksize);
        !           137:                if (severe)
        !           138:                        npat++;
        !           139:                /*
        !           140:                 * Begin check, for each track,
        !           141:                 *
        !           142:                 * 1) Write header and test pattern.
        !           143:                 * 2) Read data.  Hardware checks header and data ECC.
        !           144:                 *    Read data (esp on Eagles) is much faster when write check.
        !           145:                 */
        !           146:                lastsector = st.nspc * st.ncyl;
        !           147:                for (sector = 0; sector < lastsector; sector += st.nsect) {
        !           148:                        cyl = sector / st.nspc;
        !           149:                        trk = (sector % st.nspc) / st.nsect;
        !           150:                        for (i = 0; i < st.nsect; i++) {
        !           151:                                bp[i].header1 =
        !           152:                                        (u_short) cyl | HDR1_FMT22 | HDR1_OKSCT;
        !           153:                                bp[i].header2 = ((u_short)trk << 8) + i;
        !           154:                        }
        !           155:                        if (sector && (sector % (st.nspc * 100)) == 0)
        !           156:                                printf("cylinder %d\n", cyl);
        !           157:                        /*
        !           158:                         * Try and write the headers and data patterns into
        !           159:                         * each sector in the track.  Continue until such
        !           160:                         * we're done, or until there's less than a sector's
        !           161:                         * worth of data to transfer.
        !           162:                         *
        !           163:                         * The lseek call is necessary because of
        !           164:                         * the odd sector size (516 bytes)
        !           165:                         */
        !           166:                        for (resid = tracksize, cbp = bp, sn = sector;;) {
        !           167:                                int cc;
        !           168: 
        !           169:                                lseek(fd, sn * SECTSIZ, 0);
        !           170:                                ioctl(fd, SAIOHDR, (char *)0);
        !           171:                                cc = write(fd, cbp, resid);
        !           172:                                if (cc == resid)
        !           173:                                        break;
        !           174:                                /*
        !           175:                                 * Don't record errors during write,
        !           176:                                 * all errors will be found during
        !           177:                                 * writecheck performed below.
        !           178:                                 */
        !           179:                                sn = iob[fd - 3].i_errblk;
        !           180:                                cbp += sn - sector;
        !           181:                                resid -= (sn - sector) * sizeof (struct sector);
        !           182:                                if (resid < sizeof (struct sector)) 
        !           183:                                        break;
        !           184:                        }
        !           185:                        /*
        !           186:                         * Read test patterns.
        !           187:                         * Retry remainder of track on error until
        !           188:                         * we're done, or until there's less than a
        !           189:                         * sector to verify.
        !           190:                         */
        !           191:                        for (resid = rtracksize, rcbp = rbp, sn = sector;;) {
        !           192:                                int cc;
        !           193: 
        !           194:                                lseek(fd, sn * SECTSIZ, 0);
        !           195:                                cc = read(fd, rcbp, resid);
        !           196:                                if (cc == resid)
        !           197:                                        break;
        !           198:                                sn = iob[fd-3].i_errblk;
        !           199:                                printf("sector %d, read error\n", sn);
        !           200:                                if (recorderror(fd, sn, &st) < 0 && pass > 0)
        !           201:                                        goto out;
        !           202:                                /* advance past bad sector */
        !           203:                                sn++;
        !           204:                                rcbp += sn - sector;
        !           205:                                resid -= ((sn - sector) * SECTSIZ);
        !           206:                                if (resid < SECTSIZ) 
        !           207:                                        break;
        !           208:                        }
        !           209:                }
        !           210:        }
        !           211:        /*
        !           212:         * Checking finished.
        !           213:         */
        !           214: out:
        !           215:        if (severe && nbads) {
        !           216:                /*
        !           217:                 * Sort bads and insert in bad block table.
        !           218:                 */
        !           219:                qsort(bads, nbads, sizeof (long), qcompar);
        !           220:                severe = 0;
        !           221:                for (i = 0; i < nbads; i++) {
        !           222:                        errno = EECC;   /* for now */
        !           223:                        recorderror(fd, bads[i], &st);
        !           224:                }
        !           225:                severe++;
        !           226:        }
        !           227:        if (errors[FE_TOTAL] || errors[FE_SSE]) {
        !           228:                printf("Errors:\n");
        !           229:                for (i = 0; i < NERRORS; i++)
        !           230:                        printf("%s: %d\n", errornames[i], errors[i]);
        !           231:                printf("Total of %d hard errors found\n",
        !           232:                        errors[FE_TOTAL] + errors[FE_SSE]);
        !           233:                /* change the headers of all the bad sectors */
        !           234:                writebb(fd, errors[FE_SSE], &sstab, &st, SSERR);
        !           235:                writebb(fd, errors[FE_TOTAL], &dkbad, &st, BSERR);
        !           236:        }
        !           237:        while (errors[FE_TOTAL] < MAXBADDESC) {
        !           238:                int i = errors[FE_TOTAL]++;
        !           239: 
        !           240:                dkbad.bt_bad[i].bt_cyl = -1;
        !           241:                dkbad.bt_bad[i].bt_trksec = -1;
        !           242:        }
        !           243:        printf("\nWriting bad sector table at sector #%d\n",
        !           244:                st.ncyl * st.nspc - st.nsect);
        !           245:        /* place on disk */
        !           246:        for (i = 0; i < 10; i += 2) {
        !           247:                lseek(fd, SECTSIZ * (st.ncyl * st.nspc - st.nsect + i), 0);
        !           248:                write(fd, &dkbad, sizeof (dkbad));
        !           249:        }
        !           250:        printf("Done\n");
        !           251:        ioctl(fd,SAIONOSSI,(char *)0);
        !           252:        close(fd);
        !           253: /*
        !           254:        if (severe) {
        !           255:                asm("halt");
        !           256:                exit(0);
        !           257:        }
        !           258: */
        !           259: #ifndef JUSTEXIT
        !           260:        goto again;
        !           261: #endif
        !           262: }
        !           263: 
        !           264: qcompar(l1, l2)
        !           265: register long *l1, *l2;
        !           266: {
        !           267:        if (*l1 < *l2)
        !           268:                return(-1);
        !           269:        if (*l1 == *l2)
        !           270:                return(0);
        !           271:        return(1);
        !           272: }
        !           273: 
        !           274: /*
        !           275:  * Write out the bad blocks.
        !           276:  */
        !           277: writebb(fd, nsects, dbad, st, sw)
        !           278:        int nsects, fd;
        !           279:        struct dkbad *dbad;
        !           280:        register struct st *st;
        !           281: {
        !           282:        struct sector bb_buf; /* buffer for one sector plus 4 byte header */
        !           283:        register int i;
        !           284:        int bn, j;
        !           285:        struct bt_bad *btp;
        !           286: 
        !           287:        for (i = 0; i < nsects; i++) {
        !           288:                btp = &dbad->bt_bad[i];
        !           289:                if (sw == BSERR) {
        !           290:                        bb_buf.header1 = HDR1_FMT22|btp->bt_cyl;
        !           291:                        if (SSDEV)
        !           292:                                bb_buf.header1 |= HDR1_SSF;
        !           293:                } else
        !           294:                        bb_buf.header1 =
        !           295:                               btp->bt_cyl | HDR1_FMT22 | HDR1_SSF | HDR1_OKSCT;
        !           296:                bb_buf.header2 = btp->bt_trksec;
        !           297:                bn = st->nspc * btp->bt_cyl +
        !           298:                     st->nsect * (btp->bt_trksec >> 8) +
        !           299:                     (btp->bt_trksec & 0xff);
        !           300:                lseek(fd, bn * SECTSIZ, 0);
        !           301:                ioctl(fd, SAIOHDR, (char *)0);
        !           302:                write(fd, &bb_buf, sizeof (bb_buf));
        !           303:                if (!SSDEV)
        !           304:                        continue;
        !           305:                /*
        !           306:                 * If skip sector, mark all remaining
        !           307:                 * sectors on the track.
        !           308:                 */
        !           309:                for (j = (btp->bt_trksec & 0xff) + 1; j < st->nsect; j++) {
        !           310:                        bb_buf.header1 = j | HDR1_FMT22 | HDR1_SSF;
        !           311:                        ioctl(fd, SAIOHDR, (char *)0);
        !           312:                        write(fd, &bb_buf, sizeof (bb_buf));
        !           313:                }
        !           314:        }
        !           315: }
        !           316: 
        !           317: /*
        !           318:  * Record an error, and if there's room, put
        !           319:  * it in the appropriate bad sector table.
        !           320:  *
        !           321:  * If severe burnin store block in a list after making sure
        !           322:  * we have not already found it on a prev pass.
        !           323:  */
        !           324: recorderror(fd, bn, st)
        !           325:        int fd, bn;
        !           326:        register struct st *st;
        !           327: {
        !           328:        int cn, tn, sn, strk;
        !           329:        register i;
        !           330: 
        !           331:        
        !           332:        if (severe) {
        !           333:                for (i = 0; i < nbads; i++)
        !           334:                        if (bads[i] == bn)
        !           335:                                return(0);      /* bn already flagged */
        !           336:                if (nbads >= MAXBADDESC) {
        !           337:                        printf("Bad sector table full, burnin terminating\n");
        !           338:                        return(-1);
        !           339:                }
        !           340:                bads[nbads++] = bn;
        !           341:                return(0);
        !           342:        }
        !           343:        if (errors[FE_TOTAL] >= MAXBADDESC) {
        !           344:                printf("Too many bad sectors\n");
        !           345:                return(-1);
        !           346:        }
        !           347:        if (errors[FE_SSE] >= MAXBADDESC) {
        !           348:                printf("Too many skip sector errors\n");
        !           349:                return(-1);
        !           350:        }
        !           351:        if (errno < EBSE || errno > EHER)
        !           352:                return(0);
        !           353:        errno -= EBSE;
        !           354:        errors[errno]++;
        !           355:        cn = bn / st->nspc;
        !           356:        sn = bn % st->nspc;
        !           357:        tn = sn / st->nsect;
        !           358:        sn %= st->nsect;
        !           359:        if (SSDEV) {            /* if drive has skip sector capability */
        !           360:                int ss = errors[FE_SSE]++;
        !           361: 
        !           362:                if (ss)
        !           363:                        strk = sstab.bt_bad[ss - 1].bt_trksec >> 8;
        !           364:                else
        !           365:                        strk = -1;
        !           366:                if (tn != strk) {         /* only one skip sector/track */
        !           367:                        sstab.bt_bad[ss].bt_cyl = cn;
        !           368:                        sstab.bt_bad[ss].bt_trksec = (tn<<8) + sn;
        !           369:                        return;
        !           370:                }
        !           371:                cn = -cn;
        !           372:        }
        !           373:        /* record the bad sector address and continue */
        !           374:        dkbad.bt_bad[errors[FE_TOTAL]].bt_cyl = cn;
        !           375:        dkbad.bt_bad[errors[FE_TOTAL]++].bt_trksec = (tn << 8) + sn;
        !           376:        return(0);
        !           377: }
        !           378: 
        !           379: /*
        !           380:  * Allocate memory on a page-aligned address.
        !           381:  * Round allocated chunk to a page multiple to
        !           382:  * ease next request.
        !           383:  */
        !           384: char *
        !           385: malloc(size)
        !           386:        int size;
        !           387: {
        !           388:        char *result;
        !           389:        static caddr_t last = 0;
        !           390: 
        !           391:        if (last == 0)
        !           392:                last = (caddr_t)(((int)&end + 511) & ~0x1ff);
        !           393:        size = (size + 511) & ~0x1ff;
        !           394:        result = (char *)last;
        !           395:        last += size;
        !           396:        return (result);
        !           397: }
        !           398: 
        !           399: /*
        !           400:  * Prompt and verify a device name from the user.
        !           401:  */
        !           402: getdevice()
        !           403: {
        !           404:        register char *cp;
        !           405:        register struct devsw *dp;
        !           406:        int fd;
        !           407: 
        !           408: top:
        !           409:        cp = prompt("Device to format? ");
        !           410:        if ((fd = open(cp, 2)) < 0) {
        !           411:                printf("Known devices are: ");
        !           412:                for (dp = devsw; dp->dv_name; dp++)
        !           413:                        printf("%s ",dp->dv_name);
        !           414:                printf("\n");
        !           415:                goto top;
        !           416:        }
        !           417:        printf("Formatting drive %c%c%d on adaptor %d: ",
        !           418:                cp[0], cp[1], iob[fd - 3].i_unit % 8, iob[fd - 3].i_unit / 8);
        !           419:        cp = prompt("verify (yes/no)? ");
        !           420:        while (*cp != 'y' && *cp != 'n')
        !           421:                cp = prompt("Huh, yes or no? ");
        !           422:        if (*cp == 'y')
        !           423:                return (fd);
        !           424:        goto top;
        !           425: }
        !           426: 
        !           427: static struct pattern {
        !           428:        long    pa_value;
        !           429:        char    *pa_name;
        !           430: } pat[] = {
        !           431:        { 0xf00ff00f,   "RH750 worst case" },
        !           432:        { 0xec6dec6d,   "media worst case" },
        !           433:        { 0xa5a5a5a5,   "alternate 1's and 0's" },
        !           434:        { 0xFFFFFFFF,   "Severe burnin (takes several hours)" },
        !           435:        { 0, 0 },
        !           436: };
        !           437: 
        !           438: getpattern()
        !           439: {
        !           440:        register struct pattern *p;
        !           441:        int npatterns;
        !           442:        char *cp;
        !           443: 
        !           444:        printf("Available test patterns are:\n");
        !           445:        for (p = pat; p->pa_value; p++)
        !           446:                printf("\t%d - (%x) %s\n", (p - pat) + 1,
        !           447:                  p->pa_value & 0xffff, p->pa_name);
        !           448:        npatterns = p - pat;
        !           449:        cp = prompt("Pattern (one of the above, other to restart)? ");
        !           450:        pattern = atoi(cp) - 1;
        !           451:        severe = 0;
        !           452:        if (pat[pattern].pa_value == -1)
        !           453:                severe = 1;
        !           454:        return (pattern < 0 || pattern >= npatterns);
        !           455: }
        !           456: 
        !           457: struct xsect {
        !           458:        u_short hd1;
        !           459:        u_short hd2;
        !           460:        long    buf[128];
        !           461: };
        !           462: 
        !           463: /*
        !           464:  * Initialize the buffer with the requested pattern. 
        !           465:  */
        !           466: bufinit(bp, size)
        !           467:        register struct xsect *bp;
        !           468:        int size;
        !           469: {
        !           470:        register struct pattern *pptr;
        !           471:        register long *pp, *last;
        !           472:        register struct xsect *lastbuf;
        !           473:        int patt;
        !           474: 
        !           475:        size /= sizeof (struct sector);
        !           476:        lastbuf = bp + size;
        !           477:        if (severe) {
        !           478:                patt = ppat[npat] | ((long)ppat[npat] << 16);
        !           479:                printf("Write pattern 0x%x\n", patt&0xffff);
        !           480:        } else {
        !           481:                pptr = &pat[pattern];
        !           482:                patt = pptr->pa_value;
        !           483:        }
        !           484:        while (bp < lastbuf) {
        !           485:                last = &bp->buf[128];
        !           486:                for (pp = bp->buf; pp < last; pp++)
        !           487:                        *pp = patt;
        !           488:                bp++;
        !           489:        }
        !           490: }
        !           491: 
        !           492: char *
        !           493: prompt(msg)
        !           494:        char *msg;
        !           495: {
        !           496:        static char buf[132];
        !           497: 
        !           498:        printf("%s", msg);
        !           499:        gets(buf);
        !           500:        return (buf);
        !           501: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.