fdformat.c revision 29531
11022Sache/* 21533Sjoerg * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden 31022Sache * All rights reserved. 41022Sache * 51022Sache * Redistribution and use in source and binary forms, with or without 61022Sache * modification, are permitted provided that the following conditions 71022Sache * are met: 81022Sache * 1. Redistributions of source code must retain the above copyright 91022Sache * notice, this list of conditions and the following disclaimer. 101022Sache * 2. Redistributions in binary form must reproduce the above copyright 111022Sache * notice, this list of conditions and the following disclaimer in the 121022Sache * documentation and/or other materials provided with the distribution. 131022Sache * 141533Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 151533Sjoerg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 161533Sjoerg * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 171533Sjoerg * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, 181533Sjoerg * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 191533Sjoerg * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 201533Sjoerg * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211533Sjoerg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 221533Sjoerg * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 231533Sjoerg * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 241533Sjoerg * POSSIBILITY OF SUCH DAMAGE. 251022Sache */ 261022Sache 271022Sache/* 281022Sache * FreeBSD: 291022Sache * format a floppy disk 308857Srgrimes * 311022Sache * Added FD_GTYPE ioctl, verifying, proportional indicators. 321022Sache * Serge Vakulenko, vak@zebub.msk.su 331022Sache * Sat Dec 18 17:45:47 MSK 1993 341022Sache * 351022Sache * Final adaptation, change format/verify logic, add separate 361022Sache * format gap/interleave values 371022Sache * Andrew A. Chernov, ache@astral.msk.su 381022Sache * Thu Jan 27 00:47:24 MSK 1994 391022Sache */ 401022Sache 4129531Scharnier#include <ctype.h> 4229531Scharnier#include <err.h> 4329531Scharnier#include <fcntl.h> 441022Sache#include <stdio.h> 451022Sache#include <stdlib.h> 4629531Scharnier#include <strings.h> 471022Sache#include <unistd.h> 481022Sache 491022Sache#include <machine/ioctl_fd.h> 501022Sache 511022Sachestatic void 521022Sacheformat_track(int fd, int cyl, int secs, int head, int rate, 531137Sache int gaplen, int secsize, int fill,int interleave) 541022Sache{ 551022Sache struct fd_formb f; 561137Sache register int i,j; 571138Sache int il[FD_MAX_NSEC + 1]; 581022Sache 591137Sache memset(il,0,sizeof il); 601137Sache for(j = 0, i = 1; i <= secs; i++) { 611137Sache while(il[(j%secs)+1]) j++; 621137Sache il[(j%secs)+1] = i; 631137Sache j += interleave; 641137Sache } 651137Sache 661022Sache f.format_version = FD_FORMAT_VERSION; 671022Sache f.head = head; 681022Sache f.cyl = cyl; 691022Sache f.transfer_rate = rate; 701022Sache 711022Sache f.fd_formb_secshift = secsize; 721022Sache f.fd_formb_nsecs = secs; 731022Sache f.fd_formb_gaplen = gaplen; 741022Sache f.fd_formb_fillbyte = fill; 751022Sache for(i = 0; i < secs; i++) { 761022Sache f.fd_formb_cylno(i) = cyl; 771022Sache f.fd_formb_headno(i) = head; 781137Sache f.fd_formb_secno(i) = il[i+1]; 791022Sache f.fd_formb_secsize(i) = secsize; 801022Sache } 8129531Scharnier if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0) 8229531Scharnier err(1, "ioctl(FD_FORM)"); 831022Sache} 841022Sache 851022Sachestatic int 861022Sacheverify_track(int fd, int track, int tracksize) 871022Sache{ 881022Sache static char *buf = 0; 891022Sache static int bufsz = 0; 901533Sjoerg int fdopts = -1, ofdopts, rv = 0; 911022Sache 921533Sjoerg if (ioctl(fd, FD_GOPTS, &fdopts) < 0) 9329531Scharnier warn("warning: ioctl(FD_GOPTS)"); 941533Sjoerg else { 951533Sjoerg ofdopts = fdopts; 961533Sjoerg fdopts |= FDOPT_NORETRY; 971533Sjoerg (void)ioctl(fd, FD_SOPTS, &fdopts); 981533Sjoerg } 998857Srgrimes 1001022Sache if (bufsz < tracksize) { 1011022Sache if (buf) 1021022Sache free (buf); 1031022Sache bufsz = tracksize; 1041022Sache buf = 0; 1051022Sache } 1061022Sache if (! buf) 1071022Sache buf = malloc (bufsz); 10829531Scharnier if (! buf) 10929531Scharnier errx(2, "out of memory"); 1101022Sache if (lseek (fd, (long) track*tracksize, 0) < 0) 1111533Sjoerg rv = -1; 1121533Sjoerg /* try twice reading it, without using the normal retrier */ 1131533Sjoerg else if (read (fd, buf, tracksize) != tracksize 1141533Sjoerg && read (fd, buf, tracksize) != tracksize) 1151533Sjoerg rv = -1; 1161533Sjoerg if(fdopts != -1) 1171533Sjoerg (void)ioctl(fd, FD_SOPTS, &ofdopts); 1181533Sjoerg return (rv); 1191022Sache} 1201022Sache 1211022Sachestatic const char * 1221022Sachemakename(const char *arg, const char *suffix) 1231022Sache{ 1241022Sache static char namebuff[20]; /* big enough for "/dev/rfd0a"... */ 1251022Sache 1261022Sache memset(namebuff, 0, 20); 1271022Sache if(*arg == '\0') /* ??? */ 1281022Sache return arg; 1291022Sache if(*arg == '/') /* do not convert absolute pathnames */ 1301022Sache return arg; 1311022Sache strcpy(namebuff, "/dev/r"); 1321022Sache strncat(namebuff, arg, 3); 1331022Sache strcat(namebuff, suffix); 1341022Sache return namebuff; 1351022Sache} 1361022Sache 1371022Sachestatic void 1381533Sjoergusage (void) 1391022Sache{ 14029531Scharnier fprintf(stderr, "%s\n%s\n", 14129531Scharnier "usage: fdformat [-q] [-n | -v] [-f #] [-c #] [-s #] [-h #]", 14229531Scharnier " [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] devname"); 1431022Sache exit(2); 1441022Sache} 1451022Sache 1461022Sachestatic int 1471533Sjoergyes (void) 1481022Sache{ 1491022Sache char reply [256], *p; 1501022Sache 1511022Sache reply[sizeof(reply)-1] = 0; 1521022Sache for (;;) { 1531022Sache fflush(stdout); 1541022Sache if (! fgets (reply, sizeof(reply)-1, stdin)) 1551022Sache return (0); 1561022Sache for (p=reply; *p==' ' || *p=='\t'; ++p) 1571022Sache continue; 1581022Sache if (*p=='y' || *p=='Y') 1591022Sache return (1); 1601022Sache if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r') 1611022Sache return (0); 1621022Sache printf("Answer `yes' or `no': "); 1631022Sache } 1641022Sache} 1651022Sache 1661022Sacheint 1671022Sachemain(int argc, char **argv) 1681022Sache{ 1691022Sache int format = -1, cyls = -1, secs = -1, heads = -1, intleave = -1; 1701022Sache int rate = -1, gaplen = -1, secsize = -1, steps = -1; 1711022Sache int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0; 1721022Sache int fd, c, track, error, tracks_per_dot, bytes_per_track, errs; 1731022Sache const char *devname, *suffix; 1741022Sache struct fd_type fdt; 1751022Sache 1761022Sache while((c = getopt(argc, argv, "f:c:s:h:r:g:S:F:t:i:qvn")) != -1) 1771022Sache switch(c) { 1781022Sache case 'f': /* format in kilobytes */ 1791022Sache format = atoi(optarg); 1801022Sache break; 1811022Sache 1821022Sache case 'c': /* # of cyls */ 1831022Sache cyls = atoi(optarg); 1841022Sache break; 1851022Sache 1861022Sache case 's': /* # of secs per track */ 1871022Sache secs = atoi(optarg); 1881022Sache break; 1891022Sache 1901022Sache case 'h': /* # of heads */ 1911022Sache heads = atoi(optarg); 1921022Sache break; 1931022Sache 1941022Sache case 'r': /* transfer rate, kilobyte/sec */ 1951022Sache rate = atoi(optarg); 1961022Sache break; 1971022Sache 1981022Sache case 'g': /* length of GAP3 to format with */ 1991022Sache gaplen = atoi(optarg); 2001022Sache break; 2011022Sache 2021022Sache case 'S': /* sector size shift factor (1 << S)*128 */ 2031022Sache secsize = atoi(optarg); 2041022Sache break; 2051022Sache 2061022Sache case 'F': /* fill byte, C-like notation allowed */ 2071022Sache fill = (int)strtol(optarg, (char **)0, 0); 2081022Sache break; 2091022Sache 2101022Sache case 't': /* steps per track */ 2111022Sache steps = atoi(optarg); 2121022Sache break; 2131022Sache 2141022Sache case 'i': /* interleave factor */ 2151022Sache intleave = atoi(optarg); 2161022Sache break; 2171022Sache 2181022Sache case 'q': 2191022Sache quiet = 1; 2201022Sache break; 2211022Sache 2221022Sache case 'n': 2231022Sache verify = 0; 2241022Sache break; 2251022Sache 2261022Sache case 'v': 2271022Sache verify = 1; 2281022Sache verify_only = 1; 2291022Sache break; 2301022Sache 2311022Sache case '?': default: 2321022Sache usage(); 2331022Sache } 2341022Sache 2351022Sache if(optind != argc - 1) 2361022Sache usage(); 2371022Sache 2381022Sache switch(format) { 2391022Sache default: 24029531Scharnier errx(2, "bad floppy size: %dK", format); 2411022Sache case -1: suffix = ""; break; 2421022Sache case 360: suffix = ".360"; break; 2431022Sache case 720: suffix = ".720"; break; 2441022Sache case 800: suffix = ".800"; break; 2451022Sache case 820: suffix = ".820"; break; 2461022Sache case 1200: suffix = ".1200"; break; 2471022Sache case 1440: suffix = ".1440"; break; 2481022Sache case 1480: suffix = ".1480"; break; 2491022Sache case 1720: suffix = ".1720"; break; 2501022Sache } 2511022Sache 2521022Sache devname = makename(argv[optind], suffix); 2531022Sache 25429531Scharnier if((fd = open(devname, O_RDWR)) < 0) 25529531Scharnier err(1, "%s", devname); 2561022Sache 25729531Scharnier if(ioctl(fd, FD_GTYPE, &fdt) < 0) 25829531Scharnier errx(1, "not a floppy disk: %s", devname); 2591022Sache 2601022Sache switch(rate) { 2611022Sache case -1: break; 2621022Sache case 250: fdt.trans = FDC_250KBPS; break; 2631022Sache case 300: fdt.trans = FDC_300KBPS; break; 2641022Sache case 500: fdt.trans = FDC_500KBPS; break; 2651022Sache default: 26629531Scharnier errx(2, "invalid transfer rate: %d", rate); 2671022Sache } 2681022Sache 2691022Sache if (cyls >= 0) fdt.tracks = cyls; 2701022Sache if (secs >= 0) fdt.sectrac = secs; 27129531Scharnier if (fdt.sectrac > FD_MAX_NSEC) 27229531Scharnier errx(2, "too many sectors per track, max value is %d", FD_MAX_NSEC); 2731022Sache if (heads >= 0) fdt.heads = heads; 2741022Sache if (gaplen >= 0) fdt.f_gap = gaplen; 2751022Sache if (secsize >= 0) fdt.secsize = secsize; 2761022Sache if (steps >= 0) fdt.steptrac = steps; 2771022Sache if (intleave >= 0) fdt.f_inter = intleave; 2781022Sache 2791022Sache bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128; 2801022Sache tracks_per_dot = fdt.tracks * fdt.heads / 40; 2811022Sache 2821022Sache if (verify_only) { 2831022Sache if(!quiet) 2841022Sache printf("Verify %dK floppy `%s'.\n", 2851022Sache fdt.tracks * fdt.heads * bytes_per_track / 1024, 2861022Sache devname); 2871022Sache } 2881022Sache else if(!quiet) { 2891022Sache printf("Format %dK floppy `%s'? (y/n): ", 2901022Sache fdt.tracks * fdt.heads * bytes_per_track / 1024, 2911022Sache devname); 2921022Sache if(! yes ()) { 2931022Sache printf("Not confirmed.\n"); 2941022Sache return 0; 2951022Sache } 2961022Sache } 2971022Sache 2981022Sache /* 2991022Sache * Formatting. 3001022Sache */ 3011022Sache if(!quiet) { 3021022Sache printf("Processing ----------------------------------------\r"); 3031022Sache printf("Processing "); 3041022Sache fflush(stdout); 3051022Sache } 3061022Sache 3071022Sache error = errs = 0; 3081022Sache 3091022Sache for (track = 0; track < fdt.tracks * fdt.heads; track++) { 3101022Sache if (!verify_only) { 3111183Srgrimes format_track(fd, track / fdt.heads, fdt.sectrac, 3121183Srgrimes track % fdt.heads, fdt.trans, fdt.f_gap, 3131183Srgrimes fdt.secsize, fill, fdt.f_inter); 3141022Sache if(!quiet && !((track + 1) % tracks_per_dot)) { 3151022Sache putchar('F'); 3161022Sache fflush(stdout); 3171022Sache } 3181022Sache } 3191022Sache if (verify) { 3201022Sache if (verify_track(fd, track, bytes_per_track) < 0) 3211022Sache error = errs = 1; 3221022Sache if(!quiet && !((track + 1) % tracks_per_dot)) { 3231022Sache if (!verify_only) 3241022Sache putchar('\b'); 3251022Sache if (error) { 3261022Sache putchar('E'); 3271022Sache error = 0; 3281022Sache } 3291022Sache else 3301022Sache putchar('V'); 3311022Sache fflush(stdout); 3321022Sache } 3331022Sache } 3341022Sache } 3351022Sache if(!quiet) 3361022Sache printf(" done.\n"); 3371022Sache 3381022Sache return errs; 3391022Sache} 3401533Sjoerg/* 3411533Sjoerg * Local Variables: 3421533Sjoerg * c-indent-level: 8 3431533Sjoerg * c-continued-statement-offset: 8 3441533Sjoerg * c-continued-brace-offset: 0 3451533Sjoerg * c-brace-offset: -8 3461533Sjoerg * c-brace-imaginary-offset: 0 3471533Sjoerg * c-argdecl-indent: 8 3481533Sjoerg * c-label-offset: -8 3491533Sjoerg * c++-hanging-braces: 1 3501533Sjoerg * c++-access-specifier-offset: -8 3511533Sjoerg * c++-empty-arglist-indent: 8 3521533Sjoerg * c++-friend-offset: 0 3531533Sjoerg * End: 3541533Sjoerg */ 355