[PATCH] ub: suppress gcc warnings for pointer casts
[linux-2.6] / 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 #include <linux/bitops.h>
142
143 #include <asm/arch/oldlatches.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 DEFINE_TIMER(motor_off_timer, fd_motor_off_timer, 0, 0);
380
381 #ifdef TRACKBUFFER
382 static DEFINE_TIMER(readtrack_timer, fd_readtrack_check, 0, 0);
383 #endif
384
385 static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0);
386
387 static DEFINE_TIMER(fd_timer, check_change, 0, 0);
388
389 /* DAG: Haven't got a clue what this is? */
390 int stdma_islocked(void)
391 {
392         return 0;
393 };
394
395 /* Select the side to use. */
396
397 static void fd_select_side(int side)
398 {
399         oldlatch_aupdate(LATCHA_SIDESEL, side ? 0 : LATCHA_SIDESEL);
400 }
401
402
403 /* Select a drive, update the FDC1772's track register
404  */
405
406 static void fd_select_drive(int drive)
407 {
408 #ifdef DEBUG
409         printk("fd_select_drive:%d\n", drive);
410 #endif
411         /* Hmm - nowhere do we seem to turn the motor on - I'm going to do it here! */
412         oldlatch_aupdate(LATCHA_MOTOR | LATCHA_INUSE, 0);
413
414         if (drive == SelectedDrive)
415                 return;
416
417         oldlatch_aupdate(LATCHA_FDSELALL, 0xf - (1 << drive));
418
419         /* restore track register to saved value */
420         FDC1772_WRITE(FDC1772REG_TRACK, unit[drive].track);
421         udelay(25);
422
423         SelectedDrive = drive;
424 }
425
426
427 /* Deselect both drives. */
428
429 static void fd_deselect(void)
430 {
431         unsigned long flags;
432
433         DPRINT(("fd_deselect\n"));
434
435         oldlatch_aupdate(LATCHA_FDSELALL | LATCHA_MOTOR | LATCHA_INUSE, 0xf | LATCHA_MOTOR | LATCHA_INUSE);
436
437         SelectedDrive = -1;
438 }
439
440
441 /* This timer function deselects the drives when the FDC1772 switched the
442  * motor off. The deselection cannot happen earlier because the FDC1772
443  * counts the index signals, which arrive only if one drive is selected.
444  */
445
446 static void fd_motor_off_timer(unsigned long dummy)
447 {
448         unsigned long flags;
449         unsigned char status;
450         int delay;
451
452         del_timer(&motor_off_timer);
453
454         if (SelectedDrive < 0)
455                 /* no drive selected, needn't deselect anyone */
456                 return;
457
458         save_flags(flags);
459         cli();
460
461         if (fdc_busy)           /* was stdma_islocked */
462                 goto retry;
463
464         status = FDC1772_READ(FDC1772REG_STATUS);
465
466         if (!(status & 0x80)) {
467                 /*
468                  * motor already turned off by FDC1772 -> deselect drives
469                  * In actual fact its this deselection which turns the motor
470                  * off on the Arc, since the motor control is actually on
471                  * Latch A
472                  */
473                 DPRINT(("fdc1772: deselecting in fd_motor_off_timer\n"));
474                 fd_deselect();
475                 MotorOn = 0;
476                 restore_flags(flags);
477                 return;
478         }
479         /* not yet off, try again */
480
481 retry:
482         restore_flags(flags);
483         /* Test again later; if tested too often, it seems there is no disk
484          * in the drive and the FDC1772 will leave the motor on forever (or,
485          * at least until a disk is inserted). So we'll test only twice
486          * per second from then on...
487          */
488         delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ?
489             (++MotorOffTrys, HZ / 20) : HZ / 2;
490         START_MOTOR_OFF_TIMER(delay);
491 }
492
493
494 /* This function is repeatedly called to detect disk changes (as good
495  * as possible) and keep track of the current state of the write protection.
496  */
497
498 static void check_change(unsigned long dummy)
499 {
500         static int drive = 0;
501
502         unsigned long flags;
503         int stat;
504
505         if (fdc_busy)
506                 return;         /* Don't start poking about if the fdc is busy */
507
508         return;                 /* let's just forget it for the mo DAG */
509
510         if (++drive > 1 || !unit[drive].connected)
511                 drive = 0;
512
513         save_flags(flags);
514         cli();
515
516         if (!stdma_islocked()) {
517                 stat = !!(FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_WPROT);
518
519                 /* The idea here is that if the write protect line has changed then
520                 the disc must have changed */
521                 if (stat != unit[drive].wpstat) {
522                         DPRINT(("wpstat[%d] = %d\n", drive, stat));
523                         unit[drive].wpstat = stat;
524                         set_bit(drive, &changed_floppies);
525                 }
526         }
527         restore_flags(flags);
528
529         START_CHECK_CHANGE_TIMER(CHECK_CHANGE_DELAY);
530 }
531
532
533 /* Handling of the Head Settling Flag: This flag should be set after each
534  * seek operation, because we don't use seeks with verify.
535  */
536
537 static inline void set_head_settle_flag(void)
538 {
539         HeadSettleFlag = FDC1772CMDADD_E;
540 }
541
542 static inline int get_head_settle_flag(void)
543 {
544         int tmp = HeadSettleFlag;
545         HeadSettleFlag = 0;
546         return (tmp);
547 }
548
549
550
551
552 /* General Interrupt Handling */
553
554 static inline void copy_buffer(void *from, void *to)
555 {
556         ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
557         int cnt;
558
559         for (cnt = 512 / 4; cnt; cnt--)
560                 *p2++ = *p1++;
561 }
562
563 static void (*FloppyIRQHandler) (int status) = NULL;
564
565 static void floppy_irqconsequencehandler(void)
566 {
567         unsigned char status;
568         void (*handler) (int);
569
570         fdc1772_fdc_int_done = 0;
571
572         handler = FloppyIRQHandler;
573         FloppyIRQHandler = NULL;
574
575         if (handler) {
576                 nop();
577                 status = (unsigned char) fdc1772_comendstatus;
578                 DPRINT(("FDC1772 irq, status = %02x handler = %08lx\n", (unsigned int) status, (unsigned long) handler));
579                 handler(status);
580         } else {
581                 DPRINT(("FDC1772 irq, no handler status=%02x\n", fdc1772_comendstatus));
582         }
583         DPRINT(("FDC1772 irq: end of floppy_irq\n"));
584 }
585
586
587 /* Error handling: If some error happened, retry some times, then
588  * recalibrate, then try again, and fail after MAX_ERRORS.
589  */
590
591 static void fd_error(void)
592 {
593         printk("FDC1772: fd_error\n");
594         /*panic("fd1772: fd_error"); *//* DAG tmp */
595         if (!CURRENT)
596                 return;
597         CURRENT->errors++;
598         if (CURRENT->errors >= MAX_ERRORS) {
599                 printk("fd%d: too many errors.\n", SelectedDrive);
600                 end_request(CURRENT, 0);
601         } else if (CURRENT->errors == RECALIBRATE_ERRORS) {
602                 printk("fd%d: recalibrating\n", SelectedDrive);
603                 if (SelectedDrive != -1)
604                         unit[SelectedDrive].track = -1;
605         }
606         redo_fd_request();
607 }
608
609
610
611 #define SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0)
612
613
614 /* do_fd_action() is the general procedure for a fd request: All
615  * required parameter settings (drive select, side select, track
616  * position) are checked and set if needed. For each of these
617  * parameters and the actual reading or writing exist two functions:
618  * one that starts the setting (or skips it if possible) and one
619  * callback for the "done" interrupt. Each done func calls the next
620  * set function to propagate the request down to fd_rwsec_done().
621  */
622
623 static void do_fd_action(int drive)
624 {
625         struct request *req;
626         DPRINT(("do_fd_action unit[drive].track=%d\n", unit[drive].track));
627
628 #ifdef TRACKBUFFER
629 repeat:
630
631         if (IS_BUFFERED( drive, ReqSide, ReqTrack )) {
632                 req = CURRENT;
633                 if (ReqCmd == READ) {
634                         copy_buffer( SECTOR_BUFFER(ReqSector), ReqData );
635                         if (++ReqCnt < req->current_nr_sectors) {
636                                 /* read next sector */
637                                 setup_req_params( drive );
638                                 goto repeat;
639                         } else {
640                                 /* all sectors finished */
641                                 req->nr_sectors -= req->current_nr_sectors;
642                                 req->sector += req->current_nr_sectors;
643                                 end_request(req, 1);
644                                 redo_fd_request();
645                                 return;
646                         }
647                 } else {
648                         /* cmd == WRITE, pay attention to track buffer
649                          * consistency! */
650                         copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) );
651                 }
652         }
653 #endif
654
655         if (SelectedDrive != drive) {
656                 /*unit[drive].track = -1; DAG */
657                 fd_select_drive(drive);
658         };
659
660
661         if (unit[drive].track == -1)
662                 fd_calibrate();
663         else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch)
664                 fd_seek();
665         else
666                 fd_rwsec();
667 }
668
669
670 /* Seek to track 0 if the current track is unknown */
671
672 static void fd_calibrate(void)
673 {
674         DPRINT(("fd_calibrate\n"));
675         if (unit[SelectedDrive].track >= 0) {
676                 fd_calibrate_done(0);
677                 return;
678         }
679         DPRINT(("fd_calibrate (after track compare)\n"));
680         SET_IRQ_HANDLER(fd_calibrate_done);
681         /* we can't verify, since the speed may be incorrect */
682         FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate);
683
684         NeedSeek = 1;
685         MotorOn = 1;
686         START_TIMEOUT();
687         /* wait for IRQ */
688 }
689
690
691 static void fd_calibrate_done(int status)
692 {
693         DPRINT(("fd_calibrate_done()\n"));
694         STOP_TIMEOUT();
695
696         /* set the correct speed now */
697         if (status & FDC1772STAT_RECNF) {
698                 printk("fd%d: restore failed\n", SelectedDrive);
699                 fd_error();
700         } else {
701                 unit[SelectedDrive].track = 0;
702                 fd_seek();
703         }
704 }
705
706
707 /* Seek the drive to the requested track. The drive must have been
708  * calibrated at some point before this.
709  */
710
711 static void fd_seek(void)
712 {
713         unsigned long flags;
714         DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n", ReqTrack,
715                 unit[SelectedDrive].track));
716         if (unit[SelectedDrive].track == ReqTrack <<
717             unit[SelectedDrive].disktype->stretch) {
718                 fd_seek_done(0);
719                 return;
720         }
721         FDC1772_WRITE(FDC1772REG_DATA, ReqTrack <<
722                       unit[SelectedDrive].disktype->stretch);
723         udelay(25);
724         save_flags(flags);
725         clf();
726         SET_IRQ_HANDLER(fd_seek_done);
727         FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate |
728                 /* DAG */
729                 (MotorOn?FDC1772CMDADD_H:0));
730
731         restore_flags(flags);
732         MotorOn = 1;
733         set_head_settle_flag();
734         START_TIMEOUT();
735         /* wait for IRQ */
736 }
737
738
739 static void fd_seek_done(int status)
740 {
741         DPRINT(("fd_seek_done()\n"));
742         STOP_TIMEOUT();
743
744         /* set the correct speed */
745         if (status & FDC1772STAT_RECNF) {
746                 printk("fd%d: seek error (to track %d)\n",
747                        SelectedDrive, ReqTrack);
748                 /* we don't know exactly which track we are on now! */
749                 unit[SelectedDrive].track = -1;
750                 fd_error();
751         } else {
752                 unit[SelectedDrive].track = ReqTrack <<
753                     unit[SelectedDrive].disktype->stretch;
754                 NeedSeek = 0;
755                 fd_rwsec();
756         }
757 }
758
759
760 /* This does the actual reading/writing after positioning the head
761  * over the correct track.
762  */
763
764 #ifdef TRACKBUFFER
765 static int MultReadInProgress = 0;
766 #endif
767
768
769 static void fd_rwsec(void)
770 {
771         unsigned long paddr, flags;
772         unsigned int rwflag, old_motoron;
773         unsigned int track;
774
775         DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n", ReqSector, ReqCmd == WRITE ? 'w' : 'r'));
776         if (ReqCmd == WRITE) {
777                 /*cache_push( (unsigned long)ReqData, 512 ); */
778                 paddr = (unsigned long) ReqData;
779                 rwflag = 0x100;
780         } else {
781                 paddr = (unsigned long) PhysDMABuffer;
782 #ifdef TRACKBUFFER
783                 if (read_track)
784                         paddr = (unsigned long)PhysTrackBuffer;
785 #endif
786                 rwflag = 0;
787         }
788
789         DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n", rwflag,
790                 ReqSector, FDC1772_READ(FDC1772REG_TRACK)));
791         fd_select_side(ReqSide);
792
793         /*DPRINT(("fd_rwsec() before start sector \n")); */
794         /* Start sector of this operation */
795 #ifdef TRACKBUFFER
796         FDC1772_WRITE( FDC1772REG_SECTOR, !read_track ? ReqSector : 1 );
797 #else
798         FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector );
799 #endif
800
801         /* Cheat for track if stretch != 0 */
802         if (unit[SelectedDrive].disktype->stretch) {
803                 track = FDC1772_READ(FDC1772REG_TRACK);
804                 FDC1772_WRITE(FDC1772REG_TRACK, track >>
805                               unit[SelectedDrive].disktype->stretch);
806         }
807         udelay(25);
808
809         DPRINT(("fd_rwsec() before setup DMA \n"));
810         /* Setup DMA - Heavily modified by DAG */
811         save_flags(flags);
812         clf();
813         disable_dma(FLOPPY_DMA);
814         set_dma_mode(FLOPPY_DMA, rwflag ? DMA_MODE_WRITE : DMA_MODE_READ);
815         set_dma_addr(FLOPPY_DMA, (long) paddr);         /* DAG - changed from Atari specific */
816 #ifdef TRACKBUFFER
817         set_dma_count(FLOPPY_DMA,(!read_track ? 1 : unit[SelectedDrive].disktype->spt)*512);
818 #else
819         set_dma_count(FLOPPY_DMA, 512);         /* Block/sector size - going to have to change */
820 #endif
821         SET_IRQ_HANDLER(fd_rwsec_done);
822         /* Turn on dma int */
823         enable_dma(FLOPPY_DMA);
824         /* Now give it something to do */
825         FDC1772_WRITE(FDC1772REG_CMD, (rwflag ? (FDC1772CMD_WRSEC | FDC1772CMDADD_P) : 
826 #ifdef TRACKBUFFER
827               (FDC1772CMD_RDSEC | (read_track ? FDC1772CMDADD_M : 0) |
828               /* Hmm - the idea here is to stop the FDC spinning the disc
829               up when we know that we already still have it spinning */
830               (MotorOn?FDC1772CMDADD_H:0))
831 #else
832               FDC1772CMD_RDSEC
833 #endif
834                 ));
835
836         restore_flags(flags);
837         DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n", flags));
838         /*sti(); *//* DAG - Hmm */
839         /* Hmm - should do something DAG */
840         old_motoron = MotorOn;
841         MotorOn = 1;
842         NeedSeek = 1;
843
844         /* wait for interrupt */
845
846 #ifdef TRACKBUFFER
847         if (read_track) {
848                 /*
849                  * If reading a whole track, wait about one disk rotation and
850                  * then check if all sectors are read. The FDC will even
851                  * search for the first non-existant sector and need 1 sec to
852                  * recognise that it isn't present :-(
853                  */
854                 /* 1 rot. + 5 rot.s if motor was off  */
855                 mod_timer(&readtrack_timer, jiffies + HZ/5 + (old_motoron ? 0 : HZ));
856                 DPRINT(("Setting readtrack_timer to %d @ %d\n",
857                         readtrack_timer.expires,jiffies));
858                 MultReadInProgress = 1;
859         }
860 #endif
861
862         /*DPRINT(("fd_rwsec() before START_TIMEOUT \n")); */
863         START_TIMEOUT();
864         /*DPRINT(("fd_rwsec() after START_TIMEOUT \n")); */
865 }
866
867
868 #ifdef TRACKBUFFER
869
870 static void fd_readtrack_check(unsigned long dummy)
871 {
872         unsigned long flags, addr;
873         extern unsigned char *fdc1772_dataaddr;
874
875         DPRINT(("fd_readtrack_check @ %d\n",jiffies));
876
877         save_flags(flags);
878         clf();
879
880         del_timer( &readtrack_timer );
881
882         if (!MultReadInProgress) {
883                 /* This prevents a race condition that could arise if the
884                  * interrupt is triggered while the calling of this timer
885                  * callback function takes place. The IRQ function then has
886                  * already cleared 'MultReadInProgress'  when control flow
887                  * gets here.
888                  */
889                 restore_flags(flags);
890                 return;
891         }
892
893         /* get the current DMA address */
894         addr=(unsigned long)fdc1772_dataaddr; /* DAG - ? */
895         DPRINT(("fd_readtrack_check: addr=%x PhysTrackBuffer=%x\n",addr,PhysTrackBuffer));
896
897         if (addr >= (unsigned int)PhysTrackBuffer + unit[SelectedDrive].disktype->spt*512) {
898                 /* already read enough data, force an FDC interrupt to stop
899                  * the read operation
900                  */
901                 SET_IRQ_HANDLER( NULL );
902                 restore_flags(flags);
903                 DPRINT(("fd_readtrack_check(): done\n"));
904                 FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI );
905                 udelay(25);
906
907                 /* No error until now -- the FDC would have interrupted
908                  * otherwise!
909                  */
910                 fd_rwsec_done( 0 );
911         } else {
912                 /* not yet finished, wait another tenth rotation */
913                 restore_flags(flags);
914                 DPRINT(("fd_readtrack_check(): not yet finished\n"));
915                 readtrack_timer.expires = jiffies + HZ/5/10;
916                 add_timer( &readtrack_timer );
917         }
918 }
919
920 #endif
921
922 static void fd_rwsec_done(int status)
923 {
924         unsigned int track;
925
926         DPRINT(("fd_rwsec_done() status=%d @ %d\n", status,jiffies));
927
928 #ifdef TRACKBUFFER
929         if (read_track && !MultReadInProgress)
930                 return;
931
932         MultReadInProgress = 0;
933
934         STOP_TIMEOUT();
935
936         if (read_track)
937                 del_timer( &readtrack_timer );
938 #endif
939
940
941         /* Correct the track if stretch != 0 */
942         if (unit[SelectedDrive].disktype->stretch) {
943                 track = FDC1772_READ(FDC1772REG_TRACK);
944                 FDC1772_WRITE(FDC1772REG_TRACK, track <<
945                               unit[SelectedDrive].disktype->stretch);
946         }
947         if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) {
948                 printk("fd%d: is write protected\n", SelectedDrive);
949                 goto err_end;
950         }
951         if ((status & FDC1772STAT_RECNF)
952 #ifdef TRACKBUFFER
953             /* RECNF is no error after a multiple read when the FDC
954              * searched for a non-existant sector!
955              */
956             && !(read_track &&
957                FDC1772_READ(FDC1772REG_SECTOR) > unit[SelectedDrive].disktype->spt)
958 #endif
959             ) {
960                 if (Probing) {
961                         if (unit[SelectedDrive].disktype > disk_type) {
962                                 /* try another disk type */
963                                 unit[SelectedDrive].disktype--;
964                                 set_capacity(disks[SelectedDrive],
965                                     unit[SelectedDrive].disktype->blocks);
966                         } else
967                                 Probing = 0;
968                 } else {
969                         /* record not found, but not probing. Maybe stretch wrong ? Restart probing */
970                         if (unit[SelectedDrive].autoprobe) {
971                                 unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1;
972                                 set_capacity(disks[SelectedDrive],
973                                     unit[SelectedDrive].disktype->blocks);
974                                 Probing = 1;
975                         }
976                 }
977                 if (Probing) {
978                         setup_req_params(SelectedDrive);
979 #ifdef TRACKBUFFER
980                         BufferDrive = -1;
981 #endif
982                         do_fd_action(SelectedDrive);
983                         return;
984                 }
985                 printk("fd%d: sector %d not found (side %d, track %d)\n",
986                        SelectedDrive, FDC1772_READ(FDC1772REG_SECTOR), ReqSide, ReqTrack);
987                 goto err_end;
988         }
989         if (status & FDC1772STAT_CRC) {
990                 printk("fd%d: CRC error (side %d, track %d, sector %d)\n",
991                        SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
992                 goto err_end;
993         }
994         if (status & FDC1772STAT_LOST) {
995                 printk("fd%d: lost data (side %d, track %d, sector %d)\n",
996                        SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
997                 goto err_end;
998         }
999         Probing = 0;
1000
1001         if (ReqCmd == READ) {
1002 #ifdef TRACKBUFFER
1003                 if (!read_track) {
1004                         /*cache_clear (PhysDMABuffer, 512);*/
1005                         copy_buffer (DMABuffer, ReqData);
1006                 } else {
1007                         /*cache_clear (PhysTrackBuffer, FD1772_MAX_SECTORS * 512);*/
1008                         BufferDrive = SelectedDrive;
1009                         BufferSide  = ReqSide;
1010                         BufferTrack = ReqTrack;
1011                         copy_buffer (SECTOR_BUFFER (ReqSector), ReqData);
1012                 }
1013 #else
1014                 /*cache_clear( PhysDMABuffer, 512 ); */
1015                 copy_buffer(DMABuffer, ReqData);
1016 #endif
1017         }
1018         if (++ReqCnt < CURRENT->current_nr_sectors) {
1019                 /* read next sector */
1020                 setup_req_params(SelectedDrive);
1021                 do_fd_action(SelectedDrive);
1022         } else {
1023                 /* all sectors finished */
1024                 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
1025                 CURRENT->sector += CURRENT->current_nr_sectors;
1026                 end_request(CURRENT, 1);
1027                 redo_fd_request();
1028         }
1029         return;
1030
1031 err_end:
1032 #ifdef TRACKBUFFER
1033         BufferDrive = -1;
1034 #endif
1035
1036         fd_error();
1037 }
1038
1039
1040 static void fd_times_out(unsigned long dummy)
1041 {
1042         SET_IRQ_HANDLER(NULL);
1043         /* If the timeout occurred while the readtrack_check timer was
1044          * active, we need to cancel it, else bad things will happen */
1045         del_timer( &readtrack_timer ); 
1046         FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1047         udelay(25);
1048
1049         printk("floppy timeout\n");
1050         STOP_TIMEOUT();         /* hmm - should we do this ? */
1051         fd_error();
1052 }
1053
1054
1055 /* The (noop) seek operation here is needed to make the WP bit in the
1056  * FDC1772 status register accessible for check_change. If the last disk
1057  * operation would have been a RDSEC, this bit would always read as 0
1058  * no matter what :-( To save time, the seek goes to the track we're
1059  * already on.
1060  */
1061
1062 static void finish_fdc(void)
1063 {
1064         /* DAG - just try without this dummy seek! */
1065         finish_fdc_done(0);
1066         return;
1067
1068         if (!NeedSeek) {
1069                 finish_fdc_done(0);
1070         } else {
1071                 DPRINT(("finish_fdc: dummy seek started\n"));
1072                 FDC1772_WRITE(FDC1772REG_DATA, unit[SelectedDrive].track);
1073                 SET_IRQ_HANDLER(finish_fdc_done);
1074                 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1075                 MotorOn = 1;
1076                 START_TIMEOUT();
1077                 /* we must wait for the IRQ here, because the ST-DMA is
1078                  * released immediately afterwards and the interrupt may be
1079                  * delivered to the wrong driver.
1080                  */
1081         }
1082 }
1083
1084
1085 static void finish_fdc_done(int dummy)
1086 {
1087         unsigned long flags;
1088
1089         DPRINT(("finish_fdc_done entered\n"));
1090         STOP_TIMEOUT();
1091         NeedSeek = 0;
1092
1093         if (timer_pending(&fd_timer) &&
1094             time_after(jiffies + 5, fd_timer.expires)) 
1095                 /* If the check for a disk change is done too early after this
1096                  * last seek command, the WP bit still reads wrong :-((
1097                  */
1098                 mod_timer(&fd_timer, jiffies + 5);
1099         else {
1100                 /*      START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1101         };
1102         del_timer(&motor_off_timer);
1103         START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1104
1105         save_flags(flags);
1106         cli();
1107         /* stdma_release(); - not sure if I should do something DAG  */
1108         fdc_busy = 0;
1109         wake_up(&fdc_wait);
1110         restore_flags(flags);
1111
1112         DPRINT(("finish_fdc() finished\n"));
1113 }
1114
1115
1116 /* Prevent "aliased" accesses. */
1117 static int fd_ref[4];
1118 static int fd_device[4];
1119
1120 /* dummy for blk.h */
1121 static void floppy_off(unsigned int nr)
1122 {
1123 }
1124
1125
1126 /* On the old arcs write protect depends on the particular model
1127    of machine.  On the A310, R140, and A440 there is a disc changed
1128    detect, however on the A4x0/1 range there is not.  There
1129    is nothing to tell you which machine your on.
1130    At the moment I'm just marking changed always. I've
1131    left the Atari's 'change on write protect change' code in this
1132    part (but nothing sets it).
1133    RiscOS apparently checks the disc serial number etc. to detect changes
1134    - but if it sees a disc change line go high (?) it flips to using
1135    it. Well  maybe I'll add that in the future (!?)
1136 */
1137 static int check_floppy_change(struct gendisk *disk)
1138 {
1139         struct archy_floppy_struct *p = disk->private_data;
1140         unsigned int drive = p - unit;
1141
1142         if (test_bit(drive, &fake_change)) {
1143                 /* simulated change (e.g. after formatting) */
1144                 return 1;
1145         }
1146         if (test_bit(drive, &changed_floppies)) {
1147                 /* surely changed (the WP signal changed at least once) */
1148                 return 1;
1149         }
1150         if (p->wpstat) {
1151                 /* WP is on -> could be changed: to be sure, buffers should be
1152                    * invalidated...
1153                  */
1154                 return 1;
1155         }
1156         return 1; /* DAG - was 0 */
1157 }
1158
1159 static int floppy_revalidate(struct gendisk *disk)
1160 {
1161         struct archy_floppy_struct *p = disk->private_data;
1162         unsigned int drive = p - unit;
1163
1164         if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change)
1165             || unit[drive].disktype == 0) {
1166 #ifdef TRACKBUFFER
1167                 BufferDrive = -1;
1168 #endif
1169                 clear_bit(drive, &fake_change);
1170                 clear_bit(drive, &changed_floppies);
1171                 p->disktype = 0;
1172         }
1173         return 0;
1174 }
1175
1176 /* This sets up the global variables describing the current request. */
1177
1178 static void setup_req_params(int drive)
1179 {
1180         int block = ReqBlock + ReqCnt;
1181
1182         ReqTrack = block / unit[drive].disktype->spt;
1183         ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1;
1184         ReqSide = ReqTrack & 1;
1185         ReqTrack >>= 1;
1186         ReqData = ReqBuffer + 512 * ReqCnt;
1187
1188 #ifdef TRACKBUFFER
1189         read_track = (ReqCmd == READ && CURRENT->errors == 0);
1190 #endif
1191
1192         DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n", ReqSide,
1193                 ReqTrack, ReqSector, (unsigned long) ReqData));
1194 }
1195
1196
1197 static void redo_fd_request(void)
1198 {
1199         int drive, type;
1200         struct archy_floppy_struct *floppy;
1201
1202         DPRINT(("redo_fd_request: CURRENT=%p dev=%s CURRENT->sector=%ld\n",
1203                 CURRENT, CURRENT ? CURRENT->rq_disk->disk_name : "",
1204                 CURRENT ? CURRENT->sector : 0));
1205
1206 repeat:
1207
1208         if (!CURRENT)
1209                 goto the_end;
1210
1211         floppy = CURRENT->rq_disk->private_data;
1212         drive = floppy - unit;
1213         type = fd_device[drive];
1214
1215         if (!floppy->connected) {
1216                 /* drive not connected */
1217                 printk("Unknown Device: fd%d\n", drive);
1218                 end_request(CURRENT, 0);
1219                 goto repeat;
1220         }
1221         if (type == 0) {
1222                 if (!floppy->disktype) {
1223                         Probing = 1;
1224                         floppy->disktype = disk_type + NUM_DISK_TYPES - 1;
1225                         set_capacity(disks[drive], floppy->disktype->blocks);
1226                         floppy->autoprobe = 1;
1227                 }
1228         } else {
1229                 /* user supplied disk type */
1230                 --type;
1231                 if (type >= NUM_DISK_TYPES) {
1232                         printk("fd%d: invalid disk format", drive);
1233                         end_request(CURRENT, 0);
1234                         goto repeat;
1235                 }
1236                 floppy->disktype = &disk_type[type];
1237                 set_capacity(disks[drive], floppy->disktype->blocks);
1238                 floppy->autoprobe = 0;
1239         }
1240
1241         if (CURRENT->sector + 1 > floppy->disktype->blocks) {
1242                 end_request(CURRENT, 0);
1243                 goto repeat;
1244         }
1245         /* stop deselect timer */
1246         del_timer(&motor_off_timer);
1247
1248         ReqCnt = 0;
1249         ReqCmd = CURRENT->cmd;
1250         ReqBlock = CURRENT->sector;
1251         ReqBuffer = CURRENT->buffer;
1252         setup_req_params(drive);
1253         do_fd_action(drive);
1254
1255         return;
1256
1257 the_end:
1258         finish_fdc();
1259 }
1260
1261 static void fd1772_checkint(void)
1262 {
1263         extern int fdc1772_bytestogo;
1264
1265         /*printk("fd1772_checkint %d\n",fdc1772_fdc_int_done);*/
1266         if (fdc1772_fdc_int_done)
1267                 floppy_irqconsequencehandler();
1268         if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0);
1269         if (fdc_busy) {
1270                 schedule_work(&fd1772_tq);
1271         }
1272 }
1273
1274 static void do_fd_request(request_queue_t* q)
1275 {
1276         unsigned long flags;
1277
1278         DPRINT(("do_fd_request for pid %d\n", current->pid));
1279         if (fdc_busy) return;
1280         save_flags(flags);
1281         cli();
1282         wait_event(fdc_wait, !fdc_busy);
1283         fdc_busy = 1;
1284         ENABLE_IRQ();
1285         restore_flags(flags);
1286
1287         fdc1772_fdc_int_done = 0;
1288
1289         redo_fd_request();
1290
1291         schedule_work(&fd1772_tq);
1292 }
1293
1294
1295 static int invalidate_drive(struct block_device *bdev)
1296 {
1297         struct archy_floppy_struct *p = bdev->bd_disk->private_data;
1298         /* invalidate the buffer track to force a reread */
1299 #ifdef TRACKBUFFER
1300         BufferDrive = -1;
1301 #endif
1302
1303         set_bit(p - unit, &fake_change);
1304         return 0;
1305 }
1306
1307 static int fd_ioctl(struct inode *inode, struct file *filp,
1308                     unsigned int cmd, unsigned long param)
1309 {
1310         struct block_device *bdev = inode->i_bdev;
1311
1312         switch (cmd) {
1313         case FDFMTEND:
1314         case FDFLUSH:
1315                 invalidate_drive(bdev);
1316                 check_disk_change(bdev);
1317         case FDFMTBEG:
1318                 return 0;
1319         default:
1320                 return -EINVAL;
1321         }
1322 }
1323
1324
1325 /* Initialize the 'unit' variable for drive 'drive' */
1326
1327 static void fd_probe(int drive)
1328 {
1329         unit[drive].connected = 0;
1330         unit[drive].disktype = NULL;
1331
1332         if (!fd_test_drive_present(drive))
1333                 return;
1334
1335         unit[drive].connected = 1;
1336         unit[drive].track = -1; /* If we put the auto detect back in this can go to 0 */
1337         unit[drive].steprate = FDC1772STEP_6;
1338         MotorOn = 1;            /* from probe restore operation! */
1339 }
1340
1341
1342 /* This function tests the physical presence of a floppy drive (not
1343  * whether a disk is inserted). This is done by issuing a restore
1344  * command, waiting max. 2 seconds (that should be enough to move the
1345  * head across the whole disk) and looking at the state of the "TR00"
1346  * signal. This should now be raised if there is a drive connected
1347  * (and there is no hardware failure :-) Otherwise, the drive is
1348  * declared absent.
1349  */
1350
1351 static int fd_test_drive_present(int drive)
1352 {
1353         unsigned long timeout;
1354         unsigned char status;
1355         int ok;
1356
1357         printk("fd_test_drive_present %d\n", drive);
1358         if (drive > 1)
1359                 return (0);
1360         return (1);             /* Simple hack for the moment - the autodetect doesn't seem to work on arc */
1361         fd_select_drive(drive);
1362
1363         /* disable interrupt temporarily */
1364         DISABLE_IRQ();
1365         FDC1772_WRITE(FDC1772REG_TRACK, 0x00);  /* was ff00 why? */
1366         FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6);
1367
1368         /*printk("fd_test_drive_present: Going into timeout loop\n"); */
1369         for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; time_before(jiffies, timeout);) {
1370                 /*  What does this piece of atariism do? - query for an interrupt? */
1371                 /*  if (!(mfp.par_dt_reg & 0x20))
1372                    break; */
1373                 /* Well this is my nearest guess - quit when we get an FDC interrupt */
1374                 if (ioc_readb(IOC_FIQSTAT) & 2)
1375                         break;
1376         }
1377
1378         /*printk("fd_test_drive_present: Coming out of timeout loop\n"); */
1379         status = FDC1772_READ(FDC1772REG_STATUS);
1380         ok = (status & FDC1772STAT_TR00) != 0;
1381
1382         /*printk("fd_test_drive_present: ok=%d\n",ok); */
1383         /* force interrupt to abort restore operation (FDC1772 would try
1384          * about 50 seconds!) */
1385         FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1386         udelay(500);
1387         status = FDC1772_READ(FDC1772REG_STATUS);
1388         udelay(20);
1389         /*printk("fd_test_drive_present: just before OK code %d\n",ok); */
1390
1391         if (ok) {
1392                 /* dummy seek command to make WP bit accessible */
1393                 FDC1772_WRITE(FDC1772REG_DATA, 0);
1394                 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1395                 printk("fd_test_drive_present: just before wait for int\n");
1396                 /* DAG: Guess means wait for interrupt */
1397                 while (!(ioc_readb(IOC_FIQSTAT) & 2));
1398                 printk("fd_test_drive_present: just after wait for int\n");
1399                 status = FDC1772_READ(FDC1772REG_STATUS);
1400         }
1401         printk("fd_test_drive_present: just before ENABLE_IRQ\n");
1402         ENABLE_IRQ();
1403         printk("fd_test_drive_present: about to return\n");
1404         return (ok);
1405 }
1406
1407
1408 /* Look how many and which kind of drives are connected. If there are
1409  * floppies, additionally start the disk-change and motor-off timers.
1410  */
1411
1412 static void config_types(void)
1413 {
1414         int drive, cnt = 0;
1415
1416         printk("Probing floppy drive(s):\n");
1417         for (drive = 0; drive < FD_MAX_UNITS; drive++) {
1418                 fd_probe(drive);
1419                 if (unit[drive].connected) {
1420                         printk("fd%d\n", drive);
1421                         ++cnt;
1422                 }
1423         }
1424
1425         if (FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_BUSY) {
1426                 /* If FDC1772 is still busy from probing, give it another FORCI
1427                  * command to abort the operation. If this isn't done, the FDC1772
1428                  * will interrupt later and its IRQ line stays low, because
1429                  * the status register isn't read. And this will block any
1430                  * interrupts on this IRQ line :-(
1431                  */
1432                 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1433                 udelay(500);
1434                 FDC1772_READ(FDC1772REG_STATUS);
1435                 udelay(20);
1436         }
1437         if (cnt > 0) {
1438                 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1439                 if (cnt == 1)
1440                         fd_select_drive(0);
1441                 /*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1442         }
1443 }
1444
1445 /*
1446  * floppy_open check for aliasing (/dev/fd0 can be the same as
1447  * /dev/PS0 etc), and disallows simultaneous access to the same
1448  * drive with different device numbers.
1449  */
1450
1451 static int floppy_open(struct inode *inode, struct file *filp)
1452 {
1453         int drive = iminor(inode) & 3;
1454         int type =  iminor(inode) >> 2;
1455         int old_dev = fd_device[drive];
1456
1457         if (fd_ref[drive] && old_dev != type)
1458                 return -EBUSY;
1459
1460         if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
1461                 return -EBUSY;
1462
1463         if (filp->f_flags & O_EXCL)
1464                 fd_ref[drive] = -1;
1465         else
1466                 fd_ref[drive]++;
1467
1468         fd_device[drive] = type;
1469
1470         if (filp->f_flags & O_NDELAY)
1471                 return 0;
1472
1473         if (filp->f_mode & 3) {
1474                 check_disk_change(inode->i_bdev);
1475                 if (filp->f_mode & 2) {
1476                         if (unit[drive].wpstat) {
1477                                 floppy_release(inode, filp);
1478                                 return -EROFS;
1479                         }
1480                 }
1481         }
1482         return 0;
1483 }
1484
1485
1486 static int floppy_release(struct inode *inode, struct file *filp)
1487 {
1488         int drive = iminor(inode) & 3;
1489
1490         if (fd_ref[drive] < 0)
1491                 fd_ref[drive] = 0;
1492         else if (!fd_ref[drive]--) {
1493                 printk("floppy_release with fd_ref == 0");
1494                 fd_ref[drive] = 0;
1495         }
1496
1497         return 0;
1498 }
1499
1500 static struct block_device_operations floppy_fops =
1501 {
1502         .open           = floppy_open,
1503         .release        = floppy_release,
1504         .ioctl          = fd_ioctl,
1505         .media_changed  = check_floppy_change,
1506         .revalidate_disk= floppy_revalidate,
1507 };
1508
1509 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
1510 {
1511         int drive = *part & 3;
1512         if ((*part >> 2) > NUM_DISK_TYPES || drive >= FD_MAX_UNITS)
1513                 return NULL;
1514         *part = 0;
1515         return get_disk(disks[drive]);
1516 }
1517
1518 int fd1772_init(void)
1519 {
1520         static DEFINE_SPINLOCK(lock);
1521         int i, err = -ENOMEM;
1522
1523         if (!machine_is_archimedes())
1524                 return 0;
1525
1526         for (i = 0; i < FD_MAX_UNITS; i++) {
1527                 disks[i] = alloc_disk(1);
1528                 if (!disks[i])
1529                         goto err_disk;
1530         }
1531
1532         err = register_blkdev(MAJOR_NR, "fd");
1533         if (err)
1534                 goto err_disk;
1535
1536         err = -EBUSY;
1537         if (request_dma(FLOPPY_DMA, "fd1772")) {
1538                 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA);
1539                 goto err_blkdev;
1540         };
1541
1542         if (request_dma(FIQ_FD1772, "fd1772 end")) {
1543                 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772);
1544                 goto err_dma1;
1545         };
1546
1547         /* initialize variables */
1548         SelectedDrive = -1;
1549 #ifdef TRACKBUFFER
1550         BufferDrive = BufferSide = BufferTrack = -1;
1551         /* Atari uses 512 - I want to eventually cope with 1K sectors */
1552         DMABuffer = (char *)kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
1553         TrackBuffer = DMABuffer + 512;
1554 #else
1555         /* Allocate memory for the DMAbuffer - on the Atari this takes it
1556            out of some special memory... */
1557         DMABuffer = (char *) kmalloc(2048);     /* Copes with pretty large sectors */
1558 #endif
1559         err = -ENOMEM;
1560         if (!DMAbuffer)
1561                 goto err_dma2;
1562
1563         enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */
1564
1565         floppy_queue = blk_init_queue(do_fd_request, &lock);
1566         if (!floppy_queue)
1567                 goto err_queue;
1568
1569         for (i = 0; i < FD_MAX_UNITS; i++) {
1570                 unit[i].track = -1;
1571                 disks[i]->major = MAJOR_NR;
1572                 disks[i]->first_minor = 0;
1573                 disks[i]->fops = &floppy_fops;
1574                 sprintf(disks[i]->disk_name, "fd%d", i);
1575                 disks[i]->private_data = &unit[i];
1576                 disks[i]->queue = floppy_queue;
1577                 set_capacity(disks[i], MAX_DISK_SIZE * 2);
1578         }
1579         blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
1580                                 floppy_find, NULL, NULL);
1581
1582         for (i = 0; i < FD_MAX_UNITS; i++)
1583                 add_disk(disks[i]);
1584
1585         config_types();
1586
1587         return 0;
1588
1589  err_queue:
1590         kfree(DMAbuffer);
1591  err_dma2:
1592         free_dma(FIQ_FD1772);
1593
1594  err_dma1:
1595         free_dma(FLOPPY_DMA);
1596
1597  err_blkdev:
1598         unregister_blkdev(MAJOR_NR, "fd");
1599
1600  err_disk:
1601         while (i--)
1602                 put_disk(disks[i]);
1603         return err;
1604 }