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