drivers/block/floppy.c: add function is_ready_state
[safe/jmp/linux-2.6] / drivers / block / floppy.c
index 42dfa28..1264102 100644 (file)
@@ -5,6 +5,7 @@
  *  Copyright (C) 1993, 1994  Alain Knaff
  *  Copyright (C) 1998 Alan Cox
  */
+
 /*
  * 02.12.91 - Changed to static variables to indicate need for reset
  * and recalibrate. This makes some things easier (output_byte reset
  */
 
 /*
+ * 1998/1/21 -- Richard Gooch <rgooch@atnf.csiro.au> -- devfs support
+ */
+
+/*
  * 1998/05/07 -- Russell King -- More portability cleanups; moved definition of
  * interrupt and dma channel to asm/floppy.h. Cleaned up some formatting &
  * use of '0' for NULL.
 #define DEBUGT 2
 #define DCL_DEBUG              /* debug disk change line */
 
+#ifdef DCL_DEBUG
+#define debug_dcl(test, fmt, args...) \
+       do { if ((test) & FD_DEBUG) DPRINT(fmt, ##args); } while (0)
+#else
+#define debug_dcl(test, fmt, args...) \
+       do { if (0) DPRINT(fmt, ##args); } while (0)
+#endif
+
+
 /* do print messages for unexpected interrupts */
 static int print_unex = 1;
 #include <linux/module.h>
@@ -157,28 +171,26 @@ static int print_unex = 1;
 #include <linux/workqueue.h>
 #define FDPATCHES
 #include <linux/fdreg.h>
-
-/*
- * 1998/1/21 -- Richard Gooch <rgooch@atnf.csiro.au> -- devfs support
- */
-
 #include <linux/fd.h>
 #include <linux/hdreg.h>
-
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/bio.h>
 #include <linux/string.h>
+#include <linux/jiffies.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
 #include <linux/mc146818rtc.h> /* CMOS defines */
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
 #include <linux/buffer_head.h> /* for invalidate_buffers() */
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
 
 /*
  * PS/2 floppies have much slower step rates than regular floppies.
@@ -190,8 +202,6 @@ static int slow_floppy;
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
 
 static int FLOPPY_IRQ = 6;
 static int FLOPPY_DMA = 2;
@@ -217,12 +227,10 @@ static int use_virtual_dma;
  */
 
 static DEFINE_SPINLOCK(floppy_lock);
-static struct completion device_release;
 
 static unsigned short virtual_dma_port = 0x3f0;
-irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t floppy_interrupt(int irq, void *dev_id);
 static int set_dor(int fdc, char mask, char data);
-static void register_devfs_entries(int drive) __init;
 
 #define K_64   0x10000         /* 64KB */
 
@@ -242,9 +250,6 @@ static int allowed_drive_mask = 0x33;
 
 static int irqdma_allocated;
 
-#define LOCAL_END_REQUEST
-#define DEVICE_NAME "floppy"
-
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/cdrom.h>       /* for the compatibility eject ioctl */
@@ -252,7 +257,7 @@ static int irqdma_allocated;
 
 static struct request *current_req;
 static struct request_queue *floppy_queue;
-static void do_fd_request(request_queue_t * q);
+static void do_fd_request(struct request_queue *q);
 
 #ifndef fd_get_dma_residue
 #define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA)
@@ -265,7 +270,7 @@ static void do_fd_request(request_queue_t * q);
 #endif
 
 #ifndef fd_dma_mem_alloc
-#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,get_order(size))
+#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL, get_order(size))
 #endif
 
 static inline void fallback_on_nodma_alloc(char **addr, size_t l)
@@ -275,8 +280,7 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l)
                return;         /* we have the memory */
        if (can_use_virtual_dma != 2)
                return;         /* no fallback allowed */
-       printk
-           ("DMA memory shortage. Temporarily falling back on virtual DMA\n");
+       pr_info("DMA memory shortage. Temporarily falling back on virtual DMA\n");
        *addr = (char *)nodma_mem_alloc(l);
 #else
        return;
@@ -286,59 +290,53 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l)
 /* End dma memory related stuff */
 
 static unsigned long fake_change;
-static int initialising = 1;
+static bool initialized;
 
-#define ITYPE(x) (((x)>>2) & 0x1f)
-#define TOMINOR(x) ((x & 3) | ((x & 4) << 5))
-#define UNIT(x) ((x) & 0x03)   /* drive on fdc */
-#define FDC(x) (((x) & 0x04) >> 2)     /* fdc of drive */
+#define ITYPE(x)       (((x) >> 2) & 0x1f)
+#define TOMINOR(x)     ((x & 3) | ((x & 4) << 5))
+#define UNIT(x)                ((x) & 0x03)            /* drive on fdc */
+#define FDC(x)         (((x) & 0x04) >> 2)     /* fdc of drive */
+       /* reverse mapping from unit and fdc to drive */
 #define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2))
-                               /* reverse mapping from unit and fdc to drive */
-#define DP (&drive_params[current_drive])
-#define DRS (&drive_state[current_drive])
-#define DRWE (&write_errors[current_drive])
-#define FDCS (&fdc_state[fdc])
-#define CLEARF(x) (clear_bit(x##_BIT, &DRS->flags))
-#define SETF(x) (set_bit(x##_BIT, &DRS->flags))
-#define TESTF(x) (test_bit(x##_BIT, &DRS->flags))
-
-#define UDP (&drive_params[drive])
-#define UDRS (&drive_state[drive])
-#define UDRWE (&write_errors[drive])
-#define UFDCS (&fdc_state[FDC(drive)])
-#define UCLEARF(x) (clear_bit(x##_BIT, &UDRS->flags))
-#define USETF(x) (set_bit(x##_BIT, &UDRS->flags))
-#define UTESTF(x) (test_bit(x##_BIT, &UDRS->flags))
-
-#define DPRINT(format, args...) printk(DEVICE_NAME "%d: " format, current_drive , ## args)
-
-#define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2)
-#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH)
-
-#define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x)))
+
+#define DP     (&drive_params[current_drive])
+#define DRS    (&drive_state[current_drive])
+#define DRWE   (&write_errors[current_drive])
+#define FDCS   (&fdc_state[fdc])
+
+#define UDP    (&drive_params[drive])
+#define UDRS   (&drive_state[drive])
+#define UDRWE  (&write_errors[drive])
+#define UFDCS  (&fdc_state[FDC(drive)])
+
+#define DPRINT(format, args...) \
+       pr_info("floppy%d: " format, current_drive, ##args)
+
+#define PH_HEAD(floppy, head) (((((floppy)->stretch & 2) >> 1) ^ head) << 2)
+#define STRETCH(floppy)        ((floppy)->stretch & FD_STRETCH)
 
 /* read/write */
-#define COMMAND raw_cmd->cmd[0]
-#define DR_SELECT raw_cmd->cmd[1]
-#define TRACK raw_cmd->cmd[2]
-#define HEAD raw_cmd->cmd[3]
-#define SECTOR raw_cmd->cmd[4]
-#define SIZECODE raw_cmd->cmd[5]
-#define SECT_PER_TRACK raw_cmd->cmd[6]
-#define GAP raw_cmd->cmd[7]
-#define SIZECODE2 raw_cmd->cmd[8]
+#define COMMAND                (raw_cmd->cmd[0])
+#define DR_SELECT      (raw_cmd->cmd[1])
+#define TRACK          (raw_cmd->cmd[2])
+#define HEAD           (raw_cmd->cmd[3])
+#define SECTOR         (raw_cmd->cmd[4])
+#define SIZECODE       (raw_cmd->cmd[5])
+#define SECT_PER_TRACK (raw_cmd->cmd[6])
+#define GAP            (raw_cmd->cmd[7])
+#define SIZECODE2      (raw_cmd->cmd[8])
 #define NR_RW 9
 
 /* format */
-#define F_SIZECODE raw_cmd->cmd[2]
-#define F_SECT_PER_TRACK raw_cmd->cmd[3]
-#define F_GAP raw_cmd->cmd[4]
-#define F_FILL raw_cmd->cmd[5]
+#define F_SIZECODE     (raw_cmd->cmd[2])
+#define F_SECT_PER_TRACK (raw_cmd->cmd[3])
+#define F_GAP          (raw_cmd->cmd[4])
+#define F_FILL         (raw_cmd->cmd[5])
 #define NR_F 6
 
 /*
- * Maximum disk size (in kilobytes). This default is used whenever the
- * current disk size is unknown.
+ * Maximum disk size (in kilobytes).
+ * This default is used whenever the current disk size is unknown.
  * [Now it is rather a minimum]
  */
 #define MAX_DISK_SIZE 4                /* 3984 */
@@ -349,16 +347,16 @@ static int initialising = 1;
 #define MAX_REPLIES 16
 static unsigned char reply_buffer[MAX_REPLIES];
 static int inr;                        /* size of reply buffer, when called from interrupt */
-#define ST0 (reply_buffer[0])
-#define ST1 (reply_buffer[1])
-#define ST2 (reply_buffer[2])
-#define ST3 (reply_buffer[0])  /* result of GETSTATUS */
-#define R_TRACK (reply_buffer[3])
-#define R_HEAD (reply_buffer[4])
-#define R_SECTOR (reply_buffer[5])
-#define R_SIZECODE (reply_buffer[6])
+#define ST0            (reply_buffer[0])
+#define ST1            (reply_buffer[1])
+#define ST2            (reply_buffer[2])
+#define ST3            (reply_buffer[0])       /* result of GETSTATUS */
+#define R_TRACK                (reply_buffer[3])
+#define R_HEAD         (reply_buffer[4])
+#define R_SECTOR       (reply_buffer[5])
+#define R_SIZECODE     (reply_buffer[6])
 
-#define SEL_DLY (2*HZ/100)
+#define SEL_DLY                (2 * HZ / 100)
 
 /*
  * this struct defines the different floppy drive types.
@@ -414,7 +412,7 @@ static struct floppy_write_errors write_errors[N_DRIVE];
 static struct timer_list motor_off_timer[N_DRIVE];
 static struct gendisk *disks[N_DRIVE];
 static struct block_device *opened_bdev[N_DRIVE];
-static DECLARE_MUTEX(open_lock);
+static DEFINE_MUTEX(open_lock);
 static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
 
 /*
@@ -428,8 +426,15 @@ static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
  * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical
  * side 0 is on physical side 0 (but with the misnamed sector IDs).
  * 'stretch' should probably be renamed to something more general, like
- * 'options'.  Other parameters should be self-explanatory (see also
- * setfdprm(8)).
+ * 'options'.
+ *
+ * Bits 2 through 9 of 'stretch' tell the number of the first sector.
+ * The LSB (bit 2) is flipped. For most disks, the first sector
+ * is 1 (represented by 0x00<<2).  For some CP/M and music sampler
+ * disks (such as Ensoniq EPS 16plus) it is 0 (represented as 0x01<<2).
+ * For Amstrad CPC disks it is 0xC1 (represented as 0xC0<<2).
+ *
+ * Other parameters should be self-explanatory (see also setfdprm(8)).
  */
 /*
            Size
@@ -473,13 +478,12 @@ static struct floppy_struct floppy_type[32] = {
        { 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5"   */
        { 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5"   */
        { 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5"   */
-
        { 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5"   */
+
        { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800"  }, /* 30 800KB 3.5"    */
        { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5"    */
 };
 
-#define        NUMBER(x)       (sizeof(x) / sizeof(*(x)))
 #define SECTSIZE (_FD_SECTSIZE(*floppy))
 
 /* Auto-detection: Disk type used until the next media change occurs. */
@@ -493,6 +497,8 @@ static struct floppy_struct user_params[N_DRIVE];
 
 static sector_t floppy_sizes[256];
 
+static char floppy_device_name[] = "floppy";
+
 /*
  * The driver is trying to determine the correct media format
  * while probing is set. rw_interrupt() clears it after a
@@ -501,9 +507,9 @@ static sector_t floppy_sizes[256];
 static int probing;
 
 /* Synchronization of FDC access. */
-#define FD_COMMAND_NONE -1
-#define FD_COMMAND_ERROR 2
-#define FD_COMMAND_OKAY 3
+#define FD_COMMAND_NONE                -1
+#define FD_COMMAND_ERROR       2
+#define FD_COMMAND_OKAY                3
 
 static volatile int command_status = FD_COMMAND_NONE;
 static unsigned long fdc_busy;
@@ -511,11 +517,6 @@ static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
 static DECLARE_WAIT_QUEUE_HEAD(command_done);
 
 #define NO_SIGNAL (!interruptible || !signal_pending(current))
-#define CALL(x) if ((x) == -EINTR) return -EINTR
-#define ECALL(x) if ((ret = (x))) return ret;
-#define _WAIT(x,i) CALL(ret=wait_til_done((x),i))
-#define WAIT(x) _WAIT((x),interruptible)
-#define IWAIT(x) _WAIT((x),1)
 
 /* Errors during formatting are counted here. */
 static int format_errors;
@@ -539,12 +540,13 @@ static char *floppy_track_buffer;
 static int max_buffer_sectors;
 
 static int *errors;
-typedef void (*done_f) (int);
+typedef void (*done_f)(int);
 static struct cont_t {
-       void (*interrupt) (void);       /* this is called after the interrupt of the
-                                        * main command */
-       void (*redo) (void);    /* this is called to retry the operation */
-       void (*error) (void);   /* this is called to tally an error */
+       void (*interrupt)(void);
+                               /* this is called after the interrupt of the
+                                * main command */
+       void (*redo)(void);     /* this is called to retry the operation */
+       void (*error)(void);    /* this is called to tally an error */
        done_f done;            /* this is called to say if the operation has
                                 * succeeded/failed */
 } *cont;
@@ -555,6 +557,8 @@ static void process_fd_request(void);
 static void recalibrate_floppy(void);
 static void floppy_shutdown(unsigned long);
 
+static int floppy_request_regions(int);
+static void floppy_release_regions(int);
 static int floppy_grab_irq_and_dma(void);
 static void floppy_release_irq_and_dma(void);
 
@@ -565,7 +569,6 @@ static void floppy_release_irq_and_dma(void);
  * reset doesn't need to be tested before sending commands, because
  * output_byte is automatically disabled when reset is set.
  */
-#define CHECK_RESET { if (FDCS->reset){ reset_fdc(); return; } }
 static void reset_fdc(void);
 
 /*
@@ -573,9 +576,9 @@ static void reset_fdc(void);
  * information to interrupts. They are the data used for the current
  * request.
  */
-#define NO_TRACK -1
-#define NEED_1_RECAL -2
-#define NEED_2_RECAL -3
+#define NO_TRACK       -1
+#define NEED_1_RECAL   -2
+#define NEED_2_RECAL   -3
 
 static int usage_count;
 
@@ -618,15 +621,15 @@ static inline void set_debugt(void)
 static inline void debugt(const char *message)
 {
        if (DP->flags & DEBUGT)
-               printk("%s dtime=%lu\n", message, jiffies - debugtimer);
+               pr_info("%s dtime=%lu\n", message, jiffies - debugtimer);
 }
 #else
 static inline void set_debugt(void) { }
 static inline void debugt(const char *message) { }
 #endif /* DEBUGT */
 
-typedef void (*timeout_fn) (unsigned long);
-static struct timer_list fd_timeout = TIMER_INITIALIZER(floppy_shutdown, 0, 0);
+typedef void (*timeout_fn)(unsigned long);
+static DEFINE_TIMER(fd_timeout, floppy_shutdown, 0, 0);
 
 static const char *timeout_message;
 
@@ -634,20 +637,20 @@ static const char *timeout_message;
 static void is_alive(const char *message)
 {
        /* this routine checks whether the floppy driver is "alive" */
-       if (test_bit(0, &fdc_busy) && command_status < 2
-           && !timer_pending(&fd_timeout)) {
+       if (test_bit(0, &fdc_busy) && command_status < 2 &&
+           !timer_pending(&fd_timeout)) {
                DPRINT("timeout handler died: %s\n", message);
        }
 }
 #endif
 
-static void (*do_floppy) (void) = NULL;
+static void (*do_floppy)(void) = NULL;
 
 #ifdef FLOPPY_SANITY_CHECK
 
 #define OLOGSIZE 20
 
-static void (*lasthandler) (void);
+static void (*lasthandler)(void);
 static unsigned long interruptjiffies;
 static unsigned long resultjiffies;
 static int resultsize;
@@ -670,17 +673,14 @@ static void __reschedule_timeout(int drive, const char *message, int marg)
        if (drive == current_reqD)
                drive = current_drive;
        del_timer(&fd_timeout);
-       if (drive < 0 || drive > N_DRIVE) {
+       if (drive < 0 || drive >= N_DRIVE) {
                fd_timeout.expires = jiffies + 20UL * HZ;
                drive = 0;
        } else
                fd_timeout.expires = jiffies + UDP->timeout;
        add_timer(&fd_timeout);
-       if (UDP->flags & FD_DEBUG) {
-               DPRINT("reschedule timeout ");
-               printk(message, marg);
-               printk("\n");
-       }
+       if (UDP->flags & FD_DEBUG)
+               DPRINT("reschedule timeout %s %d\n", message, marg);
        timeout_message = message;
 }
 
@@ -693,9 +693,8 @@ static void reschedule_timeout(int drive, const char *message, int marg)
        spin_unlock_irqrestore(&floppy_lock, flags);
 }
 
-#define INFBOUND(a,b) (a)=max_t(int, a, b)
-
-#define SUPBOUND(a,b) (a)=min_t(int, a, b)
+#define INFBOUND(a, b) (a) = max_t(int, a, b)
+#define SUPBOUND(a, b) (a) = min_t(int, a, b)
 
 /*
  * Bottom half floppy driver.
@@ -733,8 +732,9 @@ static void reschedule_timeout(int drive, const char *message, int marg)
 static int disk_change(int drive)
 {
        int fdc = FDC(drive);
+
 #ifdef FLOPPY_SANITY_CHECK
-       if (jiffies - UDRS->select_date < UDP->select_delay)
+       if (time_before(jiffies, UDRS->select_date + UDP->select_delay))
                DPRINT("WARNING disk change called early\n");
        if (!(FDCS->dor & (0x10 << UNIT(drive))) ||
            (FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) {
@@ -744,22 +744,20 @@ static int disk_change(int drive)
        }
 #endif
 
-#ifdef DCL_DEBUG
-       if (UDP->flags & FD_DEBUG) {
-               DPRINT("checking disk change line for drive %d\n", drive);
-               DPRINT("jiffies=%lu\n", jiffies);
-               DPRINT("disk change line=%x\n", fd_inb(FD_DIR) & 0x80);
-               DPRINT("flags=%lx\n", UDRS->flags);
-       }
-#endif
+       debug_dcl(UDP->flags,
+                 "checking disk change line for drive %d\n", drive);
+       debug_dcl(UDP->flags, "jiffies=%lu\n", jiffies);
+       debug_dcl(UDP->flags, "disk change line=%x\n", fd_inb(FD_DIR) & 0x80);
+       debug_dcl(UDP->flags, "flags=%lx\n", UDRS->flags);
+
        if (UDP->flags & FD_BROKEN_DCL)
-               return UTESTF(FD_DISK_CHANGED);
+               return test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
        if ((fd_inb(FD_DIR) ^ UDP->flags) & 0x80) {
-               USETF(FD_VERIFY);       /* verify write protection */
-               if (UDRS->maxblock) {
-                       /* mark it changed */
-                       USETF(FD_DISK_CHANGED);
-               }
+               set_bit(FD_VERIFY_BIT, &UDRS->flags);
+                                       /* verify write protection */
+
+               if (UDRS->maxblock)     /* mark it changed */
+                       set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
 
                /* invalidate its geometry */
                if (UDRS->keep_data >= 0) {
@@ -771,11 +769,10 @@ static int disk_change(int drive)
                        floppy_sizes[TOMINOR(drive)] = MAX_DISK_SIZE << 1;
                }
 
-               /*USETF(FD_DISK_NEWCHANGE); */
                return 1;
        } else {
                UDRS->last_checked = jiffies;
-               UCLEARF(FD_DISK_NEWCHANGE);
+               clear_bit(FD_DISK_NEWCHANGE_BIT, &UDRS->flags);
        }
        return 0;
 }
@@ -785,9 +782,18 @@ static inline int is_selected(int dor, int unit)
        return ((dor & (0x10 << unit)) && (dor & 3) == unit);
 }
 
+static bool is_ready_state(int status)
+{
+       int state = status & (STATUS_READY | STATUS_DIR | STATUS_DMA);
+       return state == STATUS_READY;
+}
+
 static int set_dor(int fdc, char mask, char data)
 {
-       register unsigned char drive, unit, newdor, olddor;
+       unsigned char unit;
+       unsigned char drive;
+       unsigned char newdor;
+       unsigned char olddor;
 
        if (FDCS->address == -1)
                return -1;
@@ -798,11 +804,8 @@ static int set_dor(int fdc, char mask, char data)
                unit = olddor & 0x3;
                if (is_selected(olddor, unit) && !is_selected(newdor, unit)) {
                        drive = REVDRIVE(fdc, unit);
-#ifdef DCL_DEBUG
-                       if (UDP->flags & FD_DEBUG) {
-                               DPRINT("calling disk change from set_dor\n");
-                       }
-#endif
+                       debug_dcl(UDP->flags,
+                                 "calling disk change from set_dor\n");
                        disk_change(drive);
                }
                FDCS->dor = newdor;
@@ -814,15 +817,6 @@ static int set_dor(int fdc, char mask, char data)
                        UDRS->select_date = jiffies;
                }
        }
-       /*
-        *      We should propagate failures to grab the resources back
-        *      nicely from here. Actually we ought to rewrite the fd
-        *      driver some day too.
-        */
-       if (newdor & FLOPPY_MOTOR_MASK)
-               floppy_grab_irq_and_dma();
-       if (olddor & FLOPPY_MOTOR_MASK)
-               floppy_release_irq_and_dma();
        return olddor;
 }
 
@@ -835,8 +829,10 @@ static void twaddle(void)
        DRS->select_date = jiffies;
 }
 
-/* reset all driver information about the current fdc. This is needed after
- * a reset, and after a raw command. */
+/*
+ * Reset all driver information about the current fdc.
+ * This is needed after a reset, and after a raw command.
+ */
 static void reset_fdc_info(int mode)
 {
        int drive;
@@ -858,7 +854,7 @@ static void set_fdc(int drive)
                current_drive = drive;
        }
        if (fdc != 1 && fdc != 0) {
-               printk("bad fdc value\n");
+               pr_info("bad fdc value\n");
                return;
        }
        set_dor(fdc, ~0, 8);
@@ -872,16 +868,13 @@ static void set_fdc(int drive)
 }
 
 /* locks the driver */
-static int _lock_fdc(int drive, int interruptible, int line)
+static int _lock_fdc(int drive, bool interruptible, int line)
 {
        if (!usage_count) {
-               printk(KERN_ERR
-                      "Trying to lock fdc while usage count=0 at line %d\n",
+               pr_err("Trying to lock fdc while usage count=0 at line %d\n",
                       line);
                return -1;
        }
-       if (floppy_grab_irq_and_dma() == -1)
-               return -EBUSY;
 
        if (test_and_set_bit(0, &fdc_busy)) {
                DECLARE_WAITQUEUE(wait, current);
@@ -903,6 +896,7 @@ static int _lock_fdc(int drive, int interruptible, int line)
 
                set_current_state(TASK_RUNNING);
                remove_wait_queue(&fdc_wait, &wait);
+               flush_scheduled_work();
        }
        command_status = FD_COMMAND_NONE;
 
@@ -911,10 +905,8 @@ static int _lock_fdc(int drive, int interruptible, int line)
        return 0;
 }
 
-#define lock_fdc(drive,interruptible) _lock_fdc(drive,interruptible, __LINE__)
-
-#define LOCK_FDC(drive,interruptible) \
-if (lock_fdc(drive,interruptible)) return -EINTR;
+#define lock_fdc(drive, interruptible)                 \
+       _lock_fdc(drive, interruptible, __LINE__)
 
 /* unlocks the driver */
 static inline void unlock_fdc(void)
@@ -933,10 +925,9 @@ static inline void unlock_fdc(void)
        del_timer(&fd_timeout);
        cont = NULL;
        clear_bit(0, &fdc_busy);
-       if (elv_next_request(floppy_queue))
+       if (current_req || blk_peek_request(floppy_queue))
                do_fd_request(floppy_queue);
        spin_unlock_irqrestore(&floppy_lock, flags);
-       floppy_release_irq_and_dma();
        wake_up(&fdc_wait);
 }
 
@@ -952,7 +943,7 @@ static void motor_off_callback(unsigned long nr)
 static void floppy_off(unsigned int drive)
 {
        unsigned long volatile delta;
-       register int fdc = FDC(drive);
+       int fdc = FDC(drive);
 
        if (!(FDCS->dor & (0x10 << UNIT(drive))))
                return;
@@ -978,7 +969,9 @@ static void floppy_off(unsigned int drive)
  */
 static void scandrives(void)
 {
-       int i, drive, saved_drive;
+       int i;
+       int drive;
+       int saved_drive;
 
        if (DP->select_delay)
                return;
@@ -1002,15 +995,15 @@ static void empty(void)
 {
 }
 
-static DECLARE_WORK(floppy_work, NULL, NULL);
+static DECLARE_WORK(floppy_work, NULL);
 
-static void schedule_bh(void (*handler) (void))
+static void schedule_bh(void (*handler)(void))
 {
-       PREPARE_WORK(&floppy_work, (void (*)(void *))handler, NULL);
+       PREPARE_WORK(&floppy_work, (work_func_t)handler);
        schedule_work(&floppy_work);
 }
 
-static struct timer_list fd_timer = TIMER_INITIALIZER(NULL, 0, 0);
+static DEFINE_TIMER(fd_timer, NULL, 0, 0);
 
 static void cancel_activity(void)
 {
@@ -1018,7 +1011,7 @@ static void cancel_activity(void)
 
        spin_lock_irqsave(&floppy_lock, flags);
        do_floppy = NULL;
-       PREPARE_WORK(&floppy_work, (void *)empty, NULL);
+       PREPARE_WORK(&floppy_work, (work_func_t)empty);
        del_timer(&fd_timer);
        spin_unlock_irqrestore(&floppy_lock, flags);
 }
@@ -1027,11 +1020,7 @@ static void cancel_activity(void)
  * transfer */
 static void fd_watchdog(void)
 {
-#ifdef DCL_DEBUG
-       if (DP->flags & FD_DEBUG) {
-               DPRINT("calling disk change from watchdog\n");
-       }
-#endif
+       debug_dcl(DP->flags, "calling disk change from watchdog\n");
 
        if (disk_change(current_drive)) {
                DPRINT("disk removed during i/o\n");
@@ -1040,7 +1029,7 @@ static void fd_watchdog(void)
                reset_fdc();
        } else {
                del_timer(&fd_timer);
-               fd_timer.function = (timeout_fn) fd_watchdog;
+               fd_timer.function = (timeout_fn)fd_watchdog;
                fd_timer.expires = jiffies + HZ / 10;
                add_timer(&fd_timer);
        }
@@ -1062,7 +1051,7 @@ static int fd_wait_for_completion(unsigned long delay, timeout_fn function)
                return 1;
        }
 
-       if ((signed)(jiffies - delay) < 0) {
+       if (time_before(jiffies, delay)) {
                del_timer(&fd_timer);
                fd_timer.function = function;
                fd_timer.expires = delay;
@@ -1110,16 +1099,16 @@ static void setup_DMA(void)
        if (raw_cmd->length == 0) {
                int i;
 
-               printk("zero dma transfer size:");
+               pr_info("zero dma transfer size:");
                for (i = 0; i < raw_cmd->cmd_count; i++)
-                       printk("%x,", raw_cmd->cmd[i]);
-               printk("\n");
+                       pr_cont("%x,", raw_cmd->cmd[i]);
+               pr_cont("\n");
                cont->done(0);
                FDCS->reset = 1;
                return;
        }
        if (((unsigned long)raw_cmd->kernel_data) % 512) {
-               printk("non aligned address: %p\n", raw_cmd->kernel_data);
+               pr_info("non aligned address: %p\n", raw_cmd->kernel_data);
                cont->done(0);
                FDCS->reset = 1;
                return;
@@ -1156,7 +1145,9 @@ static void show_floppy(void);
 /* waits until the fdc becomes ready */
 static int wait_til_ready(void)
 {
-       int counter, status;
+       int status;
+       int counter;
+
        if (FDCS->reset)
                return -1;
        for (counter = 0; counter < 10000; counter++) {
@@ -1164,7 +1155,7 @@ static int wait_til_ready(void)
                if (status & STATUS_READY)
                        return status;
        }
-       if (!initialising) {
+       if (initialized) {
                DPRINT("Getstatus times out (%x) on fdc %d\n", status, fdc);
                show_floppy();
        }
@@ -1175,11 +1166,12 @@ static int wait_til_ready(void)
 /* sends a command byte to the fdc */
 static int output_byte(char byte)
 {
-       int status;
+       int status = wait_til_ready();
 
-       if ((status = wait_til_ready()) < 0)
+       if (status < 0)
                return -1;
-       if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY) {
+
+       if (is_ready_state(status)) {
                fd_outb(byte, FD_DATA);
 #ifdef FLOPPY_SANITY_CHECK
                output_log[output_log_pos].data = byte;
@@ -1190,7 +1182,7 @@ static int output_byte(char byte)
                return 0;
        }
        FDCS->reset = 1;
-       if (!initialising) {
+       if (initialized) {
                DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n",
                       byte, fdc, status);
                show_floppy();
@@ -1198,15 +1190,15 @@ static int output_byte(char byte)
        return -1;
 }
 
-#define LAST_OUT(x) if (output_byte(x)<0){ reset_fdc();return;}
-
 /* gets the response from the fdc */
 static int result(void)
 {
-       int i, status = 0;
+       int i;
+       int status = 0;
 
        for (i = 0; i < MAX_REPLIES; i++) {
-               if ((status = wait_til_ready()) < 0)
+               status = wait_til_ready();
+               if (status < 0)
                        break;
                status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA;
                if ((status & ~STATUS_BUSY) == STATUS_READY) {
@@ -1221,10 +1213,9 @@ static int result(void)
                else
                        break;
        }
-       if (!initialising) {
-               DPRINT
-                   ("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
-                    fdc, status, i);
+       if (initialized) {
+               DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
+                      fdc, status, i);
                show_floppy();
        }
        FDCS->reset = 1;
@@ -1235,11 +1226,14 @@ static int result(void)
 /* does the fdc need more output? */
 static int need_more_output(void)
 {
-       int status;
-       if ((status = wait_til_ready()) < 0)
+       int status = wait_til_ready();
+
+       if (status < 0)
                return -1;
-       if ((status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY)
+
+       if (is_ready_state(status))
                return MORE_OUTPUT;
+
        return result();
 }
 
@@ -1261,9 +1255,12 @@ static inline void perpendicular_mode(void)
                default:
                        DPRINT("Invalid data rate for perpendicular mode!\n");
                        cont->done(0);
-                       FDCS->reset = 1;        /* convenient way to return to
-                                                * redo without to much hassle (deep
-                                                * stack et al. */
+                       FDCS->reset = 1;
+                                       /*
+                                        * convenient way to return to
+                                        * redo without too much hassle
+                                        * (deep stack et al.)
+                                        */
                        return;
                }
        } else
@@ -1319,8 +1316,11 @@ static int fdc_configure(void)
  */
 static void fdc_specify(void)
 {
-       unsigned char spec1, spec2;
-       unsigned long srt, hlt, hut;
+       unsigned char spec1;
+       unsigned char spec2;
+       unsigned long srt;
+       unsigned long hlt;
+       unsigned long hut;
        unsigned long dtr = NOMINAL_DTR;
        unsigned long scale_dtr = NOMINAL_DTR;
        int hlt_max_code = 0x7f;
@@ -1329,7 +1329,6 @@ static void fdc_specify(void)
        if (FDCS->need_configure && FDCS->version >= FDC_82072A) {
                fdc_configure();
                FDCS->need_configure = 0;
-               /*DPRINT("FIFO enabled\n"); */
        }
 
        switch (raw_cmd->rate & 0x03) {
@@ -1360,20 +1359,20 @@ static void fdc_specify(void)
        }
 
        /* Convert step rate from microseconds to milliseconds and 4 bits */
-       srt = 16 - (DP->srt * scale_dtr / 1000 + NOMINAL_DTR - 1) / NOMINAL_DTR;
-       if (slow_floppy) {
+       srt = 16 - DIV_ROUND_UP(DP->srt * scale_dtr / 1000, NOMINAL_DTR);
+       if (slow_floppy)
                srt = srt / 4;
-       }
+
        SUPBOUND(srt, 0xf);
        INFBOUND(srt, 0);
 
-       hlt = (DP->hlt * scale_dtr / 2 + NOMINAL_DTR - 1) / NOMINAL_DTR;
+       hlt = DIV_ROUND_UP(DP->hlt * scale_dtr / 2, NOMINAL_DTR);
        if (hlt < 0x01)
                hlt = 0x01;
        else if (hlt > 0x7f)
                hlt = hlt_max_code;
 
-       hut = (DP->hut * scale_dtr / 16 + NOMINAL_DTR - 1) / NOMINAL_DTR;
+       hut = DIV_ROUND_UP(DP->hut * scale_dtr / 16, NOMINAL_DTR);
        if (hut < 0x1)
                hut = 0x1;
        else if (hut > 0xf)
@@ -1410,16 +1409,46 @@ static int fdc_dtr(void)
         * Pause 5 msec to avoid trouble. (Needs to be 2 jiffies)
         */
        FDCS->dtr = raw_cmd->rate & 3;
-       return (fd_wait_for_completion(jiffies + 2UL * HZ / 100,
-                                      (timeout_fn) floppy_ready));
+       return fd_wait_for_completion(jiffies + 2UL * HZ / 100,
+                                     (timeout_fn)floppy_ready);
 }                              /* fdc_dtr */
 
 static void tell_sector(void)
 {
-       printk(": track %d, head %d, sector %d, size %d",
-              R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE);
+       pr_cont(": track %d, head %d, sector %d, size %d",
+               R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE);
 }                              /* tell_sector */
 
+static void print_errors(void)
+{
+       DPRINT("");
+       if (ST0 & ST0_ECE) {
+               pr_cont("Recalibrate failed!");
+       } else if (ST2 & ST2_CRC) {
+               pr_cont("data CRC error");
+               tell_sector();
+       } else if (ST1 & ST1_CRC) {
+               pr_cont("CRC error");
+               tell_sector();
+       } else if ((ST1 & (ST1_MAM | ST1_ND)) ||
+                  (ST2 & ST2_MAM)) {
+               if (!probing) {
+                       pr_cont("sector not found");
+                       tell_sector();
+               } else
+                       pr_cont("probe failed...");
+       } else if (ST2 & ST2_WC) {      /* seek error */
+               pr_cont("wrong cylinder");
+       } else if (ST2 & ST2_BC) {      /* cylinder marked as bad */
+               pr_cont("bad cylinder");
+       } else {
+               pr_cont("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x",
+                       ST0, ST1, ST2);
+               tell_sector();
+       }
+       pr_cont("\n");
+}
+
 /*
  * OK, this error interpreting routine is called after a
  * DMA read/write has succeeded
@@ -1445,44 +1474,17 @@ static int interpret_errors(void)
                bad = 1;
                if (ST1 & ST1_WP) {
                        DPRINT("Drive is write protected\n");
-                       CLEARF(FD_DISK_WRITABLE);
+                       clear_bit(FD_DISK_WRITABLE_BIT, &DRS->flags);
                        cont->done(0);
                        bad = 2;
                } else if (ST1 & ST1_ND) {
-                       SETF(FD_NEED_TWADDLE);
+                       set_bit(FD_NEED_TWADDLE_BIT, &DRS->flags);
                } else if (ST1 & ST1_OR) {
                        if (DP->flags & FTD_MSG)
                                DPRINT("Over/Underrun - retrying\n");
                        bad = 0;
                } else if (*errors >= DP->max_errors.reporting) {
-                       DPRINT("");
-                       if (ST0 & ST0_ECE) {
-                               printk("Recalibrate failed!");
-                       } else if (ST2 & ST2_CRC) {
-                               printk("data CRC error");
-                               tell_sector();
-                       } else if (ST1 & ST1_CRC) {
-                               printk("CRC error");
-                               tell_sector();
-                       } else if ((ST1 & (ST1_MAM | ST1_ND))
-                                  || (ST2 & ST2_MAM)) {
-                               if (!probing) {
-                                       printk("sector not found");
-                                       tell_sector();
-                               } else
-                                       printk("probe failed...");
-                       } else if (ST2 & ST2_WC) {      /* seek error */
-                               printk("wrong cylinder");
-                       } else if (ST2 & ST2_BC) {      /* cylinder marked as bad */
-                               printk("bad cylinder");
-                       } else {
-                               printk
-                                   ("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x",
-                                    ST0, ST1, ST2);
-                               tell_sector();
-                       }
-                       printk("\n");
-
+                       print_errors();
                }
                if (ST2 & ST2_WC || ST2 & ST2_BC)
                        /* wrong cylinder => recal */
@@ -1508,7 +1510,10 @@ static int interpret_errors(void)
  */
 static void setup_rw_floppy(void)
 {
-       int i, r, flags, dflags;
+       int i;
+       int r;
+       int flags;
+       int dflags;
        unsigned long ready_date;
        timeout_fn function;
 
@@ -1522,11 +1527,11 @@ static void setup_rw_floppy(void)
                 * again just before spinup completion. Beware that
                 * after scandrives, we must again wait for selection.
                 */
-               if ((signed)(ready_date - jiffies) > DP->select_delay) {
+               if (time_after(ready_date, jiffies + DP->select_delay)) {
                        ready_date -= DP->select_delay;
-                       function = (timeout_fn) floppy_start;
+                       function = (timeout_fn)floppy_start;
                } else
-                       function = (timeout_fn) setup_rw_floppy;
+                       function = (timeout_fn)setup_rw_floppy;
 
                /* wait until the floppy is spinning fast enough */
                if (fd_wait_for_completion(ready_date, function))
@@ -1576,14 +1581,11 @@ static void seek_interrupt(void)
                return;
        }
        if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek) {
-#ifdef DCL_DEBUG
-               if (DP->flags & FD_DEBUG) {
-                       DPRINT
-                           ("clearing NEWCHANGE flag because of effective seek\n");
-                       DPRINT("jiffies=%lu\n", jiffies);
-               }
-#endif
-               CLEARF(FD_DISK_NEWCHANGE);      /* effective seek */
+               debug_dcl(DP->flags,
+                         "clearing NEWCHANGE flag because of effective seek\n");
+               debug_dcl(DP->flags, "jiffies=%lu\n", jiffies);
+               clear_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags);
+                                       /* effective seek */
                DRS->select_date = jiffies;
        }
        DRS->track = ST1;
@@ -1592,26 +1594,23 @@ static void seek_interrupt(void)
 
 static void check_wp(void)
 {
-       if (TESTF(FD_VERIFY)) {
-               /* check write protection */
+       if (test_bit(FD_VERIFY_BIT, &DRS->flags)) {
+                                       /* check write protection */
                output_byte(FD_GETSTATUS);
                output_byte(UNIT(current_drive));
                if (result() != 1) {
                        FDCS->reset = 1;
                        return;
                }
-               CLEARF(FD_VERIFY);
-               CLEARF(FD_NEED_TWADDLE);
-#ifdef DCL_DEBUG
-               if (DP->flags & FD_DEBUG) {
-                       DPRINT("checking whether disk is write protected\n");
-                       DPRINT("wp=%x\n", ST3 & 0x40);
-               }
-#endif
+               clear_bit(FD_VERIFY_BIT, &DRS->flags);
+               clear_bit(FD_NEED_TWADDLE_BIT, &DRS->flags);
+               debug_dcl(DP->flags,
+                         "checking whether disk is write protected\n");
+               debug_dcl(DP->flags, "wp=%x\n", ST3 & 0x40);
                if (!(ST3 & 0x40))
-                       SETF(FD_DISK_WRITABLE);
+                       set_bit(FD_DISK_WRITABLE_BIT, &DRS->flags);
                else
-                       CLEARF(FD_DISK_WRITABLE);
+                       clear_bit(FD_DISK_WRITABLE_BIT, &DRS->flags);
        }
 }
 
@@ -1621,19 +1620,15 @@ static void seek_floppy(void)
 
        blind_seek = 0;
 
-#ifdef DCL_DEBUG
-       if (DP->flags & FD_DEBUG) {
-               DPRINT("calling disk change from seek\n");
-       }
-#endif
+       debug_dcl(DP->flags, "calling disk change from seek\n");
 
-       if (!TESTF(FD_DISK_NEWCHANGE) &&
+       if (!test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) &&
            disk_change(current_drive) && (raw_cmd->flags & FD_RAW_NEED_DISK)) {
                /* the media changed flag should be cleared after the seek.
                 * If it isn't, this means that there is really no disk in
                 * the drive.
                 */
-               SETF(FD_DISK_CHANGED);
+               set_bit(FD_DISK_CHANGED_BIT, &DRS->flags);
                cont->done(0);
                cont->redo();
                return;
@@ -1641,7 +1636,7 @@ static void seek_floppy(void)
        if (DRS->track <= NEED_1_RECAL) {
                recalibrate_floppy();
                return;
-       } else if (TESTF(FD_DISK_NEWCHANGE) &&
+       } else if (test_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags) &&
                   (raw_cmd->flags & FD_RAW_NEED_DISK) &&
                   (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) {
                /* we seek to clear the media-changed condition. Does anybody
@@ -1670,7 +1665,10 @@ static void seek_floppy(void)
        do_floppy = seek_interrupt;
        output_byte(FD_SEEK);
        output_byte(UNIT(current_drive));
-       LAST_OUT(track);
+       if (output_byte(track) < 0) {
+               reset_fdc();
+               return;
+       }
        debugt("seek command:");
 }
 
@@ -1698,14 +1696,10 @@ static void recal_interrupt(void)
                         * not to move at recalibration is to
                         * be already at track 0.) Clear the
                         * new change flag */
-#ifdef DCL_DEBUG
-                       if (DP->flags & FD_DEBUG) {
-                               DPRINT
-                                   ("clearing NEWCHANGE flag because of second recalibrate\n");
-                       }
-#endif
+                       debug_dcl(DP->flags,
+                                 "clearing NEWCHANGE flag because of second recalibrate\n");
 
-                       CLEARF(FD_DISK_NEWCHANGE);
+                       clear_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags);
                        DRS->select_date = jiffies;
                        /* fall through */
                default:
@@ -1731,16 +1725,16 @@ static void print_result(char *message, int inr)
        DPRINT("%s ", message);
        if (inr >= 0)
                for (i = 0; i < inr; i++)
-                       printk("repl[%d]=%x ", i, reply_buffer[i]);
-       printk("\n");
+                       pr_cont("repl[%d]=%x ", i, reply_buffer[i]);
+       pr_cont("\n");
 }
 
 /* interrupt handler. Note that this can be called externally on the Sparc */
-irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t floppy_interrupt(int irq, void *dev_id)
 {
-       void (*handler) (void) = do_floppy;
        int do_print;
        unsigned long f;
+       void (*handler)(void) = do_floppy;
 
        lasthandler = handler;
        interruptjiffies = jiffies;
@@ -1753,9 +1747,9 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        do_floppy = NULL;
        if (fdc >= N_FDC || FDCS->address == -1) {
                /* we don't even know which FDC is the culprit */
-               printk("DOR0=%x\n", fdc_state[0].dor);
-               printk("floppy interrupt on bizarre fdc %d\n", fdc);
-               printk("handler=%p\n", handler);
+               pr_info("DOR0=%x\n", fdc_state[0].dor);
+               pr_info("floppy interrupt on bizarre fdc %d\n", fdc);
+               pr_info("handler=%p\n", handler);
                is_alive("bizarre fdc");
                return IRQ_NONE;
        }
@@ -1770,7 +1764,7 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         * activity.
         */
 
-       do_print = !handler && print_unex && !initialising;
+       do_print = !handler && print_unex && initialized;
 
        inr = result();
        if (do_print)
@@ -1783,8 +1777,8 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        if (do_print)
                                print_result("sensei", inr);
                        max_sensei--;
-               } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2
-                        && max_sensei);
+               } while ((ST0 & 0x83) != UNIT(current_drive) &&
+                        inr == 2 && max_sensei);
        }
        if (!handler) {
                FDCS->reset = 1;
@@ -1802,7 +1796,10 @@ static void recalibrate_floppy(void)
        debugt("recalibrate floppy:");
        do_floppy = recal_interrupt;
        output_byte(FD_RECALIBRATE);
-       LAST_OUT(UNIT(current_drive));
+       if (output_byte(UNIT(current_drive)) < 0) {
+               reset_fdc();
+               return;
+       }
 }
 
 /*
@@ -1813,7 +1810,7 @@ static void reset_interrupt(void)
        debugt("reset interrupt:");
        result();               /* get the status ready for set_fdc */
        if (FDCS->reset) {
-               printk("reset set in interrupt, calling %p\n", cont->error);
+               pr_info("reset set in interrupt, calling %p\n", cont->error);
                cont->error();  /* a reset just after a reset. BAD! */
        }
        cont->redo();
@@ -1851,53 +1848,51 @@ static void show_floppy(void)
 {
        int i;
 
-       printk("\n");
-       printk("floppy driver state\n");
-       printk("-------------------\n");
-       printk("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n",
-              jiffies, interruptjiffies, jiffies - interruptjiffies,
-              lasthandler);
+       pr_info("\n");
+       pr_info("floppy driver state\n");
+       pr_info("-------------------\n");
+       pr_info("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n",
+               jiffies, interruptjiffies, jiffies - interruptjiffies,
+               lasthandler);
 
 #ifdef FLOPPY_SANITY_CHECK
-       printk("timeout_message=%s\n", timeout_message);
-       printk("last output bytes:\n");
+       pr_info("timeout_message=%s\n", timeout_message);
+       pr_info("last output bytes:\n");
        for (i = 0; i < OLOGSIZE; i++)
-               printk("%2x %2x %lu\n",
-                      output_log[(i + output_log_pos) % OLOGSIZE].data,
-                      output_log[(i + output_log_pos) % OLOGSIZE].status,
-                      output_log[(i + output_log_pos) % OLOGSIZE].jiffies);
-       printk("last result at %lu\n", resultjiffies);
-       printk("last redo_fd_request at %lu\n", lastredo);
-       for (i = 0; i < resultsize; i++) {
-               printk("%2x ", reply_buffer[i]);
-       }
-       printk("\n");
+               pr_info("%2x %2x %lu\n",
+                       output_log[(i + output_log_pos) % OLOGSIZE].data,
+                       output_log[(i + output_log_pos) % OLOGSIZE].status,
+                       output_log[(i + output_log_pos) % OLOGSIZE].jiffies);
+       pr_info("last result at %lu\n", resultjiffies);
+       pr_info("last redo_fd_request at %lu\n", lastredo);
+       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1,
+                      reply_buffer, resultsize, true);
 #endif
 
-       printk("status=%x\n", fd_inb(FD_STATUS));
-       printk("fdc_busy=%lu\n", fdc_busy);
+       pr_info("status=%x\n", fd_inb(FD_STATUS));
+       pr_info("fdc_busy=%lu\n", fdc_busy);
        if (do_floppy)
-               printk("do_floppy=%p\n", do_floppy);
-       if (floppy_work.pending)
-               printk("floppy_work.func=%p\n", floppy_work.func);
+               pr_info("do_floppy=%p\n", do_floppy);
+       if (work_pending(&floppy_work))
+               pr_info("floppy_work.func=%p\n", floppy_work.func);
        if (timer_pending(&fd_timer))
-               printk("fd_timer.function=%p\n", fd_timer.function);
+               pr_info("fd_timer.function=%p\n", fd_timer.function);
        if (timer_pending(&fd_timeout)) {
-               printk("timer_function=%p\n", fd_timeout.function);
-               printk("expires=%lu\n", fd_timeout.expires - jiffies);
-               printk("now=%lu\n", jiffies);
-       }
-       printk("cont=%p\n", cont);
-       printk("current_req=%p\n", current_req);
-       printk("command_status=%d\n", command_status);
-       printk("\n");
+               pr_info("timer_function=%p\n", fd_timeout.function);
+               pr_info("expires=%lu\n", fd_timeout.expires - jiffies);
+               pr_info("now=%lu\n", jiffies);
+       }
+       pr_info("cont=%p\n", cont);
+       pr_info("current_req=%p\n", current_req);
+       pr_info("command_status=%d\n", command_status);
+       pr_info("\n");
 }
 
 static void floppy_shutdown(unsigned long data)
 {
        unsigned long flags;
 
-       if (!initialising)
+       if (initialized)
                show_floppy();
        cancel_activity();
 
@@ -1909,25 +1904,24 @@ static void floppy_shutdown(unsigned long data)
 
        /* avoid dma going to a random drive after shutdown */
 
-       if (!initialising)
+       if (initialized)
                DPRINT("floppy timeout called\n");
        FDCS->reset = 1;
        if (cont) {
                cont->done(0);
                cont->redo();   /* this will recall reset when needed */
        } else {
-               printk("no cont in shutdown!\n");
+               pr_info("no cont in shutdown!\n");
                process_fd_request();
        }
        is_alive("floppy shutdown");
 }
 
-/*typedef void (*timeout_fn)(unsigned long);*/
-
 /* start motor, check media-changed condition and write protection */
-static int start_motor(void (*function) (void))
+static int start_motor(void (*function)(void))
 {
-       int mask, data;
+       int mask;
+       int data;
 
        mask = 0xfc;
        data = UNIT(current_drive);
@@ -1948,27 +1942,26 @@ static int start_motor(void (*function) (void))
        set_dor(fdc, mask, data);
 
        /* wait_for_completion also schedules reset if needed. */
-       return (fd_wait_for_completion(DRS->select_date + DP->select_delay,
-                                      (timeout_fn) function));
+       return fd_wait_for_completion(DRS->select_date + DP->select_delay,
+                                     (timeout_fn)function);
 }
 
 static void floppy_ready(void)
 {
-       CHECK_RESET;
+       if (FDCS->reset) {
+               reset_fdc();
+               return;
+       }
        if (start_motor(floppy_ready))
                return;
        if (fdc_dtr())
                return;
 
-#ifdef DCL_DEBUG
-       if (DP->flags & FD_DEBUG) {
-               DPRINT("calling disk change from floppy_ready\n");
-       }
-#endif
+       debug_dcl(DP->flags, "calling disk change from floppy_ready\n");
        if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) &&
            disk_change(current_drive) && !DP->select_delay)
-               twaddle();      /* this clears the dcl on certain drive/controller
-                                * combinations */
+               twaddle();      /* this clears the dcl on certain
+                                * drive/controller combinations */
 
 #ifdef fd_chose_dma_mode
        if ((raw_cmd->flags & FD_RAW_READ) || (raw_cmd->flags & FD_RAW_WRITE)) {
@@ -1995,12 +1988,8 @@ static void floppy_start(void)
        reschedule_timeout(current_reqD, "floppy start", 0);
 
        scandrives();
-#ifdef DCL_DEBUG
-       if (DP->flags & FD_DEBUG) {
-               DPRINT("setting NEWCHANGE in floppy_start\n");
-       }
-#endif
-       SETF(FD_DISK_NEWCHANGE);
+       debug_dcl(DP->flags, "setting NEWCHANGE in floppy_start\n");
+       set_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags);
        floppy_ready();
 }
 
@@ -2030,17 +2019,17 @@ static struct cont_t wakeup_cont = {
        .interrupt      = empty,
        .redo           = do_wakeup,
        .error          = empty,
-       .done           = (done_f) empty
+       .done           = (done_f)empty
 };
 
 static struct cont_t intr_cont = {
        .interrupt      = empty,
        .redo           = process_fd_request,
        .error          = empty,
-       .done           = (done_f) empty
+       .done           = (done_f)empty
 };
 
-static int wait_til_done(void (*handler) (void), int interruptible)
+static int wait_til_done(void (*handler)(void), bool interruptible)
 {
        int ret;
 
@@ -2059,7 +2048,6 @@ static int wait_til_done(void (*handler) (void), int interruptible)
                                break;
 
                        is_alive("wait_til_done");
-
                        schedule();
                }
 
@@ -2151,6 +2139,7 @@ static void bad_flp_intr(void)
 static void set_floppy(int drive)
 {
        int type = ITYPE(UDRS->fd_device);
+
        if (type)
                _floppy = floppy_type + type;
        else
@@ -2175,21 +2164,25 @@ static void format_interrupt(void)
 }
 
 #define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2)
-#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1))
+#define FM_MODE(x, y) ((y) & ~(((x)->rate & 0x80) >> 1))
 #define CT(x) ((x) | 0xc0)
+
 static void setup_format_params(int track)
 {
+       int n;
+       int il;
+       int count;
+       int head_shift;
+       int track_shift;
        struct fparm {
                unsigned char track, head, sect, size;
        } *here = (struct fparm *)floppy_track_buffer;
-       int il, n;
-       int count, head_shift, track_shift;
 
        raw_cmd = &default_raw_cmd;
        raw_cmd->track = track;
 
-       raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
-           FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK;
+       raw_cmd->flags = (FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN |
+                         FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK);
        raw_cmd->rate = _floppy->rate & 0x43;
        raw_cmd->cmd_count = NR_F;
        COMMAND = FM_MODE(_floppy, FD_FORMAT);
@@ -2237,9 +2230,9 @@ static void setup_format_params(int track)
                        }
                }
        }
-       if (_floppy->stretch & FD_ZEROBASED) {
+       if (_floppy->stretch & FD_SECTBASEMASK) {
                for (count = 0; count < F_SECT_PER_TRACK; count++)
-                       here[count].sect--;
+                       here[count].sect += FD_SECTBASE(_floppy) - 1;
        }
 }
 
@@ -2262,7 +2255,9 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
 {
        int ret;
 
-       LOCK_FDC(drive, 1);
+       if (lock_fdc(drive, true))
+               return -EINTR;
+
        set_floppy(drive);
        if (!_floppy ||
            _floppy->track > DP->tracks ||
@@ -2277,7 +2272,9 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
        format_errors = 0;
        cont = &format_cont;
        errors = &format_errors;
-       IWAIT(redo_format);
+       ret = wait_til_done(redo_format, true);
+       if (ret == -EINTR)
+               return -EINTR;
        process_fd_request();
        return ret;
 }
@@ -2287,21 +2284,19 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
  * =============================
  */
 
-static void floppy_end_request(struct request *req, int uptodate)
+static void floppy_end_request(struct request *req, int error)
 {
        unsigned int nr_sectors = current_count_sectors;
+       unsigned int drive = (unsigned long)req->rq_disk->private_data;
 
        /* current_count_sectors can be zero if transfer failed */
-       if (!uptodate)
-               nr_sectors = req->current_nr_sectors;
-       if (end_that_request_first(req, uptodate, nr_sectors))
+       if (error)
+               nr_sectors = blk_rq_cur_sectors(req);
+       if (__blk_end_request(req, error, nr_sectors << 9))
                return;
-       add_disk_randomness(req->rq_disk);
-       floppy_off((long)req->rq_disk->private_data);
-       blkdev_dequeue_request(req);
-       end_that_request_last(req);
 
        /* We're done with the request */
+       floppy_off(drive);
        current_req = NULL;
 }
 
@@ -2315,38 +2310,38 @@ static void request_done(int uptodate)
        int block;
 
        probing = 0;
-       reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate);
+       reschedule_timeout(MAXTIMEOUT, "request done", uptodate);
 
        if (!req) {
-               printk("floppy.c: no request in request_done\n");
+               pr_info("floppy.c: no request in request_done\n");
                return;
        }
 
        if (uptodate) {
                /* maintain values for invalidation on geometry
                 * change */
-               block = current_count_sectors + req->sector;
+               block = current_count_sectors + blk_rq_pos(req);
                INFBOUND(DRS->maxblock, block);
                if (block > _floppy->sect)
                        DRS->maxtrack = 1;
 
                /* unlock chained buffers */
                spin_lock_irqsave(q->queue_lock, flags);
-               floppy_end_request(req, 1);
+               floppy_end_request(req, 0);
                spin_unlock_irqrestore(q->queue_lock, flags);
        } else {
                if (rq_data_dir(req) == WRITE) {
                        /* record write error information */
                        DRWE->write_errors++;
                        if (DRWE->write_errors == 1) {
-                               DRWE->first_error_sector = req->sector;
+                               DRWE->first_error_sector = blk_rq_pos(req);
                                DRWE->first_error_generation = DRS->generation;
                        }
-                       DRWE->last_error_sector = req->sector;
+                       DRWE->last_error_sector = blk_rq_pos(req);
                        DRWE->last_error_generation = DRS->generation;
                }
                spin_lock_irqsave(q->queue_lock, flags);
-               floppy_end_request(req, 0);
+               floppy_end_request(req, -EIO);
                spin_unlock_irqrestore(q->queue_lock, flags);
        }
 }
@@ -2354,7 +2349,10 @@ static void request_done(int uptodate)
 /* Interrupt handler evaluating the result of the r/w operation */
 static void rw_interrupt(void)
 {
-       int nr_sectors, ssize, eoc, heads;
+       int eoc;
+       int ssize;
+       int heads;
+       int nr_sectors;
 
        if (R_HEAD >= 2) {
                /* some Toshiba floppy controllers occasionnally seem to
@@ -2385,16 +2383,16 @@ static void rw_interrupt(void)
 
 #ifdef FLOPPY_SANITY_CHECK
        if (nr_sectors / ssize >
-           (in_sector_offset + current_count_sectors + ssize - 1) / ssize) {
+           DIV_ROUND_UP(in_sector_offset + current_count_sectors, ssize)) {
                DPRINT("long rw: %x instead of %lx\n",
                       nr_sectors, current_count_sectors);
-               printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
-               printk("rh=%d h=%d\n", R_HEAD, HEAD);
-               printk("rt=%d t=%d\n", R_TRACK, TRACK);
-               printk("heads=%d eoc=%d\n", heads, eoc);
-               printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK,
-                      fsector_t, ssize);
-               printk("in_sector_offset=%d\n", in_sector_offset);
+               pr_info("rs=%d s=%d\n", R_SECTOR, SECTOR);
+               pr_info("rh=%d h=%d\n", R_HEAD, HEAD);
+               pr_info("rt=%d t=%d\n", R_TRACK, TRACK);
+               pr_info("heads=%d eoc=%d\n", heads, eoc);
+               pr_info("spt=%d st=%d ss=%d\n",
+                       SECT_PER_TRACK, fsector_t, ssize);
+               pr_info("in_sector_offset=%d\n", in_sector_offset);
        }
 #endif
 
@@ -2447,22 +2445,19 @@ static void rw_interrupt(void)
 /* Compute maximal contiguous buffer size. */
 static int buffer_chain_size(void)
 {
-       struct bio *bio;
        struct bio_vec *bv;
-       int size, i;
+       int size;
+       struct req_iterator iter;
        char *base;
 
        base = bio_data(current_req->bio);
        size = 0;
 
-       rq_for_each_bio(bio, current_req) {
-               bio_for_each_segment(bv, bio, i) {
-                       if (page_address(bv->bv_page) + bv->bv_offset !=
-                           base + size)
-                               break;
+       rq_for_each_segment(bv, current_req, iter) {
+               if (page_address(bv->bv_page) + bv->bv_offset != base + size)
+                       break;
 
-                       size += bv->bv_len;
-               }
+               size += bv->bv_len;
        }
 
        return size >> 9;
@@ -2489,32 +2484,32 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
 {
        int remaining;          /* number of transferred 512-byte sectors */
        struct bio_vec *bv;
-       struct bio *bio;
-       char *buffer, *dma_buffer;
-       int size, i;
+       char *buffer;
+       char *dma_buffer;
+       int size;
+       struct req_iterator iter;
 
        max_sector = transfer_size(ssize,
                                   min(max_sector, max_sector_2),
-                                  current_req->nr_sectors);
+                                  blk_rq_sectors(current_req));
 
        if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE &&
-           buffer_max > fsector_t + current_req->nr_sectors)
+           buffer_max > fsector_t + blk_rq_sectors(current_req))
                current_count_sectors = min_t(int, buffer_max - fsector_t,
-                                             current_req->nr_sectors);
+                                             blk_rq_sectors(current_req));
 
        remaining = current_count_sectors << 9;
 #ifdef FLOPPY_SANITY_CHECK
-       if ((remaining >> 9) > current_req->nr_sectors &&
-           CT(COMMAND) == FD_WRITE) {
+       if (remaining > blk_rq_bytes(current_req) && CT(COMMAND) == FD_WRITE) {
                DPRINT("in copy buffer\n");
-               printk("current_count_sectors=%ld\n", current_count_sectors);
-               printk("remaining=%d\n", remaining >> 9);
-               printk("current_req->nr_sectors=%ld\n",
-                      current_req->nr_sectors);
-               printk("current_req->current_nr_sectors=%u\n",
-                      current_req->current_nr_sectors);
-               printk("max_sector=%d\n", max_sector);
-               printk("ssize=%d\n", ssize);
+               pr_info("current_count_sectors=%ld\n", current_count_sectors);
+               pr_info("remaining=%d\n", remaining >> 9);
+               pr_info("current_req->nr_sectors=%u\n",
+                       blk_rq_sectors(current_req));
+               pr_info("current_req->current_nr_sectors=%u\n",
+                       blk_rq_cur_sectors(current_req));
+               pr_info("max_sector=%d\n", max_sector);
+               pr_info("ssize=%d\n", ssize);
        }
 #endif
 
@@ -2522,45 +2517,42 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
 
        dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9);
 
-       size = current_req->current_nr_sectors << 9;
+       size = blk_rq_cur_bytes(current_req);
 
-       rq_for_each_bio(bio, current_req) {
-               bio_for_each_segment(bv, bio, i) {
-                       if (!remaining)
-                               break;
+       rq_for_each_segment(bv, current_req, iter) {
+               if (!remaining)
+                       break;
 
-                       size = bv->bv_len;
-                       SUPBOUND(size, remaining);
+               size = bv->bv_len;
+               SUPBOUND(size, remaining);
 
-                       buffer = page_address(bv->bv_page) + bv->bv_offset;
+               buffer = page_address(bv->bv_page) + bv->bv_offset;
 #ifdef FLOPPY_SANITY_CHECK
-                       if (dma_buffer + size >
-                           floppy_track_buffer + (max_buffer_sectors << 10) ||
-                           dma_buffer < floppy_track_buffer) {
-                               DPRINT("buffer overrun in copy buffer %d\n",
-                                      (int)((floppy_track_buffer -
-                                             dma_buffer) >> 9));
-                               printk("fsector_t=%d buffer_min=%d\n",
-                                      fsector_t, buffer_min);
-                               printk("current_count_sectors=%ld\n",
-                                      current_count_sectors);
-                               if (CT(COMMAND) == FD_READ)
-                                       printk("read\n");
-                               if (CT(COMMAND) == FD_WRITE)
-                                       printk("write\n");
-                               break;
-                       }
-                       if (((unsigned long)buffer) % 512)
-                               DPRINT("%p buffer not aligned\n", buffer);
-#endif
+               if (dma_buffer + size >
+                   floppy_track_buffer + (max_buffer_sectors << 10) ||
+                   dma_buffer < floppy_track_buffer) {
+                       DPRINT("buffer overrun in copy buffer %d\n",
+                              (int)((floppy_track_buffer - dma_buffer) >> 9));
+                       pr_info("fsector_t=%d buffer_min=%d\n",
+                               fsector_t, buffer_min);
+                       pr_info("current_count_sectors=%ld\n",
+                               current_count_sectors);
                        if (CT(COMMAND) == FD_READ)
-                               memcpy(buffer, dma_buffer, size);
-                       else
-                               memcpy(dma_buffer, buffer, size);
-
-                       remaining -= size;
-                       dma_buffer += size;
+                               pr_info("read\n");
+                       if (CT(COMMAND) == FD_WRITE)
+                               pr_info("write\n");
+                       break;
                }
+               if (((unsigned long)buffer) % 512)
+                       DPRINT("%p buffer not aligned\n", buffer);
+#endif
+               if (CT(COMMAND) == FD_READ)
+                       memcpy(buffer, dma_buffer, size);
+               else
+                       memcpy(dma_buffer, buffer, size);
+
+               remaining -= size;
+               dma_buffer += size;
        }
 #ifdef FLOPPY_SANITY_CHECK
        if (remaining) {
@@ -2571,19 +2563,6 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
 #endif
 }
 
-#if 0
-static inline int check_dma_crossing(char *start,
-                                    unsigned long length, char *message)
-{
-       if (CROSS_64KB(start, length)) {
-               printk("DMA xfer crosses 64KB boundary in %s %p-%p\n",
-                      message, start, start + length);
-               return 1;
-       } else
-               return 0;
-}
-#endif
-
 /* work around a bug in pseudo DMA
  * (on some FDCs) pseudo DMA does not stop when the CPU stops
  * sending data.  Hence we need a different way to signal the
@@ -2593,7 +2572,8 @@ static inline int check_dma_crossing(char *start,
  */
 static void virtualdmabug_workaround(void)
 {
-       int hard_sectors, end_sector;
+       int hard_sectors;
+       int end_sector;
 
        if (CT(COMMAND) == FD_WRITE) {
                COMMAND &= ~0x80;       /* switch off multiple track mode */
@@ -2602,13 +2582,14 @@ static void virtualdmabug_workaround(void)
                end_sector = SECTOR + hard_sectors - 1;
 #ifdef FLOPPY_SANITY_CHECK
                if (end_sector > SECT_PER_TRACK) {
-                       printk("too many sectors %d > %d\n",
-                              end_sector, SECT_PER_TRACK);
+                       pr_info("too many sectors %d > %d\n",
+                               end_sector, SECT_PER_TRACK);
                        return;
                }
 #endif
-               SECT_PER_TRACK = end_sector;    /* make sure SECT_PER_TRACK points
-                                                * to end of transfer */
+               SECT_PER_TRACK = end_sector;
+                                       /* make sure SECT_PER_TRACK
+                                        * points to end of transfer */
        }
 }
 
@@ -2625,10 +2606,13 @@ static void virtualdmabug_workaround(void)
 static int make_raw_rw_request(void)
 {
        int aligned_sector_t;
-       int max_sector, max_size, tracksize, ssize;
+       int max_sector;
+       int max_size;
+       int tracksize;
+       int ssize;
 
        if (max_buffer_sectors == 0) {
-               printk("VFS: Block I/O scheduled on unopened device\n");
+               pr_info("VFS: Block I/O scheduled on unopened device\n");
                return 0;
        }
 
@@ -2651,10 +2635,10 @@ static int make_raw_rw_request(void)
 
        max_sector = _floppy->sect * _floppy->head;
 
-       TRACK = (int)current_req->sector / max_sector;
-       fsector_t = (int)current_req->sector % max_sector;
+       TRACK = (int)blk_rq_pos(current_req) / max_sector;
+       fsector_t = (int)blk_rq_pos(current_req) % max_sector;
        if (_floppy->track && TRACK >= _floppy->track) {
-               if (current_req->current_nr_sectors & 1) {
+               if (blk_rq_cur_sectors(current_req) & 1) {
                        current_count_sectors = 1;
                        return 1;
                } else
@@ -2662,8 +2646,9 @@ static int make_raw_rw_request(void)
        }
        HEAD = fsector_t / _floppy->sect;
 
-       if (((_floppy->stretch & (FD_SWAPSIDES | FD_ZEROBASED)) ||
-            TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect)
+       if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) ||
+            test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags)) &&
+           fsector_t < _floppy->sect)
                max_sector = _floppy->sect;
 
        /* 2M disks have phantom sectors on the first track */
@@ -2672,7 +2657,7 @@ static int make_raw_rw_request(void)
                if (fsector_t >= max_sector) {
                        current_count_sectors =
                            min_t(int, _floppy->sect - fsector_t,
-                                 current_req->nr_sectors);
+                                 blk_rq_sectors(current_req));
                        return 1;
                }
                SIZECODE = 2;
@@ -2692,7 +2677,7 @@ static int make_raw_rw_request(void)
        CODE2SIZE;
        SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE;
        SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) +
-           ((_floppy->stretch & FD_ZEROBASED) ? 0 : 1);
+           FD_SECTBASE(_floppy);
 
        /* tracksize describes the size which can be filled up with sectors
         * of size ssize.
@@ -2723,7 +2708,7 @@ static int make_raw_rw_request(void)
 
        in_sector_offset = (fsector_t % _floppy->sect) % ssize;
        aligned_sector_t = fsector_t - in_sector_offset;
-       max_size = current_req->nr_sectors;
+       max_size = blk_rq_sectors(current_req);
        if ((raw_cmd->track == buffer_track) &&
            (current_drive == buffer_drive) &&
            (fsector_t >= buffer_min) && (fsector_t < buffer_max)) {
@@ -2732,10 +2717,12 @@ static int make_raw_rw_request(void)
                        copy_buffer(1, max_sector, buffer_max);
                        return 1;
                }
-       } else if (in_sector_offset || current_req->nr_sectors < ssize) {
+       } else if (in_sector_offset || blk_rq_sectors(current_req) < ssize) {
                if (CT(COMMAND) == FD_WRITE) {
-                       if (fsector_t + current_req->nr_sectors > ssize &&
-                           fsector_t + current_req->nr_sectors < ssize + ssize)
+                       unsigned int sectors;
+
+                       sectors = fsector_t + blk_rq_sectors(current_req);
+                       if (sectors > ssize && sectors < ssize + ssize)
                                max_size = ssize + ssize;
                        else
                                max_size = ssize;
@@ -2756,12 +2743,10 @@ static int make_raw_rw_request(void)
                 * on a 64 bit machine!
                 */
                max_size = buffer_chain_size();
-               dma_limit =
-                   (MAX_DMA_ADDRESS -
-                    ((unsigned long)current_req->buffer)) >> 9;
-               if ((unsigned long)max_size > dma_limit) {
+               dma_limit = (MAX_DMA_ADDRESS -
+                            ((unsigned long)current_req->buffer)) >> 9;
+               if ((unsigned long)max_size > dma_limit)
                        max_size = dma_limit;
-               }
                /* 64 kb boundaries */
                if (CROSS_64KB(current_req->buffer, max_size << 9))
                        max_size = (K_64 -
@@ -2778,24 +2763,18 @@ static int make_raw_rw_request(void)
                if (!direct ||
                    (indirect * 2 > direct * 3 &&
                     *errors < DP->max_errors.read_track &&
-                    /*!TESTF(FD_NEED_TWADDLE) && */
-                    ((!probing
-                      || (DP->read_track & (1 << DRS->probed_format)))))) {
-                       max_size = current_req->nr_sectors;
+                    ((!probing ||
+                      (DP->read_track & (1 << DRS->probed_format)))))) {
+                       max_size = blk_rq_sectors(current_req);
                } else {
                        raw_cmd->kernel_data = current_req->buffer;
                        raw_cmd->length = current_count_sectors << 9;
                        if (raw_cmd->length == 0) {
-                               DPRINT
-                                   ("zero dma transfer attempted from make_raw_request\n");
-                               DPRINT("indirect=%d direct=%d fsector_t=%d",
+                               DPRINT("zero dma transfer attempted from make_raw_request\n");
+                               DPRINT("indirect=%d direct=%d fsector_t=%d\n",
                                       indirect, direct, fsector_t);
                                return 0;
                        }
-/*                     check_dma_crossing(raw_cmd->kernel_data, 
-                                          raw_cmd->length, 
-                                          "end of make_raw_request [1]");*/
-
                        virtualdmabug_workaround();
                        return 2;
                }
@@ -2810,17 +2789,16 @@ static int make_raw_rw_request(void)
            fsector_t > buffer_max ||
            fsector_t < buffer_min ||
            ((CT(COMMAND) == FD_READ ||
-             (!in_sector_offset && current_req->nr_sectors >= ssize)) &&
+             (!in_sector_offset && blk_rq_sectors(current_req) >= ssize)) &&
             max_sector > 2 * max_buffer_sectors + buffer_min &&
-            max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)
-           /* not enough space */
-           ) {
+            max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)) {
+               /* not enough space */
                buffer_track = -1;
                buffer_drive = current_drive;
                buffer_max = buffer_min = aligned_sector_t;
        }
        raw_cmd->kernel_data = floppy_track_buffer +
-           ((aligned_sector_t - buffer_min) << 9);
+               ((aligned_sector_t - buffer_min) << 9);
 
        if (CT(COMMAND) == FD_WRITE) {
                /* copy write buffer to track buffer.
@@ -2845,8 +2823,6 @@ static int make_raw_rw_request(void)
        raw_cmd->length = ((raw_cmd->length - 1) | (ssize - 1)) + 1;
        raw_cmd->length <<= 9;
 #ifdef FLOPPY_SANITY_CHECK
-       /*check_dma_crossing(raw_cmd->kernel_data, raw_cmd->length, 
-          "end of make_raw_request"); */
        if ((raw_cmd->length < current_count_sectors << 9) ||
            (raw_cmd->kernel_data != current_req->buffer &&
             CT(COMMAND) == FD_WRITE &&
@@ -2857,19 +2833,19 @@ static int make_raw_rw_request(void)
                DPRINT("fractionary current count b=%lx s=%lx\n",
                       raw_cmd->length, current_count_sectors);
                if (raw_cmd->kernel_data != current_req->buffer)
-                       printk("addr=%d, length=%ld\n",
-                              (int)((raw_cmd->kernel_data -
-                                     floppy_track_buffer) >> 9),
-                              current_count_sectors);
-               printk("st=%d ast=%d mse=%d msi=%d\n",
-                      fsector_t, aligned_sector_t, max_sector, max_size);
-               printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE);
-               printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n",
-                      COMMAND, SECTOR, HEAD, TRACK);
-               printk("buffer drive=%d\n", buffer_drive);
-               printk("buffer track=%d\n", buffer_track);
-               printk("buffer_min=%d\n", buffer_min);
-               printk("buffer_max=%d\n", buffer_max);
+                       pr_info("addr=%d, length=%ld\n",
+                               (int)((raw_cmd->kernel_data -
+                                      floppy_track_buffer) >> 9),
+                               current_count_sectors);
+               pr_info("st=%d ast=%d mse=%d msi=%d\n",
+                       fsector_t, aligned_sector_t, max_sector, max_size);
+               pr_info("ssize=%x SIZECODE=%d\n", ssize, SIZECODE);
+               pr_info("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n",
+                       COMMAND, SECTOR, HEAD, TRACK);
+               pr_info("buffer drive=%d\n", buffer_drive);
+               pr_info("buffer track=%d\n", buffer_track);
+               pr_info("buffer_min=%d\n", buffer_min);
+               pr_info("buffer_max=%d\n", buffer_max);
                return 0;
        }
 
@@ -2880,24 +2856,24 @@ static int make_raw_rw_request(void)
                    raw_cmd->kernel_data + raw_cmd->length >
                    floppy_track_buffer + (max_buffer_sectors << 10)) {
                        DPRINT("buffer overrun in schedule dma\n");
-                       printk("fsector_t=%d buffer_min=%d current_count=%ld\n",
-                              fsector_t, buffer_min, raw_cmd->length >> 9);
-                       printk("current_count_sectors=%ld\n",
-                              current_count_sectors);
+                       pr_info("fsector_t=%d buffer_min=%d current_count=%ld\n",
+                               fsector_t, buffer_min, raw_cmd->length >> 9);
+                       pr_info("current_count_sectors=%ld\n",
+                               current_count_sectors);
                        if (CT(COMMAND) == FD_READ)
-                               printk("read\n");
+                               pr_info("read\n");
                        if (CT(COMMAND) == FD_WRITE)
-                               printk("write\n");
+                               pr_info("write\n");
                        return 0;
                }
-       } else if (raw_cmd->length > current_req->nr_sectors << 9 ||
-                  current_count_sectors > current_req->nr_sectors) {
+       } else if (raw_cmd->length > blk_rq_bytes(current_req) ||
+                  current_count_sectors > blk_rq_sectors(current_req)) {
                DPRINT("buffer overrun in direct transfer\n");
                return 0;
        } else if (raw_cmd->length < current_count_sectors << 9) {
                DPRINT("more sectors than bytes\n");
-               printk("bytes=%ld\n", raw_cmd->length >> 9);
-               printk("sectors=%ld\n", current_count_sectors);
+               pr_info("bytes=%ld\n", raw_cmd->length >> 9);
+               pr_info("sectors=%ld\n", current_count_sectors);
        }
        if (raw_cmd->length == 0) {
                DPRINT("zero dma transfer attempted from make_raw_request\n");
@@ -2924,7 +2900,7 @@ static void redo_fd_request(void)
                        struct request *req;
 
                        spin_lock_irq(floppy_queue->queue_lock);
-                       req = elv_next_request(floppy_queue);
+                       req = blk_fetch_request(floppy_queue);
                        spin_unlock_irq(floppy_queue->queue_lock);
                        if (!req) {
                                do_floppy = NULL;
@@ -2944,7 +2920,7 @@ static void redo_fd_request(void)
                        return;
                disk_change(current_drive);
                if (test_bit(current_drive, &fake_change) ||
-                   TESTF(FD_DISK_CHANGED)) {
+                   test_bit(FD_DISK_CHANGED_BIT, &DRS->flags)) {
                        DPRINT("disk absent or changed during operation\n");
                        REPEAT;
                }
@@ -2969,7 +2945,7 @@ static void redo_fd_request(void)
                        continue;
                }
 
-               if (TESTF(FD_NEED_TWADDLE))
+               if (test_bit(FD_NEED_TWADDLE_BIT, &DRS->flags))
                        twaddle();
                schedule_bh(floppy_start);
                debugt("queue fd request");
@@ -2991,18 +2967,19 @@ static void process_fd_request(void)
        schedule_bh(redo_fd_request);
 }
 
-static void do_fd_request(request_queue_t * q)
+static void do_fd_request(struct request_queue *q)
 {
        if (max_buffer_sectors == 0) {
-               printk("VFS: do_fd_request called on non-open device\n");
+               pr_info("VFS: do_fd_request called on non-open device\n");
                return;
        }
 
        if (usage_count == 0) {
-               printk("warning: usage count=0, current_req=%p exiting\n",
-                      current_req);
-               printk("sect=%ld flags=%lx\n", (long)current_req->sector,
-                      current_req->flags);
+               pr_info("warning: usage count=0, current_req=%p exiting\n",
+                       current_req);
+               pr_info("sect=%ld type=%x flags=%x\n",
+                       (long)blk_rq_pos(current_req), current_req->cmd_type,
+                       current_req->cmd_flags);
                return;
        }
        if (test_bit(0, &fdc_busy)) {
@@ -3011,7 +2988,7 @@ static void do_fd_request(request_queue_t * q)
                is_alive("do fd request, old request running");
                return;
        }
-       lock_fdc(MAXTIMEOUT, 0);
+       lock_fdc(MAXTIMEOUT, false);
        process_fd_request();
        is_alive("do fd request");
 }
@@ -3023,23 +3000,18 @@ static struct cont_t poll_cont = {
        .done           = generic_done
 };
 
-static int poll_drive(int interruptible, int flag)
+static int poll_drive(bool interruptible, int flag)
 {
-       int ret;
        /* no auto-sense, just clear dcl */
        raw_cmd = &default_raw_cmd;
        raw_cmd->flags = flag;
        raw_cmd->track = 0;
        raw_cmd->cmd_count = 0;
        cont = &poll_cont;
-#ifdef DCL_DEBUG
-       if (DP->flags & FD_DEBUG) {
-               DPRINT("setting NEWCHANGE in poll_drive\n");
-       }
-#endif
-       SETF(FD_DISK_NEWCHANGE);
-       WAIT(floppy_ready);
-       return ret;
+       debug_dcl(DP->flags, "setting NEWCHANGE in poll_drive\n");
+       set_bit(FD_DISK_NEWCHANGE_BIT, &DRS->flags);
+
+       return wait_til_done(floppy_ready, interruptible);
 }
 
 /*
@@ -3049,7 +3021,7 @@ static int poll_drive(int interruptible, int flag)
 
 static void reset_intr(void)
 {
-       printk("weird, reset interrupt called\n");
+       pr_info("weird, reset interrupt called\n");
 }
 
 static struct cont_t reset_cont = {
@@ -3059,20 +3031,23 @@ static struct cont_t reset_cont = {
        .done           = generic_done
 };
 
-static int user_reset_fdc(int drive, int arg, int interruptible)
+static int user_reset_fdc(int drive, int arg, bool interruptible)
 {
        int ret;
 
-       ret = 0;
-       LOCK_FDC(drive, interruptible);
+       if (lock_fdc(drive, interruptible))
+               return -EINTR;
+
        if (arg == FD_RESET_ALWAYS)
                FDCS->reset = 1;
        if (FDCS->reset) {
                cont = &reset_cont;
-               WAIT(reset_fdc);
+               ret = wait_til_done(reset_fdc, interruptible);
+               if (ret == -EINTR)
+                       return -EINTR;
        }
        process_fd_request();
-       return ret;
+       return 0;
 }
 
 /*
@@ -3085,17 +3060,12 @@ static inline int fd_copyout(void __user *param, const void *address,
        return copy_to_user(param, address, size) ? -EFAULT : 0;
 }
 
-static inline int fd_copyin(void __user *param, void *address, unsigned long size)
+static inline int fd_copyin(void __user *param, void *address,
+                           unsigned long size)
 {
        return copy_from_user(address, param, size) ? -EFAULT : 0;
 }
 
-#define _COPYOUT(x) (copy_to_user((void __user *)param, &(x), sizeof(x)) ? -EFAULT : 0)
-#define _COPYIN(x) (copy_from_user(&(x), (void __user *)param, sizeof(x)) ? -EFAULT : 0)
-
-#define COPYOUT(x) ECALL(_COPYOUT(x))
-#define COPYIN(x) ECALL(_COPYIN(x))
-
 static inline const char *drive_name(int type, int drive)
 {
        struct floppy_struct *floppy;
@@ -3172,14 +3142,19 @@ static inline int raw_cmd_copyout(int cmd, char __user *param,
        int ret;
 
        while (ptr) {
-               COPYOUT(*ptr);
+               ret = copy_to_user((void __user *)param, ptr, sizeof(*ptr));
+               if (ret)
+                       return -EFAULT;
                param += sizeof(struct floppy_raw_cmd);
                if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length) {
-                       if (ptr->length >= 0
-                           && ptr->length <= ptr->buffer_length)
-                               ECALL(fd_copyout
-                                     (ptr->data, ptr->kernel_data,
-                                      ptr->buffer_length - ptr->length));
+                       if (ptr->length >= 0 &&
+                           ptr->length <= ptr->buffer_length) {
+                               long length = ptr->buffer_length - ptr->length;
+                               ret = fd_copyout(ptr->data, ptr->kernel_data,
+                                                length);
+                               if (ret)
+                                       return ret;
+                       }
                }
                ptr = ptr->next;
        }
@@ -3188,7 +3163,8 @@ static inline int raw_cmd_copyout(int cmd, char __user *param,
 
 static void raw_cmd_free(struct floppy_raw_cmd **ptr)
 {
-       struct floppy_raw_cmd *next, *this;
+       struct floppy_raw_cmd *next;
+       struct floppy_raw_cmd *this;
 
        this = *ptr;
        *ptr = NULL;
@@ -3218,7 +3194,9 @@ static inline int raw_cmd_copyin(int cmd, char __user *param,
                if (!ptr)
                        return -ENOMEM;
                *rcmd = ptr;
-               COPYIN(*ptr);
+               ret = copy_from_user(ptr, (void __user *)param, sizeof(*ptr));
+               if (ret)
+                       return -EFAULT;
                ptr->next = NULL;
                ptr->buffer_length = 0;
                param += sizeof(struct floppy_raw_cmd);
@@ -3248,9 +3226,12 @@ static inline int raw_cmd_copyin(int cmd, char __user *param,
                                return -ENOMEM;
                        ptr->buffer_length = ptr->length;
                }
-               if (ptr->flags & FD_RAW_WRITE)
-                       ECALL(fd_copyin(ptr->data, ptr->kernel_data,
-                                       ptr->length));
+               if (ptr->flags & FD_RAW_WRITE) {
+                       ret = fd_copyin(ptr->data, ptr->kernel_data,
+                                       ptr->length);
+                       if (ret)
+                               return ret;
+               }
                rcmd = &(ptr->next);
                if (!(ptr->flags & FD_RAW_MORE))
                        return 0;
@@ -3260,8 +3241,10 @@ static inline int raw_cmd_copyin(int cmd, char __user *param,
 
 static int raw_cmd_ioctl(int cmd, void __user *param)
 {
-       int drive, ret, ret2;
        struct floppy_raw_cmd *my_raw_cmd;
+       int drive;
+       int ret2;
+       int ret;
 
        if (FDCS->rawcmd <= 1)
                FDCS->rawcmd = 1;
@@ -3290,12 +3273,8 @@ static int raw_cmd_ioctl(int cmd, void __user *param)
 
        raw_cmd = my_raw_cmd;
        cont = &raw_cmd_cont;
-       ret = wait_til_done(floppy_start, 1);
-#ifdef DCL_DEBUG
-       if (DP->flags & FD_DEBUG) {
-               DPRINT("calling disk change from raw_cmd ioctl\n");
-       }
-#endif
+       ret = wait_til_done(floppy_start, true);
+       debug_dcl(DP->flags, "calling disk change from raw_cmd ioctl\n");
 
        if (ret != -EINTR && FDCS->reset)
                ret = -EIO;
@@ -3328,13 +3307,16 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
            g->head <= 0 ||
            g->track <= 0 || g->track > UDP->tracks >> STRETCH(g) ||
            /* check if reserved bits are set */
-           (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_ZEROBASED)) != 0)
+           (g->stretch & ~(FD_STRETCH | FD_SWAPSIDES | FD_SECTBASEMASK)) != 0)
                return -EINVAL;
        if (type) {
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
-               down(&open_lock);
-               LOCK_FDC(drive, 1);
+               mutex_lock(&open_lock);
+               if (lock_fdc(drive, true)) {
+                       mutex_unlock(&open_lock);
+                       return -EINTR;
+               }
                floppy_type[type] = *g;
                floppy_type[type].name = "user format";
                for (cnt = type << 2; cnt < (type << 2) + 4; cnt++)
@@ -3345,16 +3327,20 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
                        struct block_device *bdev = opened_bdev[cnt];
                        if (!bdev || ITYPE(drive_state[cnt].fd_device) != type)
                                continue;
-                       __invalidate_device(bdev, 0);
+                       __invalidate_device(bdev);
                }
-               up(&open_lock);
+               mutex_unlock(&open_lock);
        } else {
                int oldStretch;
-               LOCK_FDC(drive, 1);
-               if (cmd != FDDEFPRM)
+
+               if (lock_fdc(drive, true))
+                       return -EINTR;
+               if (cmd != FDDEFPRM) {
                        /* notice a disk change immediately, else
                         * we lose our settings immediately*/
-                       CALL(poll_drive(1, FD_RAW_NEED_DISK));
+                       if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
+                               return -EINTR;
+               }
                oldStretch = g->stretch;
                user_params[drive] = *g;
                if (buffer_drive == drive)
@@ -3373,7 +3359,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
                if (DRS->maxblock > user_params[drive].sect ||
                    DRS->maxtrack ||
                    ((user_params[drive].sect ^ oldStretch) &
-                    (FD_SWAPSIDES | FD_ZEROBASED)))
+                    (FD_SWAPSIDES | FD_SECTBASEMASK)))
                        invalidate_drive(bdev);
                else
                        process_fd_request();
@@ -3419,7 +3405,7 @@ static inline int normalize_ioctl(int *cmd, int *size)
                        *size = _IOC_SIZE(*cmd);
                        *cmd = ioctl_table[i];
                        if (*size > _IOC_SIZE(*cmd)) {
-                               printk("ioctl not yet supported\n");
+                               pr_info("ioctl not yet supported\n");
                                return -EFAULT;
                        }
                        return 0;
@@ -3433,8 +3419,10 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
        if (type)
                *g = &floppy_type[type];
        else {
-               LOCK_FDC(drive, 0);
-               CALL(poll_drive(0, 0));
+               if (lock_fdc(drive, false))
+                       return -EINTR;
+               if (poll_drive(false, 0) == -EINTR)
+                       return -EINTR;
                process_fd_request();
                *g = current_type[drive];
        }
@@ -3443,15 +3431,31 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g)
        return 0;
 }
 
-static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+       int drive = (long)bdev->bd_disk->private_data;
+       int type = ITYPE(drive_state[drive].fd_device);
+       struct floppy_struct *g;
+       int ret;
+
+       ret = get_floppy_geometry(drive, type, &g);
+       if (ret)
+               return ret;
+
+       geo->heads = g->head;
+       geo->sectors = g->sect;
+       geo->cylinders = g->track;
+       return 0;
+}
+
+static int fd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
                    unsigned long param)
 {
-#define FD_IOCTL_ALLOWED ((filp) && (filp)->private_data)
-#define OUT(c,x) case c: outparam = (const char *) (x); break
-#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
+#define FD_IOCTL_ALLOWED (mode & (FMODE_WRITE|FMODE_WRITE_IOCTL))
 
-       int drive = (long)inode->i_bdev->bd_disk->private_data;
-       int i, type = ITYPE(UDRS->fd_device);
+       int drive = (long)bdev->bd_disk->private_data;
+       int type = ITYPE(UDRS->fd_device);
+       int i;
        int ret;
        int size;
        union inparam {
@@ -3466,164 +3470,166 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
         * We do this in order to provide a means to eject floppy disks before
         * installing the new fdutils package */
        if (cmd == CDROMEJECT ||        /* CD-ROM eject */
-           cmd == 0x6470 /* SunOS floppy eject */ ) {
+           cmd == 0x6470) {            /* SunOS floppy eject */
                DPRINT("obsolete eject ioctl\n");
                DPRINT("please use floppycontrol --eject\n");
                cmd = FDEJECT;
        }
 
-       /* generic block device ioctls */
-       switch (cmd) {
-               /* the following have been inspired by the corresponding
-                * code for other block devices. */
-               struct floppy_struct *g;
-       case HDIO_GETGEO:
-               {
-                       struct hd_geometry loc;
-                       ECALL(get_floppy_geometry(drive, type, &g));
-                       loc.heads = g->head;
-                       loc.sectors = g->sect;
-                       loc.cylinders = g->track;
-                       loc.start = 0;
-                       return _COPYOUT(loc);
-               }
-       }
+       if (!((cmd & 0xff00) == 0x0200))
+               return -EINVAL;
 
        /* convert the old style command into a new style command */
-       if ((cmd & 0xff00) == 0x0200) {
-               ECALL(normalize_ioctl(&cmd, &size));
-       } else
-               return -EINVAL;
+       ret = normalize_ioctl(&cmd, &size);
+       if (ret)
+               return ret;
 
        /* permission checks */
        if (((cmd & 0x40) && !FD_IOCTL_ALLOWED) ||
            ((cmd & 0x80) && !capable(CAP_SYS_ADMIN)))
                return -EPERM;
 
+       if (WARN_ON(size < 0 || size > sizeof(inparam)))
+               return -EINVAL;
+
        /* copyin */
-       CLEARSTRUCT(&inparam);
-       if (_IOC_DIR(cmd) & _IOC_WRITE)
-           ECALL(fd_copyin((void __user *)param, &inparam, size))
-
-               switch (cmd) {
-               case FDEJECT:
-                       if (UDRS->fd_ref != 1)
-                               /* somebody else has this drive open */
-                               return -EBUSY;
-                       LOCK_FDC(drive, 1);
-
-                       /* do the actual eject. Fails on
-                        * non-Sparc architectures */
-                       ret = fd_eject(UNIT(drive));
-
-                       USETF(FD_DISK_CHANGED);
-                       USETF(FD_VERIFY);
-                       process_fd_request();
+       memset(&inparam, 0, sizeof(inparam));
+       if (_IOC_DIR(cmd) & _IOC_WRITE) {
+               ret = fd_copyin((void __user *)param, &inparam, size);
+               if (ret)
                        return ret;
-               case FDCLRPRM:
-                       LOCK_FDC(drive, 1);
-                       current_type[drive] = NULL;
-                       floppy_sizes[drive] = MAX_DISK_SIZE << 1;
-                       UDRS->keep_data = 0;
-                       return invalidate_drive(inode->i_bdev);
-               case FDSETPRM:
-               case FDDEFPRM:
-                       return set_geometry(cmd, &inparam.g,
-                                           drive, type, inode->i_bdev);
-               case FDGETPRM:
-                       ECALL(get_floppy_geometry(drive, type,
-                                                 (struct floppy_struct **)
-                                                 &outparam));
-                       break;
-
-               case FDMSGON:
-                       UDP->flags |= FTD_MSG;
-                       return 0;
-               case FDMSGOFF:
-                       UDP->flags &= ~FTD_MSG;
-                       return 0;
-
-               case FDFMTBEG:
-                       LOCK_FDC(drive, 1);
-                       CALL(poll_drive(1, FD_RAW_NEED_DISK));
-                       ret = UDRS->flags;
-                       process_fd_request();
-                       if (ret & FD_VERIFY)
-                               return -ENODEV;
-                       if (!(ret & FD_DISK_WRITABLE))
-                               return -EROFS;
-                       return 0;
-               case FDFMTTRK:
-                       if (UDRS->fd_ref != 1)
-                               return -EBUSY;
-                       return do_format(drive, &inparam.f);
-               case FDFMTEND:
-               case FDFLUSH:
-                       LOCK_FDC(drive, 1);
-                       return invalidate_drive(inode->i_bdev);
-
-               case FDSETEMSGTRESH:
-                       UDP->max_errors.reporting =
-                           (unsigned short)(param & 0x0f);
-                       return 0;
-                       OUT(FDGETMAXERRS, &UDP->max_errors);
-                       IN(FDSETMAXERRS, &UDP->max_errors, max_errors);
-
-               case FDGETDRVTYP:
-                       outparam = drive_name(type, drive);
-                       SUPBOUND(size, strlen(outparam) + 1);
-                       break;
-
-                       IN(FDSETDRVPRM, UDP, dp);
-                       OUT(FDGETDRVPRM, UDP);
-
-               case FDPOLLDRVSTAT:
-                       LOCK_FDC(drive, 1);
-                       CALL(poll_drive(1, FD_RAW_NEED_DISK));
-                       process_fd_request();
-                       /* fall through */
-                       OUT(FDGETDRVSTAT, UDRS);
-
-               case FDRESET:
-                       return user_reset_fdc(drive, (int)param, 1);
-
-                       OUT(FDGETFDCSTAT, UFDCS);
-
-               case FDWERRORCLR:
-                       CLEARSTRUCT(UDRWE);
-                       return 0;
-                       OUT(FDWERRORGET, UDRWE);
-
-               case FDRAWCMD:
-                       if (type)
-                               return -EINVAL;
-                       LOCK_FDC(drive, 1);
-                       set_floppy(drive);
-                       CALL(i = raw_cmd_ioctl(cmd, (void __user *)param));
-                       process_fd_request();
-                       return i;
-
-               case FDTWADDLE:
-                       LOCK_FDC(drive, 1);
-                       twaddle();
-                       process_fd_request();
-                       return 0;
+       }
 
-               default:
+       switch (cmd) {
+       case FDEJECT:
+               if (UDRS->fd_ref != 1)
+                       /* somebody else has this drive open */
+                       return -EBUSY;
+               if (lock_fdc(drive, true))
+                       return -EINTR;
+
+               /* do the actual eject. Fails on
+                * non-Sparc architectures */
+               ret = fd_eject(UNIT(drive));
+
+               set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
+               set_bit(FD_VERIFY_BIT, &UDRS->flags);
+               process_fd_request();
+               return ret;
+       case FDCLRPRM:
+               if (lock_fdc(drive, true))
+                       return -EINTR;
+               current_type[drive] = NULL;
+               floppy_sizes[drive] = MAX_DISK_SIZE << 1;
+               UDRS->keep_data = 0;
+               return invalidate_drive(bdev);
+       case FDSETPRM:
+       case FDDEFPRM:
+               return set_geometry(cmd, &inparam.g, drive, type, bdev);
+       case FDGETPRM:
+               ret = get_floppy_geometry(drive, type,
+                                         (struct floppy_struct **)
+                                         &outparam);
+               if (ret)
+                       return ret;
+               break;
+       case FDMSGON:
+               UDP->flags |= FTD_MSG;
+               return 0;
+       case FDMSGOFF:
+               UDP->flags &= ~FTD_MSG;
+               return 0;
+       case FDFMTBEG:
+               if (lock_fdc(drive, true))
+                       return -EINTR;
+               if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
+                       return -EINTR;
+               ret = UDRS->flags;
+               process_fd_request();
+               if (ret & FD_VERIFY)
+                       return -ENODEV;
+               if (!(ret & FD_DISK_WRITABLE))
+                       return -EROFS;
+               return 0;
+       case FDFMTTRK:
+               if (UDRS->fd_ref != 1)
+                       return -EBUSY;
+               return do_format(drive, &inparam.f);
+       case FDFMTEND:
+       case FDFLUSH:
+               if (lock_fdc(drive, true))
+                       return -EINTR;
+               return invalidate_drive(bdev);
+       case FDSETEMSGTRESH:
+               UDP->max_errors.reporting = (unsigned short)(param & 0x0f);
+               return 0;
+       case FDGETMAXERRS:
+               outparam = (const char *)&UDP->max_errors;
+               break;
+       case FDSETMAXERRS:
+               UDP->max_errors = inparam.max_errors;
+               break;
+       case FDGETDRVTYP:
+               outparam = drive_name(type, drive);
+               SUPBOUND(size, strlen(outparam) + 1);
+               break;
+       case FDSETDRVPRM:
+               *UDP = inparam.dp;
+               break;
+       case FDGETDRVPRM:
+               outparam = (const char *)UDP;
+               break;
+       case FDPOLLDRVSTAT:
+               if (lock_fdc(drive, true))
+                       return -EINTR;
+               if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
+                       return -EINTR;
+               process_fd_request();
+               /* fall through */
+       case FDGETDRVSTAT:
+               outparam = (const char *)UDRS;
+               break;
+       case FDRESET:
+               return user_reset_fdc(drive, (int)param, true);
+       case FDGETFDCSTAT:
+               outparam = (const char *)UFDCS;
+               break;
+       case FDWERRORCLR:
+               memset(UDRWE, 0, sizeof(*UDRWE));
+               return 0;
+       case FDWERRORGET:
+               outparam = (const char *)UDRWE;
+               break;
+       case FDRAWCMD:
+               if (type)
                        return -EINVAL;
-               }
+               if (lock_fdc(drive, true))
+                       return -EINTR;
+               set_floppy(drive);
+               i = raw_cmd_ioctl(cmd, (void __user *)param);
+               if (i == -EINTR)
+                       return -EINTR;
+               process_fd_request();
+               return i;
+       case FDTWADDLE:
+               if (lock_fdc(drive, true))
+                       return -EINTR;
+               twaddle();
+               process_fd_request();
+               return 0;
+       default:
+               return -EINVAL;
+       }
 
        if (_IOC_DIR(cmd) & _IOC_READ)
                return fd_copyout((void __user *)param, outparam, size);
-       else
-               return 0;
-#undef OUT
-#undef IN
+
+       return 0;
 }
 
 static void __init config_types(void)
 {
-       int first = 1;
+       bool has_drive = false;
        int drive;
 
        /* read drive info out of physical CMOS */
@@ -3634,8 +3640,7 @@ static void __init config_types(void)
        if (!UDP->cmos && FLOPPY1_TYPE)
                UDP->cmos = FLOPPY1_TYPE;
 
-       /* XXX */
-       /* additional physical CMOS drive detection should go here */
+       /* FIXME: additional physical CMOS drive detection should go here */
 
        for (drive = 0; drive < N_DRIVE; drive++) {
                unsigned int type = UDP->cmos;
@@ -3643,7 +3648,7 @@ static void __init config_types(void)
                const char *name = NULL;
                static char temparea[32];
 
-               if (type < NUMBER(default_drive_params)) {
+               if (type < ARRAY_SIZE(default_drive_params)) {
                        params = &default_drive_params[type].params;
                        if (type) {
                                name = default_drive_params[type].name;
@@ -3656,25 +3661,29 @@ static void __init config_types(void)
                        name = temparea;
                }
                if (name) {
-                       const char *prepend = ",";
-                       if (first) {
-                               prepend = KERN_INFO "Floppy drive(s):";
-                               first = 0;
+                       const char *prepend;
+                       if (!has_drive) {
+                               prepend = "";
+                               has_drive = true;
+                               pr_info("Floppy drive(s):");
+                       } else {
+                               prepend = ",";
                        }
-                       printk("%s fd%d is %s", prepend, drive, name);
-                       register_devfs_entries(drive);
+
+                       pr_cont("%s fd%d is %s", prepend, drive, name);
                }
                *UDP = *params;
        }
-       if (!first)
-               printk("\n");
+
+       if (has_drive)
+               pr_cont("\n");
 }
 
-static int floppy_release(struct inode *inode, struct file *filp)
+static int floppy_release(struct gendisk *disk, fmode_t mode)
 {
-       int drive = (long)inode->i_bdev->bd_disk->private_data;
+       int drive = (long)disk->private_data;
 
-       down(&open_lock);
+       mutex_lock(&open_lock);
        if (UDRS->fd_ref < 0)
                UDRS->fd_ref = 0;
        else if (!UDRS->fd_ref--) {
@@ -3683,8 +3692,8 @@ static int floppy_release(struct inode *inode, struct file *filp)
        }
        if (!UDRS->fd_ref)
                opened_bdev[drive] = NULL;
-       floppy_release_irq_and_dma();
-       up(&open_lock);
+       mutex_unlock(&open_lock);
+
        return 0;
 }
 
@@ -3693,37 +3702,33 @@ static int floppy_release(struct inode *inode, struct file *filp)
  * /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)
+static int floppy_open(struct block_device *bdev, fmode_t mode)
 {
-       int drive = (long)inode->i_bdev->bd_disk->private_data;
-       int old_dev;
+       int drive = (long)bdev->bd_disk->private_data;
+       int old_dev, new_dev;
        int try;
        int res = -EBUSY;
        char *tmp;
 
-       filp->private_data = (void *)0;
-       down(&open_lock);
+       mutex_lock(&open_lock);
        old_dev = UDRS->fd_device;
-       if (opened_bdev[drive] && opened_bdev[drive] != inode->i_bdev)
+       if (opened_bdev[drive] && opened_bdev[drive] != bdev)
                goto out2;
 
        if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)) {
-               USETF(FD_DISK_CHANGED);
-               USETF(FD_VERIFY);
+               set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
+               set_bit(FD_VERIFY_BIT, &UDRS->flags);
        }
 
-       if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
+       if (UDRS->fd_ref == -1 || (UDRS->fd_ref && (mode & FMODE_EXCL)))
                goto out2;
 
-       if (floppy_grab_irq_and_dma())
-               goto out2;
-
-       if (filp->f_flags & O_EXCL)
+       if (mode & FMODE_EXCL)
                UDRS->fd_ref = -1;
        else
                UDRS->fd_ref++;
 
-       opened_bdev[drive] = inode->i_bdev;
+       opened_bdev[drive] = bdev;
 
        res = -ENXIO;
 
@@ -3741,9 +3746,8 @@ static int floppy_open(struct inode *inode, struct file *filp)
                        INFBOUND(try, 16);
                        tmp = (char *)fd_dma_mem_alloc(1024 * try);
                }
-               if (!tmp && !floppy_track_buffer) {
+               if (!tmp && !floppy_track_buffer)
                        fallback_on_nodma_alloc(&tmp, 2048 * try);
-               }
                if (!tmp && !floppy_track_buffer) {
                        DPRINT("Unable to allocate DMA memory\n");
                        goto out;
@@ -3758,35 +3762,30 @@ static int floppy_open(struct inode *inode, struct file *filp)
                }
        }
 
-       UDRS->fd_device = iminor(inode);
-       set_capacity(disks[drive], floppy_sizes[iminor(inode)]);
-       if (old_dev != -1 && old_dev != iminor(inode)) {
+       new_dev = MINOR(bdev->bd_dev);
+       UDRS->fd_device = new_dev;
+       set_capacity(disks[drive], floppy_sizes[new_dev]);
+       if (old_dev != -1 && old_dev != new_dev) {
                if (buffer_drive == drive)
                        buffer_track = -1;
        }
 
-       /* Allow ioctls if we have write-permissions even if read-only open.
-        * Needed so that programs such as fdrawcmd still can work on write
-        * protected disks */
-       if (filp->f_mode & 2
-           || permission(filp->f_dentry->d_inode, 2, NULL) == 0)
-               filp->private_data = (void *)8;
-
        if (UFDCS->rawcmd == 1)
                UFDCS->rawcmd = 2;
 
-       if (!(filp->f_flags & O_NDELAY)) {
-               if (filp->f_mode & 3) {
+       if (!(mode & FMODE_NDELAY)) {
+               if (mode & (FMODE_READ|FMODE_WRITE)) {
                        UDRS->last_checked = 0;
-                       check_disk_change(inode->i_bdev);
-                       if (UTESTF(FD_DISK_CHANGED))
+                       check_disk_change(bdev);
+                       if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
                                goto out;
                }
                res = -EROFS;
-               if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
+               if ((mode & FMODE_WRITE) &&
+                   !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags))
                        goto out;
        }
-       up(&open_lock);
+       mutex_unlock(&open_lock);
        return 0;
 out:
        if (UDRS->fd_ref < 0)
@@ -3795,9 +3794,8 @@ out:
                UDRS->fd_ref--;
        if (!UDRS->fd_ref)
                opened_bdev[drive] = NULL;
-       floppy_release_irq_and_dma();
 out2:
-       up(&open_lock);
+       mutex_unlock(&open_lock);
        return res;
 }
 
@@ -3808,22 +3806,18 @@ static int check_floppy_change(struct gendisk *disk)
 {
        int drive = (long)disk->private_data;
 
-       if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY))
+       if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
+           test_bit(FD_VERIFY_BIT, &UDRS->flags))
                return 1;
 
-       if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) {
-               if (floppy_grab_irq_and_dma()) {
-                       return 1;
-               }
-
-               lock_fdc(drive, 0);
-               poll_drive(0, 0);
+       if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
+               lock_fdc(drive, false);
+               poll_drive(false, 0);
                process_fd_request();
-               floppy_release_irq_and_dma();
        }
 
-       if (UTESTF(FD_DISK_CHANGED) ||
-           UTESTF(FD_VERIFY) ||
+       if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
+           test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
            test_bit(drive, &fake_change) ||
            (!ITYPE(UDRS->fd_device) && !current_type[drive]))
                return 1;
@@ -3836,14 +3830,9 @@ static int check_floppy_change(struct gendisk *disk)
  * a disk in the drive, and whether that disk is writable.
  */
 
-static int floppy_rb0_complete(struct bio *bio, unsigned int bytes_done,
-                              int err)
+static void floppy_rb0_complete(struct bio *bio, int err)
 {
-       if (bio->bi_size)
-               return 1;
-
        complete((struct completion *)bio->bi_private);
-       return 0;
 }
 
 static int __floppy_read_block_0(struct block_device *bdev)
@@ -3899,14 +3888,16 @@ static int floppy_revalidate(struct gendisk *disk)
        int cf;
        int res = 0;
 
-       if (UTESTF(FD_DISK_CHANGED) ||
-           UTESTF(FD_VERIFY) || test_bit(drive, &fake_change) || NO_GEOM) {
+       if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
+           test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
+           test_bit(drive, &fake_change) || NO_GEOM) {
                if (usage_count == 0) {
-                       printk("VFS: revalidate called on non-open device.\n");
+                       pr_info("VFS: revalidate called on non-open device.\n");
                        return -EFAULT;
                }
-               lock_fdc(drive, 0);
-               cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY);
+               lock_fdc(drive, false);
+               cf = (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
+                     test_bit(FD_VERIFY_BIT, &UDRS->flags));
                if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)) {
                        process_fd_request();   /*already done by another thread */
                        return 0;
@@ -3916,7 +3907,7 @@ static int floppy_revalidate(struct gendisk *disk)
                if (buffer_drive == drive)
                        buffer_track = -1;
                clear_bit(drive, &fake_change);
-               UCLEARF(FD_DISK_CHANGED);
+               clear_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
                if (cf)
                        UDRS->generation++;
                if (NO_GEOM) {
@@ -3924,7 +3915,7 @@ static int floppy_revalidate(struct gendisk *disk)
                        res = __floppy_read_block_0(opened_bdev[drive]);
                } else {
                        if (cf)
-                               poll_drive(0, FD_RAW_NEED_DISK);
+                               poll_drive(false, FD_RAW_NEED_DISK);
                        process_fd_request();
                }
        }
@@ -3932,45 +3923,15 @@ static int floppy_revalidate(struct gendisk *disk)
        return res;
 }
 
-static struct block_device_operations floppy_fops = {
-       .owner          = THIS_MODULE,
-       .open           = floppy_open,
-       .release        = floppy_release,
-       .ioctl          = fd_ioctl,
-       .media_changed  = check_floppy_change,
-       .revalidate_disk = floppy_revalidate,
-};
-static char *table[] = {
-       "", "d360", "h1200", "u360", "u720", "h360", "h720",
-       "u1440", "u2880", "CompaQ", "h1440", "u1680", "h410",
-       "u820", "h1476", "u1722", "h420", "u830", "h1494", "u1743",
-       "h880", "u1040", "u1120", "h1600", "u1760", "u1920",
-       "u3200", "u3520", "u3840", "u1840", "u800", "u1600",
-       NULL
+static const struct block_device_operations floppy_fops = {
+       .owner                  = THIS_MODULE,
+       .open                   = floppy_open,
+       .release                = floppy_release,
+       .locked_ioctl           = fd_ioctl,
+       .getgeo                 = fd_getgeo,
+       .media_changed          = check_floppy_change,
+       .revalidate_disk        = floppy_revalidate,
 };
-static int t360[] = { 1, 0 },
-       t1200[] = { 2, 5, 6, 10, 12, 14, 16, 18, 20, 23, 0 },
-       t3in[] = { 8, 9, 26, 27, 28, 7, 11, 15, 19, 24, 25, 29, 31, 3, 4, 13,
-                       17, 21, 22, 30, 0 };
-static int *table_sup[] =
-    { NULL, t360, t1200, t3in + 5 + 8, t3in + 5, t3in, t3in };
-
-static void __init register_devfs_entries(int drive)
-{
-       int base_minor = (drive < 4) ? drive : (124 + drive);
-
-       if (UDP->cmos < NUMBER(default_drive_params)) {
-               int i = 0;
-               do {
-                       int minor = base_minor + (table_sup[UDP->cmos][i] << 2);
-
-                       devfs_mk_bdev(MKDEV(FLOPPY_MAJOR, minor),
-                                     S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |
-                                     S_IWGRP, "floppy/%d%s", drive,
-                                     table[table_sup[UDP->cmos][i]]);
-               } while (table_sup[UDP->cmos][i++]);
-       }
-}
 
 /*
  * Floppy Driver initialization
@@ -3986,21 +3947,21 @@ static char __init get_fdc_version(void)
        output_byte(FD_DUMPREGS);       /* 82072 and better know DUMPREGS */
        if (FDCS->reset)
                return FDC_NONE;
-       if ((r = result()) <= 0x00)
+       r = result();
+       if (r <= 0x00)
                return FDC_NONE;        /* No FDC present ??? */
        if ((r == 1) && (reply_buffer[0] == 0x80)) {
-               printk(KERN_INFO "FDC %d is an 8272A\n", fdc);
+               pr_info("FDC %d is an 8272A\n", fdc);
                return FDC_8272A;       /* 8272a/765 don't know DUMPREGS */
        }
        if (r != 10) {
-               printk
-                   ("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n",
-                    fdc, r);
+               pr_info("FDC %d init: DUMPREGS: unexpected return of %d bytes.\n",
+                       fdc, r);
                return FDC_UNKNOWN;
        }
 
        if (!fdc_configure()) {
-               printk(KERN_INFO "FDC %d is an 82072\n", fdc);
+               pr_info("FDC %d is an 82072\n", fdc);
                return FDC_82072;       /* 82072 doesn't know CONFIGURE */
        }
 
@@ -4008,52 +3969,50 @@ static char __init get_fdc_version(void)
        if (need_more_output() == MORE_OUTPUT) {
                output_byte(0);
        } else {
-               printk(KERN_INFO "FDC %d is an 82072A\n", fdc);
+               pr_info("FDC %d is an 82072A\n", fdc);
                return FDC_82072A;      /* 82072A as found on Sparcs. */
        }
 
        output_byte(FD_UNLOCK);
        r = result();
        if ((r == 1) && (reply_buffer[0] == 0x80)) {
-               printk(KERN_INFO "FDC %d is a pre-1991 82077\n", fdc);
-               return FDC_82077_ORIG;  /* Pre-1991 82077, doesn't know 
+               pr_info("FDC %d is a pre-1991 82077\n", fdc);
+               return FDC_82077_ORIG;  /* Pre-1991 82077, doesn't know
                                         * LOCK/UNLOCK */
        }
        if ((r != 1) || (reply_buffer[0] != 0x00)) {
-               printk("FDC %d init: UNLOCK: unexpected return of %d bytes.\n",
-                      fdc, r);
+               pr_info("FDC %d init: UNLOCK: unexpected return of %d bytes.\n",
+                       fdc, r);
                return FDC_UNKNOWN;
        }
        output_byte(FD_PARTID);
        r = result();
        if (r != 1) {
-               printk("FDC %d init: PARTID: unexpected return of %d bytes.\n",
-                      fdc, r);
+               pr_info("FDC %d init: PARTID: unexpected return of %d bytes.\n",
+                       fdc, r);
                return FDC_UNKNOWN;
        }
        if (reply_buffer[0] == 0x80) {
-               printk(KERN_INFO "FDC %d is a post-1991 82077\n", fdc);
+               pr_info("FDC %d is a post-1991 82077\n", fdc);
                return FDC_82077;       /* Revised 82077AA passes all the tests */
        }
        switch (reply_buffer[0] >> 5) {
        case 0x0:
                /* Either a 82078-1 or a 82078SL running at 5Volt */
-               printk(KERN_INFO "FDC %d is an 82078.\n", fdc);
+               pr_info("FDC %d is an 82078.\n", fdc);
                return FDC_82078;
        case 0x1:
-               printk(KERN_INFO "FDC %d is a 44pin 82078\n", fdc);
+               pr_info("FDC %d is a 44pin 82078\n", fdc);
                return FDC_82078;
        case 0x2:
-               printk(KERN_INFO "FDC %d is a S82078B\n", fdc);
+               pr_info("FDC %d is a S82078B\n", fdc);
                return FDC_S82078B;
        case 0x3:
-               printk(KERN_INFO "FDC %d is a National Semiconductor PC87306\n",
-                      fdc);
+               pr_info("FDC %d is a National Semiconductor PC87306\n", fdc);
                return FDC_87306;
        default:
-               printk(KERN_INFO
-                      "FDC %d init: 82078 variant with unknown PARTID=%d.\n",
-                      fdc, reply_buffer[0] >> 5);
+               pr_info("FDC %d init: 82078 variant with unknown PARTID=%d.\n",
+                       fdc, reply_buffer[0] >> 5);
                return FDC_82078_UNKN;
        }
 }                              /* get_fdc_version */
@@ -4165,9 +4124,9 @@ static int __init floppy_setup(char *str)
                                else
                                        param = config_params[i].def_param;
                                if (config_params[i].fn)
-                                       config_params[i].
-                                           fn(ints, param,
-                                              config_params[i].param2);
+                                       config_params[i].fn(ints, param,
+                                                           config_params[i].
+                                                           param2);
                                if (config_params[i].var) {
                                        DPRINT("%s=%d\n", str, param);
                                        *config_params[i].var = param;
@@ -4181,29 +4140,57 @@ static int __init floppy_setup(char *str)
 
                DPRINT("allowed options are:");
                for (i = 0; i < ARRAY_SIZE(config_params); i++)
-                       printk(" %s", config_params[i].name);
-               printk("\n");
+                       pr_cont(" %s", config_params[i].name);
+               pr_cont("\n");
        } else
                DPRINT("botched floppy option\n");
-       DPRINT("Read Documentation/floppy.txt\n");
+       DPRINT("Read Documentation/blockdev/floppy.txt\n");
        return 0;
 }
 
 static int have_no_fdc = -ENODEV;
 
+static ssize_t floppy_cmos_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct platform_device *p = to_platform_device(dev);
+       int drive;
+
+       drive = p->id;
+       return sprintf(buf, "%X\n", UDP->cmos);
+}
+
+DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL);
+
 static void floppy_device_release(struct device *dev)
 {
-       complete(&device_release);
 }
 
-static struct platform_device floppy_device = {
-       .name           = "floppy",
-       .id             = 0,
-       .dev            = {
-                       .release = floppy_device_release,
-                       }
+static int floppy_resume(struct device *dev)
+{
+       int fdc;
+
+       for (fdc = 0; fdc < N_FDC; fdc++)
+               if (FDCS->address != -1)
+                       user_reset_fdc(-1, FD_RESET_ALWAYS, false);
+
+       return 0;
+}
+
+static const struct dev_pm_ops floppy_pm_ops = {
+       .resume = floppy_resume,
+       .restore = floppy_resume,
+};
+
+static struct platform_driver floppy_driver = {
+       .driver = {
+                  .name = "floppy",
+                  .pm = &floppy_pm_ops,
+       },
 };
 
+static struct platform_device floppy_device[N_DRIVE];
+
 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 {
        int drive = (*part & 3) | ((*part & 0x80) >> 5);
@@ -4211,7 +4198,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
            !(allowed_drive_mask & (1 << drive)) ||
            fdc_state[FDC(drive)].version == FDC_NONE)
                return NULL;
-       if (((*part >> 2) & 0x1f) >= NUMBER(floppy_type))
+       if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
                return NULL;
        *part = 0;
        return get_disk(disks[drive]);
@@ -4222,6 +4209,11 @@ static int __init floppy_init(void)
        int i, unit, drive;
        int err, dr;
 
+#if defined(CONFIG_PPC)
+       if (check_legacy_ioport(FDC1))
+               return -ENODEV;
+#endif
+
        raw_cmd = NULL;
 
        for (dr = 0; dr < N_DRIVE; dr++) {
@@ -4241,18 +4233,20 @@ static int __init floppy_init(void)
                motor_off_timer[dr].function = motor_off_callback;
        }
 
-       devfs_mk_dir("floppy");
-
        err = register_blkdev(FLOPPY_MAJOR, "fd");
        if (err)
-               goto out_devfs_remove;
+               goto out_put_disk;
+
+       err = platform_driver_register(&floppy_driver);
+       if (err)
+               goto out_unreg_blkdev;
 
        floppy_queue = blk_init_queue(do_fd_request, &floppy_lock);
        if (!floppy_queue) {
                err = -ENOMEM;
-               goto out_unreg_blkdev;
+               goto out_unreg_driver;
        }
-       blk_queue_max_sectors(floppy_queue, 64);
+       blk_queue_max_hw_sectors(floppy_queue, 64);
 
        blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE,
                            floppy_find, NULL, NULL);
@@ -4268,11 +4262,11 @@ static int __init floppy_init(void)
 
        for (i = 0; i < N_FDC; i++) {
                fdc = i;
-               CLEARSTRUCT(FDCS);
+               memset(FDCS, 0, sizeof(*FDCS));
                FDCS->dtr = -1;
                FDCS->dor = 0x4;
 #if defined(__sparc__) || defined(__mc68000__)
-               /*sparcs/sun3x don't have a DOR reset which we can fall back on to */
+       /*sparcs/sun3x don't have a DOR reset which we can fall back on to */
 #ifdef __mc68000__
                if (MACH_IS_SUN3X)
 #endif
@@ -4281,13 +4275,6 @@ static int __init floppy_init(void)
        }
 
        use_virtual_dma = can_use_virtual_dma & 1;
-#if defined(CONFIG_PPC64)
-       if (check_legacy_ioport(FDC1)) {
-               del_timer(&fd_timeout);
-               err = -ENODEV;
-               goto out_unreg_region;
-       }
-#endif
        fdc_state[0].address = FDC1;
        if (fdc_state[0].address == -1) {
                del_timer(&fd_timeout);
@@ -4308,11 +4295,11 @@ static int __init floppy_init(void)
 
        /* initialise drive state */
        for (drive = 0; drive < N_DRIVE; drive++) {
-               CLEARSTRUCT(UDRS);
-               CLEARSTRUCT(UDRWE);
-               USETF(FD_DISK_NEWCHANGE);
-               USETF(FD_DISK_CHANGED);
-               USETF(FD_VERIFY);
+               memset(UDRS, 0, sizeof(*UDRS));
+               memset(UDRWE, 0, sizeof(*UDRWE));
+               set_bit(FD_DISK_NEWCHANGE_BIT, &UDRS->flags);
+               set_bit(FD_DISK_CHANGED_BIT, &UDRS->flags);
+               set_bit(FD_VERIFY_BIT, &UDRS->flags);
                UDRS->fd_device = -1;
                floppy_track_buffer = NULL;
                max_buffer_sectors = 0;
@@ -4332,10 +4319,9 @@ static int __init floppy_init(void)
                if (FDCS->address == -1)
                        continue;
                FDCS->rawcmd = 2;
-               if (user_reset_fdc(-1, FD_RESET_ALWAYS, 0)) {
+               if (user_reset_fdc(-1, FD_RESET_ALWAYS, false)) {
                        /* free ioports reserved by floppy_grab_irq_and_dma() */
-                       release_region(FDCS->address + 2, 4);
-                       release_region(FDCS->address + 7, 1);
+                       floppy_release_regions(fdc);
                        FDCS->address = -1;
                        FDCS->version = FDC_NONE;
                        continue;
@@ -4344,8 +4330,7 @@ static int __init floppy_init(void)
                FDCS->version = get_fdc_version();
                if (FDCS->version == FDC_NONE) {
                        /* free ioports reserved by floppy_grab_irq_and_dma() */
-                       release_region(FDCS->address + 2, 4);
-                       release_region(FDCS->address + 7, 1);
+                       floppy_release_regions(fdc);
                        FDCS->address = -1;
                        continue;
                }
@@ -4357,38 +4342,49 @@ static int __init floppy_init(void)
                 * properly, so force a reset for the standard FDC clones,
                 * to avoid interrupt garbage.
                 */
-               user_reset_fdc(-1, FD_RESET_ALWAYS, 0);
+               user_reset_fdc(-1, FD_RESET_ALWAYS, false);
        }
        fdc = 0;
        del_timer(&fd_timeout);
        current_drive = 0;
-       floppy_release_irq_and_dma();
-       initialising = 0;
+       initialized = true;
        if (have_no_fdc) {
                DPRINT("no floppy controllers found\n");
                err = have_no_fdc;
                goto out_flush_work;
        }
 
-       err = platform_device_register(&floppy_device);
-       if (err)
-               goto out_flush_work;
-
        for (drive = 0; drive < N_DRIVE; drive++) {
                if (!(allowed_drive_mask & (1 << drive)))
                        continue;
                if (fdc_state[FDC(drive)].version == FDC_NONE)
                        continue;
+
+               floppy_device[drive].name = floppy_device_name;
+               floppy_device[drive].id = drive;
+               floppy_device[drive].dev.release = floppy_device_release;
+
+               err = platform_device_register(&floppy_device[drive]);
+               if (err)
+                       goto out_flush_work;
+
+               err = device_create_file(&floppy_device[drive].dev,
+                                        &dev_attr_cmos);
+               if (err)
+                       goto out_unreg_platform_dev;
+
                /* to be cleaned up... */
                disks[drive]->private_data = (void *)(long)drive;
                disks[drive]->queue = floppy_queue;
                disks[drive]->flags |= GENHD_FL_REMOVABLE;
-               disks[drive]->driverfs_dev = &floppy_device.dev;
+               disks[drive]->driverfs_dev = &floppy_device[drive].dev;
                add_disk(disks[drive]);
        }
 
        return 0;
 
+out_unreg_platform_dev:
+       platform_device_unregister(&floppy_device[drive]);
 out_flush_work:
        flush_scheduled_work();
        if (usage_count)
@@ -4396,10 +4392,10 @@ out_flush_work:
 out_unreg_region:
        blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
        blk_cleanup_queue(floppy_queue);
+out_unreg_driver:
+       platform_driver_unregister(&floppy_driver);
 out_unreg_blkdev:
        unregister_blkdev(FLOPPY_MAJOR, "fd");
-out_devfs_remove:
-       devfs_remove("floppy");
 out_put_disk:
        while (dr--) {
                del_timer(&motor_off_timer[dr]);
@@ -4410,6 +4406,49 @@ out_put_disk:
 
 static DEFINE_SPINLOCK(floppy_usage_lock);
 
+static const struct io_region {
+       int offset;
+       int size;
+} io_regions[] = {
+       { 2, 1 },
+       /* address + 3 is sometimes reserved by pnp bios for motherboard */
+       { 4, 2 },
+       /* address + 6 is reserved, and may be taken by IDE.
+        * Unfortunately, Adaptec doesn't know this :-(, */
+       { 7, 1 },
+};
+
+static void floppy_release_allocated_regions(int fdc, const struct io_region *p)
+{
+       while (p != io_regions) {
+               p--;
+               release_region(FDCS->address + p->offset, p->size);
+       }
+}
+
+#define ARRAY_END(X) (&((X)[ARRAY_SIZE(X)]))
+
+static int floppy_request_regions(int fdc)
+{
+       const struct io_region *p;
+
+       for (p = io_regions; p < ARRAY_END(io_regions); p++) {
+               if (!request_region(FDCS->address + p->offset,
+                                   p->size, "floppy")) {
+                       DPRINT("Floppy io-port 0x%04lx in use\n",
+                              FDCS->address + p->offset);
+                       floppy_release_allocated_regions(fdc, p);
+                       return -EBUSY;
+               }
+       }
+       return 0;
+}
+
+static void floppy_release_regions(int fdc)
+{
+       floppy_release_allocated_regions(fdc, ARRAY_END(io_regions));
+}
+
 static int floppy_grab_irq_and_dma(void)
 {
        unsigned long flags;
@@ -4420,6 +4459,13 @@ static int floppy_grab_irq_and_dma(void)
                return 0;
        }
        spin_unlock_irqrestore(&floppy_usage_lock, flags);
+
+       /*
+        * We might have scheduled a free_irq(), wait it to
+        * drain first:
+        */
+       flush_scheduled_work();
+
        if (fd_request_irq()) {
                DPRINT("Unable to grab IRQ%d for the floppy driver\n",
                       FLOPPY_IRQ);
@@ -4431,27 +4477,21 @@ static int floppy_grab_irq_and_dma(void)
        if (fd_request_dma()) {
                DPRINT("Unable to grab DMA%d for the floppy driver\n",
                       FLOPPY_DMA);
-               fd_free_irq();
-               spin_lock_irqsave(&floppy_usage_lock, flags);
-               usage_count--;
-               spin_unlock_irqrestore(&floppy_usage_lock, flags);
-               return -1;
+               if (can_use_virtual_dma & 2)
+                       use_virtual_dma = can_use_virtual_dma = 1;
+               if (!(can_use_virtual_dma & 1)) {
+                       fd_free_irq();
+                       spin_lock_irqsave(&floppy_usage_lock, flags);
+                       usage_count--;
+                       spin_unlock_irqrestore(&floppy_usage_lock, flags);
+                       return -1;
+               }
        }
 
        for (fdc = 0; fdc < N_FDC; fdc++) {
                if (FDCS->address != -1) {
-                       if (!request_region(FDCS->address + 2, 4, "floppy")) {
-                               DPRINT("Floppy io-port 0x%04lx in use\n",
-                                      FDCS->address + 2);
-                               goto cleanup1;
-                       }
-                       if (!request_region(FDCS->address + 7, 1, "floppy DIR")) {
-                               DPRINT("Floppy io-port 0x%04lx in use\n",
-                                      FDCS->address + 7);
-                               goto cleanup2;
-                       }
-                       /* address + 6 is reserved, and may be taken by IDE.
-                        * Unfortunately, Adaptec doesn't know this :-(, */
+                       if (floppy_request_regions(fdc))
+                               goto cleanup;
                }
        }
        for (fdc = 0; fdc < N_FDC; fdc++) {
@@ -4467,21 +4507,17 @@ static int floppy_grab_irq_and_dma(void)
                if (FDCS->address != -1)
                        fd_outb(FDCS->dor, FD_DOR);
        /*
-        *      The driver will try and free resources and relies on us
-        *      to know if they were allocated or not.
+        * The driver will try and free resources and relies on us
+        * to know if they were allocated or not.
         */
        fdc = 0;
        irqdma_allocated = 1;
        return 0;
-cleanup2:
-       release_region(FDCS->address + 2, 4);
-cleanup1:
+cleanup:
        fd_free_irq();
        fd_free_dma();
-       while (--fdc >= 0) {
-               release_region(FDCS->address + 2, 4);
-               release_region(FDCS->address + 7, 1);
-       }
+       while (--fdc >= 0)
+               floppy_release_regions(fdc);
        spin_lock_irqsave(&floppy_usage_lock, flags);
        usage_count--;
        spin_unlock_irqrestore(&floppy_usage_lock, flags);
@@ -4530,22 +4566,20 @@ static void floppy_release_irq_and_dma(void)
 #ifndef __sparc__
        for (drive = 0; drive < N_FDC * 4; drive++)
                if (timer_pending(motor_off_timer + drive))
-                       printk("motor off timer %d still active\n", drive);
+                       pr_info("motor off timer %d still active\n", drive);
 #endif
 
        if (timer_pending(&fd_timeout))
-               printk("floppy timer still active:%s\n", timeout_message);
+               pr_info("floppy timer still active:%s\n", timeout_message);
        if (timer_pending(&fd_timer))
-               printk("auxiliary floppy timer still active\n");
-       if (floppy_work.pending)
-               printk("work still pending\n");
+               pr_info("auxiliary floppy timer still active\n");
+       if (work_pending(&floppy_work))
+               pr_info("work still pending\n");
 #endif
        old_fdc = fdc;
        for (fdc = 0; fdc < N_FDC; fdc++)
-               if (FDCS->address != -1) {
-                       release_region(FDCS->address + 2, 4);
-                       release_region(FDCS->address + 7, 1);
-               }
+               if (FDCS->address != -1)
+                       floppy_release_regions(fdc);
        fdc = old_fdc;
 }
 
@@ -4553,25 +4587,14 @@ static void floppy_release_irq_and_dma(void)
 
 static char *floppy;
 
-static void unregister_devfs_entries(int drive)
-{
-       int i;
-
-       if (UDP->cmos < NUMBER(default_drive_params)) {
-               i = 0;
-               do {
-                       devfs_remove("floppy/%d%s", drive,
-                                    table[table_sup[UDP->cmos][i]]);
-               } while (table_sup[UDP->cmos][i++]);
-       }
-}
-
 static void __init parse_floppy_cfg_string(char *cfg)
 {
        char *ptr;
 
        while (*cfg) {
-               for (ptr = cfg; *cfg && *cfg != ' ' && *cfg != '\t'; cfg++) ;
+               ptr = cfg;
+               while (*cfg && *cfg != ' ' && *cfg != '\t')
+                       cfg++;
                if (*cfg) {
                        *cfg = '\0';
                        cfg++;
@@ -4581,20 +4604,21 @@ static void __init parse_floppy_cfg_string(char *cfg)
        }
 }
 
-int init_module(void)
+static int __init floppy_module_init(void)
 {
        if (floppy)
                parse_floppy_cfg_string(floppy);
        return floppy_init();
 }
+module_init(floppy_module_init);
 
-void cleanup_module(void)
+static void __exit floppy_module_exit(void)
 {
        int drive;
 
-       init_completion(&device_release);
        blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
        unregister_blkdev(FLOPPY_MAJOR, "fd");
+       platform_driver_unregister(&floppy_driver);
 
        for (drive = 0; drive < N_DRIVE; drive++) {
                del_timer_sync(&motor_off_timer[drive]);
@@ -4602,12 +4626,11 @@ void cleanup_module(void)
                if ((allowed_drive_mask & (1 << drive)) &&
                    fdc_state[FDC(drive)].version != FDC_NONE) {
                        del_gendisk(disks[drive]);
-                       unregister_devfs_entries(drive);
+                       device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
+                       platform_device_unregister(&floppy_device[drive]);
                }
                put_disk(disks[drive]);
        }
-       platform_device_unregister(&floppy_device);
-       devfs_remove("floppy");
 
        del_timer_sync(&fd_timeout);
        del_timer_sync(&fd_timer);
@@ -4618,10 +4641,10 @@ void cleanup_module(void)
 
        /* eject disk, if any */
        fd_eject(0);
-
-       wait_for_completion(&device_release);
 }
 
+module_exit(floppy_module_exit);
+
 module_param(floppy, charp, 0);
 module_param(FLOPPY_IRQ, int, 0);
 module_param(FLOPPY_DMA, int, 0);
@@ -4629,6 +4652,14 @@ MODULE_AUTHOR("Alain L. Knaff");
 MODULE_SUPPORTED_DEVICE("fd");
 MODULE_LICENSE("GPL");
 
+/* This doesn't actually get used other than for module information */
+static const struct pnp_device_id floppy_pnpids[] = {
+       {"PNP0700", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(pnp, floppy_pnpids);
+
 #else
 
 __setup("floppy=", floppy_setup);