1/* 2 * linux/kernel/arch/arm/drivers/block/fd1772.c 3 * Based on ataflop.c in the m68k Linux 4 * Copyright (C) 1993 Greg Harp 5 * Atari Support by Bjoern Brauel, Roman Hodek 6 * Archimedes Support by Dave Gilbert (linux@treblig.org) 7 * 8 * Big cleanup Sep 11..14 1994 Roman Hodek: 9 * - Driver now works interrupt driven 10 * - Support for two drives; should work, but I cannot test that :-( 11 * - Reading is done in whole tracks and buffered to speed up things 12 * - Disk change detection and drive deselecting after motor-off 13 * similar to TOS 14 * - Autodetection of disk format (DD/HD); untested yet, because I 15 * don't have an HD drive :-( 16 * 17 * Fixes Nov 13 1994 Martin Schaller: 18 * - Autodetection works now 19 * - Support for 5 1/4" disks 20 * - Removed drive type (unknown on atari) 21 * - Do seeks with 8 Mhz 22 * 23 * Changes by Andreas Schwab: 24 * - After errors in multiple read mode try again reading single sectors 25 * (Feb 1995): 26 * - Clean up error handling 27 * - Set blk_size for proper size checking 28 * - Initialize track register when testing presence of floppy 29 * - Implement some ioctl's 30 * 31 * Changes by Torsten Lang: 32 * - When probing the floppies we should add the FDC1772CMDADD_H flag since 33 * the FDC1772 will otherwise wait forever when no disk is inserted... 34 * 35 * Things left to do: 36 * - Formatting 37 * - Maybe a better strategy for disk change detection (does anyone 38 * know one?) 39 * - There are some strange problems left: The strangest one is 40 * that, at least on my TT (4+4MB), the first 2 Bytes of the last 41 * page of the TT-Ram (!) change their contents (some bits get 42 * set) while a floppy DMA is going on. But there are no accesses 43 * to these memory locations from the kernel... (I tested that by 44 * making the page read-only). I cannot explain what's going on... 45 * - Sometimes the drive-change-detection stops to work. The 46 * function is still called, but the WP bit always reads as 0... 47 * Maybe a problem with the status reg mode or a timing problem. 48 * Note 10/12/94: The change detection now seems to work reliably. 49 * There is no proof, but I've seen no hang for a long time... 50 * 51 * ARCHIMEDES changes: (gilbertd@cs.man.ac.uk) 52 * 26/12/95 - Changed all names starting with FDC to FDC1772 53 * Removed all references to clock speed of FDC - we're stuck with 8MHz 54 * Modified disk_type structure to remove HD formats 55 * 56 * 7/ 1/96 - Wrote FIQ code, removed most remaining atariisms 57 * 58 * 13/ 1/96 - Well I think its read a single sector; but there is a problem 59 * fd_rwsec_done which is called in FIQ mode starts another transfer 60 * off (in fd_rwsec) while still in FIQ mode. Because its still in 61 * FIQ mode it can't service the DMA and loses data. So need to 62 * heavily restructure. 63 * 14/ 1/96 - Found that the definitions of the register numbers of the 64 * FDC were multiplied by 2 in the header for the 16bit words 65 * of the atari so half the writes were going in the wrong place. 66 * Also realised that the FIQ entry didn't make any attempt to 67 * preserve registers or return correctly; now in assembler. 68 * 69 * 11/ 2/96 - Hmm - doesn't work on real machine. Auto detect doesn't 70 * and hacking that past seems to wait forever - check motor 71 * being turned on. 72 * 73 * 17/ 2/96 - still having problems - forcing track to -1 when selecting 74 * new drives seems to allow it to read first few sectors 75 * but then we get solid hangs at apparently random places 76 * which change depending what is happening. 77 * 78 * 9/ 3/96 - Fiddled a lot of stuff around to move to kernel 1.3.35 79 * A lot of fiddling in DMA stuff. Having problems with it 80 * constnatly thinking its timeing out. Ah - its timeout 81 * was set to (6*HZ) rather than jiffies+(6*HZ). Now giving 82 * duff data! 83 * 84 * 5/ 4/96 - Made it use the new IOC_ macros rather than *ioc 85 * Hmm - giving unexpected FIQ and then timeouts 86 * 18/ 8/96 - Ran through indent -kr -i8 87 * Some changes to disc change detect; don't know how well it 88 * works. 89 * 24/ 8/96 - Put all the track buffering code back in from the atari 90 * code - I wonder if it will still work... No :-) 91 * Still works if I turn off track buffering. 92 * 25/ 8/96 - Changed the timer expires that I'd added back to be 93 * jiffies + ....; and it all sprang to life! Got 2.8K/sec 94 * off a cp -r of a 679K disc (showed 94% cpu usage!) 95 * (PC gets 14.3K/sec - 0% CPU!) Hmm - hard drive corrupt! 96 * Also perhaps that compile was with cache off. 97 * changed cli in fd_readtrack_check to cliIF 98 * changed vmallocs to kmalloc (whats the difference!!) 99 * Removed the busy wait loop in do_fd_request and replaced 100 * by a routine on tq_immediate; only 11% cpu on a dd off the 101 * raw disc - but the speed is the same. 102 * 1/ 9/96 - Idea (failed!) - set the 'disable spin-up seqeunce' 103 * when we read the track if we know the motor is on; didn't 104 * help - perhaps we have to do it in stepping as well. 105 * Nope. Still doesn't help. 106 * Hmm - what seems to be happening is that fd_readtrack_check 107 * is never getting called. Its job is to terminate the read 108 * just after we think we should have got the data; otherwise 109 * the fdc takes 1 second to timeout; which is what's happening 110 * Now I can see 'readtrack_timer' being set (which should do the 111 * call); but it never seems to be called - hmm! 112 * OK - I've moved the check to my tq_immediate code - 113 * and it WORKS! 13.95K/second at 19% CPU. 114 * I wish I knew why that timer didn't work..... 115 * 116 * 16/11/96 - Fiddled and frigged for 2.0.18 117 * 118 * DAG 30/01/99 - Started frobbing for 2.2.1 119 * DAG 20/06/99 - A little more frobbing: 120 * Included include/asm/uaccess.h for get_user/put_user 121 * 122 * DAG 1/09/00 - Dusted off for 2.4.0-test7 123 * MAX_SECTORS was name clashing so it is now FD1772_... 124 * Minor parameter, name layouts for 2.4.x differences 125 */ 126 127#include <linux/sched.h> 128#include <linux/fs.h> 129#include <linux/fcntl.h> 130#include <linux/slab.h> 131#include <linux/kernel.h> 132#include <linux/interrupt.h> 133#include <linux/timer.h> 134#include <linux/tqueue.h> 135#include <linux/fd.h> 136#include <linux/fd1772.h> 137#include <linux/errno.h> 138#include <linux/types.h> 139#include <linux/delay.h> 140#include <linux/mm.h> 141 142#include <asm/arch/oldlatches.h> 143#include <asm/bitops.h> 144#include <asm/dma.h> 145#include <asm/hardware.h> 146#include <asm/hardware/ioc.h> 147#include <asm/io.h> 148#include <asm/irq.h> 149#include <asm/mach-types.h> 150#include <asm/pgtable.h> 151#include <asm/system.h> 152#include <asm/uaccess.h> 153 154 155#define MAJOR_NR FLOPPY_MAJOR 156#define FLOPPY_DMA 0 157#include <linux/blk.h> 158 159/* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with 160 * little additional rework in this file). But I'm not yet sure if 161 * some other code depends on the number of floppies... (It is defined 162 * in a public header!) 163 */ 164 165/* Ditto worries for Arc - DAG */ 166#define FD_MAX_UNITS 4 167#define TRACKBUFFER 0 168/*#define DEBUG*/ 169 170#ifdef DEBUG 171#define DPRINT(a) printk a 172#else 173#define DPRINT(a) 174#endif 175 176/* Disk types: DD */ 177static struct archy_disk_type { 178 const char *name; 179 unsigned spt; /* sectors per track */ 180 unsigned blocks; /* total number of blocks */ 181 unsigned stretch; /* track doubling ? */ 182} disk_type[] = { 183 184 { "d360", 9, 720, 0 }, /* 360kB diskette */ 185 { "D360", 9, 720, 1 }, /* 360kb in 720kb drive */ 186 { "D720", 9, 1440, 0 }, /* 720kb diskette (DD) */ 187 /*{ "D820", 10,1640, 0}, *//* DD disk with 82 tracks/10 sectors 188 - DAG - can't see how type detect can distinguish this 189 from 720K until it reads block 4 by which time its too late! */ 190}; 191 192#define NUM_DISK_TYPES (sizeof(disk_type)/sizeof(*disk_type)) 193 194/* 195 * Maximum disk size (in kilobytes). This default is used whenever the 196 * current disk size is unknown. 197 */ 198#define MAX_DISK_SIZE 720 199 200static int floppy_sizes[256]; 201static int floppy_blocksizes[256]; 202 203/* current info on each unit */ 204static struct archy_floppy_struct { 205 int connected; /* !=0 : drive is connected */ 206 int autoprobe; /* !=0 : do autoprobe */ 207 208 struct archy_disk_type *disktype; /* current type of disk */ 209 210 int track; /* current head position or -1 211 * if unknown */ 212 unsigned int steprate; /* steprate setting */ 213 unsigned int wpstat; /* current state of WP signal 214 * (for disk change detection) */ 215} unit[FD_MAX_UNITS]; 216 217/* DAG: On Arc we spin on a flag being cleared by fdc1772_comendhandler which 218 is an assembler routine */ 219extern void fdc1772_comendhandler(void); /* Actually doens't have these parameters - see fd1772.S */ 220extern volatile int fdc1772_comendstatus; 221extern volatile int fdc1772_fdc_int_done; 222 223#define FDC1772BASE ((0x210000>>2)|0x80000000) 224 225#define FDC1772_READ(reg) inb(FDC1772BASE+(reg/2)) 226 227/* DAG: You wouldn't be silly to ask why FDC1772_WRITE is a function rather 228 than the #def below - well simple - the #def won't compile - and I 229 don't understand why (__outwc not defined) */ 230/* NOTE: Reg is 0,2,4,6 as opposed to 0,1,2,3 or 0,4,8,12 to keep compatibility 231 with the ST version of fd1772.h */ 232/*#define FDC1772_WRITE(reg,val) outw(val,(reg+FDC1772BASE)); */ 233void FDC1772_WRITE(int reg, unsigned char val) 234{ 235 if (reg == FDC1772REG_CMD) { 236 DPRINT(("FDC1772_WRITE new command 0x%x @ %d\n", val,jiffies)); 237 if (fdc1772_fdc_int_done) { 238 DPRINT(("FDC1772_WRITE: Hmm fdc1772_fdc_int_done true - resetting\n")); 239 fdc1772_fdc_int_done = 0; 240 }; 241 }; 242 outb(val, (reg / 2) + FDC1772BASE); 243}; 244 245#define FD1772_MAX_SECTORS 22 246 247unsigned char *DMABuffer; /* buffer for writes */ 248/*static unsigned long PhysDMABuffer; *//* physical address */ 249/* DAG: On Arc we just go straight for the DMA buffer */ 250#define PhysDMABuffer DMABuffer 251 252#ifdef TRACKBUFFER 253unsigned char *TrackBuffer; /* buffer for reads */ 254#define PhysTrackBuffer TrackBuffer /* physical address */ 255static int BufferDrive, BufferSide, BufferTrack; 256static int read_track; /* non-zero if we are reading whole tracks */ 257 258#define SECTOR_BUFFER(sec) (TrackBuffer + ((sec)-1)*512) 259#define IS_BUFFERED(drive,side,track) \ 260 (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track)) 261#endif 262 263/* 264 * These are global variables, as that's the easiest way to give 265 * information to interrupts. They are the data used for the current 266 * request. 267 */ 268static int SelectedDrive = 0; 269static int ReqCmd, ReqBlock; 270static int ReqSide, ReqTrack, ReqSector, ReqCnt; 271static int HeadSettleFlag = 0; 272static unsigned char *ReqData, *ReqBuffer; 273static int MotorOn = 0, MotorOffTrys; 274 275/* Synchronization of FDC1772 access. */ 276static volatile int fdc_busy = 0; 277static DECLARE_WAIT_QUEUE_HEAD(fdc_wait); 278 279 280/* long req'd for set_bit --RR */ 281static unsigned long changed_floppies = 0xff, fake_change = 0; 282#define CHECK_CHANGE_DELAY HZ/2 283 284/* DAG - increased to 30*HZ - not sure if this is the correct thing to do */ 285#define FD_MOTOR_OFF_DELAY (10*HZ) 286#define FD_MOTOR_OFF_MAXTRY (10*20) 287 288#define FLOPPY_TIMEOUT (6*HZ) 289#define RECALIBRATE_ERRORS 4 /* After this many errors the drive 290 * will be recalibrated. */ 291#define MAX_ERRORS 8 /* After this many errors the driver 292 * will give up. */ 293 294#define START_MOTOR_OFF_TIMER(delay) \ 295 do { \ 296 motor_off_timer.expires = jiffies + (delay); \ 297 add_timer( &motor_off_timer ); \ 298 MotorOffTrys = 0; \ 299 } while(0) 300 301#define START_CHECK_CHANGE_TIMER(delay) \ 302 do { \ 303 mod_timer(&fd_timer, jiffies + (delay)); \ 304 } while(0) 305 306#define START_TIMEOUT() \ 307 do { \ 308 mod_timer(&timeout_timer, jiffies+FLOPPY_TIMEOUT); \ 309 } while(0) 310 311#define STOP_TIMEOUT() \ 312 do { \ 313 del_timer( &timeout_timer ); \ 314 } while(0) 315 316#define ENABLE_IRQ() enable_irq(FIQ_FD1772+64); 317 318#define DISABLE_IRQ() disable_irq(FIQ_FD1772+64); 319 320static void fd1772_checkint(void); 321 322struct tq_struct fd1772_tq = 323{ 0,0, (void *)fd1772_checkint, 0 }; 324/* 325 * The driver is trying to determine the correct media format 326 * while Probing is set. fd_rwsec_done() clears it after a 327 * successful access. 328 */ 329static int Probing = 0; 330 331/* This flag is set when a dummy seek is necesary to make the WP 332 * status bit accessible. 333 */ 334static int NeedSeek = 0; 335 336 337/***************************** Prototypes *****************************/ 338 339static void fd_select_side(int side); 340static void fd_select_drive(int drive); 341static void fd_deselect(void); 342static void fd_motor_off_timer(unsigned long dummy); 343static void check_change(unsigned long dummy); 344static __inline__ void set_head_settle_flag(void); 345static __inline__ int get_head_settle_flag(void); 346static void floppy_irqconsequencehandler(void); 347static void fd_error(void); 348static void do_fd_action(int drive); 349static void fd_calibrate(void); 350static void fd_calibrate_done(int status); 351static void fd_seek(void); 352static void fd_seek_done(int status); 353static void fd_rwsec(void); 354#ifdef TRACKBUFFER 355static void fd_readtrack_check( unsigned long dummy ); 356#endif 357static void fd_rwsec_done(int status); 358static void fd_times_out(unsigned long dummy); 359static void finish_fdc(void); 360static void finish_fdc_done(int dummy); 361static void floppy_off(unsigned int nr); 362static __inline__ void copy_buffer(void *from, void *to); 363static void setup_req_params(int drive); 364static void redo_fd_request(void); 365static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int 366 cmd, unsigned long param); 367static void fd_probe(int drive); 368static int fd_test_drive_present(int drive); 369static void config_types(void); 370static int floppy_open(struct inode *inode, struct file *filp); 371static int floppy_release(struct inode *inode, struct file *filp); 372 373/************************* End of Prototypes **************************/ 374 375static struct timer_list motor_off_timer = { 376 function: fd_motor_off_timer, 377}; 378 379#ifdef TRACKBUFFER 380static struct timer_list readtrack_timer = { 381 function: fd_readtrack_check, 382}; 383#endif 384 385static struct timer_list timeout_timer = { 386 function: fd_times_out, 387}; 388 389static struct timer_list fd_timer = { 390 function: check_change, 391}; 392 393/* DAG: Haven't got a clue what this is? */ 394int stdma_islocked(void) 395{ 396 return 0; 397}; 398 399/* Select the side to use. */ 400 401static void fd_select_side(int side) 402{ 403 oldlatch_aupdate(LATCHA_SIDESEL, side ? 0 : LATCHA_SIDESEL); 404} 405 406 407/* Select a drive, update the FDC1772's track register 408 */ 409 410static void fd_select_drive(int drive) 411{ 412#ifdef DEBUG 413 printk("fd_select_drive:%d\n", drive); 414#endif 415 /* Hmm - nowhere do we seem to turn the motor on - I'm going to do it here! */ 416 oldlatch_aupdate(LATCHA_MOTOR | LATCHA_INUSE, 0); 417 418 if (drive == SelectedDrive) 419 return; 420 421 oldlatch_aupdate(LATCHA_FDSELALL, 0xf - (1 << drive)); 422 423 /* restore track register to saved value */ 424 FDC1772_WRITE(FDC1772REG_TRACK, unit[drive].track); 425 udelay(25); 426 427 SelectedDrive = drive; 428} 429 430 431/* Deselect both drives. */ 432 433static void fd_deselect(void) 434{ 435 unsigned long flags; 436 437 DPRINT(("fd_deselect\n")); 438 439 oldlatch_aupdate(LATCHA_FDSELALL | LATCHA_MOTOR | LATCHA_INUSE, 0xf | LATCHA_MOTOR | LATCHA_INUSE); 440 441 SelectedDrive = -1; 442} 443 444 445/* This timer function deselects the drives when the FDC1772 switched the 446 * motor off. The deselection cannot happen earlier because the FDC1772 447 * counts the index signals, which arrive only if one drive is selected. 448 */ 449 450static void fd_motor_off_timer(unsigned long dummy) 451{ 452 unsigned long flags; 453 unsigned char status; 454 int delay; 455 456 del_timer(&motor_off_timer); 457 458 if (SelectedDrive < 0) 459 /* no drive selected, needn't deselect anyone */ 460 return; 461 462 save_flags(flags); 463 cli(); 464 465 if (fdc_busy) /* was stdma_islocked */ 466 goto retry; 467 468 status = FDC1772_READ(FDC1772REG_STATUS); 469 470 if (!(status & 0x80)) { 471 /* 472 * motor already turned off by FDC1772 -> deselect drives 473 * In actual fact its this deselection which turns the motor 474 * off on the Arc, since the motor control is actually on 475 * Latch A 476 */ 477 DPRINT(("fdc1772: deselecting in fd_motor_off_timer\n")); 478 fd_deselect(); 479 MotorOn = 0; 480 restore_flags(flags); 481 return; 482 } 483 /* not yet off, try again */ 484 485retry: 486 restore_flags(flags); 487 /* Test again later; if tested too often, it seems there is no disk 488 * in the drive and the FDC1772 will leave the motor on forever (or, 489 * at least until a disk is inserted). So we'll test only twice 490 * per second from then on... 491 */ 492 delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ? 493 (++MotorOffTrys, HZ / 20) : HZ / 2; 494 START_MOTOR_OFF_TIMER(delay); 495} 496 497 498/* This function is repeatedly called to detect disk changes (as good 499 * as possible) and keep track of the current state of the write protection. 500 */ 501 502static void check_change(unsigned long dummy) 503{ 504 static int drive = 0; 505 506 unsigned long flags; 507 int stat; 508 509 if (fdc_busy) 510 return; /* Don't start poking about if the fdc is busy */ 511 512 return; /* let's just forget it for the mo DAG */ 513 514 if (++drive > 1 || !unit[drive].connected) 515 drive = 0; 516 517 save_flags(flags); 518 cli(); 519 520 if (!stdma_islocked()) { 521 stat = !!(FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_WPROT); 522 523 /* The idea here is that if the write protect line has changed then 524 the disc must have changed */ 525 if (stat != unit[drive].wpstat) { 526 DPRINT(("wpstat[%d] = %d\n", drive, stat)); 527 unit[drive].wpstat = stat; 528 set_bit(drive, &changed_floppies); 529 } 530 } 531 restore_flags(flags); 532 533 START_CHECK_CHANGE_TIMER(CHECK_CHANGE_DELAY); 534} 535 536 537/* Handling of the Head Settling Flag: This flag should be set after each 538 * seek operation, because we don't use seeks with verify. 539 */ 540 541static __inline__ void set_head_settle_flag(void) 542{ 543 HeadSettleFlag = FDC1772CMDADD_E; 544} 545 546static __inline__ int get_head_settle_flag(void) 547{ 548 int tmp = HeadSettleFlag; 549 HeadSettleFlag = 0; 550 return (tmp); 551} 552 553 554 555 556/* General Interrupt Handling */ 557 558static void (*FloppyIRQHandler) (int status) = NULL; 559 560static void floppy_irqconsequencehandler(void) 561{ 562 unsigned char status; 563 void (*handler) (int); 564 565 fdc1772_fdc_int_done = 0; 566 567 handler = FloppyIRQHandler; 568 FloppyIRQHandler = NULL; 569 570 if (handler) { 571 nop(); 572 status = (unsigned char) fdc1772_comendstatus; 573 DPRINT(("FDC1772 irq, status = %02x handler = %08lx\n", (unsigned int) status, (unsigned long) handler)); 574 handler(status); 575 } else { 576 DPRINT(("FDC1772 irq, no handler status=%02x\n", fdc1772_comendstatus)); 577 } 578 DPRINT(("FDC1772 irq: end of floppy_irq\n")); 579} 580 581 582/* Error handling: If some error happened, retry some times, then 583 * recalibrate, then try again, and fail after MAX_ERRORS. 584 */ 585 586static void fd_error(void) 587{ 588 printk("FDC1772: fd_error\n"); 589 /*panic("fd1772: fd_error"); *//* DAG tmp */ 590 if (QUEUE_EMPTY) 591 return; 592 CURRENT->errors++; 593 if (CURRENT->errors >= MAX_ERRORS) { 594 printk("fd%d: too many errors.\n", SelectedDrive); 595 end_request(0); 596 } else if (CURRENT->errors == RECALIBRATE_ERRORS) { 597 printk("fd%d: recalibrating\n", SelectedDrive); 598 if (SelectedDrive != -1) 599 unit[SelectedDrive].track = -1; 600 } 601 redo_fd_request(); 602} 603 604 605 606#define SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0) 607 608 609/* do_fd_action() is the general procedure for a fd request: All 610 * required parameter settings (drive select, side select, track 611 * position) are checked and set if needed. For each of these 612 * parameters and the actual reading or writing exist two functions: 613 * one that starts the setting (or skips it if possible) and one 614 * callback for the "done" interrupt. Each done func calls the next 615 * set function to propagate the request down to fd_rwsec_done(). 616 */ 617 618static void do_fd_action(int drive) 619{ 620 DPRINT(("do_fd_action unit[drive].track=%d\n", unit[drive].track)); 621 622#ifdef TRACKBUFFER 623repeat: 624 625 if (IS_BUFFERED( drive, ReqSide, ReqTrack )) { 626 if (ReqCmd == READ) { 627 copy_buffer( SECTOR_BUFFER(ReqSector), ReqData ); 628 if (++ReqCnt < CURRENT->current_nr_sectors) { 629 /* read next sector */ 630 setup_req_params( drive ); 631 goto repeat; 632 } else { 633 /* all sectors finished */ 634 CURRENT->nr_sectors -= CURRENT->current_nr_sectors; 635 CURRENT->sector += CURRENT->current_nr_sectors; 636 end_request( 1 ); 637 redo_fd_request(); 638 return; 639 } 640 } else { 641 /* cmd == WRITE, pay attention to track buffer 642 * consistency! */ 643 copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) ); 644 } 645 } 646#endif 647 648 if (SelectedDrive != drive) { 649 /*unit[drive].track = -1; DAG */ 650 fd_select_drive(drive); 651 }; 652 653 654 if (unit[drive].track == -1) 655 fd_calibrate(); 656 else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch) 657 fd_seek(); 658 else 659 fd_rwsec(); 660} 661 662 663/* Seek to track 0 if the current track is unknown */ 664 665static void fd_calibrate(void) 666{ 667 DPRINT(("fd_calibrate\n")); 668 if (unit[SelectedDrive].track >= 0) { 669 fd_calibrate_done(0); 670 return; 671 } 672 DPRINT(("fd_calibrate (after track compare)\n")); 673 SET_IRQ_HANDLER(fd_calibrate_done); 674 /* we can't verify, since the speed may be incorrect */ 675 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate); 676 677 NeedSeek = 1; 678 MotorOn = 1; 679 START_TIMEOUT(); 680 /* wait for IRQ */ 681} 682 683 684static void fd_calibrate_done(int status) 685{ 686 DPRINT(("fd_calibrate_done()\n")); 687 STOP_TIMEOUT(); 688 689 /* set the correct speed now */ 690 if (status & FDC1772STAT_RECNF) { 691 printk("fd%d: restore failed\n", SelectedDrive); 692 fd_error(); 693 } else { 694 unit[SelectedDrive].track = 0; 695 fd_seek(); 696 } 697} 698 699 700/* Seek the drive to the requested track. The drive must have been 701 * calibrated at some point before this. 702 */ 703 704static void fd_seek(void) 705{ 706 unsigned long flags; 707 DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n", ReqTrack, 708 unit[SelectedDrive].track)); 709 if (unit[SelectedDrive].track == ReqTrack << 710 unit[SelectedDrive].disktype->stretch) { 711 fd_seek_done(0); 712 return; 713 } 714 FDC1772_WRITE(FDC1772REG_DATA, ReqTrack << 715 unit[SelectedDrive].disktype->stretch); 716 udelay(25); 717 save_flags(flags); 718 clf(); 719 SET_IRQ_HANDLER(fd_seek_done); 720 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate | 721 /* DAG */ 722 (MotorOn?FDC1772CMDADD_H:0)); 723 724 restore_flags(flags); 725 MotorOn = 1; 726 set_head_settle_flag(); 727 START_TIMEOUT(); 728 /* wait for IRQ */ 729} 730 731 732static void fd_seek_done(int status) 733{ 734 DPRINT(("fd_seek_done()\n")); 735 STOP_TIMEOUT(); 736 737 /* set the correct speed */ 738 if (status & FDC1772STAT_RECNF) { 739 printk("fd%d: seek error (to track %d)\n", 740 SelectedDrive, ReqTrack); 741 /* we don't know exactly which track we are on now! */ 742 unit[SelectedDrive].track = -1; 743 fd_error(); 744 } else { 745 unit[SelectedDrive].track = ReqTrack << 746 unit[SelectedDrive].disktype->stretch; 747 NeedSeek = 0; 748 fd_rwsec(); 749 } 750} 751 752 753/* This does the actual reading/writing after positioning the head 754 * over the correct track. 755 */ 756 757#ifdef TRACKBUFFER 758static int MultReadInProgress = 0; 759#endif 760 761 762static void fd_rwsec(void) 763{ 764 unsigned long paddr, flags; 765 unsigned int rwflag, old_motoron; 766 unsigned int track; 767 768 DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n", ReqSector, ReqCmd == WRITE ? 'w' : 'r')); 769 if (ReqCmd == WRITE) { 770 /*cache_push( (unsigned long)ReqData, 512 ); */ 771 paddr = (unsigned long) ReqData; 772 rwflag = 0x100; 773 } else { 774 paddr = (unsigned long) PhysDMABuffer; 775#ifdef TRACKBUFFER 776 if (read_track) 777 paddr = (unsigned long)PhysTrackBuffer; 778#endif 779 rwflag = 0; 780 } 781 782 DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n", rwflag, 783 ReqSector, FDC1772_READ(FDC1772REG_TRACK))); 784 fd_select_side(ReqSide); 785 786 /*DPRINT(("fd_rwsec() before start sector \n")); */ 787 /* Start sector of this operation */ 788#ifdef TRACKBUFFER 789 FDC1772_WRITE( FDC1772REG_SECTOR, !read_track ? ReqSector : 1 ); 790#else 791 FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector ); 792#endif 793 794 /* Cheat for track if stretch != 0 */ 795 if (unit[SelectedDrive].disktype->stretch) { 796 track = FDC1772_READ(FDC1772REG_TRACK); 797 FDC1772_WRITE(FDC1772REG_TRACK, track >> 798 unit[SelectedDrive].disktype->stretch); 799 } 800 udelay(25); 801 802 DPRINT(("fd_rwsec() before setup DMA \n")); 803 /* Setup DMA - Heavily modified by DAG */ 804 save_flags(flags); 805 clf(); 806 disable_dma(FLOPPY_DMA); 807 set_dma_mode(FLOPPY_DMA, rwflag ? DMA_MODE_WRITE : DMA_MODE_READ); 808 set_dma_addr(FLOPPY_DMA, (long) paddr); /* DAG - changed from Atari specific */ 809#ifdef TRACKBUFFER 810 set_dma_count(FLOPPY_DMA,(!read_track ? 1 : unit[SelectedDrive].disktype->spt)*512); 811#else 812 set_dma_count(FLOPPY_DMA, 512); /* Block/sector size - going to have to change */ 813#endif 814 SET_IRQ_HANDLER(fd_rwsec_done); 815 /* Turn on dma int */ 816 enable_dma(FLOPPY_DMA); 817 /* Now give it something to do */ 818 FDC1772_WRITE(FDC1772REG_CMD, (rwflag ? (FDC1772CMD_WRSEC | FDC1772CMDADD_P) : 819#ifdef TRACKBUFFER 820 (FDC1772CMD_RDSEC | (read_track ? FDC1772CMDADD_M : 0) | 821 /* Hmm - the idea here is to stop the FDC spinning the disc 822 up when we know that we already still have it spinning */ 823 (MotorOn?FDC1772CMDADD_H:0)) 824#else 825 FDC1772CMD_RDSEC 826#endif 827 )); 828 829 restore_flags(flags); 830 DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n", flags)); 831 /*sti(); *//* DAG - Hmm */ 832 /* Hmm - should do something DAG */ 833 old_motoron = MotorOn; 834 MotorOn = 1; 835 NeedSeek = 1; 836 837 /* wait for interrupt */ 838 839#ifdef TRACKBUFFER 840 if (read_track) { 841 /* 842 * If reading a whole track, wait about one disk rotation and 843 * then check if all sectors are read. The FDC will even 844 * search for the first non-existant sector and need 1 sec to 845 * recognise that it isn't present :-( 846 */ 847 /* 1 rot. + 5 rot.s if motor was off */ 848 mod_timer(&readtrack_timer, jiffies + HZ/5 + (old_motoron ? 0 : HZ)); 849 DPRINT(("Setting readtrack_timer to %d @ %d\n", 850 readtrack_timer.expires,jiffies)); 851 MultReadInProgress = 1; 852 } 853#endif 854 855 /*DPRINT(("fd_rwsec() before START_TIMEOUT \n")); */ 856 START_TIMEOUT(); 857 /*DPRINT(("fd_rwsec() after START_TIMEOUT \n")); */ 858} 859 860 861#ifdef TRACKBUFFER 862 863static void fd_readtrack_check(unsigned long dummy) 864{ 865 unsigned long flags, addr; 866 extern unsigned char *fdc1772_dataaddr; 867 868 DPRINT(("fd_readtrack_check @ %d\n",jiffies)); 869 870 save_flags(flags); 871 clf(); 872 873 del_timer( &readtrack_timer ); 874 875 if (!MultReadInProgress) { 876 /* This prevents a race condition that could arise if the 877 * interrupt is triggered while the calling of this timer 878 * callback function takes place. The IRQ function then has 879 * already cleared 'MultReadInProgress' when control flow 880 * gets here. 881 */ 882 restore_flags(flags); 883 return; 884 } 885 886 /* get the current DMA address */ 887 addr=(unsigned long)fdc1772_dataaddr; /* DAG - ? */ 888 DPRINT(("fd_readtrack_check: addr=%x PhysTrackBuffer=%x\n",addr,PhysTrackBuffer)); 889 890 if (addr >= (unsigned int)PhysTrackBuffer + unit[SelectedDrive].disktype->spt*512) { 891 /* already read enough data, force an FDC interrupt to stop 892 * the read operation 893 */ 894 SET_IRQ_HANDLER( NULL ); 895 restore_flags(flags); 896 DPRINT(("fd_readtrack_check(): done\n")); 897 FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI ); 898 udelay(25); 899 900 /* No error until now -- the FDC would have interrupted 901 * otherwise! 902 */ 903 fd_rwsec_done( 0 ); 904 } else { 905 /* not yet finished, wait another tenth rotation */ 906 restore_flags(flags); 907 DPRINT(("fd_readtrack_check(): not yet finished\n")); 908 readtrack_timer.expires = jiffies + HZ/5/10; 909 add_timer( &readtrack_timer ); 910 } 911} 912 913#endif 914 915static void fd_rwsec_done(int status) 916{ 917 unsigned int track; 918 919 DPRINT(("fd_rwsec_done() status=%d @ %d\n", status,jiffies)); 920 921#ifdef TRACKBUFFER 922 if (read_track && !MultReadInProgress) 923 return; 924 925 MultReadInProgress = 0; 926 927 STOP_TIMEOUT(); 928 929 if (read_track) 930 del_timer( &readtrack_timer ); 931#endif 932 933 934 /* Correct the track if stretch != 0 */ 935 if (unit[SelectedDrive].disktype->stretch) { 936 track = FDC1772_READ(FDC1772REG_TRACK); 937 FDC1772_WRITE(FDC1772REG_TRACK, track << 938 unit[SelectedDrive].disktype->stretch); 939 } 940 if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) { 941 printk("fd%d: is write protected\n", SelectedDrive); 942 goto err_end; 943 } 944 if ((status & FDC1772STAT_RECNF) 945#ifdef TRACKBUFFER 946 /* RECNF is no error after a multiple read when the FDC 947 * searched for a non-existant sector! 948 */ 949 && !(read_track && 950 FDC1772_READ(FDC1772REG_SECTOR) > unit[SelectedDrive].disktype->spt) 951#endif 952 ) { 953 if (Probing) { 954 if (unit[SelectedDrive].disktype > disk_type) { 955 /* try another disk type */ 956 unit[SelectedDrive].disktype--; 957 floppy_sizes[SelectedDrive] 958 = unit[SelectedDrive].disktype->blocks >> 1; 959 } else 960 Probing = 0; 961 } else { 962 /* record not found, but not probing. Maybe stretch wrong ? Restart probing */ 963 if (unit[SelectedDrive].autoprobe) { 964 unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1; 965 floppy_sizes[SelectedDrive] 966 = unit[SelectedDrive].disktype->blocks >> 1; 967 Probing = 1; 968 } 969 } 970 if (Probing) { 971 setup_req_params(SelectedDrive); 972#ifdef TRACKBUFFER 973 BufferDrive = -1; 974#endif 975 do_fd_action(SelectedDrive); 976 return; 977 } 978 printk("fd%d: sector %d not found (side %d, track %d)\n", 979 SelectedDrive, FDC1772_READ(FDC1772REG_SECTOR), ReqSide, ReqTrack); 980 goto err_end; 981 } 982 if (status & FDC1772STAT_CRC) { 983 printk("fd%d: CRC error (side %d, track %d, sector %d)\n", 984 SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR)); 985 goto err_end; 986 } 987 if (status & FDC1772STAT_LOST) { 988 printk("fd%d: lost data (side %d, track %d, sector %d)\n", 989 SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR)); 990 goto err_end; 991 } 992 Probing = 0; 993 994 if (ReqCmd == READ) { 995#ifdef TRACKBUFFER 996 if (!read_track) { 997 /*cache_clear (PhysDMABuffer, 512);*/ 998 copy_buffer (DMABuffer, ReqData); 999 } else { 1000 /*cache_clear (PhysTrackBuffer, FD1772_MAX_SECTORS * 512);*/ 1001 BufferDrive = SelectedDrive; 1002 BufferSide = ReqSide; 1003 BufferTrack = ReqTrack; 1004 copy_buffer (SECTOR_BUFFER (ReqSector), ReqData); 1005 } 1006#else 1007 /*cache_clear( PhysDMABuffer, 512 ); */ 1008 copy_buffer(DMABuffer, ReqData); 1009#endif 1010 } 1011 if (++ReqCnt < CURRENT->current_nr_sectors) { 1012 /* read next sector */ 1013 setup_req_params(SelectedDrive); 1014 do_fd_action(SelectedDrive); 1015 } else { 1016 /* all sectors finished */ 1017 CURRENT->nr_sectors -= CURRENT->current_nr_sectors; 1018 CURRENT->sector += CURRENT->current_nr_sectors; 1019 end_request(1); 1020 redo_fd_request(); 1021 } 1022 return; 1023 1024err_end: 1025#ifdef TRACKBUFFER 1026 BufferDrive = -1; 1027#endif 1028 1029 fd_error(); 1030} 1031 1032 1033static void fd_times_out(unsigned long dummy) 1034{ 1035 SET_IRQ_HANDLER(NULL); 1036 /* If the timeout occurred while the readtrack_check timer was 1037 * active, we need to cancel it, else bad things will happen */ 1038 del_timer( &readtrack_timer ); 1039 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI); 1040 udelay(25); 1041 1042 printk("floppy timeout\n"); 1043 STOP_TIMEOUT(); /* hmm - should we do this ? */ 1044 fd_error(); 1045} 1046 1047 1048/* The (noop) seek operation here is needed to make the WP bit in the 1049 * FDC1772 status register accessible for check_change. If the last disk 1050 * operation would have been a RDSEC, this bit would always read as 0 1051 * no matter what :-( To save time, the seek goes to the track we're 1052 * already on. 1053 */ 1054 1055static void finish_fdc(void) 1056{ 1057 /* DAG - just try without this dummy seek! */ 1058 finish_fdc_done(0); 1059 return; 1060 1061 if (!NeedSeek) { 1062 finish_fdc_done(0); 1063 } else { 1064 DPRINT(("finish_fdc: dummy seek started\n")); 1065 FDC1772_WRITE(FDC1772REG_DATA, unit[SelectedDrive].track); 1066 SET_IRQ_HANDLER(finish_fdc_done); 1067 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK); 1068 MotorOn = 1; 1069 START_TIMEOUT(); 1070 /* we must wait for the IRQ here, because the ST-DMA is 1071 * released immediatly afterwards and the interrupt may be 1072 * delivered to the wrong driver. 1073 */ 1074 } 1075} 1076 1077 1078static void finish_fdc_done(int dummy) 1079{ 1080 unsigned long flags; 1081 1082 DPRINT(("finish_fdc_done entered\n")); 1083 STOP_TIMEOUT(); 1084 NeedSeek = 0; 1085 1086 if (timer_pending(&fd_timer) && 1087 time_after(jiffies + 5, fd_timer.expires)) 1088 /* If the check for a disk change is done too early after this 1089 * last seek command, the WP bit still reads wrong :-(( 1090 */ 1091 mod_timer(&fd_timer, jiffies + 5); 1092 else { 1093 /* START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */ 1094 }; 1095 del_timer(&motor_off_timer); 1096 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY); 1097 1098 save_flags(flags); 1099 cli(); 1100 /* stdma_release(); - not sure if I should do something DAG */ 1101 fdc_busy = 0; 1102 wake_up(&fdc_wait); 1103 restore_flags(flags); 1104 1105 DPRINT(("finish_fdc() finished\n")); 1106} 1107 1108 1109/* Prevent "aliased" accesses. */ 1110static int fd_ref[4]; 1111static int fd_device[4]; 1112 1113/* 1114 * Current device number. Taken either from the block header or from the 1115 * format request descriptor. 1116 */ 1117#define CURRENT_DEVICE (CURRENT->rq_dev) 1118 1119/* Current error count. */ 1120#define CURRENT_ERRORS (CURRENT->errors) 1121 1122 1123/* dummy for blk.h */ 1124static void floppy_off(unsigned int nr) 1125{ 1126} 1127 1128 1129/* On the old arcs write protect depends on the particular model 1130 of machine. On the A310, R140, and A440 there is a disc changed 1131 detect, however on the A4x0/1 range there is not. There 1132 is nothing to tell you which machine your on. 1133 At the moment I'm just marking changed always. I've 1134 left the Atari's 'change on write protect change' code in this 1135 part (but nothing sets it). 1136 RiscOS apparently checks the disc serial number etc. to detect changes 1137 - but if it sees a disc change line go high (?) it flips to using 1138 it. Well maybe I'll add that in the future (!?) 1139*/ 1140static int check_floppy_change(dev_t dev) 1141{ 1142 unsigned int drive = (dev & 0x03); 1143 1144 if (MAJOR(dev) != MAJOR_NR) { 1145 printk("floppy_changed: not a floppy\n"); 1146 return 0; 1147 } 1148 if (test_bit(drive, &fake_change)) { 1149 /* simulated change (e.g. after formatting) */ 1150 return 1; 1151 } 1152 if (test_bit(drive, &changed_floppies)) { 1153 /* surely changed (the WP signal changed at least once) */ 1154 return 1; 1155 } 1156 if (unit[drive].wpstat) { 1157 /* WP is on -> could be changed: to be sure, buffers should be 1158 * invalidated... 1159 */ 1160 return 1; 1161 } 1162 return 1; /* DAG - was 0 */ 1163} 1164 1165static int floppy_revalidate(dev_t dev) 1166{ 1167 int drive = dev & 3; 1168 1169 if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change) 1170 || unit[drive].disktype == 0) { 1171#ifdef TRACKBUFFER 1172 BufferDrive = -1; 1173#endif 1174 clear_bit(drive, &fake_change); 1175 clear_bit(drive, &changed_floppies); 1176 unit[drive].disktype = 0; 1177 } 1178 return 0; 1179} 1180 1181static __inline__ void copy_buffer(void *from, void *to) 1182{ 1183 ulong *p1 = (ulong *) from, *p2 = (ulong *) to; 1184 int cnt; 1185 1186 for (cnt = 512 / 4; cnt; cnt--) 1187 *p2++ = *p1++; 1188} 1189 1190 1191/* This sets up the global variables describing the current request. */ 1192 1193static void setup_req_params(int drive) 1194{ 1195 int block = ReqBlock + ReqCnt; 1196 1197 ReqTrack = block / unit[drive].disktype->spt; 1198 ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1; 1199 ReqSide = ReqTrack & 1; 1200 ReqTrack >>= 1; 1201 ReqData = ReqBuffer + 512 * ReqCnt; 1202 1203#ifdef TRACKBUFFER 1204 read_track = (ReqCmd == READ && CURRENT_ERRORS == 0); 1205#endif 1206 1207 DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n", ReqSide, 1208 ReqTrack, ReqSector, (unsigned long) ReqData)); 1209} 1210 1211 1212static void redo_fd_request(void) 1213{ 1214 int device, drive, type; 1215 struct archy_floppy_struct *floppy; 1216 1217 DPRINT(("redo_fd_request: CURRENT=%08lx CURRENT->rq_dev=%04x CURRENT->sector=%ld\n", 1218 (unsigned long) CURRENT, CURRENT ? CURRENT->rq_dev : 0, 1219 !QUEUE_EMPTY ? CURRENT->sector : 0)); 1220 1221 if (!QUEUE_EMPTY && CURRENT->rq_status == RQ_INACTIVE) 1222 goto the_end; 1223 1224repeat: 1225 1226 if (QUEUE_EMPTY) 1227 goto the_end; 1228 1229 if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) 1230 panic(DEVICE_NAME ": request list destroyed"); 1231 1232 if (CURRENT->bh) { 1233 if (!buffer_locked(CURRENT->bh)) 1234 panic(DEVICE_NAME ": block not locked"); 1235 } 1236 device = MINOR(CURRENT_DEVICE); 1237 drive = device & 3; 1238 type = device >> 2; 1239 floppy = &unit[drive]; 1240 1241 if (!floppy->connected) { 1242 /* drive not connected */ 1243 printk("Unknown Device: fd%d\n", drive); 1244 end_request(0); 1245 goto repeat; 1246 } 1247 if (type == 0) { 1248 if (!floppy->disktype) { 1249 Probing = 1; 1250 floppy->disktype = disk_type + NUM_DISK_TYPES - 1; 1251 floppy_sizes[drive] = floppy->disktype->blocks >> 1; 1252 floppy->autoprobe = 1; 1253 } 1254 } else { 1255 /* user supplied disk type */ 1256 --type; 1257 if (type >= NUM_DISK_TYPES) { 1258 printk("fd%d: invalid disk format", drive); 1259 end_request(0); 1260 goto repeat; 1261 } 1262 floppy->disktype = &disk_type[type]; 1263 floppy_sizes[drive] = disk_type[type].blocks >> 1; 1264 floppy->autoprobe = 0; 1265 } 1266 1267 if (CURRENT->sector + 1 > floppy->disktype->blocks) { 1268 end_request(0); 1269 goto repeat; 1270 } 1271 /* stop deselect timer */ 1272 del_timer(&motor_off_timer); 1273 1274 ReqCnt = 0; 1275 ReqCmd = CURRENT->cmd; 1276 ReqBlock = CURRENT->sector; 1277 ReqBuffer = CURRENT->buffer; 1278 setup_req_params(drive); 1279 do_fd_action(drive); 1280 1281 return; 1282 1283the_end: 1284 finish_fdc(); 1285} 1286 1287static void fd1772_checkint(void) 1288{ 1289 extern int fdc1772_bytestogo; 1290 1291 /*printk("fd1772_checkint %d\n",fdc1772_fdc_int_done);*/ 1292 if (fdc1772_fdc_int_done) 1293 floppy_irqconsequencehandler(); 1294 if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0); 1295 if (fdc_busy) { 1296 queue_task(&fd1772_tq,&tq_immediate); 1297 mark_bh(IMMEDIATE_BH); 1298 } 1299} 1300 1301void do_fd_request(request_queue_t* q) 1302{ 1303 unsigned long flags; 1304 1305 DPRINT(("do_fd_request for pid %d\n", current->pid)); 1306 if (fdc_busy) return; 1307 save_flags(flags); 1308 cli(); 1309 while (fdc_busy) 1310 sleep_on(&fdc_wait); 1311 fdc_busy = 1; 1312 ENABLE_IRQ(); 1313 restore_flags(flags); 1314 1315 fdc1772_fdc_int_done = 0; 1316 1317 redo_fd_request(); 1318 1319 queue_task(&fd1772_tq,&tq_immediate); 1320 mark_bh(IMMEDIATE_BH); 1321} 1322 1323 1324static int invalidate_drive(int rdev) 1325{ 1326 /* invalidate the buffer track to force a reread */ 1327#ifdef TRACKBUFFER 1328 BufferDrive = -1; 1329#endif 1330 1331 set_bit(rdev & 3, &fake_change); 1332 check_disk_change(rdev); 1333 return 0; 1334} 1335 1336static int fd_ioctl(struct inode *inode, struct file *filp, 1337 unsigned int cmd, unsigned long param) 1338{ 1339 int drive, device; 1340 1341 device = inode->i_rdev; 1342 drive = MINOR(device); 1343 switch (cmd) { 1344 case FDFMTBEG: 1345 return 0; 1346 /* case FDC1772LRPRM: ??? DAG what does this do?? 1347 unit[drive].disktype = NULL; 1348 floppy_sizes[drive] = MAX_DISK_SIZE; 1349 return invalidate_drive (device); */ 1350 case FDFMTEND: 1351 case FDFLUSH: 1352 return invalidate_drive(drive); 1353 } 1354 if (!capable(CAP_SYS_ADMIN)) 1355 return -EPERM; 1356 if (drive < 0 || drive > 3) 1357 return -EINVAL; 1358 switch (cmd) { 1359 default: 1360 return -EINVAL; 1361 } 1362 return 0; 1363} 1364 1365 1366/* Initialize the 'unit' variable for drive 'drive' */ 1367 1368static void fd_probe(int drive) 1369{ 1370 unit[drive].connected = 0; 1371 unit[drive].disktype = NULL; 1372 1373 if (!fd_test_drive_present(drive)) 1374 return; 1375 1376 unit[drive].connected = 1; 1377 unit[drive].track = -1; /* If we put the auto detect back in this can go to 0 */ 1378 unit[drive].steprate = FDC1772STEP_6; 1379 MotorOn = 1; /* from probe restore operation! */ 1380} 1381 1382 1383/* This function tests the physical presence of a floppy drive (not 1384 * whether a disk is inserted). This is done by issuing a restore 1385 * command, waiting max. 2 seconds (that should be enough to move the 1386 * head across the whole disk) and looking at the state of the "TR00" 1387 * signal. This should now be raised if there is a drive connected 1388 * (and there is no hardware failure :-) Otherwise, the drive is 1389 * declared absent. 1390 */ 1391 1392static int fd_test_drive_present(int drive) 1393{ 1394 unsigned long timeout; 1395 unsigned char status; 1396 int ok; 1397 1398 printk("fd_test_drive_present %d\n", drive); 1399 if (drive > 1) 1400 return (0); 1401 return (1); /* Simple hack for the moment - the autodetect doesn't seem to work on arc */ 1402 fd_select_drive(drive); 1403 1404 /* disable interrupt temporarily */ 1405 DISABLE_IRQ(); 1406 FDC1772_WRITE(FDC1772REG_TRACK, 0x00); /* was ff00 why? */ 1407 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6); 1408 1409 /*printk("fd_test_drive_present: Going into timeout loop\n"); */ 1410 for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; time_before(jiffies, timeout);) { 1411 /* What does this piece of atariism do? - query for an interrupt? */ 1412 /* if (!(mfp.par_dt_reg & 0x20)) 1413 break; */ 1414 /* Well this is my nearest guess - quit when we get an FDC interrupt */ 1415 if (ioc_readb(IOC_FIQSTAT) & 2) 1416 break; 1417 } 1418 1419 /*printk("fd_test_drive_present: Coming out of timeout loop\n"); */ 1420 status = FDC1772_READ(FDC1772REG_STATUS); 1421 ok = (status & FDC1772STAT_TR00) != 0; 1422 1423 /*printk("fd_test_drive_present: ok=%d\n",ok); */ 1424 /* force interrupt to abort restore operation (FDC1772 would try 1425 * about 50 seconds!) */ 1426 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI); 1427 udelay(500); 1428 status = FDC1772_READ(FDC1772REG_STATUS); 1429 udelay(20); 1430 /*printk("fd_test_drive_present: just before OK code %d\n",ok); */ 1431 1432 if (ok) { 1433 /* dummy seek command to make WP bit accessible */ 1434 FDC1772_WRITE(FDC1772REG_DATA, 0); 1435 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK); 1436 printk("fd_test_drive_present: just before wait for int\n"); 1437 /* DAG: Guess means wait for interrupt */ 1438 while (!(ioc_readb(IOC_FIQSTAT) & 2)); 1439 printk("fd_test_drive_present: just after wait for int\n"); 1440 status = FDC1772_READ(FDC1772REG_STATUS); 1441 } 1442 printk("fd_test_drive_present: just before ENABLE_IRQ\n"); 1443 ENABLE_IRQ(); 1444 printk("fd_test_drive_present: about to return\n"); 1445 return (ok); 1446} 1447 1448 1449/* Look how many and which kind of drives are connected. If there are 1450 * floppies, additionally start the disk-change and motor-off timers. 1451 */ 1452 1453static void config_types(void) 1454{ 1455 int drive, cnt = 0; 1456 1457 printk("Probing floppy drive(s):\n"); 1458 for (drive = 0; drive < FD_MAX_UNITS; drive++) { 1459 fd_probe(drive); 1460 if (unit[drive].connected) { 1461 printk("fd%d\n", drive); 1462 ++cnt; 1463 } 1464 } 1465 1466 if (FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_BUSY) { 1467 /* If FDC1772 is still busy from probing, give it another FORCI 1468 * command to abort the operation. If this isn't done, the FDC1772 1469 * will interrupt later and its IRQ line stays low, because 1470 * the status register isn't read. And this will block any 1471 * interrupts on this IRQ line :-( 1472 */ 1473 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI); 1474 udelay(500); 1475 FDC1772_READ(FDC1772REG_STATUS); 1476 udelay(20); 1477 } 1478 if (cnt > 0) { 1479 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY); 1480 if (cnt == 1) 1481 fd_select_drive(0); 1482 /*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */ 1483 } 1484} 1485 1486/* 1487 * floppy_open check for aliasing (/dev/fd0 can be the same as 1488 * /dev/PS0 etc), and disallows simultaneous access to the same 1489 * drive with different device numbers. 1490 */ 1491 1492static int floppy_open(struct inode *inode, struct file *filp) 1493{ 1494 int drive; 1495 int old_dev; 1496 1497 if (!filp) { 1498 DPRINT(("Weird, open called with filp=0\n")); 1499 return -EIO; 1500 } 1501 drive = MINOR(inode->i_rdev) & 3; 1502 if ((MINOR(inode->i_rdev) >> 2) > NUM_DISK_TYPES) 1503 return -ENXIO; 1504 1505 old_dev = fd_device[drive]; 1506 1507 if (fd_ref[drive]) 1508 if (old_dev != inode->i_rdev) 1509 return -EBUSY; 1510 1511 if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL)) 1512 return -EBUSY; 1513 1514 if (filp->f_flags & O_EXCL) 1515 fd_ref[drive] = -1; 1516 else 1517 fd_ref[drive]++; 1518 1519 fd_device[drive] = inode->i_rdev; 1520 1521 if (old_dev && old_dev != inode->i_rdev) 1522 invalidate_buffers(old_dev); 1523 1524 if (filp->f_flags & O_NDELAY) 1525 return 0; 1526 1527 if (filp->f_mode & 3) { 1528 check_disk_change(inode->i_rdev); 1529 if (filp->f_mode & 2) { 1530 if (unit[drive].wpstat) { 1531 floppy_release(inode, filp); 1532 return -EROFS; 1533 } 1534 } 1535 } 1536 return 0; 1537} 1538 1539 1540static int floppy_release(struct inode *inode, struct file *filp) 1541{ 1542 int drive = MINOR(inode->i_rdev) & 3; 1543 1544 if (fd_ref[drive] < 0) 1545 fd_ref[drive] = 0; 1546 else if (!fd_ref[drive]--) { 1547 printk("floppy_release with fd_ref == 0"); 1548 fd_ref[drive] = 0; 1549 } 1550 1551 return 0; 1552} 1553 1554static struct block_device_operations floppy_fops = 1555{ 1556 open: floppy_open, 1557 release: floppy_release, 1558 ioctl: fd_ioctl, 1559 check_media_change: check_floppy_change, 1560 revalidate: floppy_revalidate, 1561}; 1562 1563 1564int fd1772_init(void) 1565{ 1566 int err; 1567 int i; 1568 1569 if (!machine_is_archimedes()) 1570 return 0; 1571 1572 if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) { 1573 printk("Unable to get major %d for floppy\n", MAJOR_NR); 1574 return 1; 1575 } 1576 1577 if (request_dma(FLOPPY_DMA, "fd1772")) { 1578 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA); 1579 return 1; 1580 }; 1581 1582 if (request_dma(FIQ_FD1772, "fd1772 end")) { 1583 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772); 1584 err = 1; 1585 goto cleanup_dma; 1586 }; 1587 1588 /* initialize variables */ 1589 err = -ENOMEM; 1590 SelectedDrive = -1; 1591#ifdef TRACKBUFFER 1592 BufferDrive = BufferSide = BufferTrack = -1; 1593 /* Atari uses 512 - I want to eventually cope with 1K sectors */ 1594 DMABuffer = (char *)kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL); 1595 if (DMABuffer == NULL) 1596 goto cleanup_dma; 1597 TrackBuffer = DMABuffer + 512; 1598#else 1599 /* Allocate memory for the DMAbuffer - on the Atari this takes it 1600 out of some special memory... */ 1601 DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */ 1602 if (DMABuffer == NULL) 1603 goto cleanup_dma; 1604#endif 1605 enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */ 1606 for (i = 0; i < FD_MAX_UNITS; i++) { 1607 unit[i].track = -1; 1608 } 1609 1610 for (i = 0; i < 256; i++) 1611 if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_TYPES) 1612 floppy_sizes[i] = disk_type[(i >> 2) - 1].blocks >> 1; 1613 else 1614 floppy_sizes[i] = MAX_DISK_SIZE; 1615 1616 blk_size[MAJOR_NR] = floppy_sizes; 1617 blksize_size[MAJOR_NR] = floppy_blocksizes; 1618 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); 1619 1620 config_types(); 1621 1622 return 0; 1623cleanup_dma: 1624 free_dma(FLOPPY_DMA); 1625 return err; 1626} 1627