1: /* 2: * bad144 3: * 4: * This program prints and/or initializes a bad block record for a pack, 5: * in the format used by the DEC standard 144. 6: * 7: * BUGS: 8: * Only reads/writes the first of the bad block record (sector 0 9: * of the last track of the disk); in fact, there are copies 10: * of the information in the first 5 even numbered sectors of this 11: * track, but UNIX uses only the first, and we don't bother with the 12: * others. 13: * 14: * It is preferable to write the bad information with a standard formatter, 15: * but this program will do in a pinch, e.g. if the bad information is 16: * accidentally wiped out this is a much faster way of restoring it than 17: * reformatting. To add a new bad sector the formatter must be used in 18: * general since UNIX doesn't have on-line formatters to write the BSE 19: * error in the header. 20: */ 21: #include <whoami.h> 22: #ifndef BADSECT 23: #define BADSECT 24: #endif 25: #include <sys/types.h> 26: #include <sys/dkbad.h> 27: #include <stdio.h> 28: 29: struct diskinfo { 30: char *di_type; /* type name of disk */ 31: daddr_t di_size; /* size of entire volume in sectors */ 32: int di_nsect; /* sectors per track */ 33: int di_ntrak; /* tracks per cylinder */ 34: } diskinfo[] = { 35: "rk06", 22*3*411L, 22, 3, 36: "rk07", 22*3*815L, 22, 3, 37: "rm02", 32*5*823L, 32, 5, 38: "rm03", 32*5*823L, 32, 5, 39: "rm05", 32*19*823L, 32, 19, 40: "rp06", 22*19*815L, 22, 19, 41: "rm80", 31*14*559L, 31, 14, 42: "rp05", 22*19*411L, 22, 19, 43: "rp07", 50*32*630L, 50, 32, 44: 0, 45: }; 46: union { 47: struct dkbad bad; 48: char buf[512]; 49: } dkbad; 50: long tell(); 51: long atol(); 52: 53: main(argc, argv) 54: int argc; 55: char **argv; 56: { 57: register struct diskinfo *di; 58: register struct bt_b *bt; 59: char name[BUFSIZ]; 60: int i, f, errs; 61: daddr_t bad; 62: int toomany = 0; 63: 64: argc--, argv++; 65: if (argc < 2) { 66: fprintf(stderr, "usage: bad type disk [ snum [ bn ... ] ]\n"); 67: fprintf(stderr, "e.g.: bad rk07 hk0\n"); 68: exit(1); 69: } 70: for (di = diskinfo; di->di_type; di++) 71: if (!strcmp(di->di_type, argv[0])) 72: goto found; 73: fprintf(stderr, "%s: not a known disk type\n", argv[0]); 74: fprintf(stderr, "known types:"); 75: for (di = diskinfo; di->di_type; di++) 76: fprintf(stderr, " %s", di->di_type); 77: fprintf(stderr, "\n"); 78: exit(1); 79: found: 80: sprintf(name, "/dev/r%sh", argv[1]); 81: argc -= 2; 82: argv += 2; 83: if (argc == 0) { 84: f = open(name, 0); 85: if (f < 0) { 86: perror(name); 87: exit(1); 88: } 89: lseek(f, 512 * (di->di_size - di->di_nsect), 0); 90: printf("bad block information at 0x%X in %s:\n", 91: tell(f), name); 92: if (read(f, &dkbad, 512) != 512) { 93: fprintf(stderr, "%s: can't read bad block info (wrong type disk?)\n", name); 94: exit(1); 95: } 96: printf("cartridge serial number: %D(10)\n", dkbad.bad.bt_csn); 97: switch (dkbad.bad.bt_flag) { 98: case -1: 99: printf("alignment cartridge\n"); 100: break; 101: case 0: 102: break; 103: default: 104: printf("bt_flag=%x(16)?\n", dkbad.bad.bt_flag); 105: break; 106: } 107: bt = dkbad.bad.bt_bad; 108: for (i = 0; i < 126; i++) { 109: bad = ((daddr_t)bt->bt_cyl<<16) + bt->bt_trksec; 110: if (bad < 0) 111: break; 112: if (!toomany && i >= MAXBAD) { 113: toomany++; 114: printf("More bad sectors than system supports.\n"); 115: printf("The remainder are not being replaced automatically...\n"); 116: } 117: printf("sn=%D, cn=%d, tn=%d, sn=%d\n", 118: ((daddr_t)bt->bt_cyl*di->di_ntrak + (bt->bt_trksec>>8)) * 119: di->di_nsect + (bt->bt_trksec&0xff), 120: bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff); 121: bt++; 122: } 123: exit (0); 124: } 125: f = open(name, 1); 126: if (f < 0) { 127: perror(name); 128: exit(1); 129: } 130: dkbad.bad.bt_csn = atol(*argv++); 131: argc--; 132: dkbad.bad.bt_mbz = 0; 133: if (argc > 2 * di->di_nsect || argc > MAXBAD) { 134: printf("bad: too many bad sectors specified\n"); 135: if (argc > MAXBAD) 136: printf("system is currently configured for only %d\n", MAXBAD); 137: else 138: printf("limited to %d (only 2 tracks of sectors)\n", 139: 2 * di->di_nsect); 140: if (2 * di->di_nsect > 126) 141: printf("limited to 126 by information format\n"); 142: exit(1); 143: } 144: errs = 0; 145: i = 0; 146: while (argc > 0) { 147: long sn = atol(*argv++); 148: argc--; 149: if (sn < 0 || sn >= di->di_size) { 150: printf("%d: out of range [0,%d) for %s\n", 151: sn, di->di_size, di->di_type); 152: errs++; 153: } 154: dkbad.bad.bt_bad[i].bt_cyl = sn / (di->di_nsect*di->di_ntrak); 155: sn %= (di->di_nsect*di->di_ntrak); 156: dkbad.bad.bt_bad[i].bt_trksec = 157: ((sn/di->di_nsect) << 8) + (sn%di->di_nsect); 158: i++; 159: } 160: while (i < 126) { 161: dkbad.bad.bt_bad[i].bt_trksec = -1; 162: dkbad.bad.bt_bad[i].bt_cyl = -1; 163: i++; 164: } 165: if (errs) 166: exit(1); 167: lseek(f, 512 * (di->di_size - di->di_nsect), 0); 168: if (write(f, (caddr_t)&dkbad, 512) != 512) { 169: perror(name); 170: exit(1); 171: } 172: exit(0); 173: }