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