fdformat.c revision 1183
190618Stmm/* 290618Stmm * Copyright (C) 1992-1993 by Joerg Wunsch, Dresden 390618Stmm * All rights reserved. 490618Stmm * 590618Stmm * Redistribution and use in source and binary forms, with or without 690618Stmm * modification, are permitted provided that the following conditions 790618Stmm * are met: 890618Stmm * 1. Redistributions of source code must retain the above copyright 990618Stmm * notice, this list of conditions and the following disclaimer. 1090618Stmm * 2. Redistributions in binary form must reproduce the above copyright 1190618Stmm * notice, this list of conditions and the following disclaimer in the 1290618Stmm * documentation and/or other materials provided with the distribution. 1390618Stmm * 1490618Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 1590618Stmm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1690618Stmm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1790618Stmm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1890618Stmm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1990618Stmm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2090618Stmm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2190618Stmm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2290618Stmm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2390618Stmm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2490618Stmm * SUCH DAMAGE. 2590618Stmm */ 2690618Stmm 2790618Stmm/* 2890618Stmm * FreeBSD: 2990618Stmm * format a floppy disk 3090618Stmm * 3190618Stmm * Added FD_GTYPE ioctl, verifying, proportional indicators. 3290618Stmm * Serge Vakulenko, vak@zebub.msk.su 3390618Stmm * Sat Dec 18 17:45:47 MSK 1993 3490618Stmm * 3590618Stmm * Final adaptation, change format/verify logic, add separate 36139825Simp * format gap/interleave values 3790618Stmm * Andrew A. Chernov, ache@astral.msk.su 3890618Stmm * Thu Jan 27 00:47:24 MSK 1994 3990618Stmm */ 4090618Stmm 4190618Stmm#include <stdio.h> 4290618Stmm#include <stdlib.h> 4390618Stmm#include <unistd.h> 4490618Stmm#include <fcntl.h> 4590618Stmm#include <strings.h> 4690618Stmm#include <ctype.h> 4790618Stmm 4890618Stmm#include <errno.h> 4990618Stmm#include <machine/ioctl_fd.h> 5090618Stmm#include <../i386/isa/fdreg.h> /* XXX should be in <machine> dir */ 5190618Stmm 5290618Stmmstatic void 5390618Stmmformat_track(int fd, int cyl, int secs, int head, int rate, 5490618Stmm int gaplen, int secsize, int fill,int interleave) 5590618Stmm{ 5690618Stmm struct fd_formb f; 5790618Stmm register int i,j; 5890618Stmm int il[FD_MAX_NSEC + 1]; 5990618Stmm 6090618Stmm memset(il,0,sizeof il); 6190618Stmm for(j = 0, i = 1; i <= secs; i++) { 6290618Stmm while(il[(j%secs)+1]) j++; 6390618Stmm il[(j%secs)+1] = i; 6490618Stmm j += interleave; 6590618Stmm } 6690618Stmm 6790618Stmm f.format_version = FD_FORMAT_VERSION; 6890618Stmm f.head = head; 6990618Stmm f.cyl = cyl; 7090618Stmm f.transfer_rate = rate; 7190618Stmm 7290618Stmm f.fd_formb_secshift = secsize; 73139825Simp f.fd_formb_nsecs = secs; 7490618Stmm f.fd_formb_gaplen = gaplen; 7590618Stmm f.fd_formb_fillbyte = fill; 76167308Smarius for(i = 0; i < secs; i++) { 7790618Stmm f.fd_formb_cylno(i) = cyl; 7890618Stmm f.fd_formb_headno(i) = head; 7990618Stmm f.fd_formb_secno(i) = il[i+1]; 8090618Stmm f.fd_formb_secsize(i) = secsize; 8190618Stmm } 8290618Stmm if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0) { 8390618Stmm perror("\nfdformat: ioctl(FD_FORM)"); 8490618Stmm exit(1); 8590618Stmm } 8690618Stmm} 8790618Stmm 8890618Stmmstatic int 8990618Stmmverify_track(int fd, int track, int tracksize) 9090618Stmm{ 9190618Stmm static char *buf = 0; 9290618Stmm static int bufsz = 0; 9390618Stmm 9490618Stmm if (bufsz < tracksize) { 9590618Stmm if (buf) 9690618Stmm free (buf); 9790618Stmm bufsz = tracksize; 9890618Stmm buf = 0; 9990618Stmm } 10090618Stmm if (! buf) 101145185Smarius buf = malloc (bufsz); 102145185Smarius if (! buf) { 103145185Smarius fprintf (stderr, "\nfdformat: out of memory\n"); 10490618Stmm exit (2); 105145185Smarius } 10690618Stmm if (lseek (fd, (long) track*tracksize, 0) < 0) 107131376Smarius return (-1); 10890618Stmm if (read (fd, buf, tracksize) != tracksize) 10990618Stmm return (-1); 11090618Stmm return (0); 11190618Stmm} 11290618Stmm 113130068Sphkstatic const char * 114107477Stmmmakename(const char *arg, const char *suffix) 115171730Smarius{ 11690618Stmm static char namebuff[20]; /* big enough for "/dev/rfd0a"... */ 117171730Smarius 11890618Stmm memset(namebuff, 0, 20); 119133589Smarius if(*arg == '\0') /* ??? */ 120152684Smarius return arg; 121119338Simp if(*arg == '/') /* do not convert absolute pathnames */ 12290618Stmm return arg; 12390618Stmm strcpy(namebuff, "/dev/r"); 124171730Smarius strncat(namebuff, arg, 3); 125116541Stmm strcat(namebuff, suffix); 12690618Stmm return namebuff; 127171730Smarius} 12890618Stmm 12990618Stmmstatic void 13090618Stmmusage () 13190618Stmm{ 13290618Stmm printf("Usage:\n\tfdformat [-q] [-n | -v] [-f #] [-c #] [-s #] [-h #]\n"); 13390618Stmm printf("\t\t [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] devname\n"); 13490618Stmm printf("Options:\n"); 13590618Stmm printf("\t-q\tsupress any normal output, don't ask for confirmation\n"); 136145186Smarius printf("\t-n\tdon't verify floppy after formatting\n"); 13790618Stmm printf("\t-v\tdon't format, verify only\n"); 13890618Stmm printf("\t-f #\tspecify desired floppy capacity, in kilobytes;\n"); 139152684Smarius printf("\t\tvalid choices are 360, 720, 800, 820, 1200, 1440, 1480, 1720\n"); 14090618Stmm printf("\tdevname\tthe full name of floppy device or in short form fd0, fd1\n"); 14190618Stmm printf("Obscure options:\n"); 14290618Stmm printf("\t-c #\tspecify number of cylinders, 40 or 80\n"); 14390618Stmm printf("\t-s #\tspecify number of sectors per track, 9, 10, 15 or 18\n"); 14490618Stmm printf("\t-h #\tspecify number of floppy heads, 1 or 2\n"); 14590618Stmm printf("\t-r #\tspecify data rate, 250, 300 or 500 kbps\n"); 14690618Stmm printf("\t-g #\tspecify gap length\n"); 14790618Stmm printf("\t-i #\tspecify interleave factor\n"); 14890618Stmm printf("\t-S #\tspecify sector size, 0=128, 1=256, 2=512 bytes\n"); 14990618Stmm printf("\t-F #\tspecify fill byte\n"); 15090618Stmm printf("\t-t #\tnumber of steps per track\n"); 15190618Stmm exit(2); 15290618Stmm} 15390618Stmm 15490618Stmmstatic int 15590618Stmmyes () 156172066Smarius{ 15790618Stmm char reply [256], *p; 15890618Stmm 15990618Stmm reply[sizeof(reply)-1] = 0; 16090618Stmm for (;;) { 16190618Stmm fflush(stdout); 162145185Smarius if (! fgets (reply, sizeof(reply)-1, stdin)) 16390618Stmm return (0); 16490618Stmm for (p=reply; *p==' ' || *p=='\t'; ++p) 165145185Smarius continue; 166145185Smarius if (*p=='y' || *p=='Y') 16790618Stmm return (1); 16890618Stmm if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r') 16990618Stmm return (0); 17090618Stmm printf("Answer `yes' or `no': "); 17190618Stmm } 17290618Stmm} 17390618Stmm 17490618Stmmint 175170852Smariusmain(int argc, char **argv) 17690618Stmm{ 177170852Smarius int format = -1, cyls = -1, secs = -1, heads = -1, intleave = -1; 17890618Stmm int rate = -1, gaplen = -1, secsize = -1, steps = -1; 179145185Smarius int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0; 180145186Smarius int fd, c, track, error, tracks_per_dot, bytes_per_track, errs; 181145185Smarius const char *devname, *suffix; 182145185Smarius struct fd_type fdt; 183145185Smarius 184145185Smarius while((c = getopt(argc, argv, "f:c:s:h:r:g:S:F:t:i:qvn")) != -1) 185145185Smarius switch(c) { 186145185Smarius case 'f': /* format in kilobytes */ 187145185Smarius format = atoi(optarg); 188145185Smarius break; 189145185Smarius 190167308Smarius case 'c': /* # of cyls */ 191152684Smarius cyls = atoi(optarg); 19290618Stmm break; 193190112Smarius 194152684Smarius case 's': /* # of secs per track */ 195152684Smarius secs = atoi(optarg); 196152684Smarius break; 197172066Smarius 198172066Smarius case 'h': /* # of heads */ 199178443Smarius heads = atoi(optarg); 200178443Smarius break; 201172066Smarius 202172066Smarius case 'r': /* transfer rate, kilobyte/sec */ 20390618Stmm rate = atoi(optarg); 204170852Smarius break; 205170852Smarius 206152684Smarius case 'g': /* length of GAP3 to format with */ 20790618Stmm gaplen = atoi(optarg); 20890618Stmm break; 20990618Stmm 21090618Stmm case 'S': /* sector size shift factor (1 << S)*128 */ 211145186Smarius secsize = atoi(optarg); 212154870Smarius break; 213154870Smarius 214154870Smarius case 'F': /* fill byte, C-like notation allowed */ 21590618Stmm fill = (int)strtol(optarg, (char **)0, 0); 21690618Stmm break; 21790618Stmm 21890618Stmm case 't': /* steps per track */ 21990618Stmm steps = atoi(optarg); 22090618Stmm break; 22190618Stmm 22290618Stmm case 'i': /* interleave factor */ 22390618Stmm intleave = atoi(optarg); 224190112Smarius break; 225190112Smarius 226190112Smarius case 'q': 22790618Stmm quiet = 1; 228190114Smarius break; 229167308Smarius 23090618Stmm case 'n': 231133589Smarius verify = 0; 232152684Smarius break; 233152684Smarius 234152684Smarius case 'v': 235152684Smarius verify = 1; 236152684Smarius verify_only = 1; 237152684Smarius break; 238133589Smarius 239190112Smarius case '?': default: 24090618Stmm usage(); 24190618Stmm } 24290618Stmm 24390618Stmm if(optind != argc - 1) 24490618Stmm usage(); 24590618Stmm 24690618Stmm switch(format) { 24790618Stmm default: 24890618Stmm fprintf(stderr, "fdformat: bad floppy size: %dK\n", format); 24990618Stmm exit(2); 25090618Stmm case -1: suffix = ""; break; 251182062Smarius case 360: suffix = ".360"; break; 25290618Stmm case 720: suffix = ".720"; break; 25390618Stmm case 800: suffix = ".800"; break; 25490618Stmm case 820: suffix = ".820"; break; 25590618Stmm case 1200: suffix = ".1200"; break; 256172066Smarius case 1440: suffix = ".1440"; break; 257172066Smarius case 1480: suffix = ".1480"; break; 258172066Smarius case 1720: suffix = ".1720"; break; 259178443Smarius } 260178443Smarius 261172066Smarius devname = makename(argv[optind], suffix); 262172066Smarius 263172066Smarius if((fd = open(devname, O_RDWR)) < 0) { 264172066Smarius perror(devname); 265172066Smarius exit(1); 266172066Smarius } 267172066Smarius 268172066Smarius if(ioctl(fd, FD_GTYPE, &fdt) < 0) { 269190112Smarius fprintf(stderr, "fdformat: not a floppy disk: %s\n", devname); 270146391Smarius exit(1); 271146391Smarius } 272146391Smarius 273146391Smarius switch(rate) { 274146391Smarius case -1: break; 27590618Stmm case 250: fdt.trans = FDC_250KBPS; break; 276190112Smarius case 300: fdt.trans = FDC_300KBPS; break; 277146391Smarius case 500: fdt.trans = FDC_500KBPS; break; 278146391Smarius default: 279146391Smarius fprintf(stderr, "fdformat: invalid transfer rate: %d\n", rate); 280146391Smarius exit(2); 281146391Smarius } 282146391Smarius 283146391Smarius if (cyls >= 0) fdt.tracks = cyls; 284146391Smarius if (secs >= 0) fdt.sectrac = secs; 285146391Smarius if (fdt.sectrac > FD_MAX_NSEC) { 286146391Smarius fprintf(stderr, "fdformat: too many sectors per track, max value is %d\n", FD_MAX_NSEC); 287146391Smarius exit(2); 288146391Smarius } 289146391Smarius if (heads >= 0) fdt.heads = heads; 29090618Stmm if (gaplen >= 0) fdt.f_gap = gaplen; 29190618Stmm if (secsize >= 0) fdt.secsize = secsize; 292167308Smarius if (steps >= 0) fdt.steptrac = steps; 293145186Smarius if (intleave >= 0) fdt.f_inter = intleave; 294167308Smarius 295145186Smarius bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128; 296167308Smarius tracks_per_dot = fdt.tracks * fdt.heads / 40; 297145186Smarius 298145186Smarius if (verify_only) { 299145186Smarius if(!quiet) 300145186Smarius printf("Verify %dK floppy `%s'.\n", 301145186Smarius fdt.tracks * fdt.heads * bytes_per_track / 1024, 302145186Smarius devname); 303145186Smarius } 304145186Smarius else if(!quiet) { 305145185Smarius printf("Format %dK floppy `%s'? (y/n): ", 30690618Stmm fdt.tracks * fdt.heads * bytes_per_track / 1024, 307172066Smarius devname); 30890618Stmm if(! yes ()) { 30990618Stmm printf("Not confirmed.\n"); 310167308Smarius return 0; 31190618Stmm } 312172066Smarius } 31390618Stmm 314172066Smarius /* 315145185Smarius * Formatting. 316190112Smarius */ 317190112Smarius if(!quiet) { 31890618Stmm printf("Processing ----------------------------------------\r"); 319145185Smarius printf("Processing "); 320172066Smarius fflush(stdout); 321167308Smarius } 322145185Smarius 323190112Smarius error = errs = 0; 324190112Smarius 325167308Smarius for (track = 0; track < fdt.tracks * fdt.heads; track++) { 326167308Smarius if (!verify_only) { 327145185Smarius format_track(fd, track / fdt.heads, fdt.sectrac, 32890618Stmm track % fdt.heads, fdt.trans, fdt.f_gap, 329190112Smarius fdt.secsize, fill, fdt.f_inter); 330145185Smarius if(!quiet && !((track + 1) % tracks_per_dot)) { 331190112Smarius putchar('F'); 33290618Stmm fflush(stdout); 33390618Stmm } 33490618Stmm } 33590618Stmm if (verify) { 33690618Stmm if (verify_track(fd, track, bytes_per_track) < 0) 33790618Stmm error = errs = 1; 338190112Smarius if(!quiet && !((track + 1) % tracks_per_dot)) { 339190112Smarius if (!verify_only) 340190112Smarius putchar('\b'); 341190112Smarius if (error) { 342190112Smarius putchar('E'); 34390618Stmm error = 0; 34490618Stmm } 34590618Stmm else 34690618Stmm putchar('V'); 34790618Stmm fflush(stdout); 34890618Stmm } 349145185Smarius } 35090618Stmm } 35190618Stmm if(!quiet) 35290618Stmm printf(" done.\n"); 35390618Stmm 354145185Smarius return errs; 35590618Stmm} 35690618Stmm