summary refs log tree commit diff
path: root/drivers/acorn
diff options
context:
space:
mode:
authorAdrian Bunk <bunk@stusta.de>2007-07-31 00:38:19 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-31 15:39:39 -0700
commit99eb8a550dbccc0e1f6c7e866fe421810e0585f6 (patch)
tree130c6e3338a0655ba74355eba83afab9261e1ed0 /drivers/acorn
parent0d0ed42e5ca2e22465c591341839c18025748fe8 (diff)
downloadlinux-99eb8a550dbccc0e1f6c7e866fe421810e0585f6.tar.gz
Remove the arm26 port
The arm26 port has been in a state where it was far from even compiling
for quite some time.

Ian Molton agreed with the removal.

Signed-off-by: Adrian Bunk <bunk@stusta.de>
Cc: Ian Molton <spyro@f2s.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/acorn')
-rw-r--r--drivers/acorn/README1
-rw-r--r--drivers/acorn/block/Kconfig36
-rw-r--r--drivers/acorn/block/Makefile9
-rw-r--r--drivers/acorn/block/fd1772.c1604
-rw-r--r--drivers/acorn/block/fd1772dma.S100
-rw-r--r--drivers/acorn/block/mfm.S162
-rw-r--r--drivers/acorn/block/mfmhd.c1385
7 files changed, 0 insertions, 3297 deletions
diff --git a/drivers/acorn/README b/drivers/acorn/README
deleted file mode 100644
index d399c09ca61c..000000000000
--- a/drivers/acorn/README
+++ /dev/null
@@ -1 +0,0 @@
-Drivers for the ACORN "podule" ARM specific bus.
diff --git a/drivers/acorn/block/Kconfig b/drivers/acorn/block/Kconfig
deleted file mode 100644
index a0ff25ea439f..000000000000
--- a/drivers/acorn/block/Kconfig
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Block device driver configuration
-#
-
-menu "Acorn-specific block devices"
-	depends on ARCH_ARC || ARCH_A5K
-
-config BLK_DEV_FD1772
-	tristate "Old Archimedes floppy (1772) support"
-	depends on ARCH_ARC || ARCH_A5K
-	help
-	  Support the floppy drive on the Acorn Archimedes (A300, A4x0, A540,
-	  R140 and R260) series of computers; it supports only 720K floppies
-	  at the moment. If you don't have one of these machines just answer
-	  N.
-
-config BLK_DEV_MFM
-	tristate "MFM harddisk support"
-	depends on ARCH_ARC || ARCH_A5K
-	help
-	  Support the MFM hard drives on the Acorn Archimedes both
-	  on-board the A4x0 motherboards and via the Acorn MFM podules.
-	  Drives up to 64MB are supported. If you haven't got one of these
-	  machines or drives just say N.
-
-config BLK_DEV_MFM_AUTODETECT
-	bool "Autodetect hard drive geometry"
-	depends on BLK_DEV_MFM
-	help
-	  If you answer Y, the MFM code will attempt to automatically detect
-	  the cylinders/heads/sectors count on your hard drive. WARNING: This
-	  sometimes doesn't work and it also does some dodgy stuff which
-	  potentially might damage your drive.
-
-endmenu
-
diff --git a/drivers/acorn/block/Makefile b/drivers/acorn/block/Makefile
deleted file mode 100644
index 38a9afe8e03f..000000000000
--- a/drivers/acorn/block/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for the Acorn block device drivers.
-#
-
-fd1772_mod-objs	:= fd1772.o fd1772dma.o
-mfmhd_mod-objs	:= mfmhd.o mfm.o
-
-obj-$(CONFIG_BLK_DEV_FD1772)	+= fd1772_mod.o
-obj-$(CONFIG_BLK_DEV_MFM)	+= mfmhd_mod.o
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
deleted file mode 100644
index d7e18ce8dad9..000000000000
--- a/drivers/acorn/block/fd1772.c
+++ /dev/null
@@ -1,1604 +0,0 @@
-/*
- *  linux/kernel/arch/arm/drivers/block/fd1772.c
- *  Based on ataflop.c in the m68k Linux
- *  Copyright (C) 1993  Greg Harp
- *  Atari Support by Bjoern Brauel, Roman Hodek
- *  Archimedes Support by Dave Gilbert (linux@treblig.org)
- *
- *  Big cleanup Sep 11..14 1994 Roman Hodek:
- *   - Driver now works interrupt driven
- *   - Support for two drives; should work, but I cannot test that :-(
- *   - Reading is done in whole tracks and buffered to speed up things
- *   - Disk change detection and drive deselecting after motor-off
- *     similar to TOS
- *   - Autodetection of disk format (DD/HD); untested yet, because I
- *     don't have an HD drive :-(
- *
- *  Fixes Nov 13 1994 Martin Schaller:
- *   - Autodetection works now
- *   - Support for 5 1/4" disks
- *   - Removed drive type (unknown on atari)
- *   - Do seeks with 8 Mhz
- *
- *  Changes by Andreas Schwab:
- *   - After errors in multiple read mode try again reading single sectors
- *  (Feb 1995):
- *   - Clean up error handling
- *   - Set blk_size for proper size checking
- *   - Initialize track register when testing presence of floppy
- *   - Implement some ioctl's
- *
- *  Changes by Torsten Lang:
- *   - When probing the floppies we should add the FDC1772CMDADD_H flag since
- *     the FDC1772 will otherwise wait forever when no disk is inserted...
- *
- *  Things left to do:
- *   - Formatting
- *   - Maybe a better strategy for disk change detection (does anyone
- *     know one?)
- *   - There are some strange problems left: The strangest one is
- *     that, at least on my TT (4+4MB), the first 2 Bytes of the last
- *     page of the TT-Ram (!) change their contents (some bits get
- *     set) while a floppy DMA is going on. But there are no accesses
- *     to these memory locations from the kernel... (I tested that by
- *     making the page read-only). I cannot explain what's going on...
- *   - Sometimes the drive-change-detection stops to work. The
- *     function is still called, but the WP bit always reads as 0...
- *     Maybe a problem with the status reg mode or a timing problem.
- *     Note 10/12/94: The change detection now seems to work reliably.
- *     There is no proof, but I've seen no hang for a long time...
- *
- * ARCHIMEDES changes: (gilbertd@cs.man.ac.uk)
- *     26/12/95 - Changed all names starting with FDC to FDC1772
- *                Removed all references to clock speed of FDC - we're stuck with 8MHz
- *                Modified disk_type structure to remove HD formats
- *
- *      7/ 1/96 - Wrote FIQ code, removed most remaining atariisms
- *
- *     13/ 1/96 - Well I think its read a single sector; but there is a problem
- *                fd_rwsec_done which is called in FIQ mode starts another transfer
- *                off (in fd_rwsec) while still in FIQ mode.  Because its still in
- *                FIQ mode it can't service the DMA and loses data. So need to
- *                heavily restructure.
- *     14/ 1/96 - Found that the definitions of the register numbers of the
- *                FDC were multiplied by 2 in the header for the 16bit words
- *                of the atari so half the writes were going in the wrong place.
- *                Also realised that the FIQ entry didn't make any attempt to
- *                preserve registers or return correctly; now in assembler.
- *
- *     11/ 2/96 - Hmm - doesn't work on real machine.  Auto detect doesn't
- *                and hacking that past seems to wait forever - check motor
- *                being turned on.
- *
- *     17/ 2/96 - still having problems - forcing track to -1 when selecting
- *                new drives seems to allow it to read first few sectors
- *                but then we get solid hangs at apparently random places
- *                which change depending what is happening.
- *
- *      9/ 3/96 - Fiddled a lot of stuff around to move to kernel 1.3.35
- *                A lot of fiddling in DMA stuff. Having problems with it
- *                constnatly thinking its timeing out. Ah - its timeout
- *                was set to (6*HZ) rather than jiffies+(6*HZ).  Now giving
- *                duff data!
- *
- *      5/ 4/96 - Made it use the new IOC_ macros rather than *ioc
- *                Hmm - giving unexpected FIQ and then timeouts
- *     18/ 8/96 - Ran through indent -kr -i8
- *                Some changes to disc change detect; don't know how well it
- *                works.
- *     24/ 8/96 - Put all the track buffering code back in from the atari
- *                code - I wonder if it will still work... No :-)
- *                Still works if I turn off track buffering.
- *     25/ 8/96 - Changed the timer expires that I'd added back to be 
- *                jiffies + ....; and it all sprang to life! Got 2.8K/sec
- *                off a cp -r of a 679K disc (showed 94% cpu usage!)
- *                (PC gets 14.3K/sec - 0% CPU!) Hmm - hard drive corrupt!
- *                Also perhaps that compile was with cache off.
- *                changed cli in fd_readtrack_check to cliIF
- *                changed vmallocs to kmalloc (whats the difference!!)
- *                Removed the busy wait loop in do_fd_request and replaced
- *                by a routine on tq_immediate; only 11% cpu on a dd off the
- *                raw disc - but the speed is the same.
- *	1/ 9/96 - Idea (failed!) - set the 'disable spin-up sequence'
- *		  when we read the track if we know the motor is on; didn't
- *		  help - perhaps we have to do it in stepping as well.
- *		  Nope. Still doesn't help.
- *		  Hmm - what seems to be happening is that fd_readtrack_check
- *		  is never getting called. Its job is to terminate the read
- *		  just after we think we should have got the data; otherwise
- *		  the fdc takes 1 second to timeout; which is what's happening
- *		  Now I can see 'readtrack_timer' being set (which should do the
- *		  call); but it never seems to be called - hmm!
- *		  OK - I've moved the check to my tq_immediate code -
- *		  and it WORKS! 13.95K/second at 19% CPU.
- *		  I wish I knew why that timer didn't work.....
- *
- *     16/11/96 - Fiddled and frigged for 2.0.18
- *
- * DAG 30/01/99 - Started frobbing for 2.2.1
- * DAG 20/06/99 - A little more frobbing:
- *		  Included include/asm/uaccess.h for get_user/put_user
- *
- * DAG  1/09/00 - Dusted off for 2.4.0-test7
- *                MAX_SECTORS was name clashing so it is now FD1772_...
- *                Minor parameter, name layouts for 2.4.x differences
- */
-
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/fcntl.h>
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/workqueue.h>
-#include <linux/fd.h>
-#include <linux/fd1772.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/bitops.h>
-
-#include <asm/arch/oldlatches.h>
-#include <asm/dma.h>
-#include <asm/hardware.h>
-#include <asm/hardware/ioc.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-
-/* Note: FD_MAX_UNITS could be redefined to 2 for the Atari (with
- * little additional rework in this file). But I'm not yet sure if
- * some other code depends on the number of floppies... (It is defined
- * in a public header!)
- */
-#if 0
-#undef FD_MAX_UNITS
-#define	FD_MAX_UNITS	2
-#endif
-
-/* Ditto worries for Arc - DAG */
-#define FD_MAX_UNITS 4
-#define TRACKBUFFER 0
-/*#define DEBUG*/
-
-#ifdef DEBUG
-#define DPRINT(a)	printk a
-#else
-#define DPRINT(a)
-#endif
-
-static struct request_queue *floppy_queue;
-
-#define MAJOR_NR FLOPPY_MAJOR
-#define FLOPPY_DMA 0
-#define DEVICE_NAME "floppy"
-#define QUEUE (floppy_queue)
-#define CURRENT elv_next_request(floppy_queue)
-
-/* Disk types: DD */
-static struct archy_disk_type {
-	const char *name;
-	unsigned spt;		/* sectors per track */
-	unsigned blocks;	/* total number of blocks */
-	unsigned stretch;	/* track doubling ? */
-} disk_type[] = {
-
-	{ "d360", 9, 720, 0 },			/* 360kB diskette */
-	{ "D360", 9, 720, 1 },			/* 360kb in 720kb drive */
-	{ "D720", 9, 1440, 0 },			/* 720kb diskette (DD) */
-	/*{ "D820", 10,1640, 0}, *//* DD disk with 82 tracks/10 sectors 
-	                              - DAG - can't see how type detect can distinguish this
-				      from 720K until it reads block 4 by which time its too late! */
-};
-
-#define	NUM_DISK_TYPES (sizeof(disk_type)/sizeof(*disk_type))
-
-/*
- * Maximum disk size (in kilobytes). This default is used whenever the
- * current disk size is unknown.
- */
-#define MAX_DISK_SIZE 720
-
-static struct gendisk *disks[FD_MAX_UNIT];
-
-/* current info on each unit */
-static struct archy_floppy_struct {
-	int connected;		/* !=0 : drive is connected */
-	int autoprobe;		/* !=0 : do autoprobe       */
-
-	struct archy_disk_type *disktype;	/* current type of disk */
-
-	int track;		/* current head position or -1
-				   * if unknown */
-	unsigned int steprate;	/* steprate setting */
-	unsigned int wpstat;	/* current state of WP signal
-				   * (for disk change detection) */
-} unit[FD_MAX_UNITS];
-
-/* DAG: On Arc we spin on a flag being cleared by fdc1772_comendhandler which
-   is an assembler routine */
-extern void fdc1772_comendhandler(void);	/* Actually doens't have these parameters - see fd1772.S */
-extern volatile int fdc1772_comendstatus;
-extern volatile int fdc1772_fdc_int_done;
-
-#define FDC1772BASE ((0x210000>>2)|0x80000000)
-
-#define FDC1772_READ(reg) inb(FDC1772BASE+(reg/2))
-
-/* DAG: You wouldn't be silly to ask why FDC1772_WRITE is a function rather
-   than the #def below - well simple - the #def won't compile - and I
-   don't understand why (__outwc not defined) */
-/* NOTE: Reg is 0,2,4,6 as opposed to 0,1,2,3 or 0,4,8,12 to keep compatibility
-   with the ST version of fd1772.h */
-/*#define FDC1772_WRITE(reg,val) outw(val,(reg+FDC1772BASE)); */
-void FDC1772_WRITE(int reg, unsigned char val)
-{
-	if (reg == FDC1772REG_CMD) {
-		DPRINT(("FDC1772_WRITE new command 0x%x @ %d\n", val,jiffies));
-		if (fdc1772_fdc_int_done) {
-			DPRINT(("FDC1772_WRITE: Hmm fdc1772_fdc_int_done true - resetting\n"));
-			fdc1772_fdc_int_done = 0;
-		};
-	};
-	outb(val, (reg / 2) + FDC1772BASE);
-};
-
-#define	FD1772_MAX_SECTORS	22
-
-unsigned char *DMABuffer;	/* buffer for writes */
-/*static unsigned long PhysDMABuffer; *//* physical address */
-/* DAG: On Arc we just go straight for the DMA buffer */
-#define PhysDMABuffer DMABuffer
-
-#ifdef TRACKBUFFER   
-unsigned char *TrackBuffer;       /* buffer for reads */
-#define PhysTrackBuffer TrackBuffer /* physical address */
-static int BufferDrive, BufferSide, BufferTrack;
-static int read_track;    /* non-zero if we are reading whole tracks */
-  
-#define SECTOR_BUFFER(sec)  (TrackBuffer + ((sec)-1)*512)
-#define IS_BUFFERED(drive,side,track) \
-    (BufferDrive == (drive) && BufferSide == (side) && BufferTrack == (track))
-#endif
-
-/*
- * These are global variables, as that's the easiest way to give
- * information to interrupts. They are the data used for the current
- * request.
- */
-static int SelectedDrive = 0;
-static int ReqCmd, ReqBlock;
-static int ReqSide, ReqTrack, ReqSector, ReqCnt;
-static int HeadSettleFlag = 0;
-static unsigned char *ReqData, *ReqBuffer;
-static int MotorOn = 0, MotorOffTrys;
-
-/* Synchronization of FDC1772 access. */
-static volatile int fdc_busy = 0;
-static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
-
-
-/* long req'd for set_bit --RR */
-static unsigned long changed_floppies = 0xff, fake_change = 0;
-#define	CHECK_CHANGE_DELAY	HZ/2
-
-/* DAG - increased to 30*HZ - not sure if this is the correct thing to do */
-#define	FD_MOTOR_OFF_DELAY	(10*HZ)
-#define	FD_MOTOR_OFF_MAXTRY	(10*20)
-
-#define FLOPPY_TIMEOUT		(6*HZ)
-#define RECALIBRATE_ERRORS	4	/* After this many errors the drive
-					 * will be recalibrated. */
-#define MAX_ERRORS		8	/* After this many errors the driver
-					 * will give up. */
-
-#define	START_MOTOR_OFF_TIMER(delay)				\
-	do {							\
-		motor_off_timer.expires = jiffies + (delay);	\
-		add_timer( &motor_off_timer );			\
-		MotorOffTrys = 0;				\
-	} while(0)
-
-#define	START_CHECK_CHANGE_TIMER(delay)				\
-	do {							\
-	        mod_timer(&fd_timer, jiffies + (delay));	\
-	} while(0)
-
-#define	START_TIMEOUT()						\
-	do {							\
-		mod_timer(&timeout_timer, jiffies+FLOPPY_TIMEOUT); \
-	} while(0)
-
-#define	STOP_TIMEOUT()						\
-	do {							\
-		del_timer( &timeout_timer );			\
-	} while(0)
-
-#define ENABLE_IRQ() enable_irq(FIQ_FD1772+64);
-
-#define DISABLE_IRQ() disable_irq(FIQ_FD1772+64);
-
-static void fd1772_checkint(void);
-
-DECLARE_WORK(fd1772_tq, (void *)fd1772_checkint, NULL);
-/*
- * The driver is trying to determine the correct media format
- * while Probing is set. fd_rwsec_done() clears it after a
- * successful access.
- */
-static int Probing = 0;
-
-/* This flag is set when a dummy seek is necessary to make the WP
- * status bit accessible.
- */
-static int NeedSeek = 0;
-
-
-/***************************** Prototypes *****************************/
-
-static void fd_select_side(int side);
-static void fd_select_drive(int drive);
-static void fd_deselect(void);
-static void fd_motor_off_timer(unsigned long dummy);
-static void check_change(unsigned long dummy);
-static void floppy_irqconsequencehandler(void);
-static void fd_error(void);
-static void do_fd_action(int drive);
-static void fd_calibrate(void);
-static void fd_calibrate_done(int status);
-static void fd_seek(void);
-static void fd_seek_done(int status);
-static void fd_rwsec(void);
-#ifdef TRACKBUFFER   
-static void fd_readtrack_check( unsigned long dummy );  
-#endif
-static void fd_rwsec_done(int status);
-static void fd_times_out(unsigned long dummy);
-static void finish_fdc(void);
-static void finish_fdc_done(int dummy);
-static void floppy_off(unsigned int nr);
-static void setup_req_params(int drive);
-static void redo_fd_request(void);
-static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int
-		    cmd, unsigned long param);
-static void fd_probe(int drive);
-static int fd_test_drive_present(int drive);
-static void config_types(void);
-static int floppy_open(struct inode *inode, struct file *filp);
-static int floppy_release(struct inode *inode, struct file *filp);
-static void do_fd_request(struct request_queue *);
-
-/************************* End of Prototypes **************************/
-
-static DEFINE_TIMER(motor_off_timer, fd_motor_off_timer, 0, 0);
-
-#ifdef TRACKBUFFER
-static DEFINE_TIMER(readtrack_timer, fd_readtrack_check, 0, 0);
-#endif
-
-static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0);
-
-static DEFINE_TIMER(fd_timer, check_change, 0, 0);
-
-/* DAG: Haven't got a clue what this is? */
-int stdma_islocked(void)
-{
-	return 0;
-};
-
-/* Select the side to use. */
-
-static void fd_select_side(int side)
-{
-	oldlatch_aupdate(LATCHA_SIDESEL, side ? 0 : LATCHA_SIDESEL);
-}
-
-
-/* Select a drive, update the FDC1772's track register
- */
-
-static void fd_select_drive(int drive)
-{
-#ifdef DEBUG
-	printk("fd_select_drive:%d\n", drive);
-#endif
-	/* Hmm - nowhere do we seem to turn the motor on - I'm going to do it here! */
-	oldlatch_aupdate(LATCHA_MOTOR | LATCHA_INUSE, 0);
-
-	if (drive == SelectedDrive)
-		return;
-
-	oldlatch_aupdate(LATCHA_FDSELALL, 0xf - (1 << drive));
-
-	/* restore track register to saved value */
-	FDC1772_WRITE(FDC1772REG_TRACK, unit[drive].track);
-	udelay(25);
-
-	SelectedDrive = drive;
-}
-
-
-/* Deselect both drives. */
-
-static void fd_deselect(void)
-{
-	unsigned long flags;
-
-	DPRINT(("fd_deselect\n"));
-
-	oldlatch_aupdate(LATCHA_FDSELALL | LATCHA_MOTOR | LATCHA_INUSE, 0xf | LATCHA_MOTOR | LATCHA_INUSE);
-
-	SelectedDrive = -1;
-}
-
-
-/* This timer function deselects the drives when the FDC1772 switched the
- * motor off. The deselection cannot happen earlier because the FDC1772
- * counts the index signals, which arrive only if one drive is selected.
- */
-
-static void fd_motor_off_timer(unsigned long dummy)
-{
-	unsigned long flags;
-	unsigned char status;
-	int delay;
-
-	del_timer(&motor_off_timer);
-
-	if (SelectedDrive < 0)
-		/* no drive selected, needn't deselect anyone */
-		return;
-
-	save_flags(flags);
-	cli();
-
-	if (fdc_busy)		/* was stdma_islocked */
-		goto retry;
-
-	status = FDC1772_READ(FDC1772REG_STATUS);
-
-	if (!(status & 0x80)) {
-		/*
-		 * motor already turned off by FDC1772 -> deselect drives
-		 * In actual fact its this deselection which turns the motor
-		 * off on the Arc, since the motor control is actually on
-		 * Latch A
-		 */
-		DPRINT(("fdc1772: deselecting in fd_motor_off_timer\n"));
-		fd_deselect();
-		MotorOn = 0;
-		restore_flags(flags);
-		return;
-	}
-	/* not yet off, try again */
-
-retry:
-	restore_flags(flags);
-	/* Test again later; if tested too often, it seems there is no disk
-	 * in the drive and the FDC1772 will leave the motor on forever (or,
-	 * at least until a disk is inserted). So we'll test only twice
-	 * per second from then on...
-	 */
-	delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ?
-	    (++MotorOffTrys, HZ / 20) : HZ / 2;
-	START_MOTOR_OFF_TIMER(delay);
-}
-
-
-/* This function is repeatedly called to detect disk changes (as good
- * as possible) and keep track of the current state of the write protection.
- */
-
-static void check_change(unsigned long dummy)
-{
-	static int drive = 0;
-
-	unsigned long flags;
-	int stat;
-
-	if (fdc_busy)
-		return;		/* Don't start poking about if the fdc is busy */
-
-	return;			/* let's just forget it for the mo DAG */
-
-	if (++drive > 1 || !unit[drive].connected)
-		drive = 0;
-
-	save_flags(flags);
-	cli();
-
-	if (!stdma_islocked()) {
-		stat = !!(FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_WPROT);
-
-		/* The idea here is that if the write protect line has changed then
-		the disc must have changed */
-		if (stat != unit[drive].wpstat) {
-			DPRINT(("wpstat[%d] = %d\n", drive, stat));
-			unit[drive].wpstat = stat;
-			set_bit(drive, &changed_floppies);
-		}
-	}
-	restore_flags(flags);
-
-	START_CHECK_CHANGE_TIMER(CHECK_CHANGE_DELAY);
-}
-
-
-/* Handling of the Head Settling Flag: This flag should be set after each
- * seek operation, because we don't use seeks with verify.
- */
-
-static inline void set_head_settle_flag(void)
-{
-	HeadSettleFlag = FDC1772CMDADD_E;
-}
-
-static inline int get_head_settle_flag(void)
-{
-	int tmp = HeadSettleFlag;
-	HeadSettleFlag = 0;
-	return (tmp);
-}
-
-
-
-
-/* General Interrupt Handling */
-
-static inline void copy_buffer(void *from, void *to)
-{
-	ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
-	int cnt;
-
-	for (cnt = 512 / 4; cnt; cnt--)
-		*p2++ = *p1++;
-}
-
-static void (*FloppyIRQHandler) (int status) = NULL;
-
-static void floppy_irqconsequencehandler(void)
-{
-	unsigned char status;
-	void (*handler) (int);
-
-	fdc1772_fdc_int_done = 0;
-
-	handler = FloppyIRQHandler;
-	FloppyIRQHandler = NULL;
-
-	if (handler) {
-		nop();
-		status = (unsigned char) fdc1772_comendstatus;
-		DPRINT(("FDC1772 irq, status = %02x handler = %08lx\n", (unsigned int) status, (unsigned long) handler));
-		handler(status);
-	} else {
-		DPRINT(("FDC1772 irq, no handler status=%02x\n", fdc1772_comendstatus));
-	}
-	DPRINT(("FDC1772 irq: end of floppy_irq\n"));
-}
-
-
-/* Error handling: If some error happened, retry some times, then
- * recalibrate, then try again, and fail after MAX_ERRORS.
- */
-
-static void fd_error(void)
-{
-	printk("FDC1772: fd_error\n");
-	/*panic("fd1772: fd_error"); *//* DAG tmp */
-	if (!CURRENT)
-		return;
-	CURRENT->errors++;
-	if (CURRENT->errors >= MAX_ERRORS) {
-		printk("fd%d: too many errors.\n", SelectedDrive);
-		end_request(CURRENT, 0);
-	} else if (CURRENT->errors == RECALIBRATE_ERRORS) {
-		printk("fd%d: recalibrating\n", SelectedDrive);
-		if (SelectedDrive != -1)
-			unit[SelectedDrive].track = -1;
-	}
-	redo_fd_request();
-}
-
-
-
-#define	SET_IRQ_HANDLER(proc) do { FloppyIRQHandler = (proc); } while(0)
-
-
-/* do_fd_action() is the general procedure for a fd request: All
- * required parameter settings (drive select, side select, track
- * position) are checked and set if needed. For each of these
- * parameters and the actual reading or writing exist two functions:
- * one that starts the setting (or skips it if possible) and one
- * callback for the "done" interrupt. Each done func calls the next
- * set function to propagate the request down to fd_rwsec_done().
- */
-
-static void do_fd_action(int drive)
-{
-	struct request *req;
-	DPRINT(("do_fd_action unit[drive].track=%d\n", unit[drive].track));
-
-#ifdef TRACKBUFFER
-repeat:
-
-	if (IS_BUFFERED( drive, ReqSide, ReqTrack )) {
-		req = CURRENT;
-		if (ReqCmd == READ) {
-			copy_buffer( SECTOR_BUFFER(ReqSector), ReqData );
-			if (++ReqCnt < req->current_nr_sectors) {
-				/* read next sector */
-				setup_req_params( drive );
-				goto repeat;
-			} else {
-				/* all sectors finished */
-				req->nr_sectors -= req->current_nr_sectors;
-				req->sector += req->current_nr_sectors;
-				end_request(req, 1);
-				redo_fd_request();
-				return;
-			}
-		} else {
-			/* cmd == WRITE, pay attention to track buffer
-			 * consistency! */
-			copy_buffer( ReqData, SECTOR_BUFFER(ReqSector) );
-		}
-	}
-#endif
-
-	if (SelectedDrive != drive) {
-		/*unit[drive].track = -1; DAG */
-		fd_select_drive(drive);
-	};
-
-
-	if (unit[drive].track == -1)
-		fd_calibrate();
-	else if (unit[drive].track != ReqTrack << unit[drive].disktype->stretch)
-		fd_seek();
-	else
-		fd_rwsec();
-}
-
-
-/* Seek to track 0 if the current track is unknown */
-
-static void fd_calibrate(void)
-{
-	DPRINT(("fd_calibrate\n"));
-	if (unit[SelectedDrive].track >= 0) {
-		fd_calibrate_done(0);
-		return;
-	}
-	DPRINT(("fd_calibrate (after track compare)\n"));
-	SET_IRQ_HANDLER(fd_calibrate_done);
-	/* we can't verify, since the speed may be incorrect */
-	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | unit[SelectedDrive].steprate);
-
-	NeedSeek = 1;
-	MotorOn = 1;
-	START_TIMEOUT();
-	/* wait for IRQ */
-}
-
-
-static void fd_calibrate_done(int status)
-{
-	DPRINT(("fd_calibrate_done()\n"));
-	STOP_TIMEOUT();
-
-	/* set the correct speed now */
-	if (status & FDC1772STAT_RECNF) {
-		printk("fd%d: restore failed\n", SelectedDrive);
-		fd_error();
-	} else {
-		unit[SelectedDrive].track = 0;
-		fd_seek();
-	}
-}
-
-
-/* Seek the drive to the requested track. The drive must have been
- * calibrated at some point before this.
- */
-
-static void fd_seek(void)
-{
-	unsigned long flags;
-	DPRINT(("fd_seek() to track %d (unit[SelectedDrive].track=%d)\n", ReqTrack,
-		unit[SelectedDrive].track));
-	if (unit[SelectedDrive].track == ReqTrack <<
-	    unit[SelectedDrive].disktype->stretch) {
-		fd_seek_done(0);
-		return;
-	}
-	FDC1772_WRITE(FDC1772REG_DATA, ReqTrack <<
-		      unit[SelectedDrive].disktype->stretch);
-	udelay(25);
-	save_flags(flags);
-	clf();
-	SET_IRQ_HANDLER(fd_seek_done);
-	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK | unit[SelectedDrive].steprate |
-		/* DAG */
-		(MotorOn?FDC1772CMDADD_H:0));
-
-	restore_flags(flags);
-	MotorOn = 1;
-	set_head_settle_flag();
-	START_TIMEOUT();
-	/* wait for IRQ */
-}
-
-
-static void fd_seek_done(int status)
-{
-	DPRINT(("fd_seek_done()\n"));
-	STOP_TIMEOUT();
-
-	/* set the correct speed */
-	if (status & FDC1772STAT_RECNF) {
-		printk("fd%d: seek error (to track %d)\n",
-		       SelectedDrive, ReqTrack);
-		/* we don't know exactly which track we are on now! */
-		unit[SelectedDrive].track = -1;
-		fd_error();
-	} else {
-		unit[SelectedDrive].track = ReqTrack <<
-		    unit[SelectedDrive].disktype->stretch;
-		NeedSeek = 0;
-		fd_rwsec();
-	}
-}
-
-
-/* This does the actual reading/writing after positioning the head
- * over the correct track.
- */
-
-#ifdef TRACKBUFFER
-static int MultReadInProgress = 0;
-#endif
-
-
-static void fd_rwsec(void)
-{
-	unsigned long paddr, flags;
-	unsigned int rwflag, old_motoron;
-	unsigned int track;
-
-	DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n", ReqSector, ReqCmd == WRITE ? 'w' : 'r'));
-	if (ReqCmd == WRITE) {
-		/*cache_push( (unsigned long)ReqData, 512 ); */
-		paddr = (unsigned long) ReqData;
-		rwflag = 0x100;
-	} else {
-		paddr = (unsigned long) PhysDMABuffer;
-#ifdef TRACKBUFFER
-		if (read_track)
-			paddr = (unsigned long)PhysTrackBuffer;
-#endif
-		rwflag = 0;
-	}
-
-	DPRINT(("fd_rwsec() before sidesel rwflag=%d sec=%d trk=%d\n", rwflag,
-		ReqSector, FDC1772_READ(FDC1772REG_TRACK)));
-	fd_select_side(ReqSide);
-
-	/*DPRINT(("fd_rwsec() before start sector \n")); */
-	/* Start sector of this operation */
-#ifdef TRACKBUFFER
-	FDC1772_WRITE( FDC1772REG_SECTOR, !read_track ? ReqSector : 1 );
-#else
-	FDC1772_WRITE( FDC1772REG_SECTOR, ReqSector );
-#endif
-
-	/* Cheat for track if stretch != 0 */
-	if (unit[SelectedDrive].disktype->stretch) {
-		track = FDC1772_READ(FDC1772REG_TRACK);
-		FDC1772_WRITE(FDC1772REG_TRACK, track >>
-			      unit[SelectedDrive].disktype->stretch);
-	}
-	udelay(25);
-
-	DPRINT(("fd_rwsec() before setup DMA \n"));
-	/* Setup DMA - Heavily modified by DAG */
-	save_flags(flags);
-	clf();
-	disable_dma(FLOPPY_DMA);
-	set_dma_mode(FLOPPY_DMA, rwflag ? DMA_MODE_WRITE : DMA_MODE_READ);
-	set_dma_addr(FLOPPY_DMA, (long) paddr);		/* DAG - changed from Atari specific */
-#ifdef TRACKBUFFER
-	set_dma_count(FLOPPY_DMA,(!read_track ? 1 : unit[SelectedDrive].disktype->spt)*512);
-#else
-	set_dma_count(FLOPPY_DMA, 512);		/* Block/sector size - going to have to change */
-#endif
-	SET_IRQ_HANDLER(fd_rwsec_done);
-	/* Turn on dma int */
-	enable_dma(FLOPPY_DMA);
-	/* Now give it something to do */
-	FDC1772_WRITE(FDC1772REG_CMD, (rwflag ? (FDC1772CMD_WRSEC | FDC1772CMDADD_P) : 
-#ifdef TRACKBUFFER
-	      (FDC1772CMD_RDSEC | (read_track ? FDC1772CMDADD_M : 0) |
-	      /* Hmm - the idea here is to stop the FDC spinning the disc
-	      up when we know that we already still have it spinning */
-	      (MotorOn?FDC1772CMDADD_H:0))
-#else
-	      FDC1772CMD_RDSEC
-#endif
-		));
-
-	restore_flags(flags);
-	DPRINT(("fd_rwsec() after DMA setup flags=0x%08x\n", flags));
-	/*sti(); *//* DAG - Hmm */
-	/* Hmm - should do something DAG */
-	old_motoron = MotorOn;
-	MotorOn = 1;
-	NeedSeek = 1;
-
-	/* wait for interrupt */
-
-#ifdef TRACKBUFFER
-	if (read_track) {
-		/*
-		 * If reading a whole track, wait about one disk rotation and
-		 * then check if all sectors are read. The FDC will even
-		 * search for the first non-existant sector and need 1 sec to
-		 * recognise that it isn't present :-(
-		 */
-		/* 1 rot. + 5 rot.s if motor was off  */
-		mod_timer(&readtrack_timer, jiffies + HZ/5 + (old_motoron ? 0 : HZ));
-		DPRINT(("Setting readtrack_timer to %d @ %d\n",
-			readtrack_timer.expires,jiffies));
-		MultReadInProgress = 1;
-	}
-#endif
-
-	/*DPRINT(("fd_rwsec() before START_TIMEOUT \n")); */
-	START_TIMEOUT();
-	/*DPRINT(("fd_rwsec() after START_TIMEOUT \n")); */
-}
-
-
-#ifdef TRACKBUFFER
-
-static void fd_readtrack_check(unsigned long dummy)
-{
-	unsigned long flags, addr;
-	extern unsigned char *fdc1772_dataaddr;
-
-	DPRINT(("fd_readtrack_check @ %d\n",jiffies));
-
-	save_flags(flags);
-	clf();
-
-	del_timer( &readtrack_timer );
-
-	if (!MultReadInProgress) {
-		/* This prevents a race condition that could arise if the
-		 * interrupt is triggered while the calling of this timer
-		 * callback function takes place. The IRQ function then has
-		 * already cleared 'MultReadInProgress'  when control flow
-		 * gets here.
-		 */
-		restore_flags(flags);
-		return;
-	}
-
-	/* get the current DMA address */
-	addr=(unsigned long)fdc1772_dataaddr; /* DAG - ? */
-	DPRINT(("fd_readtrack_check: addr=%x PhysTrackBuffer=%x\n",addr,PhysTrackBuffer));
-
-	if (addr >= (unsigned int)PhysTrackBuffer + unit[SelectedDrive].disktype->spt*512) {
-		/* already read enough data, force an FDC interrupt to stop
-		 * the read operation
-		 */
-		SET_IRQ_HANDLER( NULL );
-		restore_flags(flags);
-		DPRINT(("fd_readtrack_check(): done\n"));
-		FDC1772_WRITE( FDC1772REG_CMD, FDC1772CMD_FORCI );
-		udelay(25);
-
-		/* No error until now -- the FDC would have interrupted
-		 * otherwise!
-		 */
-		fd_rwsec_done( 0 );
-	} else {
-		/* not yet finished, wait another tenth rotation */
-		restore_flags(flags);
-		DPRINT(("fd_readtrack_check(): not yet finished\n"));
-		readtrack_timer.expires = jiffies + HZ/5/10;
-		add_timer( &readtrack_timer );
-	}
-}
-
-#endif
-
-static void fd_rwsec_done(int status)
-{
-	unsigned int track;
-
-	DPRINT(("fd_rwsec_done() status=%d @ %d\n", status,jiffies));
-
-#ifdef TRACKBUFFER
-	if (read_track && !MultReadInProgress)
-		return;
-
-	MultReadInProgress = 0;
-
-	STOP_TIMEOUT();
-
-	if (read_track)
-		del_timer( &readtrack_timer );
-#endif
-
-
-	/* Correct the track if stretch != 0 */
-	if (unit[SelectedDrive].disktype->stretch) {
-		track = FDC1772_READ(FDC1772REG_TRACK);
-		FDC1772_WRITE(FDC1772REG_TRACK, track <<
-			      unit[SelectedDrive].disktype->stretch);
-	}
-	if (ReqCmd == WRITE && (status & FDC1772STAT_WPROT)) {
-		printk("fd%d: is write protected\n", SelectedDrive);
-		goto err_end;
-	}
-	if ((status & FDC1772STAT_RECNF)
-#ifdef TRACKBUFFER
-	    /* RECNF is no error after a multiple read when the FDC
-	     * searched for a non-existant sector!
-	     */
-	    && !(read_track &&
-	       FDC1772_READ(FDC1772REG_SECTOR) > unit[SelectedDrive].disktype->spt)
-#endif
-	    ) {
-		if (Probing) {
-			if (unit[SelectedDrive].disktype > disk_type) {
-				/* try another disk type */
-				unit[SelectedDrive].disktype--;
-				set_capacity(disks[SelectedDrive],
-				    unit[SelectedDrive].disktype->blocks);
-			} else
-				Probing = 0;
-		} else {
-			/* record not found, but not probing. Maybe stretch wrong ? Restart probing */
-			if (unit[SelectedDrive].autoprobe) {
-				unit[SelectedDrive].disktype = disk_type + NUM_DISK_TYPES - 1;
-				set_capacity(disks[SelectedDrive],
-				    unit[SelectedDrive].disktype->blocks);
-				Probing = 1;
-			}
-		}
-		if (Probing) {
-			setup_req_params(SelectedDrive);
-#ifdef TRACKBUFFER
-			BufferDrive = -1;
-#endif
-			do_fd_action(SelectedDrive);
-			return;
-		}
-		printk("fd%d: sector %d not found (side %d, track %d)\n",
-		       SelectedDrive, FDC1772_READ(FDC1772REG_SECTOR), ReqSide, ReqTrack);
-		goto err_end;
-	}
-	if (status & FDC1772STAT_CRC) {
-		printk("fd%d: CRC error (side %d, track %d, sector %d)\n",
-		       SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
-		goto err_end;
-	}
-	if (status & FDC1772STAT_LOST) {
-		printk("fd%d: lost data (side %d, track %d, sector %d)\n",
-		       SelectedDrive, ReqSide, ReqTrack, FDC1772_READ(FDC1772REG_SECTOR));
-		goto err_end;
-	}
-	Probing = 0;
-
-	if (ReqCmd == READ) {
-#ifdef TRACKBUFFER
-		if (!read_track) {
-			/*cache_clear (PhysDMABuffer, 512);*/
-			copy_buffer (DMABuffer, ReqData);
-		} else {
-			/*cache_clear (PhysTrackBuffer, FD1772_MAX_SECTORS * 512);*/
-			BufferDrive = SelectedDrive;
-			BufferSide  = ReqSide;
-			BufferTrack = ReqTrack;
-			copy_buffer (SECTOR_BUFFER (ReqSector), ReqData);
-		}
-#else
-		/*cache_clear( PhysDMABuffer, 512 ); */
-		copy_buffer(DMABuffer, ReqData);
-#endif
-	}
-	if (++ReqCnt < CURRENT->current_nr_sectors) {
-		/* read next sector */
-		setup_req_params(SelectedDrive);
-		do_fd_action(SelectedDrive);
-	} else {
-		/* all sectors finished */
-		CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
-		CURRENT->sector += CURRENT->current_nr_sectors;
-		end_request(CURRENT, 1);
-		redo_fd_request();
-	}
-	return;
-
-err_end:
-#ifdef TRACKBUFFER
-	BufferDrive = -1;
-#endif
-
-	fd_error();
-}
-
-
-static void fd_times_out(unsigned long dummy)
-{
-	SET_IRQ_HANDLER(NULL);
-	/* If the timeout occurred while the readtrack_check timer was
-	 * active, we need to cancel it, else bad things will happen */
-	del_timer( &readtrack_timer ); 
-	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
-	udelay(25);
-
-	printk("floppy timeout\n");
-	STOP_TIMEOUT();		/* hmm - should we do this ? */
-	fd_error();
-}
-
-
-/* The (noop) seek operation here is needed to make the WP bit in the
- * FDC1772 status register accessible for check_change. If the last disk
- * operation would have been a RDSEC, this bit would always read as 0
- * no matter what :-( To save time, the seek goes to the track we're
- * already on.
- */
-
-static void finish_fdc(void)
-{
-	/* DAG - just try without this dummy seek! */
-	finish_fdc_done(0);
-	return;
-
-	if (!NeedSeek) {
-		finish_fdc_done(0);
-	} else {
-		DPRINT(("finish_fdc: dummy seek started\n"));
-		FDC1772_WRITE(FDC1772REG_DATA, unit[SelectedDrive].track);
-		SET_IRQ_HANDLER(finish_fdc_done);
-		FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
-		MotorOn = 1;
-		START_TIMEOUT();
-		/* we must wait for the IRQ here, because the ST-DMA is
-		 * released immediately afterwards and the interrupt may be
-		 * delivered to the wrong driver.
-		 */
-	}
-}
-
-
-static void finish_fdc_done(int dummy)
-{
-	unsigned long flags;
-
-	DPRINT(("finish_fdc_done entered\n"));
-	STOP_TIMEOUT();
-	NeedSeek = 0;
-
-	if (timer_pending(&fd_timer) &&
-	    time_after(jiffies + 5, fd_timer.expires)) 
-		/* If the check for a disk change is done too early after this
-		 * last seek command, the WP bit still reads wrong :-((
-		 */
-		mod_timer(&fd_timer, jiffies + 5);
-	else {
-		/*      START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
-	};
-	del_timer(&motor_off_timer);
-	START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
-
-	save_flags(flags);
-	cli();
-	/* stdma_release(); - not sure if I should do something DAG  */
-	fdc_busy = 0;
-	wake_up(&fdc_wait);
-	restore_flags(flags);
-
-	DPRINT(("finish_fdc() finished\n"));
-}
-
-
-/* Prevent "aliased" accesses. */
-static int fd_ref[4];
-static int fd_device[4];
-
-/* dummy for blk.h */
-static void floppy_off(unsigned int nr)
-{
-}
-
-
-/* On the old arcs write protect depends on the particular model
-   of machine.  On the A310, R140, and A440 there is a disc changed
-   detect, however on the A4x0/1 range there is not.  There
-   is nothing to tell you which machine your on.
-   At the moment I'm just marking changed always. I've
-   left the Atari's 'change on write protect change' code in this
-   part (but nothing sets it).
-   RiscOS apparently checks the disc serial number etc. to detect changes
-   - but if it sees a disc change line go high (?) it flips to using
-   it. Well  maybe I'll add that in the future (!?)
-*/
-static int check_floppy_change(struct gendisk *disk)
-{
-	struct archy_floppy_struct *p = disk->private_data;
-	unsigned int drive = p - unit;
-
-	if (test_bit(drive, &fake_change)) {
-		/* simulated change (e.g. after formatting) */
-		return 1;
-	}
-	if (test_bit(drive, &changed_floppies)) {
-		/* surely changed (the WP signal changed at least once) */
-		return 1;
-	}
-	if (p->wpstat) {
-		/* WP is on -> could be changed: to be sure, buffers should be
-		   * invalidated...
-		 */
-		return 1;
-	}
-	return 1; /* DAG - was 0 */
-}
-
-static int floppy_revalidate(struct gendisk *disk)
-{
-	struct archy_floppy_struct *p = disk->private_data;
-	unsigned int drive = p - unit;
-
-	if (test_bit(drive, &changed_floppies) || test_bit(drive, &fake_change)
-	    || unit[drive].disktype == 0) {
-#ifdef TRACKBUFFER
-		BufferDrive = -1;
-#endif
-		clear_bit(drive, &fake_change);
-		clear_bit(drive, &changed_floppies);
-		p->disktype = 0;
-	}
-	return 0;
-}
-
-/* This sets up the global variables describing the current request. */
-
-static void setup_req_params(int drive)
-{
-	int block = ReqBlock + ReqCnt;
-
-	ReqTrack = block / unit[drive].disktype->spt;
-	ReqSector = block - ReqTrack * unit[drive].disktype->spt + 1;
-	ReqSide = ReqTrack & 1;
-	ReqTrack >>= 1;
-	ReqData = ReqBuffer + 512 * ReqCnt;
-
-#ifdef TRACKBUFFER
-	read_track = (ReqCmd == READ && CURRENT->errors == 0);
-#endif
-
-	DPRINT(("Request params: Si=%d Tr=%d Se=%d Data=%08lx\n", ReqSide,
-		ReqTrack, ReqSector, (unsigned long) ReqData));
-}
-
-
-static void redo_fd_request(void)
-{
-	int drive, type;
-	struct archy_floppy_struct *floppy;
-
-	DPRINT(("redo_fd_request: CURRENT=%p dev=%s CURRENT->sector=%ld\n",
-		CURRENT, CURRENT ? CURRENT->rq_disk->disk_name : "",
-		CURRENT ? CURRENT->sector : 0));
-
-repeat:
-
-	if (!CURRENT)
-		goto the_end;
-
-	floppy = CURRENT->rq_disk->private_data;
-	drive = floppy - unit;
-	type = fd_device[drive];
-
-	if (!floppy->connected) {
-		/* drive not connected */
-		printk("Unknown Device: fd%d\n", drive);
-		end_request(CURRENT, 0);
-		goto repeat;
-	}
-	if (type == 0) {
-		if (!floppy->disktype) {
-			Probing = 1;
-			floppy->disktype = disk_type + NUM_DISK_TYPES - 1;
-			set_capacity(disks[drive], floppy->disktype->blocks);
-			floppy->autoprobe = 1;
-		}
-	} else {
-		/* user supplied disk type */
-		--type;
-		if (type >= NUM_DISK_TYPES) {
-			printk("fd%d: invalid disk format", drive);
-			end_request(CURRENT, 0);
-			goto repeat;
-		}
-		floppy->disktype = &disk_type[type];
-		set_capacity(disks[drive], floppy->disktype->blocks);
-		floppy->autoprobe = 0;
-	}
-
-	if (CURRENT->sector + 1 > floppy->disktype->blocks) {
-		end_request(CURRENT, 0);
-		goto repeat;
-	}
-	/* stop deselect timer */
-	del_timer(&motor_off_timer);
-
-	ReqCnt = 0;
-	ReqCmd = rq_data_dir(CURRENT);
-	ReqBlock = CURRENT->sector;
-	ReqBuffer = CURRENT->buffer;
-	setup_req_params(drive);
-	do_fd_action(drive);
-
-	return;
-
-the_end:
-	finish_fdc();
-}
-
-static void fd1772_checkint(void)
-{
-	extern int fdc1772_bytestogo;
-
-	/*printk("fd1772_checkint %d\n",fdc1772_fdc_int_done);*/
-	if (fdc1772_fdc_int_done)
-		floppy_irqconsequencehandler();
-	if ((MultReadInProgress) && (fdc1772_bytestogo==0)) fd_readtrack_check(0);
-	if (fdc_busy) {
-		schedule_work(&fd1772_tq);
-	}
-}
-
-static void do_fd_request(struct request_queue* q)
-{
-	unsigned long flags;
-
-	DPRINT(("do_fd_request for pid %d\n", current->pid));
-	if (fdc_busy) return;
-	save_flags(flags);
-	cli();
-	wait_event(fdc_wait, !fdc_busy);
-	fdc_busy = 1;
-	ENABLE_IRQ();
-	restore_flags(flags);
-
-	fdc1772_fdc_int_done = 0;
-
-	redo_fd_request();
-
-	schedule_work(&fd1772_tq);
-}
-
-
-static int invalidate_drive(struct block_device *bdev)
-{
-	struct archy_floppy_struct *p = bdev->bd_disk->private_data;
-	/* invalidate the buffer track to force a reread */
-#ifdef TRACKBUFFER
-	BufferDrive = -1;
-#endif
-
-	set_bit(p - unit, &fake_change);
-	return 0;
-}
-
-static int fd_ioctl(struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long param)
-{
-	struct block_device *bdev = inode->i_bdev;
-
-	switch (cmd) {
-	case FDFMTEND:
-	case FDFLUSH:
-		invalidate_drive(bdev);
-		check_disk_change(bdev);
-	case FDFMTBEG:
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-
-/* Initialize the 'unit' variable for drive 'drive' */
-
-static void fd_probe(int drive)
-{
-	unit[drive].connected = 0;
-	unit[drive].disktype = NULL;
-
-	if (!fd_test_drive_present(drive))
-		return;
-
-	unit[drive].connected = 1;
-	unit[drive].track = -1; /* If we put the auto detect back in this can go to 0 */
-	unit[drive].steprate = FDC1772STEP_6;
-	MotorOn = 1;		/* from probe restore operation! */
-}
-
-
-/* This function tests the physical presence of a floppy drive (not
- * whether a disk is inserted). This is done by issuing a restore
- * command, waiting max. 2 seconds (that should be enough to move the
- * head across the whole disk) and looking at the state of the "TR00"
- * signal. This should now be raised if there is a drive connected
- * (and there is no hardware failure :-) Otherwise, the drive is
- * declared absent.
- */
-
-static int fd_test_drive_present(int drive)
-{
-	unsigned long timeout;
-	unsigned char status;
-	int ok;
-
-	printk("fd_test_drive_present %d\n", drive);
-	if (drive > 1)
-		return (0);
-	return (1);		/* Simple hack for the moment - the autodetect doesn't seem to work on arc */
-	fd_select_drive(drive);
-
-	/* disable interrupt temporarily */
-	DISABLE_IRQ();
-	FDC1772_WRITE(FDC1772REG_TRACK, 0x00);	/* was ff00 why? */
-	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6);
-
-	/*printk("fd_test_drive_present: Going into timeout loop\n"); */
-	for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; time_before(jiffies, timeout);) {
-		/*  What does this piece of atariism do? - query for an interrupt? */
-		/*  if (!(mfp.par_dt_reg & 0x20))
-		   break; */
-		/* Well this is my nearest guess - quit when we get an FDC interrupt */
-		if (ioc_readb(IOC_FIQSTAT) & 2)
-			break;
-	}
-
-	/*printk("fd_test_drive_present: Coming out of timeout loop\n"); */
-	status = FDC1772_READ(FDC1772REG_STATUS);
-	ok = (status & FDC1772STAT_TR00) != 0;
-
-	/*printk("fd_test_drive_present: ok=%d\n",ok); */
-	/* force interrupt to abort restore operation (FDC1772 would try
-	 * about 50 seconds!) */
-	FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
-	udelay(500);
-	status = FDC1772_READ(FDC1772REG_STATUS);
-	udelay(20);
-	/*printk("fd_test_drive_present: just before OK code %d\n",ok); */
-
-	if (ok) {
-		/* dummy seek command to make WP bit accessible */
-		FDC1772_WRITE(FDC1772REG_DATA, 0);
-		FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_SEEK);
-		printk("fd_test_drive_present: just before wait for int\n");
-		/* DAG: Guess means wait for interrupt */
-		while (!(ioc_readb(IOC_FIQSTAT) & 2));
-		printk("fd_test_drive_present: just after wait for int\n");
-		status = FDC1772_READ(FDC1772REG_STATUS);
-	}
-	printk("fd_test_drive_present: just before ENABLE_IRQ\n");
-	ENABLE_IRQ();
-	printk("fd_test_drive_present: about to return\n");
-	return (ok);
-}
-
-
-/* Look how many and which kind of drives are connected. If there are
- * floppies, additionally start the disk-change and motor-off timers.
- */
-
-static void config_types(void)
-{
-	int drive, cnt = 0;
-
-	printk("Probing floppy drive(s):\n");
-	for (drive = 0; drive < FD_MAX_UNITS; drive++) {
-		fd_probe(drive);
-		if (unit[drive].connected) {
-			printk("fd%d\n", drive);
-			++cnt;
-		}
-	}
-
-	if (FDC1772_READ(FDC1772REG_STATUS) & FDC1772STAT_BUSY) {
-		/* If FDC1772 is still busy from probing, give it another FORCI
-		 * command to abort the operation. If this isn't done, the FDC1772
-		 * will interrupt later and its IRQ line stays low, because
-		 * the status register isn't read. And this will block any
-		 * interrupts on this IRQ line :-(
-		 */
-		FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
-		udelay(500);
-		FDC1772_READ(FDC1772REG_STATUS);
-		udelay(20);
-	}
-	if (cnt > 0) {
-		START_MOTOR_OFF_TIMER(FD_MOTOR_OFF_DELAY);
-		if (cnt == 1)
-			fd_select_drive(0);
-		/*START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY ); */
-	}
-}
-
-/*
- * floppy_open check for aliasing (/dev/fd0 can be the same as
- * /dev/PS0 etc), and disallows simultaneous access to the same
- * drive with different device numbers.
- */
-
-static int floppy_open(struct inode *inode, struct file *filp)
-{
-	int drive = iminor(inode) & 3;
-	int type =  iminor(inode) >> 2;
-	int old_dev = fd_device[drive];
-
-	if (fd_ref[drive] && old_dev != type)
-		return -EBUSY;
-
-	if (fd_ref[drive] == -1 || (fd_ref[drive] && filp->f_flags & O_EXCL))
-		return -EBUSY;
-
-	if (filp->f_flags & O_EXCL)
-		fd_ref[drive] = -1;
-	else
-		fd_ref[drive]++;
-
-	fd_device[drive] = type;
-
-	if (filp->f_flags & O_NDELAY)
-		return 0;
-
-	if (filp->f_mode & 3) {
-		check_disk_change(inode->i_bdev);
-		if (filp->f_mode & 2) {
-			if (unit[drive].wpstat) {
-				floppy_release(inode, filp);
-				return -EROFS;
-			}
-		}
-	}
-	return 0;
-}
-
-
-static int floppy_release(struct inode *inode, struct file *filp)
-{
-	int drive = iminor(inode) & 3;
-
-	if (fd_ref[drive] < 0)
-		fd_ref[drive] = 0;
-	else if (!fd_ref[drive]--) {
-		printk("floppy_release with fd_ref == 0");
-		fd_ref[drive] = 0;
-	}
-
-	return 0;
-}
-
-static struct block_device_operations floppy_fops =
-{
-	.open		= floppy_open,
-	.release	= floppy_release,
-	.ioctl		= fd_ioctl,
-	.media_changed	= check_floppy_change,
-	.revalidate_disk= floppy_revalidate,
-};
-
-static struct kobject *floppy_find(dev_t dev, int *part, void *data)
-{
-	int drive = *part & 3;
-	if ((*part >> 2) > NUM_DISK_TYPES || drive >= FD_MAX_UNITS)
-		return NULL;
-	*part = 0;
-	return get_disk(disks[drive]);
-}
-
-int fd1772_init(void)
-{
-	static DEFINE_SPINLOCK(lock);
-	int i, err = -ENOMEM;
-
-	if (!machine_is_archimedes())
-		return 0;
-
-	for (i = 0; i < FD_MAX_UNITS; i++) {
-		disks[i] = alloc_disk(1);
-		if (!disks[i])
-			goto err_disk;
-	}
-
-	err = register_blkdev(MAJOR_NR, "fd");
-	if (err)
-		goto err_disk;
-
-	err = -EBUSY;
-	if (request_dma(FLOPPY_DMA, "fd1772")) {
-		printk("Unable to grab DMA%d for the floppy (1772) driver\n", FLOPPY_DMA);
-		goto err_blkdev;
-	};
-
-	if (request_dma(FIQ_FD1772, "fd1772 end")) {
-		printk("Unable to grab DMA%d for the floppy (1772) driver\n", FIQ_FD1772);
-		goto err_dma1;
-	};
-
-	/* initialize variables */
-	SelectedDrive = -1;
-#ifdef TRACKBUFFER
-	BufferDrive = BufferSide = BufferTrack = -1;
-	/* Atari uses 512 - I want to eventually cope with 1K sectors */
-	DMABuffer = kmalloc((FD1772_MAX_SECTORS+1)*512,GFP_KERNEL);
-	TrackBuffer = DMABuffer + 512;
-#else
-	/* Allocate memory for the DMAbuffer - on the Atari this takes it
-	   out of some special memory... */
-	DMABuffer = kmalloc(2048);	/* Copes with pretty large sectors */
-#endif
-	err = -ENOMEM;
-	if (!DMAbuffer)
-		goto err_dma2;
-
-	enable_dma(FIQ_FD1772);	/* This inserts a call to our command end routine */
-
-	floppy_queue = blk_init_queue(do_fd_request, &lock);
-	if (!floppy_queue)
-		goto err_queue;
-
-	for (i = 0; i < FD_MAX_UNITS; i++) {
-		unit[i].track = -1;
-		disks[i]->major = MAJOR_NR;
-		disks[i]->first_minor = 0;
-		disks[i]->fops = &floppy_fops;
-		sprintf(disks[i]->disk_name, "fd%d", i);
-		disks[i]->private_data = &unit[i];
-		disks[i]->queue = floppy_queue;
-		set_capacity(disks[i], MAX_DISK_SIZE * 2);
-	}
-	blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE,
-				floppy_find, NULL, NULL);
-
-	for (i = 0; i < FD_MAX_UNITS; i++)
-		add_disk(disks[i]);
-
-	config_types();
-
-	return 0;
-
- err_queue:
-	kfree(DMAbuffer);
- err_dma2:
-	free_dma(FIQ_FD1772);
-
- err_dma1:
-	free_dma(FLOPPY_DMA);
-
- err_blkdev:
-	unregister_blkdev(MAJOR_NR, "fd");
-
- err_disk:
-	while (i--)
-		put_disk(disks[i]);
-	return err;
-}
diff --git a/drivers/acorn/block/fd1772dma.S b/drivers/acorn/block/fd1772dma.S
deleted file mode 100644
index 7964435443ec..000000000000
--- a/drivers/acorn/block/fd1772dma.S
+++ /dev/null
@@ -1,100 +0,0 @@
-#include <asm/hardware.h>
-
-@ Code for DMA with the 1772 fdc
-.text
-
-
-  .global fdc1772_dataaddr
-fdc1772_fiqdata:
-@ Number of bytes left to DMA
-  .global fdc1772_bytestogo
-fdc1772_bytestogo:
-  .word 0
-@ Place to put/get data from in DMA
-  .global fdc1772_dataaddr
-fdc1772_dataaddr:
-  .word 0
-  
-  .global fdc1772_fdc_int_done
-fdc1772_fdc_int_done:
-  .word 0
-  .global fdc1772_comendstatus
-fdc1772_comendstatus:
-  .word 0
-
-@ We hang this off DMA channel 1
-    .global fdc1772_comendhandler
-fdc1772_comendhandler:
-  mov      r8,#IOC_BASE
-  ldrb     r9,[r8,#0x34]    @ IOC FIQ status
-  tst      r9,#2
-  subeqs   pc,r14,#4        @ should I leave a space here
-  orr      r9,r8,#0x10000   @ FDC base
-  adr      r8,fdc1772_fdc_int_done
-  ldrb     r10,[r9,#0]  @ FDC status
-  mov      r9,#1        @ Got a FIQ flag
-  stmia    r8,{r9,r10}
-  subs     pc,r14,#4
-
-
-    .global fdc1772_dma_read
-fdc1772_dma_read:
-  mov      r8,#IOC_BASE
-  ldrb     r9,[r8,#0x34]    @ IOC FIQ status
-  tst      r9,#1
-  beq      fdc1772_dma_read_notours
-  orr      r8,r8,#0x10000   @ FDC base
-  ldrb     r10,[r8,#0xc]   @ Read from FDC data reg (also clears interrupt)
-  ldmia    r11,{r8,r9}
-  subs     r8,r8,#1        @ One less byte to go
-  @ If there was somewhere for this data to go then store it and update pointers
-  strplb   r10,[r9],#1     @ Store the data and increment the pointer
-  stmplia  r11,{r8,r9}     @ Update count/pointers
-  @ Handle any other interrupts if there are any
-fdc1772_dma_read_notours:
-  @ Cant branch because this code has been copied down to the FIQ vector
-  ldr pc,[pc,#-4]
-  .word fdc1772_comendhandler
-  .global fdc1772_dma_read_end
-fdc1772_dma_read_end:
-
-    .global fdc1772_dma_write
-fdc1772_dma_write:
-  mov      r8,#IOC_BASE
-  ldrb     r9,[r8,#0x34]    @ IOC FIQ status
-  tst      r9,#1
-  beq      fdc1772_dma_write_notours
-  orr      r8,r8,#0x10000   @ FDC base
-  ldmia    r11,{r9,r10}
-  subs     r9,r9,#1        @ One less byte to go
-  @ If there really is some data then get it, store it and update count
-  ldrplb   r12,[r10],#1
-  strplb   r12,[r8,#0xc]   @ write it to FDC data reg
-  stmplia  r11,{r9,r10}    @ Update count and pointer - should clear interrupt
-  @ Handle any other interrupts
-fdc1772_dma_write_notours:
-  @ Cant branch because this code has been copied down to the FIQ vector
-  ldr pc,[pc,#-4]
-  .word fdc1772_comendhandler
-
-  .global fdc1772_dma_write_end
-fdc1772_dma_write_end:
-  
-
-@ Setup the FIQ R11 to point to the data and store the count, address
-@ for this dma
-@ R0=count
-@ R1=address
-  .global fdc1772_setupdma
-fdc1772_setupdma:
-	@ The big job is flipping in and out of FIQ mode
-	adr	r2,fdc1772_fiqdata	@ This is what we really came here for
-  stmia  r2,{r0,r1}
-	mov	r3, pc
-	teqp	pc,#0x0c000001	@ Disable FIQs, IRQs and switch to FIQ mode
-	mov	r0,r0      	@ NOP
-	mov r11,r2
-	teqp	r3,#0		@ Normal mode
-	mov	r0,r0		@ NOP
-  mov pc,r14
-
diff --git a/drivers/acorn/block/mfm.S b/drivers/acorn/block/mfm.S
deleted file mode 100644
index c90cbd41ce21..000000000000
--- a/drivers/acorn/block/mfm.S
+++ /dev/null
@@ -1,162 +0,0 @@
-@ Read/Write DMA code for the ST506/MFM hard drive controllers on the A400 Acorn Archimedes
-@   motherboard and on ST506 expansion podules.
-@ (c) David Alan Gilbert (linux@treblig.org) 1996-1999
-
-#include <asm/assembler.h>
- 
-hdc63463_irqdata:
-@ Controller base address
-  .global hdc63463_baseaddress
-hdc63463_baseaddress:
-  .word 0
-
-  .global hdc63463_irqpolladdress
-hdc63463_irqpolladdress:
-  .word 0
- 
-  .global hdc63463_irqpollmask
-hdc63463_irqpollmask:
-  .word 0
-
-@ where to read/write data  from the kernel data space
-  .global hdc63463_dataptr
-hdc63463_dataptr:
-  .word 0
-
-@ Number of bytes left to transfer
-  .global hdc63463_dataleft
-hdc63463_dataleft:
-  .word 0
-
-@ -------------------------------------------------------------------------
-@ hdc63463_writedma: DMA from host to controller
-@  internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask
-@                      r3=data ptr, r4=data left, r5,r6=temporary
-  .global hdc63463_writedma
-hdc63463_writedma:
-  stmfd sp!,{r4-r7}
-  adr r5,hdc63463_irqdata
-  ldmia r5,{r0,r1,r2,r3,r4}
-
-writedma_again:
-
-  @ test number of remaining bytes to transfer
-  cmp r4,#0
-  beq writedma_end
-  bmi writedma_end
-
-  @ Check the hdc is interrupting
-  ldrb r5,[r1,#0]
-  tst r5,r2
-  beq writedma_end
-
-  @ Transfer a block of upto 256 bytes
-  cmp r4,#256
-  movlt r7,r4
-  movge r7,#256
-
-  @ Check the hdc is still busy and command has not ended and no errors
-  ldr r5,[r0,#32]     @ Status reg - 16 bit - its the top few bits which are status
-  @ think we should continue DMA until it drops busy - perhaps this was
-  @ the main problem with corrected errors causing a hang
-  @tst r5,#0x3c00        @ Test for things which should be off
-  @bne writedma_end
-  and r5,r5,#0x8000        @ This is test for things which should be on: Busy
-  cmp r5,#0x8000
-  bne writedma_end 
-
-  @ Bytes remaining at end
-  sub r4,r4,r7
-
-  @ HDC Write register location
-  add r0,r0,#32+8
-
-writedma_loop:
-  @ OK - pretty sure we should be doing this
-
-  ldr r5,[r3],#4          @ Get a word to be written
-  @ get bottom half to be sent first
-  mov r6,r5,lsl#16        @ Separate the first 2 bytes
-  orr r2,r6,r6,lsr #16    @ Duplicate them in the bottom half of the word
-  @ now the top half
-  mov r6,r5,lsr#16        @ Get 2nd 2 bytes
-  orr r6,r6,r6,lsl#16     @ Duplicate
-  @str r6,[r0]       @ to hdc
-  stmia r0,{r2,r6}
-  subs r7,r7,#4           @ Dec. number of bytes left
-  bne writedma_loop
-
-  @ If we were too slow we had better go through again - DAG - took out with new interrupt routine
-  @ sub r0,r0,#32+8
-  @ adr r2,hdc63463_irqdata
-  @ ldr r2,[r2,#8]
-  @ b writedma_again
-
-writedma_end:
-  adr r5,hdc63463_irqdata+12
-  stmia r5,{r3,r4}
-  ldmfd sp!,{r4-r7}
-  RETINSTR(mov,pc,lr)
-
-@ -------------------------------------------------------------------------
-@ hdc63463_readdma: DMA from controller to host
-@  internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask
-@                      r3=data ptr, r4=data left, r5,r6=temporary
-  .global hdc63463_readdma
-hdc63463_readdma:
-  stmfd sp!,{r4-r7}
-  adr r5,hdc63463_irqdata
-  ldmia r5,{r0,r1,r2,r3,r4}
-
-readdma_again:
-  @ test number of remaining bytes to transfer
-  cmp r4,#0
-  beq readdma_end
-  bmi readdma_end
-
-  @ Check the hdc is interrupting
-  ldrb r5,[r1,#0]
-  tst r5,r2
-  beq readdma_end
-
-  @ Check the hdc is still busy and command has not ended and no errors
-  ldr r5,[r0,#32]     @ Status reg - 16 bit - its the top few bits which are status
-  @ think we should continue DMA until it drops busy - perhaps this was
-  @ the main problem with corrected errors causing a hang
-  @tst r5,#0x3c00      @ Test for things which should be off
-  @bne readdma_end
-  and r5,r5,#0x8000        @ This is test for things which should be on: Busy
-  cmp r5,#0x8000
-  bne readdma_end 
-
-  @ Transfer a block of upto 256 bytes
-  cmp r4,#256
-  movlt r7,r4
-  movge r7,#256
-
-  @ Bytes remaining at end
-  sub r4,r4,r7
-
-  @ Set a pointer to the data register in the HDC
-  add r0,r0,#8
-readdma_loop:
-  @ OK - pretty sure we should be doing this
-  ldmia r0,{r5,r6}
-  mov r5,r5,lsl#16
-  mov r6,r6,lsl#16
-  orr r6,r6,r5,lsr #16
-  str r6,[r3],#4
-  subs r7,r7,#4        @ Decrement bytes to go
-  bne readdma_loop
-
-  @ Try reading multiple blocks - if this was fast enough then I do not think
-  @ this should help - NO taken out DAG - new interrupt handler has
-  @ non-consecutive memory blocks
-  @ sub r0,r0,#8
-  @ b readdma_again
-
-readdma_end:
-  adr r5,hdc63463_irqdata+12
-  stmia r5,{r3,r4}
-  ldmfd sp!,{r4-r7}
-  RETINSTR(mov,pc,lr)
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
deleted file mode 100644
index 74058db674db..000000000000
--- a/drivers/acorn/block/mfmhd.c
+++ /dev/null
@@ -1,1385 +0,0 @@
-/*
- * linux/drivers/acorn/block/mfmhd.c
- *
- * Copyright (C) 1995, 1996 Russell King, Dave Alan Gilbert (gilbertd@cs.man.ac.uk)
- *
- * MFM hard drive code [experimental]
- */
-
-/*
- * Change list:
- *
- *  3/2/96:DAG: Started a change list :-)
- *              Set the hardsect_size pointers up since we are running 256 byte
- *                sectors
- *              Added DMA code, put it into the rw_intr
- *              Moved RCAL out of generic interrupt code - don't want to do it
- *                while DMA'ing - its now in individual handlers.
- *              Took interrupt handlers off task queue lists and called
- *                directly - not sure of implications.
- *
- * 18/2/96:DAG: Well its reading OK I think, well enough for image file code
- *              to find the image file; but now I've discovered that I actually
- *              have to put some code in for image files.
- *
- *              Added stuff for image files; seems to work, but I've not
- *              got a multisegment image file (I don't think!).
- *              Put in a hack (yep a real hack) for multiple cylinder reads.
- *              Not convinced its working.
- *
- *  5/4/96:DAG: Added asm/hardware.h and use IOC_ macros
- *              Rewrote dma code in mfm.S (again!) - now takes a word at a time
- *              from main RAM for speed; still doesn't feel speedy!
- *
- * 20/4/96:DAG: After rewriting mfm.S a heck of a lot of times and speeding
- *              things up, I've finally figured out why its so damn slow.
- *              Linux is only reading a block at a time, and so you never
- *              get more than 1K per disc revoloution ~=60K/second.
- *
- * 27/4/96:DAG: On Russell's advice I change ll_rw_blk.c to ask it to
- *              join adjacent blocks together. Everything falls flat on its
- *              face.
- *              Four hours of debugging later; I hadn't realised that
- *              ll_rw_blk would be so generous as to join blocks whose
- *              results aren't going into consecutive buffers.
- * 
- *              OK; severe rehacking of mfm_rw_interrupt; now end_request's
- *              as soon as its DMA'd each request.  Odd thing is that
- *              we are sometimes getting interrupts where we are not transferring
- *              any data; why? Is that what happens when you miss? I doubt
- *              it; are we too fast? No - its just at command ends. Got 240K/s
- *              better than before, but RiscOS hits 480K/s
- *
- * 25/6/96:RMK: Fixed init code to allow the MFM podule to work.  Increased the
- *              number of errors for my Miniscribe drive (8425).
- *
- * 30/6/96:DAG: Russell suggested that a check drive 0 might turn the LEDs off
- *              - so in request_done just before it clears Busy it sends a
- *              check drive 0 - and the LEDs go off!!!!
- *
- *              Added test for mainboard controller. - Removes need for separate
- *              define.
- *
- * 13/7/96:DAG: Changed hardware sectore size to 512 in attempt to make
- *              IM drivers work.
- * 21/7/96:DAG: Took out old image file stuff (accessing it now produces an IO
- *              error.)
- *
- * 17/8/96:DAG: Ran through indent -kr -i8; evil - all my nice 2 character indents
- *              gone :-( Hand modified afterwards.
- *		Took out last remains of the older image map system.
- *
- * 22/9/96:DAG:	Changed mfm.S so it will carry on DMA'ing til; BSY is dropped
- *		Changed mfm_rw_intr so that it doesn't follow the error
- *		code until BSY is dropped. Nope - still broke. Problem
- *		may revolve around when it reads the results for the error
- *		number?
- *
- *16/11/96:DAG:	Modified for 2.0.18; request_irq changed
- *
- *17/12/96:RMK: Various cleanups, reorganisation, and the changes for new IO system.
- *		Improved probe for onboard MFM chip - it was hanging on my A5k.
- *		Added autodetect CHS code such that we don't rely on the presence
- *		of an ADFS boot block.  Added ioport resource manager calls so
- *		that we don't clash with already-running hardware (eg. RiscPC Ether
- *		card slots if someone tries this)!
- *
- * 17/1/97:RMK:	Upgraded to 2.1 kernels.
- *
- *  4/3/98:RMK:	Changed major number to 21.
- *
- * 27/6/98:RMK:	Changed asm/delay.h to linux/delay.h for mdelay().
- */
-
-/*
- * Possible enhancements:
- *  Multi-thread the code so that it is possible that while one drive
- *  is seeking, the other one can be reading data/seeking as well.
- *  This would be a performance boost with dual drive systems.
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/errno.h>
-#include <linux/genhd.h>
-#include <linux/major.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/blkpg.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/dma.h>
-#include <asm/hardware.h>
-#include <asm/ecard.h>
-#include <asm/hardware/ioc.h>
-
-static void (*do_mfm)(void) = NULL;
-static struct request_queue *mfm_queue;
-static DEFINE_SPINLOCK(mfm_lock);
-
-#define MAJOR_NR	MFM_ACORN_MAJOR
-#define QUEUE (mfm_queue)
-#define CURRENT elv_next_request(mfm_queue)
-
-/*
- * Configuration section
- *
- * This is the maximum number of drives that we accept
- */
-#define MFM_MAXDRIVES 2
-/*
- * Linux I/O address of onboard MFM controller or 0 to disable this
- */
-#define ONBOARD_MFM_ADDRESS ((0x002d0000 >> 2) | 0x80000000)
-/*
- * Uncomment this to enable debugging in the MFM driver...
- */
-#ifndef DEBUG
-/*#define DEBUG */
-#endif
-/*
- * End of configuration
- */
-
- 
-/*
- * This structure contains all information to do with a particular physical
- * device.
- */
-struct mfm_info {
-	unsigned char sectors;
-	unsigned char heads;
-	unsigned short cylinders;
-	unsigned short lowcurrent;
-	unsigned short precomp;
-#define NO_TRACK -1
-#define NEED_1_RECAL -2
-#define NEED_2_RECAL -3
-		 int cylinder;
-	struct {
-		char recal;
-		char report;
-		char abort;
-	} errors;
-} mfm_info[MFM_MAXDRIVES];
-
-#define MFM_DRV_INFO mfm_info[raw_cmd.dev]
-
-/* Stuff from the assembly routines */
-extern unsigned int hdc63463_baseaddress;	/* Controller base address */
-extern unsigned int hdc63463_irqpolladdress;	/* Address to read to test for int */
-extern unsigned int hdc63463_irqpollmask;	/* Mask for irq register */
-extern unsigned int hdc63463_dataptr;	/* Pointer to kernel data space to DMA */
-extern int hdc63463_dataleft;	/* Number of bytes left to transfer */
-
-
-
-
-static int lastspecifieddrive;
-static unsigned Busy;
-
-static unsigned int PartFragRead;	/* The number of sectors which have been read
-					   during a partial read split over two
-					   cylinders.  If 0 it means a partial
-					   read did not occur. */
-
-static unsigned int PartFragRead_RestartBlock;	/* Where to restart on a split access */
-static unsigned int PartFragRead_SectorsLeft;	/* Where to restart on a split access */
-
-static int Sectors256LeftInCurrent;	/* i.e. 256 byte sectors left in current */
-static int SectorsLeftInRequest;	/* i.e. blocks left in the thing mfm_request was called for */
-static int Copy_Sector;		/* The 256 byte sector we are currently at - fragments need to know 
-				   where to take over */
-static char *Copy_buffer;
-
-
-static void mfm_seek(void);
-static void mfm_rerequest(void);
-static void mfm_request(void);
-static void mfm_specify (void);
-static void issue_request(unsigned int block, unsigned int nsect,
-			  struct request *req);
-
-static unsigned int mfm_addr;		/* Controller address */
-static unsigned int mfm_IRQPollLoc;	/* Address to read for IRQ information */
-static unsigned int mfm_irqenable;	/* Podule IRQ enable location */
-static unsigned char mfm_irq;		/* Interrupt number */
-static int mfm_drives = 0;		/* drives available */
-static int mfm_status = 0;		/* interrupt status */
-static int *errors;
-
-static struct rawcmd {
-	unsigned int dev;
-	unsigned int cylinder;
-	unsigned int head;
-	unsigned int sector;
-	unsigned int cmdtype;
-	unsigned int cmdcode;
-	unsigned char cmddata[16];
-	unsigned int cmdlen;
-} raw_cmd;
-
-static unsigned char result[16];
-
-static struct cont {
-	void (*interrupt) (void);	/* interrupt handler */
-	void (*error) (void);	/* error handler */
-	void (*redo) (void);	/* redo handler */
-	void (*done) (int st);	/* done handler */
-} *cont = NULL;
-
-#if 0
-static struct tq_struct mfm_tq = {0, 0, (void (*)(void *)) NULL, 0};
-#endif
-
-int number_mfm_drives = 1;
-
-/* ------------------------------------------------------------------------------------------ */
-/*
- * From the HD63463 data sheet from Hitachi Ltd.
- */
-
-#define MFM_COMMAND (mfm_addr + 0)
-#define MFM_DATAOUT (mfm_addr + 1)
-#define MFM_STATUS  (mfm_addr + 8)
-#define MFM_DATAIN  (mfm_addr + 9)
-
-#define CMD_ABT		0xF0	/* Abort */
-#define CMD_SPC		0xE8	/* Specify */
-#define CMD_TST		0xE0	/* Test */
-#define CMD_RCLB	0xC8	/* Recalibrate */
-#define CMD_SEK		0xC0	/* Seek */
-#define CMD_WFS		0xAB	/* Write Format Skew */
-#define CMD_WFM		0xA3	/* Write Format */
-#define CMD_MTB		0x90	/* Memory to buffer */
-#define CMD_CMPD	0x88	/* Compare data */
-#define CMD_WD		0x87	/* Write data */
-#define CMD_RED		0x70	/* Read erroneous data */
-#define CMD_RIS		0x68	/* Read ID skew */
-#define CMD_FID		0x61	/* Find ID */
-#define CMD_RID		0x60	/* Read ID */
-#define CMD_BTM		0x50	/* Buffer to memory */
-#define CMD_CKD		0x48	/* Check data */
-#define CMD_RD		0x40	/* Read data */
-#define CMD_OPBW	0x38	/* Open buffer write */
-#define CMD_OPBR	0x30	/* Open buffer read */
-#define CMD_CKV		0x28	/* Check drive */
-#define CMD_CKE		0x20	/* Check ECC */
-#define CMD_POD		0x18	/* Polling disable */
-#define CMD_POL		0x10	/* Polling enable */
-#define CMD_RCAL	0x08	/* Recall */
-
-#define STAT_BSY	0x8000	/* Busy */
-#define STAT_CPR	0x4000	/* Command Parameter Rejection */
-#define STAT_CED	0x2000	/* Command end */
-#define STAT_SED	0x1000	/* Seek end */
-#define STAT_DER	0x0800	/* Drive error */
-#define STAT_ABN	0x0400	/* Abnormal end */
-#define STAT_POL	0x0200	/* Polling */
-
-/* ------------------------------------------------------------------------------------------ */
-#ifdef DEBUG
-static void console_printf(const char *fmt,...)
-{
-	static char buffer[2048];	/* Arbitary! */
-	extern void console_print(const char *);
-	unsigned long flags;
-	va_list ap;
-
-	local_irq_save(flags);
-
-	va_start(ap, fmt);
-	vsprintf(buffer, fmt, ap);
-	console_print(buffer);
-	va_end(fmt);
-
-	local_irq_restore(flags);
-};	/* console_printf */
-
-#define DBG(x...) console_printf(x)
-#else
-#define DBG(x...)
-#endif
-
-static void print_status(void)
-{
-	char *error;
-	static char *errors[] = {
-         "no error",
-	 "command aborted",
-	 "invalid command",
-	 "parameter error",
-	 "not initialised",
-	 "rejected TEST",
-	 "no useld",
-	 "write fault",
-	 "not ready",
-	 "no scp",
-	 "in seek",
-	 "invalid NCA",
-	 "invalid step rate",
-	 "seek error",
-	 "over run",
-	 "invalid PHA",
-	 "data field EEC error",
-	 "data field CRC error",
-	 "error corrected",
-	 "data field fatal error",
-	 "no data am",
-	 "not hit",
-	 "ID field CRC error",
-	 "time over",
-	 "no ID am",
-	 "not writable"
-	};
-	if (result[1] < 0x65)
-		error = errors[result[1] >> 2];
-	else
-		error = "unknown";
-	printk("(");
-	if (mfm_status & STAT_BSY) printk("BSY ");
-	if (mfm_status & STAT_CPR) printk("CPR ");
-	if (mfm_status & STAT_CED) printk("CED ");
-	if (mfm_status & STAT_SED) printk("SED ");
-	if (mfm_status & STAT_DER) printk("DER ");
-	if (mfm_status & STAT_ABN) printk("ABN ");
-	if (mfm_status & STAT_POL) printk("POL ");
-	printk(") SSB = %X (%s)\n", result[1], error);
-
-}
-
-/* ------------------------------------------------------------------------------------- */
-
-static void issue_command(int command, unsigned char *cmdb, int len)
-{
-	int status;
-#ifdef DEBUG
-	int i;
-	console_printf("issue_command: %02X: ", command);
-	for (i = 0; i < len; i++)
-		console_printf("%02X ", cmdb[i]);
-	console_printf("\n");
-#endif
-
-	do {
-		status = inw(MFM_STATUS);
-	} while (status & (STAT_BSY | STAT_POL));
-	DBG("issue_command: status after pol/bsy loop: %02X:\n ", status >> 8);
-
-	if (status & (STAT_CPR | STAT_CED | STAT_SED | STAT_DER | STAT_ABN)) {
-		outw(CMD_RCAL, MFM_COMMAND);
-		while (inw(MFM_STATUS) & STAT_BSY);
-	}
-	status = inw(MFM_STATUS);
-	DBG("issue_command: status before parameter issue: %02X:\n ", status >> 8);
-
-	while (len > 0) {
-		outw(cmdb[1] | (cmdb[0] << 8), MFM_DATAOUT);
-		len -= 2;
-		cmdb += 2;
-	}
-	status = inw(MFM_STATUS);
-	DBG("issue_command: status before command issue: %02X:\n ", status >> 8);
-
-	outw(command, MFM_COMMAND);
-	status = inw(MFM_STATUS);
-	DBG("issue_command: status immediately after command issue: %02X:\n ", status >> 8);
-}
-
-static void wait_for_completion(void)
-{
-	while ((mfm_status = inw(MFM_STATUS)) & STAT_BSY);
-}
-
-static void wait_for_command_end(void)
-{
-	int i;
-
-	while (!((mfm_status = inw(MFM_STATUS)) & STAT_CED));
-
-	for (i = 0; i < 16;) {
-		int in;
-		in = inw(MFM_DATAIN);
-		result[i++] = in >> 8;
-		result[i++] = in;
-	}
-	outw (CMD_RCAL, MFM_COMMAND);
-}
-
-/* ------------------------------------------------------------------------------------- */
-
-static void mfm_rw_intr(void)
-{
-	int old_status;		/* Holds status on entry, we read to see if the command just finished */
-#ifdef DEBUG
-	console_printf("mfm_rw_intr...dataleft=%d\n", hdc63463_dataleft);
-	print_status();
-#endif
-
-  /* Now don't handle the error until BSY drops */
-	if ((mfm_status & (STAT_DER | STAT_ABN)) && ((mfm_status&STAT_BSY)==0)) {
-		/* Something has gone wrong - let's try that again */
-		outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
-		if (cont) {
-			DBG("mfm_rw_intr: DER/ABN err\n");
-			cont->error();
-			cont->redo();
-		};
-		return;
-	};
-
-	/* OK so what ever happened it's not an error, now I reckon we are left between
-	   a choice of command end or some data which is ready to be collected */
-	/* I think we have to transfer data while the interrupt line is on and its
-	   not any other type of interrupt */
-	if (rq_data_dir(CURRENT) == WRITE) {
-		extern void hdc63463_writedma(void);
-		if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
-			printk("mfm_rw_intr: Apparent DMA write request when no more to DMA\n");
-			if (cont) {
-				cont->error();
-				cont->redo();
-			};
-			return;
-		};
-		hdc63463_writedma();
-	} else {
-		extern void hdc63463_readdma(void);
-		if ((hdc63463_dataleft <= 0) && (!(mfm_status & STAT_CED))) {
-			printk("mfm_rw_intr: Apparent DMA read request when no more to DMA\n");
-			if (cont) {
-				cont->error();
-				cont->redo();
-			};
-			return;
-		};
-		DBG("Going to try read dma..............status=0x%x, buffer=%p\n", mfm_status, hdc63463_dataptr);
-		hdc63463_readdma();
-	};			/* Read */
-
-	if (hdc63463_dataptr != ((unsigned int) Copy_buffer + 256)) {
-		/* If we didn't actually manage to get any data on this interrupt - but why? We got the interrupt */
-		/* Ah - well looking at the status its just when we get command end; so no problem */
-		/*console_printf("mfm: dataptr mismatch. dataptr=0x%08x Copy_buffer+256=0x%08p\n",
-		   hdc63463_dataptr,Copy_buffer+256);
-		   print_status(); */
-	} else {
-		Sectors256LeftInCurrent--;
-		Copy_buffer += 256;
-		Copy_Sector++;
-
-		/* We have come to the end of this request */
-		if (!Sectors256LeftInCurrent) {
-			DBG("mfm: end_request for CURRENT=0x%p CURRENT(sector=%d current_nr_sectors=%d nr_sectors=%d)\n",
-				       CURRENT, CURRENT->sector, CURRENT->current_nr_sectors, CURRENT->nr_sectors);
-
-			CURRENT->nr_sectors -= CURRENT->current_nr_sectors;
-			CURRENT->sector += CURRENT->current_nr_sectors;
-			SectorsLeftInRequest -= CURRENT->current_nr_sectors;
-
-			end_request(CURRENT, 1);
-			if (SectorsLeftInRequest) {
-				hdc63463_dataptr = (unsigned int) CURRENT->buffer;
-				Copy_buffer = CURRENT->buffer;
-				Sectors256LeftInCurrent = CURRENT->current_nr_sectors * 2;
-				errors = &(CURRENT->errors);
-				/* These should match the present calculations of the next logical sector
-				   on the device
-				   Copy_Sector=CURRENT->sector*2; */
-
-				if (Copy_Sector != CURRENT->sector * 2)
-#ifdef DEBUG
-					/*console_printf*/printk("mfm: Copy_Sector mismatch. Copy_Sector=%d CURRENT->sector*2=%d\n",
-					Copy_Sector, CURRENT->sector * 2);
-#else
-					printk("mfm: Copy_Sector mismatch! Eek!\n");
-#endif
-			};	/* CURRENT */
-		};	/* Sectors256LeftInCurrent */
-	};
-
-	old_status = mfm_status;
-	mfm_status = inw(MFM_STATUS);
-	if (mfm_status & (STAT_DER | STAT_ABN)) {
-		/* Something has gone wrong - let's try that again */
-		if (cont) {
-			DBG("mfm_rw_intr: DER/ABN error\n");
-			cont->error();
-			cont->redo();
-		};
-		return;
-	};
-
-	/* If this code wasn't entered due to command_end but there is
-	   now a command end we must read the command results out. If it was
-	   entered like this then mfm_interrupt_handler would have done the
-	   job. */
-	if ((!((old_status & (STAT_CPR | STAT_BSY)) == STAT_CPR)) &&
-	    ((mfm_status & (STAT_CPR | STAT_BSY)) == STAT_CPR)) {
-		int len = 0;
-		while (len < 16) {
-			int in;
-			in = inw(MFM_DATAIN);
-			result[len++] = in >> 8;
-			result[len++] = in;
-		};
-	};			/* Result read */
-
-	/*console_printf ("mfm_rw_intr nearexit [%02X]\n", __raw_readb(mfm_IRQPollLoc)); */
-
-	/* If end of command move on */
-	if (mfm_status & (STAT_CED)) {
-		outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
-		/* End of command - trigger the next command */
-		if (cont) {
-			cont->done(1);
-		}
-		DBG("mfm_rw_intr: returned from cont->done\n");
-	} else {
-		/* Its going to generate another interrupt */
-		do_mfm = mfm_rw_intr;
-	};
-}
-
-static void mfm_setup_rw(void)
-{
-	DBG("setting up for rw...\n");
-
-	do_mfm = mfm_rw_intr;
-	issue_command(raw_cmd.cmdcode, raw_cmd.cmddata, raw_cmd.cmdlen);
-}
-
-static void mfm_recal_intr(void)
-{
-#ifdef DEBUG
-	console_printf("recal intr - status = ");
-	print_status();
-#endif
-	outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
-	if (mfm_status & (STAT_DER | STAT_ABN)) {
-		printk("recal failed\n");
-		MFM_DRV_INFO.cylinder = NEED_2_RECAL;
-		if (cont) {
-			cont->error();
-			cont->redo();
-		}
-		return;
-	}
-	/* Thats seek end - we are finished */
-	if (mfm_status & STAT_SED) {
-		issue_command(CMD_POD, NULL, 0);
-		MFM_DRV_INFO.cylinder = 0;
-		mfm_seek();
-		return;
-	}
-	/* Command end without seek end (see data sheet p.20) for parallel seek
-	   - we have to send a POL command to wait for the seek */
-	if (mfm_status & STAT_CED) {
-		do_mfm = mfm_recal_intr;
-		issue_command(CMD_POL, NULL, 0);
-		return;
-	}
-	printk("recal: unknown status\n");
-}
-
-static void mfm_seek_intr(void)
-{
-#ifdef DEBUG
-	console_printf("seek intr - status = ");
-	print_status();
-#endif
-	outw(CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
-	if (mfm_status & (STAT_DER | STAT_ABN)) {
-		printk("seek failed\n");
-		MFM_DRV_INFO.cylinder = NEED_2_RECAL;
-		if (cont) {
-			cont->error();
-			cont->redo();
-		}
-		return;
-	}
-	if (mfm_status & STAT_SED) {
-		issue_command(CMD_POD, NULL, 0);
-		MFM_DRV_INFO.cylinder = raw_cmd.cylinder;
-		mfm_seek();
-		return;
-	}
-	if (mfm_status & STAT_CED) {
-		do_mfm = mfm_seek_intr;
-		issue_command(CMD_POL, NULL, 0);
-		return;
-	}
-	printk("seek: unknown status\n");
-}
-
-/* IDEA2 seems to work better - its what RiscOS sets my
- * disc to - on its SECOND call to specify!
- */
-#define IDEA2
-#ifndef IDEA2
-#define SPEC_SL 0x16
-#define SPEC_SH 0xa9		/* Step pulse high=21, Record Length=001 (256 bytes) */
-#else
-#define SPEC_SL 0x00		/* OM2 - SL - step pulse low */
-#define SPEC_SH 0x21		/* Step pulse high=4, Record Length=001 (256 bytes) */
-#endif
-
-static void mfm_setupspecify (int drive, unsigned char *cmdb)
-{
-	cmdb[0]  = 0x1f;		/* OM0 - !SECT,!MOD,!DIF,PADP,ECD,CRCP,CRCI,ACOR */
-	cmdb[1]  = 0xc3;		/* OM1 - DTM,BRST,!CEDM,!SEDM,!DERM,0,AMEX,PSK */
-	cmdb[2]  = SPEC_SL;		/* OM2 - SL - step pulse low */
-	cmdb[3]  = (number_mfm_drives == 1) ? 0x02 : 0x06;	/* 1 or 2 drives */
-	cmdb[4]  = 0xfc | ((mfm_info[drive].cylinders - 1) >> 8);/* RW time over/high part of number of cylinders */
-	cmdb[5]  = mfm_info[drive].cylinders - 1;		/* low part of number of cylinders */
-	cmdb[6]  = mfm_info[drive].heads - 1;			/* Number of heads */
-	cmdb[7]  = mfm_info[drive].sectors - 1;			/* Number of sectors */
-	cmdb[8]  = SPEC_SH;
-	cmdb[9]  = 0x0a;		/* gap length 1 */
-	cmdb[10] = 0x0d;		/* gap length 2 */
-	cmdb[11] = 0x0c;		/* gap length 3 */
-	cmdb[12] = (mfm_info[drive].precomp - 1) >> 8;	/* pre comp cylinder */
-	cmdb[13] = mfm_info[drive].precomp - 1;
-	cmdb[14] = (mfm_info[drive].lowcurrent - 1) >> 8;	/* Low current cylinder */
-	cmdb[15] = mfm_info[drive].lowcurrent - 1;
-}
-
-static void mfm_specify (void)
-{
-	unsigned char cmdb[16];
-
-	DBG("specify...dev=%d lastspecified=%d\n", raw_cmd.dev, lastspecifieddrive);
-	mfm_setupspecify (raw_cmd.dev, cmdb);
-
-	issue_command (CMD_SPC, cmdb, 16);
-	/* Ensure that we will do another specify if we move to the other drive */
-	lastspecifieddrive = raw_cmd.dev;
-	wait_for_completion();
-}
-
-static void mfm_seek(void)
-{
-	unsigned char cmdb[4];
-
-	DBG("seeking...\n");
-	if (MFM_DRV_INFO.cylinder < 0) {
-		do_mfm = mfm_recal_intr;
-		DBG("mfm_seek: about to call specify\n");
-		mfm_specify ();	/* DAG added this */
-
-		cmdb[0] = raw_cmd.dev + 1;
-		cmdb[1] = 0;
-
-		issue_command(CMD_RCLB, cmdb, 2);
-		return;
-	}
-	if (MFM_DRV_INFO.cylinder != raw_cmd.cylinder) {
-		cmdb[0] = raw_cmd.dev + 1;
-		cmdb[1] = 0;	/* raw_cmd.head; DAG: My data sheet says this should be 0 */
-		cmdb[2] = raw_cmd.cylinder >> 8;
-		cmdb[3] = raw_cmd.cylinder;
-
-		do_mfm = mfm_seek_intr;
-		issue_command(CMD_SEK, cmdb, 4);
-	} else
-		mfm_setup_rw();
-}
-
-static void mfm_initialise(void)
-{
-	DBG("init...\n");
-	mfm_seek();
-}
-
-static void request_done(int uptodate)
-{
-	DBG("mfm:request_done\n");
-	if (uptodate) {
-		unsigned char block[2] = {0, 0};
-
-		/* Apparently worked - let's check bytes left to DMA */
-		if (hdc63463_dataleft != (PartFragRead_SectorsLeft * 256)) {
-			printk("mfm: request_done - dataleft=%d - should be %d - Eek!\n", hdc63463_dataleft, PartFragRead_SectorsLeft * 256);
-			end_request(CURRENT, 0);
-			Busy = 0;
-		};
-		/* Potentially this means that we've done; but we might be doing
-		   a partial access, (over two cylinders) or we may have a number
-		   of fragments in an image file.  First let's deal with partial accesss
-		 */
-		if (PartFragRead) {
-			/* Yep - a partial access */
-
-			/* and issue the remainder */
-			issue_request(PartFragRead_RestartBlock, PartFragRead_SectorsLeft, CURRENT);
-			return;
-		}
-
-		/* ah well - perhaps there is another fragment to go */
-
-		/* Increment pointers/counts to start of next fragment */
-		if (SectorsLeftInRequest > 0) printk("mfm: SectorsLeftInRequest>0 - Eek! Shouldn't happen!\n");
-
-		/* No - its the end of the line */
-		/* end_request's should have happened at the end of sector DMAs */
-		/* Turns Drive LEDs off - may slow it down? */
-		if (!elv_next_request(QUEUE))
-			issue_command(CMD_CKV, block, 2);
-
-		Busy = 0;
-		DBG("request_done: About to mfm_request\n");
-		/* Next one please */
-		mfm_request();	/* Moved from mfm_rw_intr */
-		DBG("request_done: returned from mfm_request\n");
-	} else {
-		printk("mfm:request_done: update=0\n");
-		end_request(CURRENT, 0);
-		Busy = 0;
-	}
-}
-
-static void error_handler(void)
-{
-	printk("error detected... status = ");
-	print_status();
-	(*errors)++;
-	if (*errors > MFM_DRV_INFO.errors.abort)
-		cont->done(0);
-	if (*errors > MFM_DRV_INFO.errors.recal)
-		MFM_DRV_INFO.cylinder = NEED_2_RECAL;
-}
-
-static void rw_interrupt(void)
-{
-	printk("rw_interrupt\n");
-}
-
-static struct cont rw_cont =
-{
-	rw_interrupt,
-	error_handler,
-	mfm_rerequest,
-	request_done
-};
-
-/*
- * Actually gets round to issuing the request - note everything at this
- * point is in 256 byte sectors not Linux 512 byte blocks
- */
-static void issue_request(unsigned int block, unsigned int nsect,
-			  struct request *req)
-{
-	struct gendisk *disk = req->rq_disk;
-	struct mfm_info *p = disk->private_data;
-	int track, start_head, start_sector;
-	int sectors_to_next_cyl;
-	dev = p - mfm_info;
-
-	track = block / p->sectors;
-	start_sector = block % p->sectors;
-	start_head = track % p->heads;
-
-	/* First get the number of whole tracks which are free before the next
-	   track */
-	sectors_to_next_cyl = (p->heads - (start_head + 1)) * p->sectors;
-	/* Then add in the number of sectors left on this track */
-	sectors_to_next_cyl += (p->sectors - start_sector);
-
-	DBG("issue_request: mfm_info[dev].sectors=%d track=%d\n", p->sectors, track);
-
-	raw_cmd.dev = dev;
-	raw_cmd.sector = start_sector;
-	raw_cmd.head = start_head;
-	raw_cmd.cylinder = track / p->heads;
-	raw_cmd.cmdtype = CURRENT->cmd;
-	raw_cmd.cmdcode = rq_data_dir(CURRENT) == WRITE ? CMD_WD : CMD_RD;
-	raw_cmd.cmddata[0] = dev + 1;	/* DAG: +1 to get US */
-	raw_cmd.cmddata[1] = raw_cmd.head;
-	raw_cmd.cmddata[2] = raw_cmd.cylinder >> 8;
-	raw_cmd.cmddata[3] = raw_cmd.cylinder;
-	raw_cmd.cmddata[4] = raw_cmd.head;
-	raw_cmd.cmddata[5] = raw_cmd.sector;
-
-	/* Was == and worked - how the heck??? */
-	if (lastspecifieddrive != raw_cmd.dev)
-		mfm_specify ();
-
-	if (nsect <= sectors_to_next_cyl) {
-		raw_cmd.cmddata[6] = nsect >> 8;
-		raw_cmd.cmddata[7] = nsect;
-		PartFragRead = 0;	/* All in one */
-		PartFragRead_SectorsLeft = 0;	/* Must set this - used in DMA calcs */
-	} else {
-		raw_cmd.cmddata[6] = sectors_to_next_cyl >> 8;
-		raw_cmd.cmddata[7] = sectors_to_next_cyl;
-		PartFragRead = sectors_to_next_cyl;	/* only do this many this time */
-		PartFragRead_RestartBlock = block + sectors_to_next_cyl;	/* Where to restart from */
-		PartFragRead_SectorsLeft = nsect - sectors_to_next_cyl;
-	}
-	raw_cmd.cmdlen = 8;
-
-	/* Setup DMA pointers */
-	hdc63463_dataptr = (unsigned int) Copy_buffer;
-	hdc63463_dataleft = nsect * 256;	/* Better way? */
-
-	DBG("mfm%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx (%p)\n",
-	     raw_cmd.dev + 'a', rq_data_dir(CURRENT) == READ ? "read" : "writ",
-		       raw_cmd.cylinder,
-		       raw_cmd.head,
-	    raw_cmd.sector, nsect, (unsigned long) Copy_buffer, CURRENT);
-
-	cont = &rw_cont;
-	errors = &(CURRENT->errors);
-#if 0
-	mfm_tq.routine = (void (*)(void *)) mfm_initialise;
-	queue_task(&mfm_tq, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
-#else
-	mfm_initialise();
-#endif
-}				/* issue_request */
-
-/*
- * Called when an error has just happened - need to trick mfm_request
- * into thinking we weren't busy
- *
- * Turn off ints - mfm_request expects them this way
- */
-static void mfm_rerequest(void)
-{
-	DBG("mfm_rerequest\n");
-	cli();
-	Busy = 0;
-	mfm_request();
-}
-
-static struct gendisk *mfm_gendisk[2];
-
-static void mfm_request(void)
-{
-	DBG("mfm_request CURRENT=%p Busy=%d\n", CURRENT, Busy);
-
-	/* If we are still processing then return; we will get called again */
-	if (Busy) {
-		/* Again seems to be common in 1.3.45 */
-		/*DBG*/printk("mfm_request: Exiting due to busy\n");
-		return;
-	}
-	Busy = 1;
-
-	while (1) {
-		unsigned int block, nsect;
-		struct gendisk *disk;
-
-		DBG("mfm_request: loop start\n");
-		sti();
-
-		DBG("mfm_request: before !CURRENT\n");
-
-		if (!CURRENT) {
-			printk("mfm_request: Exiting due to empty queue (pre)\n");
-			do_mfm = NULL;
-			Busy = 0;
-			return;
-		}
-
-		DBG("mfm_request:                 before arg extraction\n");
-
-		disk = CURRENT->rq_disk;
-		block = CURRENT->sector;
-		nsect = CURRENT->nr_sectors;
-		if (block >= get_capacity(disk) ||
-		    block+nsect > get_capacity(disk)) {
-			printk("%s: bad access: block=%d, count=%d, nr_sects=%ld\n",
-			       disk->disk_name, block, nsect, get_capacity(disk));
-			printk("mfm: continue 1\n");
-			end_request(CURRENT, 0);
-			Busy = 0;
-			continue;
-		}
-
-		/* DAG: Linux doesn't cope with this - even though it has an array telling
-		   it the hardware block size - silly */
-		block <<= 1;	/* Now in 256 byte sectors */
-		nsect <<= 1;	/* Ditto */
-
-		SectorsLeftInRequest = nsect >> 1;
-		Sectors256LeftInCurrent = CURRENT->current_nr_sectors * 2;
-		Copy_buffer = CURRENT->buffer;
-		Copy_Sector = CURRENT->sector << 1;
-
-		DBG("mfm_request: block after offset=%d\n", block);
-
-		issue_request(block, nsect, CURRENT);
-
-		break;
-	}
-	DBG("mfm_request: Dropping out bottom\n");
-}
-
-static void do_mfm_request(struct request_queue *q)
-{
-	DBG("do_mfm_request: about to mfm_request\n");
-	mfm_request();
-}
-
-static void mfm_interrupt_handler(int unused, void *dev_id)
-{
-	void (*handler) (void) = do_mfm;
-
-	do_mfm = NULL;
-
-	DBG("mfm_interrupt_handler (handler=0x%p)\n", handler);
-
-	mfm_status = inw(MFM_STATUS);
-
-	/* If CPR (Command Parameter Reject) and not busy it means that the command
-	   has some return message to give us */
-	if ((mfm_status & (STAT_CPR | STAT_BSY)) == STAT_CPR) {
-		int len = 0;
-		while (len < 16) {
-			int in;
-			in = inw(MFM_DATAIN);
-			result[len++] = in >> 8;
-			result[len++] = in;
-		}
-	}
-	if (handler) {
-		handler();
-		return;
-	}
-	outw (CMD_RCAL, MFM_COMMAND);	/* Clear interrupt condition */
-	printk ("mfm: unexpected interrupt - status = ");
-	print_status ();
-	while (1);
-}
-
-
-
-
-
-/*
- * Tell the user about the drive if we decided it exists.
- */
-static void mfm_geometry(int drive)
-{
-	struct mfm_info *p = mfm_info + drive;
-	struct gendisk *disk = mfm_gendisk[drive];
-	disk->private_data = p;
-	if (p->cylinders)
-		printk ("%s: %dMB CHS=%d/%d/%d LCC=%d RECOMP=%d\n",
-			disk->disk_name,
-			p->cylinders * p->heads * p->sectors / 4096,
-			p->cylinders, p->heads, p->sectors,
-			p->lowcurrent, p->precomp);
-	set_capacity(disk, p->cylinders * p->heads * p->sectors / 2);
-}
-
-#ifdef CONFIG_BLK_DEV_MFM_AUTODETECT
-/*
- * Attempt to detect a drive and find its geometry.  The drive has already been
- * specified...
- *
- * We first recalibrate the disk, then try to probe sectors, heads and then
- * cylinders.  NOTE! the cylinder probe may break drives.  The xd disk driver
- * does something along these lines, so I assume that most drives are up to
- * this mistreatment...
- */
-static int mfm_detectdrive (int drive)
-{
-	unsigned int mingeo[3], maxgeo[3];
-	unsigned int attribute, need_recal = 1;
-	unsigned char cmdb[8];
-
-	memset (mingeo, 0, sizeof (mingeo));
-	maxgeo[0] = mfm_info[drive].sectors;
-	maxgeo[1] = mfm_info[drive].heads;
-	maxgeo[2] = mfm_info[drive].cylinders;
-
-	cmdb[0] = drive + 1;
-	cmdb[6] = 0;
-	cmdb[7] = 1;
-	for (attribute = 0; attribute < 3; attribute++) {
-		while (mingeo[attribute] != maxgeo[attribute]) {
-			unsigned int variable;
-
-			variable = (maxgeo[attribute] + mingeo[attribute]) >> 1;
-			cmdb[1] = cmdb[2] = cmdb[3] = cmdb[4] = cmdb[5] = 0;
-
-			if (need_recal) {
-				int tries = 5;
-
-				do {
-					issue_command (CMD_RCLB, cmdb, 2);
-					wait_for_completion ();
-					wait_for_command_end ();
-					if  (result[1] == 0x20)
-						break;
-				} while (result[1] && --tries);
-				if (result[1]) {
-					outw (CMD_RCAL, MFM_COMMAND);
-					return 0;
-				}
-				need_recal = 0;
-			}
-
-			switch (attribute) {
-			case 0:
-				cmdb[5] = variable;
-				issue_command (CMD_CMPD, cmdb, 8);
-				break;
-			case 1:
-				cmdb[1] = variable;
-				cmdb[4] = variable;
-				issue_command (CMD_CMPD, cmdb, 8);
-				break;
-			case 2:
-				cmdb[2] = variable >> 8;
-				cmdb[3] = variable;
-				issue_command (CMD_SEK, cmdb, 4);
-				break;
-			}
-			wait_for_completion ();
-			wait_for_command_end ();
-
-			switch (result[1]) {
-			case 0x00:
-			case 0x50:
-				mingeo[attribute] = variable + 1;
-				break;
-
-			case 0x20:
-				outw (CMD_RCAL, MFM_COMMAND);
-				return 0;
-
-			case 0x24:
-				need_recal = 1;
-			default:
-				maxgeo[attribute] = variable;
-				break;
-			}
-		}
-	}
-	mfm_info[drive].cylinders  = mingeo[2];
-	mfm_info[drive].lowcurrent = mingeo[2];
-	mfm_info[drive].precomp    = mingeo[2] / 2;
-	mfm_info[drive].heads 	   = mingeo[1];
-	mfm_info[drive].sectors	   = mingeo[0];
-	outw (CMD_RCAL, MFM_COMMAND);
-	return 1;
-}
-#endif
-
-/*
- * Initialise all drive information for this controller.
- */
-static int mfm_initdrives(void)
-{
-	int drive;
-
-	if (number_mfm_drives > MFM_MAXDRIVES) {
-		number_mfm_drives = MFM_MAXDRIVES;
-		printk("No. of ADFS MFM drives is greater than MFM_MAXDRIVES - you can't have that many!\n");
-	}
-
-	for (drive = 0; drive < number_mfm_drives; drive++) {
-		mfm_info[drive].lowcurrent = 1;
-		mfm_info[drive].precomp    = 1;
-		mfm_info[drive].cylinder   = -1;
-		mfm_info[drive].errors.recal  = 0;
-		mfm_info[drive].errors.report = 0;
-		mfm_info[drive].errors.abort  = 4;
-
-#ifdef CONFIG_BLK_DEV_MFM_AUTODETECT
-		mfm_info[drive].cylinders  = 1024;
-		mfm_info[drive].heads	   = 8;
-		mfm_info[drive].sectors	   = 64;
-		{
-			unsigned char cmdb[16];
-
-			mfm_setupspecify (drive, cmdb);
-			cmdb[1] &= ~0x81;
-			issue_command (CMD_SPC, cmdb, 16);
-			wait_for_completion ();
-			if (!mfm_detectdrive (drive)) {
-				mfm_info[drive].cylinders = 0;
-				mfm_info[drive].heads     = 0;
-				mfm_info[drive].sectors   = 0;
-			}
-			cmdb[0] = cmdb[1] = 0;
-			issue_command (CMD_CKV, cmdb, 2);
-		}
-#else
-		mfm_info[drive].cylinders  = 1;	/* its going to have to figure it out from the partition info */
-		mfm_info[drive].heads      = 4;
-		mfm_info[drive].sectors    = 32;
-#endif
-	}
-	return number_mfm_drives;
-}
-
-
-
-/*
- * The 'front' end of the mfm driver follows...
- */
-
-static int mfm_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
-	struct mfm_info *p = bdev->bd_disk->private_data;
-
-	geo->heads = p->heads;
-	geo->sectors = p->sectors;
-	geo->cylinders = p->cylinders;
-	return 0;
-}
-
-/*
- * This is to handle various kernel command line parameters
- * specific to this driver.
- */
-void mfm_setup(char *str, int *ints)
-{
-	return;
-}
-
-/*
- * Set the CHS from the ADFS boot block if it is present.  This is not ideal
- * since if there are any non-ADFS partitions on the disk, this won't work!
- * Hence, I want to get rid of this...
- */
-void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
-			unsigned char heads, unsigned int secsize)
-{
-	struct mfm_info *p = bdev->bd_disk->private_data;
-	int drive = p - mfm_info;
-	unsigned long disksize = bdev->bd_inode->i_size;
-
-	if (p->cylinders == 1) {
-		p->sectors = secsptrack;
-		p->heads = heads;
-		p->cylinders = discsize / (secsptrack * heads * secsize);
-
-		if ((heads < 1) || (p->cylinders > 1024)) {
-			printk("%s: Insane disc shape! Setting to 512/4/32\n",
-				bdev->bd_disk->disk_name);
-
-			/* These values are fairly arbitary, but are there so that if your
-			 * lucky you can pick apart your disc to find out what is going on -
-			 * I reckon these figures won't hurt MOST drives
-			 */
-			p->sectors = 32;
-			p->heads = 4;
-			p->cylinders = 512;
-		}
-		if (raw_cmd.dev == drive)
-			mfm_specify ();
-		mfm_geometry (drive);
-	}
-}
-
-static struct block_device_operations mfm_fops =
-{
-	.owner		= THIS_MODULE,
-	.getgeo		= mfm_getgeo,
-};
-
-/*
- * See if there is a controller at the address presently at mfm_addr
- *
- * We check to see if the controller is busy - if it is, we abort it first,
- * and check that the chip is no longer busy after at least 180 clock cycles.
- * We then issue a command and check that the BSY or CPR bits are set.
- */
-static int mfm_probecontroller (unsigned int mfm_addr)
-{
-	if (inw (MFM_STATUS) & STAT_BSY) {
-		outw (CMD_ABT, MFM_COMMAND);
-		udelay (50);
-		if (inw (MFM_STATUS) & STAT_BSY)
-			return 0;
-	}
-
-	if (inw (MFM_STATUS) & STAT_CED)
-		outw (CMD_RCAL, MFM_COMMAND);
-
-	outw (CMD_SEK, MFM_COMMAND);
-
-	if (inw (MFM_STATUS) & (STAT_BSY | STAT_CPR)) {
-		unsigned int count = 2000;
-		while (inw (MFM_STATUS) & STAT_BSY) {
-			udelay (500);
-			if (!--count)
-				return 0;
-		}
-
-		outw (CMD_RCAL, MFM_COMMAND);
-	}
-	return 1;
-}
-
-static int mfm_do_init(unsigned char irqmask)
-{
-	int i, ret;
-
-	printk("mfm: found at address %08X, interrupt %d\n", mfm_addr, mfm_irq);
-
-	ret = -EBUSY;
-	if (!request_region (mfm_addr, 10, "mfm"))
-		goto out1;
-
-	ret = register_blkdev(MAJOR_NR, "mfm");
-	if (ret)
-		goto out2;
-
-	/* Stuff for the assembler routines to get to */
-	hdc63463_baseaddress	= ioaddr(mfm_addr);
-	hdc63463_irqpolladdress	= mfm_IRQPollLoc;
-	hdc63463_irqpollmask	= irqmask;
-
-	mfm_queue = blk_init_queue(do_mfm_request, &mfm_lock);
-	if (!mfm_queue)
-		goto out2a;
-
-	Busy = 0;
-	lastspecifieddrive = -1;
-
-	mfm_drives = mfm_initdrives();
-	if (!mfm_drives) {
-		ret = -ENODEV;
-		goto out3;
-	}
-	
-	for (i = 0; i < mfm_drives; i++) {
-		struct gendisk *disk = alloc_disk(64);
-		if (!disk)
-			goto Enomem;
-		disk->major = MAJOR_NR;
-		disk->first_minor = i << 6;
-		disk->fops = &mfm_fops;
-		sprintf(disk->disk_name, "mfm%c", 'a'+i);
-		mfm_gendisk[i] = disk;
-	}
-
-	printk("mfm: detected %d hard drive%s\n", mfm_drives,
-				mfm_drives == 1 ? "" : "s");
-	ret = request_irq(mfm_irq, mfm_interrupt_handler, IRQF_DISABLED, "MFM harddisk", NULL);
-	if (ret) {
-		printk("mfm: unable to get IRQ%d\n", mfm_irq);
-		goto out4;
-	}
-
-	if (mfm_irqenable)
-		outw(0x80, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
-
-	for (i = 0; i < mfm_drives; i++) {
-		mfm_geometry(i);
-		mfm_gendisk[i]->queue = mfm_queue;
-		add_disk(mfm_gendisk[i]);
-	}
-	return 0;
-
-out4:
-	for (i = 0; i < mfm_drives; i++)
-		put_disk(mfm_gendisk[i]);
-out3:
-	blk_cleanup_queue(mfm_queue);
-out2a:
-	unregister_blkdev(MAJOR_NR, "mfm");
-out2:
-	release_region(mfm_addr, 10);
-out1:
-	return ret;
-Enomem:
-	while (i--)
-		put_disk(mfm_gendisk[i]);
-	goto out3;
-}
-
-static void mfm_do_exit(void)
-{
-	int i;
-
-	free_irq(mfm_irq, NULL);
-	for (i = 0; i < mfm_drives; i++) {
-		del_gendisk(mfm_gendisk[i]);
-		put_disk(mfm_gendisk[i]);
-	}
-	blk_cleanup_queue(mfm_queue);
-	unregister_blkdev(MAJOR_NR, "mfm");
-	if (mfm_addr)
-		release_region(mfm_addr, 10);
-}
-
-static int __devinit mfm_probe(struct expansion_card *ec, struct ecard_id *id)
-{
-	if (mfm_addr)
-		return -EBUSY;
-
-	mfm_addr	= ecard_address(ec, ECARD_IOC, ECARD_MEDIUM) + 0x800;
-	mfm_IRQPollLoc	= ioaddr(mfm_addr + 0x400);
-	mfm_irqenable	= mfm_IRQPollLoc;
-	mfm_irq		= ec->irq;
-
-	return mfm_do_init(0x08);
-}
-
-static void __devexit mfm_remove(struct expansion_card *ec)
-{
-	outw (0, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
-	mfm_do_exit();
-}
-
-static const struct ecard_id mfm_cids[] = {
-	{ MANU_ACORN, PROD_ACORN_MFM },
-	{ 0xffff, 0xffff },
-};
-
-static struct ecard_driver mfm_driver = {
-	.probe		= mfm_probe,
-	.remove		= __devexit(mfm_remove),
-	.id_table	= mfm_cids,
-	.drv = {
-		.name	= "mfm",
-	},
-};
-
-/*
- * Look for a MFM controller - first check the motherboard, then the podules
- * The podules have an extra interrupt enable that needs to be played with
- *
- * The HDC is accessed at MEDIUM IOC speeds.
- */
-static int __init mfm_init (void)
-{
-	unsigned char irqmask;
-
-	if (mfm_probecontroller(ONBOARD_MFM_ADDRESS)) {
-		mfm_addr	= ONBOARD_MFM_ADDRESS;
-		mfm_IRQPollLoc	= IOC_IRQSTATB;
-		mfm_irqenable	= 0;
-		mfm_irq		= IRQ_HARDDISK;
-		return mfm_do_init(0x08);	/* IL3 pin */
-	} else {
-		return ecard_register_driver(&mfm_driver);
-	}
-}
-
-static void __exit mfm_exit(void)
-{
-	if (mfm_addr == ONBOARD_MFM_ADDRESS)
-		mfm_do_exit();
-	else
-		ecard_unregister_driver(&mfm_driver);
-}
-
-module_init(mfm_init)
-module_exit(mfm_exit)
-MODULE_LICENSE("GPL");