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)}
70
71
72
73#if defined(INIT_GENERIC) || defined(INIT_NOOP)
74static 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
91struct device devices[] = {
92   {"\\\\\\\\.\\\\A:", 'A', GENFD },
93};
94#endif /* CYGWIN */
95
96
97#ifdef OS_aux
98#define predefined_devices
99struct 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
110struct device devices[] = {
111	{"/dev/fd1440.0", 	'A', MHD312 },
112	REMOTE
113};
114#endif
115
116
117#ifdef __BEOS__
118#define predefined_devices
119struct 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
129struct 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
159struct generic_floppy_struct
160{
161  struct floppy_geometry fg;
162};
163
164#define BLOCK_MAJOR 24
165#define CHAR_MAJOR 112
166
167static 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
183static 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
201struct 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
221struct 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))
233struct 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) */
246struct 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
261int ioctl(int, int, void *);
262
263static 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
290static 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
302struct 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
311struct 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
321struct 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
332char *alias_name = NULL;
333
334extern char *media_oldaliases(char *);
335extern char *media_findname(char *);
336
337char *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
366struct 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
392struct generic_floppy_struct
393{
394  struct fd_char fdchar;
395};
396
397#define BLOCK_MAJOR 36
398#define CHAR_MAJOR 36
399
400static 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
417static 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
432struct 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
441struct 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
453struct 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
468struct 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
483struct 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
499struct 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
508static 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
531static 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
553struct 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
566struct 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
579const 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",
5870,
588
589"Missing Address Mark",
590"Write Protect",
591"No Data - unreadable",
5920,
593"OverRun",
594"CRC error in data or address",
5950,
596"End Of Cylinder",
597
5980,
5990,
6000,
601"Not ready",
602"Equipment check error",
603"Seek end" };
604
605
606static __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
638int 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
674int 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
732struct device devices[] = {
733	{"/dev/fd0", 'A', 0, 0, 80,2, 18,0, MDEF_ARG},
734	{"/dev/fd1", 'B', 0, 0, 0,0, 0,0, FDEF_ARG},
735	/* we assume that the Zip or Jaz drive is the second on the SCSI bus */
736	{"/dev/sdb4",'J', GENHD },
737	{"/dev/sdb4",'Z', GENHD },
738	/*	{"/dev/sda4",'D', GENHD },*/
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
761static __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
771static __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
780static __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
789static __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
800struct 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
813struct 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
825struct 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
840struct 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
856struct 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
863int 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
902struct 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
913struct device devices[] = {
914	{"/dev/fd0a", 'A',  MHD312 } };
915	REMOTE
916#endif
917#endif
918
919
920#ifdef OS_nextstep
921#define predefined_devices
922struct 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
937struct device devices[] = {
938      {"/dev/fpd0",   'A', FHD312},
939      {"/dev/fpd0",   'A', FDD312},
940	  REMOTE
941};
942#else
943#define predefined_devices
944struct 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
958struct device devices[] = {};
959#endif
960
961#ifdef INIT_GENERIC
962
963#ifndef USE_2M
964#define USE_2M(x) 0x80
965#endif
966
967#ifndef SSIZE
968#define SSIZE(x) 0x82
969#endif
970
971#ifndef SET_2M
972#define SET_2M(x,y) return -1
973#endif
974
975#ifndef SET_SSIZE
976#define SET_SSIZE(x,y) return -1
977#endif
978
979#undef INIT_NOOP
980int init_geom(int fd, struct device *dev, struct device *orig_dev,
981	      struct MT_STAT *statbuf)
982{
983	struct generic_floppy_struct floppy;
984	int change;
985
986	/*
987	 * succeed if we don't have a floppy
988	 * this is the case for dosemu floppy image files for instance
989	 */
990	if (!((S_ISBLK(statbuf->st_mode) &&
991	       major(statbuf->st_rdev) == BLOCK_MAJOR)
992#ifdef CHAR_MAJOR
993	      || (S_ISCHR(statbuf->st_mode) &&
994		  major(statbuf->st_rdev) == CHAR_MAJOR)
995#endif
996		))
997		return compare_geom(dev, orig_dev);
998
999	/*
1000	 * We first try to get the current floppy parameters from the kernel.
1001	 * This allows us to
1002	 * 1. get the rate
1003	 * 2. skip the parameter setting if the parameters are already o.k.
1004	 */
1005
1006	if (get_parameters( fd, & floppy ) )
1007		/*
1008		 * autodetection failure.
1009		 * This mostly occurs because of an absent or unformatted disks.
1010		 *
1011		 * It might also occur because of bizarre formats (for example
1012		 * rate 1 on a 3 1/2 disk).
1013
1014		 * If this is the case, the user should do an explicit
1015		 * setfdprm before calling mtools
1016		 *
1017		 * Another cause might be pre-existing wrong parameters. The
1018		 * user should do an setfdprm -c to repair this situation.
1019		 *
1020		 * ...fail immediately... ( Theoretically, we could try to save
1021		 * the situation by trying out all rates, but it would be slow
1022		 * and awkward)
1023		 */
1024		return 1;
1025
1026
1027	/*
1028	 * if we have already have the correct parameters, keep them.
1029	 * the number of tracks doesn't need to match exactly, it may be bigger.
1030	 * the number of heads and sectors must match exactly, to avoid
1031	 * miscalculation of the location of a block on the disk
1032	 */
1033	change = 0;
1034	if(compare(dev->sectors, SECTORS(floppy))){
1035		SECTORS(floppy) = dev->sectors;
1036		change = 1;
1037	} else
1038		dev->sectors = SECTORS(floppy);
1039
1040	if(compare(dev->heads, HEADS(floppy))){
1041		HEADS(floppy) = dev->heads;
1042		change = 1;
1043	} else
1044		dev->heads = HEADS(floppy);
1045
1046	if(compare(dev->tracks, TRACKS(floppy))){
1047		TRACKS(floppy) = dev->tracks;
1048		change = 1;
1049	} else
1050		dev->tracks = TRACKS(floppy);
1051
1052
1053	if(compare(dev->use_2m, USE_2M(floppy))){
1054		SET_2M(&floppy, dev->use_2m);
1055		change = 1;
1056	} else
1057		dev->use_2m = USE_2M(floppy);
1058
1059	if( ! (dev->ssize & 0x80) )
1060		dev->ssize = 0;
1061	if(compare(dev->ssize, SSIZE(floppy) + 128)){
1062		SET_SSIZE(&floppy, dev->ssize);
1063		change = 1;
1064	} else
1065		dev->ssize = SSIZE(floppy);
1066
1067	if(!change)
1068		/* no change, succeed */
1069		return 0;
1070
1071#ifdef SECTORS_PER_TRACK
1072	SECTORS_PER_TRACK(floppy) = dev->sectors * dev->heads;
1073#endif
1074
1075#ifdef SECTORS_PER_DISK
1076	SECTORS_PER_DISK(floppy) = dev->sectors * dev->heads * dev->tracks;
1077#endif
1078
1079#ifdef STRETCH
1080	/* ... and the stretch */
1081	if ( dev->tracks > 41 )
1082		STRETCH(floppy) = 0;
1083	else
1084		STRETCH(floppy) = 1;
1085#endif
1086
1087	return set_parameters( fd, &floppy, statbuf);
1088}
1089#endif /* INIT_GENERIC */
1090
1091#ifdef INIT_NOOP
1092int init_geom(int fd, struct device *dev, struct device *orig_dev,
1093			  struct MT_STAT *statbuf)
1094{
1095	return compare_geom(dev, orig_dev);
1096}
1097#endif
1098
1099#ifdef predefined_devices
1100const int nr_const_devices = sizeof(const_devices) / sizeof(*const_devices);
1101#else
1102struct device devices[]={
1103	{"/dev/fd0", 'A', 0, O_EXCL, 0,0, 0,0, MDEF_ARG},
1104	/* to shut up Ultrix's native compiler, we can't make this empty :( */
1105};
1106const int nr_const_devices = 0;
1107#endif
1108