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 27 /* 28 * FreeBSD: 29 * format a floppy disk 30 * 31 * Added FD_GTYPE ioctl, verifying, proportional indicators. 32 * Serge Vakulenko, vak@zebub.msk.su 33 * Sat Dec 18 17:45:47 MSK 1993 34 * 35 * Final adaptation, change format/verify logic, add separate 36 * format gap/interleave values 37 * Andrew A. Chernov, ache@astral.msk.su 38 * Thu Jan 27 00:47:24 MSK 1994 39 */ 40 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <unistd.h> 44 #include <fcntl.h> 45 #include <strings.h> 46 #include <ctype.h> 47 48 #include <errno.h> 49 #include <machine/ioctl_fd.h> 50 #include <../i386/isa/fdreg.h> /* XXX should be in <machine> dir */ 51 52 static void 53 format_track(int fd, int cyl, int secs, int head, int rate, 54 int gaplen, int secsize, int fill,int interleave) 55 { 56 struct fd_formb f; 57 register int i,j; 58 int il[FD_MAX_NSEC + 1]; 59 60 memset(il,0,sizeof il); 61 for(j = 0, i = 1; i <= secs; i++) { 62 while(il[(j%secs)+1]) j++; 63 il[(j%secs)+1] = i; 64 j += interleave; 65 } 66 67 f.format_version = FD_FORMAT_VERSION; 68 f.head = head; 69 f.cyl = cyl; 70 f.transfer_rate = rate; 71 72 f.fd_formb_secshift = secsize; 73 f.fd_formb_nsecs = secs; 74 f.fd_formb_gaplen = gaplen; 75 f.fd_formb_fillbyte = fill; 76 for(i = 0; i < secs; i++) { 77 f.fd_formb_cylno(i) = cyl; 78 f.fd_formb_headno(i) = head; 79 f.fd_formb_secno(i) = il[i+1]; 80 f.fd_formb_secsize(i) = secsize; 81 } 82 if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0) { 83 perror("\nfdformat: ioctl(FD_FORM)"); 84 exit(1); 85 } 86 } 87 88 static int 89 verify_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 perror("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 fprintf (stderr, "\nfdformat: out of memory\n"); 113 exit (2); 114 } 115 if (lseek (fd, (long) track*tracksize, 0) < 0) 116 rv = -1; 117 /* try twice reading it, without using the normal retrier */ 118 else if (read (fd, buf, tracksize) != tracksize 119 && read (fd, buf, tracksize) != tracksize) 120 rv = -1; 121 if(fdopts != -1) 122 (void)ioctl(fd, FD_SOPTS, &ofdopts); 123 return (rv); 124 } 125 126 static const char * 127 makename(const char *arg, const char *suffix) 128 { 129 static char namebuff[20]; /* big enough for "/dev/rfd0a"... */ 130 131 memset(namebuff, 0, 20); 132 if(*arg == '\0') /* ??? */ 133 return arg; 134 if(*arg == '/') /* do not convert absolute pathnames */ 135 return arg; 136 strcpy(namebuff, "/dev/r"); 137 strncat(namebuff, arg, 3); 138 strcat(namebuff, suffix); 139 return namebuff; 140 } 141 142 static void 143 usage (void) 144 { 145 printf("Usage:\n\tfdformat [-q] [-n | -v] [-f #] [-c #] [-s #] [-h #]\n"); 146 printf("\t\t [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] devname\n"); 147 printf("Options:\n"); 148 printf("\t-q\tsupress any normal output, don't ask for confirmation\n"); 149 printf("\t-n\tdon't verify floppy after formatting\n"); 150 printf("\t-v\tdon't format, verify only\n"); 151 printf("\t-f #\tspecify desired floppy capacity, in kilobytes;\n"); 152 printf("\t\tvalid choices are 360, 720, 800, 820, 1200, 1440, 1480, 1720\n"); 153 printf("\tdevname\tthe full name of floppy device or in short form fd0, fd1\n"); 154 printf("Obscure options:\n"); 155 printf("\t-c #\tspecify number of cylinders, 40 or 80\n"); 156 printf("\t-s #\tspecify number of sectors per track, 9, 10, 15 or 18\n"); 157 printf("\t-h #\tspecify number of floppy heads, 1 or 2\n"); 158 printf("\t-r #\tspecify data rate, 250, 300 or 500 kbps\n"); 159 printf("\t-g #\tspecify gap length\n"); 160 printf("\t-i #\tspecify interleave factor\n"); 161 printf("\t-S #\tspecify sector size, 0=128, 1=256, 2=512 bytes\n"); 162 printf("\t-F #\tspecify fill byte\n"); 163 printf("\t-t #\tnumber of steps per track\n"); 164 exit(2); 165 } 166 167 static int 168 yes (void) 169 { 170 char reply [256], *p; 171 172 reply[sizeof(reply)-1] = 0; 173 for (;;) { 174 fflush(stdout); 175 if (! fgets (reply, sizeof(reply)-1, stdin)) 176 return (0); 177 for (p=reply; *p==' ' || *p=='\t'; ++p) 178 continue; 179 if (*p=='y' || *p=='Y') 180 return (1); 181 if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r') 182 return (0); 183 printf("Answer `yes' or `no': "); 184 } 185 } 186 187 int 188 main(int argc, char **argv) 189 { 190 int format = -1, cyls = -1, secs = -1, heads = -1, intleave = -1; 191 int rate = -1, gaplen = -1, secsize = -1, steps = -1; 192 int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0; 193 int fd, c, track, error, tracks_per_dot, bytes_per_track, errs; 194 const char *devname, *suffix; 195 struct fd_type fdt; 196 197 while((c = getopt(argc, argv, "f:c:s:h:r:g:S:F:t:i:qvn")) != -1) 198 switch(c) { 199 case 'f': /* format in kilobytes */ 200 format = atoi(optarg); 201 break; 202 203 case 'c': /* # of cyls */ 204 cyls = atoi(optarg); 205 break; 206 207 case 's': /* # of secs per track */ 208 secs = atoi(optarg); 209 break; 210 211 case 'h': /* # of heads */ 212 heads = atoi(optarg); 213 break; 214 215 case 'r': /* transfer rate, kilobyte/sec */ 216 rate = atoi(optarg); 217 break; 218 219 case 'g': /* length of GAP3 to format with */ 220 gaplen = atoi(optarg); 221 break; 222 223 case 'S': /* sector size shift factor (1 << S)*128 */ 224 secsize = atoi(optarg); 225 break; 226 227 case 'F': /* fill byte, C-like notation allowed */ 228 fill = (int)strtol(optarg, (char **)0, 0); 229 break; 230 231 case 't': /* steps per track */ 232 steps = atoi(optarg); 233 break; 234 235 case 'i': /* interleave factor */ 236 intleave = atoi(optarg); 237 break; 238 239 case 'q': 240 quiet = 1; 241 break; 242 243 case 'n': 244 verify = 0; 245 break; 246 247 case 'v': 248 verify = 1; 249 verify_only = 1; 250 break; 251 252 case '?': default: 253 usage(); 254 } 255 256 if(optind != argc - 1) 257 usage(); 258 259 switch(format) { 260 default: 261 fprintf(stderr, "fdformat: bad floppy size: %dK\n", format); 262 exit(2); 263 case -1: suffix = ""; break; 264 case 360: suffix = ".360"; break; 265 case 720: suffix = ".720"; break; 266 case 800: suffix = ".800"; break; 267 case 820: suffix = ".820"; break; 268 case 1200: suffix = ".1200"; break; 269 case 1440: suffix = ".1440"; break; 270 case 1480: suffix = ".1480"; break; 271 case 1720: suffix = ".1720"; break; 272 } 273 274 devname = makename(argv[optind], suffix); 275 276 if((fd = open(devname, O_RDWR)) < 0) { 277 perror(devname); 278 exit(1); 279 } 280 281 if(ioctl(fd, FD_GTYPE, &fdt) < 0) { 282 fprintf(stderr, "fdformat: not a floppy disk: %s\n", devname); 283 exit(1); 284 } 285 286 switch(rate) { 287 case -1: break; 288 case 250: fdt.trans = FDC_250KBPS; break; 289 case 300: fdt.trans = FDC_300KBPS; break; 290 case 500: fdt.trans = FDC_500KBPS; break; 291 default: 292 fprintf(stderr, "fdformat: invalid transfer rate: %d\n", rate); 293 exit(2); 294 } 295 296 if (cyls >= 0) fdt.tracks = cyls; 297 if (secs >= 0) fdt.sectrac = secs; 298 if (fdt.sectrac > FD_MAX_NSEC) { 299 fprintf(stderr, "fdformat: too many sectors per track, max value is %d\n", FD_MAX_NSEC); 300 exit(2); 301 } 302 if (heads >= 0) fdt.heads = heads; 303 if (gaplen >= 0) fdt.f_gap = gaplen; 304 if (secsize >= 0) fdt.secsize = secsize; 305 if (steps >= 0) fdt.steptrac = steps; 306 if (intleave >= 0) fdt.f_inter = intleave; 307 308 bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128; 309 tracks_per_dot = fdt.tracks * fdt.heads / 40; 310 311 if (verify_only) { 312 if(!quiet) 313 printf("Verify %dK floppy `%s'.\n", 314 fdt.tracks * fdt.heads * bytes_per_track / 1024, 315 devname); 316 } 317 else if(!quiet) { 318 printf("Format %dK floppy `%s'? (y/n): ", 319 fdt.tracks * fdt.heads * bytes_per_track / 1024, 320 devname); 321 if(! yes ()) { 322 printf("Not confirmed.\n"); 323 return 0; 324 } 325 } 326 327 /* 328 * Formatting. 329 */ 330 if(!quiet) { 331 printf("Processing ----------------------------------------\r"); 332 printf("Processing "); 333 fflush(stdout); 334 } 335 336 error = errs = 0; 337 338 for (track = 0; track < fdt.tracks * fdt.heads; track++) { 339 if (!verify_only) { 340 format_track(fd, track / fdt.heads, fdt.sectrac, 341 track % fdt.heads, fdt.trans, fdt.f_gap, 342 fdt.secsize, fill, fdt.f_inter); 343 if(!quiet && !((track + 1) % tracks_per_dot)) { 344 putchar('F'); 345 fflush(stdout); 346 } 347 } 348 if (verify) { 349 if (verify_track(fd, track, bytes_per_track) < 0) 350 error = errs = 1; 351 if(!quiet && !((track + 1) % tracks_per_dot)) { 352 if (!verify_only) 353 putchar('\b'); 354 if (error) { 355 putchar('E'); 356 error = 0; 357 } 358 else 359 putchar('V'); 360 fflush(stdout); 361 } 362 } 363 } 364 if(!quiet) 365 printf(" done.\n"); 366 367 return errs; 368 } 369 /* 370 * Local Variables: 371 * c-indent-level: 8 372 * c-continued-statement-offset: 8 373 * c-continued-brace-offset: 0 374 * c-brace-offset: -8 375 * c-brace-imaginary-offset: 0 376 * c-argdecl-indent: 8 377 * c-label-offset: -8 378 * c++-hanging-braces: 1 379 * c++-access-specifier-offset: -8 380 * c++-empty-arglist-indent: 8 381 * c++-friend-offset: 0 382 * End: 383 */ 384