home *** CD-ROM | disk | FTP | other *** search
- /*
-
- 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 */