diff options
Diffstat (limited to 'hw/ide/macio.c')
-rw-r--r-- | hw/ide/macio.c | 50 |
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); } |