1 /*
2  rawrite.c          Write a binary image to a 360K diskette.
3                     By Mark Becker
4 
5  Usage:
6           MS-DOS prompt> RAWRITE
7 
8           And follow the prompts.
9 
10 History
11 -------
12 
13   1.0     -         Initial release
14   1.1     -         Beta test (fixing bugs)                                     4/5/91
15                     Some BIOS's don't like full-track writes.
16   1.101   -         Last beta release.                                4/8/91
17                     Fixed BIOS full-track write by only
18                     writing 3 sectors at a time.
19   1.2     -         Final code and documentation clean-ups.           4/9/91
20 */
21 #include <alloc.h>
22 #include <bios.h>
23 #include <ctype.h>
24 #include <dir.h>
25 #include <dos.h>
26 #include <io.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 
31 #define SECTORSIZE  512
32 
33 #define   RESET     0
34 #define   LAST      1
35 #define   READ      2
36 #define   WRITE     3
37 #define   VERIFY    4
38 #define   FORMAT    5
39 
40 int       done;
41 
42 /*
43  Catch ^C and ^Break.
44 */
handler(void)45 int       handler(void)
46 {
47   done = true;
48   return(0);
49 }
msg(char (* s))50 void msg(char (*s))
51 {
52           fprintf(stderr, "%s\n", s);
53           _exit(1);
54 }
55 /*
56  Identify the error code with a real error message.
57 */
Error(int (status))58 void Error(int (status))
59 {
60   switch (status) {
61     case 0x00:      msg("Operation Successful");                                break;
62     case 0x01:      msg("Bad command");                                         break;
63     case 0x02:      msg("Address mark not found");                                        break;
64     case 0x03:      msg("Attempt to write on write-protected disk");  break;
65     case 0x04:      msg("Sector not found");                                    break;
66     case 0x05:      msg("Reset failed (hard disk)");                            break;
67     case 0x06:      msg("Disk changed since last operation");                   break;
68     case 0x07:      msg("Drive parameter activity failed");                     break;
69     case 0x08:      msg("DMA overrun");                                         break;
70     case 0x09:      msg("Attempt to DMA across 64K boundary");                  break;
71     case 0x0A:      msg("Bad sector detected");                                 break;
72     case 0x0B:      msg("Bad track detected");                                  break;
73     case 0x0C:      msg("Unsupported track");                                   break;
74     case 0x10:      msg("Bad CRC/ECC on disk read");                            break;
75     case 0x11:      msg("CRC/ECC corrected data error");                        break;
76     case 0x20:      msg("Controller has failed");                               break;
77     case 0x40:      msg("Seek operation failed");                               break;
78     case 0x80:      msg("Attachment failed to respond");                        break;
79     case 0xAA:      msg("Drive not ready (hard disk only");                     break;
80     case 0xBB:      msg("Undefined error occurred (hard disk only)"); break;
81     case 0xCC:      msg("Write fault occurred");                                break;
82     case 0xE0:      msg("Status error");                                                  break;
83     case 0xFF:      msg("Sense operation failed");                                        break;
84   }
85   _exit(1);
86 }
87 
88 /*
89  Identify what kind of diskette is installed in the specified drive.
90  Return the number of sectors per track assumed as follows:
91  9        -         360 K and 720 K 5.25".
92 15        -         1.2 M HD  5.25".
93 18        -         1.44 M              3.5".
94 */
nsects(int (drive))95 int nsects(int (drive))
96 {
97   static  int       nsect[] = {18, 15, 9};
98 
99   char    *buffer;
100   int     i, status;
101 /*
102  Read sector 1, head 0, track 0 to get the BIOS running.
103 */
104   buffer = (char *)malloc(SECTORSIZE);
105   biosdisk(RESET, drive, 0, 0, 0, 0, buffer);
106   status = biosdisk(READ, drive, 0, 10, 1, 1, buffer);
107   if (status == 0x06)                             /* Door signal change?        */
108   status = biosdisk(READ, drive, 0, 0, 1, 1, buffer);
109 
110   for (i=0; i < sizeof(nsect)/sizeof(int); ++i) {
111     biosdisk(RESET, drive, 0, 0, 0, 0, buffer);
112     status = biosdisk(READ, drive, 0, 0, nsect[i], 1, buffer);
113     if (status == 0x06)
114       status = biosdisk(READ, drive, 0, 0, nsect[i], 1, buffer);
115       if (status == 0x00) break;
116     }
117     if (i == sizeof(nsect)/sizeof(int)) {
118       msg("Can't figure out how many sectors/track for this diskette.");
119     }
120     free(buffer);
121     return(nsect[i]);
122 }
123 
main(void)124 void main(void)
125 {
126   char     fname[MAXPATH];
127   char    *buffer, *pbuf;
128   int      count, fdin, drive, head, track, status, spt, buflength, ns;
129 
130   puts("RaWrite 1.2 - Write disk file to raw floppy diskette\n");
131   ctrlbrk(handler);
132   printf("Enter source file name: ");
133   scanf("%s", fname);
134   _fmode = O_BINARY;
135   if ((fdin = open(fname, O_RDONLY)) <= 0) {
136      perror(fname);
137      exit(1);
138   }
139 
140   printf("Enter destination drive: ");
141   scanf("%s", fname);
142   drive = (fname[0] - 'A') & 0xf;
143   printf("Please insert a formatted diskette into ");
144   printf("drive %c: and press -ENTER- :", drive + 'A');
145   while (bioskey(1) == 0) ;                                 /* Wait...          */
146   if ((bioskey(0) & 0x7F) == 3) exit(1);                    /* Check for ^C     */
147   putchar('\n');
148   done = false;
149 /*
150  * Determine number of sectors per track and allocate buffers.
151  */
152   spt = nsects(drive);
153   buflength = spt * SECTORSIZE;
154   buffer = (char *)malloc(buflength);
155   printf("Number of sectors per track for this disk is %d\n", spt);
156   printf("Writing image to drive %c:.  Press ^C to abort.\n", drive+'A');
157 /*
158  * Start writing data to diskette until there is no more data to write.
159  */
160    head = track = 0;
161    while ((count = read(fdin, buffer, buflength)) > 0 && !done) {
162      pbuf = buffer;
163      for (ns = 1; count > 0 && !done; ns+=3) {
164        printf("Track: %02d  Head: %2d Sector: %2d\r", track, head, ns);
165        status = biosdisk(WRITE, drive, head, track, ns, 3, pbuf);
166 
167        if (status != 0) Error(status);
168 
169        count -= (3*SECTORSIZE);
170        pbuf  += (3*SECTORSIZE);
171      }
172      if ((head = (head + 1) & 1) == 0) ++track;
173    }
174    if (eof(fdin)) {
175      printf("\nDone.\n");
176      biosdisk(2, drive, 0, 0, 1, 1, buffer);                /* Retract head     */
177    }
178 }         /* end main */
179