fdformat.c revision 69793
1/* 2 * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, 18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 23 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD: head/usr.sbin/fdformat/fdformat.c 69793 2000-12-09 09:35:55Z obrien $ 27 */ 28 29/* 30 * FreeBSD: 31 * format a floppy disk 32 * 33 * Added FD_GTYPE ioctl, verifying, proportional indicators. 34 * Serge Vakulenko, vak@zebub.msk.su 35 * Sat Dec 18 17:45:47 MSK 1993 36 * 37 * Final adaptation, change format/verify logic, add separate 38 * format gap/interleave values 39 * Andrew A. Chernov, ache@astral.msk.su 40 * Thu Jan 27 00:47:24 MSK 1994 41 */ 42 43#include <ctype.h> 44#include <err.h> 45#include <fcntl.h> 46#include <paths.h> 47#include <stdio.h> 48#include <stdlib.h> 49#include <strings.h> 50#include <unistd.h> 51 52#include <machine/ioctl_fd.h> 53 54static void 55format_track(int fd, int cyl, int secs, int head, int rate, 56 int gaplen, int secsize, int fill,int interleave) 57{ 58 struct fd_formb f; 59 register int i,j; 60 int il[FD_MAX_NSEC + 1]; 61 62 memset(il,0,sizeof il); 63 for(j = 0, i = 1; i <= secs; i++) { 64 while(il[(j%secs)+1]) j++; 65 il[(j%secs)+1] = i; 66 j += interleave; 67 } 68 69 f.format_version = FD_FORMAT_VERSION; 70 f.head = head; 71 f.cyl = cyl; 72 f.transfer_rate = rate; 73 74 f.fd_formb_secshift = secsize; 75 f.fd_formb_nsecs = secs; 76 f.fd_formb_gaplen = gaplen; 77 f.fd_formb_fillbyte = fill; 78 for(i = 0; i < secs; i++) { 79 f.fd_formb_cylno(i) = cyl; 80 f.fd_formb_headno(i) = head; 81 f.fd_formb_secno(i) = il[i+1]; 82 f.fd_formb_secsize(i) = secsize; 83 } 84 if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0) 85 err(1, "ioctl(FD_FORM)"); 86} 87 88static int 89verify_track(int fd, int track, int tracksize) 90{ 91 static char *buf = 0; 92 static int bufsz = 0; 93 int fdopts = -1, ofdopts, rv = 0; 94 95 if (ioctl(fd, FD_GOPTS, &fdopts) < 0) 96 warn("warning: ioctl(FD_GOPTS)"); 97 else { 98 ofdopts = fdopts; 99 fdopts |= FDOPT_NORETRY; 100 (void)ioctl(fd, FD_SOPTS, &fdopts); 101 } 102 103 if (bufsz < tracksize) { 104 if (buf) 105 free (buf); 106 bufsz = tracksize; 107 buf = 0; 108 } 109 if (! buf) 110 buf = malloc (bufsz); 111 if (! buf) 112 errx(2, "out of memory"); 113 if (lseek (fd, (long) track*tracksize, 0) < 0) 114 rv = -1; 115 /* try twice reading it, without using the normal retrier */ 116 else if (read (fd, buf, tracksize) != tracksize 117 && read (fd, buf, tracksize) != tracksize) 118 rv = -1; 119 if(fdopts != -1) 120 (void)ioctl(fd, FD_SOPTS, &ofdopts); 121 return (rv); 122} 123 124static const char * 125makename(const char *arg, const char *suffix) 126{ 127 static char namebuff[20]; /* big enough for "/dev/fd0a"... */ 128 129 memset(namebuff, 0, 20); 130 if(*arg == '\0') /* ??? */ 131 return arg; 132 if(*arg == '/') /* do not convert absolute pathnames */ 133 return arg; 134 strcpy(namebuff, _PATH_DEV); 135 strncat(namebuff, arg, 3); 136 strcat(namebuff, suffix); 137 return namebuff; 138} 139 140static void 141usage (void) 142{ 143 fprintf(stderr, "%s\n%s\n", 144 "usage: fdformat [-y] [-q] [-n | -v] [-f #] [-c #] [-s #] [-h #]", 145 " [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] devname"); 146 exit(2); 147} 148 149static int 150yes (void) 151{ 152 char reply [256], *p; 153 154 reply[sizeof(reply)-1] = 0; 155 for (;;) { 156 fflush(stdout); 157 if (! fgets (reply, sizeof(reply)-1, stdin)) 158 return (0); 159 for (p=reply; *p==' ' || *p=='\t'; ++p) 160 continue; 161 if (*p=='y' || *p=='Y') 162 return (1); 163 if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r') 164 return (0); 165 printf("Answer `yes' or `no': "); 166 } 167} 168 169int 170main(int argc, char **argv) 171{ 172 int format = -1, cyls = -1, secs = -1, heads = -1, intleave = -1; 173 int rate = -1, gaplen = -1, secsize = -1, steps = -1; 174 int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0, confirm = 0; 175 int fd, c, track, error, tracks_per_dot, bytes_per_track, errs; 176 const char *devname, *suffix; 177 struct fd_type fdt; 178 179 while((c = getopt(argc, argv, "f:c:s:h:r:g:S:F:t:i:qyvn")) != -1) 180 switch(c) { 181 case 'f': /* format in kilobytes */ 182 format = atoi(optarg); 183 break; 184 185 case 'c': /* # of cyls */ 186 cyls = atoi(optarg); 187 break; 188 189 case 's': /* # of secs per track */ 190 secs = atoi(optarg); 191 break; 192 193 case 'h': /* # of heads */ 194 heads = atoi(optarg); 195 break; 196 197 case 'r': /* transfer rate, kilobyte/sec */ 198 rate = atoi(optarg); 199 break; 200 201 case 'g': /* length of GAP3 to format with */ 202 gaplen = atoi(optarg); 203 break; 204 205 case 'S': /* sector size shift factor (1 << S)*128 */ 206 secsize = atoi(optarg); 207 break; 208 209 case 'F': /* fill byte, C-like notation allowed */ 210 fill = (int)strtol(optarg, (char **)0, 0); 211 break; 212 213 case 't': /* steps per track */ 214 steps = atoi(optarg); 215 break; 216 217 case 'i': /* interleave factor */ 218 intleave = atoi(optarg); 219 break; 220 221 case 'q': 222 quiet = 1; 223 break; 224 225 case 'y': 226 confirm = 1; 227 break; 228 229 case 'n': 230 verify = 0; 231 break; 232 233 case 'v': 234 verify = 1; 235 verify_only = 1; 236 break; 237 238 case '?': default: 239 usage(); 240 } 241 242 if(optind != argc - 1) 243 usage(); 244 245 switch(format) { 246 default: 247 errx(2, "bad floppy size: %dK", format); 248 case -1: suffix = ""; break; 249 case 360: suffix = ".360"; break; 250 case 640: suffix = ".640"; break; 251 case 720: suffix = ".720"; break; 252 case 800: suffix = ".800"; break; 253 case 820: suffix = ".820"; break; 254 case 1200: suffix = ".1200"; break; 255 case 1232: suffix = ".1232"; break; 256 case 1440: suffix = ".1440"; break; 257 case 1480: suffix = ".1480"; break; 258 case 1720: suffix = ".1720"; break; 259 } 260 261 devname = makename(argv[optind], suffix); 262 263 if((fd = open(devname, O_RDWR)) < 0) 264 err(1, "%s", devname); 265 266 if(ioctl(fd, FD_GTYPE, &fdt) < 0) 267 errx(1, "not a floppy disk: %s", devname); 268 269 switch(rate) { 270 case -1: break; 271 case 250: fdt.trans = FDC_250KBPS; break; 272 case 300: fdt.trans = FDC_300KBPS; break; 273 case 500: fdt.trans = FDC_500KBPS; break; 274 default: 275 errx(2, "invalid transfer rate: %d", rate); 276 } 277 278 if (cyls >= 0) fdt.tracks = cyls; 279 if (secs >= 0) fdt.sectrac = secs; 280 if (fdt.sectrac > FD_MAX_NSEC) 281 errx(2, "too many sectors per track, max value is %d", FD_MAX_NSEC); 282 if (heads >= 0) fdt.heads = heads; 283 if (gaplen >= 0) fdt.f_gap = gaplen; 284 if (secsize >= 0) fdt.secsize = secsize; 285 if (steps >= 0) fdt.steptrac = steps; 286 if (intleave >= 0) fdt.f_inter = intleave; 287 288 bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128; 289 290 /* XXX 20/40 = 0.5 */ 291 tracks_per_dot = (fdt.tracks * fdt.heads + 20) / 40; 292 293 if (verify_only) { 294 if(!quiet) 295 printf("Verify %dK floppy `%s'.\n", 296 fdt.tracks * fdt.heads * bytes_per_track / 1024, 297 devname); 298 } 299 else if(!quiet && !confirm) { 300 printf("Format %dK floppy `%s'? (y/n): ", 301 fdt.tracks * fdt.heads * bytes_per_track / 1024, 302 devname); 303 if(! yes ()) { 304 printf("Not confirmed.\n"); 305 return 0; 306 } 307 } 308 309 /* 310 * Formatting. 311 */ 312 if(!quiet) { 313 int i; 314 315 printf("Processing "); 316 for (i = 0; i < (fdt.tracks * fdt.heads) / tracks_per_dot; i++) 317 putchar('-'); 318 printf("\rProcessing "); 319 fflush(stdout); 320 } 321 322 error = errs = 0; 323 324 for (track = 0; track < fdt.tracks * fdt.heads; track++) { 325 if (!verify_only) { 326 format_track(fd, track / fdt.heads, fdt.sectrac, 327 track % fdt.heads, fdt.trans, fdt.f_gap, 328 fdt.secsize, fill, fdt.f_inter); 329 if(!quiet && !((track + 1) % tracks_per_dot)) { 330 putchar('F'); 331 fflush(stdout); 332 } 333 } 334 if (verify) { 335 if (verify_track(fd, track, bytes_per_track) < 0) 336 error = errs = 1; 337 if(!quiet && !((track + 1) % tracks_per_dot)) { 338 if (!verify_only) 339 putchar('\b'); 340 if (error) { 341 putchar('E'); 342 error = 0; 343 } 344 else 345 putchar('V'); 346 fflush(stdout); 347 } 348 } 349 } 350 if(!quiet) 351 printf(" done.\n"); 352 353 return errs; 354} 355/* 356 * Local Variables: 357 * c-indent-level: 8 358 * c-continued-statement-offset: 8 359 * c-continued-brace-offset: 0 360 * c-brace-offset: -8 361 * c-brace-imaginary-offset: 0 362 * c-argdecl-indent: 8 363 * c-label-offset: -8 364 * c++-hanging-braces: 1 365 * c++-access-specifier-offset: -8 366 * c++-empty-arglist-indent: 8 367 * c++-friend-offset: 0 368 * End: 369 */ 370