home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
dskutl
/
rewrite.arc
/
REWRITE.C
next >
Wrap
C/C++ Source or Header
|
1989-10-12
|
6KB
|
229 lines
/*
REWRITE.C, a program to make 360K floppies written to in a 1.2M drive
readable in all machines by reading and rewriting each sector, with
optional formatting.
Copyright (c), Steven Fischkoff, M.D., 1989.
Last modification 10/11/89
Compile with huge model. Lesser may be fine, not tested.
*/
#include <stdio.h>
#include <dos.h>
#include <ctype.h>
#include <stdlib.h>
#include <bios.h>
char cpywrt_msg [] =
"\nREWRITE, Copyright (c), Steven Fischkoff, M.D., 1989.\n";
extern int errno;
struct track_addr_field {
unsigned char track;
unsigned char head;
unsigned char sector;
unsigned char size;
};
int break_status, abort_flag;
char tbl_buffer [11];
struct track_addr_field taf_table [9];
unsigned int seg_es, off_bx;
union REGS regs;
struct SREGS segs;
int verify (int drive, int track, int side);
void error_exit (int errno);
int c_break (void) /* Control-break handler */
{
abort_flag = 1;
return (1);
}; /* end of c_break */
#pragma warn -par
int handler (int errval, int ax, int bp, int si)
{ /* hardware error handler */
bdosptr (0x09, "Error accessing disk.$", 0);
return (2); /* abort program */
}; /* end of handler */
#pragma warn .par
void format (int drive, int track)
{int i, count = 0; /* since this must only work on a PC or XT,
we can avoid many sticky issues
like selecting disk parameter tables
and the code is much simpler */
for (i=0; i<9; i++) { /* set up track address table */
taf_table [i].track = (char) track;
taf_table [i].head = 0;
taf_table [i].sector = (char) (i+1);
taf_table [i].size = 2;
};
do {
if (count++ == 3) error_exit (1); /* try as many as 3 times */
regs.h.ah = 5; /* to make sure motor is up */
regs.h.ch = track; /* to speed */
regs.h.dl = drive;
regs.h.dh = 0;
regs.h.al = 9;
regs.x.bx = off_bx;
segs.es = seg_es;
int86x (0x13, ®s, ®s, &segs);
} while (regs.x.cflag || verify (drive, track, 0));
count = 0;
for (i=0; i<9; i++) { /* must format other side of track */
taf_table [i].track = (char) track;
taf_table [i].head = 1;
taf_table [i].sector = (char) (i+1);
taf_table [i].size = 2;
};
do {
if (count++ == 3) error_exit (1);
regs.h.ah = 5;
regs.h.ch = track;
regs.h.dl = drive;
regs.h.dh = 1;
regs.h.al = 9;
regs.x.bx = off_bx;
segs.es = seg_es;
int86x (0x13, ®s, ®s, &segs);
} while (regs.x.cflag || verify (drive, track, 1));
return;
}; /* end of format */
int verify (int drive, int track, int side)
{ /* verify correct formatting */
regs.h.ah = 4;
regs.h.al = 9;
regs.h.ch = track;
regs.h.cl = 1;
regs.h.dh = side;
regs.h.dl = drive;
int86 (0x13, ®s, ®s);
return (regs.x.cflag);
}; /* end of verify */
void error_exit (int errno) {
char blanks [] = " ";
errno &= 0xFF; /* We want only the low byte */
switch (errno) {
case 0: printf ("Disk write protected. Aborting.%s\n\n", blanks); break;
case 1: printf ("Unable to format disk. Aborting.%s\n\n", blanks); break;
/* case 1 doesn't really belong here - just taking advantage of a hole */
case 2: printf ("Drive not ready. Aborting.%s\n\n", blanks); break;
case 4:
case 8: printf ("Error reading drive. Aborting.%s\n\n", blanks); break;
case 12: printf ("Cannot read drive. Aborting.%s\n\n", blanks); break;
};
exit (5);
}; /* end of error_exit */
void main (int argc, char **argv)
{int drive, i, j, reformat = 0;
char *buffer;
struct fatinfo drive_table;
printf ("%s", cpywrt_msg);
if (argc < 2) {
printf ("No drive specified.\n");
printf ("REWRITE A: (or B:) [/F or /f (optional)]\n\n");
exit (1);
};
drive = _toupper (argv [1][0]) - 'A';
if ((drive!=1 && drive!=0) || argv [1][1]!=':') {
printf ("Error in drive specification.\n");
printf ("REWRITE A: (or B:) [/F or /f (optional)]\n\n");
exit (2);
};
if (argc == 3) {
if ((argv[2][0] == '/' || argv[2][0] == '-') &&
(toupper (argv[2][1]) == 'F')) reformat = 1;
else {
printf ("Improper command line switch.\n");
printf ("REWRITE A: (or B:) [/F or /f (optional)]\n\n");
exit (2);
};
};
regs.h.ah = 0x33; /* save break status for later */
regs.h.al = 0;
intdos (®s, ®s);
break_status = regs.h.dl;
ctrlbrk (c_break); /* set up control-break (c) handler */
harderr (handler); /* hardware error handler set up */
getfat ((char) (drive + 1), &drive_table); /* is diskette type appropriate? */
if (drive_table.fi_fatid != 0xFD) {
printf ("Disk not formatted to 360K.\n\n");
exit (3);
};
buffer = malloc (18 * drive_table.fi_bysec); /* 18 represents 1 track */
if (buffer == NULL) {
printf ("Insufficient memory to proceed.\n\n");
exit (4);
};
seg_es = FP_SEG (taf_table); /* address of track address table */
off_bx = FP_OFF (taf_table);
abort_flag = 0;
regs.h.ah = 0x33; /* turn on break flag */
regs.h.al = 1;
regs.h.dl = 1;
intdos (®s, ®s);
for (i=j=0; i<720; i+=18,j++) { /* 720 sectors per disk */
if (abort_flag) break; /* safe place to abort on control-break */
printf ("Reading sectors %d-%d. \r", i,i+17);
if (absread (drive, 18, i, buffer)) { /* read a track at a time to reduce overhead
for head motion */
error_exit (errno);
};
if (reformat) {
printf ("Reading sectors %d-%d. Formatting track %d.\r", i,i+17,j);
format (drive, j);
};
printf ("Rewriting sectors %d-%d. \r", i,i+17);
if (abswrite (drive, 18, i, buffer)) {
error_exit (errno);
};
};
free (buffer);
regs.h.ah = 0x33; /* return break flag to original status */
regs.h.al = 1;
regs.h.dl = break_status;
intdos (®s, ®s);
if (!abort_flag) printf ("Operation completed successfully.\n\n");
else printf ("Program aborted at user request.\n\n");
exit (0);
}; /* end of main */