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