fdwrite.c revision 22997
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@login.dkuug.dk> wrote this file.  As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 *
9 * $Id$
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
16#include <fcntl.h>
17#include <strings.h>
18#include <ctype.h>
19
20#include <errno.h>
21#include <machine/ioctl_fd.h>
22
23int
24format_track(int fd, int cyl, int secs, int head, int rate,
25     int gaplen, int secsize, int fill,int interleave)
26{
27    struct fd_formb f;
28    register int i,j;
29    int il[100];
30
31    memset(il,0,sizeof il);
32    for(j = 0, i = 1; i <= secs; i++) {
33	while(il[(j%secs)+1]) j++;
34	il[(j%secs)+1] = i;
35	j += interleave;
36    }
37
38    f.format_version = FD_FORMAT_VERSION;
39    f.head = head;
40    f.cyl = cyl;
41    f.transfer_rate = rate;
42
43    f.fd_formb_secshift = secsize;
44    f.fd_formb_nsecs = secs;
45    f.fd_formb_gaplen = gaplen;
46    f.fd_formb_fillbyte = fill;
47    for(i = 0; i < secs; i++) {
48	f.fd_formb_cylno(i) = cyl;
49	f.fd_formb_headno(i) = head;
50	f.fd_formb_secno(i) = il[i+1];
51	f.fd_formb_secsize(i) = secsize;
52    }
53    return ioctl(fd, FD_FORM, (caddr_t)&f);
54}
55
56static void
57usage ()
58{
59	printf("Usage:\n\tfdwrite [-v] [-y] [-f inputfile] [-d device]\n");
60	exit(2);
61}
62
63int
64main(int argc, char **argv)
65{
66    int inputfd = -1, c, fdn = 0, i,j,fd;
67    int bpt, verbose=1, nbytes=0, track;
68    int interactive = 1;
69    char *device= "/dev/rfd0", *trackbuf = 0,*vrfybuf = 0;
70    struct fd_type fdt;
71    FILE *tty;
72
73    setbuf(stdout,0);
74    while((c = getopt(argc, argv, "d:s:f:vy")) != -1)
75	    switch(c) {
76	    case 'd':	/* Which drive */
77		    device = optarg;
78		    break;
79
80	    case 'f':	/* input file */
81		    if (inputfd >= 0)
82			    close(inputfd);
83		    inputfd = open(optarg,O_RDONLY);
84		    if (inputfd < 0) {
85			    perror(optarg);
86			    exit(1);
87		    }
88		    break;
89
90	    case 'v':  /* Toggle verbosity */
91		    verbose = !verbose;
92		    break;
93
94	    case 'y':  /* Don't confirm? */
95		    interactive = 0;
96		    break;
97
98	    case '?': default:
99		    usage();
100	    }
101
102    if (inputfd < 0)
103	inputfd = 0;
104
105    if (!isatty(1))
106	interactive = 0;
107
108    if(optind < argc)
109	    usage();
110
111    tty = fopen("/dev/tty","r+");
112    if(!tty) {
113	    perror("/dev/tty");
114	    exit(1);
115    }
116    setbuf(tty,0);
117
118    for(j=1;j > 0;) {
119        fdn++;
120	if (interactive) {
121	    fprintf(tty,
122		    "Please insert floppy #%d in drive %s and press return >",
123		    fdn,device);
124	    while(1) {
125		i = getc(tty);
126		if(i == '\n') break;
127	    }
128	}
129
130	if((fd = open(device, O_RDWR)) < 0) {
131	    perror(device);
132	    exit(1);
133	}
134
135	if(ioctl(fd, FD_GTYPE, &fdt) < 0) {
136	    fprintf(stderr, "fdformat: not a floppy disk: %s\n", device);
137	    exit(1);
138	}
139
140	bpt = fdt.sectrac * (1<<fdt.secsize) * 128;
141	if(!trackbuf) {
142	    trackbuf = malloc(bpt);
143	    if(!trackbuf) { perror("malloc"); exit(1); }
144	}
145	if(!vrfybuf) {
146	    vrfybuf = malloc(bpt);
147	    if(!vrfybuf) { perror("malloc"); exit(1); }
148	}
149
150	if(fdn == 1) {
151	    if(verbose) {
152		printf("Format: %d cylinders, %d heads, %d sectors, %d bytes = %dkb\n",
153		fdt.tracks,fdt.heads,fdt.sectrac,(1<<fdt.secsize) * 128,
154		fdt.tracks*bpt*fdt.heads/1024);
155
156	    }
157	    memset(trackbuf,0,bpt);
158	    for(j=0;inputfd >= 0 && j<bpt;j+=i) {
159		if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
160		    close(inputfd);
161		    inputfd = -1;
162		    break;
163		}
164		nbytes += i;
165	    }
166	}
167	for (track = 0; track < fdt.tracks * fdt.heads; track++) {
168	    if(verbose) printf("\r%3d ",fdt.tracks * fdt.heads-track);
169	    if(verbose) putc((j ? 'I':'Z'),stdout);
170	    format_track(fd, track / fdt.heads, fdt.sectrac, track % fdt.heads,
171		    fdt.trans, fdt.f_gap, fdt.secsize, 0xe6,
172		    fdt.f_inter);
173	    if(verbose) putc('F',stdout);
174
175	    if (lseek (fd, (long) track*bpt, 0) < 0) {
176		perror("lseek");
177		exit (1);
178	    }
179	    if (write (fd, trackbuf, bpt) != bpt) {
180		perror("write");
181		exit (1);
182	    }
183	    if(verbose) putc('W',stdout);
184
185	    if (lseek (fd, (long) track*bpt, 0) < 0) {
186		perror("lseek");
187		exit (1);
188	    }
189	    if (read (fd, vrfybuf, bpt) != bpt) {
190		perror("read");
191		exit (1);
192	    }
193	    if(verbose) putc('R',stdout);
194
195	    if (memcmp(trackbuf,vrfybuf,bpt)) {
196		perror("compare");
197		exit (1);
198	    }
199	    if(verbose) putc('C',stdout);
200
201	    memset(trackbuf,0,bpt);
202	    for(j=0;inputfd >= 0 && j<bpt;j+=i) {
203		if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
204		    close(inputfd);
205		    inputfd = -1;
206		    break;
207		}
208		nbytes += i;
209	    }
210	}
211	close(fd);
212	putc('\r',stdout);
213    }
214    if(verbose)
215	printf("%d bytes on %d flopp%s\n",nbytes,fdn,fdn==1?"y":"ies");
216    exit(0);
217}
218