/*
rawrite.c Write a binary image to a 360K diskette.
By Mark Becker
Usage:
MS-DOS prompt> RAWRITE
And follow the prompts.
History
-------
1.0 - Initial release
1.1 - Beta test (fixing bugs) 4/5/91
Some BIOS's don't like full-track writes.
1.101 - Last beta release. 4/8/91
Fixed BIOS full-track write by only
writing 3 sectors at a time.
1.2 - Final code and documentation clean-ups. 4/9/91
*/
#include <alloc.h>
#include <bios.h>
#include <ctype.h>
#include <dir.h>
#include <dos.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define SECTORSIZE 512
#define RESET 0
#define LAST 1
#define READ 2
#define WRITE 3
#define VERIFY 4
#define FORMAT 5
int done;
/*
Catch ^C and ^Break.
*/
int handler(void)
{
done = true;
return(0);
}
void msg(char (*s))
{
fprintf(stderr, "%s\n", s);
_exit(1);
}
/*
Identify the error code with a real error message.
*/
void Error(int (status))
{
switch (status) {
case 0x00: msg("Operation Successful"); break;
case 0x01: msg("Bad command"); break;
case 0x02: msg("Address mark not found"); break;
case 0x03: msg("Attempt to write on write-protected disk"); break;
case 0x04: msg("Sector not found"); break;
case 0x05: msg("Reset failed (hard disk)"); break;
case 0x06: msg("Disk changed since last operation"); break;
case 0x07: msg("Drive parameter activity failed"); break;
case 0x08: msg("DMA overrun"); break;
case 0x09: msg("Attempt to DMA across 64K boundary"); break;
case 0x0A: msg("Bad sector detected"); break;
case 0x0B: msg("Bad track detected"); break;
case 0x0C: msg("Unsupported track"); break;
case 0x10: msg("Bad CRC/ECC on disk read"); break;
case 0x11: msg("CRC/ECC corrected data error"); break;
case 0x20: msg("Controller has failed"); break;
case 0x40: msg("Seek operation failed"); break;
case 0x80: msg("Attachment failed to respond"); break;
case 0xAA: msg("Drive not ready (hard disk only"); break;
case 0xBB: msg("Undefined error occurred (hard disk only)"); break;
case 0xCC: msg("Write fault occurred"); break;
case 0xE0: msg("Status error"); break;
case 0xFF: msg("Sense operation failed"); break;
}
_exit(1);
}
/*
Identify what kind of diskette is installed in the specified drive.
Return the number of sectors per track assumed as follows:
9 - 360 K and 720 K 5.25".
15 - 1.2 M HD 5.25".
18 - 1.44 M 3.5".
*/
int nsects(int (drive))
{
static int nsect[] = {18, 15, 9};
char *buffer;
int i, status;
/*
Read sector 1, head 0, track 0 to get the BIOS running.
*/
buffer = (char *)malloc(SECTORSIZE);
biosdisk(RESET, drive, 0, 0, 0, 0, buffer);
status = biosdisk(READ, drive, 0, 10, 1, 1, buffer);
if (status == 0x06) /* Door signal change? */
status = biosdisk(READ, drive, 0, 0, 1, 1, buffer);
for (i=0; i < sizeof(nsect)/sizeof(int); ++i) {
biosdisk(RESET, drive, 0, 0, 0, 0, buffer);
status = biosdisk(READ, drive, 0, 0, nsect[i], 1, buffer);
if (status == 0x06)
status = biosdisk(READ, drive, 0, 0, nsect[i], 1, buffer);
if (status == 0x00) break;
}
if (i == sizeof(nsect)/sizeof(int)) {
msg("Can't figure out how many sectors/track for this diskette.");
}
free(buffer);
return(nsect[i]);
}
void main(void)
{
char fname[MAXPATH];
char *buffer, *pbuf;
int count, fdin, drive, head, track, status, spt, buflength, ns;
puts("RaWrite 1.2 - Write disk file to raw floppy diskette\n");
ctrlbrk(handler);
printf("Enter source file name: ");
scanf("%s", fname);
_fmode = O_BINARY;
if ((fdin = open(fname, O_RDONLY)) <= 0) {
perror(fname);
exit(1);
}
printf("Enter destination drive: ");
scanf("%s", fname);
drive = (fname[0] - 'A') & 0xf;
printf("Please insert a formatted diskette into ");
printf("drive %c: and press -ENTER- :", drive + 'A');
while (bioskey(1) == 0) ; /* Wait... */
if ((bioskey(0) & 0x7F) == 3) exit(1); /* Check for ^C */
putchar('\n');
done = false;
/*
* Determine number of sectors per track and allocate buffers.
*/
spt = nsects(drive);
buflength = spt * SECTORSIZE;
buffer = (char *)malloc(buflength);
printf("Number of sectors per track for this disk is %d\n", spt);
printf("Writing image to drive %c:. Press ^C to abort.\n", drive+'A');
/*
* Start writing data to diskette until there is no more data to write.
*/
head = track = 0;
while ((count = read(fdin, buffer, buflength)) > 0 && !done) {
pbuf = buffer;
for (ns = 1; count > 0 && !done; ns+=3) {
printf("Track: %02d Head: %2d Sector: %2d\r", track, head, ns);
status = biosdisk(WRITE, drive, head, track, ns, 3, pbuf);
if (status != 0) Error(status);
count -= (3*SECTORSIZE);
pbuf += (3*SECTORSIZE);
}
if ((head = (head + 1) & 1) == 0) ++track;
}
if (eof(fdin)) {
printf("\nDone.\n");
biosdisk(2, drive, 0, 0, 1, 1, buffer); /* Retract head */
}
} /* end main */