Import 2.1.118
[davej-history.git] / drivers / acorn / block / fd1772.c
bloba92320305539e4dec464c090960a754076fb5210
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
119 #include <linux/sched.h>
120 #include <linux/fs.h>
121 #include <linux/fcntl.h>
122 #include <linux/kernel.h>
123 #include <linux/interrupt.h>
124 #include <linux/timer.h>
125 #include <linux/tqueue.h>
126 #include <linux/fd.h>
127 #include <linux/fd1772.h>
128 #include <linux/errno.h>
129 #include <linux/types.h>
130 #include <linux/delay.h>
131 #include <linux/mm.h>
133 #include <asm/arch/oldlatches.h>
134 #include <asm/system.h>
135 #include <asm/bitops.h>
136 #include <asm/dma.h>
137 #include <asm/hardware.h>
138 #include <asm/io.h>
139 #include <asm/irq.h>
140 #include <asm/irq-no.h>
141 #include <asm/pgtable.h>
142 #include <asm/segment.h>
144 #define MAJOR_NR FLOPPY_MAJOR
145 #define FLOPPY_DMA 0
146 #include "blk.h"
148 /* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with
149 * little additional rework in this file). But I'm not yet sure if
150 * some other code depends on the number of floppies... (It is defined
151 * in a public header!)
153 #if 0
154 #undef FD_MAX_UNITS
155 #define FD_MAX_UNITS 2
156 #endif
158 /* Ditto worries for Arc - DAG */
159 #define FD_MAX_UNITS 4
160 #define TRACKBUFFER 0
161 /*#define DEBUG*/
163 #ifdef DEBUG
164 #define DPRINT(a) printk a
165 #else
166 #define DPRINT(a)
167 #endif
169 /* Disk types: DD */
170 static struct archy_disk_type {
171 const char *name;
172 unsigned spt; /* sectors per track */
173 unsigned blocks; /* total number of blocks */
174 unsigned stretch; /* track doubling ? */
175 } disk_type[] = {
177 { "d360", 9, 720, 0 }, /* 360kB diskette */
178 { "D360", 9, 720, 1 }, /* 360kb in 720kb drive */
179 { "D720", 9, 1440, 0 }, /* 720kb diskette (DD) */
180 /*{ "D820", 10,1640, 0}, *//* DD disk with 82 tracks/10 sectors
181 - DAG - can't see how type detect can distinguish this
182 from 720K until it reads block 4 by which time its too late! */
185 #define NUM_DISK_TYPES (sizeof(disk_type)/sizeof(*disk_type))
188 * Maximum disk size (in kilobytes). This default is used whenever the
189 * current disk size is unknown.
191 #define MAX_DISK_SIZE 720
193 static int floppy_sizes[256];
194 static int floppy_blocksizes[256] = {0,};
196 /* current info on each unit */
197 static struct archy_floppy_struct {
198 int connected; /* !=0 : drive is connected */
199 int autoprobe; /* !=0 : do autoprobe */
201 struct archy_disk_type *disktype; /* current type of disk */
203 int track; /* current head position or -1
204 * if unknown */
205 unsigned int steprate; /* steprate setting */
206 unsigned int wpstat; /* current state of WP signal
207 * (for disk change detection) */
208 } unit[FD_MAX_UNITS];
210 /* DAG: On Arc we spin on a flag being cleared by fdc1772_comendhandler which
211 is an assembler routine */
212 extern void fdc1772_comendhandler(void); /* Actually doens't have these parameters - see fd1772.S */
213 extern volatile int fdc1772_comendstatus;
214 extern volatile int fdc1772_fdc_int_done;
216 #define FDC1772BASE ((0x210000>>2)|0x80000000)
218 #define FDC1772_READ(reg) inb(FDC1772BASE+(reg/2))
220 /* DAG: You wouldn't be silly to ask why FDC1772_WRITE is a function rather
221 than the #def below - well simple - the #def won't compile - and I
222 don't understand why (__outwc not defined) */
223 /* NOTE: Reg is 0,2,4,6 as opposed to 0,1,2,3 or 0,4,8,12 to keep compatibility
224 with the ST version of fd1772.h */
225 /*#define FDC1772_WRITE(reg,val) outw(val,(reg+FDC1772BASE)); */
226 void FDC1772_WRITE(int reg, unsigned char val)
228 if (reg == FDC1772REG_CMD) {
229 DPRINT(("FDC1772_WRITE new command 0x%x @ %d\n", val,jiffies));
230 if (fdc1772_fdc_int_done) {
231 DPRINT(("FDC1772_WRITE: Hmm fdc1772_fdc_int_done true - resetting\n"));
232 fdc1772_fdc_int_done = 0;
235 outb(val, (reg / 2) + FDC1772BASE);
238 #define MAX_SECTORS 22
240 unsigned char *DMABuffer; /* buffer for writes */
241 /*static unsigned long PhysDMABuffer; *//* physical address */
242 /* DAG: On Arc we just go straight for the DMA buffer */
243 #define PhysDMABuffer DMABuffer
245 #ifdef TRACKBUFFER
246 unsigned char *TrackBuffer; /* buffer for reads */
247 #define PhysTrackBuffer TrackBuffer /* physical address */
248 static int BufferDrive, BufferSide, BufferTrack;
249 static int read_track; /* non-zero if we are reading whole tracks */
251 #define SECTOR_BUFFER(sec) (TrackBuffer + ((sec)-1)*512)
252 #define IS_BUFFERED(drive,side,track) \
253 (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track))
254 #endif
257 * These are global variables, as that's the easiest way to give
258 * information to interrupts. They are the data used for the current
259 * request.
261 static int SelectedDrive = 0;
262 static int ReqCmd, ReqBlock;
263 static int ReqSide, ReqTrack, ReqSector, ReqCnt;
264 static int HeadSettleFlag = 0;
265 static unsigned char *ReqData, *ReqBuffer;
266 static int MotorOn = 0, MotorOffTrys;
268 /* Synchronization of FDC1772 access. */
269 static volatile int fdc_busy = 0;
270 static struct wait_queue *fdc_wait = NULL;
273 static unsigned int changed_floppies = 0xff, fake_change = 0;
274 #define CHECK_CHANGE_DELAY HZ/2
276 /* DAG - increased to 30*HZ - not sure if this is the correct thing to do */
277 #define FD_MOTOR_OFF_DELAY (10*HZ)
278 #define FD_MOTOR_OFF_MAXTRY (10*20)
280 #define FLOPPY_TIMEOUT (6*HZ)
281 #define RECALIBRATE_ERRORS 4 /* After this many errors the drive
282 * will be recalibrated. */
283 #define MAX_ERRORS 8 /* After this many errors the driver
284 * will give up. */
287 #define START_MOTOR_OFF_TIMER(delay) \
288 do { \
289 motor_off_timer.expires = jiffies + (delay); \
290 add_timer( &motor_off_timer ); \
291 MotorOffTrys = 0; \
292 } while(0)
294 #define START_CHECK_CHANGE_TIMER(delay) \
295 do { \
296 timer_table[FLOPPY_TIMER].expires = jiffies + (delay); \
297 timer_active |= (1 << FLOPPY_TIMER); \
298 } while(0)
300 #define START_TIMEOUT() \
301 do { \
302 del_timer( &timeout_timer ); \
303 timeout_timer.expires = jiffies + FLOPPY_TIMEOUT; \
304 add_timer( &timeout_timer ); \
305 } while(0)
307 #define STOP_TIMEOUT() \
308 do { \
309 del_timer( &timeout_timer ); \
310 } while(0)
312 #define ENABLE_IRQ() enable_irq(FIQ_FD1772+64);
314 #define DISABLE_IRQ() disable_irq(FIQ_FD1772+64);
316 static void fd1772_checkint(void);
318 struct tq_struct fd1772_tq =
319 { 0,0, (void *)fd1772_checkint, 0 };
321 * The driver is trying to determine the correct media format
322 * while Probing is set. fd_rwsec_done() clears it after a
323 * successful access.
325 static int Probing = 0;
327 /* This flag is set when a dummy seek is necesary to make the WP
328 * status bit accessible.
330 static int NeedSeek = 0;
333 /***************************** Prototypes *****************************/
335 static void fd_select_side(int side);
336 static void fd_select_drive(int drive);
337 static void fd_deselect(void);
338 static void fd_motor_off_timer(unsigned long dummy);
339 static void check_change(void);
340 static __inline__ void set_head_settle_flag(void);
341 static __inline__ int get_head_settle_flag(void);
342 static void floppy_irqconsequencehandler(void);
343 static void fd_error(void);
344 static void do_fd_action(int drive);
345 static void fd_calibrate(void);
346 static void fd_calibrate_done(int status);
347 static void fd_seek(void);
348 static void fd_seek_done(int status);
349 static void fd_rwsec(void);
350 #ifdef TRACKBUFFER
351 static void fd_readtrack_check( unsigned long dummy );
352 #endif
353 static void fd_rwsec_done(int status);
354 static void fd_times_out(unsigned long dummy);
355 static void finish_fdc(void);
356 static void finish_fdc_done(int dummy);
357 static void floppy_off(unsigned int nr);
358 static __inline__ void copy_buffer(void *from, void *to);
359 static void setup_req_params(int drive);
360 static void redo_fd_request(void);
361 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int
362 cmd, unsigned long param);
363 static void fd_probe(int drive);
364 static int fd_test_drive_present(int drive);
365 static void config_types(void);
366 static int floppy_open(struct inode *inode, struct file *filp);
367 static void floppy_release(struct inode *inode, struct file *filp);
369 /************************* End of Prototypes **************************/
371 static struct timer_list motor_off_timer =
372 {NULL, NULL, 0, 0, fd_motor_off_timer};
373 #ifdef TRACKBUFFER
374 static struct timer_list readtrack_timer =
375 { NULL, NULL, 0, 0, fd_readtrack_check };
376 #endif
377 static struct timer_list timeout_timer =
378 {NULL, NULL, 0, 0, fd_times_out};
380 /* DAG: Haven't got a clue what this is? */
381 int stdma_islocked(void)
383 return 0;
386 /* Select the side to use. */
388 static void fd_select_side(int side)
390 unsigned long flags;
392 save_flags(flags);
393 cli();
395 oldlatch_aupdate(LATCHA_SIDESEL, side ? 0 : LATCHA_SIDESEL);
396 restore_flags(flags);
400 /* Select a drive, update the FDC1772's track register
403 static void fd_select_drive(int drive)
405 unsigned long flags;
407 #ifdef DEBUG
408 printk("fd_select_drive:%d\n", drive);
409 #endif
410 /* Hmm - nowhere do we seem to turn the motor on - I'm going to do it here! */
411 oldlatch_aupdate(LATCHA_MOTOR | LATCHA_INUSE, 0);
413 if (drive == SelectedDrive)
414 return;
416 save_flags(flags);
417 cli();
418 oldlatch_aupdate(LATCHA_FDSELALL, 0xf - (1 << drive));
419 restore_flags(flags);
421 /* restore track register to saved value */
422 FDC1772_WRITE(FDC1772REG_TRACK, unit[drive].track);
423 udelay(25);
425 SelectedDrive = drive;
429 /* Deselect both drives. */
431 static void fd_deselect(void)
433 unsigned long flags;
435 DPRINT(("fd_deselect\n"));
437 save_flags(flags);
438 cli();
439 oldlatch_aupdate(LATCHA_FDSELALL | LATCHA_MOTOR | LATCHA_INUSE, 0xf | LATCHA_MOTOR | LATCHA_INUSE);
440 restore_flags(flags);
442 SelectedDrive = -1;
446 /* This timer function deselects the drives when the FDC1772 switched the
447 * motor off. The deselection cannot happen earlier because the FDC1772
448 * counts the index signals, which arrive only if one drive is selected.
451 static void fd_motor_off_timer(unsigned long dummy)
453 unsigned long flags;
454 unsigned char status;
455 int delay;
457 del_timer(&motor_off_timer);
459 if (SelectedDrive < 0)
460 /* no drive selected, needn't deselect anyone */
461 return;
463 save_flags(flags);
464 cli();
466 if (fdc_busy) /* was stdma_islocked */
467 goto retry;
469 status = FDC1772_READ(FDC1772REG_STATUS);
471 if (!(status & 0x80)) {
472 /* motor already turned off by FDC1772 -> deselect drives */
473 /* In actual fact its this deselection which turns the motor off on the
474 Arc, since the motor control is actually on Latch A */
475 DPRINT(("fdc1772: deselecting in fd_motor_off_timer\n"));
476 fd_deselect();
477 MotorOn = 0;
478 restore_flags(flags);
479 return;
481 /* not yet off, try again */
483 retry:
484 restore_flags(flags);
485 /* Test again later; if tested too often, it seems there is no disk
486 * in the drive and the FDC1772 will leave the motor on forever (or,
487 * at least until a disk is inserted). So we'll test only twice
488 * per second from then on...
490 delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ?
491 (++MotorOffTrys, HZ / 20) : HZ / 2;
492 START_MOTOR_OFF_TIMER(delay);
496 /* This function is repeatedly called to detect disk changes (as good
497 * as possible) and keep track of the current state of the write protection.
500 static void check_change(void)
502 static int drive = 0;
504 unsigned long flags;
505 int stat;
507 if (fdc_busy)
508 return; /* Don't start poking about if the fdc is busy */
510 return; /* let's just forget it for the mo DAG */
512 if (++drive > 1 || !unit[drive].connected)
513 drive = 0;
515 save_flags(flags);
516 cli();
518 if (!stdma_islocked()) {
519 stat = !!(FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_WPROT);
521 /* The idea here is that if the write protect line has changed then
522 the disc must have changed */
523 if (stat != unit[drive].wpstat) {
524 DPRINT(("wpstat[%d] = %d\n", drive, stat));
525 unit[drive].wpstat = stat;
526 set_bit(drive, &changed_floppies);
529 restore_flags(flags);
531 START_CHECK_CHANGE_TIMER(CHECK_CHANGE_DELAY);
535 /* Handling of the Head Settling Flag: This flag should be set after each
536 * seek operation, because we don't use seeks with verify.
539 static __inline__ void set_head_settle_flag(void)
541 HeadSettleFlag = FDC1772CMDADD_E;
544 static __inline__ int get_head_settle_flag(void)
546 int tmp = HeadSettleFlag;
547 HeadSettleFlag = 0;
548 return (tmp);
554 /* General Interrupt Handling */
556 static void (*FloppyIRQHandler) (int status) = NULL;
558 static void floppy_irqconsequencehandler(void)
560 unsigned char status;
561 void (*handler) (int);
563 fdc1772_fdc_int_done = 0;
565 handler = FloppyIRQHandler;
566 FloppyIRQHandler = NULL;
568 if (handler) {
569 nop();
570 status = (unsigned char) fdc1772_comendstatus;
571 DPRINT(("FDC1772 irq, status = %02x handler = %08lx\n", (unsigned int) status, (unsigned long) handler));
572 handler(status);
573 } else {
574 DPRINT(("FDC1772 irq, no handler status=%02x\n", fdc1772_comendstatus));
576 DPRINT(("FDC1772 irq: end of floppy_irq\n"));
580 /* Error handling: If some error happened, retry some times, then
581 * recalibrate, then try again, and fail after MAX_ERRORS.
584 static void fd_error(void)
586 printk("FDC1772: fd_error\n");
587 /*panic("fd1772: fd_error"); *//* DAG tmp */
588 if (!CURRENT)
589 return;
590 CURRENT->errors++;
591 if (CURRENT->errors >= MAX_ERRORS) {
592 printk("fd%d: too many errors.\n", SelectedDrive);
593 end_request(0);
594 } else if (CURRENT->errors == RECALIBRATE_ERRORS) {
595 printk("fd%d: recalibrating\n", SelectedDrive);
596 if (SelectedDrive != -1)
597 unit[SelectedDrive].track = -1;
599 redo_fd_request();
604 #define SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0)
607 /* do_fd_action() is the general procedure for a fd request: All
608 * required parameter settings (drive select, side select, track
609 * position) are checked and set if needed. For each of these
610 * parameters and the actual reading or writing exist two functions:
611 * one that starts the setting (or skips it if possible) and one
612 * callback for the "done" interrupt. Each done func calls the next
613 * set function to propagate the request down to fd_rwsec_done().
616 static void do_fd_action(int drive)
618 DPRINT(("do_fd_action unit[drive].track=%d\n", unit[drive].track));
620 #ifdef TRACKBUFFER
621 repeat:
623 if (IS_BUFFERED( drive, ReqSide, ReqTrack )) {
624 if (ReqCmd == READ) {
625 copy_buffer( SECTOR_BUFFER(ReqSector), ReqData );
626 if (++ReqCnt < CURRENT->current_nr_sectors) {
627 /* read next sector */
628 setup_req_params( drive );
629 goto repeat;
631 else {
632 /* all sectors finished */
633 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
634 CURRENT->sector += CURRENT->current_nr_sectors;
635 end_request( 1 );
636 redo_fd_request();
637 return;
640 else {
641 /* cmd == WRITE, pay attention to track buffer
642 * consistency! */
643 copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) );
646 #endif
648 if (SelectedDrive != drive) {
649 /*unit[drive].track = -1; DAG */
650 fd_select_drive(drive);
654 if (unit[drive].track == -1)
655 fd_calibrate();
656 else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch)
657 fd_seek();
658 else
659 fd_rwsec();
663 /* Seek to track 0 if the current track is unknown */
665 static void fd_calibrate(void)
667 DPRINT(("fd_calibrate\n"));
668 if (unit[SelectedDrive].track >= 0) {
669 fd_calibrate_done(0);
670 return;
672 DPRINT(("fd_calibrate (after track compare)\n"));
673 SET_IRQ_HANDLER(fd_calibrate_done);
674 /* we can't verify, since the speed may be incorrect */
675 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate);
677 NeedSeek = 1;
678 MotorOn = 1;
679 START_TIMEOUT();
680 /* wait for IRQ */
684 static void fd_calibrate_done(int status)
686 DPRINT(("fd_calibrate_done()\n"));
687 STOP_TIMEOUT();
689 /* set the correct speed now */
690 if (status & FDC1772STAT_RECNF) {
691 printk("fd%d: restore failed\n", SelectedDrive);
692 fd_error();
693 } else {
694 unit[SelectedDrive].track = 0;
695 fd_seek();
700 /* Seek the drive to the requested track. The drive must have been
701 * calibrated at some point before this.
704 static void fd_seek(void)
706 unsigned long flags;
707 DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n", ReqTrack,
708 unit[SelectedDrive].track));
709 if (unit[SelectedDrive].track == ReqTrack <<
710 unit[SelectedDrive].disktype->stretch) {
711 fd_seek_done(0);
712 return;
714 FDC1772_WRITE(FDC1772REG_DATA, ReqTrack <<
715 unit[SelectedDrive].disktype->stretch);
716 udelay(25);
717 save_flags(flags);
718 cliIF();
719 SET_IRQ_HANDLER(fd_seek_done);
720 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate |
721 /* DAG */
722 (MotorOn?FDC1772CMDADD_H:0));
724 restore_flags(flags);
725 MotorOn = 1;
726 set_head_settle_flag();
727 START_TIMEOUT();
728 /* wait for IRQ */
732 static void fd_seek_done(int status)
734 DPRINT(("fd_seek_done()\n"));
735 STOP_TIMEOUT();
737 /* set the correct speed */
738 if (status & FDC1772STAT_RECNF) {
739 printk("fd%d: seek error (to track %d)\n",
740 SelectedDrive, ReqTrack);
741 /* we don't know exactly which track we are on now! */
742 unit[SelectedDrive].track = -1;
743 fd_error();
744 } else {
745 unit[SelectedDrive].track = ReqTrack <<
746 unit[SelectedDrive].disktype->stretch;
747 NeedSeek = 0;
748 fd_rwsec();
753 /* This does the actual reading/writing after positioning the head
754 * over the correct track.
757 #ifdef TRACKBUFFER
758 static int MultReadInProgress = 0;
759 #endif
762 static void fd_rwsec(void)
764 unsigned long paddr, flags;
765 unsigned int rwflag, old_motoron;
766 unsigned int track;
768 DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n", ReqSector, ReqCmd == WRITE ? 'w' : 'r'));
769 if (ReqCmd == WRITE) {
770 /*cache_push( (unsigned long)ReqData, 512 ); */
771 paddr = (unsigned long) ReqData;
772 rwflag = 0x100;
773 } else {
774 #ifdef TRACKBUFFER
775 if (read_track)
776 paddr = (unsigned long)PhysTrackBuffer;
777 else
778 paddr =(unsigned long)PhysDMABuffer;
779 #else
780 paddr = (unsigned long)PhysDMABuffer;
781 #endif
782 rwflag = 0;
785 DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n", rwflag,
786 ReqSector, FDC1772_READ(FDC1772REG_TRACK)));
787 fd_select_side(ReqSide);
789 /*DPRINT(("fd_rwsec() before start sector \n")); */
790 /* Start sector of this operation */
791 #ifdef TRACKBUFFER
792 FDC1772_WRITE( FDC1772REG_SECTOR, !read_track ? ReqSector : 1 );
793 #else
794 FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector );
795 #endif
797 /* Cheat for track if stretch != 0 */
798 if (unit[SelectedDrive].disktype->stretch) {
799 track = FDC1772_READ(FDC1772REG_TRACK);
800 FDC1772_WRITE(FDC1772REG_TRACK, track >>
801 unit[SelectedDrive].disktype->stretch);
803 udelay(25);
805 DPRINT(("fd_rwsec() before setup DMA \n"));
806 /* Setup DMA - Heavily modified by DAG */
807 save_flags(flags);
808 cliIF();
809 disable_dma(FLOPPY_DMA);
810 set_dma_mode(FLOPPY_DMA, rwflag ? DMA_MODE_WRITE : DMA_MODE_READ);
811 set_dma_addr(FLOPPY_DMA, (long) paddr); /* DAG - changed from Atari specific */
812 #ifdef TRACKBUFFER
813 set_dma_count(FLOPPY_DMA,(!read_track ? 1 : unit[SelectedDrive].disktype->spt)*512);
814 #else
815 set_dma_count(FLOPPY_DMA, 512); /* Block/sector size - going to have to change */
816 #endif
817 SET_IRQ_HANDLER(fd_rwsec_done);
818 /* Turn on dma int */
819 enable_dma(FLOPPY_DMA);
820 /* Now give it something to do */
821 FDC1772_WRITE(FDC1772REG_CMD, (rwflag ? (FDC1772CMD_WRSEC | FDC1772CMDADD_P) :
822 #ifdef TRACKBUFFER
823 (FDC1772CMD_RDSEC | (read_track ? FDC1772CMDADD_M : 0) |
824 /* Hmm - the idea here is to stop the FDC spinning the disc
825 up when we know that we already still have it spinning */
826 (MotorOn?FDC1772CMDADD_H:0))
827 #else
828 FDC1772CMD_RDSEC
829 #endif
832 restore_flags(flags);
833 DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n", flags));
834 /*sti(); *//* DAG - Hmm */
835 /* Hmm - should do something DAG */
836 old_motoron = MotorOn;
837 MotorOn = 1;
838 NeedSeek = 1;
840 /* wait for interrupt */
842 #ifdef TRACKBUFFER
843 if (read_track) {
844 /* If reading a whole track, wait about one disk rotation and
845 * then check if all sectors are read. The FDC will even
846 * search for the first non-existant sector and need 1 sec to
847 * recognise that it isn't present :-(
849 del_timer( &readtrack_timer );
850 readtrack_timer.function = fd_readtrack_check;
851 readtrack_timer.expires = jiffies + HZ/5 + (old_motoron ? 0 : HZ);
852 /* 1 rot. + 5 rot.s if motor was off */
853 DPRINT(("Setting readtrack_timer to %d @ %d\n",readtrack_timer.expires,jiffies));
854 add_timer( &readtrack_timer );
855 MultReadInProgress = 1;
857 #endif
859 /*DPRINT(("fd_rwsec() before START_TIMEOUT \n")); */
860 START_TIMEOUT();
861 /*DPRINT(("fd_rwsec() after START_TIMEOUT \n")); */
865 #ifdef TRACKBUFFER
867 static void fd_readtrack_check( unsigned long dummy )
869 { unsigned long flags, addr;
870 extern unsigned char *fdc1772_dataaddr;
872 DPRINT(("fd_readtrack_check @ %d\n",jiffies));
874 save_flags(flags);
875 cliIF();
877 del_timer( &readtrack_timer );
879 if (!MultReadInProgress) {
880 /* This prevents a race condition that could arise if the
881 * interrupt is triggered while the calling of this timer
882 * callback function takes place. The IRQ function then has
883 * already cleared 'MultReadInProgress' when control flow
884 * gets here.
886 restore_flags(flags);
887 return;
890 /* get the current DMA address */
891 addr=fdc1772_dataaddr; /* DAG - ? */
892 DPRINT(("fd_readtrack_check: addr=%x PhysTrackBuffer=%x\n",addr,PhysTrackBuffer));
894 if (addr >= PhysTrackBuffer + unit[SelectedDrive].disktype->spt*512) {
895 /* already read enough data, force an FDC interrupt to stop
896 * the read operation
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);
904 /* No error until now -- the FDC would have interrupted
905 * otherwise!
907 fd_rwsec_done( 0 );
909 else {
910 /* not yet finished, wait another tenth rotation */
911 restore_flags(flags);
912 DPRINT(("fd_readtrack_check(): not yet finished\n"));
913 readtrack_timer.expires = jiffies + HZ/5/10;
914 add_timer( &readtrack_timer );
918 #endif
920 static void fd_rwsec_done(int status)
922 unsigned int track;
924 DPRINT(("fd_rwsec_done() status=%d @ %d\n", status,jiffies));
926 #ifdef TRACKBUFFER
927 if (read_track && !MultReadInProgress) return;
928 MultReadInProgress = 0;
930 STOP_TIMEOUT();
932 if (read_track)
933 del_timer( &readtrack_timer );
934 #endif
937 /* Correct the track if stretch != 0 */
938 if (unit[SelectedDrive].disktype->stretch) {
939 track = FDC1772_READ(FDC1772REG_TRACK);
940 FDC1772_WRITE(FDC1772REG_TRACK, track <<
941 unit[SelectedDrive].disktype->stretch);
943 if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) {
944 printk("fd%d: is write protected\n", SelectedDrive);
945 goto err_end;
947 if ((status & FDC1772STAT_RECNF)
948 #ifdef TRACKBUFFER
949 /* RECNF is no error after a multiple read when the FDC
950 * searched for a non-existant sector!
952 && !(read_track &&
953 FDC1772_READ(FDC1772REG_SECTOR) > unit[SelectedDrive].disktype->spt)
954 #endif
956 if (Probing) {
957 if (unit[SelectedDrive].disktype > disk_type) {
958 /* try another disk type */
959 unit[SelectedDrive].disktype--;
960 floppy_sizes[SelectedDrive]
961 = unit[SelectedDrive].disktype->blocks >> 1;
962 } else
963 Probing = 0;
964 } else {
965 /* record not found, but not probing. Maybe stretch wrong ? Restart probing */
966 if (unit[SelectedDrive].autoprobe) {
967 unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1;
968 floppy_sizes[SelectedDrive]
969 = unit[SelectedDrive].disktype->blocks >> 1;
970 Probing = 1;
973 if (Probing) {
974 setup_req_params(SelectedDrive);
975 #ifdef TRACKBUFFER
976 BufferDrive = -1;
977 #endif
978 do_fd_action(SelectedDrive);
979 return;
981 printk("fd%d: sector %d not found (side %d, track %d)\n",
982 SelectedDrive, FDC1772_READ(FDC1772REG_SECTOR), ReqSide, ReqTrack);
983 goto err_end;
985 if (status & FDC1772STAT_CRC) {
986 printk("fd%d: CRC error (side %d, track %d, sector %d)\n",
987 SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
988 goto err_end;
990 if (status & FDC1772STAT_LOST) {
991 printk("fd%d: lost data (side %d, track %d, sector %d)\n",
992 SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
993 goto err_end;
995 Probing = 0;
997 if (ReqCmd == READ) {
998 #ifdef TRACKBUFFER
999 if (!read_track)
1001 /*cache_clear (PhysDMABuffer, 512);*/
1002 copy_buffer (DMABuffer, ReqData);
1004 else
1006 /*cache_clear (PhysTrackBuffer, MAX_SECTORS * 512);*/
1007 BufferDrive = SelectedDrive;
1008 BufferSide = ReqSide;
1009 BufferTrack = ReqTrack;
1010 copy_buffer (SECTOR_BUFFER (ReqSector), ReqData);
1012 #else
1013 /*cache_clear( PhysDMABuffer, 512 ); */
1014 copy_buffer(DMABuffer, ReqData);
1015 #endif
1017 if (++ReqCnt < CURRENT->current_nr_sectors) {
1018 /* read next sector */
1019 setup_req_params(SelectedDrive);
1020 do_fd_action(SelectedDrive);
1021 } else {
1022 /* all sectors finished */
1023 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
1024 CURRENT->sector += CURRENT->current_nr_sectors;
1025 end_request(1);
1026 redo_fd_request();
1028 return;
1030 err_end:
1031 #ifdef TRACKBUFFER
1032 BufferDrive = -1;
1033 #endif
1035 fd_error();
1039 static void fd_times_out(unsigned long dummy)
1041 SET_IRQ_HANDLER(NULL);
1042 /* If the timeout occured while the readtrack_check timer was
1043 * active, we need to cancel it, else bad things will happen */
1044 del_timer( &readtrack_timer );
1045 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1046 udelay(25);
1048 printk("floppy timeout\n");
1049 STOP_TIMEOUT(); /* hmm - should we do this ? */
1050 fd_error();
1054 /* The (noop) seek operation here is needed to make the WP bit in the
1055 * FDC1772 status register accessible for check_change. If the last disk
1056 * operation would have been a RDSEC, this bit would always read as 0
1057 * no matter what :-( To save time, the seek goes to the track we're
1058 * already on.
1061 static void finish_fdc(void)
1063 /* DAG - just try without this dummy seek! */
1064 finish_fdc_done(0);
1065 return;
1067 if (!NeedSeek) {
1068 finish_fdc_done(0);
1069 } else {
1070 DPRINT(("finish_fdc: dummy seek started\n"));
1071 FDC1772_WRITE(FDC1772REG_DATA, unit[SelectedDrive].track);
1072 SET_IRQ_HANDLER(finish_fdc_done);
1073 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1074 MotorOn = 1;
1075 START_TIMEOUT();
1076 /* we must wait for the IRQ here, because the ST-DMA is
1077 * released immediatly afterwards and the interrupt may be
1078 * delivered to the wrong driver.
1084 static void finish_fdc_done(int dummy)
1086 unsigned long flags;
1088 DPRINT(("finish_fdc_done entered\n"));
1089 STOP_TIMEOUT();
1090 NeedSeek = 0;
1092 if ((timer_active & (1 << FLOPPY_TIMER)) &&
1093 timer_table[FLOPPY_TIMER].expires < jiffies + 5)
1094 /* If the check for a disk change is done too early after this
1095 * last seek command, the WP bit still reads wrong :-((
1097 timer_table[FLOPPY_TIMER].expires = jiffies + 5;
1098 else {
1099 /* START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1101 del_timer(&motor_off_timer);
1102 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1104 save_flags(flags);
1105 cli();
1106 /* stdma_release(); - not sure if I should do something DAG */
1107 fdc_busy = 0;
1108 wake_up(&fdc_wait);
1109 restore_flags(flags);
1111 DPRINT(("finish_fdc() finished\n"));
1115 /* Prevent "aliased" accesses. */
1116 static fd_ref[4] =
1117 {0, 0, 0, 0};
1118 static fd_device[4] =
1119 {0, 0, 0, 0};
1122 * Current device number. Taken either from the block header or from the
1123 * format request descriptor.
1125 #define CURRENT_DEVICE (CURRENT->rq_dev)
1127 /* Current error count. */
1128 #define CURRENT_ERRORS (CURRENT->errors)
1131 /* dummy for blk.h */
1132 static void floppy_off(unsigned int nr)
1137 /* On the old arcs write protect depends on the particular model
1138 of machine. On the A310, R140, and A440 there is a disc changed
1139 detect, however on the A4x0/1 range there is not. There
1140 is nothing to tell you which machine your on.
1141 At the moment I'm just marking changed always. I've
1142 left the Atari's 'change on write protect change' code in this
1143 part (but nothing sets it).
1144 RiscOS apparently checks the disc serial number etc. to detect changes
1145 - but if it sees a disc change line go high (?) it flips to using
1146 it. Well maybe I'll add that in the future (!?)
1148 static int check_floppy_change(dev_t dev)
1150 unsigned int drive = (dev & 0x03);
1152 if (MAJOR(dev) != MAJOR_NR) {
1153 printk("floppy_changed: not a floppy\n");
1154 return 0;
1156 if (test_bit(drive, &fake_change)) {
1157 /* simulated change (e.g. after formatting) */
1158 return 1;
1160 if (test_bit(drive, &changed_floppies)) {
1161 /* surely changed (the WP signal changed at least once) */
1162 return 1;
1164 if (unit[drive].wpstat) {
1165 /* WP is on -> could be changed: to be sure, buffers should be
1166 * invalidated...
1168 return 1;
1170 return 1; /* DAG - was 0 */
1173 static int floppy_revalidate(dev_t dev)
1175 int drive = dev & 3;
1177 if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change)
1178 || unit[drive].disktype == 0) {
1179 #ifdef TRACKBUFFER
1180 BufferDrive = -1;
1181 #endif
1182 clear_bit(drive, &fake_change);
1183 clear_bit(drive, &changed_floppies);
1184 unit[drive].disktype = 0;
1186 return 0;
1189 static __inline__ void copy_buffer(void *from, void *to)
1191 ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
1192 int cnt;
1194 for (cnt = 512 / 4; cnt; cnt--)
1195 *p2++ = *p1++;
1199 /* This sets up the global variables describing the current request. */
1201 static void setup_req_params(int drive)
1203 int block = ReqBlock + ReqCnt;
1205 ReqTrack = block / unit[drive].disktype->spt;
1206 ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1;
1207 ReqSide = ReqTrack & 1;
1208 ReqTrack >>= 1;
1209 ReqData = ReqBuffer + 512 * ReqCnt;
1211 #ifdef TRACKBUFFER
1212 read_track = (ReqCmd == READ && CURRENT_ERRORS == 0);
1213 #endif
1215 DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n", ReqSide,
1216 ReqTrack, ReqSector, (unsigned long) ReqData));
1220 static void redo_fd_request(void)
1222 int device, drive, type;
1223 struct archy_floppy_struct *floppy;
1225 DPRINT(("redo_fd_request: CURRENT=%08lx CURRENT->rq_dev=%04x CURRENT->sector=%ld\n",
1226 (unsigned long) CURRENT, CURRENT ? CURRENT->rq_dev : 0,
1227 CURRENT ? CURRENT->sector : 0));
1229 if (CURRENT && CURRENT->rq_status == RQ_INACTIVE)
1230 goto the_end;
1232 repeat:
1234 if (!CURRENT)
1235 goto the_end;
1237 if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
1238 panic(DEVICE_NAME ": request list destroyed");
1240 if (CURRENT->bh) {
1241 if (!buffer_locked(CURRENT->bh))
1242 panic(DEVICE_NAME ": block not locked");
1244 device = MINOR(CURRENT_DEVICE);
1245 drive = device & 3;
1246 type = device >> 2;
1247 floppy = &unit[drive];
1249 if (!floppy->connected) {
1250 /* drive not connected */
1251 printk("Unknown Device: fd%d\n", drive);
1252 end_request(0);
1253 goto repeat;
1255 if (type == 0) {
1256 if (!floppy->disktype) {
1257 Probing = 1;
1258 floppy->disktype = disk_type + NUM_DISK_TYPES - 1;
1259 floppy_sizes[drive] = floppy->disktype->blocks >> 1;
1260 floppy->autoprobe = 1;
1262 } else {
1263 /* user supplied disk type */
1264 --type;
1265 if (type >= NUM_DISK_TYPES) {
1266 printk("fd%d: invalid disk format", drive);
1267 end_request(0);
1268 goto repeat;
1270 floppy->disktype = &disk_type[type];
1271 floppy_sizes[drive] = disk_type[type].blocks >> 1;
1272 floppy->autoprobe = 0;
1275 if (CURRENT->sector + 1 > floppy->disktype->blocks) {
1276 end_request(0);
1277 goto repeat;
1279 /* stop deselect timer */
1280 del_timer(&motor_off_timer);
1282 ReqCnt = 0;
1283 ReqCmd = CURRENT->cmd;
1284 ReqBlock = CURRENT->sector;
1285 ReqBuffer = CURRENT->buffer;
1286 setup_req_params(drive);
1287 do_fd_action(drive);
1289 return;
1291 the_end:
1292 finish_fdc();
1295 static void fd1772_checkint(void)
1297 extern int fdc1772_bytestogo;
1299 /*printk("fd1772_checkint %d\n",fdc1772_fdc_int_done);*/
1300 if (fdc1772_fdc_int_done)
1301 floppy_irqconsequencehandler();
1302 if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0);
1303 if (fdc_busy) {
1304 queue_task(&fd1772_tq,&tq_immediate);
1305 mark_bh(IMMEDIATE_BH);
1309 void do_fd_request(void)
1311 unsigned long flags;
1313 DPRINT(("do_fd_request for pid %d\n", current->pid));
1314 if (fdc_busy) return;
1315 save_flags(flags);
1316 cli();
1317 while (fdc_busy)
1318 sleep_on(&fdc_wait);
1319 fdc_busy = 1;
1320 ENABLE_IRQ();
1321 restore_flags(flags);
1323 fdc1772_fdc_int_done = 0;
1325 redo_fd_request();
1327 queue_task(&fd1772_tq,&tq_immediate);
1328 mark_bh(IMMEDIATE_BH);
1332 static int invalidate_drive(int rdev)
1334 /* invalidate the buffer track to force a reread */
1335 #ifdef TRACKBUFFER
1336 BufferDrive = -1;
1337 #endif
1339 set_bit(rdev & 3, &fake_change);
1340 check_disk_change(rdev);
1341 return 0;
1344 static int fd_ioctl(struct inode *inode, struct file *filp,
1345 unsigned int cmd, unsigned long param)
1347 #define IOCTL_MODE_BIT 8
1348 #define OPEN_WRITE_BIT 16
1349 #define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT))
1351 int drive, device;
1353 device = inode->i_rdev;
1354 switch (cmd) {
1355 RO_IOCTLS(inode->i_rdev, param);
1357 drive = MINOR(device);
1358 if (!IOCTL_ALLOWED)
1359 return -EPERM;
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; 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 /* Allow ioctls if we have write-permissions even if read-only open */
1542 if (filp->f_mode & 2 || permission(inode, 2) == 0)
1543 filp->f_mode |= IOCTL_MODE_BIT;
1544 if (filp->f_mode & 2)
1545 filp->f_mode |= OPEN_WRITE_BIT;
1547 if (filp->f_flags & O_NDELAY)
1548 return 0;
1550 if (filp->f_mode & 3) {
1551 check_disk_change(inode->i_rdev);
1552 if (filp->f_mode & 2) {
1553 if (unit[drive].wpstat) {
1554 floppy_release(inode, filp);
1555 return -EROFS;
1559 return 0;
1563 static void floppy_release(struct inode *inode, struct file *filp)
1565 int drive;
1567 drive = inode->i_rdev & 3;
1569 if (!filp || (filp->f_mode & (2 | OPEN_WRITE_BIT)))
1570 /* if the file is mounted OR (writable now AND writable at open
1571 time) Linus: Does this cover all cases? */
1572 block_fsync(inode, filp);
1574 if (fd_ref[drive] < 0)
1575 fd_ref[drive] = 0;
1576 else if (!fd_ref[drive]--) {
1577 printk("floppy_release with fd_ref == 0");
1578 fd_ref[drive] = 0;
1582 static struct file_operations floppy_fops =
1584 NULL, /* lseek - default */
1585 block_read, /* read - general block-dev read */
1586 block_write, /* write - general block-dev write */
1587 NULL, /* readdir - bad */
1588 NULL, /* select */
1589 fd_ioctl, /* ioctl */
1590 NULL, /* mmap */
1591 floppy_open, /* open */
1592 NULL, /* flush */
1593 floppy_release, /* release */
1594 block_fsync, /* fsync */
1595 NULL, /* fasync */
1596 check_floppy_change, /* media_change */
1597 floppy_revalidate, /* revalidate */
1601 int floppy_init(void)
1603 int i;
1605 if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {
1606 printk("Unable to get major %d for floppy\n", MAJOR_NR);
1607 return 1;
1610 if (request_dma(FLOPPY_DMA, "fd1772")) {
1611 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA);
1612 return 1;
1615 if (request_dma(FIQ_FD1772, "fd1772 end")) {
1616 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772);
1617 free_dma(FLOPPY_DMA);
1618 return 1;
1620 enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */
1622 /* initialize variables */
1623 SelectedDrive = -1;
1624 #ifdef TRACKBUFFER
1625 BufferDrive = -1;
1626 #endif
1628 /* initialize check_change timer */
1629 timer_table[FLOPPY_TIMER].fn = check_change;
1630 timer_active &= ~(1 << FLOPPY_TIMER);
1633 #ifdef TRACKBUFFER
1634 DMABuffer = (char *)kmalloc((MAX_SECTORS+1)*512,GFP_KERNEL); /* Atari uses 512 - I want to eventually cope with 1K sectors */
1635 TrackBuffer = DMABuffer + 512;
1636 #else
1637 /* Allocate memory for the DMAbuffer - on the Atari this takes it
1638 out of some special memory... */
1639 DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */
1640 #endif
1641 #ifdef TRACKBUFFER
1642 BufferDrive = BufferSide = BufferTrack = -1;
1643 #endif
1645 for (i = 0; i < FD_MAX_UNITS; i++) {
1646 unit[i].track = -1;
1649 for (i = 0; i < 256; i++)
1650 if ((i >> 2) > 0 && (i >> 2) <= NUM_DISK_TYPES)
1651 floppy_sizes[i] = disk_type[(i >> 2) - 1].blocks >> 1;
1652 else
1653 floppy_sizes[i] = MAX_DISK_SIZE;
1655 blk_size[MAJOR_NR] = floppy_sizes;
1656 blksize_size[MAJOR_NR] = floppy_blocksizes;
1657 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1659 config_types();
1661 return 0;
1664 /* Just a dummy at the moment */
1665 void floppy_setup(char *str, int *ints)
1669 void floppy_eject(void) {