fdformat.c revision 61154
139665Smsmith/* 239665Smsmith * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden 339665Smsmith * All rights reserved. 439665Smsmith * 539665Smsmith * Redistribution and use in source and binary forms, with or without 639665Smsmith * modification, are permitted provided that the following conditions 739665Smsmith * are met: 839665Smsmith * 1. Redistributions of source code must retain the above copyright 939665Smsmith * notice, this list of conditions and the following disclaimer. 1039665Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1139665Smsmith * notice, this list of conditions and the following disclaimer in the 1239665Smsmith * documentation and/or other materials provided with the distribution. 1339665Smsmith * 1439665Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 1539665Smsmith * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1639665Smsmith * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1739665Smsmith * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, 1839665Smsmith * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1939665Smsmith * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2039665Smsmith * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2139665Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2239665Smsmith * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 2339665Smsmith * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2439665Smsmith * POSSIBILITY OF SUCH DAMAGE. 2539665Smsmith * 2639665Smsmith * $FreeBSD: head/usr.sbin/fdformat/fdformat.c 61154 2000-06-01 22:27:30Z phk $ 2739665Smsmith */ 2839665Smsmith 2939665Smsmith/* 3084221Sdillon * FreeBSD: 3184221Sdillon * format a floppy disk 3284221Sdillon * 3339665Smsmith * Added FD_GTYPE ioctl, verifying, proportional indicators. 3439665Smsmith * Serge Vakulenko, vak@zebub.msk.su 3539665Smsmith * Sat Dec 18 17:45:47 MSK 1993 3639665Smsmith * 3739665Smsmith * Final adaptation, change format/verify logic, add separate 3839665Smsmith * format gap/interleave values 3939665Smsmith * Andrew A. Chernov, ache@astral.msk.su 4039665Smsmith * Thu Jan 27 00:47:24 MSK 1994 4139665Smsmith */ 4239665Smsmith 4339665Smsmith#include <ctype.h> 4439665Smsmith#include <err.h> 4539665Smsmith#include <fcntl.h> 4639665Smsmith#include <stdio.h> 4739665Smsmith#include <stdlib.h> 4839665Smsmith#include <strings.h> 4939665Smsmith#include <unistd.h> 5039665Smsmith 5139665Smsmith#include <machine/ioctl_fd.h> 5239665Smsmith 5339665Smsmithstatic void 5439665Smsmithformat_track(int fd, int cyl, int secs, int head, int rate, 5539665Smsmith int gaplen, int secsize, int fill,int interleave) 5639665Smsmith{ 5739665Smsmith struct fd_formb f; 5839665Smsmith register int i,j; 5939665Smsmith int il[FD_MAX_NSEC + 1]; 6039665Smsmith 6139665Smsmith memset(il,0,sizeof il); 6239665Smsmith for(j = 0, i = 1; i <= secs; i++) { 6339665Smsmith while(il[(j%secs)+1]) j++; 6439665Smsmith il[(j%secs)+1] = i; 6539665Smsmith j += interleave; 6639665Smsmith } 6739665Smsmith 6839665Smsmith f.format_version = FD_FORMAT_VERSION; 6939665Smsmith f.head = head; 7039665Smsmith f.cyl = cyl; 7139665Smsmith f.transfer_rate = rate; 7239665Smsmith 7339665Smsmith f.fd_formb_secshift = secsize; 7439665Smsmith f.fd_formb_nsecs = secs; 7539665Smsmith f.fd_formb_gaplen = gaplen; 7639665Smsmith f.fd_formb_fillbyte = fill; 7739665Smsmith for(i = 0; i < secs; i++) { 7839665Smsmith f.fd_formb_cylno(i) = cyl; 7939665Smsmith f.fd_formb_headno(i) = head; 8039665Smsmith f.fd_formb_secno(i) = il[i+1]; 8139665Smsmith f.fd_formb_secsize(i) = secsize; 8239665Smsmith } 8339665Smsmith if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0) 8439665Smsmith err(1, "ioctl(FD_FORM)"); 8539665Smsmith} 8639665Smsmith 8739665Smsmithstatic int 8839665Smsmithverify_track(int fd, int track, int tracksize) 8939665Smsmith{ 9039665Smsmith static char *buf = 0; 9139665Smsmith static int bufsz = 0; 9239665Smsmith int fdopts = -1, ofdopts, rv = 0; 9339863Smsmith 9439863Smsmith if (ioctl(fd, FD_GOPTS, &fdopts) < 0) 9539665Smsmith warn("warning: ioctl(FD_GOPTS)"); 9639665Smsmith else { 9739665Smsmith ofdopts = fdopts; 9839665Smsmith fdopts |= FDOPT_NORETRY; 9939665Smsmith (void)ioctl(fd, FD_SOPTS, &fdopts); 10039665Smsmith } 10139863Smsmith 10239863Smsmith if (bufsz < tracksize) { 10339863Smsmith if (buf) 10439665Smsmith free (buf); 10539665Smsmith bufsz = tracksize; 10639863Smsmith buf = 0; 10739863Smsmith } 10839665Smsmith if (! buf) 10939665Smsmith buf = malloc (bufsz); 11039665Smsmith if (! buf) 11139665Smsmith errx(2, "out of memory"); 11239863Smsmith if (lseek (fd, (long) track*tracksize, 0) < 0) 11339665Smsmith rv = -1; 11439665Smsmith /* try twice reading it, without using the normal retrier */ 11539665Smsmith else if (read (fd, buf, tracksize) != tracksize 11639665Smsmith && read (fd, buf, tracksize) != tracksize) 11739665Smsmith rv = -1; 11839665Smsmith if(fdopts != -1) 11939665Smsmith (void)ioctl(fd, FD_SOPTS, &ofdopts); 12039665Smsmith return (rv); 12139665Smsmith} 12239665Smsmith 12339665Smsmithstatic const char * 12439665Smsmithmakename(const char *arg, const char *suffix) 12539665Smsmith{ 12639863Smsmith static char namebuff[20]; /* big enough for "/dev/fd0a"... */ 12739863Smsmith 12839863Smsmith memset(namebuff, 0, 20); 12939863Smsmith if(*arg == '\0') /* ??? */ 13039863Smsmith return arg; 13139665Smsmith if(*arg == '/') /* do not convert absolute pathnames */ 13239665Smsmith return arg; 13339665Smsmith strcpy(namebuff, "/dev/"); 13439665Smsmith strncat(namebuff, arg, 3); 13539665Smsmith strcat(namebuff, suffix); 13639665Smsmith return namebuff; 13739665Smsmith} 13839665Smsmith 13939665Smsmithstatic void 14039665Smsmithusage (void) 14139665Smsmith{ 14239665Smsmith fprintf(stderr, "%s\n%s\n", 14339665Smsmith "usage: fdformat [-y] [-q] [-n | -v] [-f #] [-c #] [-s #] [-h #]", 14439665Smsmith " [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] devname"); 14539665Smsmith exit(2); 14639665Smsmith} 14739665Smsmith 14839665Smsmithstatic int 14939665Smsmithyes (void) 15039665Smsmith{ 15139665Smsmith char reply [256], *p; 15239665Smsmith 15339665Smsmith reply[sizeof(reply)-1] = 0; 15439665Smsmith for (;;) { 15539665Smsmith fflush(stdout); 15639863Smsmith if (! fgets (reply, sizeof(reply)-1, stdin)) 157223854Savatar return (0); 15839665Smsmith for (p=reply; *p==' ' || *p=='\t'; ++p) 15939665Smsmith continue; 16039665Smsmith if (*p=='y' || *p=='Y') 16139665Smsmith return (1); 16239665Smsmith if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r') 16339665Smsmith return (0); 16439665Smsmith printf("Answer `yes' or `no': "); 16539665Smsmith } 16639665Smsmith} 16739665Smsmith 16839665Smsmithint 16939665Smsmithmain(int argc, char **argv) 17039665Smsmith{ 17139665Smsmith int format = -1, cyls = -1, secs = -1, heads = -1, intleave = -1; 17239665Smsmith int rate = -1, gaplen = -1, secsize = -1, steps = -1; 17339665Smsmith int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0, confirm = 0; 17439665Smsmith int fd, c, track, error, tracks_per_dot, bytes_per_track, errs; 17539665Smsmith const char *devname, *suffix; 17639665Smsmith struct fd_type fdt; 17739665Smsmith 17839665Smsmith while((c = getopt(argc, argv, "f:c:s:h:r:g:S:F:t:i:qyvn")) != -1) 17939665Smsmith switch(c) { 180223854Savatar case 'f': /* format in kilobytes */ 181223854Savatar format = atoi(optarg); 182223854Savatar break; 183223854Savatar 18439665Smsmith case 'c': /* # of cyls */ 18539665Smsmith cyls = atoi(optarg); 18639665Smsmith break; 18739665Smsmith 18839665Smsmith case 's': /* # of secs per track */ 18939665Smsmith secs = atoi(optarg); 19039665Smsmith break; 19139665Smsmith 19239665Smsmith case 'h': /* # of heads */ 19339665Smsmith heads = atoi(optarg); 19439665Smsmith break; 19539665Smsmith 19639665Smsmith case 'r': /* transfer rate, kilobyte/sec */ 19739665Smsmith rate = atoi(optarg); 19839665Smsmith break; 19939665Smsmith 20039665Smsmith case 'g': /* length of GAP3 to format with */ 20139665Smsmith gaplen = atoi(optarg); 20239665Smsmith break; 20339665Smsmith 20439665Smsmith case 'S': /* sector size shift factor (1 << S)*128 */ 20539665Smsmith secsize = atoi(optarg); 20639665Smsmith break; 20739665Smsmith 20839665Smsmith case 'F': /* fill byte, C-like notation allowed */ 20939665Smsmith fill = (int)strtol(optarg, (char **)0, 0); 21039665Smsmith break; 21139665Smsmith 21239665Smsmith case 't': /* steps per track */ 213223854Savatar steps = atoi(optarg); 214223854Savatar break; 215223854Savatar 216223854Savatar case 'i': /* interleave factor */ 21739665Smsmith intleave = atoi(optarg); 21839665Smsmith break; 21939665Smsmith 22039665Smsmith case 'q': 22139665Smsmith quiet = 1; 22239665Smsmith break; 22339665Smsmith 22439665Smsmith case 'y': 22539665Smsmith confirm = 1; 22639665Smsmith break; 22739665Smsmith 22839665Smsmith case 'n': 22939665Smsmith verify = 0; 23039665Smsmith break; 23139665Smsmith 23239665Smsmith case 'v': 23339665Smsmith verify = 1; 23439665Smsmith verify_only = 1; 23539665Smsmith break; 23639665Smsmith 23739665Smsmith case '?': default: 23839665Smsmith usage(); 23939665Smsmith } 24039665Smsmith 24139665Smsmith if(optind != argc - 1) 24239665Smsmith usage(); 24339665Smsmith 24439665Smsmith switch(format) { 24539665Smsmith default: 24639665Smsmith errx(2, "bad floppy size: %dK", format); 24739665Smsmith case -1: suffix = ""; break; 24839665Smsmith case 360: suffix = ".360"; break; 24939665Smsmith case 640: suffix = ".640"; break; 25039665Smsmith case 720: suffix = ".720"; break; 25139665Smsmith case 800: suffix = ".800"; break; 25239665Smsmith case 820: suffix = ".820"; break; 25339666Sdillon case 1200: suffix = ".1200"; break; 254108108Sdillon case 1232: suffix = ".1232"; break; 25539665Smsmith case 1440: suffix = ".1440"; break; 25639665Smsmith case 1480: suffix = ".1480"; break; 25739665Smsmith case 1720: suffix = ".1720"; break; 25839665Smsmith } 259108108Sdillon 26039665Smsmith devname = makename(argv[optind], suffix); 26139665Smsmith 26239665Smsmith if((fd = open(devname, O_RDWR)) < 0) 26339665Smsmith err(1, "%s", devname); 26439665Smsmith 265108108Sdillon if(ioctl(fd, FD_GTYPE, &fdt) < 0) 26639665Smsmith errx(1, "not a floppy disk: %s", devname); 26739666Sdillon 26839665Smsmith switch(rate) { 26939665Smsmith case -1: break; 27039665Smsmith case 250: fdt.trans = FDC_250KBPS; break; 27139665Smsmith case 300: fdt.trans = FDC_300KBPS; break; 27239665Smsmith case 500: fdt.trans = FDC_500KBPS; break; 27339665Smsmith default: 27439665Smsmith errx(2, "invalid transfer rate: %d", rate); 27539665Smsmith } 27639665Smsmith 27739665Smsmith if (cyls >= 0) fdt.tracks = cyls; 27839665Smsmith if (secs >= 0) fdt.sectrac = secs; 27939665Smsmith if (fdt.sectrac > FD_MAX_NSEC) 28039665Smsmith errx(2, "too many sectors per track, max value is %d", FD_MAX_NSEC); 28139665Smsmith if (heads >= 0) fdt.heads = heads; 28239863Smsmith if (gaplen >= 0) fdt.f_gap = gaplen; 28339665Smsmith if (secsize >= 0) fdt.secsize = secsize; 28439665Smsmith if (steps >= 0) fdt.steptrac = steps; 28539665Smsmith if (intleave >= 0) fdt.f_inter = intleave; 28639665Smsmith 28739665Smsmith bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128; 28839665Smsmith 28939665Smsmith /* XXX 20/40 = 0.5 */ 29039665Smsmith tracks_per_dot = (fdt.tracks * fdt.heads + 20) / 40; 29139665Smsmith 29239665Smsmith if (verify_only) { 29339665Smsmith if(!quiet) 29439665Smsmith printf("Verify %dK floppy `%s'.\n", 29539665Smsmith fdt.tracks * fdt.heads * bytes_per_track / 1024, 29639665Smsmith devname); 29739665Smsmith } 29839665Smsmith else if(!quiet && !confirm) { 29939665Smsmith printf("Format %dK floppy `%s'? (y/n): ", 30039665Smsmith fdt.tracks * fdt.heads * bytes_per_track / 1024, 30139665Smsmith devname); 30239665Smsmith if(! yes ()) { 30339665Smsmith printf("Not confirmed.\n"); 30439665Smsmith return 0; 30539665Smsmith } 30639665Smsmith } 30739665Smsmith 308 /* 309 * Formatting. 310 */ 311 if(!quiet) { 312 int i; 313 314 printf("Processing "); 315 for (i = 0; i < (fdt.tracks * fdt.heads) / tracks_per_dot; i++) 316 putchar('-'); 317 printf("\rProcessing "); 318 fflush(stdout); 319 } 320 321 error = errs = 0; 322 323 for (track = 0; track < fdt.tracks * fdt.heads; track++) { 324 if (!verify_only) { 325 format_track(fd, track / fdt.heads, fdt.sectrac, 326 track % fdt.heads, fdt.trans, fdt.f_gap, 327 fdt.secsize, fill, fdt.f_inter); 328 if(!quiet && !((track + 1) % tracks_per_dot)) { 329 putchar('F'); 330 fflush(stdout); 331 } 332 } 333 if (verify) { 334 if (verify_track(fd, track, bytes_per_track) < 0) 335 error = errs = 1; 336 if(!quiet && !((track + 1) % tracks_per_dot)) { 337 if (!verify_only) 338 putchar('\b'); 339 if (error) { 340 putchar('E'); 341 error = 0; 342 } 343 else 344 putchar('V'); 345 fflush(stdout); 346 } 347 } 348 } 349 if(!quiet) 350 printf(" done.\n"); 351 352 return errs; 353} 354/* 355 * Local Variables: 356 * c-indent-level: 8 357 * c-continued-statement-offset: 8 358 * c-continued-brace-offset: 0 359 * c-brace-offset: -8 360 * c-brace-imaginary-offset: 0 361 * c-argdecl-indent: 8 362 * c-label-offset: -8 363 * c++-hanging-braces: 1 364 * c++-access-specifier-offset: -8 365 * c++-empty-arglist-indent: 8 366 * c++-friend-offset: 0 367 * End: 368 */ 369