xref: /netbsd/sys/arch/i386/stand/misc/rawrite.c (revision f00c5400)
143df8ed2Stv /*
243df8ed2Stv  rawrite.c	Write a binary image to a 360K diskette.
343df8ed2Stv 		By Mark Becker
443df8ed2Stv 
543df8ed2Stv  Usage:
643df8ed2Stv 	MS-DOS prompt> RAWRITE
743df8ed2Stv 
843df8ed2Stv 	And follow the prompts.
943df8ed2Stv 
1043df8ed2Stv History
1143df8ed2Stv -------
1243df8ed2Stv 
1343df8ed2Stv   1.0	-	Initial release
1443df8ed2Stv   1.1	-	Beta test (fixing bugs)				4/5/91
1543df8ed2Stv   		Some BIOS's don't like full-track writes.
1643df8ed2Stv   1.101	-	Last beta release.				4/8/91
1743df8ed2Stv   		Fixed BIOS full-track write by only
1843df8ed2Stv 		writing 3 sectors at a time.
1943df8ed2Stv   1.2	-	Final code and documentation clean-ups.		4/9/91
2043df8ed2Stv */
2143df8ed2Stv #include <alloc.h>
2243df8ed2Stv #include <bios.h>
2343df8ed2Stv #include <ctype.h>
2443df8ed2Stv #include <dir.h>
2543df8ed2Stv #include <dos.h>
2643df8ed2Stv #include <io.h>
2743df8ed2Stv #include <fcntl.h>
2843df8ed2Stv #include <stdio.h>
2943df8ed2Stv #include <stdlib.h>
3043df8ed2Stv 
3143df8ed2Stv #define SECTORSIZE	512
3243df8ed2Stv 
3343df8ed2Stv #define	RESET	0
3443df8ed2Stv #define	LAST	1
3543df8ed2Stv #define	READ	2
3643df8ed2Stv #define	WRITE	3
3743df8ed2Stv #define	VERIFY	4
3843df8ed2Stv #define	FORMAT	5
3943df8ed2Stv 
4043df8ed2Stv int	done;
4143df8ed2Stv 
4243df8ed2Stv /*
4343df8ed2Stv  Catch ^C and ^Break.
4443df8ed2Stv */
handler(void)4543df8ed2Stv int	handler(void)
4643df8ed2Stv {
47*f00c5400Sthorpej   done = true;
4843df8ed2Stv   return(0);
4943df8ed2Stv }
msg(char (* s))5043df8ed2Stv void msg(char (*s))
5143df8ed2Stv {
5243df8ed2Stv 	fprintf(stderr, "%s\n", s);
5343df8ed2Stv 	_exit(1);
5443df8ed2Stv }
5543df8ed2Stv /*
5643df8ed2Stv  Identify the error code with a real error message.
5743df8ed2Stv */
Error(int (status))5843df8ed2Stv void Error(int (status))
5943df8ed2Stv {
6043df8ed2Stv   switch (status) {
6143df8ed2Stv     case 0x00:	msg("Operation Successful");				break;
6243df8ed2Stv     case 0x01:	msg("Bad command");					break;
6343df8ed2Stv     case 0x02:	msg("Address mark not found");				break;
6443df8ed2Stv     case 0x03:	msg("Attempt to write on write-protected disk");	break;
6543df8ed2Stv     case 0x04:	msg("Sector not found");				break;
6643df8ed2Stv     case 0x05:	msg("Reset failed (hard disk)");			break;
6743df8ed2Stv     case 0x06:	msg("Disk changed since last operation");		break;
6843df8ed2Stv     case 0x07:	msg("Drive parameter activity failed");			break;
6943df8ed2Stv     case 0x08:	msg("DMA overrun");					break;
7043df8ed2Stv     case 0x09:	msg("Attempt to DMA across 64K boundary");		break;
7143df8ed2Stv     case 0x0A:	msg("Bad sector detected");				break;
7243df8ed2Stv     case 0x0B:	msg("Bad track detected");				break;
7343df8ed2Stv     case 0x0C:	msg("Unsupported track");				break;
7443df8ed2Stv     case 0x10:	msg("Bad CRC/ECC on disk read");			break;
7543df8ed2Stv     case 0x11:	msg("CRC/ECC corrected data error");			break;
7643df8ed2Stv     case 0x20:	msg("Controller has failed");				break;
7743df8ed2Stv     case 0x40:	msg("Seek operation failed");				break;
7843df8ed2Stv     case 0x80:	msg("Attachment failed to respond");			break;
7943df8ed2Stv     case 0xAA:	msg("Drive not ready (hard disk only");			break;
8043df8ed2Stv     case 0xBB:	msg("Undefined error occurred (hard disk only)");	break;
8143df8ed2Stv     case 0xCC:	msg("Write fault occurred");				break;
8243df8ed2Stv     case 0xE0:	msg("Status error");					break;
8343df8ed2Stv     case 0xFF:	msg("Sense operation failed");				break;
8443df8ed2Stv   }
8543df8ed2Stv   _exit(1);
8643df8ed2Stv }
8743df8ed2Stv 
8843df8ed2Stv /*
8943df8ed2Stv  Identify what kind of diskette is installed in the specified drive.
9043df8ed2Stv  Return the number of sectors per track assumed as follows:
9143df8ed2Stv  9	-	360 K and 720 K 5.25".
9243df8ed2Stv 15	-	1.2 M HD	5.25".
9343df8ed2Stv 18	-	1.44 M		3.5".
9443df8ed2Stv */
nsects(int (drive))9543df8ed2Stv int nsects(int (drive))
9643df8ed2Stv {
9743df8ed2Stv   static	int	nsect[] = {18, 15, 9};
9843df8ed2Stv 
9943df8ed2Stv   char	*buffer;
10043df8ed2Stv   int	i, status;
10143df8ed2Stv /*
10243df8ed2Stv  Read sector 1, head 0, track 0 to get the BIOS running.
10343df8ed2Stv */
10443df8ed2Stv   buffer = (char *)malloc(SECTORSIZE);
10543df8ed2Stv   biosdisk(RESET, drive, 0, 0, 0, 0, buffer);
10643df8ed2Stv   status = biosdisk(READ, drive, 0, 10, 1, 1, buffer);
10743df8ed2Stv   if (status == 0x06)			/* Door signal change?	*/
10843df8ed2Stv   status = biosdisk(READ, drive, 0, 0, 1, 1, buffer);
10943df8ed2Stv 
11043df8ed2Stv   for (i=0; i < sizeof(nsect)/sizeof(int); ++i) {
11143df8ed2Stv     biosdisk(RESET, drive, 0, 0, 0, 0, buffer);
11243df8ed2Stv     status = biosdisk(READ, drive, 0, 0, nsect[i], 1, buffer);
11343df8ed2Stv     if (status == 0x06)
11443df8ed2Stv       status = biosdisk(READ, drive, 0, 0, nsect[i], 1, buffer);
11543df8ed2Stv       if (status == 0x00) break;
11643df8ed2Stv     }
11743df8ed2Stv     if (i == sizeof(nsect)/sizeof(int)) {
11843df8ed2Stv       msg("Can't figure out how many sectors/track for this diskette.");
11943df8ed2Stv     }
12043df8ed2Stv     free(buffer);
12143df8ed2Stv     return(nsect[i]);
12243df8ed2Stv }
12343df8ed2Stv 
main(void)12443df8ed2Stv void main(void)
12543df8ed2Stv {
12643df8ed2Stv   char	 fname[MAXPATH];
12743df8ed2Stv   char	*buffer, *pbuf;
12843df8ed2Stv   int	 count, fdin, drive, head, track, status, spt, buflength, ns;
12943df8ed2Stv 
13043df8ed2Stv   puts("RaWrite 1.2 - Write disk file to raw floppy diskette\n");
13143df8ed2Stv   ctrlbrk(handler);
13243df8ed2Stv   printf("Enter source file name: ");
13343df8ed2Stv   scanf("%s", fname);
13443df8ed2Stv   _fmode = O_BINARY;
13543df8ed2Stv   if ((fdin = open(fname, O_RDONLY)) <= 0) {
13643df8ed2Stv      perror(fname);
13743df8ed2Stv      exit(1);
13843df8ed2Stv   }
13943df8ed2Stv 
14043df8ed2Stv   printf("Enter destination drive: ");
14143df8ed2Stv   scanf("%s", fname);
142225615a6Sdsl   drive = (fname[0] - 'A') & 0xf;
14343df8ed2Stv   printf("Please insert a formatted diskette into ");
14443df8ed2Stv   printf("drive %c: and press -ENTER- :", drive + 'A');
14543df8ed2Stv   while (bioskey(1) == 0) ;				/* Wait...	*/
14643df8ed2Stv   if ((bioskey(0) & 0x7F) == 3) exit(1);		/* Check for ^C	*/
14743df8ed2Stv   putchar('\n');
148*f00c5400Sthorpej   done = false;
14943df8ed2Stv /*
15043df8ed2Stv  * Determine number of sectors per track and allocate buffers.
15143df8ed2Stv  */
15243df8ed2Stv   spt = nsects(drive);
15343df8ed2Stv   buflength = spt * SECTORSIZE;
15443df8ed2Stv   buffer = (char *)malloc(buflength);
15543df8ed2Stv   printf("Number of sectors per track for this disk is %d\n", spt);
15643df8ed2Stv   printf("Writing image to drive %c:.  Press ^C to abort.\n", drive+'A');
15743df8ed2Stv /*
15843df8ed2Stv  * Start writing data to diskette until there is no more data to write.
15943df8ed2Stv  */
16043df8ed2Stv    head = track = 0;
16143df8ed2Stv    while ((count = read(fdin, buffer, buflength)) > 0 && !done) {
16243df8ed2Stv      pbuf = buffer;
16343df8ed2Stv      for (ns = 1; count > 0 && !done; ns+=3) {
16443df8ed2Stv        printf("Track: %02d  Head: %2d Sector: %2d\r", track, head, ns);
16543df8ed2Stv        status = biosdisk(WRITE, drive, head, track, ns, 3, pbuf);
16643df8ed2Stv 
16743df8ed2Stv        if (status != 0) Error(status);
16843df8ed2Stv 
16943df8ed2Stv        count -= (3*SECTORSIZE);
17043df8ed2Stv        pbuf  += (3*SECTORSIZE);
17143df8ed2Stv      }
17243df8ed2Stv      if ((head = (head + 1) & 1) == 0) ++track;
17343df8ed2Stv    }
17443df8ed2Stv    if (eof(fdin)) {
17543df8ed2Stv      printf("\nDone.\n");
17643df8ed2Stv      biosdisk(2, drive, 0, 0, 1, 1, buffer);		/* Retract head	*/
17743df8ed2Stv    }
17843df8ed2Stv }	/* end main */
179