fdformat.c revision 61154
139665Smsmith/*
239665Smsmith * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden
339665Smsmith * All rights reserved.
439665Smsmith *
539665Smsmith * Redistribution and use in source and binary forms, with or without
639665Smsmith * modification, are permitted provided that the following conditions
739665Smsmith * are met:
839665Smsmith * 1. Redistributions of source code must retain the above copyright
939665Smsmith *    notice, this list of conditions and the following disclaimer.
1039665Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1139665Smsmith *    notice, this list of conditions and the following disclaimer in the
1239665Smsmith *    documentation and/or other materials provided with the distribution.
1339665Smsmith *
1439665Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
1539665Smsmith * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1639665Smsmith * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1739665Smsmith * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
1839665Smsmith * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1939665Smsmith * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2039665Smsmith * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2139665Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2239665Smsmith * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2339665Smsmith * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2439665Smsmith * POSSIBILITY OF SUCH DAMAGE.
2539665Smsmith *
2639665Smsmith * $FreeBSD: head/usr.sbin/fdformat/fdformat.c 61154 2000-06-01 22:27:30Z phk $
2739665Smsmith */
2839665Smsmith
2939665Smsmith/*
3084221Sdillon * FreeBSD:
3184221Sdillon * format a floppy disk
3284221Sdillon *
3339665Smsmith * Added FD_GTYPE ioctl, verifying, proportional indicators.
3439665Smsmith * Serge Vakulenko, vak@zebub.msk.su
3539665Smsmith * Sat Dec 18 17:45:47 MSK 1993
3639665Smsmith *
3739665Smsmith * Final adaptation, change format/verify logic, add separate
3839665Smsmith * format gap/interleave values
3939665Smsmith * Andrew A. Chernov, ache@astral.msk.su
4039665Smsmith * Thu Jan 27 00:47:24 MSK 1994
4139665Smsmith */
4239665Smsmith
4339665Smsmith#include <ctype.h>
4439665Smsmith#include <err.h>
4539665Smsmith#include <fcntl.h>
4639665Smsmith#include <stdio.h>
4739665Smsmith#include <stdlib.h>
4839665Smsmith#include <strings.h>
4939665Smsmith#include <unistd.h>
5039665Smsmith
5139665Smsmith#include <machine/ioctl_fd.h>
5239665Smsmith
5339665Smsmithstatic void
5439665Smsmithformat_track(int fd, int cyl, int secs, int head, int rate,
5539665Smsmith	     int gaplen, int secsize, int fill,int interleave)
5639665Smsmith{
5739665Smsmith	struct fd_formb f;
5839665Smsmith	register int i,j;
5939665Smsmith	int il[FD_MAX_NSEC + 1];
6039665Smsmith
6139665Smsmith	memset(il,0,sizeof il);
6239665Smsmith	for(j = 0, i = 1; i <= secs; i++) {
6339665Smsmith	    while(il[(j%secs)+1]) j++;
6439665Smsmith	    il[(j%secs)+1] = i;
6539665Smsmith	    j += interleave;
6639665Smsmith	}
6739665Smsmith
6839665Smsmith	f.format_version = FD_FORMAT_VERSION;
6939665Smsmith	f.head = head;
7039665Smsmith	f.cyl = cyl;
7139665Smsmith	f.transfer_rate = rate;
7239665Smsmith
7339665Smsmith	f.fd_formb_secshift = secsize;
7439665Smsmith	f.fd_formb_nsecs = secs;
7539665Smsmith	f.fd_formb_gaplen = gaplen;
7639665Smsmith	f.fd_formb_fillbyte = fill;
7739665Smsmith	for(i = 0; i < secs; i++) {
7839665Smsmith		f.fd_formb_cylno(i) = cyl;
7939665Smsmith		f.fd_formb_headno(i) = head;
8039665Smsmith		f.fd_formb_secno(i) = il[i+1];
8139665Smsmith		f.fd_formb_secsize(i) = secsize;
8239665Smsmith	}
8339665Smsmith	if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0)
8439665Smsmith		err(1, "ioctl(FD_FORM)");
8539665Smsmith}
8639665Smsmith
8739665Smsmithstatic int
8839665Smsmithverify_track(int fd, int track, int tracksize)
8939665Smsmith{
9039665Smsmith	static char *buf = 0;
9139665Smsmith	static int bufsz = 0;
9239665Smsmith	int fdopts = -1, ofdopts, rv = 0;
9339863Smsmith
9439863Smsmith	if (ioctl(fd, FD_GOPTS, &fdopts) < 0)
9539665Smsmith		warn("warning: ioctl(FD_GOPTS)");
9639665Smsmith	else {
9739665Smsmith		ofdopts = fdopts;
9839665Smsmith		fdopts |= FDOPT_NORETRY;
9939665Smsmith		(void)ioctl(fd, FD_SOPTS, &fdopts);
10039665Smsmith	}
10139863Smsmith
10239863Smsmith	if (bufsz < tracksize) {
10339863Smsmith		if (buf)
10439665Smsmith			free (buf);
10539665Smsmith		bufsz = tracksize;
10639863Smsmith		buf = 0;
10739863Smsmith	}
10839665Smsmith	if (! buf)
10939665Smsmith		buf = malloc (bufsz);
11039665Smsmith	if (! buf)
11139665Smsmith		errx(2, "out of memory");
11239863Smsmith	if (lseek (fd, (long) track*tracksize, 0) < 0)
11339665Smsmith		rv = -1;
11439665Smsmith	/* try twice reading it, without using the normal retrier */
11539665Smsmith	else if (read (fd, buf, tracksize) != tracksize
11639665Smsmith		 && read (fd, buf, tracksize) != tracksize)
11739665Smsmith		rv = -1;
11839665Smsmith	if(fdopts != -1)
11939665Smsmith		(void)ioctl(fd, FD_SOPTS, &ofdopts);
12039665Smsmith	return (rv);
12139665Smsmith}
12239665Smsmith
12339665Smsmithstatic const char *
12439665Smsmithmakename(const char *arg, const char *suffix)
12539665Smsmith{
12639863Smsmith	static char namebuff[20];	/* big enough for "/dev/fd0a"... */
12739863Smsmith
12839863Smsmith	memset(namebuff, 0, 20);
12939863Smsmith	if(*arg == '\0') /* ??? */
13039863Smsmith		return arg;
13139665Smsmith	if(*arg == '/')  /* do not convert absolute pathnames */
13239665Smsmith		return arg;
13339665Smsmith	strcpy(namebuff, "/dev/");
13439665Smsmith	strncat(namebuff, arg, 3);
13539665Smsmith	strcat(namebuff, suffix);
13639665Smsmith	return namebuff;
13739665Smsmith}
13839665Smsmith
13939665Smsmithstatic void
14039665Smsmithusage (void)
14139665Smsmith{
14239665Smsmith	fprintf(stderr, "%s\n%s\n",
14339665Smsmith	"usage: fdformat [-y] [-q] [-n | -v] [-f #] [-c #] [-s #] [-h #]",
14439665Smsmith	"                [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] devname");
14539665Smsmith	exit(2);
14639665Smsmith}
14739665Smsmith
14839665Smsmithstatic int
14939665Smsmithyes (void)
15039665Smsmith{
15139665Smsmith	char reply [256], *p;
15239665Smsmith
15339665Smsmith	reply[sizeof(reply)-1] = 0;
15439665Smsmith	for (;;) {
15539665Smsmith		fflush(stdout);
15639863Smsmith		if (! fgets (reply, sizeof(reply)-1, stdin))
157223854Savatar			return (0);
15839665Smsmith		for (p=reply; *p==' ' || *p=='\t'; ++p)
15939665Smsmith			continue;
16039665Smsmith		if (*p=='y' || *p=='Y')
16139665Smsmith			return (1);
16239665Smsmith		if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r')
16339665Smsmith			return (0);
16439665Smsmith		printf("Answer `yes' or `no': ");
16539665Smsmith	}
16639665Smsmith}
16739665Smsmith
16839665Smsmithint
16939665Smsmithmain(int argc, char **argv)
17039665Smsmith{
17139665Smsmith	int format = -1, cyls = -1, secs = -1, heads = -1, intleave = -1;
17239665Smsmith	int rate = -1, gaplen = -1, secsize = -1, steps = -1;
17339665Smsmith	int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0, confirm = 0;
17439665Smsmith	int fd, c, track, error, tracks_per_dot, bytes_per_track, errs;
17539665Smsmith	const char *devname, *suffix;
17639665Smsmith	struct fd_type fdt;
17739665Smsmith
17839665Smsmith	while((c = getopt(argc, argv, "f:c:s:h:r:g:S:F:t:i:qyvn")) != -1)
17939665Smsmith		switch(c) {
180223854Savatar		case 'f':	/* format in kilobytes */
181223854Savatar			format = atoi(optarg);
182223854Savatar			break;
183223854Savatar
18439665Smsmith		case 'c':	/* # of cyls */
18539665Smsmith			cyls = atoi(optarg);
18639665Smsmith			break;
18739665Smsmith
18839665Smsmith		case 's':	/* # of secs per track */
18939665Smsmith			secs = atoi(optarg);
19039665Smsmith			break;
19139665Smsmith
19239665Smsmith		case 'h':	/* # of heads */
19339665Smsmith			heads = atoi(optarg);
19439665Smsmith			break;
19539665Smsmith
19639665Smsmith		case 'r':	/* transfer rate, kilobyte/sec */
19739665Smsmith			rate = atoi(optarg);
19839665Smsmith			break;
19939665Smsmith
20039665Smsmith		case 'g':	/* length of GAP3 to format with */
20139665Smsmith			gaplen = atoi(optarg);
20239665Smsmith			break;
20339665Smsmith
20439665Smsmith		case 'S':	/* sector size shift factor (1 << S)*128 */
20539665Smsmith			secsize = atoi(optarg);
20639665Smsmith			break;
20739665Smsmith
20839665Smsmith		case 'F':	/* fill byte, C-like notation allowed */
20939665Smsmith			fill = (int)strtol(optarg, (char **)0, 0);
21039665Smsmith			break;
21139665Smsmith
21239665Smsmith		case 't':	/* steps per track */
213223854Savatar			steps = atoi(optarg);
214223854Savatar			break;
215223854Savatar
216223854Savatar		case 'i':       /* interleave factor */
21739665Smsmith			intleave = atoi(optarg);
21839665Smsmith			break;
21939665Smsmith
22039665Smsmith		case 'q':
22139665Smsmith			quiet = 1;
22239665Smsmith			break;
22339665Smsmith
22439665Smsmith		case 'y':
22539665Smsmith			confirm = 1;
22639665Smsmith			break;
22739665Smsmith
22839665Smsmith		case 'n':
22939665Smsmith			verify = 0;
23039665Smsmith			break;
23139665Smsmith
23239665Smsmith		case 'v':
23339665Smsmith			verify = 1;
23439665Smsmith			verify_only = 1;
23539665Smsmith			break;
23639665Smsmith
23739665Smsmith		case '?': default:
23839665Smsmith			usage();
23939665Smsmith		}
24039665Smsmith
24139665Smsmith	if(optind != argc - 1)
24239665Smsmith		usage();
24339665Smsmith
24439665Smsmith	switch(format) {
24539665Smsmith	default:
24639665Smsmith		errx(2, "bad floppy size: %dK", format);
24739665Smsmith	case -1:   suffix = "";      break;
24839665Smsmith	case 360:  suffix = ".360";  break;
24939665Smsmith	case 640:  suffix = ".640";  break;
25039665Smsmith	case 720:  suffix = ".720";  break;
25139665Smsmith	case 800:  suffix = ".800";  break;
25239665Smsmith	case 820:  suffix = ".820";  break;
25339666Sdillon	case 1200: suffix = ".1200"; break;
254108108Sdillon	case 1232: suffix = ".1232"; break;
25539665Smsmith	case 1440: suffix = ".1440"; break;
25639665Smsmith	case 1480: suffix = ".1480"; break;
25739665Smsmith	case 1720: suffix = ".1720"; break;
25839665Smsmith	}
259108108Sdillon
26039665Smsmith	devname = makename(argv[optind], suffix);
26139665Smsmith
26239665Smsmith	if((fd = open(devname, O_RDWR)) < 0)
26339665Smsmith		err(1, "%s", devname);
26439665Smsmith
265108108Sdillon	if(ioctl(fd, FD_GTYPE, &fdt) < 0)
26639665Smsmith		errx(1, "not a floppy disk: %s", devname);
26739666Sdillon
26839665Smsmith	switch(rate) {
26939665Smsmith	case -1:  break;
27039665Smsmith	case 250: fdt.trans = FDC_250KBPS; break;
27139665Smsmith	case 300: fdt.trans = FDC_300KBPS; break;
27239665Smsmith	case 500: fdt.trans = FDC_500KBPS; break;
27339665Smsmith	default:
27439665Smsmith		errx(2, "invalid transfer rate: %d", rate);
27539665Smsmith	}
27639665Smsmith
27739665Smsmith	if (cyls >= 0)    fdt.tracks = cyls;
27839665Smsmith	if (secs >= 0)    fdt.sectrac = secs;
27939665Smsmith	if (fdt.sectrac > FD_MAX_NSEC)
28039665Smsmith		errx(2, "too many sectors per track, max value is %d", FD_MAX_NSEC);
28139665Smsmith	if (heads >= 0)   fdt.heads = heads;
28239863Smsmith	if (gaplen >= 0)  fdt.f_gap = gaplen;
28339665Smsmith	if (secsize >= 0) fdt.secsize = secsize;
28439665Smsmith	if (steps >= 0)   fdt.steptrac = steps;
28539665Smsmith	if (intleave >= 0) fdt.f_inter = intleave;
28639665Smsmith
28739665Smsmith	bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128;
28839665Smsmith
28939665Smsmith	/* XXX  20/40 = 0.5 */
29039665Smsmith	tracks_per_dot = (fdt.tracks * fdt.heads + 20) / 40;
29139665Smsmith
29239665Smsmith	if (verify_only) {
29339665Smsmith		if(!quiet)
29439665Smsmith			printf("Verify %dK floppy `%s'.\n",
29539665Smsmith				fdt.tracks * fdt.heads * bytes_per_track / 1024,
29639665Smsmith				devname);
29739665Smsmith	}
29839665Smsmith	else if(!quiet && !confirm) {
29939665Smsmith		printf("Format %dK floppy `%s'? (y/n): ",
30039665Smsmith			fdt.tracks * fdt.heads * bytes_per_track / 1024,
30139665Smsmith			devname);
30239665Smsmith		if(! yes ()) {
30339665Smsmith			printf("Not confirmed.\n");
30439665Smsmith			return 0;
30539665Smsmith		}
30639665Smsmith	}
30739665Smsmith
308	/*
309	 * Formatting.
310	 */
311	if(!quiet) {
312		int i;
313
314		printf("Processing ");
315		for (i = 0; i < (fdt.tracks * fdt.heads) / tracks_per_dot; i++)
316			putchar('-');
317		printf("\rProcessing ");
318		fflush(stdout);
319	}
320
321	error = errs = 0;
322
323	for (track = 0; track < fdt.tracks * fdt.heads; track++) {
324		if (!verify_only) {
325			format_track(fd, track / fdt.heads, fdt.sectrac,
326				track % fdt.heads, fdt.trans, fdt.f_gap,
327				fdt.secsize, fill, fdt.f_inter);
328			if(!quiet && !((track + 1) % tracks_per_dot)) {
329				putchar('F');
330				fflush(stdout);
331			}
332		}
333		if (verify) {
334			if (verify_track(fd, track, bytes_per_track) < 0)
335				error = errs = 1;
336			if(!quiet && !((track + 1) % tracks_per_dot)) {
337				if (!verify_only)
338					putchar('\b');
339				if (error) {
340					putchar('E');
341					error = 0;
342				}
343				else
344					putchar('V');
345				fflush(stdout);
346			}
347		}
348	}
349	if(!quiet)
350		printf(" done.\n");
351
352	return errs;
353}
354/*
355 * Local Variables:
356 *  c-indent-level:               8
357 *  c-continued-statement-offset: 8
358 *  c-continued-brace-offset:     0
359 *  c-brace-offset:              -8
360 *  c-brace-imaginary-offset:     0
361 *  c-argdecl-indent:             8
362 *  c-label-offset:              -8
363 *  c++-hanging-braces:           1
364 *  c++-access-specifier-offset: -8
365 *  c++-empty-arglist-indent:     8
366 *  c++-friend-offset:            0
367 * End:
368 */
369