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
10History
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
40int	done;
41
42/*
43 Catch ^C and ^Break.
44*/
45int	handler(void)
46{
47  done = true;
48  return(0);
49}
50void 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*/
58void 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".
9215	-	1.2 M HD	5.25".
9318	-	1.44 M		3.5".
94*/
95int 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
124void 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