Initial import package mtools: Programs for accessing MS-DOS disks without mounting...
[profile/ivi/mtools.git] / devices.c
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)
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
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
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
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
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
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
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
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
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
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 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
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
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
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},
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
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
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
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
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
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
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
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 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 int nr_const_devices = 0;
1109 #endif