Commit | Line | Data |
---|---|---|
761330fe | 1 | /* |
03417304 KB |
2 | * Copyright (c) 1993, 198019861988 |
3 | * The Regents of the University of California. All rights reserved. | |
bc78840a | 4 | * |
32ce521f | 5 | * %sccs.include.redist.c% |
761330fe DF |
6 | */ |
7 | ||
8 | #ifndef lint | |
03417304 KB |
9 | static char copyright[] = |
10 | "@(#) Copyright (c) 1993, 198019861988\n\ | |
11 | The Regents of the University of California. All rights reserved.\n"; | |
761330fe DF |
12 | #endif not lint |
13 | ||
6cb1d6d5 | 14 | #ifndef lint |
03417304 | 15 | static char sccsid[] = "@(#)bad144.c 8.1 (Berkeley) %G%"; |
761330fe | 16 | #endif not lint |
52ff80b5 BJ |
17 | |
18 | /* | |
19 | * bad144 | |
20 | * | |
21 | * This program prints and/or initializes a bad block record for a pack, | |
22 | * in the format used by the DEC standard 144. | |
d2b6f994 MK |
23 | * It can also add bad sector(s) to the record, moving the sector |
24 | * replacements as necessary. | |
52ff80b5 BJ |
25 | * |
26 | * It is preferable to write the bad information with a standard formatter, | |
d2b6f994 | 27 | * but this program will do. |
ace59b28 | 28 | * |
6cb1d6d5 | 29 | * RP06 sectors are marked as bad by inverting the format bit in the |
d2b6f994 | 30 | * header; on other drives the valid-sector bit is cleared. |
52ff80b5 | 31 | */ |
01de500b | 32 | #include <sys/param.h> |
52ff80b5 | 33 | #include <sys/dkbad.h> |
ace59b28 | 34 | #include <sys/ioctl.h> |
6cb1d6d5 | 35 | #include <sys/file.h> |
7abf8d65 | 36 | #include <sys/disklabel.h> |
a64be13c | 37 | #include <ufs/ffs/fs.h> |
347d81fa | 38 | |
52ff80b5 | 39 | #include <stdio.h> |
7abf8d65 | 40 | #include <paths.h> |
52ff80b5 | 41 | |
7bfa7599 | 42 | #define RETRIES 10 /* number of retries on reading old sectors */ |
ce43fbef | 43 | #define RAWPART "c" /* disk partition containing badsector tables */ |
7bfa7599 MK |
44 | |
45 | int fflag, add, copy, verbose, nflag; | |
d2b6f994 | 46 | int compare(); |
ce43fbef | 47 | int dups; |
d44874de | 48 | int badfile = -1; /* copy of badsector table to use, -1 if any */ |
01de500b | 49 | #define MAXSECSIZE 1024 |
01de500b MK |
50 | struct dkbad curbad, oldbad; |
51 | #define DKBAD_MAGIC 0 | |
01de500b MK |
52 | |
53 | char label[BBSIZE]; | |
d2b6f994 | 54 | daddr_t size, getold(), badsn(); |
01de500b | 55 | struct disklabel *dp; |
d2b6f994 | 56 | char name[BUFSIZ]; |
5d026fbb | 57 | char *malloc(); |
aef5a985 | 58 | off_t lseek(); |
52ff80b5 BJ |
59 | |
60 | main(argc, argv) | |
61 | int argc; | |
6cb1d6d5 | 62 | char *argv[]; |
52ff80b5 | 63 | { |
52ff80b5 | 64 | register struct bt_bad *bt; |
d2b6f994 MK |
65 | daddr_t sn, bn[126]; |
66 | int i, f, nbad, new, bad, errs; | |
52ff80b5 BJ |
67 | |
68 | argc--, argv++; | |
d2b6f994 MK |
69 | while (argc > 0 && **argv == '-') { |
70 | (*argv)++; | |
71 | while (**argv) { | |
72 | switch (**argv) { | |
01de500b | 73 | #if vax |
d2b6f994 MK |
74 | case 'f': |
75 | fflag++; | |
76 | break; | |
01de500b | 77 | #endif |
d2b6f994 MK |
78 | case 'a': |
79 | add++; | |
80 | break; | |
81 | case 'c': | |
82 | copy++; | |
83 | break; | |
84 | case 'v': | |
85 | verbose++; | |
86 | break; | |
7bfa7599 MK |
87 | case 'n': |
88 | nflag++; | |
aef5a985 | 89 | verbose++; |
7bfa7599 | 90 | break; |
01de500b | 91 | default: |
d44874de MK |
92 | if (**argv >= '0' && **argv <= '4') { |
93 | badfile = **argv - '0'; | |
94 | break; | |
95 | } | |
01de500b | 96 | goto usage; |
d2b6f994 MK |
97 | } |
98 | (*argv)++; | |
99 | } | |
ace59b28 | 100 | argc--, argv++; |
ace59b28 | 101 | } |
01de500b MK |
102 | if (argc < 1) { |
103 | usage: | |
ace59b28 | 104 | fprintf(stderr, |
01de500b | 105 | "usage: bad144 [ -f ] disk [ snum [ bn ... ] ]\n"); |
d2b6f994 | 106 | fprintf(stderr, |
ce43fbef | 107 | "to read or overwrite bad-sector table, e.g.: bad144 hp0\n"); |
d2b6f994 | 108 | fprintf(stderr, |
01de500b | 109 | "or bad144 -a [ -f ] [ -c ] disk bn ...\n"); |
d2b6f994 MK |
110 | fprintf(stderr, "where options are:\n"); |
111 | fprintf(stderr, "\t-a add new bad sectors to the table\n"); | |
112 | fprintf(stderr, "\t-f reformat listed sectors as bad\n"); | |
113 | fprintf(stderr, "\t-c copy original sector to replacement\n"); | |
347d81fa SL |
114 | exit(1); |
115 | } | |
01de500b | 116 | if (argv[0][0] != '/') |
7abf8d65 | 117 | (void)sprintf(name, "%s/r%s%s", _PATH_DEV, argv[0], RAWPART); |
01de500b MK |
118 | else |
119 | strcpy(name, argv[0]); | |
120 | f = open(name, argc == 1? O_RDONLY : O_RDWR); | |
121 | if (f < 0) | |
122 | Perror(name); | |
123 | if (read(f, label, sizeof(label)) < 0) | |
124 | Perror("read"); | |
125 | for (dp = (struct disklabel *)(label + LABELOFFSET); | |
126 | dp < (struct disklabel *) | |
127 | (label + sizeof(label) - sizeof(struct disklabel)); | |
128 | dp = (struct disklabel *)((char *)dp + 64)) | |
129 | if (dp->d_magic == DISKMAGIC && dp->d_magic2 == DISKMAGIC) | |
130 | break; | |
131 | if (dp->d_magic != DISKMAGIC || dp->d_magic2 != DISKMAGIC) { | |
132 | fprintf(stderr, "Bad pack magic number (pack is unlabeled)\n"); | |
52ff80b5 BJ |
133 | exit(1); |
134 | } | |
01de500b MK |
135 | if (dp->d_secsize > MAXSECSIZE || dp->d_secsize <= 0) { |
136 | fprintf(stderr, "Disk sector size too large/small (%d)\n", | |
137 | dp->d_secsize); | |
138 | exit(7); | |
139 | } | |
347d81fa | 140 | size = dp->d_nsectors * dp->d_ntracks * dp->d_ncylinders; |
01de500b MK |
141 | argc--; |
142 | argv++; | |
52ff80b5 | 143 | if (argc == 0) { |
bafbe71a | 144 | sn = getold(f, &oldbad); |
95317c9f | 145 | printf("bad block information at sector %d in %s:\n", |
d2b6f994 | 146 | sn, name); |
bafbe71a MK |
147 | printf("cartridge serial number: %d(10)\n", oldbad.bt_csn); |
148 | switch (oldbad.bt_flag) { | |
347d81fa | 149 | |
0674a1df | 150 | case (u_short)-1: |
52ff80b5 BJ |
151 | printf("alignment cartridge\n"); |
152 | break; | |
347d81fa | 153 | |
01de500b | 154 | case DKBAD_MAGIC: |
52ff80b5 | 155 | break; |
347d81fa | 156 | |
52ff80b5 | 157 | default: |
bafbe71a | 158 | printf("bt_flag=%x(16)?\n", oldbad.bt_flag); |
52ff80b5 BJ |
159 | break; |
160 | } | |
bafbe71a | 161 | bt = oldbad.bt_bad; |
d2b6f994 | 162 | for (i = 0; i < 126; i++) { |
52ff80b5 BJ |
163 | bad = (bt->bt_cyl<<16) + bt->bt_trksec; |
164 | if (bad < 0) | |
165 | break; | |
d2b6f994 | 166 | printf("sn=%d, cn=%d, tn=%d, sn=%d\n", badsn(bt), |
52ff80b5 BJ |
167 | bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff); |
168 | bt++; | |
169 | } | |
bafbe71a | 170 | (void) checkold(&oldbad); |
6cb1d6d5 | 171 | exit(0); |
52ff80b5 | 172 | } |
d2b6f994 MK |
173 | if (add) { |
174 | /* | |
175 | * Read in the old badsector table. | |
176 | * Verify that it makes sense, and the bad sectors | |
177 | * are in order. Copy the old table to the new one. | |
178 | */ | |
179 | (void) getold(f, &oldbad); | |
bafbe71a | 180 | i = checkold(&oldbad); |
d2b6f994 | 181 | if (verbose) |
01de500b | 182 | printf("Had %d bad sectors, adding %d\n", i, argc); |
d2b6f994 MK |
183 | if (i + argc > 126) { |
184 | printf("bad144: not enough room for %d more sectors\n", | |
185 | argc); | |
186 | printf("limited to 126 by information format\n"); | |
187 | exit(1); | |
188 | } | |
01de500b | 189 | curbad = oldbad; |
d2b6f994 | 190 | } else { |
01de500b | 191 | curbad.bt_csn = atoi(*argv++); |
d2b6f994 | 192 | argc--; |
01de500b MK |
193 | curbad.bt_mbz = 0; |
194 | curbad.bt_flag = DKBAD_MAGIC; | |
d2b6f994 MK |
195 | if (argc > 126) { |
196 | printf("bad144: too many bad sectors specified\n"); | |
197 | printf("limited to 126 by information format\n"); | |
198 | exit(1); | |
199 | } | |
200 | i = 0; | |
52ff80b5 BJ |
201 | } |
202 | errs = 0; | |
d2b6f994 | 203 | new = argc; |
52ff80b5 | 204 | while (argc > 0) { |
d2b6f994 | 205 | daddr_t sn = atoi(*argv++); |
52ff80b5 | 206 | argc--; |
347d81fa | 207 | if (sn < 0 || sn >= size) { |
01de500b MK |
208 | printf("%d: out of range [0,%d) for disk %s\n", |
209 | sn, size, dp->d_typename); | |
52ff80b5 | 210 | errs++; |
d2b6f994 | 211 | continue; |
52ff80b5 | 212 | } |
d2b6f994 | 213 | bn[i] = sn; |
01de500b | 214 | curbad.bt_bad[i].bt_cyl = sn / (dp->d_nsectors*dp->d_ntracks); |
347d81fa | 215 | sn %= (dp->d_nsectors*dp->d_ntracks); |
01de500b | 216 | curbad.bt_bad[i].bt_trksec = |
347d81fa | 217 | ((sn/dp->d_nsectors) << 8) + (sn%dp->d_nsectors); |
52ff80b5 BJ |
218 | i++; |
219 | } | |
d2b6f994 MK |
220 | if (errs) |
221 | exit(1); | |
222 | nbad = i; | |
52ff80b5 | 223 | while (i < 126) { |
01de500b MK |
224 | curbad.bt_bad[i].bt_trksec = -1; |
225 | curbad.bt_bad[i].bt_cyl = -1; | |
52ff80b5 BJ |
226 | i++; |
227 | } | |
d2b6f994 MK |
228 | if (add) { |
229 | /* | |
230 | * Sort the new bad sectors into the list. | |
231 | * Then shuffle the replacement sectors so that | |
232 | * the previous bad sectors get the same replacement data. | |
233 | */ | |
01de500b | 234 | qsort((char *)curbad.bt_bad, nbad, sizeof (struct bt_bad), |
aef5a985 | 235 | compare); |
ce43fbef MK |
236 | if (dups) { |
237 | fprintf(stderr, | |
238 | "bad144: bad sectors have been duplicated; can't add existing sectors\n"); | |
239 | exit(3); | |
240 | } | |
d2b6f994 MK |
241 | shift(f, nbad, nbad-new); |
242 | } | |
d44874de MK |
243 | if (badfile == -1) |
244 | i = 0; | |
245 | else | |
246 | i = badfile * 2; | |
247 | for (; i < 10 && i < dp->d_nsectors; i += 2) { | |
d2b6f994 MK |
248 | if (lseek(f, dp->d_secsize * (size - dp->d_nsectors + i), |
249 | L_SET) < 0) | |
250 | Perror("lseek"); | |
251 | if (verbose) | |
252 | printf("write badsect file at %d\n", | |
253 | size - dp->d_nsectors + i); | |
01de500b MK |
254 | if (nflag == 0 && write(f, (caddr_t)&curbad, sizeof(curbad)) != |
255 | sizeof(curbad)) { | |
d2b6f994 | 256 | char msg[80]; |
aef5a985 JL |
257 | (void)sprintf(msg, "bad144: write bad sector file %d", |
258 | i/2); | |
d2b6f994 MK |
259 | perror(msg); |
260 | } | |
d44874de MK |
261 | if (badfile != -1) |
262 | break; | |
d2b6f994 | 263 | } |
01de500b MK |
264 | #ifdef vax |
265 | if (nflag == 0 && fflag) | |
7bfa7599 | 266 | for (i = nbad - new; i < nbad; i++) |
d2b6f994 | 267 | format(f, bn[i]); |
9ffd8bdd MK |
268 | #endif |
269 | #ifdef DIOCSBAD | |
270 | if (nflag == 0 && ioctl(f, DIOCSBAD, (caddr_t)&curbad) < 0) | |
271 | fprintf(stderr, | |
272 | "Can't sync bad-sector file; reboot for changes to take effect\n"); | |
01de500b | 273 | #endif |
d2b6f994 MK |
274 | exit(0); |
275 | } | |
ace59b28 | 276 | |
d2b6f994 MK |
277 | daddr_t |
278 | getold(f, bad) | |
279 | struct dkbad *bad; | |
280 | { | |
281 | register int i; | |
282 | daddr_t sn; | |
283 | char msg[80]; | |
284 | ||
d44874de MK |
285 | if (badfile == -1) |
286 | i = 0; | |
287 | else | |
288 | i = badfile * 2; | |
289 | for (; i < 10 && i < dp->d_nsectors; i += 2) { | |
d2b6f994 MK |
290 | sn = size - dp->d_nsectors + i; |
291 | if (lseek(f, sn * dp->d_secsize, L_SET) < 0) | |
292 | Perror("lseek"); | |
01de500b | 293 | if (read(f, (char *) bad, dp->d_secsize) == dp->d_secsize) { |
d2b6f994 MK |
294 | if (i > 0) |
295 | printf("Using bad-sector file %d\n", i/2); | |
296 | return(sn); | |
ace59b28 | 297 | } |
01de500b | 298 | (void)sprintf(msg, "bad144: read bad sector file at sn %d", sn); |
d2b6f994 | 299 | perror(msg); |
d44874de MK |
300 | if (badfile != -1) |
301 | break; | |
d2b6f994 | 302 | } |
01de500b | 303 | fprintf(stderr, "bad144: %s: can't read bad block info\n", name); |
d2b6f994 | 304 | exit(1); |
aef5a985 | 305 | /*NOTREACHED*/ |
d2b6f994 MK |
306 | } |
307 | ||
308 | checkold() | |
309 | { | |
310 | register int i; | |
311 | register struct bt_bad *bt; | |
312 | daddr_t sn, lsn; | |
7bfa7599 | 313 | int errors = 0, warned = 0; |
d2b6f994 | 314 | |
01de500b | 315 | if (oldbad.bt_flag != DKBAD_MAGIC) { |
d2b6f994 MK |
316 | fprintf(stderr, "bad144: %s: bad flag in bad-sector table\n", |
317 | name); | |
7bfa7599 | 318 | errors++; |
d2b6f994 MK |
319 | } |
320 | if (oldbad.bt_mbz != 0) { | |
321 | fprintf(stderr, "bad144: %s: bad magic number\n", name); | |
7bfa7599 | 322 | errors++; |
d2b6f994 | 323 | } |
d2b6f994 MK |
324 | bt = oldbad.bt_bad; |
325 | for (i = 0; i < 126; i++, bt++) { | |
bafbe71a | 326 | if (bt->bt_cyl == 0xffff && bt->bt_trksec == 0xffff) |
d2b6f994 MK |
327 | break; |
328 | if ((bt->bt_cyl >= dp->d_ncylinders) || | |
329 | ((bt->bt_trksec >> 8) >= dp->d_ntracks) || | |
330 | ((bt->bt_trksec & 0xff) >= dp->d_nsectors)) { | |
7bfa7599 MK |
331 | fprintf(stderr, |
332 | "bad144: cyl/trk/sect out of range in existing entry: "); | |
333 | fprintf(stderr, "sn=%d, cn=%d, tn=%d, sn=%d\n", | |
334 | badsn(bt), bt->bt_cyl, bt->bt_trksec>>8, | |
335 | bt->bt_trksec & 0xff); | |
336 | errors++; | |
d2b6f994 MK |
337 | } |
338 | sn = (bt->bt_cyl * dp->d_ntracks + | |
339 | (bt->bt_trksec >> 8)) * | |
340 | dp->d_nsectors + (bt->bt_trksec & 0xff); | |
ce43fbef | 341 | if (i > 0 && sn < lsn && !warned) { |
bafbe71a MK |
342 | fprintf(stderr, |
343 | "bad144: bad sector file is out of order\n"); | |
7bfa7599 MK |
344 | errors++; |
345 | warned++; | |
d2b6f994 | 346 | } |
ce43fbef MK |
347 | if (i > 0 && sn == lsn) { |
348 | fprintf(stderr, | |
bafbe71a MK |
349 | "bad144: bad sector file contains duplicates (sn %d)\n", |
350 | sn); | |
ce43fbef MK |
351 | errors++; |
352 | } | |
d2b6f994 MK |
353 | lsn = sn; |
354 | } | |
7bfa7599 MK |
355 | if (errors) |
356 | exit(1); | |
357 | return (i); | |
d2b6f994 MK |
358 | } |
359 | ||
360 | /* | |
361 | * Move the bad sector replacements | |
362 | * to make room for the new bad sectors. | |
363 | * new is the new number of bad sectors, old is the previous count. | |
364 | */ | |
365 | shift(f, new, old) | |
366 | { | |
367 | daddr_t repl; | |
368 | ||
369 | /* | |
370 | * First replacement is last sector of second-to-last track. | |
371 | */ | |
372 | repl = size - dp->d_nsectors - 1; | |
373 | new--; old--; | |
374 | while (new >= 0 && new != old) { | |
375 | if (old < 0 || | |
01de500b | 376 | compare(&curbad.bt_bad[new], &oldbad.bt_bad[old]) > 0) { |
d2b6f994 MK |
377 | /* |
378 | * Insert new replacement here-- copy original | |
379 | * sector if requested and possible, | |
380 | * otherwise write a zero block. | |
381 | */ | |
382 | if (!copy || | |
01de500b | 383 | !blkcopy(f, badsn(&curbad.bt_bad[new]), repl - new)) |
d2b6f994 MK |
384 | blkzero(f, repl - new); |
385 | } else { | |
386 | if (blkcopy(f, repl - old, repl - new) == 0) | |
387 | fprintf(stderr, | |
388 | "Can't copy replacement sector %d to %d\n", | |
389 | repl-old, repl-new); | |
390 | old--; | |
391 | } | |
392 | new--; | |
393 | } | |
394 | } | |
395 | ||
5d026fbb MK |
396 | char *buf; |
397 | ||
d2b6f994 MK |
398 | /* |
399 | * Copy disk sector s1 to s2. | |
400 | */ | |
401 | blkcopy(f, s1, s2) | |
402 | daddr_t s1, s2; | |
403 | { | |
7bfa7599 | 404 | register tries, n; |
d2b6f994 | 405 | |
5d026fbb | 406 | if (buf == (char *)NULL) { |
aef5a985 | 407 | buf = malloc((unsigned)dp->d_secsize); |
5d026fbb MK |
408 | if (buf == (char *)NULL) { |
409 | fprintf(stderr, "Out of memory\n"); | |
410 | exit(20); | |
411 | } | |
412 | } | |
d44874de MK |
413 | for (tries = 0; tries < RETRIES; tries++) { |
414 | if (lseek(f, dp->d_secsize * s1, L_SET) < 0) | |
415 | Perror("lseek"); | |
aef5a985 | 416 | if ((n = read(f, buf, dp->d_secsize)) == dp->d_secsize) |
7bfa7599 | 417 | break; |
d44874de | 418 | } |
aef5a985 | 419 | if (n != dp->d_secsize) { |
7bfa7599 MK |
420 | fprintf(stderr, "bad144: can't read sector, %d: ", s1); |
421 | if (n < 0) | |
aef5a985 | 422 | perror((char *)0); |
d2b6f994 MK |
423 | return(0); |
424 | } | |
425 | if (lseek(f, dp->d_secsize * s2, L_SET) < 0) | |
426 | Perror("lseek"); | |
427 | if (verbose) | |
428 | printf("copying %d to %d\n", s1, s2); | |
aef5a985 | 429 | if (nflag == 0 && write(f, buf, dp->d_secsize) != dp->d_secsize) { |
d2b6f994 | 430 | fprintf(stderr, |
7bfa7599 | 431 | "bad144: can't write replacement sector, %d: ", s2); |
aef5a985 | 432 | perror((char *)0); |
d2b6f994 MK |
433 | return(0); |
434 | } | |
435 | return(1); | |
436 | } | |
437 | ||
5d026fbb | 438 | char *zbuf; |
d2b6f994 MK |
439 | |
440 | blkzero(f, sn) | |
441 | daddr_t sn; | |
442 | { | |
443 | ||
5d026fbb | 444 | if (zbuf == (char *)NULL) { |
aef5a985 | 445 | zbuf = malloc((unsigned)dp->d_secsize); |
5d026fbb MK |
446 | if (zbuf == (char *)NULL) { |
447 | fprintf(stderr, "Out of memory\n"); | |
448 | exit(20); | |
449 | } | |
450 | } | |
d2b6f994 MK |
451 | if (lseek(f, dp->d_secsize * sn, L_SET) < 0) |
452 | Perror("lseek"); | |
453 | if (verbose) | |
454 | printf("zeroing %d\n", sn); | |
aef5a985 | 455 | if (nflag == 0 && write(f, zbuf, dp->d_secsize) != dp->d_secsize) { |
d2b6f994 | 456 | fprintf(stderr, |
7bfa7599 | 457 | "bad144: can't write replacement sector, %d: ", sn); |
aef5a985 | 458 | perror((char *)0); |
d2b6f994 MK |
459 | } |
460 | } | |
461 | ||
462 | compare(b1, b2) | |
463 | register struct bt_bad *b1, *b2; | |
464 | { | |
465 | if (b1->bt_cyl > b2->bt_cyl) | |
466 | return(1); | |
467 | if (b1->bt_cyl < b2->bt_cyl) | |
468 | return(-1); | |
ce43fbef MK |
469 | if (b1->bt_trksec == b2->bt_trksec) |
470 | dups++; | |
5d026fbb | 471 | return (b1->bt_trksec - b2->bt_trksec); |
d2b6f994 MK |
472 | } |
473 | ||
474 | daddr_t | |
475 | badsn(bt) | |
476 | register struct bt_bad *bt; | |
477 | { | |
478 | return ((bt->bt_cyl*dp->d_ntracks + (bt->bt_trksec>>8)) * dp->d_nsectors | |
479 | + (bt->bt_trksec&0xff)); | |
52ff80b5 | 480 | } |
ace59b28 | 481 | |
01de500b | 482 | #ifdef vax |
01de500b | 483 | |
ace59b28 SL |
484 | struct rp06hdr { |
485 | short h_cyl; | |
486 | short h_trksec; | |
487 | short h_key1; | |
488 | short h_key2; | |
489 | char h_data[512]; | |
490 | #define RP06_FMT 010000 /* 1 == 16 bit, 0 == 18 bit */ | |
491 | }; | |
6cb1d6d5 SL |
492 | |
493 | /* | |
494 | * Most massbus and unibus drives | |
495 | * have headers of this form | |
496 | */ | |
497 | struct hpuphdr { | |
498 | u_short hpup_cyl; | |
7bfa7599 MK |
499 | u_char hpup_sect; |
500 | u_char hpup_track; | |
6cb1d6d5 SL |
501 | char hpup_data[512]; |
502 | #define HPUP_OKSECT 0xc000 /* this normally means sector is good */ | |
7bfa7599 | 503 | #define HPUP_16BIT 0x1000 /* 1 == 16 bit format */ |
6cb1d6d5 | 504 | }; |
7bfa7599 | 505 | int rp06format(), hpupformat(); |
ace59b28 SL |
506 | |
507 | struct formats { | |
508 | char *f_name; /* disk name */ | |
509 | int f_bufsize; /* size of sector + header */ | |
6cb1d6d5 | 510 | int f_bic; /* value to bic in hpup_cyl */ |
ace59b28 SL |
511 | int (*f_routine)(); /* routine for special handling */ |
512 | } formats[] = { | |
7bfa7599 MK |
513 | { "rp06", sizeof (struct rp06hdr), RP06_FMT, rp06format }, |
514 | { "eagle", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat }, | |
515 | { "capricorn", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat }, | |
516 | { "rm03", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat }, | |
517 | { "rm05", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat }, | |
518 | { "9300", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat }, | |
519 | { "9766", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat }, | |
6cb1d6d5 | 520 | { 0, 0, 0, 0 } |
ace59b28 SL |
521 | }; |
522 | ||
aef5a985 | 523 | /*ARGSUSED*/ |
7bfa7599 | 524 | hpupformat(fp, dp, blk, buf, count) |
aef5a985 | 525 | struct formats *fp; |
01de500b | 526 | struct disklabel *dp; |
7bfa7599 MK |
527 | daddr_t blk; |
528 | char *buf; | |
529 | int count; | |
530 | { | |
531 | struct hpuphdr *hdr = (struct hpuphdr *)buf; | |
532 | int sect; | |
533 | ||
534 | if (count < sizeof(struct hpuphdr)) { | |
535 | hdr->hpup_cyl = (HPUP_OKSECT | HPUP_16BIT) | | |
536 | (blk / (dp->d_nsectors * dp->d_ntracks)); | |
537 | sect = blk % (dp->d_nsectors * dp->d_ntracks); | |
538 | hdr->hpup_track = (u_char)(sect / dp->d_nsectors); | |
539 | hdr->hpup_sect = (u_char)(sect % dp->d_nsectors); | |
540 | } | |
541 | return (0); | |
542 | } | |
543 | ||
aef5a985 | 544 | /*ARGSUSED*/ |
7bfa7599 | 545 | rp06format(fp, dp, blk, buf, count) |
aef5a985 | 546 | struct formats *fp; |
01de500b | 547 | struct disklabel *dp; |
7bfa7599 MK |
548 | daddr_t blk; |
549 | char *buf; | |
550 | int count; | |
551 | { | |
552 | ||
553 | if (count < sizeof(struct rp06hdr)) { | |
554 | fprintf(stderr, "Can't read header on blk %d, can't reformat\n", | |
555 | blk); | |
556 | return (-1); | |
557 | } | |
558 | return (0); | |
559 | } | |
560 | ||
d2b6f994 | 561 | format(fd, blk) |
ace59b28 | 562 | int fd; |
ace59b28 SL |
563 | daddr_t blk; |
564 | { | |
565 | register struct formats *fp; | |
7bfa7599 MK |
566 | static char *buf; |
567 | static char bufsize; | |
9ffd8bdd | 568 | struct format_op fop; |
7bfa7599 | 569 | int n; |
ace59b28 SL |
570 | |
571 | for (fp = formats; fp->f_name; fp++) | |
01de500b | 572 | if (strcmp(dp->d_typename, fp->f_name) == 0) |
ace59b28 SL |
573 | break; |
574 | if (fp->f_name == 0) { | |
575 | fprintf(stderr, "bad144: don't know how to format %s disks\n", | |
01de500b | 576 | dp->d_typename); |
ace59b28 SL |
577 | exit(2); |
578 | } | |
7bfa7599 MK |
579 | if (buf && bufsize < fp->f_bufsize) { |
580 | free(buf); | |
581 | buf = NULL; | |
582 | } | |
583 | if (buf == NULL) | |
aef5a985 | 584 | buf = malloc((unsigned)fp->f_bufsize); |
ace59b28 SL |
585 | if (buf == NULL) { |
586 | fprintf(stderr, "bad144: can't allocate sector buffer\n"); | |
587 | exit(3); | |
588 | } | |
7bfa7599 | 589 | bufsize = fp->f_bufsize; |
ace59b28 SL |
590 | /* |
591 | * Here we do the actual formatting. All we really | |
592 | * do is rewrite the sector header and flag the bad sector | |
593 | * according to the format table description. If a special | |
594 | * purpose format routine is specified, we allow it to | |
595 | * process the sector as well. | |
596 | */ | |
d2b6f994 MK |
597 | if (verbose) |
598 | printf("format blk %d\n", blk); | |
9ffd8bdd MK |
599 | bzero((char *)&fop, sizeof(fop)); |
600 | fop.df_buf = buf; | |
601 | fop.df_count = fp->f_bufsize; | |
602 | fop.df_startblk = blk; | |
603 | bzero(buf, fp->f_bufsize); | |
604 | if (ioctl(fd, DIOCRFORMAT, &fop) < 0) | |
605 | perror("bad144: read format"); | |
606 | if (fp->f_routine && | |
607 | (*fp->f_routine)(fp, dp, blk, buf, fop.df_count) != 0) | |
608 | return; | |
6cb1d6d5 SL |
609 | if (fp->f_bic) { |
610 | struct hpuphdr *xp = (struct hpuphdr *)buf; | |
611 | ||
612 | xp->hpup_cyl &= ~fp->f_bic; | |
613 | } | |
7bfa7599 MK |
614 | if (nflag) |
615 | return; | |
9ffd8bdd MK |
616 | bzero((char *)&fop, sizeof(fop)); |
617 | fop.df_buf = buf; | |
618 | fop.df_count = fp->f_bufsize; | |
619 | fop.df_startblk = blk; | |
620 | if (ioctl(fd, DIOCWFORMAT, &fop) < 0) | |
621 | Perror("write format"); | |
622 | if (fop.df_count != fp->f_bufsize) { | |
d2b6f994 | 623 | char msg[80]; |
aef5a985 | 624 | (void)sprintf(msg, "bad144: write format %d", blk); |
d2b6f994 MK |
625 | perror(msg); |
626 | } | |
ace59b28 | 627 | } |
01de500b | 628 | #endif |
ace59b28 | 629 | |
6cb1d6d5 SL |
630 | Perror(op) |
631 | char *op; | |
ace59b28 SL |
632 | { |
633 | ||
6cb1d6d5 SL |
634 | fprintf(stderr, "bad144: "); perror(op); |
635 | exit(4); | |
ace59b28 | 636 | } |