drivers/block/floppy.c: indent a comment
[safe/jmp/linux-2.6] / drivers / block / floppy.c
index 9e6d3a8..7743d6c 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
@@ -161,10 +162,8 @@ static int print_unex = 1;
 #include <linux/workqueue.h>
 #define FDPATCHES
 #include <linux/fdreg.h>
-
 #include <linux/fd.h>
 #include <linux/hdreg.h>
-
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
@@ -178,8 +177,11 @@ static int print_unex = 1;
 #include <linux/interrupt.h>
 #include <linux/init.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.
@@ -191,8 +193,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;
@@ -218,7 +218,6 @@ 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);
@@ -251,7 +250,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)
@@ -264,7 +263,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)
@@ -274,8 +273,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;
@@ -287,57 +285,57 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l)
 static unsigned long fake_change;
 static int initialising = 1;
 
-#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 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...) \
+       pr_info(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)
 
 /* 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 */
@@ -348,16 +346,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.
@@ -427,8 +425,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
@@ -472,8 +477,8 @@ 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"    */
 };
@@ -501,9 +506,9 @@ static char floppy_device_name[] = "floppy";
 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 +516,11 @@ 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)
+#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 +544,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 +561,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 +573,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 +580,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,7 +625,7 @@ 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) { }
@@ -641,13 +648,13 @@ static void is_alive(const char *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 +677,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 +697,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,6 +736,7 @@ 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 (time_before(jiffies, UDRS->select_date + UDP->select_delay))
                DPRINT("WARNING disk change called early\n");
@@ -771,7 +775,6 @@ 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;
@@ -787,7 +790,10 @@ static inline int is_selected(int dor, int unit)
 
 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;
@@ -799,9 +805,8 @@ static int set_dor(int fdc, char mask, char data)
                if (is_selected(olddor, unit) && !is_selected(newdor, unit)) {
                        drive = REVDRIVE(fdc, unit);
 #ifdef DCL_DEBUG
-                       if (UDP->flags & FD_DEBUG) {
+                       if (UDP->flags & FD_DEBUG)
                                DPRINT("calling disk change from set_dor\n");
-                       }
 #endif
                        disk_change(drive);
                }
@@ -849,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);
@@ -866,8 +871,7 @@ static void set_fdc(int drive)
 static int _lock_fdc(int drive, int 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;
        }
@@ -892,7 +896,6 @@ 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;
@@ -902,10 +905,12 @@ 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)                 \
+       _lock_fdc(drive, interruptible, __LINE__)
 
-#define LOCK_FDC(drive,interruptible) \
-if (lock_fdc(drive,interruptible)) return -EINTR;
+#define LOCK_FDC(drive, interruptible)     \
+       if (lock_fdc(drive, interruptible)) \
+               return -EINTR;
 
 /* unlocks the driver */
 static inline void unlock_fdc(void)
@@ -924,7 +929,7 @@ 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);
        wake_up(&fdc_wait);
@@ -942,7 +947,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;
@@ -968,7 +973,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;
@@ -992,11 +999,11 @@ 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);
 }
 
@@ -1008,7 +1015,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);
 }
@@ -1018,9 +1025,8 @@ static void cancel_activity(void)
 static void fd_watchdog(void)
 {
 #ifdef DCL_DEBUG
-       if (DP->flags & FD_DEBUG) {
+       if (DP->flags & FD_DEBUG)
                DPRINT("calling disk change from watchdog\n");
-       }
 #endif
 
        if (disk_change(current_drive)) {
@@ -1100,16 +1106,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;
@@ -1146,7 +1152,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++) {
@@ -1165,9 +1173,9 @@ 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) {
                fd_outb(byte, FD_DATA);
@@ -1188,15 +1196,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) {
@@ -1225,8 +1233,9 @@ 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)
                return MORE_OUTPUT;
@@ -1251,9 +1260,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
@@ -1309,8 +1321,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;
@@ -1319,7 +1334,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) {
@@ -1350,20 +1364,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)
@@ -1400,16 +1414,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,34 +1489,7 @@ static int interpret_errors(void)
                                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 */
@@ -1498,7 +1515,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;
 
@@ -1568,8 +1588,7 @@ static void seek_interrupt(void)
        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("clearing NEWCHANGE flag because of effective seek\n");
                        DPRINT("jiffies=%lu\n", jiffies);
                }
 #endif
@@ -1612,9 +1631,8 @@ static void seek_floppy(void)
        blind_seek = 0;
 
 #ifdef DCL_DEBUG
-       if (DP->flags & FD_DEBUG) {
+       if (DP->flags & FD_DEBUG)
                DPRINT("calling disk change from seek\n");
-       }
 #endif
 
        if (!TESTF(FD_DISK_NEWCHANGE) &&
@@ -1660,7 +1678,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:");
 }
 
@@ -1689,10 +1710,8 @@ static void recal_interrupt(void)
                         * 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");
-                       }
+                       if (DP->flags & FD_DEBUG)
+                               DPRINT("clearing NEWCHANGE flag because of second recalibrate\n");
 #endif
 
                        CLEARF(FD_DISK_NEWCHANGE);
@@ -1721,16 +1740,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)
 {
-       void (*handler) (void) = do_floppy;
        int do_print;
        unsigned long f;
+       void (*handler)(void) = do_floppy;
 
        lasthandler = handler;
        interruptjiffies = jiffies;
@@ -1743,9 +1762,9 @@ irqreturn_t floppy_interrupt(int irq, void *dev_id)
        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;
        }
@@ -1792,7 +1811,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;
+       }
 }
 
 /*
@@ -1803,7 +1825,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();
@@ -1841,46 +1863,44 @@ 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)
@@ -1906,18 +1926,17 @@ static void floppy_shutdown(unsigned long data)
                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);
@@ -1938,27 +1957,29 @@ 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) {
+       if (DP->flags & FD_DEBUG)
                DPRINT("calling disk change from floppy_ready\n");
-       }
 #endif
        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)) {
@@ -1986,9 +2007,8 @@ static void floppy_start(void)
 
        scandrives();
 #ifdef DCL_DEBUG
-       if (DP->flags & FD_DEBUG) {
+       if (DP->flags & FD_DEBUG)
                DPRINT("setting NEWCHANGE in floppy_start\n");
-       }
 #endif
        SETF(FD_DISK_NEWCHANGE);
        floppy_ready();
@@ -2020,17 +2040,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), int interruptible)
 {
        int ret;
 
@@ -2049,7 +2069,6 @@ static int wait_til_done(void (*handler) (void), int interruptible)
                                break;
 
                        is_alive("wait_til_done");
-
                        schedule();
                }
 
@@ -2141,6 +2160,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
@@ -2165,21 +2185,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);
@@ -2227,9 +2251,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;
        }
 }
 
@@ -2277,21 +2301,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, uptodate);
 
        /* We're done with the request */
+       floppy_off(drive);
        current_req = NULL;
 }
 
@@ -2305,38 +2327,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);
        }
 }
@@ -2344,7 +2366,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
@@ -2375,16 +2400,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
 
@@ -2437,22 +2462,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;
@@ -2479,32 +2501,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
 
@@ -2512,45 +2534,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) {
@@ -2561,19 +2580,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
@@ -2583,7 +2589,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 */
@@ -2592,13 +2599,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 */
        }
 }
 
@@ -2615,10 +2623,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;
        }
 
@@ -2641,10 +2652,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
@@ -2652,7 +2663,7 @@ static int make_raw_rw_request(void)
        }
        HEAD = fsector_t / _floppy->sect;
 
-       if (((_floppy->stretch & (FD_SWAPSIDES | FD_ZEROBASED)) ||
+       if (((_floppy->stretch & (FD_SWAPSIDES | FD_SECTBASEMASK)) ||
             TESTF(FD_NEED_TWADDLE)) && fsector_t < _floppy->sect)
                max_sector = _floppy->sect;
 
@@ -2662,7 +2673,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;
@@ -2682,7 +2693,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.
@@ -2713,7 +2724,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)) {
@@ -2722,10 +2733,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;
@@ -2746,12 +2759,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 -
@@ -2768,24 +2779,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;
                }
@@ -2800,17 +2805,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.
@@ -2835,8 +2839,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 &&
@@ -2847,19 +2849,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;
        }
 
@@ -2870,24 +2872,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");
@@ -2914,7 +2916,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;
@@ -2981,18 +2983,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 type=%x flags=%x\n", (long)current_req->sector,
-                      current_req->cmd_type, current_req->cmd_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)) {
@@ -3016,6 +3019,7 @@ static struct cont_t poll_cont = {
 static int poll_drive(int interruptible, int flag)
 {
        int ret;
+
        /* no auto-sense, just clear dcl */
        raw_cmd = &default_raw_cmd;
        raw_cmd->flags = flag;
@@ -3023,9 +3027,8 @@ static int poll_drive(int interruptible, int flag)
        raw_cmd->cmd_count = 0;
        cont = &poll_cont;
 #ifdef DCL_DEBUG
-       if (DP->flags & FD_DEBUG) {
+       if (DP->flags & FD_DEBUG)
                DPRINT("setting NEWCHANGE in poll_drive\n");
-       }
 #endif
        SETF(FD_DISK_NEWCHANGE);
        WAIT(floppy_ready);
@@ -3039,7 +3042,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 = {
@@ -3075,16 +3078,19 @@ 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)    (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))
+#define COPYOUT(x)     ECALL(_COPYOUT(x))
+#define COPYIN(x)      ECALL(_COPYIN(x))
 
 static inline const char *drive_name(int type, int drive)
 {
@@ -3165,11 +3171,12 @@ static inline int raw_cmd_copyout(int cmd, char __user *param,
                COPYOUT(*ptr);
                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;
+                               ECALL(fd_copyout(ptr->data, ptr->kernel_data,
+                                                length));
+                       }
                }
                ptr = ptr->next;
        }
@@ -3178,7 +3185,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;
@@ -3250,8 +3258,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;
@@ -3282,9 +3292,8 @@ static int raw_cmd_ioctl(int cmd, void __user *param)
        cont = &raw_cmd_cont;
        ret = wait_til_done(floppy_start, 1);
 #ifdef DCL_DEBUG
-       if (DP->flags & FD_DEBUG) {
+       if (DP->flags & FD_DEBUG)
                DPRINT("calling disk change from raw_cmd ioctl\n");
-       }
 #endif
 
        if (ret != -EINTR && FDCS->reset)
@@ -3318,13 +3327,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;
                mutex_lock(&open_lock);
-               LOCK_FDC(drive, 1);
+               if (lock_fdc(drive, 1)) {
+                       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++)
@@ -3363,7 +3375,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();
@@ -3409,7 +3421,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;
@@ -3450,15 +3462,16 @@ static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
        return 0;
 }
 
-static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+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 FD_IOCTL_ALLOWED (mode & (FMODE_WRITE|FMODE_WRITE_IOCTL))
 #define OUT(c,x) case c: outparam = (const char *) (x); break
 #define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0
 
-       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 {
@@ -3473,25 +3486,28 @@ 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;
        }
 
-       /* convert the old style command into a new style command */
-       if ((cmd & 0xff00) == 0x0200) {
-               ECALL(normalize_ioctl(&cmd, &size));
-       } else
+       if (!((cmd & 0xff00) == 0x0200))
                return -EINVAL;
 
+       /* convert the old style command into a new style command */
+       ECALL(normalize_ioctl(&cmd, &size));
+
        /* 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);
+       memset(&inparam, 0, sizeof(inparam));
        if (_IOC_DIR(cmd) & _IOC_WRITE)
            ECALL(fd_copyin((void __user *)param, &inparam, size))
 
@@ -3515,11 +3531,11 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        current_type[drive] = NULL;
                        floppy_sizes[drive] = MAX_DISK_SIZE << 1;
                        UDRS->keep_data = 0;
-                       return invalidate_drive(inode->i_bdev);
+                       return invalidate_drive(bdev);
                case FDSETPRM:
                case FDDEFPRM:
                        return set_geometry(cmd, &inparam.g,
-                                           drive, type, inode->i_bdev);
+                                           drive, type, bdev);
                case FDGETPRM:
                        ECALL(get_floppy_geometry(drive, type,
                                                  (struct floppy_struct **)
@@ -3550,7 +3566,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                case FDFMTEND:
                case FDFLUSH:
                        LOCK_FDC(drive, 1);
-                       return invalidate_drive(inode->i_bdev);
+                       return invalidate_drive(bdev);
 
                case FDSETEMSGTRESH:
                        UDP->max_errors.reporting =
@@ -3580,7 +3596,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        OUT(FDGETFDCSTAT, UFDCS);
 
                case FDWERRORCLR:
-                       CLEARSTRUCT(UDRWE);
+                       memset(UDRWE, 0, sizeof(*UDRWE));
                        return 0;
                        OUT(FDWERRORGET, UDRWE);
 
@@ -3613,7 +3629,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 
 static void __init config_types(void)
 {
-       int first = 1;
+       bool has_drive = false;
        int drive;
 
        /* read drive info out of physical CMOS */
@@ -3624,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;
@@ -3646,22 +3661,27 @@ 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);
+
+                       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;
 
        mutex_lock(&open_lock);
        if (UDRS->fd_ref < 0)
@@ -3682,18 +3702,17 @@ 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;
        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)) {
@@ -3701,15 +3720,15 @@ static int floppy_open(struct inode *inode, struct file *filp)
                USETF(FD_VERIFY);
        }
 
-       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 (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;
 
@@ -3727,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;
@@ -3744,31 +3762,26 @@ 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 & FMODE_WRITE) || !file_permission(filp, MAY_WRITE))
-               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);
+                       check_disk_change(bdev);
                        if (UTESTF(FD_DISK_CHANGED))
                                goto out;
                }
                res = -EROFS;
-               if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE)))
+               if ((mode & FMODE_WRITE) && !(UTESTF(FD_DISK_WRITABLE)))
                        goto out;
        }
        mutex_unlock(&open_lock);
@@ -3815,14 +3828,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)
@@ -3881,7 +3889,7 @@ static int floppy_revalidate(struct gendisk *disk)
        if (UTESTF(FD_DISK_CHANGED) ||
            UTESTF(FD_VERIFY) || 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);
@@ -3911,14 +3919,14 @@ 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,
-       .getgeo         = fd_getgeo,
-       .media_changed  = check_floppy_change,
-       .revalidate_disk = floppy_revalidate,
+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,
 };
 
 /*
@@ -3935,21 +3943,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 */
        }
 
@@ -3957,52 +3965,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 */
@@ -4114,9 +4120,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;
@@ -4130,11 +4136,11 @@ 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;
 }
 
@@ -4143,20 +4149,42 @@ 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;
+       struct platform_device *p = to_platform_device(dev);
        int drive;
 
-       p = container_of(dev, struct platform_device,dev);
        drive = p->id;
        return sprintf(buf, "%X\n", UDP->cmos);
 }
-DEVICE_ATTR(cmos,S_IRUGO,floppy_cmos_show,NULL);
+
+DEVICE_ATTR(cmos, S_IRUGO, floppy_cmos_show, NULL);
 
 static void floppy_device_release(struct device *dev)
 {
-       complete(&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, 0);
+
+       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)
@@ -4177,7 +4205,7 @@ static int __init floppy_init(void)
        int i, unit, drive;
        int err, dr;
 
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
        if (check_legacy_ioport(FDC1))
                return -ENODEV;
 #endif
@@ -4205,12 +4233,16 @@ static int __init floppy_init(void)
        if (err)
                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);
@@ -4226,11 +4258,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
@@ -4259,8 +4291,8 @@ static int __init floppy_init(void)
 
        /* initialise drive state */
        for (drive = 0; drive < N_DRIVE; drive++) {
-               CLEARSTRUCT(UDRS);
-               CLEARSTRUCT(UDRWE);
+               memset(UDRS, 0, sizeof(*UDRS));
+               memset(UDRWE, 0, sizeof(*UDRWE));
                USETF(FD_DISK_NEWCHANGE);
                USETF(FD_DISK_CHANGED);
                USETF(FD_VERIFY);
@@ -4285,8 +4317,7 @@ static int __init floppy_init(void)
                FDCS->rawcmd = 2;
                if (user_reset_fdc(-1, FD_RESET_ALWAYS, 0)) {
                        /* 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;
@@ -4295,8 +4326,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;
                }
@@ -4334,7 +4364,11 @@ static int __init floppy_init(void)
                if (err)
                        goto out_flush_work;
 
-               device_create_file(&floppy_device[drive].dev,&dev_attr_cmos);
+               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;
@@ -4345,6 +4379,8 @@ static int __init floppy_init(void)
 
        return 0;
 
+out_unreg_platform_dev:
+       platform_device_unregister(&floppy_device[drive]);
 out_flush_work:
        flush_scheduled_work();
        if (usage_count)
@@ -4352,6 +4388,8 @@ 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_put_disk:
@@ -4364,6 +4402,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;
@@ -4392,27 +4473,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++) {
@@ -4428,21 +4503,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);
@@ -4491,22 +4562,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;
 }
 
@@ -4519,7 +4588,9 @@ 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++;
@@ -4529,20 +4600,21 @@ static void __init parse_floppy_cfg_string(char *cfg)
        }
 }
 
-int __init 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]);
@@ -4565,10 +4637,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);
@@ -4576,6 +4648,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);