The aim here is to eliminate any device-specific registers from the main BMDMA bar memory region so it can potentially be moved into the shared PCI IDE device.
For each BMDMA bus create a new cmd646-bmdma-specific memory region representing the device-specific BMDMA registers and then map them using aliases onto the existing BMDMAState memory region. Signed-off-by: Mark Cave-Ayland <mark.cave-ayl...@ilande.co.uk> --- hw/ide/cmd646.c | 111 +++++++++++++++++++++++++++++++--------- include/hw/ide/cmd646.h | 4 ++ 2 files changed, 90 insertions(+), 25 deletions(-) diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 9103da581f..dd495f2e1b 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -90,7 +90,6 @@ static uint64_t bmdma_read(void *opaque, hwaddr addr, unsigned size) { BMDMAState *bm = opaque; - PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev); uint32_t val; if (size != 1) { @@ -101,19 +100,9 @@ static uint64_t bmdma_read(void *opaque, hwaddr addr, case 0: val = bm->cmd; break; - case 1: - val = pci_dev->config[MRDMODE]; - break; case 2: val = bm->status; break; - case 3: - if (bm == &bm->pci_dev->bmdma[0]) { - val = pci_dev->config[UDIDETCR0]; - } else { - val = pci_dev->config[UDIDETCR1]; - } - break; default: val = 0xff; break; @@ -127,7 +116,6 @@ static void bmdma_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { BMDMAState *bm = opaque; - PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev); if (size != 1) { return; @@ -138,23 +126,10 @@ static void bmdma_write(void *opaque, hwaddr addr, case 0: bmdma_cmd_writeb(bm, val); break; - case 1: - pci_dev->config[MRDMODE] = - (pci_dev->config[MRDMODE] & ~0x30) | (val & 0x30); - cmd646_update_dma_interrupts(pci_dev); - cmd646_update_irq(pci_dev); - break; case 2: bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); break; - case 3: - if (bm == &bm->pci_dev->bmdma[0]) { - pci_dev->config[UDIDETCR0] = val; - } else { - pci_dev->config[UDIDETCR1] = val; - } - break; } } @@ -181,6 +156,91 @@ static void bmdma_setup_bar(PCIIDEState *d) } } +static uint64_t cmd646_bmdma_read(void *opaque, hwaddr addr, unsigned size) +{ + BMDMAState *bm = opaque; + PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev); + uint32_t val; + + if (size != 1) { + return ((uint64_t)1 << (size * 8)) - 1; + } + + switch (addr & 3) { + case 1: + val = pci_dev->config[MRDMODE]; + break; + case 3: + if (bm == &bm->pci_dev->bmdma[0]) { + val = pci_dev->config[UDIDETCR0]; + } else { + val = pci_dev->config[UDIDETCR1]; + } + break; + default: + val = 0xff; + break; + } + + trace_bmdma_read_cmd646(addr, val); + return val; +} + +static void cmd646_bmdma_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + BMDMAState *bm = opaque; + PCIDevice *pci_dev = PCI_DEVICE(bm->pci_dev); + + if (size != 1) { + return; + } + + trace_bmdma_write_cmd646(addr, val); + switch (addr & 3) { + case 1: + pci_dev->config[MRDMODE] = + (pci_dev->config[MRDMODE] & ~0x30) | (val & 0x30); + cmd646_update_dma_interrupts(pci_dev); + cmd646_update_irq(pci_dev); + break; + case 3: + if (bm == &bm->pci_dev->bmdma[0]) { + pci_dev->config[UDIDETCR0] = val; + } else { + pci_dev->config[UDIDETCR1] = val; + } + break; + } +} + +static const MemoryRegionOps cmd646_bmdma_ops = { + .read = cmd646_bmdma_read, + .write = cmd646_bmdma_write, +}; + +static void cmd646_bmdma_setup(PCIIDEState *d) +{ + CMD646IDEState *s = CMD646_IDE(d); + BMDMAState *bm; + int i; + + /* Setup aliases for device-specific BMDMA registers */ + for (i = 0; i < 2; i++) { + bm = &d->bmdma[i]; + memory_region_init_io(&s->bmdma_mem[i], OBJECT(d), &cmd646_bmdma_ops, + bm, "cmd646-bmdma", 4); + memory_region_init_alias(&s->bmdma_mem_alias[i][0], OBJECT(d), + "cmd646-bmdma[1]", &s->bmdma_mem[i], 0x1, 1); + memory_region_add_subregion(&bm->extra_io, 0x1, + &s->bmdma_mem_alias[i][0]); + memory_region_init_alias(&s->bmdma_mem_alias[i][1], OBJECT(d), + "cmd646-bmdma[3]", &s->bmdma_mem[i], 0x3, 1); + memory_region_add_subregion(&bm->extra_io, 0x3, + &s->bmdma_mem_alias[i][1]); + } +} + static void cmd646_update_irq(PCIDevice *pd) { int pci_level; @@ -289,6 +349,7 @@ static void pci_cmd646_ide_realize(PCIDevice *dev, Error **errp) bmdma_setup_bar(d); pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar); + cmd646_bmdma_setup(d); /* TODO: RST# value should be 0 */ pci_conf[PCI_INTERRUPT_PIN] = 0x01; /* interrupt on pin 1 */ diff --git a/include/hw/ide/cmd646.h b/include/hw/ide/cmd646.h index 4780b1132c..5329964533 100644 --- a/include/hw/ide/cmd646.h +++ b/include/hw/ide/cmd646.h @@ -29,10 +29,14 @@ #define TYPE_CMD646_IDE "cmd646-ide" OBJECT_DECLARE_SIMPLE_TYPE(CMD646IDEState, CMD646_IDE) +#include "exec/memory.h" #include "hw/ide/pci.h" struct CMD646IDEState { PCIIDEState parent_obj; + + MemoryRegion bmdma_mem[2]; + MemoryRegion bmdma_mem_alias[2][2]; }; #endif -- 2.30.2