Annotation of 43BSD/etc/bad144.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 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 Regents of the University of California.\n\
                     10:  All rights reserved.\n";
                     11: #endif not lint
                     12: 
                     13: #ifndef lint
                     14: static char sccsid[] = "@(#)bad144.c   5.4 (Berkeley) 3/20/86";
                     15: #endif not lint
                     16: 
                     17: /*
                     18:  * bad144
                     19:  *
                     20:  * This program prints and/or initializes a bad block record for a pack,
                     21:  * in the format used by the DEC standard 144.
                     22:  * It can also add bad sector(s) to the record, moving the sector
                     23:  * replacements as necessary.
                     24:  *
                     25:  * It is preferable to write the bad information with a standard formatter,
                     26:  * but this program will do.
                     27:  * 
                     28:  * RP06 sectors are marked as bad by inverting the format bit in the
                     29:  * header; on other drives the valid-sector bit is cleared.
                     30:  */
                     31: #include <sys/types.h>
                     32: #include <sys/dkbad.h>
                     33: #include <sys/ioctl.h>
                     34: #include <sys/file.h>
                     35: #include <machine/dkio.h>
                     36: 
                     37: #include <stdio.h>
                     38: #include <disktab.h>
                     39: 
                     40: #define RETRIES        10              /* number of retries on reading old sectors */
                     41: 
                     42: int    fflag, add, copy, verbose, nflag;
                     43: int    compare();
                     44: struct dkbad dkbad, oldbad;
                     45: daddr_t        size, getold(), badsn();
                     46: struct disktab *dp;
                     47: char   name[BUFSIZ];
                     48: char   *malloc();
                     49: off_t  lseek();
                     50: 
                     51: main(argc, argv)
                     52:        int argc;
                     53:        char *argv[];
                     54: {
                     55:        register struct bt_bad *bt;
                     56:        daddr_t sn, bn[126];
                     57:        int i, f, nbad, new, bad, errs;
                     58: 
                     59:        argc--, argv++;
                     60:        while (argc > 0 && **argv == '-') {
                     61:                (*argv)++;
                     62:                while (**argv) {
                     63:                        switch (**argv) {
                     64:                            case 'f':
                     65:                                fflag++;
                     66:                                break;
                     67:                            case 'a':
                     68:                                add++;
                     69:                                break;
                     70:                            case 'c':
                     71:                                copy++;
                     72:                                break;
                     73:                            case 'v':
                     74:                                verbose++;
                     75:                                break;
                     76:                            case 'n':
                     77:                                nflag++;
                     78:                                verbose++;
                     79:                                break;
                     80:                        }
                     81:                        (*argv)++;
                     82:                }
                     83:                argc--, argv++;
                     84:        }
                     85:        if (argc < 2) {
                     86:                fprintf(stderr,
                     87:                  "usage: bad144 [ -f ] type disk [ snum [ bn ... ] ]\n");
                     88:                fprintf(stderr,
                     89:              "to read or overwrite bad-sector table, e.g.: bad144 rk07 hk0\n");
                     90:                fprintf(stderr,
                     91:                  "or bad144 -a [ -f ] [ -c ] type disk  bn ...\n");
                     92:                fprintf(stderr, "where options are:\n");
                     93:                fprintf(stderr, "\t-a  add new bad sectors to the table\n");
                     94:                fprintf(stderr, "\t-f  reformat listed sectors as bad\n");
                     95:                fprintf(stderr, "\t-c  copy original sector to replacement\n");
                     96:                exit(1);
                     97:        }
                     98:        dp = getdiskbyname(argv[0]);
                     99:        if (dp == NULL) {
                    100:                fprintf(stderr, "%s: unknown disk type\n", argv[0]);
                    101:                exit(1);
                    102:        }
                    103:        if (argv[1][0] != '/')
                    104:                (void)sprintf(name, "/dev/r%sc", argv[1]);
                    105:        else
                    106:                (void)strcpy(name, argv[1]);
                    107:        argc -= 2;
                    108:        argv += 2;
                    109:        size = dp->d_nsectors * dp->d_ntracks * dp->d_ncylinders; 
                    110:        if (argc == 0) {
                    111:                f = open(name, O_RDONLY);
                    112:                if (f < 0)
                    113:                        Perror(name);
                    114:                sn = getold(f, &dkbad);
                    115:                printf("bad block information at sector %d in %s:\n",
                    116:                    sn, name);
                    117:                printf("cartridge serial number: %d(10)\n", dkbad.bt_csn);
                    118:                switch (dkbad.bt_flag) {
                    119: 
                    120:                case -1:
                    121:                        printf("alignment cartridge\n");
                    122:                        break;
                    123: 
                    124:                case 0:
                    125:                        break;
                    126: 
                    127:                default:
                    128:                        printf("bt_flag=%x(16)?\n", dkbad.bt_flag);
                    129:                        break;
                    130:                }
                    131:                bt = dkbad.bt_bad;
                    132:                for (i = 0; i < 126; i++) {
                    133:                        bad = (bt->bt_cyl<<16) + bt->bt_trksec;
                    134:                        if (bad < 0)
                    135:                                break;
                    136:                        printf("sn=%d, cn=%d, tn=%d, sn=%d\n", badsn(bt),
                    137:                            bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff);
                    138:                        bt++;
                    139:                }
                    140:                (void) checkold();
                    141:                exit(0);
                    142:        }
                    143:        f = open(name, (fflag || add)? O_RDWR: O_WRONLY);
                    144:        if (f < 0)
                    145:                Perror(name);
                    146:        if (add) {
                    147:                /*
                    148:                 * Read in the old badsector table.
                    149:                 * Verify that it makes sense, and the bad sectors
                    150:                 * are in order.  Copy the old table to the new one.
                    151:                 */
                    152:                (void) getold(f, &oldbad);
                    153:                i = checkold();
                    154:                if (verbose)
                    155:                        printf("Had %d bad sectors\n", i);
                    156:                if (i + argc > 126) {
                    157:                        printf("bad144: not enough room for %d more sectors\n",
                    158:                                argc);
                    159:                        printf("limited to 126 by information format\n");
                    160:                        exit(1);
                    161:                }
                    162:                dkbad = oldbad;
                    163:        } else {
                    164:                dkbad.bt_csn = atoi(*argv++);
                    165:                argc--;
                    166:                dkbad.bt_mbz = 0;
                    167:                if (argc > 126) {
                    168:                        printf("bad144: too many bad sectors specified\n");
                    169:                        printf("limited to 126 by information format\n");
                    170:                        exit(1);
                    171:                }
                    172:                i = 0;
                    173:        }
                    174:        errs = 0;
                    175:        new = argc;
                    176:        while (argc > 0) {
                    177:                daddr_t sn = atoi(*argv++);
                    178:                argc--;
                    179:                if (sn < 0 || sn >= size) {
                    180:                        printf("%d: out of range [0,%d) for %s\n",
                    181:                            sn, size, dp->d_name);
                    182:                        errs++;
                    183:                        continue;
                    184:                }
                    185:                bn[i] = sn;
                    186:                dkbad.bt_bad[i].bt_cyl = sn / (dp->d_nsectors*dp->d_ntracks);
                    187:                sn %= (dp->d_nsectors*dp->d_ntracks);
                    188:                dkbad.bt_bad[i].bt_trksec =
                    189:                    ((sn/dp->d_nsectors) << 8) + (sn%dp->d_nsectors);
                    190:                i++;
                    191:        }
                    192:        if (errs)
                    193:                exit(1);
                    194:        nbad = i;
                    195:        while (i < 126) {
                    196:                dkbad.bt_bad[i].bt_trksec = -1;
                    197:                dkbad.bt_bad[i].bt_cyl = -1;
                    198:                i++;
                    199:        }
                    200:        if (add) {
                    201:                /*
                    202:                 * Sort the new bad sectors into the list.
                    203:                 * Then shuffle the replacement sectors so that
                    204:                 * the previous bad sectors get the same replacement data.
                    205:                 */
                    206:                qsort((char *)dkbad.bt_bad, nbad, sizeof (struct bt_bad),
                    207:                    compare);
                    208:                shift(f, nbad, nbad-new);
                    209:        }
                    210:        for (i = 0; i < 10 && i < dp->d_nsectors; i += 2) {
                    211:                if (lseek(f, dp->d_secsize * (size - dp->d_nsectors + i),
                    212:                    L_SET) < 0)
                    213:                        Perror("lseek");
                    214:                if (verbose)
                    215:                        printf("write badsect file at %d\n",
                    216:                                size - dp->d_nsectors + i);
                    217:                if (nflag == 0 &&
                    218:                    write(f, (caddr_t)&dkbad, sizeof dkbad) != sizeof dkbad) {
                    219:                        char msg[80];
                    220:                        (void)sprintf(msg, "bad144: write bad sector file %d",
                    221:                            i/2);
                    222:                        perror(msg);
                    223:                }
                    224:        }
                    225:        if (fflag)
                    226:                for (i = nbad - new; i < nbad; i++)
                    227:                        format(f, bn[i]);
                    228:        exit(0);
                    229: }
                    230: 
                    231: daddr_t
                    232: getold(f, bad)
                    233: struct dkbad *bad;
                    234: {
                    235:        register int i;
                    236:        daddr_t sn;
                    237:        char msg[80];
                    238: 
                    239:        for (i = 0; i < 10 && i < dp->d_nsectors; i += 2) {
                    240:                sn = size - dp->d_nsectors + i;
                    241:                if (lseek(f, sn * dp->d_secsize, L_SET) < 0)
                    242:                        Perror("lseek");
                    243:                if (read(f, (char *)bad, sizeof (*bad)) == sizeof (*bad)) {
                    244:                        if (i > 0)
                    245:                                printf("Using bad-sector file %d\n", i/2);
                    246:                        return(sn);
                    247:                }
                    248:                (void)sprintf(msg, "bad144: read bad sector file at sn %d",
                    249:                    sn);
                    250:                perror(msg);
                    251:        }
                    252:        fprintf(stderr,
                    253:            "bad144: %s: can't read bad block info\n", name);
                    254:        exit(1);
                    255:        /*NOTREACHED*/
                    256: }
                    257: 
                    258: checkold()
                    259: {
                    260:        register int i;
                    261:        register struct bt_bad *bt;
                    262:        daddr_t sn, lsn;
                    263:        int errors = 0, warned = 0;
                    264: 
                    265:        if (oldbad.bt_flag != 0) {
                    266:                fprintf(stderr, "bad144: %s: bad flag in bad-sector table\n",
                    267:                        name);
                    268:                errors++;
                    269:        }
                    270:        if (oldbad.bt_mbz != 0) {
                    271:                fprintf(stderr, "bad144: %s: bad magic number\n", name);
                    272:                errors++;
                    273:        }
                    274:        lsn = 0;
                    275:        bt = oldbad.bt_bad;
                    276:        for (i = 0; i < 126; i++, bt++) {
                    277:                if (bt->bt_cyl == -1 && bt->bt_trksec == -1)
                    278:                        break;
                    279:                if ((bt->bt_cyl >= dp->d_ncylinders) ||
                    280:                    ((bt->bt_trksec >> 8) >= dp->d_ntracks) ||
                    281:                    ((bt->bt_trksec & 0xff) >= dp->d_nsectors)) {
                    282:                        fprintf(stderr,
                    283:                     "bad144: cyl/trk/sect out of range in existing entry: ");
                    284:                        fprintf(stderr, "sn=%d, cn=%d, tn=%d, sn=%d\n",
                    285:                                badsn(bt), bt->bt_cyl, bt->bt_trksec>>8,
                    286:                                bt->bt_trksec & 0xff);
                    287:                        errors++;
                    288:                }
                    289:                sn = (bt->bt_cyl * dp->d_ntracks +
                    290:                    (bt->bt_trksec >> 8)) *
                    291:                    dp->d_nsectors + (bt->bt_trksec & 0xff);
                    292:                if (sn < lsn && !warned) {
                    293:                    fprintf(stderr, "bad144: bad sector file out of order\n");
                    294:                    errors++;
                    295:                    warned++;
                    296:                }
                    297:                lsn = sn;
                    298:        }
                    299:        if (errors)
                    300:                exit(1);
                    301:        return (i);
                    302: }
                    303: 
                    304: /*
                    305:  * Move the bad sector replacements
                    306:  * to make room for the new bad sectors.
                    307:  * new is the new number of bad sectors, old is the previous count.
                    308:  */
                    309: shift(f, new, old)
                    310: {
                    311:        daddr_t repl;
                    312: 
                    313:        /*
                    314:         * First replacement is last sector of second-to-last track.
                    315:         */
                    316:        repl = size - dp->d_nsectors - 1;
                    317:        new--; old--;
                    318:        while (new >= 0 && new != old) {
                    319:                if (old < 0 ||
                    320:                    compare(&dkbad.bt_bad[new], &oldbad.bt_bad[old]) > 0) {
                    321:                        /*
                    322:                         * Insert new replacement here-- copy original
                    323:                         * sector if requested and possible,
                    324:                         * otherwise write a zero block.
                    325:                         */
                    326:                        if (!copy ||
                    327:                            !blkcopy(f, badsn(&dkbad.bt_bad[new]), repl - new))
                    328:                                blkzero(f, repl - new);
                    329:                } else {
                    330:                        if (blkcopy(f, repl - old, repl - new) == 0)
                    331:                            fprintf(stderr,
                    332:                                "Can't copy replacement sector %d to %d\n",
                    333:                                repl-old, repl-new);
                    334:                        old--;
                    335:                }
                    336:                new--;
                    337:        }
                    338: }
                    339: 
                    340: char *buf;
                    341: 
                    342: /*
                    343:  *  Copy disk sector s1 to s2.
                    344:  */
                    345: blkcopy(f, s1, s2)
                    346: daddr_t s1, s2;
                    347: {
                    348:        register tries, n;
                    349: 
                    350:        if (buf == (char *)NULL) {
                    351:                buf = malloc((unsigned)dp->d_secsize);
                    352:                if (buf == (char *)NULL) {
                    353:                        fprintf(stderr, "Out of memory\n");
                    354:                        exit(20);
                    355:                }
                    356:        }
                    357:        if (lseek(f, dp->d_secsize * s1, L_SET) < 0)
                    358:                Perror("lseek");
                    359:        for (tries = 0; tries < RETRIES; tries++)
                    360:                if ((n = read(f, buf, dp->d_secsize)) == dp->d_secsize)
                    361:                        break;
                    362:        if (n != dp->d_secsize) {
                    363:                fprintf(stderr, "bad144: can't read sector, %d: ", s1);
                    364:                if (n < 0)
                    365:                        perror((char *)0);
                    366:                return(0);
                    367:        }
                    368:        if (lseek(f, dp->d_secsize * s2, L_SET) < 0)
                    369:                Perror("lseek");
                    370:        if (verbose)
                    371:                printf("copying %d to %d\n", s1, s2);
                    372:        if (nflag == 0 && write(f, buf, dp->d_secsize) != dp->d_secsize) {
                    373:                fprintf(stderr,
                    374:                    "bad144: can't write replacement sector, %d: ", s2);
                    375:                perror((char *)0);
                    376:                return(0);
                    377:        }
                    378:        return(1);
                    379: }
                    380: 
                    381: char *zbuf;
                    382: 
                    383: blkzero(f, sn)
                    384: daddr_t sn;
                    385: {
                    386: 
                    387:        if (zbuf == (char *)NULL) {
                    388:                zbuf = malloc((unsigned)dp->d_secsize);
                    389:                if (zbuf == (char *)NULL) {
                    390:                        fprintf(stderr, "Out of memory\n");
                    391:                        exit(20);
                    392:                }
                    393:        }
                    394:        if (lseek(f, dp->d_secsize * sn, L_SET) < 0)
                    395:                Perror("lseek");
                    396:        if (verbose)
                    397:                printf("zeroing %d\n", sn);
                    398:        if (nflag == 0 && write(f, zbuf, dp->d_secsize) != dp->d_secsize) {
                    399:                fprintf(stderr,
                    400:                    "bad144: can't write replacement sector, %d: ", sn);
                    401:                perror((char *)0);
                    402:        }
                    403: }
                    404: 
                    405: compare(b1, b2)
                    406: register struct bt_bad *b1, *b2;
                    407: {
                    408:        if (b1->bt_cyl > b2->bt_cyl)
                    409:                return(1);
                    410:        if (b1->bt_cyl < b2->bt_cyl)
                    411:                return(-1);
                    412:        return (b1->bt_trksec - b2->bt_trksec);
                    413: }
                    414: 
                    415: daddr_t
                    416: badsn(bt)
                    417: register struct bt_bad *bt;
                    418: {
                    419:        return ((bt->bt_cyl*dp->d_ntracks + (bt->bt_trksec>>8)) * dp->d_nsectors
                    420:                + (bt->bt_trksec&0xff));
                    421: }
                    422: 
                    423: struct rp06hdr {
                    424:        short   h_cyl;
                    425:        short   h_trksec;
                    426:        short   h_key1;
                    427:        short   h_key2;
                    428:        char    h_data[512];
                    429: #define        RP06_FMT        010000          /* 1 == 16 bit, 0 == 18 bit */
                    430: };
                    431: 
                    432: /*
                    433:  * Most massbus and unibus drives
                    434:  * have headers of this form
                    435:  */
                    436: struct hpuphdr {
                    437:        u_short hpup_cyl;
                    438:        u_char  hpup_sect;
                    439:        u_char  hpup_track;
                    440:        char    hpup_data[512];
                    441: #define        HPUP_OKSECT     0xc000          /* this normally means sector is good */
                    442: #define        HPUP_16BIT      0x1000          /* 1 == 16 bit format */
                    443: };
                    444: int rp06format(), hpupformat();
                    445: 
                    446: struct formats {
                    447:        char    *f_name;                /* disk name */
                    448:        int     f_bufsize;              /* size of sector + header */
                    449:        int     f_bic;                  /* value to bic in hpup_cyl */
                    450:        int     (*f_routine)();         /* routine for special handling */
                    451: } formats[] = {
                    452:        { "rp06",       sizeof (struct rp06hdr), RP06_FMT,      rp06format },
                    453:        { "eagle",      sizeof (struct hpuphdr), HPUP_OKSECT,   hpupformat },
                    454:        { "capricorn",  sizeof (struct hpuphdr), HPUP_OKSECT,   hpupformat },
                    455:        { "rm03",       sizeof (struct hpuphdr), HPUP_OKSECT,   hpupformat },
                    456:        { "rm05",       sizeof (struct hpuphdr), HPUP_OKSECT,   hpupformat },
                    457:        { "9300",       sizeof (struct hpuphdr), HPUP_OKSECT,   hpupformat },
                    458:        { "9766",       sizeof (struct hpuphdr), HPUP_OKSECT,   hpupformat },
                    459:        { 0, 0, 0, 0 }
                    460: };
                    461: 
                    462: /*ARGSUSED*/
                    463: hpupformat(fp, dp, blk, buf, count)
                    464:        struct formats *fp;
                    465:        struct disktab *dp;
                    466:        daddr_t blk;
                    467:        char *buf;
                    468:        int count;
                    469: {
                    470:        struct hpuphdr *hdr = (struct hpuphdr *)buf;
                    471:        int sect;
                    472: 
                    473:        if (count < sizeof(struct hpuphdr)) {
                    474:                hdr->hpup_cyl = (HPUP_OKSECT | HPUP_16BIT) |
                    475:                        (blk / (dp->d_nsectors * dp->d_ntracks));
                    476:                sect = blk % (dp->d_nsectors * dp->d_ntracks);
                    477:                hdr->hpup_track = (u_char)(sect / dp->d_nsectors);
                    478:                hdr->hpup_sect = (u_char)(sect % dp->d_nsectors);
                    479:        }
                    480:        return (0);
                    481: }
                    482: 
                    483: /*ARGSUSED*/
                    484: rp06format(fp, dp, blk, buf, count)
                    485:        struct formats *fp;
                    486:        struct disktab *dp;
                    487:        daddr_t blk;
                    488:        char *buf;
                    489:        int count;
                    490: {
                    491: 
                    492:        if (count < sizeof(struct rp06hdr)) {
                    493:                fprintf(stderr, "Can't read header on blk %d, can't reformat\n",
                    494:                        blk);
                    495:                return (-1);
                    496:        }
                    497:        return (0);
                    498: }
                    499: 
                    500: format(fd, blk)
                    501:        int fd;
                    502:        daddr_t blk;
                    503: {
                    504:        register struct formats *fp;
                    505:        static char *buf;
                    506:        static char bufsize;
                    507:        int n;
                    508: 
                    509:        for (fp = formats; fp->f_name; fp++)
                    510:                if (strcmp(dp->d_name, fp->f_name) == 0)
                    511:                        break;
                    512:        if (fp->f_name == 0) {
                    513:                fprintf(stderr, "bad144: don't know how to format %s disks\n",
                    514:                        dp->d_name);
                    515:                exit(2);
                    516:        }
                    517:        if (buf && bufsize < fp->f_bufsize) {
                    518:                free(buf);
                    519:                buf = NULL;
                    520:        }
                    521:        if (buf == NULL)
                    522:                buf = malloc((unsigned)fp->f_bufsize);
                    523:        if (buf == NULL) {
                    524:                fprintf(stderr, "bad144: can't allocate sector buffer\n");
                    525:                exit(3);
                    526:        }
                    527:        bufsize = fp->f_bufsize;
                    528:        /*
                    529:         * Here we do the actual formatting.  All we really
                    530:         * do is rewrite the sector header and flag the bad sector
                    531:         * according to the format table description.  If a special
                    532:         * purpose format routine is specified, we allow it to
                    533:         * process the sector as well.
                    534:         */
                    535:        if (lseek(fd, (long)blk * dp->d_secsize, L_SET) < 0)
                    536:                Perror("lseek");
                    537:        if (verbose)
                    538:                printf("format blk %d\n", blk);
                    539:        if (ioctl(fd, DKIOCHDR, (char *)0) < 0)
                    540:                Perror("ioctl");
                    541:        if ((n = read(fd, buf, fp->f_bufsize)) < 0)
                    542:                bzero(buf, fp->f_bufsize);
                    543:        if (fp->f_bic) {
                    544:                struct hpuphdr *xp = (struct hpuphdr *)buf;
                    545: 
                    546:                xp->hpup_cyl &= ~fp->f_bic;
                    547:        }
                    548:        if (fp->f_routine)
                    549:                if ((*fp->f_routine)(fp, dp, blk, buf, n) != 0)
                    550:                        return;
                    551:        if (lseek(fd, (long)blk * dp->d_secsize, L_SET) < 0)
                    552:                Perror("lseek");
                    553:        if (nflag)
                    554:                return;
                    555:        if (ioctl(fd, DKIOCHDR, (char *)0) < 0)
                    556:                Perror("ioctl");
                    557:        if (write(fd, buf, fp->f_bufsize) != fp->f_bufsize) {
                    558:                char msg[80];
                    559:                (void)sprintf(msg, "bad144: write format %d", blk);
                    560:                perror(msg);
                    561:        }
                    562: }
                    563: 
                    564: Perror(op)
                    565:        char *op;
                    566: {
                    567: 
                    568:        fprintf(stderr, "bad144: "); perror(op);
                    569:        exit(4);
                    570: }

unix.superglobalmegacorp.com

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