164de3fddSPedro F. Giffuni /*-
264de3fddSPedro F. Giffuni * SPDX-License-Identifier: Beerware
364de3fddSPedro F. Giffuni *
4b5173cbeSPoul-Henning Kamp * ----------------------------------------------------------------------------
5b5173cbeSPoul-Henning Kamp * "THE BEER-WARE LICENSE" (Revision 42):
606229ad2SPoul-Henning Kamp * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
7b5173cbeSPoul-Henning Kamp * can do whatever you want with this stuff. If we meet some day, and you think
8b5173cbeSPoul-Henning Kamp * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
9b5173cbeSPoul-Henning Kamp * ----------------------------------------------------------------------------
10b5173cbeSPoul-Henning Kamp *
11b5173cbeSPoul-Henning Kamp */
12b5173cbeSPoul-Henning Kamp
13d682bccfSPhilippe Charnier #include <err.h>
14d682bccfSPhilippe Charnier #include <fcntl.h>
151a37aa56SDavid E. O'Brien #include <paths.h>
16b5173cbeSPoul-Henning Kamp #include <stdio.h>
17b5173cbeSPoul-Henning Kamp #include <stdlib.h>
182e3cf203SStefan Farfeleder #include <string.h>
19d682bccfSPhilippe Charnier #include <unistd.h>
20b5173cbeSPoul-Henning Kamp
21d137c337SJoerg Wunsch #include <sys/fdcio.h>
22b5173cbeSPoul-Henning Kamp
234c1f1c62SXin LI static int
format_track(int fd,int cyl,int secs,int head,int rate,int gaplen,int secsize,int fill,int interleave)24b5173cbeSPoul-Henning Kamp format_track(int fd, int cyl, int secs, int head, int rate,
25b5173cbeSPoul-Henning Kamp int gaplen, int secsize, int fill, int interleave)
26b5173cbeSPoul-Henning Kamp {
27b5173cbeSPoul-Henning Kamp struct fd_formb f;
28*16e5eb21Srilysh int i, j;
29b5173cbeSPoul-Henning Kamp int il[100];
30b5173cbeSPoul-Henning Kamp
31b5173cbeSPoul-Henning Kamp memset(il,0,sizeof il);
32b5173cbeSPoul-Henning Kamp for(j = 0, i = 1; i <= secs; i++) {
33b5173cbeSPoul-Henning Kamp while(il[(j%secs)+1]) j++;
34b5173cbeSPoul-Henning Kamp il[(j%secs)+1] = i;
35b5173cbeSPoul-Henning Kamp j += interleave;
36b5173cbeSPoul-Henning Kamp }
37b5173cbeSPoul-Henning Kamp
38b5173cbeSPoul-Henning Kamp f.format_version = FD_FORMAT_VERSION;
39b5173cbeSPoul-Henning Kamp f.head = head;
40b5173cbeSPoul-Henning Kamp f.cyl = cyl;
41b5173cbeSPoul-Henning Kamp f.transfer_rate = rate;
42b5173cbeSPoul-Henning Kamp
43b5173cbeSPoul-Henning Kamp f.fd_formb_secshift = secsize;
44b5173cbeSPoul-Henning Kamp f.fd_formb_nsecs = secs;
45b5173cbeSPoul-Henning Kamp f.fd_formb_gaplen = gaplen;
46b5173cbeSPoul-Henning Kamp f.fd_formb_fillbyte = fill;
47b5173cbeSPoul-Henning Kamp for(i = 0; i < secs; i++) {
48b5173cbeSPoul-Henning Kamp f.fd_formb_cylno(i) = cyl;
49b5173cbeSPoul-Henning Kamp f.fd_formb_headno(i) = head;
50b5173cbeSPoul-Henning Kamp f.fd_formb_secno(i) = il[i+1];
51b5173cbeSPoul-Henning Kamp f.fd_formb_secsize(i) = secsize;
52b5173cbeSPoul-Henning Kamp }
53b5173cbeSPoul-Henning Kamp return ioctl(fd, FD_FORM, (caddr_t)&f);
54b5173cbeSPoul-Henning Kamp }
55b5173cbeSPoul-Henning Kamp
56b5173cbeSPoul-Henning Kamp static void
usage(void)574c1f1c62SXin LI usage(void)
58b5173cbeSPoul-Henning Kamp {
59d682bccfSPhilippe Charnier fprintf(stderr, "usage: fdwrite [-v] [-y] [-f inputfile] [-d device]\n");
60b5173cbeSPoul-Henning Kamp exit(2);
61b5173cbeSPoul-Henning Kamp }
62b5173cbeSPoul-Henning Kamp
63b5173cbeSPoul-Henning Kamp int
main(int argc,char ** argv)64b5173cbeSPoul-Henning Kamp main(int argc, char **argv)
65b5173cbeSPoul-Henning Kamp {
66b5173cbeSPoul-Henning Kamp int inputfd = -1, c, fdn = 0, i,j,fd;
67b5173cbeSPoul-Henning Kamp int bpt, verbose=1, nbytes=0, track;
6881f5cd99SJoerg Wunsch int interactive = 1;
694c1f1c62SXin LI const char *device= "/dev/fd0";
70*16e5eb21Srilysh char *trackbuf = NULL, *vrfybuf = NULL;
71b5173cbeSPoul-Henning Kamp struct fd_type fdt;
72b5173cbeSPoul-Henning Kamp FILE *tty;
73b5173cbeSPoul-Henning Kamp
74b5173cbeSPoul-Henning Kamp setbuf(stdout,0);
75d682bccfSPhilippe Charnier while((c = getopt(argc, argv, "d:f:vy")) != -1)
76b5173cbeSPoul-Henning Kamp switch(c) {
77b5173cbeSPoul-Henning Kamp case 'd': /* Which drive */
78b5173cbeSPoul-Henning Kamp device = optarg;
79b5173cbeSPoul-Henning Kamp break;
80b5173cbeSPoul-Henning Kamp
81b5173cbeSPoul-Henning Kamp case 'f': /* input file */
82b5173cbeSPoul-Henning Kamp if (inputfd >= 0)
83b5173cbeSPoul-Henning Kamp close(inputfd);
84b5173cbeSPoul-Henning Kamp inputfd = open(optarg,O_RDONLY);
85d682bccfSPhilippe Charnier if (inputfd < 0)
86d682bccfSPhilippe Charnier err(1, "%s", optarg);
87b5173cbeSPoul-Henning Kamp break;
88b5173cbeSPoul-Henning Kamp
89b5173cbeSPoul-Henning Kamp case 'v': /* Toggle verbosity */
90b5173cbeSPoul-Henning Kamp verbose = !verbose;
91b5173cbeSPoul-Henning Kamp break;
92b5173cbeSPoul-Henning Kamp
9346889276SJordan K. Hubbard case 'y': /* Don't confirm? */
9446889276SJordan K. Hubbard interactive = 0;
9546889276SJordan K. Hubbard break;
9646889276SJordan K. Hubbard
97b5173cbeSPoul-Henning Kamp case '?': default:
98b5173cbeSPoul-Henning Kamp usage();
99b5173cbeSPoul-Henning Kamp }
100b5173cbeSPoul-Henning Kamp
101b5173cbeSPoul-Henning Kamp if (inputfd < 0)
102b5173cbeSPoul-Henning Kamp inputfd = 0;
103b5173cbeSPoul-Henning Kamp
10446889276SJordan K. Hubbard if (!isatty(1))
10546889276SJordan K. Hubbard interactive = 0;
10646889276SJordan K. Hubbard
107b5173cbeSPoul-Henning Kamp if(optind < argc)
108b5173cbeSPoul-Henning Kamp usage();
109b5173cbeSPoul-Henning Kamp
1101a37aa56SDavid E. O'Brien tty = fopen(_PATH_TTY,"r+");
111d682bccfSPhilippe Charnier if(!tty)
1121a37aa56SDavid E. O'Brien err(1, _PATH_TTY);
113b5173cbeSPoul-Henning Kamp setbuf(tty,0);
114b5173cbeSPoul-Henning Kamp
115b5173cbeSPoul-Henning Kamp for(j=1;j > 0;) {
116b5173cbeSPoul-Henning Kamp fdn++;
11746889276SJordan K. Hubbard if (interactive) {
118b5173cbeSPoul-Henning Kamp fprintf(tty,
119b5173cbeSPoul-Henning Kamp "Please insert floppy #%d in drive %s and press return >",
120b5173cbeSPoul-Henning Kamp fdn,device);
121b5173cbeSPoul-Henning Kamp while(1) {
122b5173cbeSPoul-Henning Kamp i = getc(tty);
123b5173cbeSPoul-Henning Kamp if(i == '\n') break;
124b5173cbeSPoul-Henning Kamp }
12546889276SJordan K. Hubbard }
126b5173cbeSPoul-Henning Kamp
127d682bccfSPhilippe Charnier if((fd = open(device, O_RDWR)) < 0)
128d682bccfSPhilippe Charnier err(1, "%s", device);
129b5173cbeSPoul-Henning Kamp
130d682bccfSPhilippe Charnier if(ioctl(fd, FD_GTYPE, &fdt) < 0)
131d682bccfSPhilippe Charnier errx(1, "not a floppy disk: %s", device);
132b5173cbeSPoul-Henning Kamp
133b5173cbeSPoul-Henning Kamp bpt = fdt.sectrac * (1<<fdt.secsize) * 128;
134b5173cbeSPoul-Henning Kamp if(!trackbuf) {
135b5173cbeSPoul-Henning Kamp trackbuf = malloc(bpt);
136d682bccfSPhilippe Charnier if(!trackbuf) errx(1, "malloc");
137b5173cbeSPoul-Henning Kamp }
138b5173cbeSPoul-Henning Kamp if(!vrfybuf) {
139b5173cbeSPoul-Henning Kamp vrfybuf = malloc(bpt);
140d682bccfSPhilippe Charnier if(!vrfybuf) errx(1, "malloc");
141b5173cbeSPoul-Henning Kamp }
142b5173cbeSPoul-Henning Kamp
143b5173cbeSPoul-Henning Kamp if(fdn == 1) {
144b5173cbeSPoul-Henning Kamp if(verbose) {
145b5173cbeSPoul-Henning Kamp printf("Format: %d cylinders, %d heads, %d sectors, %d bytes = %dkb\n",
146b5173cbeSPoul-Henning Kamp fdt.tracks,fdt.heads,fdt.sectrac,(1<<fdt.secsize) * 128,
147b5173cbeSPoul-Henning Kamp fdt.tracks*bpt*fdt.heads/1024);
148b5173cbeSPoul-Henning Kamp
149b5173cbeSPoul-Henning Kamp }
150b5173cbeSPoul-Henning Kamp memset(trackbuf,0,bpt);
151b5173cbeSPoul-Henning Kamp for(j=0;inputfd >= 0 && j<bpt;j+=i) {
152b5173cbeSPoul-Henning Kamp if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
153b5173cbeSPoul-Henning Kamp close(inputfd);
154b5173cbeSPoul-Henning Kamp inputfd = -1;
155b5173cbeSPoul-Henning Kamp break;
156b5173cbeSPoul-Henning Kamp }
157b5173cbeSPoul-Henning Kamp nbytes += i;
158b5173cbeSPoul-Henning Kamp }
159b5173cbeSPoul-Henning Kamp }
160b5173cbeSPoul-Henning Kamp for (track = 0; track < fdt.tracks * fdt.heads; track++) {
161b5173cbeSPoul-Henning Kamp if(verbose) printf("\r%3d ",fdt.tracks * fdt.heads-track);
162b5173cbeSPoul-Henning Kamp if(verbose) putc((j ? 'I':'Z'),stdout);
163b5173cbeSPoul-Henning Kamp format_track(fd, track / fdt.heads, fdt.sectrac, track % fdt.heads,
164b5173cbeSPoul-Henning Kamp fdt.trans, fdt.f_gap, fdt.secsize, 0xe6,
165b5173cbeSPoul-Henning Kamp fdt.f_inter);
166b5173cbeSPoul-Henning Kamp if(verbose) putc('F',stdout);
167b5173cbeSPoul-Henning Kamp
168d682bccfSPhilippe Charnier if (lseek (fd, (long) track*bpt, 0) < 0) err(1, "lseek");
169d682bccfSPhilippe Charnier if (write (fd, trackbuf, bpt) != bpt) err(1, "write");
170b5173cbeSPoul-Henning Kamp if(verbose) putc('W',stdout);
171b5173cbeSPoul-Henning Kamp
172d682bccfSPhilippe Charnier if (lseek (fd, (long) track*bpt, 0) < 0) err(1, "lseek");
173d682bccfSPhilippe Charnier if (read (fd, vrfybuf, bpt) != bpt) err(1, "read");
174b5173cbeSPoul-Henning Kamp if(verbose) putc('R',stdout);
175b5173cbeSPoul-Henning Kamp
176d682bccfSPhilippe Charnier if (memcmp(trackbuf,vrfybuf,bpt)) err(1, "compare");
177b5173cbeSPoul-Henning Kamp if(verbose) putc('C',stdout);
178b5173cbeSPoul-Henning Kamp
179b5173cbeSPoul-Henning Kamp memset(trackbuf,0,bpt);
180b5173cbeSPoul-Henning Kamp for(j=0;inputfd >= 0 && j<bpt;j+=i) {
181b5173cbeSPoul-Henning Kamp if(!(i = read(inputfd,trackbuf+j,bpt-j))) {
182b5173cbeSPoul-Henning Kamp close(inputfd);
183b5173cbeSPoul-Henning Kamp inputfd = -1;
184b5173cbeSPoul-Henning Kamp break;
185b5173cbeSPoul-Henning Kamp }
186b5173cbeSPoul-Henning Kamp nbytes += i;
187b5173cbeSPoul-Henning Kamp }
188b5173cbeSPoul-Henning Kamp }
189b5173cbeSPoul-Henning Kamp close(fd);
190b5173cbeSPoul-Henning Kamp putc('\r',stdout);
191b5173cbeSPoul-Henning Kamp }
192b5173cbeSPoul-Henning Kamp if(verbose)
193b5173cbeSPoul-Henning Kamp printf("%d bytes on %d flopp%s\n",nbytes,fdn,fdn==1?"y":"ies");
194*16e5eb21Srilysh
195*16e5eb21Srilysh free(trackbuf);
196*16e5eb21Srilysh free(vrfybuf);
197b5173cbeSPoul-Henning Kamp exit(0);
198b5173cbeSPoul-Henning Kamp }
199