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