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