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