diff mbox series

[5/5] cmd646: move device-specific BMDMA registers to separate memory region

Message ID 20230609185119.691152-6-mark.cave-ayland@ilande.co.uk
State New
Headers show
Series cmd646: move device-specific BMDMA registers to separate memory region | expand

Commit Message

Mark Cave-Ayland June 9, 2023, 6:51 p.m. UTC
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-ayland@ilande.co.uk>
---
 hw/ide/cmd646.c         | 111 +++++++++++++++++++++++++++++++---------
 include/hw/ide/cmd646.h |   4 ++
 2 files changed, 90 insertions(+), 25 deletions(-)

Comments

Bernhard Beschow June 12, 2023, 7:28 p.m. UTC | #1
Am 9. Juni 2023 18:51:19 UTC schrieb Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>:
>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-ayland@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++) {

I'd use `ARRAY_SIZE()` instead of the hardcoded constant here.

>+        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];

The added complexity of a two-dimensional alias array seems like a tough call for me. I'm not totally against it but I'm reluctant.

Best regards,
Bernhard

> };
> 
> #endif
Philippe Mathieu-Daudé June 12, 2023, 10:39 p.m. UTC | #2
On 12/6/23 21:28, Bernhard Beschow wrote:
> 
> 
> Am 9. Juni 2023 18:51:19 UTC schrieb Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>:
>> 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-ayland@ilande.co.uk>
>> ---
>> hw/ide/cmd646.c         | 111 +++++++++++++++++++++++++++++++---------
>> include/hw/ide/cmd646.h |   4 ++
>> 2 files changed, 90 insertions(+), 25 deletions(-)


>> struct CMD646IDEState {
>>      PCIIDEState parent_obj;
>> +
>> +    MemoryRegion bmdma_mem[2];
>> +    MemoryRegion bmdma_mem_alias[2][2];
> 
> The added complexity of a two-dimensional alias array seems like a tough call for me. I'm not totally against it but I'm reluctant.

Alternative:

         struct {
             MemoryRegion mem;
             MemoryRegion mem_alias[2];
         } bmdma[2];

>> };
>>
>> #endif
>
Bernhard Beschow June 13, 2023, 8:07 a.m. UTC | #3
On Tue, Jun 13, 2023 at 12:39 AM Philippe Mathieu-Daudé <philmd@linaro.org>
wrote:

> On 12/6/23 21:28, Bernhard Beschow wrote:
> >
> >
> > Am 9. Juni 2023 18:51:19 UTC schrieb Mark Cave-Ayland <
> mark.cave-ayland@ilande.co.uk>:
> >> 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-ayland@ilande.co.uk>
> >> ---
> >> hw/ide/cmd646.c         | 111 +++++++++++++++++++++++++++++++---------
> >> include/hw/ide/cmd646.h |   4 ++
> >> 2 files changed, 90 insertions(+), 25 deletions(-)
>
>
> >> struct CMD646IDEState {
> >>      PCIIDEState parent_obj;
> >> +
> >> +    MemoryRegion bmdma_mem[2];
> >> +    MemoryRegion bmdma_mem_alias[2][2];
> >
> > The added complexity of a two-dimensional alias array seems like a tough
> call for me. I'm not totally against it but I'm reluctant.
>
> Alternative:
>
>          struct {
>              MemoryRegion mem;
>              MemoryRegion mem_alias[2];
>

If `mem_alias` became an anonymous struct as well we could avoid fiddling
with two indices in a matrix, lowering the complexity.

Best regards,
Bernhard

>          } bmdma[2];
>
> >> };
> >>
> >> #endif
> >
>
>
diff mbox series

Patch

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