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: }

Defined functions

Perror defined in line 564; used 11 times
badsn defined in line 415; used 4 times
blkcopy defined in line 345; used 2 times
blkzero defined in line 383; used 1 times
checkold defined in line 258; used 2 times
compare defined in line 405; used 3 times
format defined in line 500; used 1 times
getold defined in line 231; used 3 times
hpupformat defined in line 463; used 7 times
main defined in line 51; never used
rp06format defined in line 484; used 2 times
shift defined in line 309; used 1 times

Defined variables

add defined in line 42; used 4 times
buf defined in line 340; used 22 times
copy defined in line 42; used 2 times
copyright defined in line 8; never used
dkbad defined in line 44; used 18 times
dp defined in line 46; used 54 times
fflag defined in line 42; used 3 times
formats defined in line 451; used 1 times
name defined in line 47; used 10 times
nflag defined in line 42; used 5 times
oldbad defined in line 44; used 6 times
sccsid defined in line 14; never used
verbose defined in line 42; used 7 times
zbuf defined in line 381; used 4 times

Defined struct's

formats defined in line 446; used 6 times
hpuphdr defined in line 436; used 22 times
rp06hdr defined in line 423; used 4 times

Defined macros

HPUP_16BIT defined in line 442; used 1 times
HPUP_OKSECT defined in line 441; used 7 times
RETRIES defined in line 40; used 1 times
RP06_FMT defined in line 429; used 1 times
Last modified: 1986-03-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2065
Valid CSS Valid XHTML 1.0 Strict