fdformat.c revision 1022
1/* 2 * Copyright (C) 1992-1993 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 ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * 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 52static void 53format_track(int fd, int cyl, int secs, int head, int rate, 54 int gaplen, int secsize, int fill) 55{ 56 struct fd_formb f; 57 register int i; 58 59 f.format_version = FD_FORMAT_VERSION; 60 f.head = head; 61 f.cyl = cyl; 62 f.transfer_rate = rate; 63 64 f.fd_formb_secshift = secsize; 65 f.fd_formb_nsecs = secs; 66 f.fd_formb_gaplen = gaplen; 67 f.fd_formb_fillbyte = fill; 68 for(i = 0; i < secs; i++) { 69 f.fd_formb_cylno(i) = cyl; 70 f.fd_formb_headno(i) = head; 71 f.fd_formb_secno(i) = i + 1; 72 f.fd_formb_secsize(i) = secsize; 73 } 74 if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0) { 75 perror("\nfdformat: ioctl(FD_FORM)"); 76 exit(1); 77 } 78} 79 80static int 81verify_track(int fd, int track, int tracksize) 82{ 83 static char *buf = 0; 84 static int bufsz = 0; 85 86 if (bufsz < tracksize) { 87 if (buf) 88 free (buf); 89 bufsz = tracksize; 90 buf = 0; 91 } 92 if (! buf) 93 buf = malloc (bufsz); 94 if (! buf) { 95 fprintf (stderr, "\nfdformat: out of memory\n"); 96 exit (2); 97 } 98 if (lseek (fd, (long) track*tracksize, 0) < 0) 99 return (-1); 100 if (read (fd, buf, tracksize) != tracksize) 101 return (-1); 102 return (0); 103} 104 105static const char * 106makename(const char *arg, const char *suffix) 107{ 108 static char namebuff[20]; /* big enough for "/dev/rfd0a"... */ 109 110 memset(namebuff, 0, 20); 111 if(*arg == '\0') /* ??? */ 112 return arg; 113 if(*arg == '/') /* do not convert absolute pathnames */ 114 return arg; 115 strcpy(namebuff, "/dev/r"); 116 strncat(namebuff, arg, 3); 117 strcat(namebuff, suffix); 118 return namebuff; 119} 120 121static void 122usage () 123{ 124 printf("Usage:\n\tfdformat [-q] [-n | -v] [-f #] [-c #] [-s #] [-h #]\n"); 125 printf("\t\t [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] devname\n"); 126 printf("Options:\n"); 127 printf("\t-q\tsupress any normal output, don't ask for confirmation\n"); 128 printf("\t-n\tdon't verify floppy after formatting\n"); 129 printf("\t-v\tdon't format, verify only\n"); 130 printf("\t-f #\tspecify desired floppy capacity, in kilobytes;\n"); 131 printf("\t\tvalid choices are 360, 720, 800, 820, 1200, 1440, 1480, 1720\n"); 132 printf("\tdevname\tthe full name of floppy device or in short form fd0, fd1\n"); 133 printf("Obscure options:\n"); 134 printf("\t-c #\tspecify number of cylinders, 40 or 80\n"); 135 printf("\t-s #\tspecify number of sectors per track, 9, 10, 15 or 18\n"); 136 printf("\t-h #\tspecify number of floppy heads, 1 or 2\n"); 137 printf("\t-r #\tspecify data rate, 250, 300 or 500 kbps\n"); 138 printf("\t-g #\tspecify gap length\n"); 139 printf("\t-i #\tspecify interleave factor\n"); 140 printf("\t-S #\tspecify sector size, 0=128, 1=256, 2=512 bytes\n"); 141 printf("\t-F #\tspecify fill byte\n"); 142 printf("\t-t #\tnumber of steps per track\n"); 143 exit(2); 144} 145 146static int 147yes () 148{ 149 char reply [256], *p; 150 151 reply[sizeof(reply)-1] = 0; 152 for (;;) { 153 fflush(stdout); 154 if (! fgets (reply, sizeof(reply)-1, stdin)) 155 return (0); 156 for (p=reply; *p==' ' || *p=='\t'; ++p) 157 continue; 158 if (*p=='y' || *p=='Y') 159 return (1); 160 if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r') 161 return (0); 162 printf("Answer `yes' or `no': "); 163 } 164} 165 166int 167main(int argc, char **argv) 168{ 169 int format = -1, cyls = -1, secs = -1, heads = -1, intleave = -1; 170 int rate = -1, gaplen = -1, secsize = -1, steps = -1; 171 int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0; 172 int fd, c, track, error, tracks_per_dot, bytes_per_track, errs; 173 const char *devname, *suffix; 174 struct fd_type fdt; 175 176 while((c = getopt(argc, argv, "f:c:s:h:r:g:S:F:t:i:qvn")) != -1) 177 switch(c) { 178 case 'f': /* format in kilobytes */ 179 format = atoi(optarg); 180 break; 181 182 case 'c': /* # of cyls */ 183 cyls = atoi(optarg); 184 break; 185 186 case 's': /* # of secs per track */ 187 secs = atoi(optarg); 188 break; 189 190 case 'h': /* # of heads */ 191 heads = atoi(optarg); 192 break; 193 194 case 'r': /* transfer rate, kilobyte/sec */ 195 rate = atoi(optarg); 196 break; 197 198 case 'g': /* length of GAP3 to format with */ 199 gaplen = atoi(optarg); 200 break; 201 202 case 'S': /* sector size shift factor (1 << S)*128 */ 203 secsize = atoi(optarg); 204 break; 205 206 case 'F': /* fill byte, C-like notation allowed */ 207 fill = (int)strtol(optarg, (char **)0, 0); 208 break; 209 210 case 't': /* steps per track */ 211 steps = atoi(optarg); 212 break; 213 214 case 'i': /* interleave factor */ 215 intleave = atoi(optarg); 216 break; 217 218 case 'q': 219 quiet = 1; 220 break; 221 222 case 'n': 223 verify = 0; 224 break; 225 226 case 'v': 227 verify = 1; 228 verify_only = 1; 229 break; 230 231 case '?': default: 232 usage(); 233 } 234 235 if(optind != argc - 1) 236 usage(); 237 238 switch(format) { 239 default: 240 fprintf(stderr, "fdformat: bad floppy size: %dK\n", format); 241 exit(2); 242 case -1: suffix = ""; break; 243 case 360: suffix = ".360"; break; 244 case 720: suffix = ".720"; break; 245 case 800: suffix = ".800"; break; 246 case 820: suffix = ".820"; break; 247 case 1200: suffix = ".1200"; break; 248 case 1440: suffix = ".1440"; break; 249 case 1480: suffix = ".1480"; break; 250 case 1720: suffix = ".1720"; break; 251 } 252 253 devname = makename(argv[optind], suffix); 254 255 if((fd = open(devname, O_RDWR)) < 0) { 256 perror(devname); 257 exit(1); 258 } 259 260 if(ioctl(fd, FD_GTYPE, &fdt) < 0) { 261 fprintf(stderr, "fdformat: not a floppy disk: %s\n", devname); 262 exit(1); 263 } 264 265 switch(rate) { 266 case -1: break; 267 case 250: fdt.trans = FDC_250KBPS; break; 268 case 300: fdt.trans = FDC_300KBPS; break; 269 case 500: fdt.trans = FDC_500KBPS; break; 270 default: 271 fprintf(stderr, "fdformat: invalid transfer rate: %d\n", rate); 272 exit(2); 273 } 274 275 if (cyls >= 0) fdt.tracks = cyls; 276 if (secs >= 0) fdt.sectrac = secs; 277 if (heads >= 0) fdt.heads = heads; 278 if (gaplen >= 0) fdt.f_gap = gaplen; 279 if (secsize >= 0) fdt.secsize = secsize; 280 if (steps >= 0) fdt.steptrac = steps; 281 if (intleave >= 0) fdt.f_inter = intleave; 282 if (fdt.f_inter != 1) { 283 fprintf(stderr, "fdformat: can't format with interleave != 1 yet\n"); 284 exit(2); 285 } 286 287 bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128; 288 tracks_per_dot = fdt.tracks * fdt.heads / 40; 289 290 if (verify_only) { 291 if(!quiet) 292 printf("Verify %dK floppy `%s'.\n", 293 fdt.tracks * fdt.heads * bytes_per_track / 1024, 294 devname); 295 } 296 else if(!quiet) { 297 printf("Format %dK floppy `%s'? (y/n): ", 298 fdt.tracks * fdt.heads * bytes_per_track / 1024, 299 devname); 300 if(! yes ()) { 301 printf("Not confirmed.\n"); 302 return 0; 303 } 304 } 305 306 /* 307 * Formatting. 308 */ 309 if(!quiet) { 310 printf("Processing ----------------------------------------\r"); 311 printf("Processing "); 312 fflush(stdout); 313 } 314 315 error = errs = 0; 316 317 for (track = 0; track < fdt.tracks * fdt.heads; track++) { 318 if (!verify_only) { 319 format_track(fd, track / 2, fdt.sectrac, track & 1, 320 fdt.trans, fdt.f_gap, fdt.secsize, fill); 321 if(!quiet && !((track + 1) % tracks_per_dot)) { 322 putchar('F'); 323 fflush(stdout); 324 } 325 } 326 if (verify) { 327 if (verify_track(fd, track, bytes_per_track) < 0) 328 error = errs = 1; 329 if(!quiet && !((track + 1) % tracks_per_dot)) { 330 if (!verify_only) 331 putchar('\b'); 332 if (error) { 333 putchar('E'); 334 error = 0; 335 } 336 else 337 putchar('V'); 338 fflush(stdout); 339 } 340 } 341 } 342 if(!quiet) 343 printf(" done.\n"); 344 345 return errs; 346} 347