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