summary refs log tree commit diff stats
path: root/hw/ide/macio.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-06-16 18:26:21 +0100
committerPeter Maydell <peter.maydell@linaro.org>2014-06-16 18:26:21 +0100
commitaf44da87e926ff64260b95f4350d338c4fc113ca (patch)
tree303a18d80e73641bb6e23218ac7b7df0666bcc6b /hw/ide/macio.c
parentf27701510cdce9f76cdad0aaf9fb0bbcb23d299a (diff)
parent9dbae97723e964692364fb43012c6fa5448a661f (diff)
downloadfocaccia-qemu-af44da87e926ff64260b95f4350d338c4fc113ca.tar.gz
focaccia-qemu-af44da87e926ff64260b95f4350d338c4fc113ca.zip
Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging
Patch queue for ppc - 2014-06-16

This pull request brings a lot of fun things. Among others we have

  - e500: u-boot firmware support
  - sPAPR: magic page enablement
  - sPAPR: add "compat" CPU option to support older guests
  - sPAPR: refactorings in preparation for VFIO
  - POWER8 live migration
  - mac99: expose bus frequency
  - little endian core dump, gdb and disas support
  - new ppc64le-linux-user target
  - DFP emulation
  - bug fixes

# gpg: Signature made Mon 16 Jun 2014 12:28:32 BST using RSA key ID 03FEDC60
# gpg: Can't check signature: public key not found

* remotes/agraf/tags/signed-ppc-for-upstream: (156 commits)
  spapr_pci: Advertise MSI quota
  PPC: KVM: Make pv hcall endian agnostic
  powerpc: use float64 for frsqrte
  spapr: Add kvm-type property
  spapr: Create SPAPRMachine struct
  linux-user: Tell guest about big host page sizes
  spapr_hcall: Add address-translation-mode-on-interrupt resource in H_SET_MODE
  spapr_hcall: Split h_set_mode()
  target-ppc: Enable DABRX SPR and limit it to <=POWER7
  target-ppc: Enable PPR and VRSAVE SPRs migration
  target-ppc: Add POWER8's Event Based Branch (EBB) control SPRs
  KVM: target-ppc: Enable TM state migration
  target-ppc: Add POWER8's TM SPRs
  target-ppc: Add POWER8's MMCR2/MMCRS SPRs
  target-ppc: Enable FSCR facility check for TAR
  target-ppc: Add POWER8's FSCR SPR
  target-ppc: Add POWER8's TIR SPR
  target-ppc: Refactor class init for POWER7/8
  target-ppc: Switch POWER7/8 classes to use correct PMU SPRs
  target-ppc: Make use of gen_spr_power5p_lpar() for POWER7/8
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/ide/macio.c')
-rw-r--r--hw/ide/macio.c71
1 files changed, 61 insertions, 10 deletions
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 1c20616f5a..c14a1ddddb 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -193,6 +193,11 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
         goto done;
     }
 
+    if (--io->requests) {
+        /* More requests still in flight */
+        return;
+    }
+
     if (!m->dma_active) {
         MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n",
                       s->nsector, io->len, s->status);
@@ -212,6 +217,13 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
         s->nsector -= n;
     }
 
+    if (io->finish_remain_read) {
+        /* Finish a stale read from the last iteration */
+        io->finish_remain_read = false;
+        cpu_physical_memory_write(io->finish_addr, io->remainder,
+                                  io->finish_len);
+    }
+
     MACIO_DPRINTF("remainder: %d io->len: %d nsector: %d "
                   "sector_num: %" PRId64 "\n",
                   io->remainder_len, io->len, s->nsector, sector_num);
@@ -229,7 +241,6 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
             break;
         case IDE_DMA_WRITE:
             cpu_physical_memory_read(io->addr, p, remainder_len);
-            bdrv_write(s->bs, sector_num - 1, io->remainder, 1);
             break;
         case IDE_DMA_TRIM:
             break;
@@ -237,6 +248,15 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
         io->addr += remainder_len;
         io->len -= remainder_len;
         io->remainder_len -= remainder_len;
+
+        if (s->dma_cmd == IDE_DMA_WRITE && !io->remainder_len) {
+            io->requests++;
+            qemu_iovec_reset(&io->iov);
+            qemu_iovec_add(&io->iov, io->remainder, 0x200);
+
+            m->aiocb = bdrv_aio_writev(s->bs, sector_num - 1, &io->iov, 1,
+                                       pmac_ide_transfer_cb, io);
+        }
     }
 
     if (s->nsector == 0 && !io->remainder_len) {
@@ -267,20 +287,25 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
 
         switch (s->dma_cmd) {
         case IDE_DMA_READ:
-            bdrv_read(s->bs, sector_num + nsector, io->remainder, 1);
-            cpu_physical_memory_write(io->addr + io->len - unaligned,
-                                      io->remainder, unaligned);
+            io->requests++;
+            io->finish_addr = io->addr + io->len - unaligned;
+            io->finish_len = unaligned;
+            io->finish_remain_read = true;
+            qemu_iovec_reset(&io->iov);
+            qemu_iovec_add(&io->iov, io->remainder, 0x200);
+
+            m->aiocb = bdrv_aio_readv(s->bs, sector_num + nsector, &io->iov, 1,
+                                      pmac_ide_transfer_cb, io);
             break;
         case IDE_DMA_WRITE:
             /* cache the contents in our io struct */
             cpu_physical_memory_read(io->addr + io->len - unaligned,
-                                     io->remainder, unaligned);
+                                     io->remainder + io->remainder_len,
+                                     unaligned);
             break;
         case IDE_DMA_TRIM:
             break;
         }
-
-        io->len -= unaligned;
     }
 
     MACIO_DPRINTF("io->len = %#x\n", io->len);
@@ -292,10 +317,12 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
     io->remainder_len = (0x200 - unaligned) & 0x1ff;
     MACIO_DPRINTF("set remainder to: %d\n", io->remainder_len);
 
-    /* We would read no data from the block layer, thus not get a callback.
-       Just fake completion manually. */
+    /* Only subsector reads happening */
     if (!io->len) {
-        pmac_ide_transfer_cb(opaque, 0);
+        if (!io->requests) {
+            io->requests++;
+            pmac_ide_transfer_cb(opaque, ret);
+        }
         return;
     }
 
@@ -319,6 +346,8 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
                                DMA_DIRECTION_TO_DEVICE);
         break;
     }
+
+    io->requests++;
     return;
 
 done:
@@ -337,6 +366,27 @@ static void pmac_ide_transfer(DBDMA_io *io)
 
     s->io_buffer_size = 0;
     if (s->drive_kind == IDE_CD) {
+
+        /* Handle non-block ATAPI DMA transfers */
+        if (s->lba == -1) {
+            s->io_buffer_size = MIN(io->len, s->packet_transfer_size);
+            bdrv_acct_start(s->bs, &s->acct, s->io_buffer_size,
+                            BDRV_ACCT_READ);
+            MACIO_DPRINTF("non-block ATAPI DMA transfer size: %d\n",
+                          s->io_buffer_size);
+
+            /* Copy ATAPI buffer directly to RAM and finish */
+            cpu_physical_memory_write(io->addr, s->io_buffer,
+                                      s->io_buffer_size);
+            ide_atapi_cmd_ok(s);
+            m->dma_active = false;
+
+            MACIO_DPRINTF("end of non-block ATAPI DMA transfer\n");
+            bdrv_acct_done(s->bs, &s->acct);
+            io->dma_end(io);
+            return;
+        }
+
         bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ);
         pmac_ide_atapi_transfer_cb(io, 0);
         return;
@@ -353,6 +403,7 @@ static void pmac_ide_transfer(DBDMA_io *io)
         break;
     }
 
+    io->requests++;
     pmac_ide_transfer_cb(io, 0);
 }