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 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 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 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