fdformat.c revision 69793
1193323Sed/* 2193323Sed * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden 3193323Sed * All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer. 10193323Sed * 2. Redistributions in binary form must reproduce the above copyright 11193323Sed * notice, this list of conditions and the following disclaimer in the 12193323Sed * documentation and/or other materials provided with the distribution. 13193323Sed * 14193323Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15193323Sed * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16193323Sed * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17193323Sed * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, 18226633Sdim * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19193323Sed * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20203954Srdivacky * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21198892Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22221345Sdim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 23234353Sdim * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24198090Srdivacky * POSSIBILITY OF SUCH DAMAGE. 25218893Sdim * 26193323Sed * $FreeBSD: head/usr.sbin/fdformat/fdformat.c 69793 2000-12-09 09:35:55Z obrien $ 27234353Sdim */ 28234353Sdim 29234353Sdim/* 30234353Sdim * FreeBSD: 31193323Sed * format a floppy disk 32193323Sed * 33193323Sed * Added FD_GTYPE ioctl, verifying, proportional indicators. 34193323Sed * Serge Vakulenko, vak@zebub.msk.su 35193323Sed * Sat Dec 18 17:45:47 MSK 1993 36198090Srdivacky * 37193323Sed * Final adaptation, change format/verify logic, add separate 38193323Sed * format gap/interleave values 39193323Sed * Andrew A. Chernov, ache@astral.msk.su 40195098Sed * Thu Jan 27 00:47:24 MSK 1994 41195098Sed */ 42195098Sed 43193323Sed#include <ctype.h> 44195098Sed#include <err.h> 45193323Sed#include <fcntl.h> 46234353Sdim#include <paths.h> 47193323Sed#include <stdio.h> 48193323Sed#include <stdlib.h> 49218893Sdim#include <strings.h> 50218893Sdim#include <unistd.h> 51193323Sed 52198090Srdivacky#include <machine/ioctl_fd.h> 53198892Srdivacky 54198892Srdivackystatic void 55198892Srdivackyformat_track(int fd, int cyl, int secs, int head, int rate, 56198892Srdivacky int gaplen, int secsize, int fill,int interleave) 57198892Srdivacky{ 58198892Srdivacky struct fd_formb f; 59198892Srdivacky register int i,j; 60198090Srdivacky int il[FD_MAX_NSEC + 1]; 61198892Srdivacky 62198892Srdivacky memset(il,0,sizeof il); 63198090Srdivacky for(j = 0, i = 1; i <= secs; i++) { 64193323Sed while(il[(j%secs)+1]) j++; 65198090Srdivacky il[(j%secs)+1] = i; 66198090Srdivacky j += interleave; 67193323Sed } 68193323Sed 69198892Srdivacky f.format_version = FD_FORMAT_VERSION; 70193323Sed f.head = head; 71193323Sed f.cyl = cyl; 72193323Sed f.transfer_rate = rate; 73193323Sed 74193323Sed f.fd_formb_secshift = secsize; 75198090Srdivacky f.fd_formb_nsecs = secs; 76193323Sed f.fd_formb_gaplen = gaplen; 77193323Sed f.fd_formb_fillbyte = fill; 78198892Srdivacky for(i = 0; i < secs; i++) { 79198090Srdivacky f.fd_formb_cylno(i) = cyl; 80218893Sdim f.fd_formb_headno(i) = head; 81193323Sed f.fd_formb_secno(i) = il[i+1]; 82193323Sed f.fd_formb_secsize(i) = secsize; 83193323Sed } 84198090Srdivacky if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0) 85193323Sed err(1, "ioctl(FD_FORM)"); 86193323Sed} 87193323Sed 88198090Srdivackystatic int 89218893Sdimverify_track(int fd, int track, int tracksize) 90218893Sdim{ 91218893Sdim static char *buf = 0; 92198090Srdivacky static int bufsz = 0; 93193323Sed int fdopts = -1, ofdopts, rv = 0; 94193323Sed 95218893Sdim if (ioctl(fd, FD_GOPTS, &fdopts) < 0) 96218893Sdim warn("warning: ioctl(FD_GOPTS)"); 97218893Sdim else { 98218893Sdim ofdopts = fdopts; 99218893Sdim fdopts |= FDOPT_NORETRY; 100218893Sdim (void)ioctl(fd, FD_SOPTS, &fdopts); 101218893Sdim } 102218893Sdim 103218893Sdim if (bufsz < tracksize) { 104218893Sdim if (buf) 105193323Sed free (buf); 106218893Sdim bufsz = tracksize; 107193323Sed buf = 0; 108218893Sdim } 109218893Sdim if (! buf) 110198892Srdivacky buf = malloc (bufsz); 111218893Sdim if (! buf) 112218893Sdim errx(2, "out of memory"); 113193323Sed if (lseek (fd, (long) track*tracksize, 0) < 0) 114218893Sdim rv = -1; 115218893Sdim /* try twice reading it, without using the normal retrier */ 116218893Sdim else if (read (fd, buf, tracksize) != tracksize 117193323Sed && read (fd, buf, tracksize) != tracksize) 118193323Sed rv = -1; 119198090Srdivacky if(fdopts != -1) 120198090Srdivacky (void)ioctl(fd, FD_SOPTS, &ofdopts); 121193323Sed return (rv); 122218893Sdim} 123218893Sdim 124203954Srdivackystatic const char * 125221345Sdimmakename(const char *arg, const char *suffix) 126226633Sdim{ 127221345Sdim static char namebuff[20]; /* big enough for "/dev/fd0a"... */ 128193323Sed 129218893Sdim memset(namebuff, 0, 20); 130193323Sed if(*arg == '\0') /* ??? */ 131193323Sed return arg; 132218893Sdim if(*arg == '/') /* do not convert absolute pathnames */ 133218893Sdim return arg; 134203954Srdivacky strcpy(namebuff, _PATH_DEV); 135203954Srdivacky strncat(namebuff, arg, 3); 136203954Srdivacky strcat(namebuff, suffix); 137203954Srdivacky return namebuff; 138203954Srdivacky} 139223017Sdim 140218893Sdimstatic void 141218893Sdimusage (void) 142218893Sdim{ 143218893Sdim fprintf(stderr, "%s\n%s\n", 144218893Sdim "usage: fdformat [-y] [-q] [-n | -v] [-f #] [-c #] [-s #] [-h #]", 145223017Sdim " [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] devname"); 146226633Sdim exit(2); 147193323Sed} 148193323Sed 149218893Sdimstatic int 150218893Sdimyes (void) 151218893Sdim{ 152221345Sdim char reply [256], *p; 153218893Sdim 154218893Sdim reply[sizeof(reply)-1] = 0; 155193323Sed for (;;) { 156218893Sdim fflush(stdout); 157218893Sdim if (! fgets (reply, sizeof(reply)-1, stdin)) 158221345Sdim return (0); 159221345Sdim for (p=reply; *p==' ' || *p=='\t'; ++p) 160193323Sed continue; 161221345Sdim if (*p=='y' || *p=='Y') 162193323Sed return (1); 163218893Sdim if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r') 164193323Sed return (0); 165193323Sed printf("Answer `yes' or `no': "); 166218893Sdim } 167193323Sed} 168193323Sed 169193323Sedint 170193323Sedmain(int argc, char **argv) 171193323Sed{ 172193323Sed int format = -1, cyls = -1, secs = -1, heads = -1, intleave = -1; 173193323Sed int rate = -1, gaplen = -1, secsize = -1, steps = -1; 174193323Sed int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0, confirm = 0; 175193323Sed int fd, c, track, error, tracks_per_dot, bytes_per_track, errs; 176203954Srdivacky const char *devname, *suffix; 177218893Sdim struct fd_type fdt; 178218893Sdim 179218893Sdim while((c = getopt(argc, argv, "f:c:s:h:r:g:S:F:t:i:qyvn")) != -1) 180218893Sdim switch(c) { 181221345Sdim case 'f': /* format in kilobytes */ 182218893Sdim format = atoi(optarg); 183218893Sdim break; 184203954Srdivacky 185193323Sed case 'c': /* # of cyls */ 186193323Sed cyls = atoi(optarg); 187193323Sed break; 188226633Sdim 189198090Srdivacky case 's': /* # of secs per track */ 190198090Srdivacky secs = atoi(optarg); 191193323Sed break; 192193323Sed 193203954Srdivacky case 'h': /* # of heads */ 194198090Srdivacky heads = atoi(optarg); 195198090Srdivacky break; 196198090Srdivacky 197203954Srdivacky case 'r': /* transfer rate, kilobyte/sec */ 198193323Sed rate = atoi(optarg); 199193323Sed break; 200193323Sed 201226633Sdim case 'g': /* length of GAP3 to format with */ 202199481Srdivacky gaplen = atoi(optarg); 203226633Sdim break; 204210299Sed 205226633Sdim case 'S': /* sector size shift factor (1 << S)*128 */ 206193323Sed secsize = atoi(optarg); 207203954Srdivacky break; 208203954Srdivacky 209203954Srdivacky case 'F': /* fill byte, C-like notation allowed */ 210203954Srdivacky fill = (int)strtol(optarg, (char **)0, 0); 211203954Srdivacky break; 212193323Sed 213221345Sdim case 't': /* steps per track */ 214218893Sdim steps = atoi(optarg); 215193323Sed break; 216193323Sed 217193323Sed case 'i': /* interleave factor */ 218203954Srdivacky intleave = atoi(optarg); 219203954Srdivacky break; 220203954Srdivacky 221193323Sed case 'q': 222193323Sed quiet = 1; 223193323Sed break; 224193323Sed 225193323Sed case 'y': 226221345Sdim confirm = 1; 227193323Sed break; 228193323Sed 229193323Sed case 'n': 230193323Sed verify = 0; 231193323Sed break; 232234353Sdim 233234353Sdim case 'v': 234234353Sdim verify = 1; 235234353Sdim verify_only = 1; 236234353Sdim break; 237234353Sdim 238234353Sdim case '?': default: 239234353Sdim usage(); 240234353Sdim } 241234353Sdim 242234353Sdim if(optind != argc - 1) 243234353Sdim usage(); 244234353Sdim 245234353Sdim switch(format) { 246234353Sdim default: 247234353Sdim errx(2, "bad floppy size: %dK", format); 248234353Sdim case -1: suffix = ""; break; 249234353Sdim case 360: suffix = ".360"; break; 250234353Sdim case 640: suffix = ".640"; break; 251234353Sdim case 720: suffix = ".720"; break; 252193323Sed case 800: suffix = ".800"; break; 253218893Sdim case 820: suffix = ".820"; break; 254218893Sdim case 1200: suffix = ".1200"; break; 255218893Sdim case 1232: suffix = ".1232"; break; 256193323Sed case 1440: suffix = ".1440"; break; 257218893Sdim case 1480: suffix = ".1480"; break; 258193323Sed case 1720: suffix = ".1720"; break; 259218893Sdim } 260218893Sdim 261218893Sdim devname = makename(argv[optind], suffix); 262193323Sed 263221345Sdim if((fd = open(devname, O_RDWR)) < 0) 264221345Sdim err(1, "%s", devname); 265193323Sed 266193323Sed if(ioctl(fd, FD_GTYPE, &fdt) < 0) 267193323Sed errx(1, "not a floppy disk: %s", devname); 268193323Sed 269193323Sed switch(rate) { 270193323Sed case -1: break; 271193323Sed case 250: fdt.trans = FDC_250KBPS; break; 272193323Sed case 300: fdt.trans = FDC_300KBPS; break; 273193323Sed case 500: fdt.trans = FDC_500KBPS; break; 274193323Sed default: 275193323Sed errx(2, "invalid transfer rate: %d", rate); 276198090Srdivacky } 277198090Srdivacky 278193323Sed if (cyls >= 0) fdt.tracks = cyls; 279221345Sdim if (secs >= 0) fdt.sectrac = secs; 280218893Sdim if (fdt.sectrac > FD_MAX_NSEC) 281218893Sdim errx(2, "too many sectors per track, max value is %d", FD_MAX_NSEC); 282193323Sed if (heads >= 0) fdt.heads = heads; 283221345Sdim if (gaplen >= 0) fdt.f_gap = gaplen; 284193323Sed if (secsize >= 0) fdt.secsize = secsize; 285193323Sed if (steps >= 0) fdt.steptrac = steps; 286193323Sed if (intleave >= 0) fdt.f_inter = intleave; 287221345Sdim 288193323Sed bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128; 289193323Sed 290193323Sed /* XXX 20/40 = 0.5 */ 291193323Sed tracks_per_dot = (fdt.tracks * fdt.heads + 20) / 40; 292193323Sed 293221345Sdim if (verify_only) { 294193323Sed if(!quiet) 295193323Sed printf("Verify %dK floppy `%s'.\n", 296193323Sed fdt.tracks * fdt.heads * bytes_per_track / 1024, 297193323Sed devname); 298193323Sed } 299193323Sed else if(!quiet && !confirm) { 300218893Sdim printf("Format %dK floppy `%s'? (y/n): ", 301193323Sed fdt.tracks * fdt.heads * bytes_per_track / 1024, 302193323Sed devname); 303193323Sed if(! yes ()) { 304193323Sed printf("Not confirmed.\n"); 305198090Srdivacky return 0; 306198892Srdivacky } 307198892Srdivacky } 308193323Sed 309193323Sed /* 310198892Srdivacky * Formatting. 311198892Srdivacky */ 312198892Srdivacky if(!quiet) { 313198892Srdivacky int i; 314221345Sdim 315193323Sed printf("Processing "); 316193323Sed for (i = 0; i < (fdt.tracks * fdt.heads) / tracks_per_dot; i++) 317198090Srdivacky putchar('-'); 318198090Srdivacky printf("\rProcessing "); 319193323Sed fflush(stdout); 320193323Sed } 321193323Sed 322193323Sed error = errs = 0; 323193323Sed 324193323Sed for (track = 0; track < fdt.tracks * fdt.heads; track++) { 325194178Sed if (!verify_only) { 326193323Sed format_track(fd, track / fdt.heads, fdt.sectrac, 327193323Sed track % fdt.heads, fdt.trans, fdt.f_gap, 328193323Sed fdt.secsize, fill, fdt.f_inter); 329193323Sed if(!quiet && !((track + 1) % tracks_per_dot)) { 330193323Sed putchar('F'); 331193323Sed fflush(stdout); 332218893Sdim } 333218893Sdim } 334218893Sdim if (verify) { 335218893Sdim if (verify_track(fd, track, bytes_per_track) < 0) 336193323Sed error = errs = 1; 337226633Sdim if(!quiet && !((track + 1) % tracks_per_dot)) { 338218893Sdim if (!verify_only) 339193323Sed putchar('\b'); 340193323Sed if (error) { 341218893Sdim putchar('E'); 342218893Sdim error = 0; 343218893Sdim } 344218893Sdim else 345218893Sdim putchar('V'); 346193323Sed fflush(stdout); 347193323Sed } 348193323Sed } 349193323Sed } 350193323Sed if(!quiet) 351193323Sed printf(" done.\n"); 352193323Sed 353193323Sed return errs; 354193323Sed} 355198090Srdivacky/* 356193323Sed * Local Variables: 357239462Sdim * c-indent-level: 8 358193323Sed * c-continued-statement-offset: 8 359195098Sed * c-continued-brace-offset: 0 360195098Sed * c-brace-offset: -8 361195098Sed * c-brace-imaginary-offset: 0 362195098Sed * c-argdecl-indent: 8 363195098Sed * c-label-offset: -8 364198090Srdivacky * c++-hanging-braces: 1 365198090Srdivacky * c++-access-specifier-offset: -8 366195098Sed * c++-empty-arglist-indent: 8 367198892Srdivacky * c++-friend-offset: 0 368198892Srdivacky * End: 369198892Srdivacky */ 370198892Srdivacky