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)
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
14 * - Autodetection of disk format (DD/HD); untested yet, because I
15 * don't have an HD drive :-(
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
23 * Changes by Andreas Schwab:
24 * - After errors in multiple read mode try again reading single sectors
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
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...
37 * - Maybe a better strategy for disk change detection (does anyone
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...
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
56 * 7/ 1/96 - Wrote FIQ code, removed most remaining atariisms
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.
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
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.
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
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
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.....
116 * 16/11/96 - Fiddled and frigged for 2.0.18
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
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
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>
142 #include <asm/arch/oldlatches.h>
143 #include <asm/bitops.h>
145 #include <asm/hardware.h>
146 #include <asm/hardware/ioc.h>
149 #include <asm/mach-types.h>
150 #include <asm/pgtable.h>
151 #include <asm/system.h>
152 #include <asm/uaccess.h>
155 #define MAJOR_NR FLOPPY_MAJOR
157 #include <linux/blk.h>
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!)
166 #define FD_MAX_UNITS 2
169 /* Ditto worries for Arc - DAG */
170 #define FD_MAX_UNITS 4
171 #define TRACKBUFFER 0
175 #define DPRINT(a) printk a
181 static struct archy_disk_type {
183 unsigned spt; /* sectors per track */
184 unsigned blocks; /* total number of blocks */
185 unsigned stretch; /* track doubling ? */
188 { "d360", 9, 720, 0 }, /* 360kB diskette */
189 { "D360", 9, 720, 1 }, /* 360kb in 720kb drive */
190 { "D720", 9, 1440, 0 }, /* 720kb diskette (DD) */
191 /*{ "D820", 10,1640, 0}, *//* DD disk with 82 tracks/10 sectors
192 - DAG - can't see how type detect can distinguish this
193 from 720K until it reads block 4 by which time its too late! */
196 #define NUM_DISK_TYPES (sizeof(disk_type)/sizeof(*disk_type))
199 * Maximum disk size (in kilobytes). This default is used whenever the
200 * current disk size is unknown.
202 #define MAX_DISK_SIZE 720
204 static int floppy_sizes[256];
205 static int floppy_blocksizes[256];
207 /* current info on each unit */
208 static struct archy_floppy_struct {
209 int connected; /* !=0 : drive is connected */
210 int autoprobe; /* !=0 : do autoprobe */
212 struct archy_disk_type *disktype; /* current type of disk */
214 int track; /* current head position or -1
216 unsigned int steprate; /* steprate setting */
217 unsigned int wpstat; /* current state of WP signal
218 * (for disk change detection) */
219 } unit[FD_MAX_UNITS];
221 /* DAG: On Arc we spin on a flag being cleared by fdc1772_comendhandler which
222 is an assembler routine */
223 extern void fdc1772_comendhandler(void); /* Actually doens't have these parameters - see fd1772.S */
224 extern volatile int fdc1772_comendstatus;
225 extern volatile int fdc1772_fdc_int_done;
227 #define FDC1772BASE ((0x210000>>2)|0x80000000)
229 #define FDC1772_READ(reg) inb(FDC1772BASE+(reg/2))
231 /* DAG: You wouldn't be silly to ask why FDC1772_WRITE is a function rather
232 than the #def below - well simple - the #def won't compile - and I
233 don't understand why (__outwc not defined) */
234 /* NOTE: Reg is 0,2,4,6 as opposed to 0,1,2,3 or 0,4,8,12 to keep compatibility
235 with the ST version of fd1772.h */
236 /*#define FDC1772_WRITE(reg,val) outw(val,(reg+FDC1772BASE)); */
237 void FDC1772_WRITE(int reg, unsigned char val)
239 if (reg == FDC1772REG_CMD) {
240 DPRINT(("FDC1772_WRITE new command 0x%x @ %d\n", val,jiffies));
241 if (fdc1772_fdc_int_done) {
242 DPRINT(("FDC1772_WRITE: Hmm fdc1772_fdc_int_done true - resetting\n"));
243 fdc1772_fdc_int_done = 0;
246 outb(val, (reg / 2) + FDC1772BASE);
249 #define FD1772_MAX_SECTORS 22
251 unsigned char *DMABuffer; /* buffer for writes */
252 /*static unsigned long PhysDMABuffer; *//* physical address */
253 /* DAG: On Arc we just go straight for the DMA buffer */
254 #define PhysDMABuffer DMABuffer
257 unsigned char *TrackBuffer; /* buffer for reads */
258 #define PhysTrackBuffer TrackBuffer /* physical address */
259 static int BufferDrive, BufferSide, BufferTrack;
260 static int read_track; /* non-zero if we are reading whole tracks */
262 #define SECTOR_BUFFER(sec) (TrackBuffer + ((sec)-1)*512)
263 #define IS_BUFFERED(drive,side,track) \
264 (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track))
268 * These are global variables, as that's the easiest way to give
269 * information to interrupts. They are the data used for the current
272 static int SelectedDrive = 0;
273 static int ReqCmd, ReqBlock;
274 static int ReqSide, ReqTrack, ReqSector, ReqCnt;
275 static int HeadSettleFlag = 0;
276 static unsigned char *ReqData, *ReqBuffer;
277 static int MotorOn = 0, MotorOffTrys;
279 /* Synchronization of FDC1772 access. */
280 static volatile int fdc_busy = 0;
281 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
284 /* long req'd for set_bit --RR */
285 static unsigned long changed_floppies = 0xff, fake_change = 0;
286 #define CHECK_CHANGE_DELAY HZ/2
288 /* DAG - increased to 30*HZ - not sure if this is the correct thing to do */
289 #define FD_MOTOR_OFF_DELAY (10*HZ)
290 #define FD_MOTOR_OFF_MAXTRY (10*20)
292 #define FLOPPY_TIMEOUT (6*HZ)
293 #define RECALIBRATE_ERRORS 4 /* After this many errors the drive
294 * will be recalibrated. */
295 #define MAX_ERRORS 8 /* After this many errors the driver
298 #define START_MOTOR_OFF_TIMER(delay) \
300 motor_off_timer.expires = jiffies + (delay); \
301 add_timer( &motor_off_timer ); \
305 #define START_CHECK_CHANGE_TIMER(delay) \
307 mod_timer(&fd_timer, jiffies + (delay)); \
310 #define START_TIMEOUT() \
312 mod_timer(&timeout_timer, jiffies+FLOPPY_TIMEOUT); \
315 #define STOP_TIMEOUT() \
317 del_timer( &timeout_timer ); \
320 #define ENABLE_IRQ() enable_irq(FIQ_FD1772+64);
322 #define DISABLE_IRQ() disable_irq(FIQ_FD1772+64);
324 static void fd1772_checkint(void);
326 struct tq_struct fd1772_tq =
327 { 0,0, (void *)fd1772_checkint, 0 };
329 * The driver is trying to determine the correct media format
330 * while Probing is set. fd_rwsec_done() clears it after a
333 static int Probing = 0;
335 /* This flag is set when a dummy seek is necesary to make the WP
336 * status bit accessible.
338 static int NeedSeek = 0;
341 /***************************** Prototypes *****************************/
343 static void fd_select_side(int side);
344 static void fd_select_drive(int drive);
345 static void fd_deselect(void);
346 static void fd_motor_off_timer(unsigned long dummy);
347 static void check_change(unsigned long dummy);
348 static __inline__ void set_head_settle_flag(void);
349 static __inline__ int get_head_settle_flag(void);
350 static void floppy_irqconsequencehandler(void);
351 static void fd_error(void);
352 static void do_fd_action(int drive);
353 static void fd_calibrate(void);
354 static void fd_calibrate_done(int status);
355 static void fd_seek(void);
356 static void fd_seek_done(int status);
357 static void fd_rwsec(void);
359 static void fd_readtrack_check( unsigned long dummy );
361 static void fd_rwsec_done(int status);
362 static void fd_times_out(unsigned long dummy);
363 static void finish_fdc(void);
364 static void finish_fdc_done(int dummy);
365 static void floppy_off(unsigned int nr);
366 static __inline__ void copy_buffer(void *from, void *to);
367 static void setup_req_params(int drive);
368 static void redo_fd_request(void);
369 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int
370 cmd, unsigned long param);
371 static void fd_probe(int drive);
372 static int fd_test_drive_present(int drive);
373 static void config_types(void);
374 static int floppy_open(struct inode *inode, struct file *filp);
375 static int floppy_release(struct inode *inode, struct file *filp);
377 /************************* End of Prototypes **************************/
379 static struct timer_list motor_off_timer = {
380 function: fd_motor_off_timer,
384 static struct timer_list readtrack_timer = {
385 function: fd_readtrack_check,
389 static struct timer_list timeout_timer = {
390 function: fd_times_out,
393 static struct timer_list fd_timer = {
394 function: check_change,
397 /* DAG: Haven't got a clue what this is? */
398 int stdma_islocked(void)
403 /* Select the side to use. */
405 static void fd_select_side(int side)
407 oldlatch_aupdate(LATCHA_SIDESEL, side ? 0 : LATCHA_SIDESEL);
411 /* Select a drive, update the FDC1772's track register
414 static void fd_select_drive(int drive)
417 printk("fd_select_drive:%d\n", drive);
419 /* Hmm - nowhere do we seem to turn the motor on - I'm going to do it here! */
420 oldlatch_aupdate(LATCHA_MOTOR | LATCHA_INUSE, 0);
422 if (drive == SelectedDrive)
425 oldlatch_aupdate(LATCHA_FDSELALL, 0xf - (1 << drive));
427 /* restore track register to saved value */
428 FDC1772_WRITE(FDC1772REG_TRACK, unit[drive].track);
431 SelectedDrive = drive;
435 /* Deselect both drives. */
437 static void fd_deselect(void)
441 DPRINT(("fd_deselect\n"));
443 oldlatch_aupdate(LATCHA_FDSELALL | LATCHA_MOTOR | LATCHA_INUSE, 0xf | LATCHA_MOTOR | LATCHA_INUSE);
449 /* This timer function deselects the drives when the FDC1772 switched the
450 * motor off. The deselection cannot happen earlier because the FDC1772
451 * counts the index signals, which arrive only if one drive is selected.
454 static void fd_motor_off_timer(unsigned long dummy)
457 unsigned char status;
460 del_timer(&motor_off_timer);
462 if (SelectedDrive < 0)
463 /* no drive selected, needn't deselect anyone */
469 if (fdc_busy) /* was stdma_islocked */
472 status = FDC1772_READ(FDC1772REG_STATUS);
474 if (!(status & 0x80)) {
476 * motor already turned off by FDC1772 -> deselect drives
477 * In actual fact its this deselection which turns the motor
478 * off on the Arc, since the motor control is actually on
481 DPRINT(("fdc1772: deselecting in fd_motor_off_timer\n"));
484 restore_flags(flags);
487 /* not yet off, try again */
490 restore_flags(flags);
491 /* Test again later; if tested too often, it seems there is no disk
492 * in the drive and the FDC1772 will leave the motor on forever (or,
493 * at least until a disk is inserted). So we'll test only twice
494 * per second from then on...
496 delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ?
497 (++MotorOffTrys, HZ / 20) : HZ / 2;
498 START_MOTOR_OFF_TIMER(delay);
502 /* This function is repeatedly called to detect disk changes (as good
503 * as possible) and keep track of the current state of the write protection.
506 static void check_change(unsigned long dummy)
508 static int drive = 0;
514 return; /* Don't start poking about if the fdc is busy */
516 return; /* let's just forget it for the mo DAG */
518 if (++drive > 1 || !unit[drive].connected)
524 if (!stdma_islocked()) {
525 stat = !!(FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_WPROT);
527 /* The idea here is that if the write protect line has changed then
528 the disc must have changed */
529 if (stat != unit[drive].wpstat) {
530 DPRINT(("wpstat[%d] = %d\n", drive, stat));
531 unit[drive].wpstat = stat;
532 set_bit(drive, &changed_floppies);
535 restore_flags(flags);
537 START_CHECK_CHANGE_TIMER(CHECK_CHANGE_DELAY);
541 /* Handling of the Head Settling Flag: This flag should be set after each
542 * seek operation, because we don't use seeks with verify.
545 static __inline__ void set_head_settle_flag(void)
547 HeadSettleFlag = FDC1772CMDADD_E;
550 static __inline__ int get_head_settle_flag(void)
552 int tmp = HeadSettleFlag;
560 /* General Interrupt Handling */
562 static void (*FloppyIRQHandler) (int status) = NULL;
564 static void floppy_irqconsequencehandler(void)
566 unsigned char status;
567 void (*handler) (int);
569 fdc1772_fdc_int_done = 0;
571 handler = FloppyIRQHandler;
572 FloppyIRQHandler = NULL;
576 status = (unsigned char) fdc1772_comendstatus;
577 DPRINT(("FDC1772 irq, status = %02x handler = %08lx\n", (unsigned int) status, (unsigned long) handler));
580 DPRINT(("FDC1772 irq, no handler status=%02x\n", fdc1772_comendstatus));
582 DPRINT(("FDC1772 irq: end of floppy_irq\n"));
586 /* Error handling: If some error happened, retry some times, then
587 * recalibrate, then try again, and fail after MAX_ERRORS.
590 static void fd_error(void)
592 printk("FDC1772: fd_error\n");
593 /*panic("fd1772: fd_error"); *//* DAG tmp */
597 if (CURRENT->errors >= MAX_ERRORS) {
598 printk("fd%d: too many errors.\n", SelectedDrive);
600 } else if (CURRENT->errors == RECALIBRATE_ERRORS) {
601 printk("fd%d: recalibrating\n", SelectedDrive);
602 if (SelectedDrive != -1)
603 unit[SelectedDrive].track = -1;
610 #define SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0)
613 /* do_fd_action() is the general procedure for a fd request: All
614 * required parameter settings (drive select, side select, track
615 * position) are checked and set if needed. For each of these
616 * parameters and the actual reading or writing exist two functions:
617 * one that starts the setting (or skips it if possible) and one
618 * callback for the "done" interrupt. Each done func calls the next
619 * set function to propagate the request down to fd_rwsec_done().
622 static void do_fd_action(int drive)
624 DPRINT(("do_fd_action unit[drive].track=%d\n", unit[drive].track));
629 if (IS_BUFFERED( drive, ReqSide, ReqTrack )) {
630 if (ReqCmd == READ) {
631 copy_buffer( SECTOR_BUFFER(ReqSector), ReqData );
632 if (++ReqCnt < CURRENT->current_nr_sectors) {
633 /* read next sector */
634 setup_req_params( drive );
637 /* all sectors finished */
638 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
639 CURRENT->sector += CURRENT->current_nr_sectors;
645 /* cmd == WRITE, pay attention to track buffer
647 copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) );
652 if (SelectedDrive != drive) {
653 /*unit[drive].track = -1; DAG */
654 fd_select_drive(drive);
658 if (unit[drive].track == -1)
660 else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch)
667 /* Seek to track 0 if the current track is unknown */
669 static void fd_calibrate(void)
671 DPRINT(("fd_calibrate\n"));
672 if (unit[SelectedDrive].track >= 0) {
673 fd_calibrate_done(0);
676 DPRINT(("fd_calibrate (after track compare)\n"));
677 SET_IRQ_HANDLER(fd_calibrate_done);
678 /* we can't verify, since the speed may be incorrect */
679 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate);
688 static void fd_calibrate_done(int status)
690 DPRINT(("fd_calibrate_done()\n"));
693 /* set the correct speed now */
694 if (status & FDC1772STAT_RECNF) {
695 printk("fd%d: restore failed\n", SelectedDrive);
698 unit[SelectedDrive].track = 0;
704 /* Seek the drive to the requested track. The drive must have been
705 * calibrated at some point before this.
708 static void fd_seek(void)
711 DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n", ReqTrack,
712 unit[SelectedDrive].track));
713 if (unit[SelectedDrive].track == ReqTrack <<
714 unit[SelectedDrive].disktype->stretch) {
718 FDC1772_WRITE(FDC1772REG_DATA, ReqTrack <<
719 unit[SelectedDrive].disktype->stretch);
723 SET_IRQ_HANDLER(fd_seek_done);
724 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate |
726 (MotorOn?FDC1772CMDADD_H:0));
728 restore_flags(flags);
730 set_head_settle_flag();
736 static void fd_seek_done(int status)
738 DPRINT(("fd_seek_done()\n"));
741 /* set the correct speed */
742 if (status & FDC1772STAT_RECNF) {
743 printk("fd%d: seek error (to track %d)\n",
744 SelectedDrive, ReqTrack);
745 /* we don't know exactly which track we are on now! */
746 unit[SelectedDrive].track = -1;
749 unit[SelectedDrive].track = ReqTrack <<
750 unit[SelectedDrive].disktype->stretch;
757 /* This does the actual reading/writing after positioning the head
758 * over the correct track.
762 static int MultReadInProgress = 0;
766 static void fd_rwsec(void)
768 unsigned long paddr, flags;
769 unsigned int rwflag, old_motoron;
772 DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n", ReqSector, ReqCmd == WRITE ? 'w' : 'r'));
773 if (ReqCmd == WRITE) {
774 /*cache_push( (unsigned long)ReqData, 512 ); */
775 paddr = (unsigned long) ReqData;
778 paddr = (unsigned long) PhysDMABuffer;
781 paddr = (unsigned long)PhysTrackBuffer;
786 DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n", rwflag,
787 ReqSector, FDC1772_READ(FDC1772REG_TRACK)));
788 fd_select_side(ReqSide);
790 /*DPRINT(("fd_rwsec() before start sector \n")); */
791 /* Start sector of this operation */
793 FDC1772_WRITE( FDC1772REG_SECTOR, !read_track ? ReqSector : 1 );
795 FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector );
798 /* Cheat for track if stretch != 0 */
799 if (unit[SelectedDrive].disktype->stretch) {
800 track = FDC1772_READ(FDC1772REG_TRACK);
801 FDC1772_WRITE(FDC1772REG_TRACK, track >>
802 unit[SelectedDrive].disktype->stretch);
806 DPRINT(("fd_rwsec() before setup DMA \n"));
807 /* Setup DMA - Heavily modified by DAG */
810 disable_dma(FLOPPY_DMA);
811 set_dma_mode(FLOPPY_DMA, rwflag ? DMA_MODE_WRITE : DMA_MODE_READ);
812 set_dma_addr(FLOPPY_DMA, (long) paddr); /* DAG - changed from Atari specific */
814 set_dma_count(FLOPPY_DMA,(!read_track ? 1 : unit[SelectedDrive].disktype->spt)*512);
816 set_dma_count(FLOPPY_DMA, 512); /* Block/sector size - going to have to change */
818 SET_IRQ_HANDLER(fd_rwsec_done);
819 /* Turn on dma int */
820 enable_dma(FLOPPY_DMA);
821 /* Now give it something to do */
822 FDC1772_WRITE(FDC1772REG_CMD, (rwflag ? (FDC1772CMD_WRSEC | FDC1772CMDADD_P) :
824 (FDC1772CMD_RDSEC | (read_track ? FDC1772CMDADD_M : 0) |
825 /* Hmm - the idea here is to stop the FDC spinning the disc
826 up when we know that we already still have it spinning */
827 (MotorOn?FDC1772CMDADD_H:0))
833 restore_flags(flags);
834 DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n", flags));
835 /*sti(); *//* DAG - Hmm */
836 /* Hmm - should do something DAG */
837 old_motoron = MotorOn;
841 /* wait for interrupt */
846 * If reading a whole track, wait about one disk rotation and
847 * then check if all sectors are read. The FDC will even
848 * search for the first non-existant sector and need 1 sec to
849 * recognise that it isn't present :-(
851 /* 1 rot. + 5 rot.s if motor was off */
852 mod_timer(&readtrack_timer, jiffies + HZ/5 + (old_motoron ? 0 : HZ));
853 DPRINT(("Setting readtrack_timer to %d @ %d\n",
854 readtrack_timer.expires,jiffies));
855 MultReadInProgress = 1;
859 /*DPRINT(("fd_rwsec() before START_TIMEOUT \n")); */
861 /*DPRINT(("fd_rwsec() after START_TIMEOUT \n")); */
867 static void fd_readtrack_check(unsigned long dummy)
869 unsigned long flags, addr;
870 extern unsigned char *fdc1772_dataaddr;
872 DPRINT(("fd_readtrack_check @ %d\n",jiffies));
877 del_timer( &readtrack_timer );
879 if (!MultReadInProgress) {
880 /* This prevents a race condition that could arise if the
881 * interrupt is triggered while the calling of this timer
882 * callback function takes place. The IRQ function then has
883 * already cleared 'MultReadInProgress' when control flow
886 restore_flags(flags);
890 /* get the current DMA address */
891 addr=(unsigned long)fdc1772_dataaddr; /* DAG - ? */
892 DPRINT(("fd_readtrack_check: addr=%x PhysTrackBuffer=%x\n",addr,PhysTrackBuffer));
894 if (addr >= (unsigned int)PhysTrackBuffer + unit[SelectedDrive].disktype->spt*512) {
895 /* already read enough data, force an FDC interrupt to stop
898 SET_IRQ_HANDLER( NULL );
899 restore_flags(flags);
900 DPRINT(("fd_readtrack_check(): done\n"));
901 FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI );
904 /* No error until now -- the FDC would have interrupted
909 /* not yet finished, wait another tenth rotation */
910 restore_flags(flags);
911 DPRINT(("fd_readtrack_check(): not yet finished\n"));
912 readtrack_timer.expires = jiffies + HZ/5/10;
913 add_timer( &readtrack_timer );
919 static void fd_rwsec_done(int status)
923 DPRINT(("fd_rwsec_done() status=%d @ %d\n", status,jiffies));
926 if (read_track && !MultReadInProgress)
929 MultReadInProgress = 0;
934 del_timer( &readtrack_timer );
938 /* Correct the track if stretch != 0 */
939 if (unit[SelectedDrive].disktype->stretch) {
940 track = FDC1772_READ(FDC1772REG_TRACK);
941 FDC1772_WRITE(FDC1772REG_TRACK, track <<
942 unit[SelectedDrive].disktype->stretch);
944 if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) {
945 printk("fd%d: is write protected\n", SelectedDrive);
948 if ((status & FDC1772STAT_RECNF)
950 /* RECNF is no error after a multiple read when the FDC
951 * searched for a non-existant sector!
954 FDC1772_READ(FDC1772REG_SECTOR) > unit[SelectedDrive].disktype->spt)
958 if (unit[SelectedDrive].disktype > disk_type) {
959 /* try another disk type */
960 unit[SelectedDrive].disktype--;
961 floppy_sizes[SelectedDrive]
962 = unit[SelectedDrive].disktype->blocks >> 1;
966 /* record not found, but not probing. Maybe stretch wrong ? Restart probing */
967 if (unit[SelectedDrive].autoprobe) {
968 unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1;
969 floppy_sizes[SelectedDrive]
970 = unit[SelectedDrive].disktype->blocks >> 1;
975 setup_req_params(SelectedDrive);
979 do_fd_action(SelectedDrive);
982 printk("fd%d: sector %d not found (side %d, track %d)\n",
983 SelectedDrive, FDC1772_READ(FDC1772REG_SECTOR), ReqSide, ReqTrack);
986 if (status & FDC1772STAT_CRC) {
987 printk("fd%d: CRC error (side %d, track %d, sector %d)\n",
988 SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
991 if (status & FDC1772STAT_LOST) {
992 printk("fd%d: lost data (side %d, track %d, sector %d)\n",
993 SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
998 if (ReqCmd == READ) {
1001 /*cache_clear (PhysDMABuffer, 512);*/
1002 copy_buffer (DMABuffer, ReqData);
1004 /*cache_clear (PhysTrackBuffer, FD1772_MAX_SECTORS * 512);*/
1005 BufferDrive = SelectedDrive;
1006 BufferSide = ReqSide;
1007 BufferTrack = ReqTrack;
1008 copy_buffer (SECTOR_BUFFER (ReqSector), ReqData);
1011 /*cache_clear( PhysDMABuffer, 512 ); */
1012 copy_buffer(DMABuffer, ReqData);
1015 if (++ReqCnt < CURRENT->current_nr_sectors) {
1016 /* read next sector */
1017 setup_req_params(SelectedDrive);
1018 do_fd_action(SelectedDrive);
1020 /* all sectors finished */
1021 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
1022 CURRENT->sector += CURRENT->current_nr_sectors;
1037 static void fd_times_out(unsigned long dummy)
1039 SET_IRQ_HANDLER(NULL);
1040 /* If the timeout occurred while the readtrack_check timer was
1041 * active, we need to cancel it, else bad things will happen */
1042 del_timer( &readtrack_timer );
1043 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1046 printk("floppy timeout\n");
1047 STOP_TIMEOUT(); /* hmm - should we do this ? */
1052 /* The (noop) seek operation here is needed to make the WP bit in the
1053 * FDC1772 status register accessible for check_change. If the last disk
1054 * operation would have been a RDSEC, this bit would always read as 0
1055 * no matter what :-( To save time, the seek goes to the track we're
1059 static void finish_fdc(void)
1061 /* DAG - just try without this dummy seek! */
1068 DPRINT(("finish_fdc: dummy seek started\n"));
1069 FDC1772_WRITE(FDC1772REG_DATA, unit[SelectedDrive].track);
1070 SET_IRQ_HANDLER(finish_fdc_done);
1071 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1074 /* we must wait for the IRQ here, because the ST-DMA is
1075 * released immediatly afterwards and the interrupt may be
1076 * delivered to the wrong driver.
1082 static void finish_fdc_done(int dummy)
1084 unsigned long flags;
1086 DPRINT(("finish_fdc_done entered\n"));
1090 if (timer_pending(&fd_timer) &&
1091 time_after(jiffies + 5, fd_timer.expires))
1092 /* If the check for a disk change is done too early after this
1093 * last seek command, the WP bit still reads wrong :-((
1095 mod_timer(&fd_timer, jiffies + 5);
1097 /* START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1099 del_timer(&motor_off_timer);
1100 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1104 /* stdma_release(); - not sure if I should do something DAG */
1107 restore_flags(flags);
1109 DPRINT(("finish_fdc() finished\n"));
1113 /* Prevent "aliased" accesses. */
1114 static int fd_ref[4];
1115 static int fd_device[4];
1118 * Current device number. Taken either from the block header or from the
1119 * format request descriptor.
1121 #define CURRENT_DEVICE (CURRENT->rq_dev)
1123 /* Current error count. */
1124 #define CURRENT_ERRORS (CURRENT->errors)
1127 /* dummy for blk.h */
1128 static void floppy_off(unsigned int nr)
1133 /* On the old arcs write protect depends on the particular model
1134 of machine. On the A310, R140, and A440 there is a disc changed
1135 detect, however on the A4x0/1 range there is not. There
1136 is nothing to tell you which machine your on.
1137 At the moment I'm just marking changed always. I've
1138 left the Atari's 'change on write protect change' code in this
1139 part (but nothing sets it).
1140 RiscOS apparently checks the disc serial number etc. to detect changes
1141 - but if it sees a disc change line go high (?) it flips to using
1142 it. Well maybe I'll add that in the future (!?)
1144 static int check_floppy_change(dev_t dev)
1146 unsigned int drive = (dev & 0x03);
1148 if (MAJOR(dev) != MAJOR_NR) {
1149 printk("floppy_changed: not a floppy\n");
1152 if (test_bit(drive, &fake_change)) {
1153 /* simulated change (e.g. after formatting) */
1156 if (test_bit(drive, &changed_floppies)) {
1157 /* surely changed (the WP signal changed at least once) */
1160 if (unit[drive].wpstat) {
1161 /* WP is on -> could be changed: to be sure, buffers should be
1166 return 1; /* DAG - was 0 */
1169 static int floppy_revalidate(dev_t dev)
1171 int drive = dev & 3;
1173 if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change)
1174 || unit[drive].disktype == 0) {
1178 clear_bit(drive, &fake_change);
1179 clear_bit(drive, &changed_floppies);
1180 unit[drive].disktype = 0;
1185 static __inline__ void copy_buffer(void *from, void *to)
1187 ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
1190 for (cnt = 512 / 4; cnt; cnt--)
1195 /* This sets up the global variables describing the current request. */
1197 static void setup_req_params(int drive)
1199 int block = ReqBlock + ReqCnt;
1201 ReqTrack = block / unit[drive].disktype->spt;
1202 ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1;
1203 ReqSide = ReqTrack & 1;
1205 ReqData = ReqBuffer + 512 * ReqCnt;
1208 read_track = (ReqCmd == READ && CURRENT_ERRORS == 0);
1211 DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n", ReqSide,
1212 ReqTrack, ReqSector, (unsigned long) ReqData));
1216 static void redo_fd_request(void)
1218 int device, drive, type;
1219 struct archy_floppy_struct *floppy;
1221 DPRINT(("redo_fd_request: CURRENT=%08lx CURRENT->rq_dev=%04x CURRENT->sector=%ld\n",
1222 (unsigned long) CURRENT, CURRENT ? CURRENT->rq_dev : 0,
1223 !QUEUE_EMPTY ? CURRENT->sector : 0));
1225 if (!QUEUE_EMPTY && CURRENT->rq_status == RQ_INACTIVE)
1233 if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
1234 panic(DEVICE_NAME ": request list destroyed");
1237 if (!buffer_locked(CURRENT->bh))
1238 panic(DEVICE_NAME ": block not locked");
1240 device = MINOR(CURRENT_DEVICE);
1243 floppy = &unit[drive];
1245 if (!floppy->connected) {
1246 /* drive not connected */
1247 printk("Unknown Device: fd%d\n", drive);
1252 if (!floppy->disktype) {
1254 floppy->disktype = disk_type + NUM_DISK_TYPES - 1;
1255 floppy_sizes[drive] = floppy->disktype->blocks >> 1;
1256 floppy->autoprobe = 1;
1259 /* user supplied disk type */
1261 if (type >= NUM_DISK_TYPES) {
1262 printk("fd%d: invalid disk format", drive);
1266 floppy->disktype = &disk_type[type];
1267 floppy_sizes[drive] = disk_type[type].blocks >> 1;
1268 floppy->autoprobe = 0;
1271 if (CURRENT->sector + 1 > floppy->disktype->blocks) {
1275 /* stop deselect timer */
1276 del_timer(&motor_off_timer);
1279 ReqCmd = CURRENT->cmd;
1280 ReqBlock = CURRENT->sector;
1281 ReqBuffer = CURRENT->buffer;
1282 setup_req_params(drive);
1283 do_fd_action(drive);
1291 static void fd1772_checkint(void)
1293 extern int fdc1772_bytestogo;
1295 /*printk("fd1772_checkint %d\n",fdc1772_fdc_int_done);*/
1296 if (fdc1772_fdc_int_done)
1297 floppy_irqconsequencehandler();
1298 if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0);
1300 queue_task(&fd1772_tq,&tq_immediate);
1301 mark_bh(IMMEDIATE_BH);
1305 void do_fd_request(request_queue_t* q)
1307 unsigned long flags;
1309 DPRINT(("do_fd_request for pid %d\n", current->pid));
1310 if (fdc_busy) return;
1314 sleep_on(&fdc_wait);
1317 restore_flags(flags);
1319 fdc1772_fdc_int_done = 0;
1323 queue_task(&fd1772_tq,&tq_immediate);
1324 mark_bh(IMMEDIATE_BH);
1328 static int invalidate_drive(int rdev)
1330 /* invalidate the buffer track to force a reread */
1335 set_bit(rdev & 3, &fake_change);
1336 check_disk_change(rdev);
1340 static int fd_ioctl(struct inode *inode, struct file *filp,
1341 unsigned int cmd, unsigned long param)
1345 device = inode->i_rdev;
1346 drive = MINOR(device);
1350 /* case FDC1772LRPRM: ??? DAG what does this do??
1351 unit[drive].disktype = NULL;
1352 floppy_sizes[drive] = MAX_DISK_SIZE;
1353 return invalidate_drive (device); */
1356 return invalidate_drive(drive);
1358 if (!capable(CAP_SYS_ADMIN))
1360 if (drive < 0 || drive > 3)
1370 /* Initialize the 'unit' variable for drive 'drive' */
1372 static void fd_probe(int drive)
1374 unit[drive].connected = 0;
1375 unit[drive].disktype = NULL;
1377 if (!fd_test_drive_present(drive))
1380 unit[drive].connected = 1;
1381 unit[drive].track = -1; /* If we put the auto detect back in this can go to 0 */
1382 unit[drive].steprate = FDC1772STEP_6;
1383 MotorOn = 1; /* from probe restore operation! */
1387 /* This function tests the physical presence of a floppy drive (not
1388 * whether a disk is inserted). This is done by issuing a restore
1389 * command, waiting max. 2 seconds (that should be enough to move the
1390 * head across the whole disk) and looking at the state of the "TR00"
1391 * signal. This should now be raised if there is a drive connected
1392 * (and there is no hardware failure :-) Otherwise, the drive is
1396 static int fd_test_drive_present(int drive)
1398 unsigned long timeout;
1399 unsigned char status;
1402 printk("fd_test_drive_present %d\n", drive);
1405 return (1); /* Simple hack for the moment - the autodetect doesn't seem to work on arc */
1406 fd_select_drive(drive);
1408 /* disable interrupt temporarily */
1410 FDC1772_WRITE(FDC1772REG_TRACK, 0x00); /* was ff00 why? */
1411 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6);
1413 /*printk("fd_test_drive_present: Going into timeout loop\n"); */
1414 for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; time_before(jiffies, timeout);) {
1415 /* What does this piece of atariism do? - query for an interrupt? */
1416 /* if (!(mfp.par_dt_reg & 0x20))
1418 /* Well this is my nearest guess - quit when we get an FDC interrupt */
1419 if (ioc_readb(IOC_FIQSTAT) & 2)
1423 /*printk("fd_test_drive_present: Coming out of timeout loop\n"); */
1424 status = FDC1772_READ(FDC1772REG_STATUS);
1425 ok = (status & FDC1772STAT_TR00) != 0;
1427 /*printk("fd_test_drive_present: ok=%d\n",ok); */
1428 /* force interrupt to abort restore operation (FDC1772 would try
1429 * about 50 seconds!) */
1430 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1432 status = FDC1772_READ(FDC1772REG_STATUS);
1434 /*printk("fd_test_drive_present: just before OK code %d\n",ok); */
1437 /* dummy seek command to make WP bit accessible */
1438 FDC1772_WRITE(FDC1772REG_DATA, 0);
1439 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1440 printk("fd_test_drive_present: just before wait for int\n");
1441 /* DAG: Guess means wait for interrupt */
1442 while (!(ioc_readb(IOC_FIQSTAT) & 2));
1443 printk("fd_test_drive_present: just after wait for int\n");
1444 status = FDC1772_READ(FDC1772REG_STATUS);
1446 printk("fd_test_drive_present: just before ENABLE_IRQ\n");
1448 printk("fd_test_drive_present: about to return\n");
1453 /* Look how many and which kind of drives are connected. If there are
1454 * floppies, additionally start the disk-change and motor-off timers.
1457 static void config_types(void)
1461 printk("Probing floppy drive(s):\n");
1462 for (drive = 0; drive < FD_MAX_UNITS; drive++) {
1464 if (unit[drive].connected) {
1465 printk("fd%d\n", drive);
1470 if (FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_BUSY) {
1471 /* If FDC1772 is still busy from probing, give it another FORCI
1472 * command to abort the operation. If this isn't done, the FDC1772
1473 * will interrupt later and its IRQ line stays low, because
1474 * the status register isn't read. And this will block any
1475 * interrupts on this IRQ line :-(
1477 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1479 FDC1772_READ(FDC1772REG_STATUS);
1483 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1486 /*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1491 * floppy_open check for aliasing (/dev/fd0 can be the same as
1492 * /dev/PS0 etc), and disallows simultaneous access to the same
1493 * drive with different device numbers.
1496 static int floppy_open(struct inode *inode, struct file *filp)
1502 DPRINT(("Weird, open called with filp=0\n"));
1505 drive = MINOR(inode->i_rdev) & 3;
1506 if ((MINOR(inode->i_rdev) >> 2) > NUM_DISK_TYPES)
1509 old_dev = fd_device[drive];
1512 if (old_dev != inode->i_rdev)
1515 if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
1518 if (filp->f_flags & O_EXCL)
1523 fd_device[drive] = inode->i_rdev;
1525 if (old_dev && old_dev != inode->i_rdev)
1526 invalidate_buffers(old_dev);
1528 if (filp->f_flags & O_NDELAY)
1531 if (filp->f_mode & 3) {
1532 check_disk_change(inode->i_rdev);
1533 if (filp->f_mode & 2) {
1534 if (unit[drive].wpstat) {
1535 floppy_release(inode, filp);
1544 static int floppy_release(struct inode *inode, struct file *filp)
1546 int drive = MINOR(inode->i_rdev) & 3;
1548 if (fd_ref[drive] < 0)
1550 else if (!fd_ref[drive]--) {
1551 printk("floppy_release with fd_ref == 0");
1558 static struct block_device_operations floppy_fops =
1561 release: floppy_release,
1563 check_media_change: check_floppy_change,
1564 revalidate: floppy_revalidate,
1568 int fd1772_init(void)
1572 if (!machine_is_archimedes())
1575 err = register_blkdev(MAJOR_NR, "fd", &floppy_fops);
1577 printk("Unable to get major %d for floppy\n", MAJOR_NR);
1582 if (request_dma(FLOPPY_DMA, "fd1772")) {
1583 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA);
1587 if (request_dma(FIQ_FD1772, "fd1772 end")) {
1588 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772);
1592 /* initialize variables */
1596 BufferDrive = BufferSide = BufferTrack = -1;
1597 /* Atari uses 512 - I want to eventually cope with 1K sectors */
1598 DMABuffer = (char *)kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
1599 TrackBuffer = DMABuffer + 512;
1601 /* Allocate memory for the DMAbuffer - on the Atari this takes it
1602 out of some special memory... */
1603 DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */
1605 if (DMABuffer == NULL)
1608 enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */
1609 for (i = 0; i < FD_MAX_UNITS; i++) {
1613 for (i = 0; i < 256; i++)
1614 if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_TYPES)
1615 floppy_sizes[i] = disk_type[(i >> 2) - 1].blocks >> 1;
1617 floppy_sizes[i] = MAX_DISK_SIZE;
1619 blk_size[MAJOR_NR] = floppy_sizes;
1620 blksize_size[MAJOR_NR] = floppy_blocksizes;
1621 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
1628 free_dma(FIQ_FD1772);
1630 free_dma(FLOPPY_DMA);
1632 unregister_blkdev(MAJOR_NR, &floppy_fops);