The IDE core doesn't care about BMDMA blocking IRQs from getting submitted, so let's reflect that in the code and make IRQ blocking fully transparent.
Signed-off-by: Alexander Graf <ag...@suse.de> --- hw/ide/core.c | 6 ------ hw/ide/internal.h | 4 ++-- hw/ide/pci.c | 44 +++++++++++++++++++++++++++----------------- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index fce994f..6284539 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2586,18 +2586,12 @@ static void ide_init1(IDEBus *bus, int unit) ide_sector_write_timer_cb, s); } -static int ide_nop_start_irq(void *opaque) -{ - return 1; -} - static int ide_nop(void *opaque) { return 0; } static const IDEDMAOps ide_dma_nop = { - .start_irq = ide_nop_start_irq, .start_dma = (void*)ide_nop, .start_transfer = (void*)ide_nop, .prepare_buf = (void*)ide_nop, diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 15ab119..af7e741 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -457,7 +457,6 @@ struct IDEState { }; struct IDEDMAOps { - DMAFunc *start_irq; DMAStartFunc *start_dma; DMAFunc *start_transfer; DMAIntFunc *prepare_buf; @@ -530,6 +529,7 @@ struct BMDMAState { uint32_t nsector; IORange addr_ioport; QEMUBH *bh; + qemu_irq irq; }; static inline IDEState *idebus_active_if(IDEBus *bus) @@ -545,7 +545,7 @@ static inline IDEState *bmdma_active_if(BMDMAState *bmdma) static inline void ide_set_irq(IDEBus *bus) { - if (bus->dma.ops->start_irq(bus->dma.opaque)) { + if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) { qemu_irq_raise(bus->irq); } } diff --git a/hw/ide/pci.c b/hw/ide/pci.c index 2506cc5..270c13a 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -35,22 +35,6 @@ #define BMDMA_PAGE_SIZE 4096 -static int bmdma_start_irq(void *opaque) -{ - BMDMAState *bm = opaque; - IDEBus *bus = bm->bus; - - if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) { - if (bm) { - bm->status |= BM_STATUS_INT; - } - return 1; - } - - /* IRQ forbidden */ - return 0; -} - static void bmdma_start_dma(void *opaque, IDEState *s, BlockDriverCompletionFunc *dma_cb) { @@ -286,6 +270,24 @@ static int bmdma_start_transfer(void *opaque) return 0; } +static void bmdma_irq(void *opaque, int n, int level) +{ + BMDMAState *bm = opaque; + + if (!level) { + /* pass through lower */ + qemu_set_irq(bm->irq, level); + return; + } + + if (bm) { + bm->status |= BM_STATUS_INT; + } + + /* trigger the real irq */ + qemu_set_irq(bm->irq, level); +} + void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) { BMDMAState *bm = opaque; @@ -453,7 +455,6 @@ void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table) } static const struct IDEDMAOps bmdma_ops = { - .start_irq = bmdma_start_irq, .start_dma = bmdma_start_dma, .start_transfer = bmdma_start_transfer, .prepare_buf = bmdma_prepare_buf, @@ -467,6 +468,15 @@ static const struct IDEDMAOps bmdma_ops = { void bmdma_init(IDEBus *bus, BMDMAState *bm) { + qemu_irq *irq; + + if (bus->dma.ops == &bmdma_ops) { + return; + } + bus->dma.ops = &bmdma_ops; bus->dma.opaque = bm; + bm->irq = bus->irq; + irq = qemu_allocate_irqs(bmdma_irq, bm, 1); + bus->irq = *irq; } -- 1.6.0.2