static char *sccsid
= "@(#)bad144.c 4.4 (Berkeley) 83/02/23";
* This program prints and/or initializes a bad block record for a pack,
* in the format used by the DEC standard 144.
* Only reads/writes the first of the bad block record (sector 0
* of the last track of the disk); in fact, there are copies
* of the information in the first 5 even numbered sectors of this
* track, but UNIX uses only the first, and we don't bother with the
* It is preferable to write the bad information with a standard formatter,
* but this program will do in a pinch, e.g. if the bad information is
* accidentally wiped out this is a much faster way of restoring it than
* For the RP06 the -f flag may be used to mark a sector as bad by
* inverting the format bit in the header and writing the sector header.
* One should be able to do this on all drives ... as soon as someone
#include <machine/dkio.h>
register struct bt_bad
*bt
;
register struct disktab
*dp
;
int size
, i
, f
, bad
, oldbad
, errs
;
if (argc
> 0 && strcmp(*argv
, "-f") == 0) {
"usage: bad144 [ -f ] type disk [ snum [ bn ... ] ]\n");
fprintf(stderr
, "e.g.: bad144 rk07 hk0\n");
dp
= getdiskbyname(argv
[0]);
fprintf(stderr
, "%s: unknown disk type\n", argv
[0]);
sprintf(name
, "/dev/r%sc", argv
[1]);
size
= dp
->d_nsectors
* dp
->d_ntracks
* dp
->d_ncylinders
;
lseek(f
, dp
->d_secsize
* (size
- dp
->d_nsectors
), 0);
printf("bad block information at 0x%x in %s:\n",
if (read(f
, &dkbad
, sizeof (struct dkbad
)) !=
fprintf("%s: can't read bad block info (wrong type disk?)\n");
printf("cartidge serial number: %d(10)\n", dkbad
.bt_csn
);
printf("alignment cartridge\n");
printf("bt_flag=%x(16)?\n", dkbad
.bt_flag
);
for (i
= 0; i
< 128; i
++) {
bad
= (bt
->bt_cyl
<<16) + bt
->bt_trksec
;
printf("sn=%d, cn=%d, tn=%d, sn=%d\n",
(bt
->bt_cyl
*dp
->d_ntracks
+ (bt
->bt_trksec
>>8)) *
dp
->d_nsectors
+ (bt
->bt_trksec
&0xff),
bt
->bt_cyl
, bt
->bt_trksec
>>8, bt
->bt_trksec
&0xff);
f
= open(name
, 1 + fflag
);
dkbad
.bt_csn
= atoi(*argv
++);
if (argc
> 2 * dp
->d_nsectors
|| argc
> 126) {
printf("bad144: too many bad sectors specified\n");
if (2 * dp
->d_nsectors
> 126)
printf("limited to 126 by information format\n");
printf("limited to %d (only 2 tracks of sectors)\n",
if (sn
< 0 || sn
>= size
) {
printf("%d: out of range [0,%d) for %s\n",
dkbad
.bt_bad
[i
].bt_cyl
= sn
/ (dp
->d_nsectors
*dp
->d_ntracks
);
sn
%= (dp
->d_nsectors
*dp
->d_ntracks
);
dkbad
.bt_bad
[i
].bt_trksec
=
((sn
/dp
->d_nsectors
) << 8) + (sn
%dp
->d_nsectors
);
dkbad
.bt_bad
[i
].bt_trksec
= -1;
dkbad
.bt_bad
[i
].bt_cyl
= -1;
lseek(f
, dp
->d_secsize
* (size
- dp
->d_nsectors
), 0);
if (write(f
, (caddr_t
)&dkbad
, sizeof (dkbad
)) != sizeof (dkbad
)) {
for (i
= 0, bt
= dkbad
.bt_bad
; i
< 128; i
++, bt
++) {
bad
= (bt
->bt_cyl
<<16) + bt
->bt_trksec
;
bn
= (bt
->bt_cyl
* dp
->d_ntracks
+
dp
->d_nsectors
+ (bt
->bt_trksec
& 0xff);
#define RP06_FMT 010000 /* 1 == 16 bit, 0 == 18 bit */
char *f_name
; /* disk name */
int f_bufsize
; /* size of sector + header */
int (*f_routine
)(); /* routine for special handling */
{ "rp06", sizeof (struct rp06hdr
), rp06fmt
},
register struct formats
*fp
;
for (fp
= formats
; fp
->f_name
; fp
++)
if (strcmp(dp
->d_name
, fp
->f_name
) == 0)
fprintf(stderr
, "bad144: don't know how to format %s disks\n",
buf
= malloc(fp
->f_bufsize
);
fprintf(stderr
, "bad144: can't allocate sector buffer\n");
* Here we do the actual formatting. All we really
* do is rewrite the sector header and flag the bad sector
* according to the format table description. If a special
* purpose format routine is specified, we allow it to
* process the sector as well.
lseek(fd
, (long)blk
* 512, 0);
read(fd
, buf
, fp
->f_bufsize
);
(*fp
->f_routine
)(fp
, dp
, blk
, buf
);
lseek(fd
, (long)blk
* 512, 0);
write(fd
, buf
, fp
->f_bufsize
);