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