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

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

unix.superglobalmegacorp.com

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