|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.