1433d6423SLionel Sambuc /* format 1.1 - format PC floppy disk Author: Kees J. Bot
2433d6423SLionel Sambuc * 5 Mar 1994
3433d6423SLionel Sambuc */
4433d6423SLionel Sambuc #define nil 0
5433d6423SLionel Sambuc #include <sys/types.h>
6433d6423SLionel Sambuc #include <sys/stat.h>
7433d6423SLionel Sambuc #include <stdio.h>
8433d6423SLionel Sambuc #include <unistd.h>
9433d6423SLionel Sambuc #include <stdlib.h>
10433d6423SLionel Sambuc #include <fcntl.h>
11433d6423SLionel Sambuc #include <string.h>
12433d6423SLionel Sambuc #include <time.h>
13433d6423SLionel Sambuc #include <errno.h>
14433d6423SLionel Sambuc #include <limits.h>
15433d6423SLionel Sambuc #include <machine/diskparm.h>
16433d6423SLionel Sambuc #include <minix/minlib.h>
17433d6423SLionel Sambuc
18433d6423SLionel Sambuc /* Constants. */
19433d6423SLionel Sambuc #define SECTOR_SIZE 512
20433d6423SLionel Sambuc #define NR_HEADS 2
21433d6423SLionel Sambuc #define MAX_SECTORS 18 /* 1.44Mb is the largest. */
22433d6423SLionel Sambuc
23433d6423SLionel Sambuc /* Name error in <ibm/diskparm.h>, left over from the days floppies were
24433d6423SLionel Sambuc * single sided.
25433d6423SLionel Sambuc */
26433d6423SLionel Sambuc #define sectors_per_track sectors_per_cylinder
27433d6423SLionel Sambuc
28433d6423SLionel Sambuc /* From floppy device number to drive/type/format-bit and back. See fd(4). */
29433d6423SLionel Sambuc #define isfloppy(dev) (((dev) & 0xFF00) == 0x0200)
30433d6423SLionel Sambuc #define fl_drive(dev) (((dev) & 0x0003) >> 0)
31433d6423SLionel Sambuc #define fl_type(dev) (((dev) & 0x007C) >> 2)
32433d6423SLionel Sambuc #define fl_format(dev) (((dev) & 0x0080) >> 7)
33433d6423SLionel Sambuc #define fl_makedev(drive, type, fmt) \
34433d6423SLionel Sambuc ((dev_t) (0x0200 | ((fmt) << 7) | ((type) << 2) | ((drive) << 0)))
35433d6423SLionel Sambuc
36433d6423SLionel Sambuc /* Recognize floppy types. */
37433d6423SLionel Sambuc #define NR_TYPES 7 /* # non-auto types */
38433d6423SLionel Sambuc #define isflauto(type) ((type) == 0)
39433d6423SLionel Sambuc #define isfltyped(type) ((unsigned) ((type) - 1) < NR_TYPES)
40433d6423SLionel Sambuc #define isflpart(type) ((unsigned) (type) >= 28)
41433d6423SLionel Sambuc
42433d6423SLionel Sambuc /* Formatting parameters per type. (Most of these parameters have no use
43433d6423SLionel Sambuc * for formatting, disk_parameter_s probably matches a BIOS parameter table.)
44433d6423SLionel Sambuc */
45433d6423SLionel Sambuc typedef struct disk_parameter_s fmt_params_t;
46433d6423SLionel Sambuc
47433d6423SLionel Sambuc typedef struct type_parameters {
48433d6423SLionel Sambuc unsigned media_size;
49433d6423SLionel Sambuc unsigned drive_size;
50433d6423SLionel Sambuc fmt_params_t fmt_params;
51433d6423SLionel Sambuc } type_parameters_t;
52433d6423SLionel Sambuc
53433d6423SLionel Sambuc #define DC 0 /* Don't care. */
54433d6423SLionel Sambuc
55433d6423SLionel Sambuc type_parameters_t parameters[NR_TYPES] = {
56433d6423SLionel Sambuc /* mediasize s1 off sec/cyl dlen fill start */
57433d6423SLionel Sambuc /* drivesize s2 sizecode gap fmtgap settle */
58433d6423SLionel Sambuc /* pc */ { 360, 360, { DC, DC, DC, 2, 9, DC, DC, 0x50, 0xF6, DC, DC }},
59433d6423SLionel Sambuc /* at */ { 1200, 1200, { DC, DC, DC, 2, 15, DC, DC, 0x54, 0xF6, DC, DC }},
60433d6423SLionel Sambuc /* qd */ { 360, 720, { DC, DC, DC, 2, 9, DC, DC, 0x50, 0xF6, DC, DC }},
61433d6423SLionel Sambuc /* ps */ { 720, 720, { DC, DC, DC, 2, 9, DC, DC, 0x50, 0xF6, DC, DC }},
62433d6423SLionel Sambuc /* pat */{ 360, 1200, { DC, DC, DC, 2, 9, DC, DC, 0x50, 0xF6, DC, DC }},
63433d6423SLionel Sambuc /* qh */ { 720, 1200, { DC, DC, DC, 2, 9, DC, DC, 0x50, 0xF6, DC, DC }},
64433d6423SLionel Sambuc /* PS */ { 1440, 1440, { DC, DC, DC, 2, 18, DC, DC, 0x54, 0xF6, DC, DC }},
65433d6423SLionel Sambuc };
66433d6423SLionel Sambuc
67433d6423SLionel Sambuc /* Per sector ID to be sent to the controller by the driver. */
68433d6423SLionel Sambuc typedef struct sector_id {
69433d6423SLionel Sambuc unsigned char cyl;
70433d6423SLionel Sambuc unsigned char head;
71433d6423SLionel Sambuc unsigned char sector;
72433d6423SLionel Sambuc unsigned char sector_size_code;
73433d6423SLionel Sambuc } sector_id_t;
74433d6423SLionel Sambuc
75433d6423SLionel Sambuc /* Data to be "written" to the driver to format a track. (lseek to the track
76433d6423SLionel Sambuc * first.) The first sector contains sector ID's, the second format params.
77433d6423SLionel Sambuc */
78433d6423SLionel Sambuc
79433d6423SLionel Sambuc typedef struct track_data {
80433d6423SLionel Sambuc sector_id_t sec_ids[SECTOR_SIZE / sizeof(sector_id_t)];
81433d6423SLionel Sambuc fmt_params_t fmt_params;
82433d6423SLionel Sambuc char padding[SECTOR_SIZE - sizeof(fmt_params_t)];
83433d6423SLionel Sambuc } track_data_t;
84433d6423SLionel Sambuc
report(const char * label)85433d6423SLionel Sambuc void report(const char *label)
86433d6423SLionel Sambuc {
87433d6423SLionel Sambuc fprintf(stderr, "format: %s: %s\n", label, strerror(errno));
88433d6423SLionel Sambuc }
89433d6423SLionel Sambuc
fatal(const char * label)90433d6423SLionel Sambuc void fatal(const char *label)
91433d6423SLionel Sambuc {
92433d6423SLionel Sambuc report(label);
93433d6423SLionel Sambuc exit(1);
94433d6423SLionel Sambuc }
95433d6423SLionel Sambuc
format_track(int ffd,unsigned type,unsigned cyl,unsigned head)96433d6423SLionel Sambuc void format_track(int ffd, unsigned type, unsigned cyl, unsigned head)
97433d6423SLionel Sambuc /* Format a single track on a floppy. */
98433d6423SLionel Sambuc {
99433d6423SLionel Sambuc type_parameters_t *tparams= ¶meters[type - 1];
100433d6423SLionel Sambuc track_data_t track_data;
101433d6423SLionel Sambuc off_t track_pos;
102433d6423SLionel Sambuc unsigned sector;
103433d6423SLionel Sambuc unsigned nr_sectors= tparams->fmt_params.sectors_per_track;
104433d6423SLionel Sambuc sector_id_t *sid;
105433d6423SLionel Sambuc
106433d6423SLionel Sambuc memset(&track_data, 0, sizeof(track_data));
107433d6423SLionel Sambuc
108433d6423SLionel Sambuc /* Set the sector id's. (Note that sectors count from 1.) */
109433d6423SLionel Sambuc for (sector= 0; sector <= nr_sectors; sector++) {
110433d6423SLionel Sambuc sid= &track_data.sec_ids[sector];
111433d6423SLionel Sambuc
112433d6423SLionel Sambuc sid->cyl= cyl;
113433d6423SLionel Sambuc sid->head= head;
114433d6423SLionel Sambuc sid->sector= sector + 1;
115433d6423SLionel Sambuc sid->sector_size_code= tparams->fmt_params.sector_size_code;
116433d6423SLionel Sambuc }
117433d6423SLionel Sambuc
118433d6423SLionel Sambuc /* Format parameters. */
119433d6423SLionel Sambuc track_data.fmt_params= tparams->fmt_params;
120433d6423SLionel Sambuc
121433d6423SLionel Sambuc /* Seek to the right track. */
122433d6423SLionel Sambuc track_pos= (off_t) (cyl * NR_HEADS + head) * nr_sectors * SECTOR_SIZE;
123433d6423SLionel Sambuc if (lseek(ffd, track_pos, SEEK_SET) == -1) {
124433d6423SLionel Sambuc fprintf(stderr,
125*d0055759SDavid van Moolenbroek "format: seeking to cyl %u, head %u (pos %lld) failed: %s\n",
126433d6423SLionel Sambuc cyl, head, track_pos, strerror(errno));
127433d6423SLionel Sambuc exit(1);
128433d6423SLionel Sambuc }
129433d6423SLionel Sambuc
130433d6423SLionel Sambuc /* Format track. */
131433d6423SLionel Sambuc if (write(ffd, &track_data, sizeof(track_data)) < 0) {
132433d6423SLionel Sambuc fprintf(stderr,
133433d6423SLionel Sambuc "format: formatting cyl %d, head %d failed: %s\n",
134433d6423SLionel Sambuc cyl, head, strerror(errno));
135433d6423SLionel Sambuc exit(1);
136433d6423SLionel Sambuc }
137433d6423SLionel Sambuc
138433d6423SLionel Sambuc /* Make sure the data is not just cached in a file system. */
139433d6423SLionel Sambuc fsync(ffd);
140433d6423SLionel Sambuc }
141433d6423SLionel Sambuc
verify_track(int vfd,unsigned type,unsigned cyl,unsigned head)142433d6423SLionel Sambuc void verify_track(int vfd, unsigned type, unsigned cyl, unsigned head)
143433d6423SLionel Sambuc /* Verify a track by reading it. On error read sector by sector. */
144433d6423SLionel Sambuc {
145433d6423SLionel Sambuc type_parameters_t *tparams= ¶meters[type - 1];
146433d6423SLionel Sambuc off_t track_pos;
147433d6423SLionel Sambuc unsigned sector;
148433d6423SLionel Sambuc unsigned nr_sectors= tparams->fmt_params.sectors_per_track;
149433d6423SLionel Sambuc size_t track_bytes;
150433d6423SLionel Sambuc static char buf[MAX_SECTORS * SECTOR_SIZE];
151433d6423SLionel Sambuc static unsigned bad_count;
152433d6423SLionel Sambuc
153433d6423SLionel Sambuc /* Seek to the right track. */
154433d6423SLionel Sambuc track_pos= (off_t) (cyl * NR_HEADS + head) * nr_sectors * SECTOR_SIZE;
155433d6423SLionel Sambuc if (lseek(vfd, track_pos, SEEK_SET) == -1) {
156433d6423SLionel Sambuc fprintf(stderr,
157*d0055759SDavid van Moolenbroek "format: seeking to cyl %u, head %u (pos %lld) failed: %s\n",
158433d6423SLionel Sambuc cyl, head, track_pos, strerror(errno));
159433d6423SLionel Sambuc exit(1);
160433d6423SLionel Sambuc }
161433d6423SLionel Sambuc
162433d6423SLionel Sambuc /* Read the track whole. */
163433d6423SLionel Sambuc track_bytes= nr_sectors * SECTOR_SIZE;
164433d6423SLionel Sambuc if (read(vfd, buf, track_bytes) == track_bytes) return;
165433d6423SLionel Sambuc
166433d6423SLionel Sambuc /* An error occurred, retry sector by sector. */
167433d6423SLionel Sambuc for (sector= 0; sector < nr_sectors; sector++) {
168433d6423SLionel Sambuc if (lseek(vfd, track_pos, SEEK_SET) == -1) {
169433d6423SLionel Sambuc fprintf(stderr,
170*d0055759SDavid van Moolenbroek "format: seeking to cyl %u, head %u, sector %u (pos %lld) failed: %s\n",
171433d6423SLionel Sambuc cyl, head, sector, track_pos, strerror(errno));
172433d6423SLionel Sambuc exit(1);
173433d6423SLionel Sambuc }
174433d6423SLionel Sambuc
175433d6423SLionel Sambuc switch (read(vfd, buf, SECTOR_SIZE)) {
176433d6423SLionel Sambuc case -1:
177433d6423SLionel Sambuc fprintf(stderr,
178*d0055759SDavid van Moolenbroek "format: bad sector at cyl %u, head %u, sector %u (pos %lld)\n",
179433d6423SLionel Sambuc cyl, head, sector, track_pos);
180433d6423SLionel Sambuc bad_count++;
181433d6423SLionel Sambuc break;
182433d6423SLionel Sambuc case SECTOR_SIZE:
183433d6423SLionel Sambuc /* Fine. */
184433d6423SLionel Sambuc break;
185433d6423SLionel Sambuc default:
186*d0055759SDavid van Moolenbroek fprintf(stderr, "format: short read at pos %lld\n",
187433d6423SLionel Sambuc track_pos);
188433d6423SLionel Sambuc bad_count++;
189433d6423SLionel Sambuc }
190433d6423SLionel Sambuc track_pos+= SECTOR_SIZE;
191433d6423SLionel Sambuc if (bad_count >= nr_sectors) {
192433d6423SLionel Sambuc fprintf(stderr, "format: too many bad sectors, floppy unusable\n");
193433d6423SLionel Sambuc exit(1);
194433d6423SLionel Sambuc }
195433d6423SLionel Sambuc }
196433d6423SLionel Sambuc }
197433d6423SLionel Sambuc
format_device(unsigned drive,unsigned type,int verify)198433d6423SLionel Sambuc void format_device(unsigned drive, unsigned type, int verify)
199433d6423SLionel Sambuc {
200433d6423SLionel Sambuc int ffd, vfd;
201433d6423SLionel Sambuc char *fmt_dev, *ver_dev;
202433d6423SLionel Sambuc struct stat st;
203433d6423SLionel Sambuc unsigned cyl, head;
204433d6423SLionel Sambuc unsigned nr_cyls;
205433d6423SLionel Sambuc type_parameters_t *tparams= ¶meters[type - 1];
206433d6423SLionel Sambuc int verbose= isatty(1);
207433d6423SLionel Sambuc
208433d6423SLionel Sambuc fmt_dev= tmpnam(nil);
209433d6423SLionel Sambuc
210433d6423SLionel Sambuc if (mknod(fmt_dev, S_IFBLK | 0700, fl_makedev(drive, type, 1)) < 0) {
211433d6423SLionel Sambuc fprintf(stderr, "format: making format device failed: %s\n",
212433d6423SLionel Sambuc strerror(errno));
213433d6423SLionel Sambuc exit(1);
214433d6423SLionel Sambuc }
215433d6423SLionel Sambuc
216433d6423SLionel Sambuc if ((ffd= open(fmt_dev, O_WRONLY)) < 0 || fstat(ffd, &st) < 0) {
217433d6423SLionel Sambuc report(fmt_dev);
218433d6423SLionel Sambuc (void) unlink(fmt_dev);
219433d6423SLionel Sambuc exit(1);
220433d6423SLionel Sambuc }
221433d6423SLionel Sambuc
222433d6423SLionel Sambuc (void) unlink(fmt_dev);
223433d6423SLionel Sambuc
224433d6423SLionel Sambuc if (st.st_rdev != fl_makedev(drive, type, 1)) {
225433d6423SLionel Sambuc /* Someone is trying to trick me. */
226433d6423SLionel Sambuc exit(1);
227433d6423SLionel Sambuc }
228433d6423SLionel Sambuc
229433d6423SLionel Sambuc if (verify) {
230433d6423SLionel Sambuc ver_dev= tmpnam(nil);
231433d6423SLionel Sambuc
232433d6423SLionel Sambuc if (mknod(ver_dev, S_IFBLK | 0700, fl_makedev(drive, type, 0))
233433d6423SLionel Sambuc < 0) {
234433d6423SLionel Sambuc fprintf(stderr,
235433d6423SLionel Sambuc "format: making verify device failed: %s\n",
236433d6423SLionel Sambuc strerror(errno));
237433d6423SLionel Sambuc exit(1);
238433d6423SLionel Sambuc }
239433d6423SLionel Sambuc
240433d6423SLionel Sambuc if ((vfd= open(ver_dev, O_RDONLY)) < 0) {
241433d6423SLionel Sambuc report(ver_dev);
242433d6423SLionel Sambuc (void) unlink(ver_dev);
243433d6423SLionel Sambuc exit(1);
244433d6423SLionel Sambuc }
245433d6423SLionel Sambuc
246433d6423SLionel Sambuc (void) unlink(ver_dev);
247433d6423SLionel Sambuc }
248433d6423SLionel Sambuc
249433d6423SLionel Sambuc nr_cyls= tparams->media_size * (1024 / SECTOR_SIZE) / NR_HEADS
250433d6423SLionel Sambuc / tparams->fmt_params.sectors_per_track;
251433d6423SLionel Sambuc
252433d6423SLionel Sambuc if (verbose) {
253433d6423SLionel Sambuc printf("Formatting a %uk diskette in a %uk drive\n",
254433d6423SLionel Sambuc tparams->media_size, tparams->drive_size);
255433d6423SLionel Sambuc }
256433d6423SLionel Sambuc
257433d6423SLionel Sambuc for (cyl= 0; cyl < nr_cyls; cyl++) {
258433d6423SLionel Sambuc for (head= 0; head < NR_HEADS; head++) {
259433d6423SLionel Sambuc if (verbose) {
260433d6423SLionel Sambuc printf(" Cyl. %2u, Head %u\r", cyl, head);
261433d6423SLionel Sambuc fflush(stdout);
262433d6423SLionel Sambuc }
263433d6423SLionel Sambuc /* After formatting a track we are too late to format
264433d6423SLionel Sambuc * the next track. So we can sleep at most 1/6 sec to
265433d6423SLionel Sambuc * allow the above printf to get displayed before we
266433d6423SLionel Sambuc * lock Minix into the floppy driver again.
267433d6423SLionel Sambuc */
268433d6423SLionel Sambuc if (verbose) usleep(50000); /* 1/20 sec will do. */
269433d6423SLionel Sambuc format_track(ffd, type, cyl, head);
270433d6423SLionel Sambuc if (verify) verify_track(vfd, type, cyl, head);
271433d6423SLionel Sambuc }
272433d6423SLionel Sambuc }
273433d6423SLionel Sambuc if (verbose) fputc('\n', stdout);
274433d6423SLionel Sambuc }
275433d6423SLionel Sambuc
usage(void)276433d6423SLionel Sambuc void usage(void)
277433d6423SLionel Sambuc {
278433d6423SLionel Sambuc fprintf(stderr,
279433d6423SLionel Sambuc "Usage: format [-v] <device> [<media size> [<drive size>]]\n");
280433d6423SLionel Sambuc exit(1);
281433d6423SLionel Sambuc }
282433d6423SLionel Sambuc
main(int argc,char ** argv)283433d6423SLionel Sambuc int main(int argc, char **argv)
284433d6423SLionel Sambuc {
285433d6423SLionel Sambuc char *device;
286433d6423SLionel Sambuc unsigned drive;
287433d6423SLionel Sambuc unsigned type;
288433d6423SLionel Sambuc unsigned media_size;
289433d6423SLionel Sambuc unsigned drive_size;
290433d6423SLionel Sambuc int verify= 0;
291433d6423SLionel Sambuc struct stat st0, st;
292433d6423SLionel Sambuc char special[PATH_MAX + 1], mounted_on[PATH_MAX + 1];
293433d6423SLionel Sambuc char version[MNTNAMELEN], rw_flag[MNTFLAGLEN];
294433d6423SLionel Sambuc
295433d6423SLionel Sambuc /* Option -v. */
296433d6423SLionel Sambuc while (argc > 1 && argv[1][0] == '-') {
297433d6423SLionel Sambuc char *p;
298433d6423SLionel Sambuc
299433d6423SLionel Sambuc for (p= argv[1]; *p == '-' || *p == 'v'; p++) {
300433d6423SLionel Sambuc if (*p == 'v') verify= 1;
301433d6423SLionel Sambuc }
302433d6423SLionel Sambuc if (*p != 0) usage();
303433d6423SLionel Sambuc argc--;
304433d6423SLionel Sambuc argv++;
305433d6423SLionel Sambuc if (strcmp(argv[0], "--") == 0) break;
306433d6423SLionel Sambuc }
307433d6423SLionel Sambuc
308433d6423SLionel Sambuc if (argc < 2 || argc > 4) usage();
309433d6423SLionel Sambuc
310433d6423SLionel Sambuc /* Check if the caller has read-write permission. Use the access()
311433d6423SLionel Sambuc * call to check with the real uid & gid. This program is usually
312433d6423SLionel Sambuc * set-uid root.
313433d6423SLionel Sambuc */
314433d6423SLionel Sambuc device= argv[1];
315433d6423SLionel Sambuc if (stat(device, &st0) < 0
316433d6423SLionel Sambuc || access(device, R_OK|W_OK) < 0
317433d6423SLionel Sambuc || stat(device, &st) < 0
318433d6423SLionel Sambuc || (errno= EACCES, 0) /* set errno for following tests */
319433d6423SLionel Sambuc || st.st_dev != st0.st_dev
320433d6423SLionel Sambuc || st.st_ino != st0.st_ino
321433d6423SLionel Sambuc ) {
322433d6423SLionel Sambuc fatal(device);
323433d6423SLionel Sambuc }
324433d6423SLionel Sambuc
325433d6423SLionel Sambuc if (!S_ISBLK(st.st_mode) || !isfloppy(st.st_rdev)) {
326433d6423SLionel Sambuc fprintf(stderr, "format: %s: not a floppy device\n", device);
327433d6423SLionel Sambuc exit(1);
328433d6423SLionel Sambuc }
329433d6423SLionel Sambuc
330433d6423SLionel Sambuc drive= fl_drive(st.st_rdev);
331433d6423SLionel Sambuc type= fl_type(st.st_rdev);
332433d6423SLionel Sambuc
333433d6423SLionel Sambuc /* The drive should not be mounted. */
334433d6423SLionel Sambuc if (load_mtab("mkfs") < 0) exit(1);
335433d6423SLionel Sambuc
336433d6423SLionel Sambuc while (get_mtab_entry(special, mounted_on, version, rw_flag) == 0) {
337433d6423SLionel Sambuc if (stat(special, &st) >= 0 && isfloppy(st.st_rdev)
338433d6423SLionel Sambuc && fl_drive(st.st_rdev) == drive) {
339433d6423SLionel Sambuc fprintf(stderr, "format: %s is mounted on %s\n",
340433d6423SLionel Sambuc device, mounted_on);
341433d6423SLionel Sambuc exit(1);
342433d6423SLionel Sambuc }
343433d6423SLionel Sambuc }
344433d6423SLionel Sambuc
345433d6423SLionel Sambuc if (isflauto(type)) {
346433d6423SLionel Sambuc /* Auto type 0 requires size(s). */
347433d6423SLionel Sambuc unsigned long lmedia, ldrive;
348433d6423SLionel Sambuc char *end;
349433d6423SLionel Sambuc
350433d6423SLionel Sambuc if (argc < 3) {
351433d6423SLionel Sambuc fprintf(stderr,
352433d6423SLionel Sambuc "format: no size specified for auto floppy device %s\n",
353433d6423SLionel Sambuc device);
354433d6423SLionel Sambuc usage();
355433d6423SLionel Sambuc }
356433d6423SLionel Sambuc
357433d6423SLionel Sambuc lmedia= strtoul(argv[2], &end, 10);
358433d6423SLionel Sambuc if (end == argv[2] || *end != 0 || lmedia > 20 * 1024)
359433d6423SLionel Sambuc usage();
360433d6423SLionel Sambuc
361433d6423SLionel Sambuc if (argc == 4) {
362433d6423SLionel Sambuc ldrive= strtoul(argv[3], &end, 10);
363433d6423SLionel Sambuc if (end == argv[3] || *end != 0 || ldrive > 20 * 1024)
364433d6423SLionel Sambuc usage();
365433d6423SLionel Sambuc } else {
366433d6423SLionel Sambuc ldrive= lmedia;
367433d6423SLionel Sambuc }
368433d6423SLionel Sambuc
369433d6423SLionel Sambuc /* Silently correct wrong ordered sizes. */
370433d6423SLionel Sambuc if (lmedia > ldrive) {
371433d6423SLionel Sambuc media_size= ldrive;
372433d6423SLionel Sambuc drive_size= lmedia;
373433d6423SLionel Sambuc } else {
374433d6423SLionel Sambuc media_size= lmedia;
375433d6423SLionel Sambuc drive_size= ldrive;
376433d6423SLionel Sambuc }
377433d6423SLionel Sambuc
378433d6423SLionel Sambuc /* A 1.44M drive can do 720k diskettes with no extra tricks.
379433d6423SLionel Sambuc * Diddle with the 720k params so it is found.
380433d6423SLionel Sambuc */
381433d6423SLionel Sambuc if (media_size == 720 && drive_size == 1440)
382433d6423SLionel Sambuc parameters[4 - 1].drive_size= 1440;
383433d6423SLionel Sambuc
384433d6423SLionel Sambuc /* Translate the auto type to a known type. */
385433d6423SLionel Sambuc for (type= 1; type <= NR_TYPES; type++) {
386433d6423SLionel Sambuc if (parameters[type - 1].media_size == media_size
387433d6423SLionel Sambuc && parameters[type - 1].drive_size == drive_size
388433d6423SLionel Sambuc ) break;
389433d6423SLionel Sambuc }
390433d6423SLionel Sambuc
391433d6423SLionel Sambuc if (!isfltyped(type)) {
392433d6423SLionel Sambuc fprintf(stderr,
393433d6423SLionel Sambuc "format: can't format a %uk floppy in a %uk drive\n",
394433d6423SLionel Sambuc media_size, drive_size);
395433d6423SLionel Sambuc exit(1);
396433d6423SLionel Sambuc }
397433d6423SLionel Sambuc } else
398433d6423SLionel Sambuc if (isfltyped(type)) {
399433d6423SLionel Sambuc /* No sizes needed for a non-auto type. */
400433d6423SLionel Sambuc
401433d6423SLionel Sambuc if (argc > 2) {
402433d6423SLionel Sambuc fprintf(stderr,
403433d6423SLionel Sambuc "format: no sizes need to be specified for non-auto floppy device %s\n",
404433d6423SLionel Sambuc device);
405433d6423SLionel Sambuc usage();
406433d6423SLionel Sambuc }
407433d6423SLionel Sambuc } else
408433d6423SLionel Sambuc if (isflpart(type)) {
409433d6423SLionel Sambuc fprintf(stderr,
410433d6423SLionel Sambuc "format: floppy partition %s can't be formatted\n",
411433d6423SLionel Sambuc device);
412433d6423SLionel Sambuc exit(1);
413433d6423SLionel Sambuc } else {
414433d6423SLionel Sambuc fprintf(stderr,
415433d6423SLionel Sambuc "format: %s: can't format strange type %d\n",
416433d6423SLionel Sambuc device, type);
417433d6423SLionel Sambuc }
418433d6423SLionel Sambuc
419433d6423SLionel Sambuc format_device(drive, type, verify);
420433d6423SLionel Sambuc exit(0);
421433d6423SLionel Sambuc }
422