12849Sphk/*
22849Sphk * ----------------------------------------------------------------------------
32849Sphk * "THE BEER-WARE LICENSE" (Revision 42):
493150Sphk * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
52849Sphk * can do whatever you want with this stuff. If we meet some day, and you think
62849Sphk * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
72849Sphk * ----------------------------------------------------------------------------
82849Sphk *
950479Speter * $FreeBSD$
102849Sphk *
112849Sphk */
122849Sphk
1329559Scharnier#include <ctype.h>
1429559Scharnier#include <err.h>
1529559Scharnier#include <fcntl.h>
1669793Sobrien#include <paths.h>
172849Sphk#include <stdio.h>
182849Sphk#include <stdlib.h>
19129863Sstefanf#include <string.h>
202849Sphk#include <unistd.h>
212849Sphk
2277801Sjoerg#include <sys/fdcio.h>
232849Sphk
24139905Sdelphijstatic int
252849Sphkformat_track(int fd, int cyl, int secs, int head, int rate,
26139905Sdelphij     int gaplen, int secsize, int fill, int interleave)
272849Sphk{
282849Sphk    struct fd_formb f;
292849Sphk    register int i,j;
302849Sphk    int il[100];
312849Sphk
322849Sphk    memset(il,0,sizeof il);
332849Sphk    for(j = 0, i = 1; i <= secs; i++) {
342849Sphk	while(il[(j%secs)+1]) j++;
352849Sphk	il[(j%secs)+1] = i;
362849Sphk	j += interleave;
372849Sphk    }
382849Sphk
392849Sphk    f.format_version = FD_FORMAT_VERSION;
402849Sphk    f.head = head;
412849Sphk    f.cyl = cyl;
422849Sphk    f.transfer_rate = rate;
432849Sphk
442849Sphk    f.fd_formb_secshift = secsize;
452849Sphk    f.fd_formb_nsecs = secs;
462849Sphk    f.fd_formb_gaplen = gaplen;
472849Sphk    f.fd_formb_fillbyte = fill;
482849Sphk    for(i = 0; i < secs; i++) {
492849Sphk	f.fd_formb_cylno(i) = cyl;
502849Sphk	f.fd_formb_headno(i) = head;
512849Sphk	f.fd_formb_secno(i) = il[i+1];
522849Sphk	f.fd_formb_secsize(i) = secsize;
532849Sphk    }
542849Sphk    return ioctl(fd, FD_FORM, (caddr_t)&f);
552849Sphk}
562849Sphk
572849Sphkstatic void
58139905Sdelphijusage(void)
592849Sphk{
6029559Scharnier	fprintf(stderr, "usage: fdwrite [-v] [-y] [-f inputfile] [-d device]\n");
612849Sphk	exit(2);
622849Sphk}
632849Sphk
642849Sphkint
652849Sphkmain(int argc, char **argv)
662849Sphk{
672849Sphk    int inputfd = -1, c, fdn = 0, i,j,fd;
682849Sphk    int bpt, verbose=1, nbytes=0, track;
69194892Sjoerg    int interactive = 1;
70139905Sdelphij    const char *device= "/dev/fd0";
71139905Sdelphij    char *trackbuf = 0,*vrfybuf = 0;
722849Sphk    struct fd_type fdt;
732849Sphk    FILE *tty;
742849Sphk
752849Sphk    setbuf(stdout,0);
7629559Scharnier    while((c = getopt(argc, argv, "d:f:vy")) != -1)
772849Sphk	    switch(c) {
782849Sphk	    case 'd':	/* Which drive */
792849Sphk		    device = optarg;
802849Sphk		    break;
812849Sphk
822849Sphk	    case 'f':	/* input file */
832849Sphk		    if (inputfd >= 0)
842849Sphk			    close(inputfd);
852849Sphk		    inputfd = open(optarg,O_RDONLY);
8629559Scharnier		    if (inputfd < 0)
8729559Scharnier			    err(1, "%s", optarg);
882849Sphk		    break;
892849Sphk
902849Sphk	    case 'v':  /* Toggle verbosity */
912849Sphk		    verbose = !verbose;
922849Sphk		    break;
932849Sphk
9418573Sjkh	    case 'y':  /* Don't confirm? */
9518573Sjkh		    interactive = 0;
9618573Sjkh		    break;
9718573Sjkh
982849Sphk	    case '?': default:
992849Sphk		    usage();
1002849Sphk	    }
1012849Sphk
1022849Sphk    if (inputfd < 0)
1032849Sphk	inputfd = 0;
1042849Sphk
10518573Sjkh    if (!isatty(1))
10618573Sjkh	interactive = 0;
10718573Sjkh
1082849Sphk    if(optind < argc)
1092849Sphk	    usage();
1102849Sphk
11169793Sobrien    tty = fopen(_PATH_TTY,"r+");
11229559Scharnier    if(!tty)
11369793Sobrien	    err(1, _PATH_TTY);
1142849Sphk    setbuf(tty,0);
1152849Sphk
1162849Sphk    for(j=1;j > 0;) {
1172849Sphk        fdn++;
11818573Sjkh	if (interactive) {
11918573Sjkh	    fprintf(tty,
12018573Sjkh		    "Please insert floppy #%d in drive %s and press return >",
12118573Sjkh		    fdn,device);
12218573Sjkh	    while(1) {
12318573Sjkh		i = getc(tty);
12418573Sjkh		if(i == '\n') break;
12518573Sjkh	    }
1262849Sphk	}
1272849Sphk
12829559Scharnier	if((fd = open(device, O_RDWR)) < 0)
12929559Scharnier	    err(1, "%s", device);
1302849Sphk
13129559Scharnier	if(ioctl(fd, FD_GTYPE, &fdt) < 0)
13229559Scharnier	    errx(1, "not a floppy disk: %s", device);
1332849Sphk
1342849Sphk	bpt = fdt.sectrac * (1<<fdt.secsize) * 128;
1352849Sphk	if(!trackbuf) {
1362849Sphk	    trackbuf = malloc(bpt);
13729559Scharnier	    if(!trackbuf) errx(1, "malloc");
1382849Sphk	}
1392849Sphk	if(!vrfybuf) {
1402849Sphk	    vrfybuf = malloc(bpt);
14129559Scharnier	    if(!vrfybuf) errx(1, "malloc");
1422849Sphk	}
1432849Sphk
1442849Sphk	if(fdn == 1) {
1452849Sphk	    if(verbose) {
1462849Sphk		printf("Format: %d cylinders, %d heads, %d sectors, %d bytes = %dkb\n",
1472849Sphk		fdt.tracks,fdt.heads,fdt.sectrac,(1<<fdt.secsize) * 128,
1482849Sphk		fdt.tracks*bpt*fdt.heads/1024);
1498857Srgrimes
1502849Sphk	    }
1512849Sphk	    memset(trackbuf,0,bpt);
1522849Sphk	    for(j=0;inputfd >= 0 && j<bpt;j+=i) {
1532849Sphk		if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
1542849Sphk		    close(inputfd);
1552849Sphk		    inputfd = -1;
1562849Sphk		    break;
1572849Sphk		}
1582849Sphk		nbytes += i;
1592849Sphk	    }
1602849Sphk	}
1612849Sphk	for (track = 0; track < fdt.tracks * fdt.heads; track++) {
1622849Sphk	    if(verbose) printf("\r%3d ",fdt.tracks * fdt.heads-track);
1632849Sphk	    if(verbose) putc((j ? 'I':'Z'),stdout);
1642849Sphk	    format_track(fd, track / fdt.heads, fdt.sectrac, track % fdt.heads,
1652849Sphk		    fdt.trans, fdt.f_gap, fdt.secsize, 0xe6,
1662849Sphk		    fdt.f_inter);
1672849Sphk	    if(verbose) putc('F',stdout);
1682849Sphk
16929559Scharnier	    if (lseek (fd, (long) track*bpt, 0) < 0) err(1, "lseek");
17029559Scharnier	    if (write (fd, trackbuf, bpt) != bpt) err(1, "write");
1712849Sphk	    if(verbose) putc('W',stdout);
1722849Sphk
17329559Scharnier	    if (lseek (fd, (long) track*bpt, 0) < 0) err(1, "lseek");
17429559Scharnier	    if (read (fd, vrfybuf, bpt) != bpt) err(1, "read");
1752849Sphk	    if(verbose) putc('R',stdout);
1762849Sphk
17729559Scharnier	    if (memcmp(trackbuf,vrfybuf,bpt)) err(1, "compare");
1782849Sphk	    if(verbose) putc('C',stdout);
1792849Sphk
1802849Sphk	    memset(trackbuf,0,bpt);
1812849Sphk	    for(j=0;inputfd >= 0 && j<bpt;j+=i) {
1822849Sphk		if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
1832849Sphk		    close(inputfd);
1842849Sphk		    inputfd = -1;
1852849Sphk		    break;
1862849Sphk		}
1872849Sphk		nbytes += i;
1882849Sphk	    }
1892849Sphk	}
1902849Sphk	close(fd);
1912849Sphk	putc('\r',stdout);
1922849Sphk    }
1932849Sphk    if(verbose)
1942849Sphk	printf("%d bytes on %d flopp%s\n",nbytes,fdn,fdn==1?"y":"ies");
1952849Sphk    exit(0);
1962849Sphk}
197