Index: hw/fdc.c
===================================================================
--- hw/fdc.c	(revision 5771)
+++ hw/fdc.c	(working copy)
@@ -471,7 +471,12 @@
     uint8_t version;
     /* HW */
     qemu_irq irq;
-    int dma_chann;
+    fdcdma_memory_read_write dma_memory_read;
+    fdcdma_memory_read_write dma_memory_write;
+    fdcdma_hold_release dma_hold;
+    fdcdma_hold_release dma_release;
+    void *dma_opaque;
+    int i8257_dma_chann;
     target_phys_addr_t io_base;
     /* Controller state */
     QEMUTimer *result_timer;
@@ -771,7 +776,7 @@
         fdctrl->sra |= FD_SRA_nDRV2;
     fdctrl->cur_drv = 0;
     fdctrl->dor = FD_DOR_nRESET;
-    fdctrl->dor |= (fdctrl->dma_chann != -1) ? FD_DOR_DMAEN : 0;
+    fdctrl->dor |= (fdctrl->dma_memory_read && fdctrl->dma_memory_write) ? FD_DOR_DMAEN : 0;
     fdctrl->msr = FD_MSR_RQM;
     /* FIFO state */
     fdctrl->data_pos = 0;
@@ -1068,8 +1073,8 @@
     fdctrl->fifo[5] = cur_drv->sect;
     fdctrl->fifo[6] = FD_SECTOR_SC;
     fdctrl->data_dir = FD_DIR_READ;
-    if (!(fdctrl->msr & FD_MSR_NONDMA)) {
-        DMA_release_DREQ(fdctrl->dma_chann);
+    if (!(fdctrl->msr & FD_MSR_NONDMA) && fdctrl->dma_release) {
+        fdctrl->dma_release(fdctrl->dma_opaque);
     }
     fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
     fdctrl->msr &= ~FD_MSR_NONDMA;
@@ -1144,29 +1149,15 @@
     }
     fdctrl->eot = fdctrl->fifo[6];
     if (fdctrl->dor & FD_DOR_DMAEN) {
-        int dma_mode;
-        /* DMA transfer are enabled. Check if DMA channel is well programmed */
-        dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
-        dma_mode = (dma_mode >> 2) & 3;
-        FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n",
-                       dma_mode, direction,
-                       (128 << fdctrl->fifo[5]) *
-                       (cur_drv->last_sect - ks + 1), fdctrl->data_len);
-        if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
-              direction == FD_DIR_SCANH) && dma_mode == 0) ||
-            (direction == FD_DIR_WRITE && dma_mode == 2) ||
-            (direction == FD_DIR_READ && dma_mode == 1)) {
-            /* No access is allowed until DMA transfer has completed */
+        /* DMA transfer are enabled */
+        if (fdctrl->dma_hold) {
+            fdctrl->dma_hold(fdctrl->dma_opaque);
+        } else {
+            /* Do the transfer synchronously... */
             fdctrl->msr &= ~FD_MSR_RQM;
-            /* Now, we just have to wait for the DMA controller to
-             * recall us...
-             */
-            DMA_hold_DREQ(fdctrl->dma_chann);
-            DMA_schedule(fdctrl->dma_chann);
-            return;
-        } else {
-            FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, direction);
+            fdctrl_transfer_handler(fdctrl, -1, 0, fdctrl->data_len);
         }
+        return;
     }
     FLOPPY_DPRINTF("start non-DMA transfer\n");
     fdctrl->msr |= FD_MSR_NONDMA;
@@ -1174,8 +1165,6 @@
         fdctrl->msr |= FD_MSR_DIO;
     /* IO based transfer: calculate len */
     fdctrl_raise_irq(fdctrl, 0x00);
-
-    return;
 }
 
 /* Prepare a transfer of deleted data */
@@ -1241,13 +1230,11 @@
         switch (fdctrl->data_dir) {
         case FD_DIR_READ:
             /* READ commands */
-            DMA_write_memory (nchan, fdctrl->fifo + rel_pos,
-                              fdctrl->data_pos, len);
+            fdctrl->dma_memory_write(fdctrl->dma_opaque, fdctrl->fifo + rel_pos, len);
             break;
         case FD_DIR_WRITE:
             /* WRITE commands */
-            DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
-                             fdctrl->data_pos, len);
+            fdctrl->dma_memory_read(fdctrl->dma_opaque, fdctrl->fifo + rel_pos, len);
             if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),
                            fdctrl->fifo, 1) < 0) {
                 FLOPPY_ERROR("writing sector %d\n", fd_sector(cur_drv));
@@ -1260,7 +1247,7 @@
             {
                 uint8_t tmpbuf[FD_SECTOR_LEN];
                 int ret;
-                DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len);
+                fdctrl->dma_memory_read(fdctrl->dma_opaque, tmpbuf, len);
                 ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
                 if (ret == 0) {
                     status2 = FD_SR2_SEH;
@@ -1833,7 +1820,12 @@
 }
 
 /* Init functions */
-static fdctrl_t *fdctrl_init_common (qemu_irq irq, int dma_chann,
+static fdctrl_t *fdctrl_init_common (qemu_irq irq,
+                                     fdcdma_memory_read_write dma_memory_read,
+                                     fdcdma_memory_read_write dma_memory_write,
+                                     fdcdma_hold_release dma_hold,
+                                     fdcdma_hold_release dma_release,
+                                     void *dma_opaque,
                                      target_phys_addr_t io_base,
                                      BlockDriverState **fds)
 {
@@ -1862,12 +1854,13 @@
 
     fdctrl->version = 0x90; /* Intel 82078 controller */
     fdctrl->irq = irq;
-    fdctrl->dma_chann = dma_chann;
+    fdctrl->dma_memory_read = dma_memory_read;
+    fdctrl->dma_memory_write = dma_memory_write;
+    fdctrl->dma_hold = dma_hold;
+    fdctrl->dma_release = dma_release;
+    fdctrl->dma_opaque = dma_opaque;
     fdctrl->io_base = io_base;
     fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */
-    if (fdctrl->dma_chann != -1) {
-        DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
-    }
     for (i = 0; i < MAX_FD; i++) {
         fd_init(&fdctrl->drives[i], fds[i]);
     }
@@ -1881,14 +1874,21 @@
     return fdctrl;
 }
 
-fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped,
+fdctrl_t *fdctrl_init (qemu_irq irq,
+                       fdcdma_memory_read_write dma_memory_read,
+                       fdcdma_memory_read_write dma_memory_write,
+                       fdcdma_hold_release dma_hold,
+                       fdcdma_hold_release dma_release,
+                       void *dma_opaque, int mem_mapped,
                        target_phys_addr_t io_base,
                        BlockDriverState **fds)
 {
     fdctrl_t *fdctrl;
     int io_mem;
 
-    fdctrl = fdctrl_init_common(irq, dma_chann, io_base, fds);
+    fdctrl = fdctrl_init_common(irq, dma_memory_read, dma_memory_write,
+                                dma_hold, dma_release,
+                                dma_opaque, io_base, fds);
 
     fdctrl->sun4m = 0;
     if (mem_mapped) {
@@ -1915,7 +1915,7 @@
     fdctrl_t *fdctrl;
     int io_mem;
 
-    fdctrl = fdctrl_init_common(irq, -1, io_base, fds);
+    fdctrl = fdctrl_init_common(irq, NULL, NULL, NULL, NULL, NULL, io_base, fds);
     fdctrl->sun4m = 1;
     io_mem = cpu_register_io_memory(0, fdctrl_mem_read_strict,
                                     fdctrl_mem_write_strict,
@@ -1925,3 +1925,81 @@
 
     return fdctrl;
 }
+
+static void i8257_dma_read(void *opaque, uint8_t *buf, int len)
+{
+    fdctrl_t *fdctrl = opaque;
+    DMA_read_memory(fdctrl->i8257_dma_chann, buf, fdctrl->data_pos, len);
+}
+
+static void i8257_dma_write(void *opaque, uint8_t *buf, int len)
+{
+    fdctrl_t *fdctrl = opaque;
+    DMA_write_memory(fdctrl->i8257_dma_chann, buf, fdctrl->data_pos, len);
+}
+
+static void i8257_dma_hold(void *opaque)
+{
+    fdctrl_t *fdctrl = opaque;
+    int dma_mode;
+    int direction = fdctrl->data_dir;
+
+    /* DMA transfer are enabled. Check if DMA channel is well programmed */
+    dma_mode = DMA_get_channel_mode(fdctrl->i8257_dma_chann);
+    dma_mode = (dma_mode >> 2) & 3;
+    FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n",
+                   dma_mode, direction,
+                   (128 << fdctrl->fifo[5]) *
+                   (cur_drv->last_sect - fdctrl->fifo[4] + 1), fdctrl->data_len);
+    if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
+          direction == FD_DIR_SCANH) && dma_mode == 0) ||
+        (direction == FD_DIR_WRITE && dma_mode == 2) ||
+        (direction == FD_DIR_READ && dma_mode == 1)) {
+        /* No access is allowed until DMA transfer has completed */
+        fdctrl->msr &= ~FD_MSR_RQM;
+        /* Now, we just have to wait for the DMA controller to
+         * recall us...
+         */
+        DMA_hold_DREQ(fdctrl->i8257_dma_chann);
+        DMA_schedule(fdctrl->i8257_dma_chann);
+    } else {
+        FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, direction);
+    }
+}
+
+static void i8257_dma_release(void *opaque)
+{
+    fdctrl_t *fdctrl = opaque;
+    DMA_release_DREQ(fdctrl->i8257_dma_chann);
+}
+
+fdctrl_t *fdctrl_i8257_init (qemu_irq irq, int i8257_dma_chann,
+                             int mem_mapped,
+                             target_phys_addr_t io_base,
+                             BlockDriverState **fds)
+{
+    fdcdma_memory_read_write dma_memory_read = NULL;
+    fdcdma_memory_read_write dma_memory_write = NULL;
+    fdcdma_hold_release dma_hold = NULL;
+    fdcdma_hold_release dma_release = NULL;
+    fdctrl_t *fdctrl;
+
+    if (i8257_dma_chann != -1) {
+        dma_memory_read = i8257_dma_read;
+        dma_memory_write = i8257_dma_write;
+        dma_hold = i8257_dma_hold;
+        dma_release = i8257_dma_release;
+    }
+
+    fdctrl = fdctrl_init(irq, dma_memory_read, dma_memory_write,
+                         i8257_dma_hold, i8257_dma_release, NULL,
+                         mem_mapped, io_base, fds);
+
+    if (i8257_dma_chann != -1) {
+        fdctrl->dma_opaque = fdctrl;
+        fdctrl->i8257_dma_chann = i8257_dma_chann;
+        DMA_register_channel(fdctrl->i8257_dma_chann, &fdctrl_transfer_handler, fdctrl);
+    }
+
+    return fdctrl;
+}
\ No newline at end of file
Index: hw/fdc.h
===================================================================
--- hw/fdc.h	(revision 5771)
+++ hw/fdc.h	(working copy)
@@ -3,9 +3,20 @@
 
 typedef struct fdctrl_t fdctrl_t;
 
-fdctrl_t *fdctrl_init (qemu_irq irq, int dma_chann, int mem_mapped,
+typedef void (*fdcdma_memory_read_write)(void *opaque, uint8_t *buf, int len);
+typedef void (*fdcdma_hold_release)(void *opaque);
+fdctrl_t *fdctrl_init (qemu_irq irq,
+                       fdcdma_memory_read_write dma_memory_read,
+                       fdcdma_memory_read_write dma_memory_write,
+                       fdcdma_hold_release dma_hold,
+                       fdcdma_hold_release dma_release,
+                       void *dma_opaque, int mem_mapped,
                        target_phys_addr_t io_base,
                        BlockDriverState **fds);
+fdctrl_t *fdctrl_i8257_init (qemu_irq irq, int i8257_dma_chann,
+                             int mem_mapped,
+                             target_phys_addr_t io_base,
+                             BlockDriverState **fds);
 fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base,
                              BlockDriverState **fds, qemu_irq *fdc_tc);
 int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num);
Index: hw/mips_jazz.c
===================================================================
--- hw/mips_jazz.c	(revision 5771)
+++ hw/mips_jazz.c	(working copy)
@@ -221,7 +221,7 @@
         else
             fds[n] = NULL;
     }
-    fdctrl_init(rc4030[1], 0, 1, 0x80003000, fds);
+    fdctrl_init(rc4030[1], NULL, NULL, NULL, NULL, NULL, 1, 0x80003000, fds);
 
     /* Real time clock */
     rtc_init(0x70, i8259[8]);
Index: hw/mips_malta.c
===================================================================
--- hw/mips_malta.c	(revision 5771)
+++ hw/mips_malta.c	(working copy)
@@ -929,7 +929,7 @@
        else
            fd[i] = NULL;
     }
-    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
+    floppy_controller = fdctrl_i8257_init(i8259[6], 2, 0, 0x3f0, fd);
 
     /* Sound card */
 #ifdef HAS_AUDIO
Index: hw/pc.c
===================================================================
--- hw/pc.c	(revision 5771)
+++ hw/pc.c	(working copy)
@@ -1052,7 +1052,7 @@
 	else
 	    fd[i] = NULL;
     }
-    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
+    floppy_controller = fdctrl_i8257_init(i8259[6], 2, 0, 0x3f0, fd);
 
     cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);
 
Index: hw/ppc_prep.c
===================================================================
--- hw/ppc_prep.c	(revision 5771)
+++ hw/ppc_prep.c	(working copy)
@@ -709,7 +709,7 @@
         else
             fd[i] = NULL;
     }
-    fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
+    fdctrl_i8257_init(i8259[6], 2, 0, 0x3f0, fd);
 
     /* Register speaker port */
     register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
Index: hw/sun4m.c
===================================================================
--- hw/sun4m.c	(revision 5771)
+++ hw/sun4m.c	(working copy)
@@ -1589,7 +1589,7 @@
 
     if (hwdef->fd_base != (target_phys_addr_t)-1) {
         /* there is zero or one floppy drive */
-        fd[1] = fd[0] = NULL;
+        memset(fd, 0, sizeof(fd));
         drive_index = drive_get_index(IF_FLOPPY, 0, 0);
         if (drive_index != -1)
             fd[0] = drives_table[drive_index].bdrv;
Index: hw/sun4u.c
===================================================================
--- hw/sun4u.c	(revision 5771)
+++ hw/sun4u.c	(working copy)
@@ -508,7 +508,7 @@
        else
            fd[i] = NULL;
     }
-    floppy_controller = fdctrl_init(NULL/*6*/, 2, 0, 0x3f0, fd);
+    floppy_controller = fdctrl_i8257_init(NULL/*6*/, 2, 0, 0x3f0, fd);
     nvram = m48t59_init(NULL/*8*/, 0, 0x0074, NVRAM_SIZE, 59);
     sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", RAM_size, boot_devices,
                            KERNEL_LOAD_ADDR, kernel_size,
