1 /* $OpenBSD: fdformat.c,v 1.9 2000/06/30 16:00:25 millert Exp $ */ 2 3 /* 4 * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 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 <stdio.h> 44 #include <stdlib.h> 45 #include <unistd.h> 46 #include <fcntl.h> 47 #include <string.h> 48 #include <ctype.h> 49 #include <err.h> 50 #include <util.h> 51 52 #include <errno.h> 53 #include <sys/types.h> 54 #include <sys/ioctl.h> 55 #include <machine/ioctl_fd.h> 56 57 extern const char *__progname; 58 59 static void 60 format_track(fd, cyl, secs, head, rate, gaplen, secsize, fill, interleave) 61 int fd, cyl, secs, head, rate, gaplen, secsize; 62 int fill, interleave; 63 { 64 struct fd_formb f; 65 register int i,j; 66 int il[FD_MAX_NSEC + 1]; 67 68 memset(il,0,sizeof il); 69 for(j = 0, i = 1; i <= secs; i++) { 70 while(il[(j%secs)+1]) 71 j++; 72 il[(j%secs)+1] = i; 73 j += interleave; 74 } 75 76 f.format_version = FD_FORMAT_VERSION; 77 f.head = head; 78 f.cyl = cyl; 79 f.transfer_rate = rate; 80 81 f.fd_formb_secshift = secsize; 82 f.fd_formb_nsecs = secs; 83 f.fd_formb_gaplen = gaplen; 84 f.fd_formb_fillbyte = fill; 85 for(i = 0; i < secs; i++) { 86 f.fd_formb_cylno(i) = cyl; 87 f.fd_formb_headno(i) = head; 88 f.fd_formb_secno(i) = il[i+1]; 89 f.fd_formb_secsize(i) = secsize; 90 } 91 if (ioctl(fd, FD_FORM, (caddr_t)&f) < 0) 92 err(1, "FD_FORM"); 93 } 94 95 static int 96 verify_track(fd, track, tracksize) 97 int fd, track, tracksize; 98 { 99 static char *buf = 0; 100 static int bufsz = 0; 101 int fdopts = -1, ofdopts, rv = 0; 102 103 if (ioctl(fd, FD_GOPTS, &fdopts) < 0) 104 warn("FD_GOPTS"); 105 else { 106 ofdopts = fdopts; 107 fdopts |= FDOPT_NORETRY; 108 (void)ioctl(fd, FD_SOPTS, &fdopts); 109 } 110 111 if (bufsz < tracksize) { 112 if (buf) 113 free (buf); 114 bufsz = tracksize; 115 buf = 0; 116 } 117 if (! buf) 118 buf = malloc (bufsz); 119 if (! buf) { 120 fprintf (stderr, "\nfdformat: out of memory\n"); 121 exit (2); 122 } 123 if (lseek (fd, (off_t) track*tracksize, 0) < 0) 124 rv = -1; 125 /* try twice reading it, without using the normal retrier */ 126 else if (read (fd, buf, tracksize) != tracksize 127 && read (fd, buf, tracksize) != tracksize) 128 rv = -1; 129 if (fdopts != -1) 130 (void)ioctl(fd, FD_SOPTS, &ofdopts); 131 return (rv); 132 } 133 134 static void 135 usage () 136 { 137 printf("Usage:\n\t%s [-q] [-n | -v] [-c #] [-s #] [-h #]\n", 138 __progname); 139 printf("\t\t [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] devname\n"); 140 printf("Options:\n"); 141 printf("\t-q\tsupress any normal output, don't ask for confirmation\n"); 142 printf("\t-n\tdon't verify floppy after formatting\n"); 143 printf("\t-v\tdon't format, verify only\n"); 144 printf("\t\tvalid choices are 360, 720, 800, 820, 1200, 1440, 1480, 1720\n"); 145 printf("\tdevname\tthe full name of floppy device or in short form fd0, fd1\n"); 146 printf("Obscure options:\n"); 147 printf("\t-c #\tspecify number of cylinders, 40 or 80\n"); 148 printf("\t-s #\tspecify number of sectors per track, 9, 10, 15 or 18\n"); 149 printf("\t-h #\tspecify number of floppy heads, 1 or 2\n"); 150 printf("\t-r #\tspecify data rate, 250, 300 or 500 kbps\n"); 151 printf("\t-g #\tspecify gap length\n"); 152 printf("\t-i #\tspecify interleave factor\n"); 153 printf("\t-S #\tspecify sector size, 0=128, 1=256, 2=512 bytes\n"); 154 printf("\t-F #\tspecify fill byte\n"); 155 printf("\t-t #\tnumber of steps per track\n"); 156 exit(2); 157 } 158 159 static int 160 yes () 161 { 162 char reply [256], *p; 163 164 reply[sizeof(reply)-1] = 0; 165 for (;;) { 166 fflush(stdout); 167 if (! fgets (reply, sizeof(reply)-1, stdin)) 168 return (0); 169 for (p=reply; *p==' ' || *p=='\t'; ++p) 170 continue; 171 if (*p=='y' || *p=='Y') 172 return (1); 173 if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r') 174 return (0); 175 printf("Answer `yes' or `no': "); 176 } 177 } 178 179 int 180 main(argc, argv) 181 int argc; 182 char *argv[]; 183 { 184 int cyls = -1, secs = -1, heads = -1, intleave = -1; 185 int rate = -1, gaplen = -1, secsize = -1, steps = -1; 186 int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0; 187 int fd, c, track, error, tracks_per_dot, bytes_per_track, errs; 188 char *devname; 189 struct fd_type fdt; 190 191 while((c = getopt(argc, argv, "c:s:h:r:g:S:F:t:i:qvn")) != -1) 192 switch (c) { 193 case 'c': /* # of cyls */ 194 cyls = atoi(optarg); 195 break; 196 197 case 's': /* # of secs per track */ 198 secs = atoi(optarg); 199 break; 200 201 case 'h': /* # of heads */ 202 heads = atoi(optarg); 203 break; 204 205 case 'r': /* transfer rate, kilobyte/sec */ 206 rate = atoi(optarg); 207 break; 208 209 case 'g': /* length of GAP3 to format with */ 210 gaplen = atoi(optarg); 211 break; 212 213 case 'S': /* sector size shift factor (1 << S)*128 */ 214 secsize = atoi(optarg); 215 break; 216 217 case 'F': /* fill byte, C-like notation allowed */ 218 fill = (int)strtol(optarg, (char **)0, 0); 219 break; 220 221 case 't': /* steps per track */ 222 steps = atoi(optarg); 223 break; 224 225 case 'i': /* interleave factor */ 226 intleave = atoi(optarg); 227 break; 228 229 case 'q': 230 quiet = 1; 231 break; 232 233 case 'n': 234 verify = 0; 235 break; 236 237 case 'v': 238 verify = 1; 239 verify_only = 1; 240 break; 241 242 case '?': default: 243 usage(); 244 } 245 246 if (optind != argc - 1) 247 usage(); 248 249 if ((fd = opendev(argv[optind], O_RDWR, OPENDEV_PART, &devname)) < 0) 250 err(1, "%s", devname); 251 252 if (ioctl(fd, FD_GTYPE, &fdt) < 0) 253 errx(1, "not a floppy disk: %s", devname); 254 255 switch (rate) { 256 case -1: 257 break; 258 case 250: 259 fdt.rate = FDC_250KBPS; 260 break; 261 case 300: 262 fdt.rate = FDC_300KBPS; 263 break; 264 case 500: 265 fdt.rate = FDC_500KBPS; 266 break; 267 default: 268 errx(1, "invalid transfer rate: %d", rate); 269 } 270 271 if (cyls >= 0) 272 fdt.tracks = cyls; 273 if (secs >= 0) 274 fdt.sectrac = secs; 275 if (fdt.sectrac > FD_MAX_NSEC) 276 errx(1, "too many sectors per track, max value is %d", 277 FD_MAX_NSEC); 278 if (heads >= 0) 279 fdt.heads = heads; 280 if (gaplen >= 0) 281 fdt.gap2 = gaplen; 282 if (secsize >= 0) 283 fdt.secsize = secsize; 284 if (steps >= 0) 285 fdt.step = steps; 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 exit(0); 303 } 304 } 305 306 /* 307 * Formatting. 308 */ 309 if (!quiet) { 310 printf("Processing "); 311 for (track = 0; track < fdt.tracks * fdt.heads; track++) { 312 if (!((track + 1) % tracks_per_dot)) 313 putchar('-'); 314 } 315 putchar('\r'); 316 printf("Processing "); 317 fflush(stdout); 318 } 319 320 error = errs = 0; 321 322 for (track = 0; track < fdt.tracks * fdt.heads; track++) { 323 if (!verify_only) { 324 format_track(fd, track / fdt.heads, fdt.sectrac, 325 track % fdt.heads, fdt.rate, fdt.gap2, 326 fdt.secsize, fill, 327 intleave >= 0 ? intleave : 1); 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 exit(errs); 353 } 354