fdformat.c revision 1137
11022Sache/* 21022Sache * Copyright (C) 1992-1993 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 * 141022Sache * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 151022Sache * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161022Sache * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171022Sache * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 181022Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191022Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201022Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211022Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221022Sache * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231022Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241022Sache * SUCH DAMAGE. 251022Sache */ 261022Sache 271022Sache/* 281022Sache * FreeBSD: 291022Sache * format a floppy disk 301022Sache * 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 411022Sache#include <stdio.h> 421022Sache#include <stdlib.h> 431022Sache#include <unistd.h> 441022Sache#include <fcntl.h> 451022Sache#include <strings.h> 461022Sache#include <ctype.h> 471022Sache 481022Sache#include <errno.h> 491022Sache#include <machine/ioctl_fd.h> 501022Sache#include <../i386/isa/fdreg.h> /* XXX should be in <machine> dir */ 511022Sache 521022Sachestatic void 531022Sacheformat_track(int fd, int cyl, int secs, int head, int rate, 541137Sache int gaplen, int secsize, int fill,int interleave) 551022Sache{ 561022Sache struct fd_formb f; 571137Sache register int i,j; 581137Sache int il[FD_MAX_NSEC]; 591022Sache 601137Sache memset(il,0,sizeof il); 611137Sache for(j = 0, i = 1; i <= secs; i++) { 621137Sache while(il[(j%secs)+1]) j++; 631137Sache il[(j%secs)+1] = i; 641137Sache j += interleave; 651137Sache } 661137Sache 671022Sache f.format_version = FD_FORMAT_VERSION; 681022Sache f.head = head; 691022Sache f.cyl = cyl; 701022Sache f.transfer_rate = rate; 711022Sache 721022Sache f.fd_formb_secshift = secsize; 731022Sache f.fd_formb_nsecs = secs; 741022Sache f.fd_formb_gaplen = gaplen; 751022Sache f.fd_formb_fillbyte = fill; 761022Sache for(i = 0; i < secs; i++) { 771022Sache f.fd_formb_cylno(i) = cyl; 781022Sache f.fd_formb_headno(i) = head; 791137Sache f.fd_formb_secno(i) = il[i+1]; 801022Sache f.fd_formb_secsize(i) = secsize; 811022Sache } 821022Sache if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0) { 831022Sache perror("\nfdformat: ioctl(FD_FORM)"); 841022Sache exit(1); 851022Sache } 861022Sache} 871022Sache 881022Sachestatic int 891022Sacheverify_track(int fd, int track, int tracksize) 901022Sache{ 911022Sache static char *buf = 0; 921022Sache static int bufsz = 0; 931022Sache 941022Sache if (bufsz < tracksize) { 951022Sache if (buf) 961022Sache free (buf); 971022Sache bufsz = tracksize; 981022Sache buf = 0; 991022Sache } 1001022Sache if (! buf) 1011022Sache buf = malloc (bufsz); 1021022Sache if (! buf) { 1031022Sache fprintf (stderr, "\nfdformat: out of memory\n"); 1041022Sache exit (2); 1051022Sache } 1061022Sache if (lseek (fd, (long) track*tracksize, 0) < 0) 1071022Sache return (-1); 1081022Sache if (read (fd, buf, tracksize) != tracksize) 1091022Sache return (-1); 1101022Sache return (0); 1111022Sache} 1121022Sache 1131022Sachestatic const char * 1141022Sachemakename(const char *arg, const char *suffix) 1151022Sache{ 1161022Sache static char namebuff[20]; /* big enough for "/dev/rfd0a"... */ 1171022Sache 1181022Sache memset(namebuff, 0, 20); 1191022Sache if(*arg == '\0') /* ??? */ 1201022Sache return arg; 1211022Sache if(*arg == '/') /* do not convert absolute pathnames */ 1221022Sache return arg; 1231022Sache strcpy(namebuff, "/dev/r"); 1241022Sache strncat(namebuff, arg, 3); 1251022Sache strcat(namebuff, suffix); 1261022Sache return namebuff; 1271022Sache} 1281022Sache 1291022Sachestatic void 1301022Sacheusage () 1311022Sache{ 1321022Sache printf("Usage:\n\tfdformat [-q] [-n | -v] [-f #] [-c #] [-s #] [-h #]\n"); 1331022Sache printf("\t\t [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] devname\n"); 1341022Sache printf("Options:\n"); 1351022Sache printf("\t-q\tsupress any normal output, don't ask for confirmation\n"); 1361022Sache printf("\t-n\tdon't verify floppy after formatting\n"); 1371022Sache printf("\t-v\tdon't format, verify only\n"); 1381022Sache printf("\t-f #\tspecify desired floppy capacity, in kilobytes;\n"); 1391022Sache printf("\t\tvalid choices are 360, 720, 800, 820, 1200, 1440, 1480, 1720\n"); 1401022Sache printf("\tdevname\tthe full name of floppy device or in short form fd0, fd1\n"); 1411022Sache printf("Obscure options:\n"); 1421022Sache printf("\t-c #\tspecify number of cylinders, 40 or 80\n"); 1431022Sache printf("\t-s #\tspecify number of sectors per track, 9, 10, 15 or 18\n"); 1441022Sache printf("\t-h #\tspecify number of floppy heads, 1 or 2\n"); 1451022Sache printf("\t-r #\tspecify data rate, 250, 300 or 500 kbps\n"); 1461022Sache printf("\t-g #\tspecify gap length\n"); 1471022Sache printf("\t-i #\tspecify interleave factor\n"); 1481022Sache printf("\t-S #\tspecify sector size, 0=128, 1=256, 2=512 bytes\n"); 1491022Sache printf("\t-F #\tspecify fill byte\n"); 1501022Sache printf("\t-t #\tnumber of steps per track\n"); 1511022Sache exit(2); 1521022Sache} 1531022Sache 1541022Sachestatic int 1551022Sacheyes () 1561022Sache{ 1571022Sache char reply [256], *p; 1581022Sache 1591022Sache reply[sizeof(reply)-1] = 0; 1601022Sache for (;;) { 1611022Sache fflush(stdout); 1621022Sache if (! fgets (reply, sizeof(reply)-1, stdin)) 1631022Sache return (0); 1641022Sache for (p=reply; *p==' ' || *p=='\t'; ++p) 1651022Sache continue; 1661022Sache if (*p=='y' || *p=='Y') 1671022Sache return (1); 1681022Sache if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r') 1691022Sache return (0); 1701022Sache printf("Answer `yes' or `no': "); 1711022Sache } 1721022Sache} 1731022Sache 1741022Sacheint 1751022Sachemain(int argc, char **argv) 1761022Sache{ 1771022Sache int format = -1, cyls = -1, secs = -1, heads = -1, intleave = -1; 1781022Sache int rate = -1, gaplen = -1, secsize = -1, steps = -1; 1791022Sache int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0; 1801022Sache int fd, c, track, error, tracks_per_dot, bytes_per_track, errs; 1811022Sache const char *devname, *suffix; 1821022Sache struct fd_type fdt; 1831022Sache 1841022Sache while((c = getopt(argc, argv, "f:c:s:h:r:g:S:F:t:i:qvn")) != -1) 1851022Sache switch(c) { 1861022Sache case 'f': /* format in kilobytes */ 1871022Sache format = atoi(optarg); 1881022Sache break; 1891022Sache 1901022Sache case 'c': /* # of cyls */ 1911022Sache cyls = atoi(optarg); 1921022Sache break; 1931022Sache 1941022Sache case 's': /* # of secs per track */ 1951022Sache secs = atoi(optarg); 1961022Sache break; 1971022Sache 1981022Sache case 'h': /* # of heads */ 1991022Sache heads = atoi(optarg); 2001022Sache break; 2011022Sache 2021022Sache case 'r': /* transfer rate, kilobyte/sec */ 2031022Sache rate = atoi(optarg); 2041022Sache break; 2051022Sache 2061022Sache case 'g': /* length of GAP3 to format with */ 2071022Sache gaplen = atoi(optarg); 2081022Sache break; 2091022Sache 2101022Sache case 'S': /* sector size shift factor (1 << S)*128 */ 2111022Sache secsize = atoi(optarg); 2121022Sache break; 2131022Sache 2141022Sache case 'F': /* fill byte, C-like notation allowed */ 2151022Sache fill = (int)strtol(optarg, (char **)0, 0); 2161022Sache break; 2171022Sache 2181022Sache case 't': /* steps per track */ 2191022Sache steps = atoi(optarg); 2201022Sache break; 2211022Sache 2221022Sache case 'i': /* interleave factor */ 2231022Sache intleave = atoi(optarg); 2241022Sache break; 2251022Sache 2261022Sache case 'q': 2271022Sache quiet = 1; 2281022Sache break; 2291022Sache 2301022Sache case 'n': 2311022Sache verify = 0; 2321022Sache break; 2331022Sache 2341022Sache case 'v': 2351022Sache verify = 1; 2361022Sache verify_only = 1; 2371022Sache break; 2381022Sache 2391022Sache case '?': default: 2401022Sache usage(); 2411022Sache } 2421022Sache 2431022Sache if(optind != argc - 1) 2441022Sache usage(); 2451022Sache 2461022Sache switch(format) { 2471022Sache default: 2481022Sache fprintf(stderr, "fdformat: bad floppy size: %dK\n", format); 2491022Sache exit(2); 2501022Sache case -1: suffix = ""; break; 2511022Sache case 360: suffix = ".360"; break; 2521022Sache case 720: suffix = ".720"; break; 2531022Sache case 800: suffix = ".800"; break; 2541022Sache case 820: suffix = ".820"; break; 2551022Sache case 1200: suffix = ".1200"; break; 2561022Sache case 1440: suffix = ".1440"; break; 2571022Sache case 1480: suffix = ".1480"; break; 2581022Sache case 1720: suffix = ".1720"; break; 2591022Sache } 2601022Sache 2611022Sache devname = makename(argv[optind], suffix); 2621022Sache 2631022Sache if((fd = open(devname, O_RDWR)) < 0) { 2641022Sache perror(devname); 2651022Sache exit(1); 2661022Sache } 2671022Sache 2681022Sache if(ioctl(fd, FD_GTYPE, &fdt) < 0) { 2691022Sache fprintf(stderr, "fdformat: not a floppy disk: %s\n", devname); 2701022Sache exit(1); 2711022Sache } 2721022Sache 2731022Sache switch(rate) { 2741022Sache case -1: break; 2751022Sache case 250: fdt.trans = FDC_250KBPS; break; 2761022Sache case 300: fdt.trans = FDC_300KBPS; break; 2771022Sache case 500: fdt.trans = FDC_500KBPS; break; 2781022Sache default: 2791022Sache fprintf(stderr, "fdformat: invalid transfer rate: %d\n", rate); 2801022Sache exit(2); 2811022Sache } 2821022Sache 2831022Sache if (cyls >= 0) fdt.tracks = cyls; 2841022Sache if (secs >= 0) fdt.sectrac = secs; 2851137Sache if (fdt.sectrac > FD_MAX_NSEC) { 2861137Sache fprintf(stderr, "fdformat: too many sectors per track, max value is %d\n", FD_MAX_NSEC); 2871137Sache exit(2); 2881137Sache } 2891022Sache if (heads >= 0) fdt.heads = heads; 2901022Sache if (gaplen >= 0) fdt.f_gap = gaplen; 2911022Sache if (secsize >= 0) fdt.secsize = secsize; 2921022Sache if (steps >= 0) fdt.steptrac = steps; 2931022Sache if (intleave >= 0) fdt.f_inter = intleave; 2941022Sache 2951022Sache bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128; 2961022Sache tracks_per_dot = fdt.tracks * fdt.heads / 40; 2971022Sache 2981022Sache if (verify_only) { 2991022Sache if(!quiet) 3001022Sache printf("Verify %dK floppy `%s'.\n", 3011022Sache fdt.tracks * fdt.heads * bytes_per_track / 1024, 3021022Sache devname); 3031022Sache } 3041022Sache else if(!quiet) { 3051022Sache printf("Format %dK floppy `%s'? (y/n): ", 3061022Sache fdt.tracks * fdt.heads * bytes_per_track / 1024, 3071022Sache devname); 3081022Sache if(! yes ()) { 3091022Sache printf("Not confirmed.\n"); 3101022Sache return 0; 3111022Sache } 3121022Sache } 3131022Sache 3141022Sache /* 3151022Sache * Formatting. 3161022Sache */ 3171022Sache if(!quiet) { 3181022Sache printf("Processing ----------------------------------------\r"); 3191022Sache printf("Processing "); 3201022Sache fflush(stdout); 3211022Sache } 3221022Sache 3231022Sache error = errs = 0; 3241022Sache 3251022Sache for (track = 0; track < fdt.tracks * fdt.heads; track++) { 3261022Sache if (!verify_only) { 3271022Sache format_track(fd, track / 2, fdt.sectrac, track & 1, 3281137Sache fdt.trans, fdt.f_gap, fdt.secsize, fill, 3291137Sache fdt.f_inter); 3301022Sache if(!quiet && !((track + 1) % tracks_per_dot)) { 3311022Sache putchar('F'); 3321022Sache fflush(stdout); 3331022Sache } 3341022Sache } 3351022Sache if (verify) { 3361022Sache if (verify_track(fd, track, bytes_per_track) < 0) 3371022Sache error = errs = 1; 3381022Sache if(!quiet && !((track + 1) % tracks_per_dot)) { 3391022Sache if (!verify_only) 3401022Sache putchar('\b'); 3411022Sache if (error) { 3421022Sache putchar('E'); 3431022Sache error = 0; 3441022Sache } 3451022Sache else 3461022Sache putchar('V'); 3471022Sache fflush(stdout); 3481022Sache } 3491022Sache } 3501022Sache } 3511022Sache if(!quiet) 3521022Sache printf(" done.\n"); 3531022Sache 3541022Sache return errs; 3551022Sache} 356