If a directory's not created, emit a warning as usual but still set its modes.
[unix-history] / usr.sbin / bad144 / bad144.c
CommitLineData
15637ed4
RG
1/*
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, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35char copyright[] =
36"@(#) Copyright (c) 1980,1986,1988 Regents of the University of California.\n\
37 All rights reserved.\n";
38#endif not lint
39
40#ifndef lint
41static char sccsid[] = "@(#)bad144.c 5.19 (Berkeley) 4/11/91";
42#endif not lint
43
44/*
45 * bad144
46 *
47 * This program prints and/or initializes a bad block record for a pack,
48 * in the format used by the DEC standard 144.
49 * It can also add bad sector(s) to the record, moving the sector
50 * replacements as necessary.
51 *
52 * It is preferable to write the bad information with a standard formatter,
53 * but this program will do.
54 *
55 * RP06 sectors are marked as bad by inverting the format bit in the
56 * header; on other drives the valid-sector bit is cleared.
57 */
1148d35e
AM
58
59#define DKTYPENAMES
60
15637ed4
RG
61#include <sys/param.h>
62#include <sys/dkbad.h>
63#include <sys/ioctl.h>
64#include <ufs/fs.h>
65#include <sys/file.h>
66#include <sys/disklabel.h>
67
68#include <stdio.h>
69#include <paths.h>
1148d35e 70#include <string.h>
15637ed4
RG
71
72#define RETRIES 10 /* number of retries on reading old sectors */
73#ifdef __386BSD__
74#define RAWPART "d" /* disk partition containing badsector tables */
75#else
76#define RAWPART "c" /* disk partition containing badsector tables */
77#endif
78
1148d35e 79int fflag, add, copy, verbose, nflag, sflag;
15637ed4
RG
80int compare();
81int dups;
82int badfile = -1; /* copy of badsector table to use, -1 if any */
83#define MAXSECSIZE 1024
84struct dkbad curbad, oldbad;
85#define DKBAD_MAGIC 0x4321
86
1148d35e 87char *buf;
15637ed4
RG
88char label[BBSIZE];
89daddr_t size, getold(), badsn();
90struct disklabel *dp;
91char name[BUFSIZ];
92char *malloc();
93off_t lseek();
1148d35e
AM
94int bstart, bend; /* start and ending block numbers */
95char *p; /* temp dev name pointer */
96char devname[BUFSIZ];
97
98#ifdef __386BSD__
99static char * parts[] = {
100 "ROOT ",
101 "SWAP ",
102 "386BSD",
103 "DISK ",
104 "DOS? ",
105 "USR2 ",
106 "USR1 ",
107 "USR "
108};
109#endif
15637ed4
RG
110
111main(argc, argv)
112 int argc;
113 char *argv[];
114{
115 register struct bt_bad *bt;
116 daddr_t sn, bn[126];
1148d35e 117 int i, j, f, nbad, new, bad, errs;
15637ed4 118
1148d35e 119 setbuf(stdout, NULL);
15637ed4
RG
120 argc--, argv++;
121 while (argc > 0 && **argv == '-') {
122 (*argv)++;
123 while (**argv) {
124 switch (**argv) {
125#if vax
126 case 'f':
127 fflag++;
128 break;
129#endif
130 case 'a':
131 add++;
132 break;
133 case 'c':
134 copy++;
135 break;
136 case 'v':
137 verbose++;
138 break;
139 case 'n':
140 nflag++;
141 verbose++;
142 break;
1148d35e
AM
143 case 's': /* scan partition */
144 sflag++;
145 verbose++;
146 break;
15637ed4
RG
147 default:
148 if (**argv >= '0' && **argv <= '4') {
149 badfile = **argv - '0';
150 break;
151 }
152 goto usage;
153 }
154 (*argv)++;
155 }
156 argc--, argv++;
157 }
158 if (argc < 1) {
159usage:
1148d35e
AM
160 fprintf(stderr, "usage: bad144 [ -f ] disk [ snum [ bn ... ] ]\n");
161 fprintf(stderr, "to read or overwrite bad-sector table, e.g., bad144 hp0\n");
162 fprintf(stderr, "or bad144 -a [ -f ] [ -c ] disk bn ...\n");
15637ed4
RG
163 fprintf(stderr, "where options are:\n");
164 fprintf(stderr, "\t-a add new bad sectors to the table\n");
165 fprintf(stderr, "\t-f reformat listed sectors as bad\n");
166 fprintf(stderr, "\t-c copy original sector to replacement\n");
1148d35e 167 fprintf(stderr, "\t-s scan partition for bad sectors\n");
15637ed4
RG
168 exit(1);
169 }
170 if (argv[0][0] != '/')
1148d35e 171 (void)sprintf(name, "%sr%s%s", _PATH_DEV, argv[0], RAWPART);
15637ed4
RG
172 else
173 strcpy(name, argv[0]);
174 f = open(name, argc == 1? O_RDONLY : O_RDWR);
175 if (f < 0)
176 Perror(name);
1148d35e
AM
177 p = strrchr(name, '/');
178 strcpy(devname,++p);
179 devname[strlen(p)-1] = '\0';
15637ed4 180 /* obtain label and adjust to fit */
1148d35e 181 dp = (struct disklabel *)&label;
15637ed4
RG
182 if (ioctl(f, DIOCGDINFO, dp) < 0)
183 Perror("ioctl DIOCGDINFO");
15637ed4
RG
184 if (dp->d_magic != DISKMAGIC || dp->d_magic2 != DISKMAGIC
185 /* dkcksum(lp) != 0 */ ) {
186 fprintf(stderr, "Bad pack magic number (pack is unlabeled)\n");
187 exit(1);
188 }
189 if (dp->d_secsize > MAXSECSIZE || dp->d_secsize <= 0) {
190 fprintf(stderr, "Disk sector size too large/small (%d)\n",
191 dp->d_secsize);
192 exit(7);
193 }
194#ifdef __386BSD__
195 if (dp->d_type == DTYPE_SCSI) {
196 fprintf(stderr, "SCSI disks don't use bad144!\n");
197 exit(1);
198 }
199 /* are we inside a DOS partition? */
1148d35e
AM
200 if (verbose) {
201 printf("device /dev/%s is a %s disk\n", devname, dktypenames[dp->d_type]);
202 j = dp->d_secpercyl;
203 for (i=0; i < dp->d_npartitions; i++) {
204 if (dp->d_partitions[i].p_size == 0)
205 continue;
206 printf("%s%c %s offset: %7d (%4d), size: %7d (%4d), type = %s\n",
207 devname, 'a'+i, parts[i], dp->d_partitions[i].p_offset,
208 dp->d_partitions[i].p_offset/j,
209 dp->d_partitions[i].p_size,
210 dp->d_partitions[i].p_size/j,
211 fstypenames[dp->d_partitions[i].p_fstype]);
212 }
213 }
15637ed4 214 if (dp->d_partitions[0].p_offset) {
1148d35e
AM
215 /*
216 * yes, rules change. assume bad tables at end of partition C,
217 * which maps all of DOS partition we are within -wfj
218 */
219 size = dp->d_partitions[2].p_offset +
220 dp->d_partitions[2].p_size;
15637ed4
RG
221 } else
222#endif
1148d35e
AM
223 size = dp->d_nsectors * dp->d_ntracks * dp->d_ncylinders;
224 bstart = 0;
225 if (dp->d_partitions[2].p_size) {
226 bstart = dp->d_partitions[2].p_offset;
227 }
228 /* determine where to stop scanning */
229 bend = dp->d_partitions[2].p_size + dp->d_partitions[2].p_offset;
230 bend -= (dp->d_nsectors + 126);
231 if (verbose) {
232 printf("secs: %d, tracks: %d, cyl: %d, sec/cyl: %d, start: %d, end: %d\n",
233 dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders,
234 dp->d_secpercyl, bstart, bend);
235 }
236 if (sflag) { /* search for bad sectors */
237 int curr_sec, tries, n;
238 int spc = dp->d_secpercyl;
239 int ss = dp->d_secsize;
240 int trk = dp->d_nsectors;
241 int step;
242
243 if (buf == (char *)NULL) {
244 buf = malloc((unsigned)(trk*ss));
245 if (buf == (char *)NULL) {
246 fprintf(stderr, "Out of memory\n");
247 exit(20);
248 }
249 }
250
251 printf("Starting scan of /dev/%sc at cylinder %d\n", devname, bstart/spc);
252 /* seek to start of parition c, we are in d */
253 for (tries = 0; tries < RETRIES; tries++) {
254 if (lseek(f, bstart * ss, L_SET) < 0) {
255 Perror("lseek");
256 } else
257 break;
258 }
259 step = trk;
260 for (curr_sec = bstart; curr_sec < bend; curr_sec += step) {
261 int gotone = 0;
262
263 if (verbose) {
264 if ((curr_sec % spc) == 0)
265 printf("\r%4d(%7d)",
266 curr_sec/spc, curr_sec);
267 }
268 for (tries = 0; tries < RETRIES; tries++) {
269 if (lseek(f, curr_sec * ss, L_SET) < 0) {
270 fprintf(stderr,
271 "\nbad144: can't seek sector, %d\n",
272 curr_sec);
273 gotone = 1;
274 } else
275 break;
276 }
277 if (gotone) {
278 fprintf(stderr,
279 "\nbad144: bad sector (seek), %d\n",
280 curr_sec);
281 step = 1;
282 continue;
283 }
284 if (step == trk) {
285 if ((n = read(f, buf, (ss*trk))) == (ss*trk)) {
286 continue;
287 }
288 }
289 /* switch to single sector reads */
290 lseek(f, curr_sec * ss, L_SET);
291 step = 1;
292 for (tries = 0; tries < RETRIES; tries++) {
293 if ((n = read(f, buf, ss)) != ss) {
294 fprintf(stderr,
295 "\nbad144: can't read sector,
296 %d\n", curr_sec);
297 gotone = 1;
298 lseek(f, curr_sec * ss, L_SET);
299 } else {
300 if ((curr_sec % trk) == 0) {
301 step = trk;
302 }
303 break;
304 }
305 }
306 if (gotone) {
307 fprintf(stderr,
308 "\nbad144: bad sector (read), %d\n",
309 curr_sec);
310 continue;
311 }
312 }
313 }
15637ed4
RG
314 argc--;
315 argv++;
316 if (argc == 0) {
317 sn = getold(f, &oldbad);
1148d35e 318 printf("\nbad block information at sector %d in %s:\n",
15637ed4 319 sn, name);
7d1221ed 320 printf("cartridge serial number: %d(10)\n", oldbad.bt_csn);
15637ed4
RG
321 switch (oldbad.bt_flag) {
322
323 case (u_short)-1:
324 printf("alignment cartridge\n");
325 break;
326
327 case DKBAD_MAGIC:
328 break;
329
330 default:
331 printf("bt_flag=%x(16)?\n", oldbad.bt_flag);
332 break;
333 }
334 bt = oldbad.bt_bad;
335 for (i = 0; i < 126; i++) {
336 bad = (bt->bt_cyl<<16) + bt->bt_trksec;
337 if (bad < 0)
338 break;
339 printf("sn=%d, cn=%d, tn=%d, sn=%d\n", badsn(bt),
340 bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff);
341 bt++;
342 }
343 (void) checkold(&oldbad);
344 exit(0);
345 }
346 if (add) {
347 /*
348 * Read in the old badsector table.
349 * Verify that it makes sense, and the bad sectors
350 * are in order. Copy the old table to the new one.
351 */
352 (void) getold(f, &oldbad);
353 i = checkold(&oldbad);
354 if (verbose)
355 printf("Had %d bad sectors, adding %d\n", i, argc);
356 if (i + argc > 126) {
357 printf("bad144: not enough room for %d more sectors\n",
1148d35e 358 argc);
15637ed4
RG
359 printf("limited to 126 by information format\n");
360 exit(1);
361 }
362 curbad = oldbad;
363 } else {
364 curbad.bt_csn = atoi(*argv++);
365 argc--;
366 curbad.bt_mbz = 0;
367 curbad.bt_flag = DKBAD_MAGIC;
368 if (argc > 126) {
369 printf("bad144: too many bad sectors specified\n");
370 printf("limited to 126 by information format\n");
371 exit(1);
372 }
373 i = 0;
374 }
375 errs = 0;
376 new = argc;
377 while (argc > 0) {
378 daddr_t sn = atoi(*argv++);
379 argc--;
380 if (sn < 0 || sn >= size) {
381 printf("%d: out of range [0,%d) for disk %s\n",
382 sn, size, dp->d_typename);
383 errs++;
384 continue;
385 }
386 bn[i] = sn;
387 curbad.bt_bad[i].bt_cyl = sn / (dp->d_nsectors*dp->d_ntracks);
388 sn %= (dp->d_nsectors*dp->d_ntracks);
389 curbad.bt_bad[i].bt_trksec =
390 ((sn/dp->d_nsectors) << 8) + (sn%dp->d_nsectors);
391 i++;
392 }
393 if (errs)
394 exit(1);
395 nbad = i;
396 while (i < 126) {
397 curbad.bt_bad[i].bt_trksec = -1;
398 curbad.bt_bad[i].bt_cyl = -1;
399 i++;
400 }
401 if (add) {
402 /*
403 * Sort the new bad sectors into the list.
404 * Then shuffle the replacement sectors so that
405 * the previous bad sectors get the same replacement data.
406 */
407 qsort((char *)curbad.bt_bad, nbad, sizeof (struct bt_bad),
408 compare);
409 if (dups) {
1148d35e 410 fprintf(stderr, "bad144: bad sectors have been duplicated; can't add existing sectors\n");
15637ed4
RG
411 exit(3);
412 }
413 shift(f, nbad, nbad-new);
414 }
415 if (badfile == -1)
416 i = 0;
417 else
418 i = badfile * 2;
419 for (; i < 10 && i < dp->d_nsectors; i += 2) {
420 if (lseek(f, dp->d_secsize * (size - dp->d_nsectors + i),
1148d35e 421 L_SET) < 0)
15637ed4
RG
422 Perror("lseek");
423 if (verbose)
424 printf("write badsect file at %d\n",
1148d35e 425 size - dp->d_nsectors + i);
15637ed4 426 if (nflag == 0 && write(f, (caddr_t)&curbad, sizeof(curbad)) !=
1148d35e 427 sizeof(curbad)) {
15637ed4
RG
428 char msg[80];
429 (void)sprintf(msg, "bad144: write bad sector file %d",
430 i/2);
431 perror(msg);
432 }
433 if (badfile != -1)
434 break;
435 }
436#ifdef vax
437 if (nflag == 0 && fflag)
438 for (i = nbad - new; i < nbad; i++)
439 format(f, bn[i]);
440#endif
441#ifdef DIOCSBAD
442 if (nflag == 0 && ioctl(f, DIOCSBAD, (caddr_t)&curbad) < 0)
443 fprintf(stderr,
444 "Can't sync bad-sector file; reboot for changes to take effect\n");
445#endif
446 if ((dp->d_flags & D_BADSECT) == 0 && nflag == 0) {
447 dp->d_flags |= D_BADSECT;
448 if (ioctl(f, DIOCWDINFO, dp) < 0) {
449 perror("label");
450 fprintf(stderr, "Can't write disklabel to enable bad secctor handling by the drive\n");
451 exit(1);
452 }
453 }
454 exit(0);
455}
456
457daddr_t
458getold(f, bad)
459struct dkbad *bad;
460{
461 register int i;
462 daddr_t sn;
463 char msg[80];
464
465 if (badfile == -1)
466 i = 0;
467 else
468 i = badfile * 2;
469 for (; i < 10 && i < dp->d_nsectors; i += 2) {
470 sn = size - dp->d_nsectors + i;
471 if (lseek(f, sn * dp->d_secsize, L_SET) < 0)
472 Perror("lseek");
473 if (read(f, (char *) bad, dp->d_secsize) == dp->d_secsize) {
474 if (i > 0)
475 printf("Using bad-sector file %d\n", i/2);
476 return(sn);
477 }
478 (void)sprintf(msg, "bad144: read bad sector file at sn %d", sn);
479 perror(msg);
480 if (badfile != -1)
481 break;
482 }
483 fprintf(stderr, "bad144: %s: can't read bad block info\n", name);
484 exit(1);
485 /*NOTREACHED*/
486}
487
488checkold()
489{
490 register int i;
491 register struct bt_bad *bt;
492 daddr_t sn, lsn;
493 int errors = 0, warned = 0;
494
495 if (oldbad.bt_flag != DKBAD_MAGIC) {
496 fprintf(stderr, "bad144: %s: bad flag in bad-sector table\n",
1148d35e 497 name);
15637ed4
RG
498 errors++;
499 }
500 if (oldbad.bt_mbz != 0) {
501 fprintf(stderr, "bad144: %s: bad magic number\n", name);
502 errors++;
503 }
504 bt = oldbad.bt_bad;
505 for (i = 0; i < 126; i++, bt++) {
506 if (bt->bt_cyl == 0xffff && bt->bt_trksec == 0xffff)
507 break;
508 if ((bt->bt_cyl >= dp->d_ncylinders) ||
1148d35e
AM
509 ((bt->bt_trksec >> 8) >= dp->d_ntracks) ||
510 ((bt->bt_trksec & 0xff) >= dp->d_nsectors)) {
15637ed4 511 fprintf(stderr,
1148d35e 512 "bad144: cyl/trk/sect out of range in existing entry: ");
15637ed4 513 fprintf(stderr, "sn=%d, cn=%d, tn=%d, sn=%d\n",
1148d35e
AM
514 badsn(bt), bt->bt_cyl, bt->bt_trksec>>8,
515 bt->bt_trksec & 0xff);
15637ed4
RG
516 errors++;
517 }
518 sn = (bt->bt_cyl * dp->d_ntracks +
1148d35e
AM
519 (bt->bt_trksec >> 8)) *
520 dp->d_nsectors + (bt->bt_trksec & 0xff);
15637ed4 521 if (i > 0 && sn < lsn && !warned) {
1148d35e
AM
522 fprintf(stderr,
523 "bad144: bad sector file is out of order\n");
524 errors++;
525 warned++;
15637ed4
RG
526 }
527 if (i > 0 && sn == lsn) {
1148d35e
AM
528 fprintf(stderr,
529 "bad144: bad sector file contains duplicates (sn %d)\n",
530 sn);
531 errors++;
15637ed4
RG
532 }
533 lsn = sn;
534 }
535 if (errors)
536 exit(1);
537 return (i);
538}
539
540/*
541 * Move the bad sector replacements
542 * to make room for the new bad sectors.
543 * new is the new number of bad sectors, old is the previous count.
544 */
545shift(f, new, old)
546{
547 daddr_t repl;
548
549 /*
550 * First replacement is last sector of second-to-last track.
551 */
552 repl = size - dp->d_nsectors - 1;
553 new--; old--;
554 while (new >= 0 && new != old) {
555 if (old < 0 ||
1148d35e 556 compare(&curbad.bt_bad[new], &oldbad.bt_bad[old]) > 0) {
15637ed4
RG
557 /*
558 * Insert new replacement here-- copy original
559 * sector if requested and possible,
560 * otherwise write a zero block.
561 */
562 if (!copy ||
1148d35e 563 !blkcopy(f, badsn(&curbad.bt_bad[new]), repl - new))
15637ed4
RG
564 blkzero(f, repl - new);
565 } else {
566 if (blkcopy(f, repl - old, repl - new) == 0)
1148d35e
AM
567 fprintf(stderr,
568 "Can't copy replacement sector %d to %d\n",
15637ed4
RG
569 repl-old, repl-new);
570 old--;
571 }
572 new--;
573 }
574}
575
15637ed4
RG
576/*
577 * Copy disk sector s1 to s2.
578 */
579blkcopy(f, s1, s2)
580daddr_t s1, s2;
581{
582 register tries, n;
583
584 if (buf == (char *)NULL) {
585 buf = malloc((unsigned)dp->d_secsize);
586 if (buf == (char *)NULL) {
587 fprintf(stderr, "Out of memory\n");
588 exit(20);
589 }
590 }
591 for (tries = 0; tries < RETRIES; tries++) {
592 if (lseek(f, dp->d_secsize * s1, L_SET) < 0)
593 Perror("lseek");
594 if ((n = read(f, buf, dp->d_secsize)) == dp->d_secsize)
595 break;
596 }
597 if (n != dp->d_secsize) {
598 fprintf(stderr, "bad144: can't read sector, %d: ", s1);
599 if (n < 0)
600 perror((char *)0);
601 return(0);
602 }
603 if (lseek(f, dp->d_secsize * s2, L_SET) < 0)
604 Perror("lseek");
605 if (verbose)
606 printf("copying %d to %d\n", s1, s2);
607 if (nflag == 0 && write(f, buf, dp->d_secsize) != dp->d_secsize) {
608 fprintf(stderr,
609 "bad144: can't write replacement sector, %d: ", s2);
610 perror((char *)0);
611 return(0);
612 }
613 return(1);
614}
615
616char *zbuf;
617
618blkzero(f, sn)
619daddr_t sn;
620{
621
622 if (zbuf == (char *)NULL) {
623 zbuf = malloc((unsigned)dp->d_secsize);
624 if (zbuf == (char *)NULL) {
625 fprintf(stderr, "Out of memory\n");
626 exit(20);
627 }
628 }
629 if (lseek(f, dp->d_secsize * sn, L_SET) < 0)
630 Perror("lseek");
631 if (verbose)
632 printf("zeroing %d\n", sn);
633 if (nflag == 0 && write(f, zbuf, dp->d_secsize) != dp->d_secsize) {
634 fprintf(stderr,
635 "bad144: can't write replacement sector, %d: ", sn);
636 perror((char *)0);
637 }
638}
639
640compare(b1, b2)
641register struct bt_bad *b1, *b2;
642{
643 if (b1->bt_cyl > b2->bt_cyl)
644 return(1);
645 if (b1->bt_cyl < b2->bt_cyl)
646 return(-1);
647 if (b1->bt_trksec == b2->bt_trksec)
648 dups++;
649 return (b1->bt_trksec - b2->bt_trksec);
650}
651
652daddr_t
653badsn(bt)
654register struct bt_bad *bt;
655{
656 return ((bt->bt_cyl*dp->d_ntracks + (bt->bt_trksec>>8)) * dp->d_nsectors
1148d35e 657 + (bt->bt_trksec&0xff));
15637ed4
RG
658}
659
660#ifdef vax
661
662struct rp06hdr {
663 short h_cyl;
664 short h_trksec;
665 short h_key1;
666 short h_key2;
667 char h_data[512];
668#define RP06_FMT 010000 /* 1 == 16 bit, 0 == 18 bit */
669};
670
671/*
672 * Most massbus and unibus drives
673 * have headers of this form
674 */
675struct hpuphdr {
676 u_short hpup_cyl;
677 u_char hpup_sect;
678 u_char hpup_track;
679 char hpup_data[512];
680#define HPUP_OKSECT 0xc000 /* this normally means sector is good */
681#define HPUP_16BIT 0x1000 /* 1 == 16 bit format */
682};
683int rp06format(), hpupformat();
684
685struct formats {
686 char *f_name; /* disk name */
687 int f_bufsize; /* size of sector + header */
688 int f_bic; /* value to bic in hpup_cyl */
689 int (*f_routine)(); /* routine for special handling */
690} formats[] = {
691 { "rp06", sizeof (struct rp06hdr), RP06_FMT, rp06format },
692 { "eagle", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
693 { "capricorn", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
694 { "rm03", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
695 { "rm05", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
696 { "9300", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
697 { "9766", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
698 { 0, 0, 0, 0 }
699};
700
701/*ARGSUSED*/
702hpupformat(fp, dp, blk, buf, count)
703 struct formats *fp;
704 struct disklabel *dp;
705 daddr_t blk;
706 char *buf;
707 int count;
708{
709 struct hpuphdr *hdr = (struct hpuphdr *)buf;
710 int sect;
711
712 if (count < sizeof(struct hpuphdr)) {
713 hdr->hpup_cyl = (HPUP_OKSECT | HPUP_16BIT) |
1148d35e 714 (blk / (dp->d_nsectors * dp->d_ntracks));
15637ed4
RG
715 sect = blk % (dp->d_nsectors * dp->d_ntracks);
716 hdr->hpup_track = (u_char)(sect / dp->d_nsectors);
717 hdr->hpup_sect = (u_char)(sect % dp->d_nsectors);
718 }
719 return (0);
720}
721
722/*ARGSUSED*/
723rp06format(fp, dp, blk, buf, count)
724 struct formats *fp;
725 struct disklabel *dp;
726 daddr_t blk;
727 char *buf;
728 int count;
729{
730
731 if (count < sizeof(struct rp06hdr)) {
732 fprintf(stderr, "Can't read header on blk %d, can't reformat\n",
1148d35e 733 blk);
15637ed4
RG
734 return (-1);
735 }
736 return (0);
737}
738
739format(fd, blk)
740 int fd;
741 daddr_t blk;
742{
743 register struct formats *fp;
744 static char *buf;
745 static char bufsize;
746 struct format_op fop;
747 int n;
748
749 for (fp = formats; fp->f_name; fp++)
750 if (strcmp(dp->d_typename, fp->f_name) == 0)
751 break;
752 if (fp->f_name == 0) {
753 fprintf(stderr, "bad144: don't know how to format %s disks\n",
754 dp->d_typename);
755 exit(2);
756 }
757 if (buf && bufsize < fp->f_bufsize) {
758 free(buf);
759 buf = NULL;
760 }
761 if (buf == NULL)
762 buf = malloc((unsigned)fp->f_bufsize);
763 if (buf == NULL) {
764 fprintf(stderr, "bad144: can't allocate sector buffer\n");
765 exit(3);
766 }
767 bufsize = fp->f_bufsize;
768 /*
769 * Here we do the actual formatting. All we really
770 * do is rewrite the sector header and flag the bad sector
771 * according to the format table description. If a special
772 * purpose format routine is specified, we allow it to
773 * process the sector as well.
774 */
775 if (verbose)
776 printf("format blk %d\n", blk);
777 bzero((char *)&fop, sizeof(fop));
778 fop.df_buf = buf;
779 fop.df_count = fp->f_bufsize;
780 fop.df_startblk = blk;
781 bzero(buf, fp->f_bufsize);
782 if (ioctl(fd, DIOCRFORMAT, &fop) < 0)
783 perror("bad144: read format");
784 if (fp->f_routine &&
1148d35e 785 (*fp->f_routine)(fp, dp, blk, buf, fop.df_count) != 0)
15637ed4
RG
786 return;
787 if (fp->f_bic) {
788 struct hpuphdr *xp = (struct hpuphdr *)buf;
789
790 xp->hpup_cyl &= ~fp->f_bic;
791 }
792 if (nflag)
793 return;
794 bzero((char *)&fop, sizeof(fop));
795 fop.df_buf = buf;
796 fop.df_count = fp->f_bufsize;
797 fop.df_startblk = blk;
798 if (ioctl(fd, DIOCWFORMAT, &fop) < 0)
799 Perror("write format");
800 if (fop.df_count != fp->f_bufsize) {
801 char msg[80];
802 (void)sprintf(msg, "bad144: write format %d", blk);
803 perror(msg);
804 }
805}
806#endif
807
808Perror(op)
809 char *op;
810{
811
812 fprintf(stderr, "bad144: "); perror(op);
813 exit(4);
814}