summaryrefslogtreecommitdiffstats
path: root/hw/ide
diff options
context:
space:
mode:
authorPeter Maydell2014-06-16 19:26:21 +0200
committerPeter Maydell2014-06-16 19:26:21 +0200
commitaf44da87e926ff64260b95f4350d338c4fc113ca (patch)
tree303a18d80e73641bb6e23218ac7b7df0666bcc6b /hw/ide
parentrules.mak: remove $(sort) from extract-libs (diff)
parentspapr_pci: Advertise MSI quota (diff)
downloadqemu-af44da87e926ff64260b95f4350d338c4fc113ca.tar.gz
qemu-af44da87e926ff64260b95f4350d338c4fc113ca.tar.xz
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')
-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);
}