Deleted the MACROS for BINDIR, BINOWN, BINMODE. They are already setup
[unix-history] / usr.sbin / fdformat / fdformat.c
CommitLineData
745cabe1 1/*
1bd4610c 2 * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden
745cabe1
AC
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
1bd4610c
JW
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
23 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
745cabe1
AC
25 */
26
27/*
28 * FreeBSD:
29 * format a floppy disk
30 *
31 * Added FD_GTYPE ioctl, verifying, proportional indicators.
32 * Serge Vakulenko, vak@zebub.msk.su
33 * Sat Dec 18 17:45:47 MSK 1993
34 *
35 * Final adaptation, change format/verify logic, add separate
36 * format gap/interleave values
37 * Andrew A. Chernov, ache@astral.msk.su
38 * Thu Jan 27 00:47:24 MSK 1994
39 */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <fcntl.h>
45#include <strings.h>
46#include <ctype.h>
47
48#include <errno.h>
49#include <machine/ioctl_fd.h>
50#include <../i386/isa/fdreg.h> /* XXX should be in <machine> dir */
51
52static void
53format_track(int fd, int cyl, int secs, int head, int rate,
7531a868 54 int gaplen, int secsize, int fill,int interleave)
745cabe1
AC
55{
56 struct fd_formb f;
7531a868 57 register int i,j;
ea3541cb 58 int il[FD_MAX_NSEC + 1];
7531a868
AC
59
60 memset(il,0,sizeof il);
61 for(j = 0, i = 1; i <= secs; i++) {
62 while(il[(j%secs)+1]) j++;
63 il[(j%secs)+1] = i;
64 j += interleave;
65 }
745cabe1
AC
66
67 f.format_version = FD_FORMAT_VERSION;
68 f.head = head;
69 f.cyl = cyl;
70 f.transfer_rate = rate;
71
72 f.fd_formb_secshift = secsize;
73 f.fd_formb_nsecs = secs;
74 f.fd_formb_gaplen = gaplen;
75 f.fd_formb_fillbyte = fill;
76 for(i = 0; i < secs; i++) {
77 f.fd_formb_cylno(i) = cyl;
78 f.fd_formb_headno(i) = head;
7531a868 79 f.fd_formb_secno(i) = il[i+1];
745cabe1
AC
80 f.fd_formb_secsize(i) = secsize;
81 }
82 if(ioctl(fd, FD_FORM, (caddr_t)&f) < 0) {
83 perror("\nfdformat: ioctl(FD_FORM)");
84 exit(1);
85 }
86}
87
88static int
89verify_track(int fd, int track, int tracksize)
90{
91 static char *buf = 0;
92 static int bufsz = 0;
1bd4610c
JW
93 int fdopts = -1, ofdopts, rv = 0;
94
95 if (ioctl(fd, FD_GOPTS, &fdopts) < 0)
96 perror("warning: ioctl(FD_GOPTS)");
97 else {
98 ofdopts = fdopts;
99 fdopts |= FDOPT_NORETRY;
100 (void)ioctl(fd, FD_SOPTS, &fdopts);
101 }
102
745cabe1
AC
103 if (bufsz < tracksize) {
104 if (buf)
105 free (buf);
106 bufsz = tracksize;
107 buf = 0;
108 }
109 if (! buf)
110 buf = malloc (bufsz);
111 if (! buf) {
112 fprintf (stderr, "\nfdformat: out of memory\n");
113 exit (2);
114 }
115 if (lseek (fd, (long) track*tracksize, 0) < 0)
1bd4610c
JW
116 rv = -1;
117 /* try twice reading it, without using the normal retrier */
118 else if (read (fd, buf, tracksize) != tracksize
119 && read (fd, buf, tracksize) != tracksize)
120 rv = -1;
121 if(fdopts != -1)
122 (void)ioctl(fd, FD_SOPTS, &ofdopts);
123 return (rv);
745cabe1
AC
124}
125
126static const char *
127makename(const char *arg, const char *suffix)
128{
129 static char namebuff[20]; /* big enough for "/dev/rfd0a"... */
130
131 memset(namebuff, 0, 20);
132 if(*arg == '\0') /* ??? */
133 return arg;
134 if(*arg == '/') /* do not convert absolute pathnames */
135 return arg;
136 strcpy(namebuff, "/dev/r");
137 strncat(namebuff, arg, 3);
138 strcat(namebuff, suffix);
139 return namebuff;
140}
141
142static void
1bd4610c 143usage (void)
745cabe1
AC
144{
145 printf("Usage:\n\tfdformat [-q] [-n | -v] [-f #] [-c #] [-s #] [-h #]\n");
146 printf("\t\t [-r #] [-g #] [-i #] [-S #] [-F #] [-t #] devname\n");
147 printf("Options:\n");
148 printf("\t-q\tsupress any normal output, don't ask for confirmation\n");
149 printf("\t-n\tdon't verify floppy after formatting\n");
150 printf("\t-v\tdon't format, verify only\n");
151 printf("\t-f #\tspecify desired floppy capacity, in kilobytes;\n");
152 printf("\t\tvalid choices are 360, 720, 800, 820, 1200, 1440, 1480, 1720\n");
153 printf("\tdevname\tthe full name of floppy device or in short form fd0, fd1\n");
154 printf("Obscure options:\n");
155 printf("\t-c #\tspecify number of cylinders, 40 or 80\n");
156 printf("\t-s #\tspecify number of sectors per track, 9, 10, 15 or 18\n");
157 printf("\t-h #\tspecify number of floppy heads, 1 or 2\n");
158 printf("\t-r #\tspecify data rate, 250, 300 or 500 kbps\n");
159 printf("\t-g #\tspecify gap length\n");
160 printf("\t-i #\tspecify interleave factor\n");
161 printf("\t-S #\tspecify sector size, 0=128, 1=256, 2=512 bytes\n");
162 printf("\t-F #\tspecify fill byte\n");
163 printf("\t-t #\tnumber of steps per track\n");
164 exit(2);
165}
166
167static int
1bd4610c 168yes (void)
745cabe1
AC
169{
170 char reply [256], *p;
171
172 reply[sizeof(reply)-1] = 0;
173 for (;;) {
174 fflush(stdout);
175 if (! fgets (reply, sizeof(reply)-1, stdin))
176 return (0);
177 for (p=reply; *p==' ' || *p=='\t'; ++p)
178 continue;
179 if (*p=='y' || *p=='Y')
180 return (1);
181 if (*p=='n' || *p=='N' || *p=='\n' || *p=='\r')
182 return (0);
183 printf("Answer `yes' or `no': ");
184 }
185}
186
187int
188main(int argc, char **argv)
189{
190 int format = -1, cyls = -1, secs = -1, heads = -1, intleave = -1;
191 int rate = -1, gaplen = -1, secsize = -1, steps = -1;
192 int fill = 0xf6, quiet = 0, verify = 1, verify_only = 0;
193 int fd, c, track, error, tracks_per_dot, bytes_per_track, errs;
194 const char *devname, *suffix;
195 struct fd_type fdt;
196
197 while((c = getopt(argc, argv, "f:c:s:h:r:g:S:F:t:i:qvn")) != -1)
198 switch(c) {
199 case 'f': /* format in kilobytes */
200 format = atoi(optarg);
201 break;
202
203 case 'c': /* # of cyls */
204 cyls = atoi(optarg);
205 break;
206
207 case 's': /* # of secs per track */
208 secs = atoi(optarg);
209 break;
210
211 case 'h': /* # of heads */
212 heads = atoi(optarg);
213 break;
214
215 case 'r': /* transfer rate, kilobyte/sec */
216 rate = atoi(optarg);
217 break;
218
219 case 'g': /* length of GAP3 to format with */
220 gaplen = atoi(optarg);
221 break;
222
223 case 'S': /* sector size shift factor (1 << S)*128 */
224 secsize = atoi(optarg);
225 break;
226
227 case 'F': /* fill byte, C-like notation allowed */
228 fill = (int)strtol(optarg, (char **)0, 0);
229 break;
230
231 case 't': /* steps per track */
232 steps = atoi(optarg);
233 break;
234
235 case 'i': /* interleave factor */
236 intleave = atoi(optarg);
237 break;
238
239 case 'q':
240 quiet = 1;
241 break;
242
243 case 'n':
244 verify = 0;
245 break;
246
247 case 'v':
248 verify = 1;
249 verify_only = 1;
250 break;
251
252 case '?': default:
253 usage();
254 }
255
256 if(optind != argc - 1)
257 usage();
258
259 switch(format) {
260 default:
261 fprintf(stderr, "fdformat: bad floppy size: %dK\n", format);
262 exit(2);
263 case -1: suffix = ""; break;
264 case 360: suffix = ".360"; break;
265 case 720: suffix = ".720"; break;
266 case 800: suffix = ".800"; break;
267 case 820: suffix = ".820"; break;
268 case 1200: suffix = ".1200"; break;
269 case 1440: suffix = ".1440"; break;
270 case 1480: suffix = ".1480"; break;
271 case 1720: suffix = ".1720"; break;
272 }
273
274 devname = makename(argv[optind], suffix);
275
276 if((fd = open(devname, O_RDWR)) < 0) {
277 perror(devname);
278 exit(1);
279 }
280
281 if(ioctl(fd, FD_GTYPE, &fdt) < 0) {
282 fprintf(stderr, "fdformat: not a floppy disk: %s\n", devname);
283 exit(1);
284 }
285
286 switch(rate) {
287 case -1: break;
288 case 250: fdt.trans = FDC_250KBPS; break;
289 case 300: fdt.trans = FDC_300KBPS; break;
290 case 500: fdt.trans = FDC_500KBPS; break;
291 default:
292 fprintf(stderr, "fdformat: invalid transfer rate: %d\n", rate);
293 exit(2);
294 }
295
296 if (cyls >= 0) fdt.tracks = cyls;
297 if (secs >= 0) fdt.sectrac = secs;
7531a868
AC
298 if (fdt.sectrac > FD_MAX_NSEC) {
299 fprintf(stderr, "fdformat: too many sectors per track, max value is %d\n", FD_MAX_NSEC);
300 exit(2);
301 }
745cabe1
AC
302 if (heads >= 0) fdt.heads = heads;
303 if (gaplen >= 0) fdt.f_gap = gaplen;
304 if (secsize >= 0) fdt.secsize = secsize;
305 if (steps >= 0) fdt.steptrac = steps;
306 if (intleave >= 0) fdt.f_inter = intleave;
745cabe1
AC
307
308 bytes_per_track = fdt.sectrac * (1<<fdt.secsize) * 128;
309 tracks_per_dot = fdt.tracks * fdt.heads / 40;
310
311 if (verify_only) {
312 if(!quiet)
313 printf("Verify %dK floppy `%s'.\n",
314 fdt.tracks * fdt.heads * bytes_per_track / 1024,
315 devname);
316 }
317 else if(!quiet) {
318 printf("Format %dK floppy `%s'? (y/n): ",
319 fdt.tracks * fdt.heads * bytes_per_track / 1024,
320 devname);
321 if(! yes ()) {
322 printf("Not confirmed.\n");
323 return 0;
324 }
325 }
326
327 /*
328 * Formatting.
329 */
330 if(!quiet) {
331 printf("Processing ----------------------------------------\r");
332 printf("Processing ");
333 fflush(stdout);
334 }
335
336 error = errs = 0;
337
338 for (track = 0; track < fdt.tracks * fdt.heads; track++) {
339 if (!verify_only) {
6cdf8df9
RG
340 format_track(fd, track / fdt.heads, fdt.sectrac,
341 track % fdt.heads, fdt.trans, fdt.f_gap,
342 fdt.secsize, fill, fdt.f_inter);
745cabe1
AC
343 if(!quiet && !((track + 1) % tracks_per_dot)) {
344 putchar('F');
345 fflush(stdout);
346 }
347 }
348 if (verify) {
349 if (verify_track(fd, track, bytes_per_track) < 0)
350 error = errs = 1;
351 if(!quiet && !((track + 1) % tracks_per_dot)) {
352 if (!verify_only)
353 putchar('\b');
354 if (error) {
355 putchar('E');
356 error = 0;
357 }
358 else
359 putchar('V');
360 fflush(stdout);
361 }
362 }
363 }
364 if(!quiet)
365 printf(" done.\n");
366
367 return errs;
368}
1bd4610c
JW
369/*
370 * Local Variables:
371 * c-indent-level: 8
372 * c-continued-statement-offset: 8
373 * c-continued-brace-offset: 0
374 * c-brace-offset: -8
375 * c-brace-imaginary-offset: 0
376 * c-argdecl-indent: 8
377 * c-label-offset: -8
378 * c++-hanging-braces: 1
379 * c++-access-specifier-offset: -8
380 * c++-empty-arglist-indent: 8
381 * c++-friend-offset: 0
382 * End:
383 */