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