Annotation of 42BSD/sys/stand/format.c, revision 1.1.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.