1/* Copyright 1986-1992 Emmet P. Gray. 2 * Copyright 1996-2003,2006,2007,2009 Alain Knaff. 3 * This file is part of mtools. 4 * 5 * Mtools is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * Mtools is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with Mtools. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19/* 20 * Device tables. See the Configure file for a complete description. 21 */ 22 23#define NO_TERMIO 24#include "sysincludes.h" 25#include "msdos.h" 26#include "mtools.h" 27#include "devices.h" 28 29#define INIT_NOOP 30 31#define DEF_ARG1(x) (x), 0x2,0,(char *)0, 0, 0 32#define DEF_ARG0(x) 0,DEF_ARG1(x) 33 34#define MDEF_ARG 0L,DEF_ARG0(MFORMAT_ONLY_FLAG) 35#define FDEF_ARG 0L,DEF_ARG0(0) 36#define VOLD_DEF_ARG 0L,DEF_ARG0(VOLD_FLAG|MFORMAT_ONLY_FLAG) 37 38#define MED312 12,0,80,2,36,0,MDEF_ARG /* 3 1/2 extra density */ 39#define MHD312 12,0,80,2,18,0,MDEF_ARG /* 3 1/2 high density */ 40#define MDD312 12,0,80,2, 9,0,MDEF_ARG /* 3 1/2 double density */ 41#define MHD514 12,0,80,2,15,0,MDEF_ARG /* 5 1/4 high density */ 42#define MDD514 12,0,40,2, 9,0,MDEF_ARG /* 5 1/4 double density (360k) */ 43#define MSS514 12,0,40,1, 9,0,MDEF_ARG /* 5 1/4 single sided DD, (180k) */ 44#define MDDsmall 12,0,40,2, 8,0,MDEF_ARG /* 5 1/4 double density (320k) */ 45#define MSSsmall 12,0,40,1, 8,0,MDEF_ARG /* 5 1/4 single sided DD, (160k) */ 46 47#define FED312 12,0,80,2,36,0,FDEF_ARG /* 3 1/2 extra density */ 48#define FHD312 12,0,80,2,18,0,FDEF_ARG /* 3 1/2 high density */ 49#define FDD312 12,0,80,2, 9,0,FDEF_ARG /* 3 1/2 double density */ 50#define FHD514 12,0,80,2,15,0,FDEF_ARG /* 5 1/4 high density */ 51#define FDD514 12,0,40,2, 9,0,FDEF_ARG /* 5 1/4 double density (360k) */ 52#define FSS514 12,0,40,1, 9,0,FDEF_ARG /* 5 1/4 single sided DD, (180k) */ 53#define FDDsmall 12,0,40,2, 8,0,FDEF_ARG /* 5 1/4 double density (320k) */ 54#define FSSsmall 12,0,40,1, 8,0,FDEF_ARG /* 5 1/4 single sided DD, (160k) */ 55 56#define GENHD 16,0, 0,0, 0,0,MDEF_ARG /* Generic 16 bit FAT fs */ 57#define GENFD 12,0,80,2,18,0,MDEF_ARG /* Generic 12 bit FAT fs */ 58#define VOLDFD 12,0,80,2,18,0,VOLD_DEF_ARG /* Generic 12 bit FAT fs with vold */ 59#define GEN 0,0, 0,0, 0,0,MDEF_ARG /* Generic fs of any FAT bits */ 60 61#define ZIPJAZ(x,c,h,s,y) 16,(x),(c),(h),(s),(s),0L, 4, \ 62 DEF_ARG1((y)|MFORMAT_ONLY_FLAG) /* Jaz disks */ 63 64#define JAZ(x) ZIPJAZ(x,1021, 64, 32, 0) 65#define RJAZ(x) ZIPJAZ(x,1021, 64, 32, SCSI_FLAG|PRIV_FLAG) 66#define ZIP(x) ZIPJAZ(x,96, 64, 32, 0) 67#define RZIP(x) ZIPJAZ(x,96, 64, 32, SCSI_FLAG|PRIV_FLAG) 68 69#define REMOTE {"$DISPLAY", 'X', 0,0, 0,0, 0,0,0L, DEF_ARG0(FLOPPYD_FLAG)} 70 71 72 73#if defined(INIT_GENERIC) || defined(INIT_NOOP) 74static 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 91struct device devices[] = { 92 {"\\\\\\\\.\\\\A:", 'A', GENFD }, 93}; 94#endif /* CYGWIN */ 95 96 97#ifdef OS_aux 98#define predefined_devices 99struct 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 110struct device devices[] = { 111 {"/dev/fd1440.0", 'A', MHD312 }, 112 REMOTE 113}; 114#endif 115 116 117#ifdef __BEOS__ 118#define predefined_devices 119struct 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 129struct 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 159struct generic_floppy_struct 160{ 161 struct floppy_geometry fg; 162}; 163 164#define BLOCK_MAJOR 24 165#define CHAR_MAJOR 112 166 167static 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 183static 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 201struct 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 221struct 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)) 233struct 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) */ 246struct 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 261int ioctl(int, int, void *); 262 263static 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 290static 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 302struct 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 311struct 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 321struct 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 332char *alias_name = NULL; 333 334extern char *media_oldaliases(char *); 335extern char *media_findname(char *); 336 337char *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 366struct 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 392struct generic_floppy_struct 393{ 394 struct fd_char fdchar; 395}; 396 397#define BLOCK_MAJOR 36 398#define CHAR_MAJOR 36 399 400static 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 417static 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 432struct 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 441struct 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 453struct 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 468struct 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 483struct 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 499struct 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 508static 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 531static 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 553struct 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 566struct 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 579const 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", 5870, 588 589"Missing Address Mark", 590"Write Protect", 591"No Data - unreadable", 5920, 593"OverRun", 594"CRC error in data or address", 5950, 596"End Of Cylinder", 597 5980, 5990, 6000, 601"Not ready", 602"Equipment check error", 603"Seek end" }; 604 605 606static __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 638int 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 674int 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 732struct device devices[] = { 733 {"/dev/fd0", 'A', 0, 0, 80,2, 18,0, MDEF_ARG}, 734 {"/dev/fd1", 'B', 0, 0, 0,0, 0,0, FDEF_ARG}, 735 /* we assume that the Zip or Jaz drive is the second on the SCSI bus */ 736 {"/dev/sdb4",'J', GENHD }, 737 {"/dev/sdb4",'Z', GENHD }, 738 /* {"/dev/sda4",'D', GENHD },*/ 739 REMOTE 740}; 741 742/* 743 * Stuffing back the floppy parameters into the driver allows for gems 744 * like 21 sector or single sided floppies from Atari ST systems. 745 * 746 * Alain Knaff, Universit� Joseph Fourier, France, November 12, 1993. 747 */ 748 749 750#define INIT_GENERIC 751#define generic_floppy_struct floppy_struct 752#define BLOCK_MAJOR 2 753#define SECTORS(floppy) floppy.sect 754#define TRACKS(floppy) floppy.track 755#define HEADS(floppy) floppy.head 756#define SECTORS_PER_DISK(floppy) floppy.size 757#define STRETCH(floppy) floppy.stretch 758#define USE_2M(floppy) ((floppy.rate & FD_2M) ? 0xff : 0x80 ) 759#define SSIZE(floppy) ((((floppy.rate & 0x38) >> 3 ) + 2) % 8) 760 761static __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 771static __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 780static __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 789static __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 800struct 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 813struct 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 825struct 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 840struct 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 856struct 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 863int 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 902struct 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 913struct device devices[] = { 914 {"/dev/fd0a", 'A', MHD312 } }; 915 REMOTE 916#endif 917#endif 918 919 920#ifdef OS_nextstep 921#define predefined_devices 922struct 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 937struct device devices[] = { 938 {"/dev/fpd0", 'A', FHD312}, 939 {"/dev/fpd0", 'A', FDD312}, 940 REMOTE 941}; 942#else 943#define predefined_devices 944struct 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 958struct device devices[] = {}; 959#endif 960 961#ifdef INIT_GENERIC 962 963#ifndef USE_2M 964#define USE_2M(x) 0x80 965#endif 966 967#ifndef SSIZE 968#define SSIZE(x) 0x82 969#endif 970 971#ifndef SET_2M 972#define SET_2M(x,y) return -1 973#endif 974 975#ifndef SET_SSIZE 976#define SET_SSIZE(x,y) return -1 977#endif 978 979#undef INIT_NOOP 980int init_geom(int fd, struct device *dev, struct device *orig_dev, 981 struct MT_STAT *statbuf) 982{ 983 struct generic_floppy_struct floppy; 984 int change; 985 986 /* 987 * succeed if we don't have a floppy 988 * this is the case for dosemu floppy image files for instance 989 */ 990 if (!((S_ISBLK(statbuf->st_mode) && 991 major(statbuf->st_rdev) == BLOCK_MAJOR) 992#ifdef CHAR_MAJOR 993 || (S_ISCHR(statbuf->st_mode) && 994 major(statbuf->st_rdev) == CHAR_MAJOR) 995#endif 996 )) 997 return compare_geom(dev, orig_dev); 998 999 /* 1000 * We first try to get the current floppy parameters from the kernel. 1001 * This allows us to 1002 * 1. get the rate 1003 * 2. skip the parameter setting if the parameters are already o.k. 1004 */ 1005 1006 if (get_parameters( fd, & floppy ) ) 1007 /* 1008 * autodetection failure. 1009 * This mostly occurs because of an absent or unformatted disks. 1010 * 1011 * It might also occur because of bizarre formats (for example 1012 * rate 1 on a 3 1/2 disk). 1013 1014 * If this is the case, the user should do an explicit 1015 * setfdprm before calling mtools 1016 * 1017 * Another cause might be pre-existing wrong parameters. The 1018 * user should do an setfdprm -c to repair this situation. 1019 * 1020 * ...fail immediately... ( Theoretically, we could try to save 1021 * the situation by trying out all rates, but it would be slow 1022 * and awkward) 1023 */ 1024 return 1; 1025 1026 1027 /* 1028 * if we have already have the correct parameters, keep them. 1029 * the number of tracks doesn't need to match exactly, it may be bigger. 1030 * the number of heads and sectors must match exactly, to avoid 1031 * miscalculation of the location of a block on the disk 1032 */ 1033 change = 0; 1034 if(compare(dev->sectors, SECTORS(floppy))){ 1035 SECTORS(floppy) = dev->sectors; 1036 change = 1; 1037 } else 1038 dev->sectors = SECTORS(floppy); 1039 1040 if(compare(dev->heads, HEADS(floppy))){ 1041 HEADS(floppy) = dev->heads; 1042 change = 1; 1043 } else 1044 dev->heads = HEADS(floppy); 1045 1046 if(compare(dev->tracks, TRACKS(floppy))){ 1047 TRACKS(floppy) = dev->tracks; 1048 change = 1; 1049 } else 1050 dev->tracks = TRACKS(floppy); 1051 1052 1053 if(compare(dev->use_2m, USE_2M(floppy))){ 1054 SET_2M(&floppy, dev->use_2m); 1055 change = 1; 1056 } else 1057 dev->use_2m = USE_2M(floppy); 1058 1059 if( ! (dev->ssize & 0x80) ) 1060 dev->ssize = 0; 1061 if(compare(dev->ssize, SSIZE(floppy) + 128)){ 1062 SET_SSIZE(&floppy, dev->ssize); 1063 change = 1; 1064 } else 1065 dev->ssize = SSIZE(floppy); 1066 1067 if(!change) 1068 /* no change, succeed */ 1069 return 0; 1070 1071#ifdef SECTORS_PER_TRACK 1072 SECTORS_PER_TRACK(floppy) = dev->sectors * dev->heads; 1073#endif 1074 1075#ifdef SECTORS_PER_DISK 1076 SECTORS_PER_DISK(floppy) = dev->sectors * dev->heads * dev->tracks; 1077#endif 1078 1079#ifdef STRETCH 1080 /* ... and the stretch */ 1081 if ( dev->tracks > 41 ) 1082 STRETCH(floppy) = 0; 1083 else 1084 STRETCH(floppy) = 1; 1085#endif 1086 1087 return set_parameters( fd, &floppy, statbuf); 1088} 1089#endif /* INIT_GENERIC */ 1090 1091#ifdef INIT_NOOP 1092int init_geom(int fd, struct device *dev, struct device *orig_dev, 1093 struct MT_STAT *statbuf) 1094{ 1095 return compare_geom(dev, orig_dev); 1096} 1097#endif 1098 1099#ifdef predefined_devices 1100const int nr_const_devices = sizeof(const_devices) / sizeof(*const_devices); 1101#else 1102struct device devices[]={ 1103 {"/dev/fd0", 'A', 0, O_EXCL, 0,0, 0,0, MDEF_ARG}, 1104 /* to shut up Ultrix's native compiler, we can't make this empty :( */ 1105}; 1106const int nr_const_devices = 0; 1107#endif 1108