diff options
Diffstat (limited to 'devices.c')
-rw-r--r-- | devices.c | 1109 |
1 files changed, 1109 insertions, 0 deletions
diff --git a/devices.c b/devices.c new file mode 100644 index 0000000..9838a95 --- /dev/null +++ b/devices.c @@ -0,0 +1,1109 @@ +/* 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)} + + + +#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 + +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}, + {"/dev/fd1", 'B', 0, 0, 0,0, 0,0, FDEF_ARG}, + /* we assume that the Zip or Jaz drive is the second on the SCSI bus */ + {"/dev/sdb4",'J', GENHD }, + {"/dev/sdb4",'Z', GENHD }, + /* {"/dev/sda4",'D', GENHD },*/ + 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 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 int nr_const_devices = 0; +#endif |