mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-28 14:00:44 +00:00
ide: Ignore double DMA transfer starts/stops
You can only start a DMA transfer if it's not running yet, and you can only cancel it if it's running. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
This commit is contained in:
parent
e3982b3cf6
commit
c29947bbb0
60
hw/ide/pci.c
60
hw/ide/pci.c
@ -39,38 +39,42 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
|
|||||||
#ifdef DEBUG_IDE
|
#ifdef DEBUG_IDE
|
||||||
printf("%s: 0x%08x\n", __func__, val);
|
printf("%s: 0x%08x\n", __func__, val);
|
||||||
#endif
|
#endif
|
||||||
if (!(val & BM_CMD_START)) {
|
|
||||||
/*
|
/* Ignore writes to SSBM if it keeps the old value */
|
||||||
* We can't cancel Scatter Gather DMA in the middle of the
|
if ((val & BM_CMD_START) != (bm->cmd & BM_CMD_START)) {
|
||||||
* operation or a partial (not full) DMA transfer would reach
|
if (!(val & BM_CMD_START)) {
|
||||||
* the storage so we wait for completion instead (we beahve
|
/*
|
||||||
* like if the DMA was completed by the time the guest trying
|
* We can't cancel Scatter Gather DMA in the middle of the
|
||||||
* to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
|
* operation or a partial (not full) DMA transfer would reach
|
||||||
* set).
|
* the storage so we wait for completion instead (we beahve
|
||||||
*
|
* like if the DMA was completed by the time the guest trying
|
||||||
* In the future we'll be able to safely cancel the I/O if the
|
* to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
|
||||||
* whole DMA operation will be submitted to disk with a single
|
* set).
|
||||||
* aio operation with preadv/pwritev.
|
*
|
||||||
*/
|
* In the future we'll be able to safely cancel the I/O if the
|
||||||
if (bm->aiocb) {
|
* whole DMA operation will be submitted to disk with a single
|
||||||
qemu_aio_flush();
|
* aio operation with preadv/pwritev.
|
||||||
|
*/
|
||||||
|
if (bm->aiocb) {
|
||||||
|
qemu_aio_flush();
|
||||||
#ifdef DEBUG_IDE
|
#ifdef DEBUG_IDE
|
||||||
if (bm->aiocb)
|
if (bm->aiocb)
|
||||||
printf("ide_dma_cancel: aiocb still pending");
|
printf("ide_dma_cancel: aiocb still pending");
|
||||||
if (bm->status & BM_STATUS_DMAING)
|
if (bm->status & BM_STATUS_DMAING)
|
||||||
printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
|
printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!(bm->status & BM_STATUS_DMAING)) {
|
||||||
|
bm->status |= BM_STATUS_DMAING;
|
||||||
|
/* start dma transfer if possible */
|
||||||
|
if (bm->dma_cb)
|
||||||
|
bm->dma_cb(bm, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bm->cmd = val & 0x09;
|
|
||||||
} else {
|
|
||||||
if (!(bm->status & BM_STATUS_DMAING)) {
|
|
||||||
bm->status |= BM_STATUS_DMAING;
|
|
||||||
/* start dma transfer if possible */
|
|
||||||
if (bm->dma_cb)
|
|
||||||
bm->dma_cb(bm, 0);
|
|
||||||
}
|
|
||||||
bm->cmd = val & 0x09;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bm->cmd = val & 0x09;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bmdma_addr_read(IORange *ioport, uint64_t addr,
|
static void bmdma_addr_read(IORange *ioport, uint64_t addr,
|
||||||
|
Loading…
Reference in New Issue
Block a user