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