[TG3]: Add tagged status support.
[linux-2.6/verdex.git] / drivers / acorn / block / fd1772.c
blob3cd2e968e96c31dd24477343470834091f29ee5d
1 /*
2 * linux/kernel/arch/arm/drivers/block/fd1772.c
3 * Based on ataflop.c in the m68k Linux
4 * Copyright (C) 1993 Greg Harp
5 * Atari Support by Bjoern Brauel, Roman Hodek
6 * Archimedes Support by Dave Gilbert (linux@treblig.org)
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 sequence'
103 * when we read the track if we know the motor is on; didn't
104 * help - perhaps we have to do it in stepping as well.
105 * Nope. Still doesn't help.
106 * Hmm - what seems to be happening is that fd_readtrack_check
107 * is never getting called. Its job is to terminate the read
108 * just after we think we should have got the data; otherwise
109 * the fdc takes 1 second to timeout; which is what's happening
110 * Now I can see 'readtrack_timer' being set (which should do the
111 * call); but it never seems to be called - hmm!
112 * OK - I've moved the check to my tq_immediate code -
113 * and it WORKS! 13.95K/second at 19% CPU.
114 * I wish I knew why that timer didn't work.....
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
122 * DAG 1/09/00 - Dusted off for 2.4.0-test7
123 * MAX_SECTORS was name clashing so it is now FD1772_...
124 * Minor parameter, name layouts for 2.4.x differences
127 #include <linux/sched.h>
128 #include <linux/fs.h>
129 #include <linux/fcntl.h>
130 #include <linux/slab.h>
131 #include <linux/kernel.h>
132 #include <linux/interrupt.h>
133 #include <linux/timer.h>
134 #include <linux/workqueue.h>
135 #include <linux/fd.h>
136 #include <linux/fd1772.h>
137 #include <linux/errno.h>
138 #include <linux/types.h>
139 #include <linux/delay.h>
140 #include <linux/mm.h>
141 #include <linux/bitops.h>
143 #include <asm/arch/oldlatches.h>
144 #include <asm/dma.h>
145 #include <asm/hardware.h>
146 #include <asm/hardware/ioc.h>
147 #include <asm/io.h>
148 #include <asm/irq.h>
149 #include <asm/mach-types.h>
150 #include <asm/pgtable.h>
151 #include <asm/system.h>
152 #include <asm/uaccess.h>
155 /* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with
156 * little additional rework in this file). But I'm not yet sure if
157 * some other code depends on the number of floppies... (It is defined
158 * in a public header!)
160 #if 0
161 #undef FD_MAX_UNITS
162 #define FD_MAX_UNITS 2
163 #endif
165 /* Ditto worries for Arc - DAG */
166 #define FD_MAX_UNITS 4
167 #define TRACKBUFFER 0
168 /*#define DEBUG*/
170 #ifdef DEBUG
171 #define DPRINT(a) printk a
172 #else
173 #define DPRINT(a)
174 #endif
176 static struct request_queue *floppy_queue;
178 #define MAJOR_NR FLOPPY_MAJOR
179 #define FLOPPY_DMA 0
180 #define DEVICE_NAME "floppy"
181 #define QUEUE (floppy_queue)
182 #define CURRENT elv_next_request(floppy_queue)
184 /* Disk types: DD */
185 static struct archy_disk_type {
186 const char *name;
187 unsigned spt; /* sectors per track */
188 unsigned blocks; /* total number of blocks */
189 unsigned stretch; /* track doubling ? */
190 } disk_type[] = {
192 { "d360", 9, 720, 0 }, /* 360kB diskette */
193 { "D360", 9, 720, 1 }, /* 360kb in 720kb drive */
194 { "D720", 9, 1440, 0 }, /* 720kb diskette (DD) */
195 /*{ "D820", 10,1640, 0}, *//* DD disk with 82 tracks/10 sectors
196 - DAG - can't see how type detect can distinguish this
197 from 720K until it reads block 4 by which time its too late! */
200 #define NUM_DISK_TYPES (sizeof(disk_type)/sizeof(*disk_type))
203 * Maximum disk size (in kilobytes). This default is used whenever the
204 * current disk size is unknown.
206 #define MAX_DISK_SIZE 720
208 static struct gendisk *disks[FD_MAX_UNIT];
210 /* current info on each unit */
211 static struct archy_floppy_struct {
212 int connected; /* !=0 : drive is connected */
213 int autoprobe; /* !=0 : do autoprobe */
215 struct archy_disk_type *disktype; /* current type of disk */
217 int track; /* current head position or -1
218 * if unknown */
219 unsigned int steprate; /* steprate setting */
220 unsigned int wpstat; /* current state of WP signal
221 * (for disk change detection) */
222 } unit[FD_MAX_UNITS];
224 /* DAG: On Arc we spin on a flag being cleared by fdc1772_comendhandler which
225 is an assembler routine */
226 extern void fdc1772_comendhandler(void); /* Actually doens't have these parameters - see fd1772.S */
227 extern volatile int fdc1772_comendstatus;
228 extern volatile int fdc1772_fdc_int_done;
230 #define FDC1772BASE ((0x210000>>2)|0x80000000)
232 #define FDC1772_READ(reg) inb(FDC1772BASE+(reg/2))
234 /* DAG: You wouldn't be silly to ask why FDC1772_WRITE is a function rather
235 than the #def below - well simple - the #def won't compile - and I
236 don't understand why (__outwc not defined) */
237 /* NOTE: Reg is 0,2,4,6 as opposed to 0,1,2,3 or 0,4,8,12 to keep compatibility
238 with the ST version of fd1772.h */
239 /*#define FDC1772_WRITE(reg,val) outw(val,(reg+FDC1772BASE)); */
240 void FDC1772_WRITE(int reg, unsigned char val)
242 if (reg == FDC1772REG_CMD) {
243 DPRINT(("FDC1772_WRITE new command 0x%x @ %d\n", val,jiffies));
244 if (fdc1772_fdc_int_done) {
245 DPRINT(("FDC1772_WRITE: Hmm fdc1772_fdc_int_done true - resetting\n"));
246 fdc1772_fdc_int_done = 0;
249 outb(val, (reg / 2) + FDC1772BASE);
252 #define FD1772_MAX_SECTORS 22
254 unsigned char *DMABuffer; /* buffer for writes */
255 /*static unsigned long PhysDMABuffer; *//* physical address */
256 /* DAG: On Arc we just go straight for the DMA buffer */
257 #define PhysDMABuffer DMABuffer
259 #ifdef TRACKBUFFER
260 unsigned char *TrackBuffer; /* buffer for reads */
261 #define PhysTrackBuffer TrackBuffer /* physical address */
262 static int BufferDrive, BufferSide, BufferTrack;
263 static int read_track; /* non-zero if we are reading whole tracks */
265 #define SECTOR_BUFFER(sec) (TrackBuffer + ((sec)-1)*512)
266 #define IS_BUFFERED(drive,side,track) \
267 (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track))
268 #endif
271 * These are global variables, as that's the easiest way to give
272 * information to interrupts. They are the data used for the current
273 * request.
275 static int SelectedDrive = 0;
276 static int ReqCmd, ReqBlock;
277 static int ReqSide, ReqTrack, ReqSector, ReqCnt;
278 static int HeadSettleFlag = 0;
279 static unsigned char *ReqData, *ReqBuffer;
280 static int MotorOn = 0, MotorOffTrys;
282 /* Synchronization of FDC1772 access. */
283 static volatile int fdc_busy = 0;
284 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
287 /* long req'd for set_bit --RR */
288 static unsigned long changed_floppies = 0xff, fake_change = 0;
289 #define CHECK_CHANGE_DELAY HZ/2
291 /* DAG - increased to 30*HZ - not sure if this is the correct thing to do */
292 #define FD_MOTOR_OFF_DELAY (10*HZ)
293 #define FD_MOTOR_OFF_MAXTRY (10*20)
295 #define FLOPPY_TIMEOUT (6*HZ)
296 #define RECALIBRATE_ERRORS 4 /* After this many errors the drive
297 * will be recalibrated. */
298 #define MAX_ERRORS 8 /* After this many errors the driver
299 * will give up. */
301 #define START_MOTOR_OFF_TIMER(delay) \
302 do { \
303 motor_off_timer.expires = jiffies + (delay); \
304 add_timer( &motor_off_timer ); \
305 MotorOffTrys = 0; \
306 } while(0)
308 #define START_CHECK_CHANGE_TIMER(delay) \
309 do { \
310 mod_timer(&fd_timer, jiffies + (delay)); \
311 } while(0)
313 #define START_TIMEOUT() \
314 do { \
315 mod_timer(&timeout_timer, jiffies+FLOPPY_TIMEOUT); \
316 } while(0)
318 #define STOP_TIMEOUT() \
319 do { \
320 del_timer( &timeout_timer ); \
321 } while(0)
323 #define ENABLE_IRQ() enable_irq(FIQ_FD1772+64);
325 #define DISABLE_IRQ() disable_irq(FIQ_FD1772+64);
327 static void fd1772_checkint(void);
329 DECLARE_WORK(fd1772_tq, (void *)fd1772_checkint, NULL);
331 * The driver is trying to determine the correct media format
332 * while Probing is set. fd_rwsec_done() clears it after a
333 * successful access.
335 static int Probing = 0;
337 /* This flag is set when a dummy seek is necessary to make the WP
338 * status bit accessible.
340 static int NeedSeek = 0;
343 /***************************** Prototypes *****************************/
345 static void fd_select_side(int side);
346 static void fd_select_drive(int drive);
347 static void fd_deselect(void);
348 static void fd_motor_off_timer(unsigned long dummy);
349 static void check_change(unsigned long dummy);
350 static void floppy_irqconsequencehandler(void);
351 static void fd_error(void);
352 static void do_fd_action(int drive);
353 static void fd_calibrate(void);
354 static void fd_calibrate_done(int status);
355 static void fd_seek(void);
356 static void fd_seek_done(int status);
357 static void fd_rwsec(void);
358 #ifdef TRACKBUFFER
359 static void fd_readtrack_check( unsigned long dummy );
360 #endif
361 static void fd_rwsec_done(int status);
362 static void fd_times_out(unsigned long dummy);
363 static void finish_fdc(void);
364 static void finish_fdc_done(int dummy);
365 static void floppy_off(unsigned int nr);
366 static void setup_req_params(int drive);
367 static void redo_fd_request(void);
368 static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int
369 cmd, unsigned long param);
370 static void fd_probe(int drive);
371 static int fd_test_drive_present(int drive);
372 static void config_types(void);
373 static int floppy_open(struct inode *inode, struct file *filp);
374 static int floppy_release(struct inode *inode, struct file *filp);
375 static void do_fd_request(request_queue_t *);
377 /************************* End of Prototypes **************************/
379 static struct timer_list motor_off_timer =
380 TIMER_INITIALIZER(fd_motor_off_timer, 0, 0);
382 #ifdef TRACKBUFFER
383 static struct timer_list readtrack_timer =
384 TIMER_INITIALIZER(fd_readtrack_check, 0, 0);
385 #endif
387 static struct timer_list timeout_timer =
388 TIMER_INITIALIZER(fd_times_out, 0, 0);
390 static struct timer_list fd_timer =
391 TIMER_INITIALIZER(check_change, 0, 0);
393 /* DAG: Haven't got a clue what this is? */
394 int stdma_islocked(void)
396 return 0;
399 /* Select the side to use. */
401 static void fd_select_side(int side)
403 oldlatch_aupdate(LATCHA_SIDESEL, side ? 0 : LATCHA_SIDESEL);
407 /* Select a drive, update the FDC1772's track register
410 static void fd_select_drive(int drive)
412 #ifdef DEBUG
413 printk("fd_select_drive:%d\n", drive);
414 #endif
415 /* Hmm - nowhere do we seem to turn the motor on - I'm going to do it here! */
416 oldlatch_aupdate(LATCHA_MOTOR | LATCHA_INUSE, 0);
418 if (drive == SelectedDrive)
419 return;
421 oldlatch_aupdate(LATCHA_FDSELALL, 0xf - (1 << drive));
423 /* restore track register to saved value */
424 FDC1772_WRITE(FDC1772REG_TRACK, unit[drive].track);
425 udelay(25);
427 SelectedDrive = drive;
431 /* Deselect both drives. */
433 static void fd_deselect(void)
435 unsigned long flags;
437 DPRINT(("fd_deselect\n"));
439 oldlatch_aupdate(LATCHA_FDSELALL | LATCHA_MOTOR | LATCHA_INUSE, 0xf | LATCHA_MOTOR | LATCHA_INUSE);
441 SelectedDrive = -1;
445 /* This timer function deselects the drives when the FDC1772 switched the
446 * motor off. The deselection cannot happen earlier because the FDC1772
447 * counts the index signals, which arrive only if one drive is selected.
450 static void fd_motor_off_timer(unsigned long dummy)
452 unsigned long flags;
453 unsigned char status;
454 int delay;
456 del_timer(&motor_off_timer);
458 if (SelectedDrive < 0)
459 /* no drive selected, needn't deselect anyone */
460 return;
462 save_flags(flags);
463 cli();
465 if (fdc_busy) /* was stdma_islocked */
466 goto retry;
468 status = FDC1772_READ(FDC1772REG_STATUS);
470 if (!(status & 0x80)) {
472 * motor already turned off by FDC1772 -> deselect drives
473 * In actual fact its this deselection which turns the motor
474 * off on the Arc, since the motor control is actually on
475 * Latch A
477 DPRINT(("fdc1772: deselecting in fd_motor_off_timer\n"));
478 fd_deselect();
479 MotorOn = 0;
480 restore_flags(flags);
481 return;
483 /* not yet off, try again */
485 retry:
486 restore_flags(flags);
487 /* Test again later; if tested too often, it seems there is no disk
488 * in the drive and the FDC1772 will leave the motor on forever (or,
489 * at least until a disk is inserted). So we'll test only twice
490 * per second from then on...
492 delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ?
493 (++MotorOffTrys, HZ / 20) : HZ / 2;
494 START_MOTOR_OFF_TIMER(delay);
498 /* This function is repeatedly called to detect disk changes (as good
499 * as possible) and keep track of the current state of the write protection.
502 static void check_change(unsigned long dummy)
504 static int drive = 0;
506 unsigned long flags;
507 int stat;
509 if (fdc_busy)
510 return; /* Don't start poking about if the fdc is busy */
512 return; /* let's just forget it for the mo DAG */
514 if (++drive > 1 || !unit[drive].connected)
515 drive = 0;
517 save_flags(flags);
518 cli();
520 if (!stdma_islocked()) {
521 stat = !!(FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_WPROT);
523 /* The idea here is that if the write protect line has changed then
524 the disc must have changed */
525 if (stat != unit[drive].wpstat) {
526 DPRINT(("wpstat[%d] = %d\n", drive, stat));
527 unit[drive].wpstat = stat;
528 set_bit(drive, &changed_floppies);
531 restore_flags(flags);
533 START_CHECK_CHANGE_TIMER(CHECK_CHANGE_DELAY);
537 /* Handling of the Head Settling Flag: This flag should be set after each
538 * seek operation, because we don't use seeks with verify.
541 static inline void set_head_settle_flag(void)
543 HeadSettleFlag = FDC1772CMDADD_E;
546 static inline int get_head_settle_flag(void)
548 int tmp = HeadSettleFlag;
549 HeadSettleFlag = 0;
550 return (tmp);
556 /* General Interrupt Handling */
558 static inline void copy_buffer(void *from, void *to)
560 ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
561 int cnt;
563 for (cnt = 512 / 4; cnt; cnt--)
564 *p2++ = *p1++;
567 static void (*FloppyIRQHandler) (int status) = NULL;
569 static void floppy_irqconsequencehandler(void)
571 unsigned char status;
572 void (*handler) (int);
574 fdc1772_fdc_int_done = 0;
576 handler = FloppyIRQHandler;
577 FloppyIRQHandler = NULL;
579 if (handler) {
580 nop();
581 status = (unsigned char) fdc1772_comendstatus;
582 DPRINT(("FDC1772 irq, status = %02x handler = %08lx\n", (unsigned int) status, (unsigned long) handler));
583 handler(status);
584 } else {
585 DPRINT(("FDC1772 irq, no handler status=%02x\n", fdc1772_comendstatus));
587 DPRINT(("FDC1772 irq: end of floppy_irq\n"));
591 /* Error handling: If some error happened, retry some times, then
592 * recalibrate, then try again, and fail after MAX_ERRORS.
595 static void fd_error(void)
597 printk("FDC1772: fd_error\n");
598 /*panic("fd1772: fd_error"); *//* DAG tmp */
599 if (!CURRENT)
600 return;
601 CURRENT->errors++;
602 if (CURRENT->errors >= MAX_ERRORS) {
603 printk("fd%d: too many errors.\n", SelectedDrive);
604 end_request(CURRENT, 0);
605 } else if (CURRENT->errors == RECALIBRATE_ERRORS) {
606 printk("fd%d: recalibrating\n", SelectedDrive);
607 if (SelectedDrive != -1)
608 unit[SelectedDrive].track = -1;
610 redo_fd_request();
615 #define SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0)
618 /* do_fd_action() is the general procedure for a fd request: All
619 * required parameter settings (drive select, side select, track
620 * position) are checked and set if needed. For each of these
621 * parameters and the actual reading or writing exist two functions:
622 * one that starts the setting (or skips it if possible) and one
623 * callback for the "done" interrupt. Each done func calls the next
624 * set function to propagate the request down to fd_rwsec_done().
627 static void do_fd_action(int drive)
629 struct request *req;
630 DPRINT(("do_fd_action unit[drive].track=%d\n", unit[drive].track));
632 #ifdef TRACKBUFFER
633 repeat:
635 if (IS_BUFFERED( drive, ReqSide, ReqTrack )) {
636 req = CURRENT;
637 if (ReqCmd == READ) {
638 copy_buffer( SECTOR_BUFFER(ReqSector), ReqData );
639 if (++ReqCnt < req->current_nr_sectors) {
640 /* read next sector */
641 setup_req_params( drive );
642 goto repeat;
643 } else {
644 /* all sectors finished */
645 req->nr_sectors -= req->current_nr_sectors;
646 req->sector += req->current_nr_sectors;
647 end_request(req, 1);
648 redo_fd_request();
649 return;
651 } else {
652 /* cmd == WRITE, pay attention to track buffer
653 * consistency! */
654 copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) );
657 #endif
659 if (SelectedDrive != drive) {
660 /*unit[drive].track = -1; DAG */
661 fd_select_drive(drive);
665 if (unit[drive].track == -1)
666 fd_calibrate();
667 else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch)
668 fd_seek();
669 else
670 fd_rwsec();
674 /* Seek to track 0 if the current track is unknown */
676 static void fd_calibrate(void)
678 DPRINT(("fd_calibrate\n"));
679 if (unit[SelectedDrive].track >= 0) {
680 fd_calibrate_done(0);
681 return;
683 DPRINT(("fd_calibrate (after track compare)\n"));
684 SET_IRQ_HANDLER(fd_calibrate_done);
685 /* we can't verify, since the speed may be incorrect */
686 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate);
688 NeedSeek = 1;
689 MotorOn = 1;
690 START_TIMEOUT();
691 /* wait for IRQ */
695 static void fd_calibrate_done(int status)
697 DPRINT(("fd_calibrate_done()\n"));
698 STOP_TIMEOUT();
700 /* set the correct speed now */
701 if (status & FDC1772STAT_RECNF) {
702 printk("fd%d: restore failed\n", SelectedDrive);
703 fd_error();
704 } else {
705 unit[SelectedDrive].track = 0;
706 fd_seek();
711 /* Seek the drive to the requested track. The drive must have been
712 * calibrated at some point before this.
715 static void fd_seek(void)
717 unsigned long flags;
718 DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n", ReqTrack,
719 unit[SelectedDrive].track));
720 if (unit[SelectedDrive].track == ReqTrack <<
721 unit[SelectedDrive].disktype->stretch) {
722 fd_seek_done(0);
723 return;
725 FDC1772_WRITE(FDC1772REG_DATA, ReqTrack <<
726 unit[SelectedDrive].disktype->stretch);
727 udelay(25);
728 save_flags(flags);
729 clf();
730 SET_IRQ_HANDLER(fd_seek_done);
731 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate |
732 /* DAG */
733 (MotorOn?FDC1772CMDADD_H:0));
735 restore_flags(flags);
736 MotorOn = 1;
737 set_head_settle_flag();
738 START_TIMEOUT();
739 /* wait for IRQ */
743 static void fd_seek_done(int status)
745 DPRINT(("fd_seek_done()\n"));
746 STOP_TIMEOUT();
748 /* set the correct speed */
749 if (status & FDC1772STAT_RECNF) {
750 printk("fd%d: seek error (to track %d)\n",
751 SelectedDrive, ReqTrack);
752 /* we don't know exactly which track we are on now! */
753 unit[SelectedDrive].track = -1;
754 fd_error();
755 } else {
756 unit[SelectedDrive].track = ReqTrack <<
757 unit[SelectedDrive].disktype->stretch;
758 NeedSeek = 0;
759 fd_rwsec();
764 /* This does the actual reading/writing after positioning the head
765 * over the correct track.
768 #ifdef TRACKBUFFER
769 static int MultReadInProgress = 0;
770 #endif
773 static void fd_rwsec(void)
775 unsigned long paddr, flags;
776 unsigned int rwflag, old_motoron;
777 unsigned int track;
779 DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n", ReqSector, ReqCmd == WRITE ? 'w' : 'r'));
780 if (ReqCmd == WRITE) {
781 /*cache_push( (unsigned long)ReqData, 512 ); */
782 paddr = (unsigned long) ReqData;
783 rwflag = 0x100;
784 } else {
785 paddr = (unsigned long) PhysDMABuffer;
786 #ifdef TRACKBUFFER
787 if (read_track)
788 paddr = (unsigned long)PhysTrackBuffer;
789 #endif
790 rwflag = 0;
793 DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n", rwflag,
794 ReqSector, FDC1772_READ(FDC1772REG_TRACK)));
795 fd_select_side(ReqSide);
797 /*DPRINT(("fd_rwsec() before start sector \n")); */
798 /* Start sector of this operation */
799 #ifdef TRACKBUFFER
800 FDC1772_WRITE( FDC1772REG_SECTOR, !read_track ? ReqSector : 1 );
801 #else
802 FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector );
803 #endif
805 /* Cheat for track if stretch != 0 */
806 if (unit[SelectedDrive].disktype->stretch) {
807 track = FDC1772_READ(FDC1772REG_TRACK);
808 FDC1772_WRITE(FDC1772REG_TRACK, track >>
809 unit[SelectedDrive].disktype->stretch);
811 udelay(25);
813 DPRINT(("fd_rwsec() before setup DMA \n"));
814 /* Setup DMA - Heavily modified by DAG */
815 save_flags(flags);
816 clf();
817 disable_dma(FLOPPY_DMA);
818 set_dma_mode(FLOPPY_DMA, rwflag ? DMA_MODE_WRITE : DMA_MODE_READ);
819 set_dma_addr(FLOPPY_DMA, (long) paddr); /* DAG - changed from Atari specific */
820 #ifdef TRACKBUFFER
821 set_dma_count(FLOPPY_DMA,(!read_track ? 1 : unit[SelectedDrive].disktype->spt)*512);
822 #else
823 set_dma_count(FLOPPY_DMA, 512); /* Block/sector size - going to have to change */
824 #endif
825 SET_IRQ_HANDLER(fd_rwsec_done);
826 /* Turn on dma int */
827 enable_dma(FLOPPY_DMA);
828 /* Now give it something to do */
829 FDC1772_WRITE(FDC1772REG_CMD, (rwflag ? (FDC1772CMD_WRSEC | FDC1772CMDADD_P) :
830 #ifdef TRACKBUFFER
831 (FDC1772CMD_RDSEC | (read_track ? FDC1772CMDADD_M : 0) |
832 /* Hmm - the idea here is to stop the FDC spinning the disc
833 up when we know that we already still have it spinning */
834 (MotorOn?FDC1772CMDADD_H:0))
835 #else
836 FDC1772CMD_RDSEC
837 #endif
840 restore_flags(flags);
841 DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n", flags));
842 /*sti(); *//* DAG - Hmm */
843 /* Hmm - should do something DAG */
844 old_motoron = MotorOn;
845 MotorOn = 1;
846 NeedSeek = 1;
848 /* wait for interrupt */
850 #ifdef TRACKBUFFER
851 if (read_track) {
853 * If reading a whole track, wait about one disk rotation and
854 * then check if all sectors are read. The FDC will even
855 * search for the first non-existant sector and need 1 sec to
856 * recognise that it isn't present :-(
858 /* 1 rot. + 5 rot.s if motor was off */
859 mod_timer(&readtrack_timer, jiffies + HZ/5 + (old_motoron ? 0 : HZ));
860 DPRINT(("Setting readtrack_timer to %d @ %d\n",
861 readtrack_timer.expires,jiffies));
862 MultReadInProgress = 1;
864 #endif
866 /*DPRINT(("fd_rwsec() before START_TIMEOUT \n")); */
867 START_TIMEOUT();
868 /*DPRINT(("fd_rwsec() after START_TIMEOUT \n")); */
872 #ifdef TRACKBUFFER
874 static void fd_readtrack_check(unsigned long dummy)
876 unsigned long flags, addr;
877 extern unsigned char *fdc1772_dataaddr;
879 DPRINT(("fd_readtrack_check @ %d\n",jiffies));
881 save_flags(flags);
882 clf();
884 del_timer( &readtrack_timer );
886 if (!MultReadInProgress) {
887 /* This prevents a race condition that could arise if the
888 * interrupt is triggered while the calling of this timer
889 * callback function takes place. The IRQ function then has
890 * already cleared 'MultReadInProgress' when control flow
891 * gets here.
893 restore_flags(flags);
894 return;
897 /* get the current DMA address */
898 addr=(unsigned long)fdc1772_dataaddr; /* DAG - ? */
899 DPRINT(("fd_readtrack_check: addr=%x PhysTrackBuffer=%x\n",addr,PhysTrackBuffer));
901 if (addr >= (unsigned int)PhysTrackBuffer + unit[SelectedDrive].disktype->spt*512) {
902 /* already read enough data, force an FDC interrupt to stop
903 * the read operation
905 SET_IRQ_HANDLER( NULL );
906 restore_flags(flags);
907 DPRINT(("fd_readtrack_check(): done\n"));
908 FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI );
909 udelay(25);
911 /* No error until now -- the FDC would have interrupted
912 * otherwise!
914 fd_rwsec_done( 0 );
915 } else {
916 /* not yet finished, wait another tenth rotation */
917 restore_flags(flags);
918 DPRINT(("fd_readtrack_check(): not yet finished\n"));
919 readtrack_timer.expires = jiffies + HZ/5/10;
920 add_timer( &readtrack_timer );
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)
934 return;
936 MultReadInProgress = 0;
938 STOP_TIMEOUT();
940 if (read_track)
941 del_timer( &readtrack_timer );
942 #endif
945 /* Correct the track if stretch != 0 */
946 if (unit[SelectedDrive].disktype->stretch) {
947 track = FDC1772_READ(FDC1772REG_TRACK);
948 FDC1772_WRITE(FDC1772REG_TRACK, track <<
949 unit[SelectedDrive].disktype->stretch);
951 if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) {
952 printk("fd%d: is write protected\n", SelectedDrive);
953 goto err_end;
955 if ((status & FDC1772STAT_RECNF)
956 #ifdef TRACKBUFFER
957 /* RECNF is no error after a multiple read when the FDC
958 * searched for a non-existant sector!
960 && !(read_track &&
961 FDC1772_READ(FDC1772REG_SECTOR) > unit[SelectedDrive].disktype->spt)
962 #endif
964 if (Probing) {
965 if (unit[SelectedDrive].disktype > disk_type) {
966 /* try another disk type */
967 unit[SelectedDrive].disktype--;
968 set_capacity(disks[SelectedDrive],
969 unit[SelectedDrive].disktype->blocks);
970 } else
971 Probing = 0;
972 } else {
973 /* record not found, but not probing. Maybe stretch wrong ? Restart probing */
974 if (unit[SelectedDrive].autoprobe) {
975 unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1;
976 set_capacity(disks[SelectedDrive],
977 unit[SelectedDrive].disktype->blocks);
978 Probing = 1;
981 if (Probing) {
982 setup_req_params(SelectedDrive);
983 #ifdef TRACKBUFFER
984 BufferDrive = -1;
985 #endif
986 do_fd_action(SelectedDrive);
987 return;
989 printk("fd%d: sector %d not found (side %d, track %d)\n",
990 SelectedDrive, FDC1772_READ(FDC1772REG_SECTOR), ReqSide, ReqTrack);
991 goto err_end;
993 if (status & FDC1772STAT_CRC) {
994 printk("fd%d: CRC error (side %d, track %d, sector %d)\n",
995 SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
996 goto err_end;
998 if (status & FDC1772STAT_LOST) {
999 printk("fd%d: lost data (side %d, track %d, sector %d)\n",
1000 SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
1001 goto err_end;
1003 Probing = 0;
1005 if (ReqCmd == READ) {
1006 #ifdef TRACKBUFFER
1007 if (!read_track) {
1008 /*cache_clear (PhysDMABuffer, 512);*/
1009 copy_buffer (DMABuffer, ReqData);
1010 } else {
1011 /*cache_clear (PhysTrackBuffer, FD1772_MAX_SECTORS * 512);*/
1012 BufferDrive = SelectedDrive;
1013 BufferSide = ReqSide;
1014 BufferTrack = ReqTrack;
1015 copy_buffer (SECTOR_BUFFER (ReqSector), ReqData);
1017 #else
1018 /*cache_clear( PhysDMABuffer, 512 ); */
1019 copy_buffer(DMABuffer, ReqData);
1020 #endif
1022 if (++ReqCnt < CURRENT->current_nr_sectors) {
1023 /* read next sector */
1024 setup_req_params(SelectedDrive);
1025 do_fd_action(SelectedDrive);
1026 } else {
1027 /* all sectors finished */
1028 CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
1029 CURRENT->sector += CURRENT->current_nr_sectors;
1030 end_request(CURRENT, 1);
1031 redo_fd_request();
1033 return;
1035 err_end:
1036 #ifdef TRACKBUFFER
1037 BufferDrive = -1;
1038 #endif
1040 fd_error();
1044 static void fd_times_out(unsigned long dummy)
1046 SET_IRQ_HANDLER(NULL);
1047 /* If the timeout occurred while the readtrack_check timer was
1048 * active, we need to cancel it, else bad things will happen */
1049 del_timer( &readtrack_timer );
1050 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1051 udelay(25);
1053 printk("floppy timeout\n");
1054 STOP_TIMEOUT(); /* hmm - should we do this ? */
1055 fd_error();
1059 /* The (noop) seek operation here is needed to make the WP bit in the
1060 * FDC1772 status register accessible for check_change. If the last disk
1061 * operation would have been a RDSEC, this bit would always read as 0
1062 * no matter what :-( To save time, the seek goes to the track we're
1063 * already on.
1066 static void finish_fdc(void)
1068 /* DAG - just try without this dummy seek! */
1069 finish_fdc_done(0);
1070 return;
1072 if (!NeedSeek) {
1073 finish_fdc_done(0);
1074 } else {
1075 DPRINT(("finish_fdc: dummy seek started\n"));
1076 FDC1772_WRITE(FDC1772REG_DATA, unit[SelectedDrive].track);
1077 SET_IRQ_HANDLER(finish_fdc_done);
1078 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1079 MotorOn = 1;
1080 START_TIMEOUT();
1081 /* we must wait for the IRQ here, because the ST-DMA is
1082 * released immediately afterwards and the interrupt may be
1083 * delivered to the wrong driver.
1089 static void finish_fdc_done(int dummy)
1091 unsigned long flags;
1093 DPRINT(("finish_fdc_done entered\n"));
1094 STOP_TIMEOUT();
1095 NeedSeek = 0;
1097 if (timer_pending(&fd_timer) &&
1098 time_after(jiffies + 5, fd_timer.expires))
1099 /* If the check for a disk change is done too early after this
1100 * last seek command, the WP bit still reads wrong :-((
1102 mod_timer(&fd_timer, jiffies + 5);
1103 else {
1104 /* START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1106 del_timer(&motor_off_timer);
1107 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1109 save_flags(flags);
1110 cli();
1111 /* stdma_release(); - not sure if I should do something DAG */
1112 fdc_busy = 0;
1113 wake_up(&fdc_wait);
1114 restore_flags(flags);
1116 DPRINT(("finish_fdc() finished\n"));
1120 /* Prevent "aliased" accesses. */
1121 static int fd_ref[4];
1122 static int fd_device[4];
1124 /* dummy for blk.h */
1125 static void floppy_off(unsigned int nr)
1130 /* On the old arcs write protect depends on the particular model
1131 of machine. On the A310, R140, and A440 there is a disc changed
1132 detect, however on the A4x0/1 range there is not. There
1133 is nothing to tell you which machine your on.
1134 At the moment I'm just marking changed always. I've
1135 left the Atari's 'change on write protect change' code in this
1136 part (but nothing sets it).
1137 RiscOS apparently checks the disc serial number etc. to detect changes
1138 - but if it sees a disc change line go high (?) it flips to using
1139 it. Well maybe I'll add that in the future (!?)
1141 static int check_floppy_change(struct gendisk *disk)
1143 struct archy_floppy_struct *p = disk->private_data;
1144 unsigned int drive = p - unit;
1146 if (test_bit(drive, &fake_change)) {
1147 /* simulated change (e.g. after formatting) */
1148 return 1;
1150 if (test_bit(drive, &changed_floppies)) {
1151 /* surely changed (the WP signal changed at least once) */
1152 return 1;
1154 if (p->wpstat) {
1155 /* WP is on -> could be changed: to be sure, buffers should be
1156 * invalidated...
1158 return 1;
1160 return 1; /* DAG - was 0 */
1163 static int floppy_revalidate(struct gendisk *disk)
1165 struct archy_floppy_struct *p = disk->private_data;
1166 unsigned int drive = p - unit;
1168 if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change)
1169 || unit[drive].disktype == 0) {
1170 #ifdef TRACKBUFFER
1171 BufferDrive = -1;
1172 #endif
1173 clear_bit(drive, &fake_change);
1174 clear_bit(drive, &changed_floppies);
1175 p->disktype = 0;
1177 return 0;
1180 /* This sets up the global variables describing the current request. */
1182 static void setup_req_params(int drive)
1184 int block = ReqBlock + ReqCnt;
1186 ReqTrack = block / unit[drive].disktype->spt;
1187 ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1;
1188 ReqSide = ReqTrack & 1;
1189 ReqTrack >>= 1;
1190 ReqData = ReqBuffer + 512 * ReqCnt;
1192 #ifdef TRACKBUFFER
1193 read_track = (ReqCmd == READ && CURRENT->errors == 0);
1194 #endif
1196 DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n", ReqSide,
1197 ReqTrack, ReqSector, (unsigned long) ReqData));
1201 static void redo_fd_request(void)
1203 int drive, type;
1204 struct archy_floppy_struct *floppy;
1206 DPRINT(("redo_fd_request: CURRENT=%p dev=%s CURRENT->sector=%ld\n",
1207 CURRENT, CURRENT ? CURRENT->rq_disk->disk_name : "",
1208 CURRENT ? CURRENT->sector : 0));
1210 repeat:
1212 if (!CURRENT)
1213 goto the_end;
1215 floppy = CURRENT->rq_disk->private_data;
1216 drive = floppy - unit;
1217 type = fd_device[drive];
1219 if (!floppy->connected) {
1220 /* drive not connected */
1221 printk("Unknown Device: fd%d\n", drive);
1222 end_request(CURRENT, 0);
1223 goto repeat;
1225 if (type == 0) {
1226 if (!floppy->disktype) {
1227 Probing = 1;
1228 floppy->disktype = disk_type + NUM_DISK_TYPES - 1;
1229 set_capacity(disks[drive], floppy->disktype->blocks);
1230 floppy->autoprobe = 1;
1232 } else {
1233 /* user supplied disk type */
1234 --type;
1235 if (type >= NUM_DISK_TYPES) {
1236 printk("fd%d: invalid disk format", drive);
1237 end_request(CURRENT, 0);
1238 goto repeat;
1240 floppy->disktype = &disk_type[type];
1241 set_capacity(disks[drive], floppy->disktype->blocks);
1242 floppy->autoprobe = 0;
1245 if (CURRENT->sector + 1 > floppy->disktype->blocks) {
1246 end_request(CURRENT, 0);
1247 goto repeat;
1249 /* stop deselect timer */
1250 del_timer(&motor_off_timer);
1252 ReqCnt = 0;
1253 ReqCmd = CURRENT->cmd;
1254 ReqBlock = CURRENT->sector;
1255 ReqBuffer = CURRENT->buffer;
1256 setup_req_params(drive);
1257 do_fd_action(drive);
1259 return;
1261 the_end:
1262 finish_fdc();
1265 static void fd1772_checkint(void)
1267 extern int fdc1772_bytestogo;
1269 /*printk("fd1772_checkint %d\n",fdc1772_fdc_int_done);*/
1270 if (fdc1772_fdc_int_done)
1271 floppy_irqconsequencehandler();
1272 if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0);
1273 if (fdc_busy) {
1274 schedule_work(&fd1772_tq);
1278 static void do_fd_request(request_queue_t* q)
1280 unsigned long flags;
1282 DPRINT(("do_fd_request for pid %d\n", current->pid));
1283 if (fdc_busy) return;
1284 save_flags(flags);
1285 cli();
1286 while (fdc_busy)
1287 sleep_on(&fdc_wait);
1288 fdc_busy = 1;
1289 ENABLE_IRQ();
1290 restore_flags(flags);
1292 fdc1772_fdc_int_done = 0;
1294 redo_fd_request();
1296 schedule_work(&fd1772_tq);
1300 static int invalidate_drive(struct block_device *bdev)
1302 struct archy_floppy_struct *p = bdev->bd_disk->private_data;
1303 /* invalidate the buffer track to force a reread */
1304 #ifdef TRACKBUFFER
1305 BufferDrive = -1;
1306 #endif
1308 set_bit(p - unit, &fake_change);
1309 return 0;
1312 static int fd_ioctl(struct inode *inode, struct file *filp,
1313 unsigned int cmd, unsigned long param)
1315 struct block_device *bdev = inode->i_bdev;
1317 switch (cmd) {
1318 case FDFMTEND:
1319 case FDFLUSH:
1320 invalidate_drive(bdev);
1321 check_disk_change(bdev);
1322 case FDFMTBEG:
1323 return 0;
1324 default:
1325 return -EINVAL;
1330 /* Initialize the 'unit' variable for drive 'drive' */
1332 static void fd_probe(int drive)
1334 unit[drive].connected = 0;
1335 unit[drive].disktype = NULL;
1337 if (!fd_test_drive_present(drive))
1338 return;
1340 unit[drive].connected = 1;
1341 unit[drive].track = -1; /* If we put the auto detect back in this can go to 0 */
1342 unit[drive].steprate = FDC1772STEP_6;
1343 MotorOn = 1; /* from probe restore operation! */
1347 /* This function tests the physical presence of a floppy drive (not
1348 * whether a disk is inserted). This is done by issuing a restore
1349 * command, waiting max. 2 seconds (that should be enough to move the
1350 * head across the whole disk) and looking at the state of the "TR00"
1351 * signal. This should now be raised if there is a drive connected
1352 * (and there is no hardware failure :-) Otherwise, the drive is
1353 * declared absent.
1356 static int fd_test_drive_present(int drive)
1358 unsigned long timeout;
1359 unsigned char status;
1360 int ok;
1362 printk("fd_test_drive_present %d\n", drive);
1363 if (drive > 1)
1364 return (0);
1365 return (1); /* Simple hack for the moment - the autodetect doesn't seem to work on arc */
1366 fd_select_drive(drive);
1368 /* disable interrupt temporarily */
1369 DISABLE_IRQ();
1370 FDC1772_WRITE(FDC1772REG_TRACK, 0x00); /* was ff00 why? */
1371 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6);
1373 /*printk("fd_test_drive_present: Going into timeout loop\n"); */
1374 for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; time_before(jiffies, timeout);) {
1375 /* What does this piece of atariism do? - query for an interrupt? */
1376 /* if (!(mfp.par_dt_reg & 0x20))
1377 break; */
1378 /* Well this is my nearest guess - quit when we get an FDC interrupt */
1379 if (ioc_readb(IOC_FIQSTAT) & 2)
1380 break;
1383 /*printk("fd_test_drive_present: Coming out of timeout loop\n"); */
1384 status = FDC1772_READ(FDC1772REG_STATUS);
1385 ok = (status & FDC1772STAT_TR00) != 0;
1387 /*printk("fd_test_drive_present: ok=%d\n",ok); */
1388 /* force interrupt to abort restore operation (FDC1772 would try
1389 * about 50 seconds!) */
1390 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1391 udelay(500);
1392 status = FDC1772_READ(FDC1772REG_STATUS);
1393 udelay(20);
1394 /*printk("fd_test_drive_present: just before OK code %d\n",ok); */
1396 if (ok) {
1397 /* dummy seek command to make WP bit accessible */
1398 FDC1772_WRITE(FDC1772REG_DATA, 0);
1399 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
1400 printk("fd_test_drive_present: just before wait for int\n");
1401 /* DAG: Guess means wait for interrupt */
1402 while (!(ioc_readb(IOC_FIQSTAT) & 2));
1403 printk("fd_test_drive_present: just after wait for int\n");
1404 status = FDC1772_READ(FDC1772REG_STATUS);
1406 printk("fd_test_drive_present: just before ENABLE_IRQ\n");
1407 ENABLE_IRQ();
1408 printk("fd_test_drive_present: about to return\n");
1409 return (ok);
1413 /* Look how many and which kind of drives are connected. If there are
1414 * floppies, additionally start the disk-change and motor-off timers.
1417 static void config_types(void)
1419 int drive, cnt = 0;
1421 printk("Probing floppy drive(s):\n");
1422 for (drive = 0; drive < FD_MAX_UNITS; drive++) {
1423 fd_probe(drive);
1424 if (unit[drive].connected) {
1425 printk("fd%d\n", drive);
1426 ++cnt;
1430 if (FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_BUSY) {
1431 /* If FDC1772 is still busy from probing, give it another FORCI
1432 * command to abort the operation. If this isn't done, the FDC1772
1433 * will interrupt later and its IRQ line stays low, because
1434 * the status register isn't read. And this will block any
1435 * interrupts on this IRQ line :-(
1437 FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
1438 udelay(500);
1439 FDC1772_READ(FDC1772REG_STATUS);
1440 udelay(20);
1442 if (cnt > 0) {
1443 START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
1444 if (cnt == 1)
1445 fd_select_drive(0);
1446 /*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
1451 * floppy_open check for aliasing (/dev/fd0 can be the same as
1452 * /dev/PS0 etc), and disallows simultaneous access to the same
1453 * drive with different device numbers.
1456 static int floppy_open(struct inode *inode, struct file *filp)
1458 int drive = iminor(inode) & 3;
1459 int type = iminor(inode) >> 2;
1460 int old_dev = fd_device[drive];
1462 if (fd_ref[drive] && old_dev != type)
1463 return -EBUSY;
1465 if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
1466 return -EBUSY;
1468 if (filp->f_flags & O_EXCL)
1469 fd_ref[drive] = -1;
1470 else
1471 fd_ref[drive]++;
1473 fd_device[drive] = type;
1475 if (filp->f_flags & O_NDELAY)
1476 return 0;
1478 if (filp->f_mode & 3) {
1479 check_disk_change(inode->i_bdev);
1480 if (filp->f_mode & 2) {
1481 if (unit[drive].wpstat) {
1482 floppy_release(inode, filp);
1483 return -EROFS;
1487 return 0;
1491 static int floppy_release(struct inode *inode, struct file *filp)
1493 int drive = iminor(inode) & 3;
1495 if (fd_ref[drive] < 0)
1496 fd_ref[drive] = 0;
1497 else if (!fd_ref[drive]--) {
1498 printk("floppy_release with fd_ref == 0");
1499 fd_ref[drive] = 0;
1502 return 0;
1505 static struct block_device_operations floppy_fops =
1507 .open = floppy_open,
1508 .release = floppy_release,
1509 .ioctl = fd_ioctl,
1510 .media_changed = check_floppy_change,
1511 .revalidate_disk= floppy_revalidate,
1514 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
1516 int drive = *part & 3;
1517 if ((*part >> 2) > NUM_DISK_TYPES || drive >= FD_MAX_UNITS)
1518 return NULL;
1519 *part = 0;
1520 return get_disk(disks[drive]);
1523 int fd1772_init(void)
1525 static DEFINE_SPINLOCK(lock);
1526 int i, err = -ENOMEM;
1528 if (!machine_is_archimedes())
1529 return 0;
1531 for (i = 0; i < FD_MAX_UNITS; i++) {
1532 disks[i] = alloc_disk(1);
1533 if (!disks[i])
1534 goto err_disk;
1537 err = register_blkdev(MAJOR_NR, "fd");
1538 if (err)
1539 goto err_disk;
1541 err = -EBUSY;
1542 if (request_dma(FLOPPY_DMA, "fd1772")) {
1543 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA);
1544 goto err_blkdev;
1547 if (request_dma(FIQ_FD1772, "fd1772 end")) {
1548 printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772);
1549 goto err_dma1;
1552 /* initialize variables */
1553 SelectedDrive = -1;
1554 #ifdef TRACKBUFFER
1555 BufferDrive = BufferSide = BufferTrack = -1;
1556 /* Atari uses 512 - I want to eventually cope with 1K sectors */
1557 DMABuffer = (char *)kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
1558 TrackBuffer = DMABuffer + 512;
1559 #else
1560 /* Allocate memory for the DMAbuffer - on the Atari this takes it
1561 out of some special memory... */
1562 DMABuffer = (char *) kmalloc(2048); /* Copes with pretty large sectors */
1563 #endif
1564 err = -ENOMEM;
1565 if (!DMAbuffer)
1566 goto err_dma2;
1568 enable_dma(FIQ_FD1772); /* This inserts a call to our command end routine */
1570 floppy_queue = blk_init_queue(do_fd_request, &lock);
1571 if (!floppy_queue)
1572 goto err_queue;
1574 for (i = 0; i < FD_MAX_UNITS; i++) {
1575 unit[i].track = -1;
1576 disks[i]->major = MAJOR_NR;
1577 disks[i]->first_minor = 0;
1578 disks[i]->fops = &floppy_fops;
1579 sprintf(disks[i]->disk_name, "fd%d", i);
1580 disks[i]->private_data = &unit[i];
1581 disks[i]->queue = floppy_queue;
1582 set_capacity(disks[i], MAX_DISK_SIZE * 2);
1584 blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
1585 floppy_find, NULL, NULL);
1587 for (i = 0; i < FD_MAX_UNITS; i++)
1588 add_disk(disks[i]);
1590 config_types();
1592 return 0;
1594 err_queue:
1595 kfree(DMAbuffer);
1596 err_dma2:
1597 free_dma(FIQ_FD1772);
1599 err_dma1:
1600 free_dma(FLOPPY_DMA);
1602 err_blkdev:
1603 unregister_blkdev(MAJOR_NR, "fd");
1605 err_disk:
1606 while (i--)
1607 put_disk(disks[i]);
1608 return err;