Merge with Linux 2.3.40.
[linux-2.6/linux-mips.git] / drivers / acorn / block / fd1772.c
blob54ed9ac6b38a5204712fb61580d96854b320fadb
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 (gilbertd@cs.man.ac.uk)
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 :-(
17 * Fixes Nov 13 1994 Martin Schaller:
18 * - Autodetection works now
19 * - Support for 5 1/4" disks
20 * - Removed drive type (unknown on atari)
21 * - Do seeks with 8 Mhz
23 * Changes by Andreas Schwab:
24 * - After errors in multiple read mode try again reading single sectors
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
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...
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...
51 * ARCHIMEDES changes: (gilbertd@cs.man.ac.uk)
52 * 26/12/95 - Changed all names starting with FDC to FDC1772
53 * Removed all references to clock speed of FDC - we're stuck with 8MHz
54 * Modified disk_type structure to remove HD formats
56 * 7/ 1/96 - Wrote FIQ code, removed most remaining atariisms
58 * 13/ 1/96 - Well I think its read a single sector; but there is a problem
59 * fd_rwsec_done which is called in FIQ mode starts another transfer
60 * off (in fd_rwsec) while still in FIQ mode. Because its still in
61 * FIQ mode it can't service the DMA and loses data. So need to
62 * heavily restructure.
63 * 14/ 1/96 - Found that the definitions of the register numbers of the
64 * FDC were multiplied by 2 in the header for the 16bit words
65 * of the atari so half the writes were going in the wrong place.
66 * Also realised that the FIQ entry didn't make any attempt to
67 * preserve registers or return correctly; now in assembler.
69 * 11/ 2/96 - Hmm - doesn't work on real machine. Auto detect doesn't
70 * and hacking that past seems to wait forever - check motor
71 * being turned on.
73 * 17/ 2/96 - still having problems - forcing track to -1 when selecting
74 * new drives seems to allow it to read first few sectors
75 * but then we get solid hangs at apparently random places
76 * which change depending what is happening.
78 * 9/ 3/96 - Fiddled a lot of stuff around to move to kernel 1.3.35
79 * A lot of fiddling in DMA stuff. Having problems with it
80 * constnatly thinking its timeing out. Ah - its timeout
81 * was set to (6*HZ) rather than jiffies+(6*HZ). Now giving
82 * duff data!
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.....
116 * 16/11/96 - Fiddled and frigged for 2.0.18
118 * DAG 30/01/99 - Started frobbing for 2.2.1
119 * DAG 20/06/99 - A little more frobbing:
120 * Included include/asm/uaccess.h for get_user/put_user
123 #include <linux/sched.h>
124 #include <linux/fs.h>
125 #include <linux/fcntl.h>
126 #include <linux/kernel.h>
127 #include <linux/interrupt.h>
128 #include <linux/timer.h>
129 #include <linux/tqueue.h>
130 #include <linux/fd.h>
131 #include <linux/fd1772.h>
132 #include <linux/errno.h>
133 #include <linux/types.h>
134 #include <linux/delay.h>
135 #include <linux/mm.h>
137 #include <asm/arch/oldlatches.h>
138 #include <asm/system.h>
139 #include <asm/bitops.h>
140 #include <asm/dma.h>
141 #include <asm/hardware.h>
142 #include <asm/io.h>
143 #include <asm/ioc.h>
144 #include <asm/irq.h>
145 #include <asm/pgtable.h>
146 #include <asm/segment.h>
147 #include <asm/uaccess.h>
150 #define MAJOR_NR FLOPPY_MAJOR
151 #define FLOPPY_DMA 0
152 #include <linux/blk.h>
154 /* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with
155 * little additional rework in this file). But I'm not yet sure if
156 * some other code depends on the number of floppies... (It is defined
157 * in a public header!)
159 #if 0
160 #undef FD_MAX_UNITS
161 #define FD_MAX_UNITS 2
162 #endif
164 /* Ditto worries for Arc - DAG */
165 #define FD_MAX_UNITS 4
166 #define TRACKBUFFER 0
167 /*#define DEBUG*/
169 #ifdef DEBUG
170 #define DPRINT(a) printk a
171 #else
172 #define DPRINT(a)
173 #endif
175 /* Disk types: DD */
176 static struct archy_disk_type {
177 const char *name;
178 unsigned spt; /* sectors per track */
179 unsigned blocks; /* total number of blocks */
180 unsigned stretch; /* track doubling ? */
181 } disk_type[] = {
183 { "d360", 9, 720, 0 }, /* 360kB diskette */
184 { "D360", 9, 720, 1 }, /* 360kb in 720kb drive */
185 { "D720", 9, 1440, 0 }, /* 720kb diskette (DD) */
186 /*{ "D820", 10,1640, 0}, *//* DD disk with 82 tracks/10 sectors
187 - DAG - can't see how type detect can distinguish this
188 from 720K until it reads block 4 by which time its too late! */
191 #define NUM_DISK_TYPES (sizeof(disk_type)/sizeof(*disk_type))
194 * Maximum disk size (in kilobytes). This default is used whenever the
195 * current disk size is unknown.
197 #define MAX_DISK_SIZE 720
199 static int floppy_sizes[256];
200 static int floppy_blocksizes[256] = {0,};
202 /* current info on each unit */
203 static struct archy_floppy_struct {
204 int connected; /* !=0 : drive is connected */
205 int autoprobe; /* !=0 : do autoprobe */
207 struct archy_disk_type *disktype; /* current type of disk */
209 int track; /* current head position or -1
210 * if unknown */
211 unsigned int steprate; /* steprate setting */
212 unsigned int wpstat; /* current state of WP signal
213 * (for disk change detection) */
214 } unit[FD_MAX_UNITS];
216 /* DAG: On Arc we spin on a flag being cleared by fdc1772_comendhandler which
217 is an assembler routine */
218 extern void fdc1772_comendhandler(void); /* Actually doens't have these parameters - see fd1772.S */
219 extern volatile int fdc1772_comendstatus;
220 extern volatile int fdc1772_fdc_int_done;
222 #define FDC1772BASE ((0x210000>>2)|0x80000000)
224 #define FDC1772_READ(reg) inb(FDC1772BASE+(reg/2))
226 /* DAG: You wouldn't be silly to ask why FDC1772_WRITE is a function rather
227 than the #def below - well simple - the #def won't compile - and I
228 don't understand why (__outwc not defined) */
229 /* NOTE: Reg is 0,2,4,6 as opposed to 0,1,2,3 or 0,4,8,12 to keep compatibility
230 with the ST version of fd1772.h */
231 /*#define FDC1772_WRITE(reg,val) outw(val,(reg+FDC1772BASE)); */
232 void FDC1772_WRITE(int reg, unsigned char val)
234 if (reg == FDC1772REG_CMD) {
235 DPRINT(("FDC1772_WRITE new command 0x%x @ %d\n", val,jiffies));
236 if (fdc1772_fdc_int_done) {
237 DPRINT(("FDC1772_WRITE: Hmm fdc1772_fdc_int_done true - resetting\n"));
238 fdc1772_fdc_int_done = 0;
241 outb(val, (reg / 2) + FDC1772BASE);
244 #define MAX_SECTORS 22
246 unsigned char *DMABuffer; /* buffer for writes */
247 /*static unsigned long PhysDMABuffer; *//* physical address */
248 /* DAG: On Arc we just go straight for the DMA buffer */
249 #define PhysDMABuffer DMABuffer
251 #ifdef TRACKBUFFER
252 unsigned char *TrackBuffer; /* buffer for reads */
253 #define PhysTrackBuffer TrackBuffer /* physical address */
254 static int BufferDrive, BufferSide, BufferTrack;
255 static int read_track; /* non-zero if we are reading whole tracks */
257 #define SECTOR_BUFFER(sec) (TrackBuffer + ((sec)-1)*512)
258 #define IS_BUFFERED(drive,side,track) \
259 (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track))
260 #endif
263 * These are global variables, as that's the easiest way to give
264 * information to interrupts. They are the data used for the current
265 * request.
267 static int SelectedDrive = 0;
268 static int ReqCmd, ReqBlock;
269 static int ReqSide, ReqTrack, ReqSector, ReqCnt;
270 static int HeadSettleFlag = 0;
271 static unsigned char *ReqData, *ReqBuffer;
272 static int MotorOn = 0, MotorOffTrys;
274 /* Synchronization of FDC1772 access. */
275 static volatile int fdc_busy = 0;
276 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
279 static unsigned int changed_floppies = 0xff, fake_change = 0;
280 #define CHECK_CHANGE_DELAY HZ/2
282 /* DAG - increased to 30*HZ - not sure if this is the correct thing to do */
283 #define FD_MOTOR_OFF_DELAY (10*HZ)
284 #define FD_MOTOR_OFF_MAXTRY (10*20)
286 #define FLOPPY_TIMEOUT (6*HZ)
287 #define RECALIBRATE_ERRORS 4 /* After this many errors the drive
288 * will be recalibrated. */
289 #define MAX_ERRORS 8 /* After this many errors the driver
290 * will give up. */
293 #define START_MOTOR_OFF_TIMER(delay) \
294 do { \
295 motor_off_timer.expires = jiffies + (delay); \
296 add_timer( &motor_off_timer ); \
297 MotorOffTrys = 0; \
298 } while(0)
300 #define START_CHECK_CHANGE_TIMER(delay) \
301 do { \
302 timer_table[FLOPPY_TIMER].expires = jiffies + (delay); \
303 timer_active |= (1 << FLOPPY_TIMER); \
304 } while(0)
306 #define START_TIMEOUT() \
307 do { \
308 del_timer( &timeout_timer ); \
309 timeout_timer.expires = jiffies + FLOPPY_TIMEOUT; \
310 add_timer( &timeout_timer ); \
311 } while(0)
313 #define STOP_TIMEOUT() \
314 do { \
315 del_timer( &timeout_timer ); \
316 } while(0)
318 #define ENABLE_IRQ() enable_irq(FIQ_FD1772+64);
320 #define DISABLE_IRQ() disable_irq(FIQ_FD1772+64);
322 static void fd1772_checkint(void);
324 struct tq_struct fd1772_tq =
325 { 0,0, (void *)fd1772_checkint, 0 };
327 * The driver is trying to determine the correct media format
328 * while Probing is set. fd_rwsec_done() clears it after a
329 * successful access.
331 static int Probing = 0;
333 /* This flag is set when a dummy seek is necesary to make the WP
334 * status bit accessible.
336 static int NeedSeek = 0;
339 /***************************** Prototypes *****************************/
341 static void fd_select_side(int side);
342 static void fd_select_drive(int drive);
343 static void fd_deselect(void);
344 static void fd_motor_off_timer(unsigned long dummy);
345 static void check_change(void);
346 static __inline__ void set_head_settle_flag(void);
347 static __inline__ int get_head_settle_flag(void);
348 static void floppy_irqconsequencehandler(void);
349 static void fd_error(void);
350 static void do_fd_action(int drive);
351 static void fd_calibrate(void);
352 static void fd_calibrate_done(int status);
353 static void fd_seek(void);
354 static void fd_seek_done(int status);
355 static void fd_rwsec(void);
356 #ifdef TRACKBUFFER
357 static void fd_readtrack_check( unsigned long dummy );
358 #endif
359 static void fd_rwsec_done(int status);
360 static void fd_times_out(unsigned long dummy);
361 static void finish_fdc(void);
362 static void finish_fdc_done(int dummy);
363 static void floppy_off(unsigned int nr);
364 static __inline__ void copy_buffer(void *from, void *to);
365 static void setup_req_params(int drive);
366 static void redo_fd_request(void);
367 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int
368 cmd, unsigned long param);
369 static void fd_probe(int drive);
370 static int fd_test_drive_present(int drive);
371 static void config_types(void);
372 static int floppy_open(struct inode *inode, struct file *filp);
373 static void floppy_release(struct inode *inode, struct file *filp);
375 /************************* End of Prototypes **************************/
377 static struct timer_list motor_off_timer =
378 {NULL, NULL, 0, 0, fd_motor_off_timer};
379 #ifdef TRACKBUFFER
380 static struct timer_list readtrack_timer =
381 { NULL, NULL, 0, 0, fd_readtrack_check };
382 #endif
383 static struct timer_list timeout_timer =
384 {NULL, NULL, 0, 0, fd_times_out};
386 /* DAG: Haven't got a clue what this is? */
387 int stdma_islocked(void)
389 return 0;
392 /* Select the side to use. */
394 static void fd_select_side(int side)
396 unsigned long flags;
398 save_flags(flags);
399 cli();
401 oldlatch_aupdate(LATCHA_SIDESEL, side ? 0 : LATCHA_SIDESEL);
402 restore_flags(flags);
406 /* Select a drive, update the FDC1772's track register
409 static void fd_select_drive(int drive)
411 unsigned long flags;
413 #ifdef DEBUG
414 printk("fd_select_drive:%d\n", drive);
415 #endif
416 /* Hmm - nowhere do we seem to turn the motor on - I'm going to do it here! */
417 oldlatch_aupdate(LATCHA_MOTOR | LATCHA_INUSE, 0);
419 if (drive == SelectedDrive)
420 return;
422 save_flags(flags);
423 cli();
424 oldlatch_aupdate(LATCHA_FDSELALL, 0xf - (1 << drive));
425 restore_flags(flags);
427 /* restore track register to saved value */
428 FDC1772_WRITE(FDC1772REG_TRACK, unit[drive].track);
429 udelay(25);
431 SelectedDrive = drive;
435 /* Deselect both drives. */
437 static void fd_deselect(void)
439 unsigned long flags;
441 DPRINT(("fd_deselect\n"));
443 save_flags(flags);
444 cli();
445 oldlatch_aupdate(LATCHA_FDSELALL | LATCHA_MOTOR | LATCHA_INUSE, 0xf | LATCHA_MOTOR | LATCHA_INUSE);
446 restore_flags(flags);
448 SelectedDrive = -1;
452 /* This timer function deselects the drives when the FDC1772 switched the
453 * motor off. The deselection cannot happen earlier because the FDC1772
454 * counts the index signals, which arrive only if one drive is selected.
457 static void fd_motor_off_timer(unsigned long dummy)
459 unsigned long flags;
460 unsigned char status;
461 int delay;
463 del_timer(&motor_off_timer);
465 if (SelectedDrive < 0)
466 /* no drive selected, needn't deselect anyone */
467 return;
469 save_flags(flags);
470 cli();
472 if (fdc_busy) /* was stdma_islocked */
473 goto retry;
475 status = FDC1772_READ(FDC1772REG_STATUS);
477 if (!(status & 0x80)) {
478 /* motor already turned off by FDC1772 -> deselect drives */
479 /* In actual fact its this deselection which turns the motor off on the
480 Arc, since the motor control is actually on Latch A */
481 DPRINT(("fdc1772: deselecting in fd_motor_off_timer\n"));
482 fd_deselect();
483 MotorOn = 0;
484 restore_flags(flags);
485 return;
487 /* not yet off, try again */
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...
496 delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ?
497 (++MotorOffTrys, HZ / 20) : HZ / 2;
498 START_MOTOR_OFF_TIMER(delay);
502 /* This function is repeatedly called to detect disk changes (as good
503 * as possible) and keep track of the current state of the write protection.
506 static void check_change(void)
508 static int drive = 0;
510 unsigned long flags;
511 int stat;
513 if (fdc_busy)
514 return; /* Don't start poking about if the fdc is busy */
516 return; /* let's just forget it for the mo DAG */
518 if (++drive > 1 || !unit[drive].connected)
519 drive = 0;
521 save_flags(flags);
522 cli();
524 if (!stdma_islocked()) {
525 stat = !!(FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_WPROT);
527 /* The idea here is that if the write protect line has changed then
528 the disc must have changed */
529 if (stat != unit[drive].wpstat) {
530 DPRINT(("wpstat[%d] = %d\n", drive, stat));
531 unit[drive].wpstat = stat;
532 set_bit(drive, &changed_floppies);
535 restore_flags(flags);
537 START_CHECK_CHANGE_TIMER(CHECK_CHANGE_DELAY);
541 /* Handling of the Head Settling Flag: This flag should be set after each
542 * seek operation, because we don't use seeks with verify.
545 static __inline__ void set_head_settle_flag(void)
547 HeadSettleFlag = FDC1772CMDADD_E;
550 static __inline__ int get_head_settle_flag(void)
552 int tmp = HeadSettleFlag;
553 HeadSettleFlag = 0;
554 return (tmp);
560 /* General Interrupt Handling */
562 static void (*FloppyIRQHandler) (int status) = NULL;
564 static void floppy_irqconsequencehandler(void)
566 unsigned char status;
567 void (*handler) (int);
569 fdc1772_fdc_int_done = 0;
571 handler = FloppyIRQHandler;
572 FloppyIRQHandler = NULL;
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));
582 DPRINT(("FDC1772 irq: end of floppy_irq\n"));
586 /* Error handling: If some error happened, retry some times, then
587 * recalibrate, then try again, and fail after MAX_ERRORS.
590 static void fd_error(void)
592 printk("FDC1772: fd_error\n");
593 /*panic("fd1772: fd_error"); *//* DAG tmp */
594 if (!CURRENT)
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;
605 redo_fd_request();
610 #define SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0)
613 /* do_fd_action() is the general procedure for a fd request: All
614 * required parameter settings (drive select, side select, track
615 * position) are checked and set if needed. For each of these
616 * parameters and the actual reading or writing exist two functions:
617 * one that starts the setting (or skips it if possible) and one
618 * callback for the "done" interrupt. Each done func calls the next
619 * set function to propagate the request down to fd_rwsec_done().
622 static void do_fd_action(int drive)
624 DPRINT(("do_fd_action unit[drive].track=%d\n", unit[drive].track));
626 #ifdef TRACKBUFFER
627 repeat:
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;
637 else {
638 /* all sectors finished */
639 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
640 CURRENT->sector += CURRENT->current_nr_sectors;
641 end_request( 1 );
642 redo_fd_request();
643 return;
646 else {
647 /* cmd == WRITE, pay attention to track buffer
648 * consistency! */
649 copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) );
652 #endif
654 if (SelectedDrive != drive) {
655 /*unit[drive].track = -1; DAG */
656 fd_select_drive(drive);
660 if (unit[drive].track == -1)
661 fd_calibrate();
662 else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch)
663 fd_seek();
664 else
665 fd_rwsec();
669 /* Seek to track 0 if the current track is unknown */
671 static void fd_calibrate(void)
673 DPRINT(("fd_calibrate\n"));
674 if (unit[SelectedDrive].track >= 0) {
675 fd_calibrate_done(0);
676 return;
678 DPRINT(("fd_calibrate (after track compare)\n"));
679 SET_IRQ_HANDLER(fd_calibrate_done);
680 /* we can't verify, since the speed may be incorrect */
681 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate);
683 NeedSeek = 1;
684 MotorOn = 1;
685 START_TIMEOUT();
686 /* wait for IRQ */
690 static void fd_calibrate_done(int status)
692 DPRINT(("fd_calibrate_done()\n"));
693 STOP_TIMEOUT();
695 /* set the correct speed now */
696 if (status & FDC1772STAT_RECNF) {
697 printk("fd%d: restore failed\n", SelectedDrive);
698 fd_error();
699 } else {
700 unit[SelectedDrive].track = 0;
701 fd_seek();
706 /* Seek the drive to the requested track. The drive must have been
707 * calibrated at some point before this.
710 static void fd_seek(void)
712 unsigned long flags;
713 DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n", ReqTrack,
714 unit[SelectedDrive].track));
715 if (unit[SelectedDrive].track == ReqTrack <<
716 unit[SelectedDrive].disktype->stretch) {
717 fd_seek_done(0);
718 return;
720 FDC1772_WRITE(FDC1772REG_DATA, ReqTrack <<
721 unit[SelectedDrive].disktype->stretch);
722 udelay(25);
723 save_flags(flags);
724 cliIF();
725 SET_IRQ_HANDLER(fd_seek_done);
726 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate |
727 /* DAG */
728 (MotorOn?FDC1772CMDADD_H:0));
730 restore_flags(flags);
731 MotorOn = 1;
732 set_head_settle_flag();
733 START_TIMEOUT();
734 /* wait for IRQ */
738 static void fd_seek_done(int status)
740 DPRINT(("fd_seek_done()\n"));
741 STOP_TIMEOUT();
743 /* set the correct speed */
744 if (status & FDC1772STAT_RECNF) {
745 printk("fd%d: seek error (to track %d)\n",
746 SelectedDrive, ReqTrack);
747 /* we don't know exactly which track we are on now! */
748 unit[SelectedDrive].track = -1;
749 fd_error();
750 } else {
751 unit[SelectedDrive].track = ReqTrack <<
752 unit[SelectedDrive].disktype->stretch;
753 NeedSeek = 0;
754 fd_rwsec();
759 /* This does the actual reading/writing after positioning the head
760 * over the correct track.
763 #ifdef TRACKBUFFER
764 static int MultReadInProgress = 0;
765 #endif
768 static void fd_rwsec(void)
770 unsigned long paddr, flags;
771 unsigned int rwflag, old_motoron;
772 unsigned int track;
774 DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n", ReqSector, ReqCmd == WRITE ? 'w' : 'r'));
775 if (ReqCmd == WRITE) {
776 /*cache_push( (unsigned long)ReqData, 512 ); */
777 paddr = (unsigned long) ReqData;
778 rwflag = 0x100;
779 } else {
780 #ifdef TRACKBUFFER
781 if (read_track)
782 paddr = (unsigned long)PhysTrackBuffer;
783 else
784 paddr =(unsigned long)PhysDMABuffer;
785 #else
786 paddr = (unsigned long)PhysDMABuffer;
787 #endif
788 rwflag = 0;
791 DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n", rwflag,
792 ReqSector, FDC1772_READ(FDC1772REG_TRACK)));
793 fd_select_side(ReqSide);
795 /*DPRINT(("fd_rwsec() before start sector \n")); */
796 /* Start sector of this operation */
797 #ifdef TRACKBUFFER
798 FDC1772_WRITE( FDC1772REG_SECTOR, !read_track ? ReqSector : 1 );
799 #else
800 FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector );
801 #endif
803 /* Cheat for track if stretch != 0 */
804 if (unit[SelectedDrive].disktype->stretch) {
805 track = FDC1772_READ(FDC1772REG_TRACK);
806 FDC1772_WRITE(FDC1772REG_TRACK, track >>
807 unit[SelectedDrive].disktype->stretch);
809 udelay(25);
811 DPRINT(("fd_rwsec() before setup DMA \n"));
812 /* Setup DMA - Heavily modified by DAG */
813 save_flags(flags);
814 cliIF();
815 disable_dma(FLOPPY_DMA);
816 set_dma_mode(FLOPPY_DMA, rwflag ? DMA_MODE_WRITE : DMA_MODE_READ);
817 set_dma_addr(FLOPPY_DMA, (long) paddr); /* DAG - changed from Atari specific */
818 #ifdef TRACKBUFFER
819 set_dma_count(FLOPPY_DMA,(!read_track ? 1 : unit[SelectedDrive].disktype->spt)*512);
820 #else
821 set_dma_count(FLOPPY_DMA, 512); /* Block/sector size - going to have to change */
822 #endif
823 SET_IRQ_HANDLER(fd_rwsec_done);
824 /* Turn on dma int */
825 enable_dma(FLOPPY_DMA);
826 /* Now give it something to do */
827 FDC1772_WRITE(FDC1772REG_CMD, (rwflag ? (FDC1772CMD_WRSEC | FDC1772CMDADD_P) :
828 #ifdef TRACKBUFFER
829 (FDC1772CMD_RDSEC | (read_track ? FDC1772CMDADD_M : 0) |
830 /* Hmm - the idea here is to stop the FDC spinning the disc
831 up when we know that we already still have it spinning */
832 (MotorOn?FDC1772CMDADD_H:0))
833 #else
834 FDC1772CMD_RDSEC
835 #endif
838 restore_flags(flags);
839 DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n", flags));
840 /*sti(); *//* DAG - Hmm */
841 /* Hmm - should do something DAG */
842 old_motoron = MotorOn;
843 MotorOn = 1;
844 NeedSeek = 1;
846 /* wait for interrupt */
848 #ifdef TRACKBUFFER
849 if (read_track) {
850 /* If reading a whole track, wait about one disk rotation and
851 * then check if all sectors are read. The FDC will even
852 * search for the first non-existant sector and need 1 sec to
853 * recognise that it isn't present :-(
855 del_timer( &readtrack_timer );
856 readtrack_timer.function = fd_readtrack_check;
857 readtrack_timer.expires = jiffies + HZ/5 + (old_motoron ? 0 : HZ);
858 /* 1 rot. + 5 rot.s if motor was off */
859 DPRINT(("Setting readtrack_timer to %d @ %d\n",readtrack_timer.expires,jiffies));
860 add_timer( &readtrack_timer );
861 MultReadInProgress = 1;
863 #endif
865 /*DPRINT(("fd_rwsec() before START_TIMEOUT \n")); */
866 START_TIMEOUT();
867 /*DPRINT(("fd_rwsec() after START_TIMEOUT \n")); */
871 #ifdef TRACKBUFFER
873 static void fd_readtrack_check( unsigned long dummy )
875 { unsigned long flags, addr;
876 extern unsigned char *fdc1772_dataaddr;
878 DPRINT(("fd_readtrack_check @ %d\n",jiffies));
880 save_flags(flags);
881 cliIF();
883 del_timer( &readtrack_timer );
885 if (!MultReadInProgress) {
886 /* This prevents a race condition that could arise if the
887 * interrupt is triggered while the calling of this timer
888 * callback function takes place. The IRQ function then has
889 * already cleared 'MultReadInProgress' when control flow
890 * gets here.
892 restore_flags(flags);
893 return;
896 /* get the current DMA address */
897 addr=fdc1772_dataaddr; /* DAG - ? */
898 DPRINT(("fd_readtrack_check: addr=%x PhysTrackBuffer=%x\n",addr,PhysTrackBuffer));
900 if (addr >= PhysTrackBuffer + unit[SelectedDrive].disktype->spt*512) {
901 /* already read enough data, force an FDC interrupt to stop
902 * the read operation
904 SET_IRQ_HANDLER( NULL );
905 restore_flags(flags);
906 DPRINT(("fd_readtrack_check(): done\n"));
907 FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI );
908 udelay(25);
910 /* No error until now -- the FDC would have interrupted
911 * otherwise!
913 fd_rwsec_done( 0 );
915 else {
916 /* not yet finished, wait another tenth rotation */
917 restore_flags(flags);
918 DPRINT(("fd_readtrack_check(): not yet finished\n"));
919 readtrack_timer.expires = jiffies + HZ/5/10;
920 add_timer( &readtrack_timer );
924 #endif
926 static void fd_rwsec_done(int status)
928 unsigned int track;
930 DPRINT(("fd_rwsec_done() status=%d @ %d\n", status,jiffies));
932 #ifdef TRACKBUFFER
933 if (read_track && !MultReadInProgress) return;
934 MultReadInProgress = 0;
936 STOP_TIMEOUT();
938 if (read_track)
939 del_timer( &readtrack_timer );
940 #endif
943 /* Correct the track if stretch != 0 */
944 if (unit[SelectedDrive].disktype->stretch) {
945 track = FDC1772_READ(FDC1772REG_TRACK);
946 FDC1772_WRITE(FDC1772REG_TRACK, track <<
947 unit[SelectedDrive].disktype->stretch);
949 if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) {
950 printk("fd%d: is write protected\n", SelectedDrive);
951 goto err_end;
953 if ((status & FDC1772STAT_RECNF)
954 #ifdef TRACKBUFFER
955 /* RECNF is no error after a multiple read when the FDC
956 * searched for a non-existant sector!
958 && !(read_track &&
959 FDC1772_READ(FDC1772REG_SECTOR) > unit[SelectedDrive].disktype->spt)
960 #endif
962 if (Probing) {
963 if (unit[SelectedDrive].disktype > disk_type) {
964 /* try another disk type */
965 unit[SelectedDrive].disktype--;
966 floppy_sizes[SelectedDrive]
967 = unit[SelectedDrive].disktype->blocks >> 1;
968 } else
969 Probing = 0;
970 } else {
971 /* record not found, but not probing. Maybe stretch wrong ? Restart probing */
972 if (unit[SelectedDrive].autoprobe) {
973 unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1;
974 floppy_sizes[SelectedDrive]
975 = unit[SelectedDrive].disktype->blocks >> 1;
976 Probing = 1;
979 if (Probing) {
980 setup_req_params(SelectedDrive);
981 #ifdef TRACKBUFFER
982 BufferDrive = -1;
983 #endif
984 do_fd_action(SelectedDrive);
985 return;
987 printk("fd%d: sector %d not found (side %d, track %d)\n",
988 SelectedDrive, FDC1772_READ(FDC1772REG_SECTOR), ReqSide, ReqTrack);
989 goto err_end;
991 if (status & FDC1772STAT_CRC) {
992 printk("fd%d: CRC error (side %d, track %d, sector %d)\n",
993 SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
994 goto err_end;
996 if (status & FDC1772STAT_LOST) {
997 printk("fd%d: lost data (side %d, track %d, sector %d)\n",
998 SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
999 goto err_end;
1001 Probing = 0;
1003 if (ReqCmd == READ) {
1004 #ifdef TRACKBUFFER
1005 if (!read_track)
1007 /*cache_clear (PhysDMABuffer, 512);*/
1008 copy_buffer (DMABuffer, ReqData);
1010 else
1012 /*cache_clear (PhysTrackBuffer, MAX_SECTORS * 512);*/
1013 BufferDrive = SelectedDrive;
1014 BufferSide = ReqSide;
1015 BufferTrack = ReqTrack;
1016 copy_buffer (SECTOR_BUFFER (ReqSector), ReqData);
1018 #else
1019 /*cache_clear( PhysDMABuffer, 512 ); */
1020 copy_buffer(DMABuffer, ReqData);
1021 #endif
1023 if (++ReqCnt < CURRENT->current_nr_sectors) {
1024 /* read next sector */
1025 setup_req_params(SelectedDrive);
1026 do_fd_action(SelectedDrive);
1027 } else {
1028 /* all sectors finished */
1029 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
1030 CURRENT->sector += CURRENT->current_nr_sectors;
1031 end_request(1);
1032 redo_fd_request();
1034 return;
1036 err_end:
1037 #ifdef TRACKBUFFER
1038 BufferDrive = -1;
1039 #endif
1041 fd_error();
1045 static void fd_times_out(unsigned long dummy)
1047 SET_IRQ_HANDLER(NULL);
1048 /* If the timeout occurred while the readtrack_check timer was
1049 * active, we need to cancel it, else bad things will happen */
1050 del_timer( &readtrack_timer );
1051 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1052 udelay(25);
1054 printk("floppy timeout\n");
1055 STOP_TIMEOUT(); /* hmm - should we do this ? */
1056 fd_error();
1060 /* The (noop) seek operation here is needed to make the WP bit in the
1061 * FDC1772 status register accessible for check_change. If the last disk
1062 * operation would have been a RDSEC, this bit would always read as 0
1063 * no matter what :-( To save time, the seek goes to the track we're
1064 * already on.
1067 static void finish_fdc(void)
1069 /* DAG - just try without this dummy seek! */
1070 finish_fdc_done(0);
1071 return;
1073 if (!NeedSeek) {
1074 finish_fdc_done(0);
1075 } else {
1076 DPRINT(("finish_fdc: dummy seek started\n"));
1077 FDC1772_WRITE(FDC1772REG_DATA, unit[SelectedDrive].track);
1078 SET_IRQ_HANDLER(finish_fdc_done);
1079 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1080 MotorOn = 1;
1081 START_TIMEOUT();
1082 /* we must wait for the IRQ here, because the ST-DMA is
1083 * released immediatly afterwards and the interrupt may be
1084 * delivered to the wrong driver.
1090 static void finish_fdc_done(int dummy)
1092 unsigned long flags;
1094 DPRINT(("finish_fdc_done entered\n"));
1095 STOP_TIMEOUT();
1096 NeedSeek = 0;
1098 if ((timer_active & (1 << FLOPPY_TIMER)) &&
1099 time_after(jiffies + 5, timer_table[FLOPPY_TIMER].expires))
1100 /* If the check for a disk change is done too early after this
1101 * last seek command, the WP bit still reads wrong :-((
1103 timer_table[FLOPPY_TIMER].expires = jiffies + 5;
1104 else {
1105 /* START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1107 del_timer(&motor_off_timer);
1108 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1110 save_flags(flags);
1111 cli();
1112 /* stdma_release(); - not sure if I should do something DAG */
1113 fdc_busy = 0;
1114 wake_up(&fdc_wait);
1115 restore_flags(flags);
1117 DPRINT(("finish_fdc() finished\n"));
1121 /* Prevent "aliased" accesses. */
1122 static fd_ref[4] =
1123 {0, 0, 0, 0};
1124 static fd_device[4] =
1125 {0, 0, 0, 0};
1128 * Current device number. Taken either from the block header or from the
1129 * format request descriptor.
1131 #define CURRENT_DEVICE (CURRENT->rq_dev)
1133 /* Current error count. */
1134 #define CURRENT_ERRORS (CURRENT->errors)
1137 /* dummy for blk.h */
1138 static void floppy_off(unsigned int nr)
1143 /* On the old arcs write protect depends on the particular model
1144 of machine. On the A310, R140, and A440 there is a disc changed
1145 detect, however on the A4x0/1 range there is not. There
1146 is nothing to tell you which machine your on.
1147 At the moment I'm just marking changed always. I've
1148 left the Atari's 'change on write protect change' code in this
1149 part (but nothing sets it).
1150 RiscOS apparently checks the disc serial number etc. to detect changes
1151 - but if it sees a disc change line go high (?) it flips to using
1152 it. Well maybe I'll add that in the future (!?)
1154 static int check_floppy_change(dev_t dev)
1156 unsigned int drive = (dev & 0x03);
1158 if (MAJOR(dev) != MAJOR_NR) {
1159 printk("floppy_changed: not a floppy\n");
1160 return 0;
1162 if (test_bit(drive, &fake_change)) {
1163 /* simulated change (e.g. after formatting) */
1164 return 1;
1166 if (test_bit(drive, &changed_floppies)) {
1167 /* surely changed (the WP signal changed at least once) */
1168 return 1;
1170 if (unit[drive].wpstat) {
1171 /* WP is on -> could be changed: to be sure, buffers should be
1172 * invalidated...
1174 return 1;
1176 return 1; /* DAG - was 0 */
1179 static int floppy_revalidate(dev_t dev)
1181 int drive = dev & 3;
1183 if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change)
1184 || unit[drive].disktype == 0) {
1185 #ifdef TRACKBUFFER
1186 BufferDrive = -1;
1187 #endif
1188 clear_bit(drive, &fake_change);
1189 clear_bit(drive, &changed_floppies);
1190 unit[drive].disktype = 0;
1192 return 0;
1195 static __inline__ void copy_buffer(void *from, void *to)
1197 ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
1198 int cnt;
1200 for (cnt = 512 / 4; cnt; cnt--)
1201 *p2++ = *p1++;
1205 /* This sets up the global variables describing the current request. */
1207 static void setup_req_params(int drive)
1209 int block = ReqBlock + ReqCnt;
1211 ReqTrack = block / unit[drive].disktype->spt;
1212 ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1;
1213 ReqSide = ReqTrack & 1;
1214 ReqTrack >>= 1;
1215 ReqData = ReqBuffer + 512 * ReqCnt;
1217 #ifdef TRACKBUFFER
1218 read_track = (ReqCmd == READ && CURRENT_ERRORS == 0);
1219 #endif
1221 DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n", ReqSide,
1222 ReqTrack, ReqSector, (unsigned long) ReqData));
1226 static void redo_fd_request(void)
1228 int device, drive, type;
1229 struct archy_floppy_struct *floppy;
1231 DPRINT(("redo_fd_request: CURRENT=%08lx CURRENT->rq_dev=%04x CURRENT->sector=%ld\n",
1232 (unsigned long) CURRENT, CURRENT ? CURRENT->rq_dev : 0,
1233 CURRENT ? CURRENT->sector : 0));
1235 if (CURRENT && CURRENT->rq_status == RQ_INACTIVE)
1236 goto the_end;
1238 repeat:
1240 if (!CURRENT)
1241 goto the_end;
1243 if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
1244 panic(DEVICE_NAME ": request list destroyed");
1246 if (CURRENT->bh) {
1247 if (!buffer_locked(CURRENT->bh))
1248 panic(DEVICE_NAME ": block not locked");
1250 device = MINOR(CURRENT_DEVICE);
1251 drive = device & 3;
1252 type = device >> 2;
1253 floppy = &unit[drive];
1255 if (!floppy->connected) {
1256 /* drive not connected */
1257 printk("Unknown Device: fd%d\n", drive);
1258 end_request(0);
1259 goto repeat;
1261 if (type == 0) {
1262 if (!floppy->disktype) {
1263 Probing = 1;
1264 floppy->disktype = disk_type + NUM_DISK_TYPES - 1;
1265 floppy_sizes[drive] = floppy->disktype->blocks >> 1;
1266 floppy->autoprobe = 1;
1268 } else {
1269 /* user supplied disk type */
1270 --type;
1271 if (type >= NUM_DISK_TYPES) {
1272 printk("fd%d: invalid disk format", drive);
1273 end_request(0);
1274 goto repeat;
1276 floppy->disktype = &disk_type[type];
1277 floppy_sizes[drive] = disk_type[type].blocks >> 1;
1278 floppy->autoprobe = 0;
1281 if (CURRENT->sector + 1 > floppy->disktype->blocks) {
1282 end_request(0);
1283 goto repeat;
1285 /* stop deselect timer */
1286 del_timer(&motor_off_timer);
1288 ReqCnt = 0;
1289 ReqCmd = CURRENT->cmd;
1290 ReqBlock = CURRENT->sector;
1291 ReqBuffer = CURRENT->buffer;
1292 setup_req_params(drive);
1293 do_fd_action(drive);
1295 return;
1297 the_end:
1298 finish_fdc();
1301 static void fd1772_checkint(void)
1303 extern int fdc1772_bytestogo;
1305 /*printk("fd1772_checkint %d\n",fdc1772_fdc_int_done);*/
1306 if (fdc1772_fdc_int_done)
1307 floppy_irqconsequencehandler();
1308 if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0);
1309 if (fdc_busy) {
1310 queue_task(&fd1772_tq,&tq_immediate);
1311 mark_bh(IMMEDIATE_BH);
1315 void do_fd_request(void)
1317 unsigned long flags;
1319 DPRINT(("do_fd_request for pid %d\n", current->pid));
1320 if (fdc_busy) return;
1321 save_flags(flags);
1322 cli();
1323 while (fdc_busy)
1324 sleep_on(&fdc_wait);
1325 fdc_busy = 1;
1326 ENABLE_IRQ();
1327 restore_flags(flags);
1329 fdc1772_fdc_int_done = 0;
1331 redo_fd_request();
1333 queue_task(&fd1772_tq,&tq_immediate);
1334 mark_bh(IMMEDIATE_BH);
1338 static int invalidate_drive(int rdev)
1340 /* invalidate the buffer track to force a reread */
1341 #ifdef TRACKBUFFER
1342 BufferDrive = -1;
1343 #endif
1345 set_bit(rdev & 3, &fake_change);
1346 check_disk_change(rdev);
1347 return 0;
1350 static int fd_ioctl(struct inode *inode, struct file *filp,
1351 unsigned int cmd, unsigned long param)
1353 int drive, device;
1355 device = inode->i_rdev;
1356 switch (cmd) {
1357 RO_IOCTLS(inode->i_rdev, param);
1359 drive = MINOR(device);
1360 switch (cmd) {
1361 case FDFMTBEG:
1362 return 0;
1363 /* case FDC1772LRPRM: ??? DAG what does this do??
1364 unit[drive].disktype = NULL;
1365 floppy_sizes[drive] = MAX_DISK_SIZE;
1366 return invalidate_drive (device); */
1367 case FDFMTEND:
1368 case FDFLUSH:
1369 return invalidate_drive(drive);
1371 if (!capable(CAP_SYS_ADMIN))
1372 return -EPERM;
1373 if (drive < 0 || drive > 3)
1374 return -EINVAL;
1375 switch (cmd) {
1376 default:
1377 return -EINVAL;
1379 return 0;
1383 /* Initialize the 'unit' variable for drive 'drive' */
1385 static void fd_probe(int drive)
1387 unit[drive].connected = 0;
1388 unit[drive].disktype = NULL;
1390 if (!fd_test_drive_present(drive))
1391 return;
1393 unit[drive].connected = 1;
1394 unit[drive].track = -1; /* If we put the auto detect back in this can go to 0 */
1395 unit[drive].steprate = FDC1772STEP_6;
1396 MotorOn = 1; /* from probe restore operation! */
1400 /* This function tests the physical presence of a floppy drive (not
1401 * whether a disk is inserted). This is done by issuing a restore
1402 * command, waiting max. 2 seconds (that should be enough to move the
1403 * head across the whole disk) and looking at the state of the "TR00"
1404 * signal. This should now be raised if there is a drive connected
1405 * (and there is no hardware failure :-) Otherwise, the drive is
1406 * declared absent.
1409 static int fd_test_drive_present(int drive)
1411 unsigned long timeout;
1412 unsigned char status;
1413 int ok;
1415 printk("fd_test_drive_present %d\n", drive);
1416 if (drive > 1)
1417 return (0);
1418 return (1); /* Simple hack for the moment - the autodetect doesn't seem to work on arc */
1419 fd_select_drive(drive);
1421 /* disable interrupt temporarily */
1422 DISABLE_IRQ();
1423 FDC1772_WRITE(FDC1772REG_TRACK, 0x00); /* was ff00 why? */
1424 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6);
1426 /*printk("fd_test_drive_present: Going into timeout loop\n"); */
1427 for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; time_before(jiffies, timeout);) {
1428 /* What does this piece of atariism do? - query for an interrupt? */
1429 /* if (!(mfp.par_dt_reg & 0x20))
1430 break; */
1431 /* Well this is my nearest guess - quit when we get an FDC interrupt */
1432 if (IOC_FIQSTAT & 2)
1433 break;
1436 /*printk("fd_test_drive_present: Coming out of timeout loop\n"); */
1437 status = FDC1772_READ(FDC1772REG_STATUS);
1438 ok = (status & FDC1772STAT_TR00) != 0;
1440 /*printk("fd_test_drive_present: ok=%d\n",ok); */
1441 /* force interrupt to abort restore operation (FDC1772 would try
1442 * about 50 seconds!) */
1443 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1444 udelay(500);
1445 status = FDC1772_READ(FDC1772REG_STATUS);
1446 udelay(20);
1447 /*printk("fd_test_drive_present: just before OK code %d\n",ok); */
1449 if (ok) {
1450 /* dummy seek command to make WP bit accessible */
1451 FDC1772_WRITE(FDC1772REG_DATA, 0);
1452 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1453 printk("fd_test_drive_present: just before wait for int\n");
1454 /* DAG: Guess means wait for interrupt */
1455 while (!(IOC_FIQSTAT & 2));
1456 printk("fd_test_drive_present: just after wait for int\n");
1457 status = FDC1772_READ(FDC1772REG_STATUS);
1459 printk("fd_test_drive_present: just before ENABLE_IRQ\n");
1460 ENABLE_IRQ();
1461 printk("fd_test_drive_present: about to return\n");
1462 return (ok);
1466 /* Look how many and which kind of drives are connected. If there are
1467 * floppies, additionally start the disk-change and motor-off timers.
1470 static void config_types(void)
1472 int drive, cnt = 0;
1474 printk("Probing floppy drive(s):\n");
1475 for (drive = 0; drive < FD_MAX_UNITS; drive++) {
1476 fd_probe(drive);
1477 if (unit[drive].connected) {
1478 printk("fd%d\n", drive);
1479 ++cnt;
1483 if (FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_BUSY) {
1484 /* If FDC1772 is still busy from probing, give it another FORCI
1485 * command to abort the operation. If this isn't done, the FDC1772
1486 * will interrupt later and its IRQ line stays low, because
1487 * the status register isn't read. And this will block any
1488 * interrupts on this IRQ line :-(
1490 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1491 udelay(500);
1492 FDC1772_READ(FDC1772REG_STATUS);
1493 udelay(20);
1495 if (cnt > 0) {
1496 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1497 if (cnt == 1)
1498 fd_select_drive(0);
1499 /*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1504 * floppy_open check for aliasing (/dev/fd0 can be the same as
1505 * /dev/PS0 etc), and disallows simultaneous access to the same
1506 * drive with different device numbers.
1509 static int floppy_open(struct inode *inode, struct file *filp)
1511 int drive;
1512 int old_dev;
1514 if (!filp) {
1515 DPRINT(("Weird, open called with filp=0\n"));
1516 return -EIO;
1518 drive = MINOR(inode->i_rdev) & 3;
1519 if ((MINOR(inode->i_rdev) >> 2) > NUM_DISK_TYPES)
1520 return -ENXIO;
1522 old_dev = fd_device[drive];
1524 if (fd_ref[drive])
1525 if (old_dev != inode->i_rdev)
1526 return -EBUSY;
1528 if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
1529 return -EBUSY;
1531 if (filp->f_flags & O_EXCL)
1532 fd_ref[drive] = -1;
1533 else
1534 fd_ref[drive]++;
1536 fd_device[drive] = inode->i_rdev;
1538 if (old_dev && old_dev != inode->i_rdev)
1539 invalidate_buffers(old_dev);
1541 if (filp->f_flags & O_NDELAY)
1542 return 0;
1544 if (filp->f_mode & 3) {
1545 check_disk_change(inode->i_rdev);
1546 if (filp->f_mode & 2) {
1547 if (unit[drive].wpstat) {
1548 floppy_release(inode, filp);
1549 return -EROFS;
1553 return 0;
1557 static void floppy_release(struct inode *inode, struct file *filp)
1559 int drive = MINOR(inode->i_rdev) & 3;
1561 if (fd_ref[drive] < 0)
1562 fd_ref[drive] = 0;
1563 else if (!fd_ref[drive]--) {
1564 printk("floppy_release with fd_ref == 0");
1565 fd_ref[drive] = 0;
1569 static struct block_device_operations floppy_fops =
1571 open: floppy_open,
1572 release: floppy_release,
1573 ioctl: fd_ioctl,
1574 check_media_change: check_floppy_change,
1575 revalidate: floppy_revalidate,
1579 int fd1772_init(void)
1581 int i;
1583 if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {
1584 printk("Unable to get major %d for floppy\n", MAJOR_NR);
1585 return 1;
1588 if (request_dma(FLOPPY_DMA, "fd1772")) {
1589 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA);
1590 return 1;
1593 if (request_dma(FIQ_FD1772, "fd1772 end")) {
1594 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772);
1595 free_dma(FLOPPY_DMA);
1596 return 1;
1598 enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */
1600 /* initialize variables */
1601 SelectedDrive = -1;
1602 #ifdef TRACKBUFFER
1603 BufferDrive = -1;
1604 #endif
1606 /* initialize check_change timer */
1607 timer_table[FLOPPY_TIMER].fn = check_change;
1608 timer_active &= ~(1 << FLOPPY_TIMER);
1611 #ifdef TRACKBUFFER
1612 DMABuffer = (char *)kmalloc((MAX_SECTORS+1)*512,GFP_KERNEL); /* Atari uses 512 - I want to eventually cope with 1K sectors */
1613 TrackBuffer = DMABuffer + 512;
1614 #else
1615 /* Allocate memory for the DMAbuffer - on the Atari this takes it
1616 out of some special memory... */
1617 DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */
1618 #endif
1619 #ifdef TRACKBUFFER
1620 BufferDrive = BufferSide = BufferTrack = -1;
1621 #endif
1623 for (i = 0; i < FD_MAX_UNITS; i++) {
1624 unit[i].track = -1;
1627 for (i = 0; i < 256; i++)
1628 if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_TYPES)
1629 floppy_sizes[i] = disk_type[(i >> 2) - 1].blocks >> 1;
1630 else
1631 floppy_sizes[i] = MAX_DISK_SIZE;
1633 blk_size[MAJOR_NR] = floppy_sizes;
1634 blksize_size[MAJOR_NR] = floppy_blocksizes;
1635 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1637 config_types();
1639 return 0;
1642 /* Just a dummy at the moment */
1643 void floppy_setup(char *str, int *ints)
1647 void floppy_eject(void) {