/* format.c 6.2 83/09/18 */
* Standalone program to do media checking
* and record bad block information on any
* disk with the appropriate driver and RM03-style headers.
#define MAXBADDESC 126 /* size of bad block table */
#define CHUNK 48 /* max # of sectors/io operation */
#define SECTSIZ 512 /* standard sector size */
#define HDRSIZ 4 /* number of bytes in sector header */
#define SSDEV ((ioctl(iob[fd-3], SAIOSSDEV, (char *)0) == 0))
struct dkbad dkbad
; /* bad sector table */
struct dkbad sstab
; /* skip sector table */
int errors
[NERRORS
]; /* histogram of errors */
int lastsector
, tracksize
;
int unit
, fd
, resid
, i
, trk
, cyl
, debug
;
printf("Disk format/check utility\n\n");
cp
= prompt("Enable debugging (1=bse, 2=ecc, 3=bse+ecc)? ");
for (i
= 0; i
< NERRORS
; i
++)
ioctl(fd
, SAIODEVDATA
, &st
);
printf("Device data: #cylinders=%d, #tracks=%d, #sectors=%d\n",
st
.ncyl
, st
.ntrak
, st
.nsect
);
printf("Start formatting...make sure the drive is online\n");
ioctl(fd
, SAIONOBAD
, (char *)0);
ioctl(fd
, SAIOECCLIM
, (char *)0);
ioctl(fd
, SAIODEBUG
, (char *)debug
);
ioctl(fd
, SAIOSSI
, (char *)0); /* set skip sector inhibit */
tracksize
= sizeof (struct sector
) * st
.nsect
;
bp
= (struct sector
*)malloc(tracksize
);
* Begin check, for each track,
* 1) Write header and test pattern.
* 2) Write check header and data.
lastsector
= st
.nspc
* st
.ncyl
;
for (sector
= 0; sector
< lastsector
; sector
+= st
.nsect
) {
trk
= (sector
% st
.nspc
) / st
.nsect
;
for (i
= 0; i
< st
.nsect
; i
++) {
(u_short
) cyl
| HDR1_FMT22
| HDR1_OKSCT
;
bp
[i
].header2
= ((u_short
)trk
<< 8) + i
;
if (sector
&& (sector
% (st
.nspc
* 10)) == 0)
printf("cylinder %d\n", cyl
);
* Try and write the headers and data patterns into
* each sector in the track. Continue until such
* we're done, or until there's less than a sector's
* worth of data to transfer.
* The lseek call is necessary because of
* the odd sector size (516 bytes)
for (resid
= tracksize
, cbp
= bp
, sn
= sector
;;) {
lseek(fd
, sn
* SECTSIZ
, 0);
ioctl(fd
, SAIOHDR
, (char *)0);
cc
= write(fd
, cbp
, resid
);
* Don't record errors during write,
* all errors will be found during
* writecheck performed below.
sn
= iob
[fd
- 3].i_errblk
;
resid
-= (sn
- sector
) * sizeof (struct sector
);
if (resid
< sizeof (struct sector
))
* Write check headers and test patterns.
* Retry remainder of track on error until
* we're done, or until there's less than a
for (resid
= tracksize
, cbp
= bp
, sn
= sector
;;) {
lseek(fd
, sn
* SECTSIZ
, 0);
ioctl(fd
, SAIOHCHECK
, (char *)0);
cc
= read(fd
, cbp
, resid
);
printf("sector %d, write check error\n", sn
);
recorderror(fd
, sn
, &st
);
/* advance past bad sector */
resid
-= (sn
- sector
) * sizeof (struct sector
);
if (resid
< sizeof (struct sector
))
if (errors
[FE_TOTAL
] || errors
[FE_SSE
]) {
for (i
= 0; i
< NERRORS
; i
++)
printf("%s: %d\n", errornames
[i
], errors
[i
]);
printf("Total of %d hard errors found\n",
errors
[FE_TOTAL
] + errors
[FE_SSE
]);
/* change the headers of all the bad sectors */
writebb(fd
, errors
[FE_SSE
], &sstab
, &st
, SSERR
);
writebb(fd
, errors
[FE_TOTAL
], &dkbad
, &st
, BSERR
);
while (errors
[FE_TOTAL
] < MAXBADDESC
) {
int i
= errors
[FE_TOTAL
]++;
dkbad
.bt_bad
[i
].bt_cyl
= -1;
dkbad
.bt_bad
[i
].bt_trksec
= -1;
printf("\nWriting bad sector table at sector #%d\n",
st
.ncyl
* st
.nspc
- st
.nsect
);
for (i
= 0; i
< 10; i
+= 2) {
lseek(fd
, SECTSIZ
* (st
.ncyl
* st
.nspc
- st
.nsect
+ i
), 0);
write(fd
, &dkbad
, sizeof (dkbad
));
ioctl(fd
,SAIONOSSI
,(char *)0);
* Write out the bad blocks.
writebb(fd
, nsects
, dbad
, st
, sw
)
struct sector bb_buf
; /* buffer for one sector plus 4 byte header */
for (i
= 0; i
< nsects
; i
++) {
bb_buf
.header1
= HDR1_FMT22
|btp
->bt_cyl
;
bb_buf
.header1
|= HDR1_SSF
;
btp
->bt_cyl
| HDR1_FMT22
| HDR1_SSF
| HDR1_OKSCT
;
bb_buf
.header2
= btp
->bt_trksec
;
bn
= st
->nspc
* btp
->bt_cyl
+
st
->nsect
* (btp
->bt_trksec
>> 8) +
lseek(fd
, bn
* SECTSIZ
, 0);
ioctl(fd
, SAIOHDR
, (char *)0);
write(fd
, &bb_buf
, sizeof (bb_buf
));
* If skip sector, mark all remaining
for (j
= (btp
->bt_trksec
& 0xff) + 1; j
< st
->nsect
; j
++) {
bb_buf
.header1
= j
| HDR1_FMT22
| HDR1_SSF
;
ioctl(fd
, SAIOHDR
, (char *)0);
write(fd
, &bb_buf
, sizeof (bb_buf
));
* Record an error, and if there's room, put
* it in the appropriate bad sector table.
if (errors
[FE_TOTAL
] >= MAXBADDESC
) {
printf("Too many bad sectors\n");
if (errors
[FE_SSE
] >= MAXBADDESC
) {
printf("Too many skip sector errors\n");
if (errno
< EBSE
|| errno
> EHER
)
if (SSDEV
) { /* if drive has skip sector capability */
int ss
= errors
[FE_SSE
]++;
strk
= sstab
.bt_bad
[ss
- 1].bt_trksec
>> 8;
if (tn
!= strk
) { /* only one skip sector/track */
sstab
.bt_bad
[ss
].bt_cyl
= cn
;
sstab
.bt_bad
[ss
].bt_trksec
= (tn
<<8) + sn
;
/* record the bad sector address and continue */
dkbad
.bt_bad
[errors
[FE_TOTAL
]].bt_cyl
= cn
;
dkbad
.bt_bad
[errors
[FE_TOTAL
]++].bt_trksec
= (tn
<< 8) + sn
;
* Allocate memory on a page-aligned address.
* Round allocated chunk to a page multiple to
last
= (caddr_t
)(((int)&end
+ 511) & ~0x1ff);
size
= (size
+ 511) & ~0x1ff;
* Prompt and verify a device name from the user.
register struct devsw
*dp
;
cp
= prompt("Device to format? ");
if ((fd
= open(cp
, 2)) < 0) {
printf("Known devices are: ");
for (dp
= devsw
; dp
->dv_name
; dp
++)
printf("%s ",dp
->dv_name
);
printf("Formatting drive %d on %c%c%d ",
iob
[fd
- 3].i_unit
% 8, cp
[0], cp
[1], iob
[fd
- 3].i_unit
/ 8);
cp
= prompt("verify (yes/no)? ");
while (*cp
!= 'y' && *cp
!= 'n')
cp
= prompt("Huh, yes or no? ");
{ 0xf00ff00f, "RH750 worst case" },
{ 0xec6dec6d, "media worst case" },
{ 0xa5a5a5a5, "alternate 1's and 0's" },
register struct pattern
*p
;
printf("Available test patterns are:\n");
for (p
= pat
; p
->pa_value
; p
++)
printf("\t%d - (%x) %s\n", (p
- pat
) + 1,
p
->pa_value
& 0xffff, p
->pa_name
);
cp
= prompt("Pattern (one of the above, other to restart)? ");
return (pattern
< 0 || pattern
>= npatterns
);
* Initialize the buffer with the requested pattern.
register struct xsect
*bp
;
register struct pattern
*pptr
;
register long *pp
, *last
;
register struct xsect
*lastbuf
;
size
/= sizeof (struct sector
);
for (pp
= bp
->buf
; pp
< last
; pp
++)