| /* Copyright 1986-1992 Emmet P. Gray. |
| * Copyright 1996-2003,2006,2007,2009 Alain Knaff. |
| * This file is part of mtools. |
| * |
| * Mtools is free software: you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation, either version 3 of the License, or |
| * (at your option) any later version. |
| * |
| * Mtools is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with Mtools. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| /* |
| * Device tables. See the Configure file for a complete description. |
| */ |
| |
| #define NO_TERMIO |
| #include "sysincludes.h" |
| #include "msdos.h" |
| #include "mtools.h" |
| #include "devices.h" |
| |
| #define INIT_NOOP |
| |
| #define DEF_ARG1(x) (x), 0x2,0,(char *)0, 0, 0 |
| #define DEF_ARG0(x) 0,DEF_ARG1(x) |
| |
| #define MDEF_ARG 0L,DEF_ARG0(MFORMAT_ONLY_FLAG) |
| #define FDEF_ARG 0L,DEF_ARG0(0) |
| #define VOLD_DEF_ARG 0L,DEF_ARG0(VOLD_FLAG|MFORMAT_ONLY_FLAG) |
| |
| #define MED312 12,0,80,2,36,0,MDEF_ARG /* 3 1/2 extra density */ |
| #define MHD312 12,0,80,2,18,0,MDEF_ARG /* 3 1/2 high density */ |
| #define MDD312 12,0,80,2, 9,0,MDEF_ARG /* 3 1/2 double density */ |
| #define MHD514 12,0,80,2,15,0,MDEF_ARG /* 5 1/4 high density */ |
| #define MDD514 12,0,40,2, 9,0,MDEF_ARG /* 5 1/4 double density (360k) */ |
| #define MSS514 12,0,40,1, 9,0,MDEF_ARG /* 5 1/4 single sided DD, (180k) */ |
| #define MDDsmall 12,0,40,2, 8,0,MDEF_ARG /* 5 1/4 double density (320k) */ |
| #define MSSsmall 12,0,40,1, 8,0,MDEF_ARG /* 5 1/4 single sided DD, (160k) */ |
| |
| #define FED312 12,0,80,2,36,0,FDEF_ARG /* 3 1/2 extra density */ |
| #define FHD312 12,0,80,2,18,0,FDEF_ARG /* 3 1/2 high density */ |
| #define FDD312 12,0,80,2, 9,0,FDEF_ARG /* 3 1/2 double density */ |
| #define FHD514 12,0,80,2,15,0,FDEF_ARG /* 5 1/4 high density */ |
| #define FDD514 12,0,40,2, 9,0,FDEF_ARG /* 5 1/4 double density (360k) */ |
| #define FSS514 12,0,40,1, 9,0,FDEF_ARG /* 5 1/4 single sided DD, (180k) */ |
| #define FDDsmall 12,0,40,2, 8,0,FDEF_ARG /* 5 1/4 double density (320k) */ |
| #define FSSsmall 12,0,40,1, 8,0,FDEF_ARG /* 5 1/4 single sided DD, (160k) */ |
| |
| #define GENHD 16,0, 0,0, 0,0,MDEF_ARG /* Generic 16 bit FAT fs */ |
| #define GENFD 12,0,80,2,18,0,MDEF_ARG /* Generic 12 bit FAT fs */ |
| #define VOLDFD 12,0,80,2,18,0,VOLD_DEF_ARG /* Generic 12 bit FAT fs with vold */ |
| #define GEN 0,0, 0,0, 0,0,MDEF_ARG /* Generic fs of any FAT bits */ |
| |
| #define ZIPJAZ(x,c,h,s,y) 16,(x),(c),(h),(s),(s),0L, 4, \ |
| DEF_ARG1((y)|MFORMAT_ONLY_FLAG) /* Jaz disks */ |
| |
| #define JAZ(x) ZIPJAZ(x,1021, 64, 32, 0) |
| #define RJAZ(x) ZIPJAZ(x,1021, 64, 32, SCSI_FLAG|PRIV_FLAG) |
| #define ZIP(x) ZIPJAZ(x,96, 64, 32, 0) |
| #define RZIP(x) ZIPJAZ(x,96, 64, 32, SCSI_FLAG|PRIV_FLAG) |
| |
| #define REMOTE {"$DISPLAY", 'X', 0,0, 0,0, 0,0,0L, DEF_ARG0(FLOPPYD_FLAG),0,0} |
| |
| |
| |
| #if defined(INIT_GENERIC) || defined(INIT_NOOP) |
| static int compare_geom(struct device *dev, struct device *orig_dev) |
| { |
| if(IS_MFORMAT_ONLY(orig_dev)) |
| return 0; /* geometry only for mformatting ==> ok */ |
| if(!orig_dev || !orig_dev->tracks || !dev || !dev->tracks) |
| return 0; /* no original device. This is ok */ |
| return(orig_dev->tracks != dev->tracks || |
| orig_dev->heads != dev->heads || |
| orig_dev->sectors != dev->sectors); |
| } |
| #endif |
| |
| #define devices const_devices |
| |
| |
| #ifdef __CYGWIN__ |
| #define predefined_devices |
| struct device devices[] = { |
| {"\\\\\\\\.\\\\A:", 'A', GENFD }, |
| }; |
| #endif /* CYGWIN */ |
| |
| |
| #ifdef OS_aux |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/floppy0", 'A', GENFD }, |
| {"/dev/rdsk/c104d0s31", 'J', JAZ(O_EXCL) }, |
| {"/dev/rdsk/c105d0s31", 'Z', ZIP(O_EXCL) }, |
| REMOTE |
| }; |
| #endif /* aux */ |
| |
| |
| #ifdef OS_lynxos |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/fd1440.0", 'A', MHD312 }, |
| REMOTE |
| }; |
| #endif |
| |
| |
| #ifdef __BEOS__ |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/disk/floppy/raw", 'A', MHD312 }, |
| REMOTE |
| }; |
| #endif /* BEBOX */ |
| |
| |
| #ifdef OS_hpux |
| |
| #define predefined_devices |
| struct device devices[] = { |
| #ifdef OS_hpux10 |
| /* hpux10 uses different device names according to Frank Maritato |
| * <frank@math.hmc.edu> */ |
| {"/dev/floppy/c0t0d0", 'A', MHD312 }, |
| {"/dev/floppy/c0t0d1", 'B', MHD312 }, /* guessed by me */ |
| {"/dev/rscsi", 'C', GENHD }, /* guessed by me */ |
| #else |
| /* Use rfloppy, according to Simao Campos <simao@iris.ctd.comsat.com> */ |
| {"/dev/rfloppy/c201d0s0", 'A', FHD312 }, |
| {"/dev/rfloppy/c20Ad0s0", 'A', FHD312 }, |
| {"/dev/rfloppy/c201d1s0", 'B', FHD312 }, |
| {"/dev/rfloppy/c20Ad1s0", 'B', FHD312 }, |
| {"/dev/rscsi", 'C', GENHD }, |
| #endif |
| {"/dev/rdsk/c201d4", 'J', RJAZ(O_EXCL) }, |
| {"/dev/rdsk/c201d4s0", 'J', RJAZ(O_EXCL) }, |
| {"/dev/rdsk/c201d5", 'Z', RZIP(O_EXCL) }, |
| {"/dev/rdsk/c201d5s0", 'Z', RZIP(O_EXCL) }, |
| REMOTE |
| }; |
| |
| #ifdef HAVE_SYS_FLOPPY |
| /* geometry setting ioctl's contributed by Paolo Zeppegno |
| * <paolo@to.sem.it>, may cause "Not a typewriter" messages on other |
| * versions according to support@vital.com */ |
| |
| #include <sys/floppy.h> |
| #undef SSIZE |
| |
| struct generic_floppy_struct |
| { |
| struct floppy_geometry fg; |
| }; |
| |
| #define BLOCK_MAJOR 24 |
| #define CHAR_MAJOR 112 |
| |
| static inline int get_parameters(int fd, struct generic_floppy_struct *floppy) |
| { |
| if (ioctl(fd, FLOPPY_GET_GEOMETRY, &(floppy->fg)) != 0) { |
| perror("FLOPPY_GET_GEOMETRY"); |
| return(1); |
| } |
| |
| return 0; |
| } |
| |
| #define TRACKS(floppy) floppy.fg.tracks |
| #define HEADS(floppy) floppy.fg.heads |
| #define SECTORS(floppy) floppy.fg.sectors |
| #define FD_SECTSIZE(floppy) floppy.fg.sector_size |
| #define FD_SET_SECTSIZE(floppy,v) { floppy.fg.sector_size = v; } |
| |
| static inline int set_parameters(int fd, struct generic_floppy_struct *floppy, |
| struct MT_STAT *buf) |
| { |
| if (ioctl(fd, FLOPPY_SET_GEOMETRY, &(floppy->fg)) != 0) { |
| perror(""); |
| return(1); |
| } |
| |
| return 0; |
| } |
| #define INIT_GENERIC |
| #endif |
| |
| #endif /* hpux */ |
| |
| |
| #if (defined(OS_sinix) || defined(VENDOR_sni) || defined(SNI)) |
| #define predefined_devices |
| struct device devices[] = { |
| #ifdef CPU_mips /* for Siemens Nixdorf's SINIX-N/O (mips) 5.4x SVR4 */ |
| { "/dev/at/flp/f0t", 'A', FHD312}, |
| { "/dev/fd0", 'A', GENFD}, |
| #else |
| #ifdef CPU_i386 /* for Siemens Nixdorf's SINIX-D/L (intel) 5.4x SVR4 */ |
| { "/dev/fd0135ds18", 'A', FHD312}, |
| { "/dev/fd0135ds9", 'A', FDD312}, |
| { "/dev/fd0", 'A', GENFD}, |
| { "/dev/fd1135ds15", 'B', FHD514}, |
| { "/dev/fd1135ds9", 'B', FDD514}, |
| { "/dev/fd1", 'B', GENFD}, |
| #endif /* CPU_i386 */ |
| #endif /*mips*/ |
| REMOTE |
| }; |
| #endif |
| |
| #ifdef OS_ultrix |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/rfd0a", 'A', GENFD}, /* guessed */ |
| {"/dev/rfd0c", 'A', GENFD}, /* guessed */ |
| REMOTE |
| }; |
| |
| #endif |
| |
| |
| #ifdef OS_isc |
| #define predefined_devices |
| #if (defined(OS_isc2) && defined(OLDSTUFF)) |
| struct device devices[] = { |
| {"/dev/rdsk/f0d9dt", 'A', FDD514}, |
| {"/dev/rdsk/f0q15dt", 'A', FHD514}, |
| {"/dev/rdsk/f0d8dt", 'A', FDDsmall}, |
| {"/dev/rdsk/f13ht", 'B', FHD312}, |
| {"/dev/rdsk/f13dt", 'B', FDD312}, |
| {"/dev/rdsk/0p1", 'C', GENHD}, |
| {"/usr/vpix/defaults/C:",'D',12, 0, 0, 0, 0,8704L,DEF_ARG0}, |
| {"$HOME/vpix/C:", 'E', 12, 0, 0, 0, 0,8704L,MDEF_ARG}, |
| REMOTE |
| }; |
| #else |
| /* contributed by larry.jones@sdrc.com (Larry Jones) */ |
| struct device devices[] = { |
| {"/dev/rfd0", 'A', GEN}, |
| {"/dev/rfd1", 'B', GEN}, |
| {"/dev/rdsk/0p1", 'C', GEN}, |
| {"/usr/vpix/defaults/C:",'D', GEN, 1}, |
| {"$HOME/vpix/C:", 'E', GEN, 1}, |
| REMOTE |
| }; |
| |
| #include <sys/vtoc.h> |
| #include <sys/sysmacros.h> |
| #undef SSIZE |
| #define BLOCK_MAJOR 1 |
| #define CHAR_MAJOR 1 |
| #define generic_floppy_struct disk_parms |
| int ioctl(int, int, void *); |
| |
| static int get_parameters(int fd, struct generic_floppy_struct *floppy) |
| { |
| mt_off_t off; |
| char buf[512]; |
| |
| off = lseek(fd, 0, SEEK_CUR); |
| if(off < 0) { |
| perror("device seek 1"); |
| exit(1); |
| } |
| if (off == 0) { |
| /* need to read at least 1 sector to get correct info */ |
| read(fd, buf, sizeof buf); |
| if(lseek(fd, 0, SEEK_SET) < 0) { |
| perror("device seek 2"); |
| exit(1); |
| } |
| } |
| return ioctl(fd, V_GETPARMS, floppy); |
| } |
| |
| #define TRACKS(floppy) (floppy).dp_cyls |
| #define HEADS(floppy) (floppy).dp_heads |
| #define SECTORS(floppy) (floppy).dp_sectors |
| #define FD_SECTSIZE(floppy) (floppy).dp_secsiz |
| #define FD_SET_SECTSIZE(floppy,v) { (floppy).dp_secsiz = (v); } |
| |
| static int set_parameters(int fd, struct generic_floppy_struct *floppy, |
| struct MT_STAT *buf) |
| { |
| return 1; |
| } |
| |
| #define INIT_GENERIC |
| #endif |
| #endif /* isc */ |
| |
| #ifdef CPU_i370 |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/rfd0", 'A', GENFD}, |
| REMOTE |
| }; |
| #endif /* CPU_i370 */ |
| |
| #ifdef OS_aix |
| /* modified by Federico Bianchi */ |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/fd0",'A',GENFD}, |
| REMOTE |
| }; |
| #endif /* aix */ |
| |
| |
| #ifdef OS_osf4 |
| /* modified by Chris Samuel <chris@rivers.dra.hmg.gb> */ |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/fd0c",'A',GENFD}, |
| REMOTE |
| }; |
| #endif /* OS_osf4 */ |
| |
| |
| #ifdef OS_solaris |
| |
| #ifdef USING_NEW_VOLD |
| |
| char *alias_name = NULL; |
| |
| extern char *media_oldaliases(char *); |
| extern char *media_findname(char *); |
| |
| char *getVoldName(struct device *dev, char *name) |
| { |
| char *rname; |
| |
| if(!SHOULD_USE_VOLD(dev)) |
| return name; |
| |
| /*** |
| * Solaris specific routines to use the volume management |
| * daemon and libraries to get the correct device name... |
| ***/ |
| rname = media_findname(name); |
| #ifdef HAVE_MEDIA_OLDALIASES |
| if (rname == NULL) { |
| if ((alias_name = media_oldaliases(name)) != NULL) |
| rname = media_findname(alias_name); |
| } |
| #endif |
| if (rname == NULL) { |
| fprintf(stderr, |
| "No such volume or no media in device: %s.\n", |
| name); |
| exit(1); |
| } |
| return rname; |
| } |
| #endif /* USING_NEW_VOLD */ |
| |
| #define predefined_devices |
| struct device devices[] = { |
| #ifdef USING_NEW_VOLD |
| {"floppy", 'A', VOLDFD }, |
| #elif USING_VOLD |
| {"/vol/dev/aliases/floppy0", 'A', GENFD}, |
| {"/dev/rdiskette", 'B', GENFD}, |
| #else /* ! USING_VOLD */ |
| {"/dev/rdiskette", 'A', GENFD}, |
| {"/vol/dev/aliases/floppy0", 'B', GENFD}, |
| #endif /* USING_VOLD */ |
| {"/dev/rdsk/c0t4d0s2", 'J', RJAZ(O_NDELAY)}, |
| {"/dev/rdsk/c0t5d0s2", 'Z', RZIP(O_NDELAY)}, |
| REMOTE |
| }; |
| |
| |
| |
| /* |
| * Ofer Licht <ofer@stat.Berkeley.EDU>, May 14, 1997. |
| */ |
| |
| #define INIT_GENERIC |
| |
| #include <sys/fdio.h> |
| #include <sys/mkdev.h> /* for major() */ |
| |
| struct generic_floppy_struct |
| { |
| struct fd_char fdchar; |
| }; |
| |
| #define BLOCK_MAJOR 36 |
| #define CHAR_MAJOR 36 |
| |
| static inline int get_parameters(int fd, struct generic_floppy_struct *floppy) |
| { |
| if (ioctl(fd, FDIOGCHAR, &(floppy->fdchar)) != 0) { |
| perror(""); |
| ioctl(fd, FDEJECT, NULL); |
| return(1); |
| } |
| return 0; |
| } |
| |
| #define TRACKS(floppy) floppy.fdchar.fdc_ncyl |
| #define HEADS(floppy) floppy.fdchar.fdc_nhead |
| #define SECTORS(floppy) floppy.fdchar.fdc_secptrack |
| /* SECTORS_PER_DISK(floppy) not used */ |
| #define FD_SECTSIZE(floppy) floppy.fdchar.fdc_sec_size |
| #define FD_SET_SECTSIZE(floppy,v) { floppy.fdchar.fdc_sec_size = v; } |
| |
| static inline int set_parameters(int fd, struct generic_floppy_struct *floppy, |
| struct MT_STAT *buf) |
| { |
| if (ioctl(fd, FDIOSCHAR, &(floppy->fdchar)) != 0) { |
| ioctl(fd, FDEJECT, NULL); |
| perror(""); |
| return(1); |
| } |
| return 0; |
| } |
| #define INIT_GENERIC |
| #endif /* solaris */ |
| |
| #ifdef OS_sunos3 |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/rfdl0c", 'A', FDD312}, |
| {"/dev/rfd0c", 'A', FHD312}, |
| REMOTE |
| }; |
| #endif /* OS_sunos3 */ |
| |
| #ifdef OS_xenix |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/fd096ds15", 'A', FHD514}, |
| {"/dev/fd048ds9", 'A', FDD514}, |
| {"/dev/fd1135ds18", 'B', FHD312}, |
| {"/dev/fd1135ds9", 'B', FDD312}, |
| {"/dev/hd0d", 'C', GENHD}, |
| REMOTE |
| }; |
| #endif /* OS_xenix */ |
| |
| #ifdef OS_sco |
| #define predefined_devices |
| struct device devices[] = { |
| { "/dev/fd0135ds18", 'A', FHD312}, |
| { "/dev/fd0135ds9", 'A', FDD312}, |
| { "/dev/fd0", 'A', GENFD}, |
| { "/dev/fd1135ds15", 'B', FHD514}, |
| { "/dev/fd1135ds9", 'B', FDD514}, |
| { "/dev/fd1", 'B', GENFD}, |
| { "/dev/hd0d", 'C', GENHD}, |
| REMOTE |
| }; |
| #endif /* OS_sco */ |
| |
| |
| #ifdef OS_irix |
| #define predefined_devices |
| struct device devices[] = { |
| { "/dev/rdsk/fds0d2.3.5hi", 'A', FHD312}, |
| { "/dev/rdsk/fds0d2.3.5", 'A', FDD312}, |
| { "/dev/rdsk/fds0d2.96", 'A', FHD514}, |
| {"/dev/rdsk/fds0d2.48", 'A', FDD514}, |
| REMOTE |
| }; |
| #endif /* OS_irix */ |
| |
| |
| #ifdef OS_sunos4 |
| #include <sys/ioctl.h> |
| #include <sun/dkio.h> |
| |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/rfd0c", 'A', GENFD}, |
| {"/dev/rsd4c", 'J', RJAZ(O_NDELAY)}, |
| {"/dev/rsd5c", 'Z', RZIP(O_NDELAY)}, |
| REMOTE |
| }; |
| |
| /* |
| * Stuffing back the floppy parameters into the driver allows for gems |
| * like 10 sector or single sided floppies from Atari ST systems. |
| * |
| * Martin Schulz, Universite de Moncton, N.B., Canada, March 11, 1991. |
| */ |
| |
| #define INIT_GENERIC |
| |
| struct generic_floppy_struct |
| { |
| struct fdk_char dkbuf; |
| struct dk_map dkmap; |
| }; |
| |
| #define BLOCK_MAJOR 16 |
| #define CHAR_MAJOR 54 |
| |
| static inline int get_parameters(int fd, struct generic_floppy_struct *floppy) |
| { |
| if (ioctl(fd, DKIOCGPART, &(floppy->dkmap)) != 0) { |
| perror("DKIOCGPART"); |
| ioctl(fd, FDKEJECT, NULL); |
| return(1); |
| } |
| |
| if (ioctl(fd, FDKIOGCHAR, &( floppy->dkbuf)) != 0) { |
| perror(""); |
| ioctl(fd, FDKEJECT, NULL); |
| return(1); |
| } |
| return 0; |
| } |
| |
| #define TRACKS(floppy) floppy.dkbuf.ncyl |
| #define HEADS(floppy) floppy.dkbuf.nhead |
| #define SECTORS(floppy) floppy.dkbuf.secptrack |
| #define SECTORS_PER_DISK(floppy) floppy.dkmap.dkl_nblk |
| #define FD_SECTSIZE(floppy) floppy.dkbuf.sec_size |
| #define FD_SET_SECTSIZE(floppy,v) { floppy.dkbuf.sec_size = v; } |
| |
| static inline int set_parameters(int fd, struct generic_floppy_struct *floppy, |
| struct MT_STAT *buf) |
| { |
| if (ioctl(fd, FDKIOSCHAR, &(floppy->dkbuf)) != 0) { |
| ioctl(fd, FDKEJECT, NULL); |
| perror(""); |
| return(1); |
| } |
| |
| if (ioctl(fd, ( unsigned int) DKIOCSPART, &(floppy->dkmap)) != 0) { |
| ioctl(fd, FDKEJECT, NULL); |
| perror(""); |
| return(1); |
| } |
| return 0; |
| } |
| #define INIT_GENERIC |
| #endif /* sparc && sunos */ |
| |
| |
| #ifdef DPX1000 |
| #define predefined_devices |
| struct device devices[] = { |
| /* [block device]: DPX1000 has /dev/flbm60, DPX2 has /dev/easyfb */ |
| {"/dev/flbm60", 'A', MHD514}; |
| {"/dev/flbm60", 'B', MDD514}, |
| {"/dev/flbm60", 'C', MDDsmall}, |
| {"/dev/flbm60", 'D', MSS}, |
| {"/dev/flbm60", 'E', MSSsmall}, |
| REMOTE |
| }; |
| #endif /* DPX1000 */ |
| |
| #ifdef OS_bosx |
| #define predefined_devices |
| struct device devices[] = { |
| /* [block device]: DPX1000 has /dev/flbm60, DPX2 has /dev/easyfb */ |
| {"/dev/easyfb", 'A', MHD514}, |
| {"/dev/easyfb", 'B', MDD514}, |
| {"/dev/easyfb", 'C', MDDsmall}, |
| {"/dev/easyfb", 'D', MSS}, |
| {"/dev/easyfb", 'E', MSSsmall}, |
| REMOTE |
| }; |
| #endif /* OS_bosx */ |
| |
| #ifdef OS_linux |
| |
| static const char *error_msg[22]={ |
| "Missing Data Address Mark", |
| "Bad cylinder", |
| "Scan not satisfied", |
| "Scan equal hit", |
| "Wrong cylinder", |
| "CRC error in data field", |
| "Control Mark = deleted", |
| 0, |
| |
| "Missing Address Mark", |
| "Write Protect", |
| "No Data - unreadable", |
| 0, |
| "OverRun", |
| "CRC error in data or address", |
| 0, |
| "End Of Cylinder", |
| |
| 0, |
| 0, |
| 0, |
| "Not ready", |
| "Equipment check error", |
| "Seek end" }; |
| |
| |
| static __inline__ void print_message(RawRequest_t *raw_cmd,const char *message) |
| { |
| int i, code; |
| if(!message) |
| return; |
| |
| fprintf(stderr," "); |
| for (i=0; i< raw_cmd->cmd_count; i++) |
| fprintf(stderr,"%2.2x ", |
| (int)raw_cmd->cmd[i] ); |
| fprintf(stderr,"\n"); |
| for (i=0; i< raw_cmd->reply_count; i++) |
| fprintf(stderr,"%2.2x ", |
| (int)raw_cmd->reply[i] ); |
| fprintf(stderr,"\n"); |
| code = (raw_cmd->reply[0] <<16) + |
| (raw_cmd->reply[1] << 8) + |
| raw_cmd->reply[2]; |
| for(i=0; i<22; i++){ |
| if ((code & (1 << i)) && error_msg[i]) |
| fprintf(stderr,"%s\n", |
| error_msg[i]); |
| } |
| } |
| |
| |
| /* return values: |
| * -1: Fatal error, don't bother retrying. |
| * 0: OK |
| * 1: minor error, retry |
| */ |
| |
| int send_one_cmd(int fd, RawRequest_t *raw_cmd, const char *message) |
| { |
| if (ioctl( fd, FDRAWCMD, raw_cmd) >= 0) { |
| if (raw_cmd->reply_count < 7) { |
| fprintf(stderr,"Short reply from FDC\n"); |
| return -1; |
| } |
| return 0; |
| } |
| |
| switch(errno) { |
| case EBUSY: |
| fprintf(stderr, "FDC busy, sleeping for a second\n"); |
| sleep(1); |
| return 1; |
| case EIO: |
| fprintf(stderr,"resetting controller\n"); |
| if(ioctl(fd, FDRESET, 2) < 0){ |
| perror("reset"); |
| return -1; |
| } |
| return 1; |
| default: |
| perror(message); |
| return -1; |
| } |
| } |
| |
| |
| /* |
| * return values |
| * -1: error |
| * 0: OK, last sector |
| * 1: more raw commands follow |
| */ |
| |
| int analyze_one_reply(RawRequest_t *raw_cmd, int *bytes, int do_print) |
| { |
| |
| if(raw_cmd->reply_count == 7) { |
| int end; |
| |
| if (raw_cmd->reply[3] != raw_cmd->cmd[2]) { |
| /* end of cylinder */ |
| end = raw_cmd->cmd[6] + 1; |
| } else { |
| end = raw_cmd->reply[5]; |
| } |
| |
| *bytes = end - raw_cmd->cmd[4]; |
| /* FIXME: over/under run */ |
| *bytes = *bytes << (7 + raw_cmd->cmd[5]); |
| } else |
| *bytes = 0; |
| |
| switch(raw_cmd->reply[0] & 0xc0){ |
| case 0x40: |
| if ((raw_cmd->reply[0] & 0x38) == 0 && |
| (raw_cmd->reply[1]) == 0x80 && |
| (raw_cmd->reply[2]) == 0) { |
| *bytes += 1 << (7 + raw_cmd->cmd[5]); |
| break; |
| } |
| |
| if ( raw_cmd->reply[1] & ST1_WP ){ |
| *bytes = 0; |
| fprintf(stderr, |
| "This disk is write protected\n"); |
| return -1; |
| } |
| if(!*bytes && do_print) |
| print_message(raw_cmd, ""); |
| return -1; |
| case 0x80: |
| *bytes = 0; |
| fprintf(stderr, |
| "invalid command given\n"); |
| return -1; |
| case 0xc0: |
| *bytes = 0; |
| fprintf(stderr, |
| "abnormal termination caused by polling\n"); |
| return -1; |
| default: |
| break; |
| } |
| #ifdef FD_RAW_MORE |
| if(raw_cmd->flags & FD_RAW_MORE) |
| return 1; |
| #endif |
| return 0; |
| } |
| |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/fd0", 'A', 0, 0, 80,2, 18,0, MDEF_ARG, 0, 0}, |
| {"/dev/fd1", 'B', 0, 0, 0,0, 0,0, FDEF_ARG, 0, 0}, |
| /* we assume that the Zip or Jaz drive is the second on the SCSI bus */ |
| {"/dev/sdb4",'J', GENHD, 0, 0 }, |
| {"/dev/sdb4",'Z', GENHD, 0, 0 }, |
| /* {"/dev/sda4",'D', GENHD, 0, 0 },*/ |
| REMOTE |
| }; |
| |
| /* |
| * Stuffing back the floppy parameters into the driver allows for gems |
| * like 21 sector or single sided floppies from Atari ST systems. |
| * |
| * Alain Knaff, Université Joseph Fourier, France, November 12, 1993. |
| */ |
| |
| |
| #define INIT_GENERIC |
| #define generic_floppy_struct floppy_struct |
| #define BLOCK_MAJOR 2 |
| #define SECTORS(floppy) floppy.sect |
| #define TRACKS(floppy) floppy.track |
| #define HEADS(floppy) floppy.head |
| #define SECTORS_PER_DISK(floppy) floppy.size |
| #define STRETCH(floppy) floppy.stretch |
| #define USE_2M(floppy) ((floppy.rate & FD_2M) ? 0xff : 0x80 ) |
| #define SSIZE(floppy) ((((floppy.rate & 0x38) >> 3 ) + 2) % 8) |
| |
| static __inline__ void set_2m(struct floppy_struct *floppy, int value) |
| { |
| if (value & 0x7f) |
| value = FD_2M; |
| else |
| value = 0; |
| floppy->rate = (floppy->rate & ~FD_2M) | value; |
| } |
| #define SET_2M set_2m |
| |
| static __inline__ void set_ssize(struct floppy_struct *floppy, int value) |
| { |
| value = (( (value & 7) + 6 ) % 8) << 3; |
| |
| floppy->rate = (floppy->rate & ~0x38) | value; |
| } |
| |
| #define SET_SSIZE set_ssize |
| |
| static __inline__ int set_parameters(int fd, struct floppy_struct *floppy, |
| struct MT_STAT *buf) |
| { |
| if ( ( MINOR(buf->st_rdev ) & 0x7f ) > 3 ) |
| return 1; |
| |
| return ioctl(fd, FDSETPRM, floppy); |
| } |
| |
| static __inline__ int get_parameters(int fd, struct floppy_struct *floppy) |
| { |
| return ioctl(fd, FDGETPRM, floppy); |
| } |
| |
| #endif /* linux */ |
| |
| |
| /* OS/2, gcc+emx */ |
| #ifdef __EMX__ |
| #define predefined_devices |
| struct device devices[] = { |
| {"A:", 'A', GENFD}, |
| {"B:", 'B', GENFD}, |
| }; |
| #define INIT_NOOP |
| #endif |
| |
| |
| |
| /*** /jes -- for D.O.S. 486 BL DX2/80 ***/ |
| /*** Jean-Marc Zucconi <jmz@FreeBSD.org> 2001/03/30 ***/ |
| #ifdef OS_freebsd |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/fd0.1440", 'A', FHD312}, |
| {"/dev/fd0.720", 'A', FDD312}, |
| {"/dev/fd1.1200", 'B', MHD514}, |
| {"/dev/sd0s1", 'C', GENHD}, |
| REMOTE |
| }; |
| #endif /* __FreeBSD__ */ |
| |
| /*** /jes -- for ALR 486 DX4/100 ***/ |
| #if defined(OS_netbsd) || defined(OS_netbsdelf) |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/rfd0a", 'A', FHD312}, |
| {"/dev/rfd0f", 'A', FDD312}, |
| {"/dev/rfd0f", 'S', MDD312}, |
| {"/dev/rfd1a", 'B', FHD514}, |
| {"/dev/rfd1d", 'B', FDD514}, |
| {"/dev/rfd1d", 'T', MDD514}, |
| {"/dev/rwd0d", 'C', 16, 0, 0, 0, 0, 0, 63L*512L, DEF_ARG0(0)}, |
| REMOTE |
| }; |
| #endif /* OS_NetBSD */ |
| |
| /* fgsch@openbsd.org 2000/05/19 */ |
| #if defined(OS_openbsd) |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/rfd0Bc", 'A', FHD312}, |
| {"/dev/rfd0Fc", 'A', FDD312}, |
| {"/dev/rfd1Cc", 'B', FHD514}, |
| {"/dev/rfd1Dc", 'B', FDD514}, |
| {"/dev/rwd0c", 'C', 16, 0, 0, 0, 0, 0, 63L*512L, DEF_ARG0(0)}, |
| REMOTE |
| }; |
| #endif /* OS_openbsd */ |
| |
| |
| |
| #if (!defined(predefined_devices) && defined (CPU_m68000) && defined (OS_sysv)) |
| #include <sys/gdioctl.h> |
| |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/rfp020", 'A', 12,O_NDELAY,40,2, 9, 0, MDEF_ARG}, |
| {"/usr/bin/DOS/dvd000", 'C', GENFD}, |
| REMOTE |
| }; |
| |
| #undef INIT_NOOP |
| int init_geom(int fd, struct device *dev, struct device *orig_dev, |
| struct MT_STAT *statbuf) |
| { |
| struct gdctl gdbuf; |
| |
| if (ioctl(fd, GDGETA, &gdbuf) == -1) { |
| ioctl(fd, GDDISMNT, &gdbuf); |
| return 1; |
| } |
| if((dev->use_2m & 0x7f) || (dev->ssize & 0x7f)) |
| return 1; |
| |
| SET_INT(gdbuf.params.cyls,dev->ntracks); |
| SET_INT(gdbuf.params.heads,dev->nheads); |
| SET_INT(gdbuf.params.psectrk,dev->nsect); |
| dev->ntracks = gdbuf.params.cyls; |
| dev->nheads = gdbuf.params.heads; |
| dev->nsect = gdbuf.params.psectrk; |
| dev->use_2m = 0x80; |
| dev->ssize = 0x82; |
| |
| gdbuf.params.pseccyl = gdbuf.params.psectrk * gdbuf.params.heads; |
| gdbuf.params.flags = 1; /* disk type flag */ |
| gdbuf.params.step = 0; /* step rate for controller */ |
| gdbuf.params.sectorsz = 512; /* sector size */ |
| |
| if (ioctl(fd, GDSETA, &gdbuf) < 0) { |
| ioctl(fd, GDDISMNT, &gdbuf); |
| return(1); |
| } |
| return(0); |
| } |
| #endif /* (defined (m68000) && defined (sysv))*/ |
| |
| #ifdef CPU_alpha |
| #ifndef OS_osf4 |
| #ifdef __osf__ |
| #include <sys/fcntl.h> |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/rfd0c", 'A', GENFD}, |
| REMOTE |
| }; |
| #endif |
| #endif |
| #endif |
| |
| #ifdef OS_osf |
| #ifndef predefined_devices |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/fd0a", 'A', MHD312 } }; |
| REMOTE |
| #endif |
| #endif |
| |
| |
| #ifdef OS_nextstep |
| #define predefined_devices |
| struct device devices[] = { |
| #ifdef CPU_m68k |
| {"/dev/rfd0b", 'A', MED312 }, |
| REMOTE |
| #else |
| {"/dev/rfd0b", 'A', MHD312 }, |
| REMOTE |
| #endif |
| }; |
| #endif |
| |
| |
| #if (!defined(predefined_devices) && defined(OS_sysv4)) |
| #ifdef __uxp__ |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/fpd0", 'A', FHD312}, |
| {"/dev/fpd0", 'A', FDD312}, |
| REMOTE |
| }; |
| #else |
| #define predefined_devices |
| struct device devices[] = { |
| {"/dev/rdsk/f1q15dt", 'B', FHD514}, |
| {"/dev/rdsk/f1d9dt", 'B', FDD514}, |
| {"/dev/rdsk/f1d8dt", 'B', FDDsmall}, |
| {"/dev/rdsk/f03ht", 'A', FHD312}, |
| {"/dev/rdsk/f03dt", 'A', FDD312}, |
| {"/dev/rdsk/dos", 'C', GENHD}, |
| REMOTE |
| }; |
| #endif |
| #endif /* sysv4 */ |
| |
| #ifdef OS_mingw32msvc |
| #define predefined_devices |
| struct device devices[] = { |
| {"\\\\.\\A:", 'A', GENFD }, |
| }; |
| #endif |
| |
| #ifdef INIT_GENERIC |
| |
| #ifndef USE_2M |
| #define USE_2M(x) 0x80 |
| #endif |
| |
| #ifndef SSIZE |
| #define SSIZE(x) 0x82 |
| #endif |
| |
| #ifndef SET_2M |
| #define SET_2M(x,y) return -1 |
| #endif |
| |
| #ifndef SET_SSIZE |
| #define SET_SSIZE(x,y) return -1 |
| #endif |
| |
| #undef INIT_NOOP |
| int init_geom(int fd, struct device *dev, struct device *orig_dev, |
| struct MT_STAT *statbuf) |
| { |
| struct generic_floppy_struct floppy; |
| int change; |
| |
| /* |
| * succeed if we don't have a floppy |
| * this is the case for dosemu floppy image files for instance |
| */ |
| if (!((S_ISBLK(statbuf->st_mode) && |
| major(statbuf->st_rdev) == BLOCK_MAJOR) |
| #ifdef CHAR_MAJOR |
| || (S_ISCHR(statbuf->st_mode) && |
| major(statbuf->st_rdev) == CHAR_MAJOR) |
| #endif |
| )) |
| return compare_geom(dev, orig_dev); |
| |
| /* |
| * We first try to get the current floppy parameters from the kernel. |
| * This allows us to |
| * 1. get the rate |
| * 2. skip the parameter setting if the parameters are already o.k. |
| */ |
| |
| if (get_parameters( fd, & floppy ) ) |
| /* |
| * autodetection failure. |
| * This mostly occurs because of an absent or unformatted disks. |
| * |
| * It might also occur because of bizarre formats (for example |
| * rate 1 on a 3 1/2 disk). |
| |
| * If this is the case, the user should do an explicit |
| * setfdprm before calling mtools |
| * |
| * Another cause might be pre-existing wrong parameters. The |
| * user should do an setfdprm -c to repair this situation. |
| * |
| * ...fail immediately... ( Theoretically, we could try to save |
| * the situation by trying out all rates, but it would be slow |
| * and awkward) |
| */ |
| return 1; |
| |
| |
| /* |
| * if we have already have the correct parameters, keep them. |
| * the number of tracks doesn't need to match exactly, it may be bigger. |
| * the number of heads and sectors must match exactly, to avoid |
| * miscalculation of the location of a block on the disk |
| */ |
| change = 0; |
| if(compare(dev->sectors, SECTORS(floppy))){ |
| SECTORS(floppy) = dev->sectors; |
| change = 1; |
| } else |
| dev->sectors = SECTORS(floppy); |
| |
| if(compare(dev->heads, HEADS(floppy))){ |
| HEADS(floppy) = dev->heads; |
| change = 1; |
| } else |
| dev->heads = HEADS(floppy); |
| |
| if(compare(dev->tracks, TRACKS(floppy))){ |
| TRACKS(floppy) = dev->tracks; |
| change = 1; |
| } else |
| dev->tracks = TRACKS(floppy); |
| |
| |
| if(compare(dev->use_2m, USE_2M(floppy))){ |
| SET_2M(&floppy, dev->use_2m); |
| change = 1; |
| } else |
| dev->use_2m = USE_2M(floppy); |
| |
| if( ! (dev->ssize & 0x80) ) |
| dev->ssize = 0; |
| if(compare(dev->ssize, SSIZE(floppy) + 128)){ |
| SET_SSIZE(&floppy, dev->ssize); |
| change = 1; |
| } else |
| dev->ssize = SSIZE(floppy); |
| |
| if(!change) |
| /* no change, succeed */ |
| return 0; |
| |
| #ifdef SECTORS_PER_TRACK |
| SECTORS_PER_TRACK(floppy) = dev->sectors * dev->heads; |
| #endif |
| |
| #ifdef SECTORS_PER_DISK |
| SECTORS_PER_DISK(floppy) = dev->sectors * dev->heads * dev->tracks; |
| #endif |
| |
| #ifdef STRETCH |
| /* ... and the stretch */ |
| if ( dev->tracks > 41 ) |
| STRETCH(floppy) = 0; |
| else |
| STRETCH(floppy) = 1; |
| #endif |
| |
| return set_parameters( fd, &floppy, statbuf); |
| } |
| #endif /* INIT_GENERIC */ |
| |
| #ifdef INIT_NOOP |
| int init_geom(int fd, struct device *dev, struct device *orig_dev, |
| struct MT_STAT *statbuf) |
| { |
| return compare_geom(dev, orig_dev); |
| } |
| #endif |
| |
| #ifdef predefined_devices |
| const unsigned int nr_const_devices = sizeof(const_devices) / sizeof(*const_devices); |
| #else |
| struct device devices[]={ |
| {"/dev/fd0", 'A', 0, O_EXCL, 0,0, 0,0, MDEF_ARG}, |
| /* to shut up Ultrix's native compiler, we can't make this empty :( */ |
| }; |
| const unsigned int nr_const_devices = 0; |
| #endif |