Commit | Line | Data |
---|---|---|
6cb1d6d5 SL |
1 | #ifndef lint |
2 | static char *sccsid = "@(#)bad144.c 4.5 (Berkeley) 83/06/12"; | |
3 | #endif | |
52ff80b5 BJ |
4 | |
5 | /* | |
6 | * bad144 | |
7 | * | |
8 | * This program prints and/or initializes a bad block record for a pack, | |
9 | * in the format used by the DEC standard 144. | |
10 | * | |
11 | * BUGS: | |
12 | * Only reads/writes the first of the bad block record (sector 0 | |
13 | * of the last track of the disk); in fact, there are copies | |
14 | * of the information in the first 5 even numbered sectors of this | |
15 | * track, but UNIX uses only the first, and we don't bother with the | |
16 | * others. | |
17 | * | |
18 | * It is preferable to write the bad information with a standard formatter, | |
19 | * but this program will do in a pinch, e.g. if the bad information is | |
20 | * accidentally wiped out this is a much faster way of restoring it than | |
ace59b28 SL |
21 | * reformatting. |
22 | * | |
6cb1d6d5 SL |
23 | * RP06 sectors are marked as bad by inverting the format bit in the |
24 | * header; on other drives the BSE bit is set. | |
52ff80b5 BJ |
25 | */ |
26 | #include <sys/types.h> | |
27 | #include <sys/dkbad.h> | |
ace59b28 | 28 | #include <sys/ioctl.h> |
6cb1d6d5 | 29 | #include <sys/file.h> |
ace59b28 | 30 | #include <machine/dkio.h> |
347d81fa | 31 | |
52ff80b5 | 32 | #include <stdio.h> |
347d81fa | 33 | #include <disktab.h> |
52ff80b5 | 34 | |
ace59b28 | 35 | int fflag; |
52ff80b5 BJ |
36 | struct dkbad dkbad; |
37 | ||
38 | main(argc, argv) | |
39 | int argc; | |
6cb1d6d5 | 40 | char *argv[]; |
52ff80b5 | 41 | { |
52ff80b5 | 42 | register struct bt_bad *bt; |
347d81fa | 43 | register struct disktab *dp; |
52ff80b5 | 44 | char name[BUFSIZ]; |
347d81fa | 45 | int size, i, f, bad, oldbad, errs; |
52ff80b5 BJ |
46 | |
47 | argc--, argv++; | |
ace59b28 SL |
48 | if (argc > 0 && strcmp(*argv, "-f") == 0) { |
49 | argc--, argv++; | |
50 | fflag++; | |
51 | } | |
52ff80b5 | 52 | if (argc < 2) { |
ace59b28 SL |
53 | fprintf(stderr, |
54 | "usage: bad144 [ -f ] type disk [ snum [ bn ... ] ]\n"); | |
347d81fa SL |
55 | fprintf(stderr, "e.g.: bad144 rk07 hk0\n"); |
56 | exit(1); | |
57 | } | |
58 | dp = getdiskbyname(argv[0]); | |
59 | if (dp == NULL) { | |
60 | fprintf(stderr, "%s: unknown disk type\n", argv[0]); | |
52ff80b5 BJ |
61 | exit(1); |
62 | } | |
52ff80b5 BJ |
63 | sprintf(name, "/dev/r%sc", argv[1]); |
64 | argc -= 2; | |
65 | argv += 2; | |
347d81fa | 66 | size = dp->d_nsectors * dp->d_ntracks * dp->d_ncylinders; |
52ff80b5 | 67 | if (argc == 0) { |
6cb1d6d5 SL |
68 | f = open(name, O_RDONLY); |
69 | if (f < 0) | |
70 | Perror(name); | |
71 | if (lseek(f, dp->d_secsize*(size-dp->d_nsectors), L_SET) < 0) | |
72 | Perror("lseek"); | |
52ff80b5 BJ |
73 | printf("bad block information at 0x%x in %s:\n", |
74 | tell(f), name); | |
75 | if (read(f, &dkbad, sizeof (struct dkbad)) != | |
76 | sizeof (struct dkbad)) { | |
6cb1d6d5 | 77 | fprintf("bad144: %s: can't read bad block info\n"); |
52ff80b5 BJ |
78 | exit(1); |
79 | } | |
80 | printf("cartidge serial number: %d(10)\n", dkbad.bt_csn); | |
81 | switch (dkbad.bt_flag) { | |
347d81fa | 82 | |
52ff80b5 BJ |
83 | case -1: |
84 | printf("alignment cartridge\n"); | |
85 | break; | |
347d81fa | 86 | |
52ff80b5 BJ |
87 | case 0: |
88 | break; | |
347d81fa | 89 | |
52ff80b5 BJ |
90 | default: |
91 | printf("bt_flag=%x(16)?\n", dkbad.bt_flag); | |
92 | break; | |
93 | } | |
94 | oldbad = 0; | |
95 | bt = dkbad.bt_bad; | |
96 | for (i = 0; i < 128; i++) { | |
97 | bad = (bt->bt_cyl<<16) + bt->bt_trksec; | |
98 | if (bad < 0) | |
99 | break; | |
100 | printf("sn=%d, cn=%d, tn=%d, sn=%d\n", | |
347d81fa SL |
101 | (bt->bt_cyl*dp->d_ntracks + (bt->bt_trksec>>8)) * |
102 | dp->d_nsectors + (bt->bt_trksec&0xff), | |
52ff80b5 BJ |
103 | bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff); |
104 | bt++; | |
105 | } | |
6cb1d6d5 | 106 | exit(0); |
52ff80b5 | 107 | } |
ace59b28 | 108 | f = open(name, 1 + fflag); |
6cb1d6d5 SL |
109 | if (f < 0) |
110 | Perror(name); | |
52ff80b5 BJ |
111 | dkbad.bt_csn = atoi(*argv++); |
112 | argc--; | |
67f2497d | 113 | dkbad.bt_mbz = 0; |
347d81fa SL |
114 | if (argc > 2 * dp->d_nsectors || argc > 126) { |
115 | printf("bad144: too many bad sectors specified\n"); | |
116 | if (2 * dp->d_nsectors > 126) | |
52ff80b5 BJ |
117 | printf("limited to 126 by information format\n"); |
118 | else | |
119 | printf("limited to %d (only 2 tracks of sectors)\n", | |
347d81fa | 120 | 2 * dp->d_nsectors); |
52ff80b5 BJ |
121 | exit(1); |
122 | } | |
123 | errs = 0; | |
124 | i = 0; | |
125 | while (argc > 0) { | |
126 | int sn = atoi(*argv++); | |
347d81fa | 127 | |
52ff80b5 | 128 | argc--; |
347d81fa | 129 | if (sn < 0 || sn >= size) { |
52ff80b5 | 130 | printf("%d: out of range [0,%d) for %s\n", |
347d81fa | 131 | sn, size, dp->d_name); |
52ff80b5 BJ |
132 | errs++; |
133 | } | |
347d81fa SL |
134 | dkbad.bt_bad[i].bt_cyl = sn / (dp->d_nsectors*dp->d_ntracks); |
135 | sn %= (dp->d_nsectors*dp->d_ntracks); | |
52ff80b5 | 136 | dkbad.bt_bad[i].bt_trksec = |
347d81fa | 137 | ((sn/dp->d_nsectors) << 8) + (sn%dp->d_nsectors); |
52ff80b5 BJ |
138 | i++; |
139 | } | |
140 | while (i < 126) { | |
141 | dkbad.bt_bad[i].bt_trksec = -1; | |
142 | dkbad.bt_bad[i].bt_cyl = -1; | |
143 | i++; | |
144 | } | |
145 | if (errs) | |
146 | exit(1); | |
6cb1d6d5 SL |
147 | if (lseek(f, dp->d_secsize * (size - dp->d_nsectors), L_SET) < 0) |
148 | Perror("lseek"); | |
149 | if (write(f, (caddr_t)&dkbad, sizeof (dkbad)) != sizeof (dkbad)) | |
150 | Perror(name); | |
ace59b28 SL |
151 | if (fflag) |
152 | for (i = 0, bt = dkbad.bt_bad; i < 128; i++, bt++) { | |
153 | daddr_t bn; | |
154 | ||
155 | bad = (bt->bt_cyl<<16) + bt->bt_trksec; | |
156 | if (bad < 0) | |
157 | break; | |
158 | bn = (bt->bt_cyl * dp->d_ntracks + | |
159 | (bt->bt_trksec >> 8)) * | |
160 | dp->d_nsectors + (bt->bt_trksec & 0xff); | |
161 | format(f, dp, bn); | |
162 | } | |
52ff80b5 BJ |
163 | exit(0); |
164 | } | |
ace59b28 SL |
165 | |
166 | struct rp06hdr { | |
167 | short h_cyl; | |
168 | short h_trksec; | |
169 | short h_key1; | |
170 | short h_key2; | |
171 | char h_data[512]; | |
172 | #define RP06_FMT 010000 /* 1 == 16 bit, 0 == 18 bit */ | |
173 | }; | |
6cb1d6d5 SL |
174 | |
175 | /* | |
176 | * Most massbus and unibus drives | |
177 | * have headers of this form | |
178 | */ | |
179 | struct hpuphdr { | |
180 | u_short hpup_cyl; | |
181 | u_short hpup_trksec; | |
182 | char hpup_data[512]; | |
183 | #define HPUP_OKSECT 0xc000 /* this normally means sector is good */ | |
184 | }; | |
ace59b28 SL |
185 | |
186 | struct formats { | |
187 | char *f_name; /* disk name */ | |
188 | int f_bufsize; /* size of sector + header */ | |
6cb1d6d5 | 189 | int f_bic; /* value to bic in hpup_cyl */ |
ace59b28 SL |
190 | int (*f_routine)(); /* routine for special handling */ |
191 | } formats[] = { | |
6cb1d6d5 SL |
192 | { "rp06", sizeof (struct rp06hdr), RP06_FMT, 0 }, |
193 | { "eagle", sizeof (struct hpuphdr), HPUP_OKSECT, 0 }, | |
194 | { "capricorn", sizeof (struct hpuphdr), HPUP_OKSECT, 0 }, | |
195 | { 0, 0, 0, 0 } | |
ace59b28 SL |
196 | }; |
197 | ||
198 | format(fd, dp, blk) | |
199 | int fd; | |
200 | struct disktab *dp; | |
201 | daddr_t blk; | |
202 | { | |
203 | register struct formats *fp; | |
204 | char *buf, *malloc(); | |
205 | ||
206 | for (fp = formats; fp->f_name; fp++) | |
207 | if (strcmp(dp->d_name, fp->f_name) == 0) | |
208 | break; | |
209 | if (fp->f_name == 0) { | |
210 | fprintf(stderr, "bad144: don't know how to format %s disks\n", | |
211 | dp->d_name); | |
212 | exit(2); | |
213 | } | |
214 | buf = malloc(fp->f_bufsize); | |
215 | if (buf == NULL) { | |
216 | fprintf(stderr, "bad144: can't allocate sector buffer\n"); | |
217 | exit(3); | |
218 | } | |
219 | /* | |
220 | * Here we do the actual formatting. All we really | |
221 | * do is rewrite the sector header and flag the bad sector | |
222 | * according to the format table description. If a special | |
223 | * purpose format routine is specified, we allow it to | |
224 | * process the sector as well. | |
225 | */ | |
6cb1d6d5 SL |
226 | if (lseek(fd, (long)blk * 512, L_SET) < 0) |
227 | Perror("lseek"); | |
228 | if (ioctl(fd, DKIOCHDR, 0) < 0) | |
229 | Perror("ioctl"); | |
230 | if (read(fd, buf, fp->f_bufsize) != fp->f_bufsize) | |
231 | Perror("read"); | |
232 | if (fp->f_bic) { | |
233 | struct hpuphdr *xp = (struct hpuphdr *)buf; | |
234 | ||
235 | xp->hpup_cyl &= ~fp->f_bic; | |
236 | } | |
ace59b28 SL |
237 | if (fp->f_routine) |
238 | (*fp->f_routine)(fp, dp, blk, buf); | |
6cb1d6d5 SL |
239 | if (lseek(fd, (long)blk * 512, L_SET) < 0) |
240 | Perror("lseek"); | |
241 | if (ioctl(fd, DKIOCHDR, 0) < 0) | |
242 | Perror("ioctl"); | |
243 | if (write(fd, buf, fp->f_bufsize) != fp->f_bufsize) | |
244 | Perror("write"); | |
ace59b28 SL |
245 | } |
246 | ||
6cb1d6d5 SL |
247 | Perror(op) |
248 | char *op; | |
ace59b28 SL |
249 | { |
250 | ||
6cb1d6d5 SL |
251 | fprintf(stderr, "bad144: "); perror(op); |
252 | exit(4); | |
ace59b28 | 253 | } |