aboutsummaryrefslogtreecommitdiff
path: root/hw/ide/macio.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/ide/macio.c')
-rw-r--r--hw/ide/macio.c50
1 files changed, 40 insertions, 10 deletions
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index af57168db3..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:
@@ -374,6 +403,7 @@ static void pmac_ide_transfer(DBDMA_io *io)
break;
}
+ io->requests++;
pmac_ide_transfer_cb(io, 0);
}