xref: /aosp_15_r20/external/mtools/devices.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
1 /*  Copyright 1986-1992 Emmet P. Gray.
2  *  Copyright 1996-2003,2006,2007,2009 Alain Knaff.
3  *  This file is part of mtools.
4  *
5  *  Mtools is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  Mtools is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /*
20  * Device tables.  See the Configure file for a complete description.
21  */
22 
23 #define NO_TERMIO
24 #include "sysincludes.h"
25 #include "msdos.h"
26 #include "mtools.h"
27 #include "devices.h"
28 
29 #define INIT_NOOP
30 
31 #define DEF_ARG1(x) (x), 0x2,0,(char *)0, 0, 0, 0, 0, 0, 0, NULL
32 #define DEF_ARG0(x) 0,DEF_ARG1(x)
33 
34 #define MDEF_ARG 0L,DEF_ARG0(MFORMAT_ONLY_FLAG)
35 #define FDEF_ARG 0L,DEF_ARG0(0)
36 
37 #pragma GCC diagnostic push
38 #pragma GCC diagnostic ignored "-Wunused-macros"
39 
40 #define VOLD_DEF_ARG 0L,DEF_ARG0(VOLD_FLAG|MFORMAT_ONLY_FLAG)
41 
42 #define MED312	12,0,80,2,36,0,MDEF_ARG /* 3 1/2 extra density */
43 #define MHD312	12,0,80,2,18,0,MDEF_ARG /* 3 1/2 high density */
44 #define MDD312	12,0,80,2, 9,0,MDEF_ARG /* 3 1/2 double density */
45 #define MHD514	12,0,80,2,15,0,MDEF_ARG /* 5 1/4 high density */
46 #define MDD514	12,0,40,2, 9,0,MDEF_ARG /* 5 1/4 double density (360k) */
47 #define MSS514	12,0,40,1, 9,0,MDEF_ARG /* 5 1/4 single sided DD, (180k) */
48 #define MDDsmall	12,0,40,2, 8,0,MDEF_ARG /* 5 1/4 double density (320k) */
49 #define MSSsmall	12,0,40,1, 8,0,MDEF_ARG /* 5 1/4 single sided DD, (160k) */
50 
51 #define FED312	12,0,80,2,36,0,FDEF_ARG /* 3 1/2 extra density */
52 #define FHD312	12,0,80,2,18,0,FDEF_ARG /* 3 1/2 high density */
53 #define FDD312	12,0,80,2, 9,0,FDEF_ARG /* 3 1/2 double density */
54 #define FHD514	12,0,80,2,15,0,FDEF_ARG /* 5 1/4 high density */
55 #define FDD514	12,0,40,2, 9,0,FDEF_ARG /* 5 1/4 double density (360k) */
56 #define FSS514	12,0,40,1, 9,0,FDEF_ARG /* 5 1/4 single sided DD, (180k) */
57 #define FDDsmall	12,0,40,2, 8,0,FDEF_ARG /* 5 1/4 double density (320k) */
58 #define FSSsmall	12,0,40,1, 8,0,FDEF_ARG /* 5 1/4 single sided DD, (160k) */
59 
60 #define GENHD	16,0, 0,0, 0,0,MDEF_ARG /* Generic 16 bit FAT fs */
61 #define GENFD	12,0,80,2,18,0,MDEF_ARG /* Generic 12 bit FAT fs */
62 #define VOLDFD	12,0,80,2,18,0,VOLD_DEF_ARG /* Generic 12 bit FAT fs with vold */
63 #define GEN    	 0,0, 0,0, 0,0,MDEF_ARG /* Generic fs of any FAT bits */
64 
65 #define ZIPJAZ(x,c,h,s,y) 16,(x),(c),(h),(s),(s),0L, 4, \
66 		DEF_ARG1((y)|MFORMAT_ONLY_FLAG) /* Jaz disks */
67 
68 #define JAZ(x)	 ZIPJAZ(x,1021, 64, 32, 0)
69 #define RJAZ(x)	 ZIPJAZ(x,1021, 64, 32, SCSI_FLAG|PRIV_FLAG)
70 #define ZIP(x)	 ZIPJAZ(x,96, 64, 32, 0)
71 #define RZIP(x)	 ZIPJAZ(x,96, 64, 32, SCSI_FLAG|PRIV_FLAG)
72 
73 #pragma GCC diagnostic pop
74 
75 #define REMOTE    {"$DISPLAY", 'X', 0,0, 0,0, 0,0,0L, DEF_ARG0(FLOPPYD_FLAG)}
76 
77 
78 
79 #if defined(INIT_GENERIC) || defined(INIT_NOOP)
compare_geom(struct device * dev,struct device * orig_dev)80 static int compare_geom(struct device *dev, struct device *orig_dev)
81 {
82 	if(IS_MFORMAT_ONLY(orig_dev))
83 		return 0; /* geometry only for mformatting ==> ok */
84 	if(!orig_dev || !orig_dev->tracks || !dev || !dev->tracks)
85 		return 0; /* no original device. This is ok */
86 	return(orig_dev->tracks != dev->tracks ||
87 	       orig_dev->heads != dev->heads ||
88 	       orig_dev->sectors  != dev->sectors);
89 }
90 #endif
91 
92 #define devices const_devices
93 
94 
95 #ifdef __CYGWIN__
96 #define predefined_devices
97 struct device devices[] = {
98    {"\\\\\\\\.\\\\A:", 'A', GENFD },
99 };
100 #endif /* CYGWIN */
101 
102 
103 #ifdef OS_aux
104 #define predefined_devices
105 struct device devices[] = {
106    {"/dev/floppy0", 'A', GENFD },
107    {"/dev/rdsk/c104d0s31", 'J', JAZ(O_EXCL) },
108    {"/dev/rdsk/c105d0s31", 'Z', ZIP(O_EXCL) },
109    REMOTE
110 };
111 #endif /* aux */
112 
113 
114 #ifdef OS_lynxos
115 #define predefined_devices
116 struct device devices[] = {
117 	{"/dev/fd1440.0", 	'A', MHD312 },
118 	REMOTE
119 };
120 #endif
121 
122 
123 #ifdef __BEOS__
124 #define predefined_devices
125 struct device devices[] = {
126 	{"/dev/disk/floppy/raw", 	'A', MHD312 },
127 	REMOTE
128 };
129 #endif /* BEBOX */
130 
131 
132 #ifdef OS_hpux
133 
134 #define predefined_devices
135 struct device devices[] = {
136 #ifdef OS_hpux10
137 /* hpux10 uses different device names according to Frank Maritato
138  * <[email protected]> */
139 	{"/dev/floppy/c0t0d0",		'A', MHD312 },
140 	{"/dev/floppy/c0t0d1",		'B', MHD312 }, /* guessed by me */
141  	{"/dev/rscsi",			'C', GENHD }, /* guessed by me */
142 #else
143 /* Use rfloppy, according to Simao Campos <[email protected]> */
144 	{"/dev/rfloppy/c201d0s0",	'A', FHD312 },
145 	{"/dev/rfloppy/c20Ad0s0", 	'A', FHD312 },
146  	{"/dev/rfloppy/c201d1s0",	'B', FHD312 },
147  	{"/dev/rfloppy/c20Ad1s0",	'B', FHD312 },
148  	{"/dev/rscsi",			'C', GENHD },
149 #endif
150 	{"/dev/rdsk/c201d4",		'J', RJAZ(O_EXCL) },
151 	{"/dev/rdsk/c201d4s0",		'J', RJAZ(O_EXCL) },
152 	{"/dev/rdsk/c201d5",		'Z', RZIP(O_EXCL) },
153 	{"/dev/rdsk/c201d5s0",		'Z', RZIP(O_EXCL) },
154 	REMOTE
155 };
156 
157 #ifdef HAVE_SYS_FLOPPY
158 /* geometry setting ioctl's contributed by Paolo Zeppegno
159  * <[email protected]>, may cause "Not a typewriter" messages on other
160  * versions according to [email protected] */
161 
162 #include <sys/floppy.h>
163 #undef SSIZE
164 
165 struct generic_floppy_struct
166 {
167   struct floppy_geometry fg;
168 };
169 
170 #define BLOCK_MAJOR 24
171 #define CHAR_MAJOR 112
172 
get_parameters(int fd,struct generic_floppy_struct * floppy)173 static inline int get_parameters(int fd, struct generic_floppy_struct *floppy)
174 {
175 	if (ioctl(fd, FLOPPY_GET_GEOMETRY, &(floppy->fg)) != 0) {
176 		perror("FLOPPY_GET_GEOMETRY");
177 		return(1);
178 	}
179 
180 	return 0;
181 }
182 
183 #define TRACKS(floppy) floppy.fg.tracks
184 #define HEADS(floppy) floppy.fg.heads
185 #define SECTORS(floppy) floppy.fg.sectors
186 #define FD_SECTSIZE(floppy) floppy.fg.sector_size
187 #define FD_SET_SECTSIZE(floppy,v) { floppy.fg.sector_size = v; }
188 
set_parameters(int fd,struct generic_floppy_struct * floppy,struct MT_STAT * buf)189 static inline int set_parameters(int fd, struct generic_floppy_struct *floppy,
190 				 struct MT_STAT *buf)
191 {
192 	if (ioctl(fd, FLOPPY_SET_GEOMETRY, &(floppy->fg)) != 0) {
193 		perror("");
194 		return(1);
195 	}
196 
197 	return 0;
198 }
199 #define INIT_GENERIC
200 #endif
201 
202 #endif /* hpux */
203 
204 
205 #if (defined(OS_sinix) || defined(VENDOR_sni) || defined(SNI))
206 #define predefined_devices
207 struct device devices[] = {
208 #ifdef CPU_mips     /* for Siemens Nixdorf's  SINIX-N/O (mips) 5.4x SVR4 */
209 	{ "/dev/at/flp/f0t",    'A', FHD312},
210 	{ "/dev/fd0",           'A', GENFD},
211 #else
212 #ifdef CPU_i386     /* for Siemens Nixdorf's  SINIX-D/L (intel) 5.4x SVR4 */
213 	{ "/dev/fd0135ds18",	'A', FHD312},
214 	{ "/dev/fd0135ds9",	'A', FDD312},
215 	{ "/dev/fd0",		'A', GENFD},
216 	{ "/dev/fd1135ds15",	'B', FHD514},
217 	{ "/dev/fd1135ds9",	'B', FDD514},
218 	{ "/dev/fd1",		'B', GENFD},
219 #endif /* CPU_i386 */
220 #endif /*mips*/
221 	REMOTE
222 };
223 #endif
224 
225 #ifdef OS_ultrix
226 #define predefined_devices
227 struct device devices[] = {
228 	{"/dev/rfd0a",		'A', GENFD}, /* guessed */
229 	{"/dev/rfd0c",		'A', GENFD}, /* guessed */
230 	REMOTE
231 };
232 
233 #endif
234 
235 
236 #ifdef OS_isc
237 #define predefined_devices
238 #if (defined(OS_isc2) && defined(OLDSTUFF))
239 struct device devices[] = {
240 	{"/dev/rdsk/f0d9dt",   	'A', FDD514},
241 	{"/dev/rdsk/f0q15dt",	'A', FHD514},
242 	{"/dev/rdsk/f0d8dt",	'A', FDDsmall},
243 	{"/dev/rdsk/f13ht",	'B', FHD312},
244 	{"/dev/rdsk/f13dt",	'B', FDD312},
245 	{"/dev/rdsk/0p1",	'C', GENHD},
246 	{"/usr/vpix/defaults/C:",'D',12, 0, 0, 0, 0,8704L,DEF_ARG0},
247 	{"$HOME/vpix/C:", 	'E', 12, 0, 0, 0, 0,8704L,MDEF_ARG},
248 	REMOTE
249 };
250 #else
251 /* contributed by [email protected] (Larry Jones) */
252 struct device devices[] = {
253 	{"/dev/rfd0",		'A', GEN},
254 	{"/dev/rfd1",		'B', GEN},
255 	{"/dev/rdsk/0p1",	'C', GEN},
256 	{"/usr/vpix/defaults/C:",'D', GEN, 1},
257 	{"$HOME/vpix/C:", 	'E', GEN, 1},
258 	REMOTE
259 };
260 
261 #include <sys/vtoc.h>
262 #include <sys/sysmacros.h>
263 #undef SSIZE
264 #define BLOCK_MAJOR 1
265 #define CHAR_MAJOR  1
266 #define generic_floppy_struct disk_parms
267 int ioctl(int, int, void *);
268 
get_parameters(int fd,struct generic_floppy_struct * floppy)269 static int get_parameters(int fd, struct generic_floppy_struct *floppy)
270 {
271 	mt_off_t off;
272 	char buf[512];
273 
274 	off = lseek(fd, 0, SEEK_CUR);
275 	if(off < 0) {
276 		perror("device seek 1");
277 		exit(1);
278 	}
279 	if (off == 0) {
280 		/* need to read at least 1 sector to get correct info */
281 		read(fd, buf, sizeof buf);
282 		if(lseek(fd, 0, SEEK_SET) < 0) {
283 			perror("device seek 2");
284 			exit(1);
285 		}
286 	}
287 	return ioctl(fd, V_GETPARMS, floppy);
288 }
289 
290 #define TRACKS(floppy)  (floppy).dp_cyls
291 #define HEADS(floppy)   (floppy).dp_heads
292 #define SECTORS(floppy) (floppy).dp_sectors
293 #define FD_SECTSIZE(floppy) (floppy).dp_secsiz
294 #define FD_SET_SECTSIZE(floppy,v) { (floppy).dp_secsiz = (v); }
295 
set_parameters(int fd,struct generic_floppy_struct * floppy,struct MT_STAT * buf)296 static int set_parameters(int fd, struct generic_floppy_struct *floppy,
297 	struct MT_STAT *buf)
298 {
299 	return 1;
300 }
301 
302 #define INIT_GENERIC
303 #endif
304 #endif /* isc */
305 
306 #ifdef CPU_i370
307 #define predefined_devices
308 struct device devices[] = {
309 	{"/dev/rfd0", 'A', GENFD},
310 	REMOTE
311 };
312 #endif /* CPU_i370 */
313 
314 #ifdef OS_aix
315 /* modified by Federico Bianchi */
316 #define predefined_devices
317 struct device devices[] = {
318 	{"/dev/fd0",'A',GENFD},
319 	REMOTE
320 };
321 #endif /* aix */
322 
323 
324 #ifdef OS_osf4
325 /* modified by Chris Samuel <[email protected]> */
326 #define predefined_devices
327 struct device devices[] = {
328 	{"/dev/fd0c",'A',GENFD},
329 	REMOTE
330 };
331 #endif /* OS_osf4 */
332 
333 
334 #ifdef OS_solaris
335 
336 #ifdef USING_NEW_VOLD
337 
338 char *alias_name = NULL;
339 
340 extern char *media_oldaliases(char *);
341 extern char *media_findname(char *);
342 
getVoldName(struct device * dev,char * name)343 char *getVoldName(struct device *dev, char *name)
344 {
345 	char *rname;
346 
347 	if(!SHOULD_USE_VOLD(dev))
348 		return name;
349 
350 	/***
351 	 * Solaris specific routines to use the volume management
352 	 * daemon and libraries to get the correct device name...
353 	 ***/
354 	rname = media_findname(name);
355 #ifdef HAVE_MEDIA_OLDALIASES
356 	if (rname == NULL) {
357 		if ((alias_name = media_oldaliases(name)) != NULL)
358 			rname = media_findname(alias_name);
359 	}
360 #endif
361 	if (rname == NULL) {
362 		fprintf(stderr,
363 				"No such volume or no media in device: %s.\n",
364 				name);
365 		exit(1);
366 	}
367 	return rname;
368 }
369 #endif /* USING_NEW_VOLD */
370 
371 #define predefined_devices
372 struct device devices[] = {
373 #ifdef  USING_NEW_VOLD
374 	{"floppy", 'A', VOLDFD },
375 #elif	USING_VOLD
376 	{"/vol/dev/aliases/floppy0", 'A', GENFD},
377 	{"/dev/rdiskette", 'B', GENFD},
378 #else	/* ! USING_VOLD */
379 	{"/dev/rdiskette", 'A', GENFD},
380 	{"/vol/dev/aliases/floppy0", 'B', GENFD},
381 #endif	/* USING_VOLD */
382 	{"/dev/rdsk/c0t4d0s2", 'J', RJAZ(O_NDELAY)},
383 	{"/dev/rdsk/c0t5d0s2", 'Z', RZIP(O_NDELAY)},
384 	REMOTE
385 };
386 
387 
388 
389 #ifdef HAVE_SYS_FDIO_H
390 /*
391  * Ofer Licht <[email protected]>, May 14, 1997.
392  */
393 
394 #define INIT_GENERIC
395 
396 #include <sys/fdio.h>
397 #include <sys/mkdev.h>	/* for major() */
398 
399 struct generic_floppy_struct
400 {
401   struct fd_char fdchar;
402 };
403 
404 #define BLOCK_MAJOR 36
405 #define CHAR_MAJOR 36
406 
get_parameters(int fd,struct generic_floppy_struct * floppy)407 static inline int get_parameters(int fd, struct generic_floppy_struct *floppy)
408 {
409 	if (ioctl(fd, FDIOGCHAR, &(floppy->fdchar)) != 0) {
410 		perror("");
411 		ioctl(fd, FDEJECT, NULL);
412 		return(1);
413 	}
414 	return 0;
415 }
416 
417 #define TRACKS(floppy) floppy.fdchar.fdc_ncyl
418 #define HEADS(floppy) floppy.fdchar.fdc_nhead
419 #define SECTORS(floppy) floppy.fdchar.fdc_secptrack
420 /* SECTORS_PER_DISK(floppy) not used */
421 #define FD_SECTSIZE(floppy) floppy.fdchar.fdc_sec_size
422 #define FD_SET_SECTSIZE(floppy,v) { floppy.fdchar.fdc_sec_size = v; }
423 
set_parameters(int fd,struct generic_floppy_struct * floppy,struct MT_STAT * buf UNUSEDP)424 static inline int set_parameters(int fd, struct generic_floppy_struct *floppy,
425 				 struct MT_STAT *buf UNUSEDP)
426 {
427 	if (ioctl(fd, FDIOSCHAR, &(floppy->fdchar)) != 0) {
428 		ioctl(fd, FDEJECT, NULL);
429 		perror("");
430 		return(1);
431 	}
432 	return 0;
433 }
434 #endif
435 #endif /* solaris */
436 
437 #ifdef OS_sunos3
438 #define predefined_devices
439 struct device devices[] = {
440 	{"/dev/rfdl0c",	'A', FDD312},
441 	{"/dev/rfd0c",	'A', FHD312},
442 	REMOTE
443 };
444 #endif /* OS_sunos3 */
445 
446 #ifdef OS_xenix
447 #define predefined_devices
448 struct device devices[] = {
449 	{"/dev/fd096ds15",	'A', FHD514},
450 	{"/dev/fd048ds9",	'A', FDD514},
451 	{"/dev/fd1135ds18",	'B', FHD312},
452 	{"/dev/fd1135ds9",	'B', FDD312},
453 	{"/dev/hd0d",		'C', GENHD},
454 	REMOTE
455 };
456 #endif /* OS_xenix */
457 
458 #ifdef OS_sco
459 #define predefined_devices
460 struct device devices[] = {
461 	{ "/dev/fd0135ds18",	'A', FHD312},
462 	{ "/dev/fd0135ds9",	'A', FDD312},
463 	{ "/dev/fd0",		'A', GENFD},
464 	{ "/dev/fd1135ds15",	'B', FHD514},
465 	{ "/dev/fd1135ds9",	'B', FDD514},
466 	{ "/dev/fd1",		'B', GENFD},
467 	{ "/dev/hd0d",		'C', GENHD},
468 	REMOTE
469 };
470 #endif /* OS_sco */
471 
472 
473 #ifdef OS_irix
474 #define predefined_devices
475 struct device devices[] = {
476   { "/dev/rdsk/fds0d2.3.5hi",	'A', FHD312},
477   { "/dev/rdsk/fds0d2.3.5",	'A', FDD312},
478   { "/dev/rdsk/fds0d2.96",	'A', FHD514},
479   {"/dev/rdsk/fds0d2.48",	'A', FDD514},
480   REMOTE
481 };
482 #endif /* OS_irix */
483 
484 
485 #ifdef OS_sunos4
486 #include <sys/ioctl.h>
487 #include <sun/dkio.h>
488 
489 #define predefined_devices
490 struct device devices[] = {
491 	{"/dev/rfd0c",	'A', GENFD},
492 	{"/dev/rsd4c",	'J', RJAZ(O_NDELAY)},
493 	{"/dev/rsd5c",	'Z', RZIP(O_NDELAY)},
494 	REMOTE
495 };
496 
497 /*
498  * Stuffing back the floppy parameters into the driver allows for gems
499  * like 10 sector or single sided floppies from Atari ST systems.
500  *
501  * Martin Schulz, Universite de Moncton, N.B., Canada, March 11, 1991.
502  */
503 
504 #define INIT_GENERIC
505 
506 struct generic_floppy_struct
507 {
508   struct fdk_char dkbuf;
509   struct dk_map dkmap;
510 };
511 
512 #define BLOCK_MAJOR 16
513 #define CHAR_MAJOR 54
514 
get_parameters(int fd,struct generic_floppy_struct * floppy)515 static inline int get_parameters(int fd, struct generic_floppy_struct *floppy)
516 {
517 	if (ioctl(fd, DKIOCGPART, &(floppy->dkmap)) != 0) {
518 		perror("DKIOCGPART");
519 		ioctl(fd, FDKEJECT, NULL);
520 		return(1);
521 	}
522 
523 	if (ioctl(fd, FDKIOGCHAR, &( floppy->dkbuf)) != 0) {
524 		perror("");
525 		ioctl(fd, FDKEJECT, NULL);
526 		return(1);
527 	}
528 	return 0;
529 }
530 
531 #define TRACKS(floppy) floppy.dkbuf.ncyl
532 #define HEADS(floppy) floppy.dkbuf.nhead
533 #define SECTORS(floppy) floppy.dkbuf.secptrack
534 #define SECTORS_PER_DISK(floppy) floppy.dkmap.dkl_nblk
535 #define FD_SECTSIZE(floppy) floppy.dkbuf.sec_size
536 #define FD_SET_SECTSIZE(floppy,v) { floppy.dkbuf.sec_size = v; }
537 
set_parameters(int fd,struct generic_floppy_struct * floppy,struct MT_STAT * buf)538 static inline int set_parameters(int fd, struct generic_floppy_struct *floppy,
539 				 struct MT_STAT *buf)
540 {
541 	if (ioctl(fd, FDKIOSCHAR, &(floppy->dkbuf)) != 0) {
542 		ioctl(fd, FDKEJECT, NULL);
543 		perror("");
544 		return(1);
545 	}
546 
547 	if (ioctl(fd, ( unsigned int) DKIOCSPART, &(floppy->dkmap)) != 0) {
548 		ioctl(fd, FDKEJECT, NULL);
549 		perror("");
550 		return(1);
551 	}
552 	return 0;
553 }
554 #define INIT_GENERIC
555 #endif /* sparc && sunos */
556 
557 
558 #ifdef DPX1000
559 #define predefined_devices
560 struct device devices[] = {
561 	/* [block device]: DPX1000 has /dev/flbm60, DPX2 has /dev/easyfb */
562 	{"/dev/flbm60", 'A', MHD514};
563 	{"/dev/flbm60", 'B', MDD514},
564 	{"/dev/flbm60", 'C', MDDsmall},
565 	{"/dev/flbm60", 'D', MSS},
566 	{"/dev/flbm60", 'E', MSSsmall},
567 	REMOTE
568 };
569 #endif /* DPX1000 */
570 
571 #ifdef OS_bosx
572 #define predefined_devices
573 struct device devices[] = {
574 	/* [block device]: DPX1000 has /dev/flbm60, DPX2 has /dev/easyfb */
575 	{"/dev/easyfb", 'A', MHD514},
576 	{"/dev/easyfb", 'B', MDD514},
577 	{"/dev/easyfb", 'C', MDDsmall},
578 	{"/dev/easyfb", 'D', MSS},
579 	{"/dev/easyfb", 'E', MSSsmall},
580 	REMOTE
581 };
582 #endif /* OS_bosx */
583 
584 #ifdef OS_linux
585 
586 static const char *error_msg[22]={
587 "Missing Data Address Mark",
588 "Bad cylinder",
589 "Scan not satisfied",
590 "Scan equal hit",
591 "Wrong cylinder",
592 "CRC error in data field",
593 "Control Mark = deleted",
594 0,
595 
596 "Missing Address Mark",
597 "Write Protect",
598 "No Data - unreadable",
599 0,
600 "OverRun",
601 "CRC error in data or address",
602 0,
603 "End Of Cylinder",
604 
605 0,
606 0,
607 0,
608 "Not ready",
609 "Equipment check error",
610 "Seek end" };
611 
612 
print_message(RawRequest_t * raw_cmd,const char * message)613 static __inline__ void print_message(RawRequest_t *raw_cmd,const char *message)
614 {
615 	int i, code;
616 	if(!message)
617 		return;
618 
619 	fprintf(stderr,"   ");
620 	for (i=0; i< raw_cmd->cmd_count; i++)
621 		fprintf(stderr,"%2.2x ",
622 			(int)raw_cmd->cmd[i] );
623 	fprintf(stderr,"\n");
624 	for (i=0; i< raw_cmd->reply_count; i++)
625 		fprintf(stderr,"%2.2x ",
626 			(int)raw_cmd->reply[i] );
627 	fprintf(stderr,"\n");
628 	code = (raw_cmd->reply[0] <<16) +
629 		(raw_cmd->reply[1] << 8) +
630 		raw_cmd->reply[2];
631 	for(i=0; i<22; i++){
632 		if ((code & (1 << i)) && error_msg[i])
633 			fprintf(stderr,"%s\n",
634 				error_msg[i]);
635 	}
636 }
637 
638 
639 /* return values:
640  *  -1: Fatal error, don't bother retrying.
641  *   0: OK
642  *   1: minor error, retry
643  */
644 
send_one_cmd(int fd,RawRequest_t * raw_cmd,const char * message)645 int send_one_cmd(int fd, RawRequest_t *raw_cmd, const char *message)
646 {
647 	if (ioctl( fd, FDRAWCMD, raw_cmd) >= 0) {
648 		if (raw_cmd->reply_count < 7) {
649 			fprintf(stderr,"Short reply from FDC\n");
650 			return -1;
651 		}
652 		return 0;
653 	}
654 
655 	switch(errno) {
656 		case EBUSY:
657 			fprintf(stderr, "FDC busy, sleeping for a second\n");
658 			sleep(1);
659 			return 1;
660 		case EIO:
661 			fprintf(stderr,"resetting controller\n");
662 			if(ioctl(fd, FDRESET, 2)  < 0){
663 				perror("reset");
664 				return -1;
665 			}
666 			return 1;
667 		default:
668 			perror(message);
669 			return -1;
670 	}
671 }
672 
673 
674 /*
675  * return values
676  *  -1: error
677  *   0: OK, last sector
678  *   1: more raw commands follow
679  */
680 
analyze_one_reply(RawRequest_t * raw_cmd,int * bytes,int do_print)681 int analyze_one_reply(RawRequest_t *raw_cmd, int *bytes, int do_print)
682 {
683 
684 	if(raw_cmd->reply_count == 7) {
685 		int end;
686 
687 		if (raw_cmd->reply[3] != raw_cmd->cmd[2]) {
688 			/* end of cylinder */
689 			end = raw_cmd->cmd[6] + 1;
690 		} else {
691 			end = raw_cmd->reply[5];
692 		}
693 
694 		*bytes = end - raw_cmd->cmd[4];
695 		/* FIXME: over/under run */
696 		*bytes = *bytes << (7 + raw_cmd->cmd[5]);
697 	} else
698 		*bytes = 0;
699 
700 	switch(raw_cmd->reply[0] & 0xc0){
701 		case 0x40:
702 			if ((raw_cmd->reply[0] & 0x38) == 0 &&
703 			    (raw_cmd->reply[1]) == 0x80 &&
704 			    (raw_cmd->reply[2]) == 0) {
705 				*bytes += 1 << (7 + raw_cmd->cmd[5]);
706 				break;
707 			}
708 
709 			if ( raw_cmd->reply[1] & ST1_WP ){
710 				*bytes = 0;
711 				fprintf(stderr,
712 					"This disk is write protected\n");
713 				return -1;
714 			}
715 			if(!*bytes && do_print)
716 				print_message(raw_cmd, "");
717 			return -1;
718 		case 0x80:
719 			*bytes = 0;
720 			fprintf(stderr,
721 				"invalid command given\n");
722 			return -1;
723 		case 0xc0:
724 			*bytes = 0;
725 			fprintf(stderr,
726 				"abnormal termination caused by polling\n");
727 			return -1;
728 		default:
729 			break;
730 	}
731 #ifdef FD_RAW_MORE
732 	if(raw_cmd->flags & FD_RAW_MORE)
733 		return 1;
734 #endif
735 	return 0;
736 }
737 
738 #define predefined_devices
739 struct device devices[] = {
740 	{"/dev/fd0", 'A', 0, 0, 80,2, 18,0, MDEF_ARG },
741 	{"/dev/fd1", 'B', 0, 0, 0,0, 0,0, FDEF_ARG },
742 	/* we assume that the Zip or Jaz drive is the second on the SCSI bus */
743 	{"/dev/sdb4",'J', GENHD },
744 	{"/dev/sdb4",'Z', GENHD },
745 	/*	{"/dev/sda4",'D', GENHD },*/
746 	REMOTE
747 };
748 
749 /*
750  * Stuffing back the floppy parameters into the driver allows for gems
751  * like 21 sector or single sided floppies from Atari ST systems.
752  *
753  * Alain Knaff, Universit� Joseph Fourier, France, November 12, 1993.
754  */
755 
756 
757 #define INIT_GENERIC
758 #define generic_floppy_struct floppy_struct
759 #define BLOCK_MAJOR 2
760 #define SECTORS(floppy) floppy.sect
761 #define TRACKS(floppy) floppy.track
762 #define HEADS(floppy) floppy.head
763 #define SECTORS_PER_DISK(floppy) floppy.size
764 #define STRETCH(floppy) floppy.stretch
765 #define USE_2M(floppy) ((floppy.rate & FD_2M) ? 0xff : 0x80 )
766 #define SSIZE(floppy) ((((floppy.rate & 0x38) >> 3 ) + 2) % 8)
767 
set_2m(struct floppy_struct * floppy,unsigned int value)768 static __inline__ void set_2m(struct floppy_struct *floppy, unsigned int value)
769 {
770 	uint8_t v;
771 	if (value & 0x7f)
772 		v = FD_2M;
773 	else
774 		v = 0;
775 	floppy->rate = (floppy->rate & ~FD_2M) | v;
776 }
777 #define SET_2M set_2m
778 
set_ssize(struct floppy_struct * floppy,int value)779 static __inline__ void set_ssize(struct floppy_struct *floppy, int value)
780 {
781 	uint8_t v = (uint8_t) ((( (value & 7) + 6 ) % 8) << 3);
782 
783 	floppy->rate = (floppy->rate & ~0x38) | v;
784 }
785 
786 #define SET_SSIZE set_ssize
787 
set_parameters(int fd,struct floppy_struct * floppy,struct MT_STAT * buf)788 static __inline__ int set_parameters(int fd, struct floppy_struct *floppy,
789 				     struct MT_STAT *buf)
790 {
791 	if ( ( MINOR(buf->st_rdev ) & 0x7f ) > 3 )
792 		return 1;
793 
794 	return ioctl(fd, FDSETPRM, floppy);
795 }
796 
get_parameters(int fd,struct floppy_struct * floppy)797 static __inline__ int get_parameters(int fd, struct floppy_struct *floppy)
798 {
799 	return ioctl(fd, FDGETPRM, floppy);
800 }
801 
802 #include "linux/hdreg.h"
803 #include "linux/fs.h"
804 
ulong_to_sectors(unsigned long raw_sect)805 static uint32_t ulong_to_sectors(unsigned long raw_sect) {
806 	/* Number of sectors must fit into 32bit value */
807 	if (raw_sect > ULONG_MAX) {
808 		fprintf(stderr, "Too many sectors for FAT %8lx\n",raw_sect);
809 		exit(1);
810 	}
811 	return (uint32_t) raw_sect;
812 }
813 
get_sector_size(int fd)814 int get_sector_size(int fd) {
815 	int sec_size;
816 	if (ioctl(fd, BLKSSZGET, &sec_size) != 0 || sec_size <= 0) {
817 		fprintf(stderr, "Could not get sector size of device (%s)",
818 			strerror(errno));
819 		return -1;
820 	}
821 
822 	/* Cap sector size at 4096 */
823 	if(sec_size > 4096)
824 		sec_size = 4096;
825 	return sec_size;
826 }
827 
get_block_geom(int fd,struct device * dev)828 static int get_block_geom(int fd, struct device *dev) {
829 	struct hd_geometry geom;
830 	int sec_size;
831 	unsigned long size;
832 	uint16_t heads=dev->heads;
833 	uint16_t sectors=dev->sectors;
834 	uint32_t sect_per_track;
835 
836 	if (ioctl(fd, HDIO_GETGEO, &geom) < 0) {
837 		fprintf(stderr, "Could not get geometry of device (%s)",
838 			strerror(errno));
839 		return -1;
840 	}
841 
842 	if (ioctl(fd, BLKGETSIZE, &size) < 0) {
843 		fprintf(stderr, "Could not get size of device (%s)",
844 			strerror(errno));
845 		return -1;
846 	}
847 
848 	sec_size = get_sector_size(fd);
849 	if(sec_size < 0)
850 		return -1;
851 
852 	dev->ssize = 0;
853 	while (dev->ssize < 0x7F && (128 << dev->ssize) < sec_size)
854 		dev->ssize++;
855 
856 	if(!heads)
857 		heads = geom.heads;
858 	if(!sectors)
859 		sectors = geom.sectors;
860 
861 	sect_per_track = heads * sectors;
862 	if(!dev->hidden) {
863 		uint32_t hidden;
864 		hidden = geom.start % sect_per_track;
865 		if(hidden && hidden != sectors) {
866 			fprintf(stderr,
867 				"Hidden (%d) does not match sectors (%d)\n",
868 				hidden, sectors);
869 			return -1;
870 		}
871 		dev->hidden = hidden;
872 	}
873 	dev->heads = heads;
874 	dev->sectors = sectors;
875 	if(!dev->tracks)
876 		dev->tracks = ulong_to_sectors((size + dev->hidden % sect_per_track) / sect_per_track);
877 	return 0;
878 }
879 
880 #define HAVE_GET_BLOCK_GEOM
881 
882 #endif /* linux */
883 
884 
885 /* OS/2, gcc+emx */
886 #ifdef __EMX__
887 #define predefined_devices
888 struct device devices[] = {
889   {"A:", 'A', GENFD},
890   {"B:", 'B', GENFD},
891 };
892 #define INIT_NOOP
893 #endif
894 
895 
896 
897 /*** /jes -- for D.O.S. 486 BL DX2/80 ***/
898 /*** Jean-Marc Zucconi <[email protected]> 2001/03/30 ***/
899 #ifdef OS_freebsd
900 #define predefined_devices
901 struct device devices[] = {
902 	{"/dev/fd0.1440", 'A', FHD312},
903 	{"/dev/fd0.720",  'A', FDD312},
904 	{"/dev/fd1.1200", 'B', MHD514},
905 	{"/dev/sd0s1",     'C', GENHD},
906 	REMOTE
907 };
908 #endif /* __FreeBSD__ */
909 
910 /*** /jes -- for ALR 486 DX4/100 ***/
911 #if defined(OS_netbsd) || defined(OS_netbsdelf)
912 #define predefined_devices
913 struct device devices[] = {
914 	{"/dev/rfd0a", 'A', FHD312},
915 	{"/dev/rfd0f", 'A', FDD312},
916 	{"/dev/rfd0f", 'S', MDD312},
917 	{"/dev/rfd1a", 'B', FHD514},
918 	{"/dev/rfd1d", 'B', FDD514},
919 	{"/dev/rfd1d", 'T', MDD514},
920 	{"/dev/rwd0d", 'C', 16, 0, 0, 0, 0, 0, 63L*512L, DEF_ARG0(0)},
921 	REMOTE
922 };
923 #endif /* OS_NetBSD */
924 
925 /* [email protected] 2000/05/19 */
926 #if defined(OS_openbsd)
927 #define predefined_devices
928 struct device devices[] = {
929 	{"/dev/rfd0Bc", 'A', FHD312},
930 	{"/dev/rfd0Fc", 'A', FDD312},
931 	{"/dev/rfd1Cc", 'B', FHD514},
932 	{"/dev/rfd1Dc", 'B', FDD514},
933 	{"/dev/rwd0c", 'C', 16, 0, 0, 0, 0, 0, 63L*512L, DEF_ARG0(0)},
934 	REMOTE
935 };
936 #endif /* OS_openbsd */
937 
938 
939 
940 #if (!defined(predefined_devices) && defined (CPU_m68000) && defined (OS_sysv))
941 #include <sys/gdioctl.h>
942 
943 #define predefined_devices
944 struct device devices[] = {
945 	{"/dev/rfp020",		'A', 12,O_NDELAY,40,2, 9, 0, MDEF_ARG},
946 	{"/usr/bin/DOS/dvd000", 'C', GENFD},
947 	REMOTE
948 };
949 
950 #undef INIT_NOOP
init_geom(int fd,struct device * dev,struct device * orig_dev,struct MT_STAT * statbuf)951 int init_geom(int fd, struct device *dev, struct device *orig_dev,
952 	      struct MT_STAT *statbuf)
953 {
954 	struct gdctl gdbuf;
955 
956 	if (ioctl(fd, GDGETA, &gdbuf) == -1) {
957 		ioctl(fd, GDDISMNT, &gdbuf);
958 		return 1;
959 	}
960 	if((dev->use_2m & 0x7f) || (dev->ssize & 0x7f))
961 		return 1;
962 
963 	SET_INT(gdbuf.params.cyls,dev->ntracks);
964 	SET_INT(gdbuf.params.heads,dev->nheads);
965 	SET_INT(gdbuf.params.psectrk,dev->nsect);
966 	dev->ntracks = gdbuf.params.cyls;
967 	dev->nheads = gdbuf.params.heads;
968 	dev->nsect = gdbuf.params.psectrk;
969 	dev->use_2m = 0x80;
970 	dev->ssize = 0x02;
971 
972 	gdbuf.params.pseccyl = gdbuf.params.psectrk * gdbuf.params.heads;
973 	gdbuf.params.flags = 1;		/* disk type flag */
974 	gdbuf.params.step = 0;		/* step rate for controller */
975 	gdbuf.params.sectorsz = 512;	/* sector size */
976 
977 	if (ioctl(fd, GDSETA, &gdbuf) < 0) {
978 		ioctl(fd, GDDISMNT, &gdbuf);
979 		return(1);
980 	}
981 	return(0);
982 }
983 #endif /* (defined (m68000) && defined (sysv))*/
984 
985 #ifdef CPU_alpha
986 #ifndef OS_osf4
987 #ifdef __osf__
988 #include <sys/fcntl.h>
989 #define predefined_devices
990 struct device devices[] = {
991 	{"/dev/rfd0c",		'A', GENFD},
992 	REMOTE
993 };
994 #endif
995 #endif
996 #endif
997 
998 #ifdef OS_osf
999 #ifndef predefined_devices
1000 #define predefined_devices
1001 struct device devices[] = {
1002 	{"/dev/fd0a", 'A',  MHD312 } };
1003 	REMOTE
1004 #endif
1005 #endif
1006 
1007 
1008 #ifdef OS_nextstep
1009 #define predefined_devices
1010 struct device devices[] = {
1011 #ifdef CPU_m68k
1012 	{"/dev/rfd0b", 'A', MED312 },
1013 	REMOTE
1014 #else
1015 	{"/dev/rfd0b", 'A', MHD312 },
1016 	REMOTE
1017 #endif
1018 };
1019 #endif
1020 
1021 
1022 #if (!defined(predefined_devices) && defined(OS_sysv4))
1023 #ifdef __uxp__
1024 #define predefined_devices
1025 struct device devices[] = {
1026       {"/dev/fpd0",   'A', FHD312},
1027       {"/dev/fpd0",   'A', FDD312},
1028 	  REMOTE
1029 };
1030 #else
1031 #define predefined_devices
1032 struct device devices[] = {
1033 	{"/dev/rdsk/f1q15dt",	'B', FHD514},
1034 	{"/dev/rdsk/f1d9dt",	'B', FDD514},
1035 	{"/dev/rdsk/f1d8dt",	'B', FDDsmall},
1036 	{"/dev/rdsk/f03ht",	'A', FHD312},
1037 	{"/dev/rdsk/f03dt",	'A', FDD312},
1038 	{"/dev/rdsk/dos",	'C', GENHD},
1039 	REMOTE
1040 };
1041 #endif
1042 #endif /* sysv4 */
1043 
1044 #ifdef OS_mingw32msvc
1045 #define predefined_devices
1046 struct device devices[] = {
1047    {"\\\\.\\A:", 'A', GENFD },
1048 };
1049 #endif
1050 
1051 #ifdef INIT_GENERIC
1052 
1053 #ifndef USE_2M
1054 #define USE_2M(x) 0x80
1055 #endif
1056 
1057 #ifndef SSIZE
1058 #define SSIZE(x) 0x02
1059 #endif
1060 
1061 #ifndef SET_2M
1062 #define SET_2M(x,y) return -1
1063 #endif
1064 
1065 #ifndef SET_SSIZE
1066 #define SET_SSIZE(x,y) return -1
1067 #endif
1068 
1069 #undef INIT_NOOP
init_geom(int fd,struct device * dev,struct device * orig_dev,struct MT_STAT * statbuf)1070 int init_geom(int fd, struct device *dev, struct device *orig_dev,
1071 	      struct MT_STAT *statbuf)
1072 {
1073 	struct generic_floppy_struct floppy;
1074 	int change;
1075 
1076 #ifdef HAVE_GET_BLOCK_GEOM
1077 	/**
1078 	 * Block device which *isn't* a floppy device
1079 	 */
1080 	if (S_ISBLK(statbuf->st_mode) &&
1081 	    major(statbuf->st_rdev) != BLOCK_MAJOR) {
1082 		get_block_geom(fd, dev);
1083 		return compare_geom(dev, orig_dev);
1084 	}
1085 #endif
1086 
1087 	/*
1088 	 * succeed if we don't have a floppy
1089 	 * this is the case for dosemu floppy image files for instance
1090 	 */
1091 	if (!((S_ISBLK(statbuf->st_mode) &&
1092 	       major(statbuf->st_rdev) == BLOCK_MAJOR)
1093 #ifdef CHAR_MAJOR
1094 	      || (S_ISCHR(statbuf->st_mode) &&
1095 		  major(statbuf->st_rdev) == CHAR_MAJOR)
1096 #endif
1097 		))
1098 		return compare_geom(dev, orig_dev);
1099 
1100 	/*
1101 	 * We first try to get the current floppy parameters from the kernel.
1102 	 * This allows us to
1103 	 * 1. get the rate
1104 	 * 2. skip the parameter setting if the parameters are already o.k.
1105 	 */
1106 
1107 	if (get_parameters( fd, & floppy ) )
1108 		/*
1109 		 * autodetection failure.
1110 		 * This mostly occurs because of an absent or unformatted disks.
1111 		 *
1112 		 * It might also occur because of bizarre formats (for example
1113 		 * rate 1 on a 3 1/2 disk).
1114 
1115 		 * If this is the case, the user should do an explicit
1116 		 * setfdprm before calling mtools
1117 		 *
1118 		 * Another cause might be pre-existing wrong parameters. The
1119 		 * user should do an setfdprm -c to repair this situation.
1120 		 *
1121 		 * ...fail immediately... ( Theoretically, we could try to save
1122 		 * the situation by trying out all rates, but it would be slow
1123 		 * and awkward)
1124 		 */
1125 		return 1;
1126 
1127 
1128 	/*
1129 	 * if we have already have the correct parameters, keep them.
1130 	 * the number of tracks doesn't need to match exactly, it may be bigger.
1131 	 * the number of heads and sectors must match exactly, to avoid
1132 	 * miscalculation of the location of a block on the disk
1133 	 */
1134 	change = 0;
1135 	if(compare(dev->sectors, SECTORS(floppy))){
1136 		SECTORS(floppy) = dev->sectors;
1137 		change = 1;
1138 	} else
1139 		dev->sectors = (uint16_t) SECTORS(floppy);
1140 
1141 	if(compare(dev->heads, HEADS(floppy))){
1142 		HEADS(floppy) = dev->heads;
1143 		change = 1;
1144 	} else
1145 		dev->heads = (uint16_t) HEADS(floppy);
1146 
1147 	if(compare(dev->tracks, (unsigned int) TRACKS(floppy))){
1148 		TRACKS(floppy) = dev->tracks;
1149 		change = 1;
1150 	} else
1151 		dev->tracks = TRACKS(floppy);
1152 
1153 
1154 	if(compare(dev->use_2m, USE_2M(floppy))){
1155 		SET_2M(&floppy, dev->use_2m);
1156 		change = 1;
1157 	} else
1158 		dev->use_2m = USE_2M(floppy);
1159 
1160 	if( ! (dev->ssize & 0x80) )
1161 		dev->ssize = 0;
1162 	if(compare(dev->ssize, SSIZE(floppy) + 128)){
1163 		SET_SSIZE(&floppy, dev->ssize);
1164 		change = 1;
1165 	} else
1166 		dev->ssize = SSIZE(floppy);
1167 
1168 	if(!change)
1169 		/* no change, succeed */
1170 		return 0;
1171 
1172 #ifdef SECTORS_PER_TRACK
1173 	SECTORS_PER_TRACK(floppy) = dev->sectors * dev->heads;
1174 #endif
1175 
1176 #ifdef SECTORS_PER_DISK
1177 	SECTORS_PER_DISK(floppy) = dev->sectors * dev->heads * dev->tracks;
1178 #endif
1179 
1180 #ifdef STRETCH
1181 	/* ... and the stretch */
1182 	if ( dev->tracks > 41 )
1183 		STRETCH(floppy) = 0;
1184 	else
1185 		STRETCH(floppy) = 1;
1186 #endif
1187 
1188 	return set_parameters( fd, &floppy, statbuf);
1189 }
1190 #endif /* INIT_GENERIC */
1191 
1192 #ifdef INIT_NOOP
init_geom(int fd,struct device * dev,struct device * orig_dev,struct MT_STAT * statbuf)1193 int init_geom(int fd, struct device *dev, struct device *orig_dev,
1194 			  struct MT_STAT *statbuf)
1195 {
1196 	return compare_geom(dev, orig_dev);
1197 }
1198 #endif
1199 
1200 #ifdef predefined_devices
1201 const unsigned int nr_const_devices = sizeof(const_devices) / sizeof(*const_devices);
1202 #else
1203 struct device devices[]={
1204 	{"/dev/fd0", 'A', 0, O_EXCL, 0,0, 0,0, MDEF_ARG},
1205 	/* to shut up Ultrix's native compiler, we can't make this empty :( */
1206 };
1207 const unsigned int nr_const_devices = 0;
1208 #endif
1209