1 /* $OpenBSD: fdformat.c,v 1.25 2022/12/04 23:50:50 cheloha 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 <limits.h> 49 #include <ctype.h> 50 #include <err.h> 51 #include <util.h> 52 53 #include <errno.h> 54 #include <sys/types.h> 55 #include <sys/ioctl.h> 56 #include <machine/ioctl_fd.h> 57 58 extern const char *__progname; 59 60 static void 61 format_track(int fd, int cyl, int secs, int head, int rate, int gaplen, 62 int secsize, int fill, int interleave) 63 { 64 struct fd_formb f; 65 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) == -1) 92 err(1, "FD_FORM"); 93 } 94 95 static int 96 verify_track(int fd, int track, int tracksize) 97 { 98 static char *buf = 0; 99 static int bufsz = 0; 100 int fdopts = -1, ofdopts, rv = 0; 101 102 if (ioctl(fd, FD_GOPTS, &fdopts) == -1) 103 warn("FD_GOPTS"); 104 else { 105 ofdopts = fdopts; 106 fdopts |= FDOPT_NORETRY; 107 (void)ioctl(fd, FD_SOPTS, &fdopts); 108 } 109 110 if (bufsz < tracksize) { 111 free(buf); 112 bufsz = tracksize; 113 buf = 0; 114 } 115 if (! buf) 116 buf = malloc(bufsz); 117 if (! buf) { 118 fprintf (stderr, "\nfdformat: out of memory\n"); 119 exit (2); 120 } 121 if (lseek (fd, (off_t) track*tracksize, SEEK_SET) == -1) 122 rv = -1; 123 /* try twice reading it, without using the normal retrier */ 124 else if (read (fd, buf, tracksize) != tracksize 125 && read (fd, buf, tracksize) != tracksize) 126 rv = -1; 127 if (fdopts != -1) 128 (void)ioctl(fd, FD_SOPTS, &ofdopts); 129 return (rv); 130 } 131 132 static void 133 usage(void) 134 { 135 printf("usage: %s [-nqv] [-c cyls] [-F fillbyte] [-g gap3len] " 136 "[-h heads]\n" 137 " [-i intleave] [-r rate] [-S secshft] [-s secs]\n" 138 " [-t steps_per_track] device_name\n", __progname); 139 exit(2); 140 } 141 142 static int 143 yes(void) 144 { 145 char reply[256], *p; 146 147 for (;;) { 148 fflush(stdout); 149 if (!fgets(reply, sizeof(reply), stdin)) 150 return (0); 151 for (p=reply; *p==' ' || *p=='\t'; ++p) 152 continue; 153 if (*p=='y' || *p=='Y') 154 return (1); 155 if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r') 156 return (0); 157 printf("Answer `yes' or `no': "); 158 } 159 } 160 161 int 162 main(int argc, char *argv[]) 163 { 164 int cyls = -1, secs = -1, heads = -1, intleave = -1; 165 int rate = -1, gaplen = -1, secsize = -1, steps = -1; 166 int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0; 167 int fd, c, track, error, tracks_per_dot, bytes_per_track, errs; 168 const char *errstr; 169 char *devname; 170 struct fd_type fdt; 171 172 while((c = getopt(argc, argv, "c:s:h:r:g:S:F:t:i:qvn")) != -1) 173 switch (c) { 174 case 'c': /* # of cyls */ 175 cyls = strtonum(optarg, 1, INT_MAX, &errstr); 176 if (errstr) 177 errx(1, "-c %s: %s", optarg, errstr); 178 break; 179 180 case 's': /* # of secs per track */ 181 secs = strtonum(optarg, 1, INT_MAX, &errstr); 182 if (errstr) 183 errx(1, "-s %s: %s", optarg, errstr); 184 break; 185 186 case 'h': /* # of heads */ 187 heads = strtonum(optarg, 1, INT_MAX, &errstr); 188 if (errstr) 189 errx(1, "-h %s: %s", optarg, errstr); 190 break; 191 192 case 'r': /* transfer rate, kilobyte/sec */ 193 rate = strtonum(optarg, 1, INT_MAX, &errstr); 194 if (errstr) 195 errx(1, "-r %s: %s", optarg, errstr); 196 break; 197 198 case 'g': /* length of GAP3 to format with */ 199 gaplen = strtonum(optarg, 1, INT_MAX, &errstr); 200 if (errstr) 201 errx(1, "-g %s: %s", optarg, errstr); 202 break; 203 204 case 'S': /* sector size shift factor (1 << S)*128 */ 205 secsize = strtonum(optarg, 0, INT_MAX, &errstr); 206 if (errstr) 207 errx(1, "-S %s: %s", optarg, errstr); 208 break; 209 210 case 'F': /* fill byte, C-like notation allowed */ 211 fill = (int)strtol(optarg, NULL, 0); 212 break; 213 214 case 't': /* steps per track */ 215 steps = strtonum(optarg, 1, INT_MAX, &errstr); 216 if (errstr) 217 errx(1, "-t %s: %s", optarg, errstr); 218 break; 219 220 case 'i': /* interleave factor */ 221 intleave = strtonum(optarg, 1, INT_MAX, &errstr); 222 if (errstr) 223 errx(1, "-i %s: %s", optarg, errstr); 224 break; 225 226 case 'q': 227 quiet = 1; 228 break; 229 230 case 'n': 231 verify = 0; 232 break; 233 234 case 'v': 235 verify = 1; 236 verify_only = 1; 237 break; 238 239 default: 240 usage(); 241 } 242 243 if (optind != argc - 1) 244 usage(); 245 246 if ((fd = opendev(argv[optind], O_RDWR, OPENDEV_PART, &devname)) == -1) 247 err(1, "%s", devname); 248 249 if (ioctl(fd, FD_GTYPE, &fdt) == -1) 250 errx(1, "not a floppy disk: %s", devname); 251 252 switch (rate) { 253 case -1: 254 break; 255 case 250: 256 fdt.rate = FDC_250KBPS; 257 break; 258 case 300: 259 fdt.rate = FDC_300KBPS; 260 break; 261 case 500: 262 fdt.rate = FDC_500KBPS; 263 break; 264 default: 265 errx(1, "invalid transfer rate: %d", rate); 266 } 267 268 if (cyls >= 0) 269 fdt.tracks = cyls; 270 if (secs >= 0) 271 fdt.sectrac = secs; 272 if (fdt.sectrac > FD_MAX_NSEC) 273 errx(1, "too many sectors per track, max value is %d", 274 FD_MAX_NSEC); 275 if (heads >= 0) 276 fdt.heads = heads; 277 if (gaplen >= 0) 278 fdt.gap2 = gaplen; 279 if (secsize >= 0) 280 fdt.secsize = secsize; 281 if (steps >= 0) 282 fdt.step = steps; 283 284 bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128; 285 tracks_per_dot = fdt.tracks * fdt.heads / 40; 286 if (tracks_per_dot == 0) 287 tracks_per_dot++; 288 289 if (verify_only) { 290 if (!quiet) 291 printf("Verify %dK floppy `%s'.\n", 292 fdt.tracks * fdt.heads * bytes_per_track / 1024, 293 devname); 294 } 295 else if (!quiet) { 296 printf("Format %dK floppy `%s'? (y/n): ", 297 fdt.tracks * fdt.heads * bytes_per_track / 1024, 298 devname); 299 if (!yes()) { 300 printf("Not confirmed.\n"); 301 exit(0); 302 } 303 } 304 305 /* 306 * Formatting. 307 */ 308 if (!quiet) { 309 printf("Processing "); 310 for (track = 0; track < fdt.tracks * fdt.heads; track++) { 311 if (!((track + 1) % tracks_per_dot)) 312 putchar('-'); 313 } 314 putchar('\r'); 315 printf("Processing "); 316 fflush(stdout); 317 } 318 319 error = errs = 0; 320 321 for (track = 0; track < fdt.tracks * fdt.heads; track++) { 322 if (!verify_only) { 323 format_track(fd, track / fdt.heads, fdt.sectrac, 324 track % fdt.heads, fdt.rate, fdt.gap2, 325 fdt.secsize, fill, 326 intleave >= 0 ? intleave : 1); 327 if (!quiet && !((track + 1) % tracks_per_dot)) { 328 putchar('F'); 329 fflush(stdout); 330 } 331 } 332 if (verify) { 333 if (verify_track(fd, track, bytes_per_track) < 0) 334 error = errs = 1; 335 if (!quiet && !((track + 1) % tracks_per_dot)) { 336 if (!verify_only) 337 putchar('\b'); 338 if (error) { 339 putchar('E'); 340 error = 0; 341 } 342 else 343 putchar('V'); 344 fflush(stdout); 345 } 346 } 347 } 348 close(fd); 349 if (!quiet) 350 printf(" done.\n"); 351 352 exit(errs); 353 } 354