ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / acorn / block / fd1772.c
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 sequence'
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/workqueue.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 /* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with
156  * little additional rework in this file). But I'm not yet sure if
157  * some other code depends on the number of floppies... (It is defined
158  * in a public header!)
159  */
160 #if 0
161 #undef FD_MAX_UNITS
162 #define FD_MAX_UNITS    2
163 #endif
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 static struct request_queue *floppy_queue;
177
178 #define MAJOR_NR FLOPPY_MAJOR
179 #define FLOPPY_DMA 0
180 #define DEVICE_NAME "floppy"
181 #define QUEUE (floppy_queue)
182 #define CURRENT elv_next_request(floppy_queue)
183
184 /* Disk types: DD */
185 static struct archy_disk_type {
186         const char *name;
187         unsigned spt;           /* sectors per track */
188         unsigned blocks;        /* total number of blocks */
189         unsigned stretch;       /* track doubling ? */
190 } disk_type[] = {
191
192         { "d360", 9, 720, 0 },                  /* 360kB diskette */
193         { "D360", 9, 720, 1 },                  /* 360kb in 720kb drive */
194         { "D720", 9, 1440, 0 },                 /* 720kb diskette (DD) */
195         /*{ "D820", 10,1640, 0}, *//* DD disk with 82 tracks/10 sectors 
196                                       - DAG - can't see how type detect can distinguish this
197                                       from 720K until it reads block 4 by which time its too late! */
198 };
199
200 #define NUM_DISK_TYPES (sizeof(disk_type)/sizeof(*disk_type))
201
202 /*
203  * Maximum disk size (in kilobytes). This default is used whenever the
204  * current disk size is unknown.
205  */
206 #define MAX_DISK_SIZE 720
207
208 static struct gendisk *disks[FD_MAX_UNIT];
209
210 /* current info on each unit */
211 static struct archy_floppy_struct {
212         int connected;          /* !=0 : drive is connected */
213         int autoprobe;          /* !=0 : do autoprobe       */
214
215         struct archy_disk_type *disktype;       /* current type of disk */
216
217         int track;              /* current head position or -1
218                                    * if unknown */
219         unsigned int steprate;  /* steprate setting */
220         unsigned int wpstat;    /* current state of WP signal
221                                    * (for disk change detection) */
222 } unit[FD_MAX_UNITS];
223
224 /* DAG: On Arc we spin on a flag being cleared by fdc1772_comendhandler which
225    is an assembler routine */
226 extern void fdc1772_comendhandler(void);        /* Actually doens't have these parameters - see fd1772.S */
227 extern volatile int fdc1772_comendstatus;
228 extern volatile int fdc1772_fdc_int_done;
229
230 #define FDC1772BASE ((0x210000>>2)|0x80000000)
231
232 #define FDC1772_READ(reg) inb(FDC1772BASE+(reg/2))
233
234 /* DAG: You wouldn't be silly to ask why FDC1772_WRITE is a function rather
235    than the #def below - well simple - the #def won't compile - and I
236    don't understand why (__outwc not defined) */
237 /* NOTE: Reg is 0,2,4,6 as opposed to 0,1,2,3 or 0,4,8,12 to keep compatibility
238    with the ST version of fd1772.h */
239 /*#define FDC1772_WRITE(reg,val) outw(val,(reg+FDC1772BASE)); */
240 void FDC1772_WRITE(int reg, unsigned char val)
241 {
242         if (reg == FDC1772REG_CMD) {
243                 DPRINT(("FDC1772_WRITE new command 0x%x @ %d\n", val,jiffies));
244                 if (fdc1772_fdc_int_done) {
245                         DPRINT(("FDC1772_WRITE: Hmm fdc1772_fdc_int_done true - resetting\n"));
246                         fdc1772_fdc_int_done = 0;
247                 };
248         };
249         outb(val, (reg / 2) + FDC1772BASE);
250 };
251
252 #define FD1772_MAX_SECTORS      22
253
254 unsigned char *DMABuffer;       /* buffer for writes */
255 /*static unsigned long PhysDMABuffer; *//* physical address */
256 /* DAG: On Arc we just go straight for the DMA buffer */
257 #define PhysDMABuffer DMABuffer
258
259 #ifdef TRACKBUFFER   
260 unsigned char *TrackBuffer;       /* buffer for reads */
261 #define PhysTrackBuffer TrackBuffer /* physical address */
262 static int BufferDrive, BufferSide, BufferTrack;
263 static int read_track;    /* non-zero if we are reading whole tracks */
264   
265 #define SECTOR_BUFFER(sec)  (TrackBuffer + ((sec)-1)*512)
266 #define IS_BUFFERED(drive,side,track) \
267     (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track))
268 #endif
269
270 /*
271  * These are global variables, as that's the easiest way to give
272  * information to interrupts. They are the data used for the current
273  * request.
274  */
275 static int SelectedDrive = 0;
276 static int ReqCmd, ReqBlock;
277 static int ReqSide, ReqTrack, ReqSector, ReqCnt;
278 static int HeadSettleFlag = 0;
279 static unsigned char *ReqData, *ReqBuffer;
280 static int MotorOn = 0, MotorOffTrys;
281
282 /* Synchronization of FDC1772 access. */
283 static volatile int fdc_busy = 0;
284 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
285
286
287 /* long req'd for set_bit --RR */
288 static unsigned long changed_floppies = 0xff, fake_change = 0;
289 #define CHECK_CHANGE_DELAY      HZ/2
290
291 /* DAG - increased to 30*HZ - not sure if this is the correct thing to do */
292 #define FD_MOTOR_OFF_DELAY      (10*HZ)
293 #define FD_MOTOR_OFF_MAXTRY     (10*20)
294
295 #define FLOPPY_TIMEOUT          (6*HZ)
296 #define RECALIBRATE_ERRORS      4       /* After this many errors the drive
297                                          * will be recalibrated. */
298 #define MAX_ERRORS              8       /* After this many errors the driver
299                                          * will give up. */
300
301 #define START_MOTOR_OFF_TIMER(delay)                            \
302         do {                                                    \
303                 motor_off_timer.expires = jiffies + (delay);    \
304                 add_timer( &motor_off_timer );                  \
305                 MotorOffTrys = 0;                               \
306         } while(0)
307
308 #define START_CHECK_CHANGE_TIMER(delay)                         \
309         do {                                                    \
310                 mod_timer(&fd_timer, jiffies + (delay));        \
311         } while(0)
312
313 #define START_TIMEOUT()                                         \
314         do {                                                    \
315                 mod_timer(&timeout_timer, jiffies+FLOPPY_TIMEOUT); \
316         } while(0)
317
318 #define STOP_TIMEOUT()                                          \
319         do {                                                    \
320                 del_timer( &timeout_timer );                    \
321         } while(0)
322
323 #define ENABLE_IRQ() enable_irq(FIQ_FD1772+64);
324
325 #define DISABLE_IRQ() disable_irq(FIQ_FD1772+64);
326
327 static void fd1772_checkint(void);
328
329 DECLARE_WORK(fd1772_tq, (void *)fd1772_checkint, NULL);
330 /*
331  * The driver is trying to determine the correct media format
332  * while Probing is set. fd_rwsec_done() clears it after a
333  * successful access.
334  */
335 static int Probing = 0;
336
337 /* This flag is set when a dummy seek is necessary to make the WP
338  * status bit accessible.
339  */
340 static int NeedSeek = 0;
341
342
343 /***************************** Prototypes *****************************/
344
345 static void fd_select_side(int side);
346 static void fd_select_drive(int drive);
347 static void fd_deselect(void);
348 static void fd_motor_off_timer(unsigned long dummy);
349 static void check_change(unsigned long dummy);
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);
358 #ifdef TRACKBUFFER   
359 static void fd_readtrack_check( unsigned long dummy );  
360 #endif
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 void setup_req_params(int drive);
367 static void redo_fd_request(void);
368 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int
369                     cmd, unsigned long param);
370 static void fd_probe(int drive);
371 static int fd_test_drive_present(int drive);
372 static void config_types(void);
373 static int floppy_open(struct inode *inode, struct file *filp);
374 static int floppy_release(struct inode *inode, struct file *filp);
375 static void do_fd_request(request_queue_t *);
376
377 /************************* End of Prototypes **************************/
378
379 static struct timer_list motor_off_timer =
380         TIMER_INITIALIZER(fd_motor_off_timer, 0, 0);
381
382 #ifdef TRACKBUFFER
383 static struct timer_list readtrack_timer =
384         TIMER_INITIALIZER(fd_readtrack_check, 0, 0);
385 #endif
386
387 static struct timer_list timeout_timer =
388         TIMER_INITIALIZER(fd_times_out, 0, 0);
389
390 static struct timer_list fd_timer =
391         TIMER_INITIALIZER(check_change, 0, 0);
392
393 /* DAG: Haven't got a clue what this is? */
394 int stdma_islocked(void)
395 {
396         return 0;
397 };
398
399 /* Select the side to use. */
400
401 static 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
410 static 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
433 static 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
450 static 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
485 retry:
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
502 static 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
541 static inline void set_head_settle_flag(void)
542 {
543         HeadSettleFlag = FDC1772CMDADD_E;
544 }
545
546 static 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
558 static inline void copy_buffer(void *from, void *to)
559 {
560         ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
561         int cnt;
562
563         for (cnt = 512 / 4; cnt; cnt--)
564                 *p2++ = *p1++;
565 }
566
567 static void (*FloppyIRQHandler) (int status) = NULL;
568
569 static void floppy_irqconsequencehandler(void)
570 {
571         unsigned char status;
572         void (*handler) (int);
573
574         fdc1772_fdc_int_done = 0;
575
576         handler = FloppyIRQHandler;
577         FloppyIRQHandler = NULL;
578
579         if (handler) {
580                 nop();
581                 status = (unsigned char) fdc1772_comendstatus;
582                 DPRINT(("FDC1772 irq, status = %02x handler = %08lx\n", (unsigned int) status, (unsigned long) handler));
583                 handler(status);
584         } else {
585                 DPRINT(("FDC1772 irq, no handler status=%02x\n", fdc1772_comendstatus));
586         }
587         DPRINT(("FDC1772 irq: end of floppy_irq\n"));
588 }
589
590
591 /* Error handling: If some error happened, retry some times, then
592  * recalibrate, then try again, and fail after MAX_ERRORS.
593  */
594
595 static void fd_error(void)
596 {
597         printk("FDC1772: fd_error\n");
598         /*panic("fd1772: fd_error"); *//* DAG tmp */
599         if (!CURRENT)
600                 return;
601         CURRENT->errors++;
602         if (CURRENT->errors >= MAX_ERRORS) {
603                 printk("fd%d: too many errors.\n", SelectedDrive);
604                 end_request(CURRENT, 0);
605         } else if (CURRENT->errors == RECALIBRATE_ERRORS) {
606                 printk("fd%d: recalibrating\n", SelectedDrive);
607                 if (SelectedDrive != -1)
608                         unit[SelectedDrive].track = -1;
609         }
610         redo_fd_request();
611 }
612
613
614
615 #define SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0)
616
617
618 /* do_fd_action() is the general procedure for a fd request: All
619  * required parameter settings (drive select, side select, track
620  * position) are checked and set if needed. For each of these
621  * parameters and the actual reading or writing exist two functions:
622  * one that starts the setting (or skips it if possible) and one
623  * callback for the "done" interrupt. Each done func calls the next
624  * set function to propagate the request down to fd_rwsec_done().
625  */
626
627 static void do_fd_action(int drive)
628 {
629         struct request *req;
630         DPRINT(("do_fd_action unit[drive].track=%d\n", unit[drive].track));
631
632 #ifdef TRACKBUFFER
633 repeat:
634
635         if (IS_BUFFERED( drive, ReqSide, ReqTrack )) {
636                 req = CURRENT;
637                 if (ReqCmd == READ) {
638                         copy_buffer( SECTOR_BUFFER(ReqSector), ReqData );
639                         if (++ReqCnt < req->current_nr_sectors) {
640                                 /* read next sector */
641                                 setup_req_params( drive );
642                                 goto repeat;
643                         } else {
644                                 /* all sectors finished */
645                                 req->nr_sectors -= req->current_nr_sectors;
646                                 req->sector += req->current_nr_sectors;
647                                 end_request(req, 1);
648                                 redo_fd_request();
649                                 return;
650                         }
651                 } else {
652                         /* cmd == WRITE, pay attention to track buffer
653                          * consistency! */
654                         copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) );
655                 }
656         }
657 #endif
658
659         if (SelectedDrive != drive) {
660                 /*unit[drive].track = -1; DAG */
661                 fd_select_drive(drive);
662         };
663
664
665         if (unit[drive].track == -1)
666                 fd_calibrate();
667         else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch)
668                 fd_seek();
669         else
670                 fd_rwsec();
671 }
672
673
674 /* Seek to track 0 if the current track is unknown */
675
676 static void fd_calibrate(void)
677 {
678         DPRINT(("fd_calibrate\n"));
679         if (unit[SelectedDrive].track >= 0) {
680                 fd_calibrate_done(0);
681                 return;
682         }
683         DPRINT(("fd_calibrate (after track compare)\n"));
684         SET_IRQ_HANDLER(fd_calibrate_done);
685         /* we can't verify, since the speed may be incorrect */
686         FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate);
687
688         NeedSeek = 1;
689         MotorOn = 1;
690         START_TIMEOUT();
691         /* wait for IRQ */
692 }
693
694
695 static void fd_calibrate_done(int status)
696 {
697         DPRINT(("fd_calibrate_done()\n"));
698         STOP_TIMEOUT();
699
700         /* set the correct speed now */
701         if (status & FDC1772STAT_RECNF) {
702                 printk("fd%d: restore failed\n", SelectedDrive);
703                 fd_error();
704         } else {
705                 unit[SelectedDrive].track = 0;
706                 fd_seek();
707         }
708 }
709
710
711 /* Seek the drive to the requested track. The drive must have been
712  * calibrated at some point before this.
713  */
714
715 static void fd_seek(void)
716 {
717         unsigned long flags;
718         DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n", ReqTrack,
719                 unit[SelectedDrive].track));
720         if (unit[SelectedDrive].track == ReqTrack <<
721             unit[SelectedDrive].disktype->stretch) {
722                 fd_seek_done(0);
723                 return;
724         }
725         FDC1772_WRITE(FDC1772REG_DATA, ReqTrack <<
726                       unit[SelectedDrive].disktype->stretch);
727         udelay(25);
728         save_flags(flags);
729         clf();
730         SET_IRQ_HANDLER(fd_seek_done);
731         FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate |
732                 /* DAG */
733                 (MotorOn?FDC1772CMDADD_H:0));
734
735         restore_flags(flags);
736         MotorOn = 1;
737         set_head_settle_flag();
738         START_TIMEOUT();
739         /* wait for IRQ */
740 }
741
742
743 static void fd_seek_done(int status)
744 {
745         DPRINT(("fd_seek_done()\n"));
746         STOP_TIMEOUT();
747
748         /* set the correct speed */
749         if (status & FDC1772STAT_RECNF) {
750                 printk("fd%d: seek error (to track %d)\n",
751                        SelectedDrive, ReqTrack);
752                 /* we don't know exactly which track we are on now! */
753                 unit[SelectedDrive].track = -1;
754                 fd_error();
755         } else {
756                 unit[SelectedDrive].track = ReqTrack <<
757                     unit[SelectedDrive].disktype->stretch;
758                 NeedSeek = 0;
759                 fd_rwsec();
760         }
761 }
762
763
764 /* This does the actual reading/writing after positioning the head
765  * over the correct track.
766  */
767
768 #ifdef TRACKBUFFER
769 static int MultReadInProgress = 0;
770 #endif
771
772
773 static void fd_rwsec(void)
774 {
775         unsigned long paddr, flags;
776         unsigned int rwflag, old_motoron;
777         unsigned int track;
778
779         DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n", ReqSector, ReqCmd == WRITE ? 'w' : 'r'));
780         if (ReqCmd == WRITE) {
781                 /*cache_push( (unsigned long)ReqData, 512 ); */
782                 paddr = (unsigned long) ReqData;
783                 rwflag = 0x100;
784         } else {
785                 paddr = (unsigned long) PhysDMABuffer;
786 #ifdef TRACKBUFFER
787                 if (read_track)
788                         paddr = (unsigned long)PhysTrackBuffer;
789 #endif
790                 rwflag = 0;
791         }
792
793         DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n", rwflag,
794                 ReqSector, FDC1772_READ(FDC1772REG_TRACK)));
795         fd_select_side(ReqSide);
796
797         /*DPRINT(("fd_rwsec() before start sector \n")); */
798         /* Start sector of this operation */
799 #ifdef TRACKBUFFER
800         FDC1772_WRITE( FDC1772REG_SECTOR, !read_track ? ReqSector : 1 );
801 #else
802         FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector );
803 #endif
804
805         /* Cheat for track if stretch != 0 */
806         if (unit[SelectedDrive].disktype->stretch) {
807                 track = FDC1772_READ(FDC1772REG_TRACK);
808                 FDC1772_WRITE(FDC1772REG_TRACK, track >>
809                               unit[SelectedDrive].disktype->stretch);
810         }
811         udelay(25);
812
813         DPRINT(("fd_rwsec() before setup DMA \n"));
814         /* Setup DMA - Heavily modified by DAG */
815         save_flags(flags);
816         clf();
817         disable_dma(FLOPPY_DMA);
818         set_dma_mode(FLOPPY_DMA, rwflag ? DMA_MODE_WRITE : DMA_MODE_READ);
819         set_dma_addr(FLOPPY_DMA, (long) paddr);         /* DAG - changed from Atari specific */
820 #ifdef TRACKBUFFER
821         set_dma_count(FLOPPY_DMA,(!read_track ? 1 : unit[SelectedDrive].disktype->spt)*512);
822 #else
823         set_dma_count(FLOPPY_DMA, 512);         /* Block/sector size - going to have to change */
824 #endif
825         SET_IRQ_HANDLER(fd_rwsec_done);
826         /* Turn on dma int */
827         enable_dma(FLOPPY_DMA);
828         /* Now give it something to do */
829         FDC1772_WRITE(FDC1772REG_CMD, (rwflag ? (FDC1772CMD_WRSEC | FDC1772CMDADD_P) : 
830 #ifdef TRACKBUFFER
831               (FDC1772CMD_RDSEC | (read_track ? FDC1772CMDADD_M : 0) |
832               /* Hmm - the idea here is to stop the FDC spinning the disc
833               up when we know that we already still have it spinning */
834               (MotorOn?FDC1772CMDADD_H:0))
835 #else
836               FDC1772CMD_RDSEC
837 #endif
838                 ));
839
840         restore_flags(flags);
841         DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n", flags));
842         /*sti(); *//* DAG - Hmm */
843         /* Hmm - should do something DAG */
844         old_motoron = MotorOn;
845         MotorOn = 1;
846         NeedSeek = 1;
847
848         /* wait for interrupt */
849
850 #ifdef TRACKBUFFER
851         if (read_track) {
852                 /*
853                  * If reading a whole track, wait about one disk rotation and
854                  * then check if all sectors are read. The FDC will even
855                  * search for the first non-existant sector and need 1 sec to
856                  * recognise that it isn't present :-(
857                  */
858                 /* 1 rot. + 5 rot.s if motor was off  */
859                 mod_timer(&readtrack_timer, jiffies + HZ/5 + (old_motoron ? 0 : HZ));
860                 DPRINT(("Setting readtrack_timer to %d @ %d\n",
861                         readtrack_timer.expires,jiffies));
862                 MultReadInProgress = 1;
863         }
864 #endif
865
866         /*DPRINT(("fd_rwsec() before START_TIMEOUT \n")); */
867         START_TIMEOUT();
868         /*DPRINT(("fd_rwsec() after START_TIMEOUT \n")); */
869 }
870
871
872 #ifdef TRACKBUFFER
873
874 static void fd_readtrack_check(unsigned long dummy)
875 {
876         unsigned long flags, addr;
877         extern unsigned char *fdc1772_dataaddr;
878
879         DPRINT(("fd_readtrack_check @ %d\n",jiffies));
880
881         save_flags(flags);
882         clf();
883
884         del_timer( &readtrack_timer );
885
886         if (!MultReadInProgress) {
887                 /* This prevents a race condition that could arise if the
888                  * interrupt is triggered while the calling of this timer
889                  * callback function takes place. The IRQ function then has
890                  * already cleared 'MultReadInProgress'  when control flow
891                  * gets here.
892                  */
893                 restore_flags(flags);
894                 return;
895         }
896
897         /* get the current DMA address */
898         addr=(unsigned long)fdc1772_dataaddr; /* DAG - ? */
899         DPRINT(("fd_readtrack_check: addr=%x PhysTrackBuffer=%x\n",addr,PhysTrackBuffer));
900
901         if (addr >= (unsigned int)PhysTrackBuffer + unit[SelectedDrive].disktype->spt*512) {
902                 /* already read enough data, force an FDC interrupt to stop
903                  * the read operation
904                  */
905                 SET_IRQ_HANDLER( NULL );
906                 restore_flags(flags);
907                 DPRINT(("fd_readtrack_check(): done\n"));
908                 FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI );
909                 udelay(25);
910
911                 /* No error until now -- the FDC would have interrupted
912                  * otherwise!
913                  */
914                 fd_rwsec_done( 0 );
915         } else {
916                 /* not yet finished, wait another tenth rotation */
917                 restore_flags(flags);
918                 DPRINT(("fd_readtrack_check(): not yet finished\n"));
919                 readtrack_timer.expires = jiffies + HZ/5/10;
920                 add_timer( &readtrack_timer );
921         }
922 }
923
924 #endif
925
926 static void fd_rwsec_done(int status)
927 {
928         unsigned int track;
929
930         DPRINT(("fd_rwsec_done() status=%d @ %d\n", status,jiffies));
931
932 #ifdef TRACKBUFFER
933         if (read_track && !MultReadInProgress)
934                 return;
935
936         MultReadInProgress = 0;
937
938         STOP_TIMEOUT();
939
940         if (read_track)
941                 del_timer( &readtrack_timer );
942 #endif
943
944
945         /* Correct the track if stretch != 0 */
946         if (unit[SelectedDrive].disktype->stretch) {
947                 track = FDC1772_READ(FDC1772REG_TRACK);
948                 FDC1772_WRITE(FDC1772REG_TRACK, track <<
949                               unit[SelectedDrive].disktype->stretch);
950         }
951         if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) {
952                 printk("fd%d: is write protected\n", SelectedDrive);
953                 goto err_end;
954         }
955         if ((status & FDC1772STAT_RECNF)
956 #ifdef TRACKBUFFER
957             /* RECNF is no error after a multiple read when the FDC
958              * searched for a non-existant sector!
959              */
960             && !(read_track &&
961                FDC1772_READ(FDC1772REG_SECTOR) > unit[SelectedDrive].disktype->spt)
962 #endif
963             ) {
964                 if (Probing) {
965                         if (unit[SelectedDrive].disktype > disk_type) {
966                                 /* try another disk type */
967                                 unit[SelectedDrive].disktype--;
968                                 set_capacity(disks[SelectedDrive],
969                                     unit[SelectedDrive].disktype->blocks);
970                         } else
971                                 Probing = 0;
972                 } else {
973                         /* record not found, but not probing. Maybe stretch wrong ? Restart probing */
974                         if (unit[SelectedDrive].autoprobe) {
975                                 unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1;
976                                 set_capacity(disks[SelectedDrive],
977                                     unit[SelectedDrive].disktype->blocks);
978                                 Probing = 1;
979                         }
980                 }
981                 if (Probing) {
982                         setup_req_params(SelectedDrive);
983 #ifdef TRACKBUFFER
984                         BufferDrive = -1;
985 #endif
986                         do_fd_action(SelectedDrive);
987                         return;
988                 }
989                 printk("fd%d: sector %d not found (side %d, track %d)\n",
990                        SelectedDrive, FDC1772_READ(FDC1772REG_SECTOR), ReqSide, ReqTrack);
991                 goto err_end;
992         }
993         if (status & FDC1772STAT_CRC) {
994                 printk("fd%d: CRC error (side %d, track %d, sector %d)\n",
995                        SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
996                 goto err_end;
997         }
998         if (status & FDC1772STAT_LOST) {
999                 printk("fd%d: lost data (side %d, track %d, sector %d)\n",
1000                        SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
1001                 goto err_end;
1002         }
1003         Probing = 0;
1004
1005         if (ReqCmd == READ) {
1006 #ifdef TRACKBUFFER
1007                 if (!read_track) {
1008                         /*cache_clear (PhysDMABuffer, 512);*/
1009                         copy_buffer (DMABuffer, ReqData);
1010                 } else {
1011                         /*cache_clear (PhysTrackBuffer, FD1772_MAX_SECTORS * 512);*/
1012                         BufferDrive = SelectedDrive;
1013                         BufferSide  = ReqSide;
1014                         BufferTrack = ReqTrack;
1015                         copy_buffer (SECTOR_BUFFER (ReqSector), ReqData);
1016                 }
1017 #else
1018                 /*cache_clear( PhysDMABuffer, 512 ); */
1019                 copy_buffer(DMABuffer, ReqData);
1020 #endif
1021         }
1022         if (++ReqCnt < CURRENT->current_nr_sectors) {
1023                 /* read next sector */
1024                 setup_req_params(SelectedDrive);
1025                 do_fd_action(SelectedDrive);
1026         } else {
1027                 /* all sectors finished */
1028                 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
1029                 CURRENT->sector += CURRENT->current_nr_sectors;
1030                 end_request(CURRENT, 1);
1031                 redo_fd_request();
1032         }
1033         return;
1034
1035 err_end:
1036 #ifdef TRACKBUFFER
1037         BufferDrive = -1;
1038 #endif
1039
1040         fd_error();
1041 }
1042
1043
1044 static void fd_times_out(unsigned long dummy)
1045 {
1046         SET_IRQ_HANDLER(NULL);
1047         /* If the timeout occurred while the readtrack_check timer was
1048          * active, we need to cancel it, else bad things will happen */
1049         del_timer( &readtrack_timer ); 
1050         FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1051         udelay(25);
1052
1053         printk("floppy timeout\n");
1054         STOP_TIMEOUT();         /* hmm - should we do this ? */
1055         fd_error();
1056 }
1057
1058
1059 /* The (noop) seek operation here is needed to make the WP bit in the
1060  * FDC1772 status register accessible for check_change. If the last disk
1061  * operation would have been a RDSEC, this bit would always read as 0
1062  * no matter what :-( To save time, the seek goes to the track we're
1063  * already on.
1064  */
1065
1066 static void finish_fdc(void)
1067 {
1068         /* DAG - just try without this dummy seek! */
1069         finish_fdc_done(0);
1070         return;
1071
1072         if (!NeedSeek) {
1073                 finish_fdc_done(0);
1074         } else {
1075                 DPRINT(("finish_fdc: dummy seek started\n"));
1076                 FDC1772_WRITE(FDC1772REG_DATA, unit[SelectedDrive].track);
1077                 SET_IRQ_HANDLER(finish_fdc_done);
1078                 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1079                 MotorOn = 1;
1080                 START_TIMEOUT();
1081                 /* we must wait for the IRQ here, because the ST-DMA is
1082                  * released immediately afterwards and the interrupt may be
1083                  * delivered to the wrong driver.
1084                  */
1085         }
1086 }
1087
1088
1089 static void finish_fdc_done(int dummy)
1090 {
1091         unsigned long flags;
1092
1093         DPRINT(("finish_fdc_done entered\n"));
1094         STOP_TIMEOUT();
1095         NeedSeek = 0;
1096
1097         if (timer_pending(&fd_timer) &&
1098             time_after(jiffies + 5, fd_timer.expires)) 
1099                 /* If the check for a disk change is done too early after this
1100                  * last seek command, the WP bit still reads wrong :-((
1101                  */
1102                 mod_timer(&fd_timer, jiffies + 5);
1103         else {
1104                 /*      START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1105         };
1106         del_timer(&motor_off_timer);
1107         START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1108
1109         save_flags(flags);
1110         cli();
1111         /* stdma_release(); - not sure if I should do something DAG  */
1112         fdc_busy = 0;
1113         wake_up(&fdc_wait);
1114         restore_flags(flags);
1115
1116         DPRINT(("finish_fdc() finished\n"));
1117 }
1118
1119
1120 /* Prevent "aliased" accesses. */
1121 static int fd_ref[4];
1122 static int fd_device[4];
1123
1124 /* dummy for blk.h */
1125 static void floppy_off(unsigned int nr)
1126 {
1127 }
1128
1129
1130 /* On the old arcs write protect depends on the particular model
1131    of machine.  On the A310, R140, and A440 there is a disc changed
1132    detect, however on the A4x0/1 range there is not.  There
1133    is nothing to tell you which machine your on.
1134    At the moment I'm just marking changed always. I've
1135    left the Atari's 'change on write protect change' code in this
1136    part (but nothing sets it).
1137    RiscOS apparently checks the disc serial number etc. to detect changes
1138    - but if it sees a disc change line go high (?) it flips to using
1139    it. Well  maybe I'll add that in the future (!?)
1140 */
1141 static int check_floppy_change(struct gendisk *disk)
1142 {
1143         struct archy_floppy_struct *p = disk->private_data;
1144         unsigned int drive = p - unit;
1145
1146         if (test_bit(drive, &fake_change)) {
1147                 /* simulated change (e.g. after formatting) */
1148                 return 1;
1149         }
1150         if (test_bit(drive, &changed_floppies)) {
1151                 /* surely changed (the WP signal changed at least once) */
1152                 return 1;
1153         }
1154         if (p->wpstat) {
1155                 /* WP is on -> could be changed: to be sure, buffers should be
1156                    * invalidated...
1157                  */
1158                 return 1;
1159         }
1160         return 1; /* DAG - was 0 */
1161 }
1162
1163 static int floppy_revalidate(struct gendisk *disk)
1164 {
1165         struct archy_floppy_struct *p = disk->private_data;
1166         unsigned int drive = p - unit;
1167
1168         if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change)
1169             || unit[drive].disktype == 0) {
1170 #ifdef TRACKBUFFER
1171                 BufferDrive = -1;
1172 #endif
1173                 clear_bit(drive, &fake_change);
1174                 clear_bit(drive, &changed_floppies);
1175                 p->disktype = 0;
1176         }
1177         return 0;
1178 }
1179
1180 /* This sets up the global variables describing the current request. */
1181
1182 static void setup_req_params(int drive)
1183 {
1184         int block = ReqBlock + ReqCnt;
1185
1186         ReqTrack = block / unit[drive].disktype->spt;
1187         ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1;
1188         ReqSide = ReqTrack & 1;
1189         ReqTrack >>= 1;
1190         ReqData = ReqBuffer + 512 * ReqCnt;
1191
1192 #ifdef TRACKBUFFER
1193         read_track = (ReqCmd == READ && CURRENT->errors == 0);
1194 #endif
1195
1196         DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n", ReqSide,
1197                 ReqTrack, ReqSector, (unsigned long) ReqData));
1198 }
1199
1200
1201 static void redo_fd_request(void)
1202 {
1203         int drive, type;
1204         struct archy_floppy_struct *floppy;
1205
1206         DPRINT(("redo_fd_request: CURRENT=%p dev=%s CURRENT->sector=%ld\n",
1207                 CURRENT, CURRENT ? CURRENT->rq_disk->disk_name : "",
1208                 CURRENT ? CURRENT->sector : 0));
1209
1210 repeat:
1211
1212         if (!CURRENT)
1213                 goto the_end;
1214
1215         floppy = CURRENT->rq_disk->private_data;
1216         drive = floppy - unit;
1217         type = fd_device[drive];
1218
1219         if (!floppy->connected) {
1220                 /* drive not connected */
1221                 printk("Unknown Device: fd%d\n", drive);
1222                 end_request(CURRENT, 0);
1223                 goto repeat;
1224         }
1225         if (type == 0) {
1226                 if (!floppy->disktype) {
1227                         Probing = 1;
1228                         floppy->disktype = disk_type + NUM_DISK_TYPES - 1;
1229                         set_capacity(disks[drive], floppy->disktype->blocks);
1230                         floppy->autoprobe = 1;
1231                 }
1232         } else {
1233                 /* user supplied disk type */
1234                 --type;
1235                 if (type >= NUM_DISK_TYPES) {
1236                         printk("fd%d: invalid disk format", drive);
1237                         end_request(CURRENT, 0);
1238                         goto repeat;
1239                 }
1240                 floppy->disktype = &disk_type[type];
1241                 set_capacity(disks[drive], floppy->disktype->blocks);
1242                 floppy->autoprobe = 0;
1243         }
1244
1245         if (CURRENT->sector + 1 > floppy->disktype->blocks) {
1246                 end_request(CURRENT, 0);
1247                 goto repeat;
1248         }
1249         /* stop deselect timer */
1250         del_timer(&motor_off_timer);
1251
1252         ReqCnt = 0;
1253         ReqCmd = CURRENT->cmd;
1254         ReqBlock = CURRENT->sector;
1255         ReqBuffer = CURRENT->buffer;
1256         setup_req_params(drive);
1257         do_fd_action(drive);
1258
1259         return;
1260
1261 the_end:
1262         finish_fdc();
1263 }
1264
1265 static void fd1772_checkint(void)
1266 {
1267         extern int fdc1772_bytestogo;
1268
1269         /*printk("fd1772_checkint %d\n",fdc1772_fdc_int_done);*/
1270         if (fdc1772_fdc_int_done)
1271                 floppy_irqconsequencehandler();
1272         if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0);
1273         if (fdc_busy) {
1274                 schedule_work(&fd1772_tq);
1275         }
1276 }
1277
1278 static void do_fd_request(request_queue_t* q)
1279 {
1280         unsigned long flags;
1281
1282         DPRINT(("do_fd_request for pid %d\n", current->pid));
1283         if (fdc_busy) return;
1284         save_flags(flags);
1285         cli();
1286         while (fdc_busy)
1287                 sleep_on(&fdc_wait);
1288         fdc_busy = 1;
1289         ENABLE_IRQ();
1290         restore_flags(flags);
1291
1292         fdc1772_fdc_int_done = 0;
1293
1294         redo_fd_request();
1295
1296         schedule_work(&fd1772_tq);
1297 }
1298
1299
1300 static int invalidate_drive(struct block_device *bdev)
1301 {
1302         struct archy_floppy_struct *p = bdev->bd_disk->private_data;
1303         /* invalidate the buffer track to force a reread */
1304 #ifdef TRACKBUFFER
1305         BufferDrive = -1;
1306 #endif
1307
1308         set_bit(p - unit, &fake_change);
1309         return 0;
1310 }
1311
1312 static int fd_ioctl(struct inode *inode, struct file *filp,
1313                     unsigned int cmd, unsigned long param)
1314 {
1315         struct block_device *bdev = inode->i_bdev;
1316
1317         switch (cmd) {
1318         case FDFMTEND:
1319         case FDFLUSH:
1320                 invalidate_drive(bdev);
1321                 check_disk_change(bdev);
1322         case FDFMTBEG:
1323                 return 0;
1324         default:
1325                 return -EINVAL;
1326         }
1327 }
1328
1329
1330 /* Initialize the 'unit' variable for drive 'drive' */
1331
1332 static void fd_probe(int drive)
1333 {
1334         unit[drive].connected = 0;
1335         unit[drive].disktype = NULL;
1336
1337         if (!fd_test_drive_present(drive))
1338                 return;
1339
1340         unit[drive].connected = 1;
1341         unit[drive].track = -1; /* If we put the auto detect back in this can go to 0 */
1342         unit[drive].steprate = FDC1772STEP_6;
1343         MotorOn = 1;            /* from probe restore operation! */
1344 }
1345
1346
1347 /* This function tests the physical presence of a floppy drive (not
1348  * whether a disk is inserted). This is done by issuing a restore
1349  * command, waiting max. 2 seconds (that should be enough to move the
1350  * head across the whole disk) and looking at the state of the "TR00"
1351  * signal. This should now be raised if there is a drive connected
1352  * (and there is no hardware failure :-) Otherwise, the drive is
1353  * declared absent.
1354  */
1355
1356 static int fd_test_drive_present(int drive)
1357 {
1358         unsigned long timeout;
1359         unsigned char status;
1360         int ok;
1361
1362         printk("fd_test_drive_present %d\n", drive);
1363         if (drive > 1)
1364                 return (0);
1365         return (1);             /* Simple hack for the moment - the autodetect doesn't seem to work on arc */
1366         fd_select_drive(drive);
1367
1368         /* disable interrupt temporarily */
1369         DISABLE_IRQ();
1370         FDC1772_WRITE(FDC1772REG_TRACK, 0x00);  /* was ff00 why? */
1371         FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6);
1372
1373         /*printk("fd_test_drive_present: Going into timeout loop\n"); */
1374         for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; time_before(jiffies, timeout);) {
1375                 /*  What does this piece of atariism do? - query for an interrupt? */
1376                 /*  if (!(mfp.par_dt_reg & 0x20))
1377                    break; */
1378                 /* Well this is my nearest guess - quit when we get an FDC interrupt */
1379                 if (ioc_readb(IOC_FIQSTAT) & 2)
1380                         break;
1381         }
1382
1383         /*printk("fd_test_drive_present: Coming out of timeout loop\n"); */
1384         status = FDC1772_READ(FDC1772REG_STATUS);
1385         ok = (status & FDC1772STAT_TR00) != 0;
1386
1387         /*printk("fd_test_drive_present: ok=%d\n",ok); */
1388         /* force interrupt to abort restore operation (FDC1772 would try
1389          * about 50 seconds!) */
1390         FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1391         udelay(500);
1392         status = FDC1772_READ(FDC1772REG_STATUS);
1393         udelay(20);
1394         /*printk("fd_test_drive_present: just before OK code %d\n",ok); */
1395
1396         if (ok) {
1397                 /* dummy seek command to make WP bit accessible */
1398                 FDC1772_WRITE(FDC1772REG_DATA, 0);
1399                 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1400                 printk("fd_test_drive_present: just before wait for int\n");
1401                 /* DAG: Guess means wait for interrupt */
1402                 while (!(ioc_readb(IOC_FIQSTAT) & 2));
1403                 printk("fd_test_drive_present: just after wait for int\n");
1404                 status = FDC1772_READ(FDC1772REG_STATUS);
1405         }
1406         printk("fd_test_drive_present: just before ENABLE_IRQ\n");
1407         ENABLE_IRQ();
1408         printk("fd_test_drive_present: about to return\n");
1409         return (ok);
1410 }
1411
1412
1413 /* Look how many and which kind of drives are connected. If there are
1414  * floppies, additionally start the disk-change and motor-off timers.
1415  */
1416
1417 static void config_types(void)
1418 {
1419         int drive, cnt = 0;
1420
1421         printk("Probing floppy drive(s):\n");
1422         for (drive = 0; drive < FD_MAX_UNITS; drive++) {
1423                 fd_probe(drive);
1424                 if (unit[drive].connected) {
1425                         printk("fd%d\n", drive);
1426                         ++cnt;
1427                 }
1428         }
1429
1430         if (FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_BUSY) {
1431                 /* If FDC1772 is still busy from probing, give it another FORCI
1432                  * command to abort the operation. If this isn't done, the FDC1772
1433                  * will interrupt later and its IRQ line stays low, because
1434                  * the status register isn't read. And this will block any
1435                  * interrupts on this IRQ line :-(
1436                  */
1437                 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1438                 udelay(500);
1439                 FDC1772_READ(FDC1772REG_STATUS);
1440                 udelay(20);
1441         }
1442         if (cnt > 0) {
1443                 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1444                 if (cnt == 1)
1445                         fd_select_drive(0);
1446                 /*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1447         }
1448 }
1449
1450 /*
1451  * floppy_open check for aliasing (/dev/fd0 can be the same as
1452  * /dev/PS0 etc), and disallows simultaneous access to the same
1453  * drive with different device numbers.
1454  */
1455
1456 static int floppy_open(struct inode *inode, struct file *filp)
1457 {
1458         int drive = iminor(inode) & 3;
1459         int type =  iminor(inode) >> 2;
1460         int old_dev = fd_device[drive];
1461
1462         if (fd_ref[drive] && old_dev != type)
1463                 return -EBUSY;
1464
1465         if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
1466                 return -EBUSY;
1467
1468         if (filp->f_flags & O_EXCL)
1469                 fd_ref[drive] = -1;
1470         else
1471                 fd_ref[drive]++;
1472
1473         fd_device[drive] = type;
1474
1475         if (filp->f_flags & O_NDELAY)
1476                 return 0;
1477
1478         if (filp->f_mode & 3) {
1479                 check_disk_change(inode->i_bdev);
1480                 if (filp->f_mode & 2) {
1481                         if (unit[drive].wpstat) {
1482                                 floppy_release(inode, filp);
1483                                 return -EROFS;
1484                         }
1485                 }
1486         }
1487         return 0;
1488 }
1489
1490
1491 static int floppy_release(struct inode *inode, struct file *filp)
1492 {
1493         int drive = iminor(inode) & 3;
1494
1495         if (fd_ref[drive] < 0)
1496                 fd_ref[drive] = 0;
1497         else if (!fd_ref[drive]--) {
1498                 printk("floppy_release with fd_ref == 0");
1499                 fd_ref[drive] = 0;
1500         }
1501
1502         return 0;
1503 }
1504
1505 static struct block_device_operations floppy_fops =
1506 {
1507         .open           = floppy_open,
1508         .release        = floppy_release,
1509         .ioctl          = fd_ioctl,
1510         .media_changed  = check_floppy_change,
1511         .revalidate_disk= floppy_revalidate,
1512 };
1513
1514 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
1515 {
1516         int drive = *part & 3;
1517         if ((*part >> 2) > NUM_DISK_TYPES || drive >= FD_MAX_UNITS)
1518                 return NULL;
1519         *part = 0;
1520         return get_disk(disks[drive]);
1521 }
1522
1523 int fd1772_init(void)
1524 {
1525         static spinlock_t lock = SPIN_LOCK_UNLOCKED;
1526         int i, err = -ENOMEM;
1527
1528         if (!machine_is_archimedes())
1529                 return 0;
1530
1531         for (i = 0; i < FD_MAX_UNITS; i++) {
1532                 disks[i] = alloc_disk(1);
1533                 if (!disks[i])
1534                         goto err_disk;
1535         }
1536
1537         err = register_blkdev(MAJOR_NR, "fd");
1538         if (err)
1539                 goto err_disk;
1540
1541         err = -EBUSY;
1542         if (request_dma(FLOPPY_DMA, "fd1772")) {
1543                 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA);
1544                 goto err_blkdev;
1545         };
1546
1547         if (request_dma(FIQ_FD1772, "fd1772 end")) {
1548                 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772);
1549                 goto err_dma1;
1550         };
1551
1552         /* initialize variables */
1553         SelectedDrive = -1;
1554 #ifdef TRACKBUFFER
1555         BufferDrive = BufferSide = BufferTrack = -1;
1556         /* Atari uses 512 - I want to eventually cope with 1K sectors */
1557         DMABuffer = (char *)kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
1558         TrackBuffer = DMABuffer + 512;
1559 #else
1560         /* Allocate memory for the DMAbuffer - on the Atari this takes it
1561            out of some special memory... */
1562         DMABuffer = (char *) kmalloc(2048);     /* Copes with pretty large sectors */
1563 #endif
1564         err = -ENOMEM;
1565         if (!DMAbuffer)
1566                 goto err_dma2;
1567
1568         enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */
1569
1570         floppy_queue = blk_init_queue(do_fd_request, &lock);
1571         if (!floppy_queue)
1572                 goto err_queue;
1573
1574         for (i = 0; i < FD_MAX_UNITS; i++) {
1575                 unit[i].track = -1;
1576                 disks[i]->major = MAJOR_NR;
1577                 disks[i]->first_minor = 0;
1578                 disks[i]->fops = &floppy_fops;
1579                 sprintf(disks[i]->disk_name, "fd%d", i);
1580                 disks[i]->private_data = &unit[i];
1581                 disks[i]->queue = floppy_queue;
1582                 set_capacity(disks[i], MAX_DISK_SIZE * 2);
1583         }
1584         blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
1585                                 floppy_find, NULL, NULL);
1586
1587         for (i = 0; i < FD_MAX_UNITS; i++)
1588                 add_disk(disks[i]);
1589
1590         config_types();
1591
1592         return 0;
1593
1594  err_queue:
1595         kfree(DMAbuffer);
1596  err_dma2:
1597         free_dma(FIQ_FD1772);
1598
1599  err_dma1:
1600         free_dma(FLOPPY_DMA);
1601
1602  err_blkdev:
1603         unregister_blkdev(MAJOR_NR, "fd");
1604
1605  err_disk:
1606         while (i--)
1607                 put_disk(disks[i]);
1608         return err;
1609 }