diff mbox series

[1/2] hw/mips/jazz: create ESP device directly via qdev

Message ID 20180613094727.11326-2-mark.cave-ayland@ilande.co.uk
State New
Headers show
Series scsi: remove legacy esp_init() function | expand

Commit Message

Mark Cave-Ayland June 13, 2018, 9:47 a.m. UTC
MIPS jazz is the last user of the legacy esp_init() function so move creation
of the ESP device over to use qdev.

Note that the esp_reset and dma_enable qemu_irqs are currently unused and so
we do not wire these up and instead remove the variables to prevent the
compiler emitting unused variable warnings.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
---
 hw/mips/mips_jazz.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

Comments

Paolo Bonzini June 13, 2018, 10:06 a.m. UTC | #1
On 13/06/2018 11:47, Mark Cave-Ayland wrote:
> +    dev = qdev_create(NULL, TYPE_ESP);
> +    sysbus_esp = ESP_STATE(dev);
> +    esp = &sysbus_esp->esp;
> +    esp->dma_memory_read = rc4030_dma_read;
> +    esp->dma_memory_write = rc4030_dma_write;
> +    esp->dma_opaque = dmas[0];

Poking at the functions here is a bit ugly, and it's the last user of
rc4030_dma_{read,write}.  It would be nicer if ESP could get a memory
region like it's done a bit above for the NIC.  I guess it's not a big
deal, but perhaps there could be a TODO comment.

I'm mostly mentioning this because Hervé is copied and because SPARC DMA
has the same issue of using function pointers instead of an IOMMU memory
region...

Thanks,

Paolo

> +    sysbus_esp->it_shift = 0;
> +    /* XXX for now until rc4030 has been changed to use DMA enable signal */
> +    esp->dma_enabled = 1;
> +    qdev_init_nofail(dev);
> +
> +    sysbus = SYS_BUS_DEVICE(dev);
> +    sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 5));
> +    sysbus_mmio_map(sysbus, 0, 0x80002000);
> +
Mark Cave-Ayland June 13, 2018, 10:36 a.m. UTC | #2
On 13/06/18 11:06, Paolo Bonzini wrote:

> On 13/06/2018 11:47, Mark Cave-Ayland wrote:
>> +    dev = qdev_create(NULL, TYPE_ESP);
>> +    sysbus_esp = ESP_STATE(dev);
>> +    esp = &sysbus_esp->esp;
>> +    esp->dma_memory_read = rc4030_dma_read;
>> +    esp->dma_memory_write = rc4030_dma_write;
>> +    esp->dma_opaque = dmas[0];
> 
> Poking at the functions here is a bit ugly, and it's the last user of
> rc4030_dma_{read,write}.  It would be nicer if ESP could get a memory
> region like it's done a bit above for the NIC.  I guess it's not a big
> deal, but perhaps there could be a TODO comment.

Okay - I'll wait for Hervé to confirm it passes his tests and then see 
if wants a respin with a TODO added (or can add it himself).

> I'm mostly mentioning this because Hervé is copied and because SPARC DMA
> has the same issue of using function pointers instead of an IOMMU memory
> region...

Ahhh this is a fun one :)

As part of the SPARC32 cleanups for the last release there is now a 
proper sun4m IOMMU implementation, but from memory the big issue was 
that the DMA functions need access to the device state to affect the 
transfer.

Check out hw/dma/sparc32_dma.c for some ugly examples: 
espdma_memory_read()/espdma_memory_write() update the DMA address 
pointer register after each read/write, and 
ledma_memory_read()/ledma_memory_write() need to determine if the pcnet 
card has byte-swapping enabled: if so, then don't perform the required 
lance 16-bit swap and if not, do perform the 16-bit swap.

So yes, it's fairly ugly but I can't think of good solution involving 
just IOMMU memory regions.


ATB,

Mark.
Paolo Bonzini June 13, 2018, 11:19 a.m. UTC | #3
On 13/06/2018 12:36, Mark Cave-Ayland wrote:
> Check out hw/dma/sparc32_dma.c for some ugly examples:
> espdma_memory_read()/espdma_memory_write() update the DMA address
> pointer register after each read/write, and
> ledma_memory_read()/ledma_memory_write() need to determine if the pcnet
> card has byte-swapping enabled: if so, then don't perform the required
> lance 16-bit swap and if not, do perform the 16-bit swap.

Heh, those are disgusting indeed. :)  So I guess it would have to stay,
only MIPS can use the pure MemoryRegion-based approach.

Regarding pcnet, is CSR_BSWP really a no-op on PCI cards?  If not, an
option could be to move that handling to pcnet.c - making the ledma swap
unconditional and removing the do_bswap argument.  The disadvantage is
that SPARC would swap twice, and you'd have to keep the callback because
of s->dmaregs[3], but maybe it's still worthwhile.

Thanks,

Paolo
Mark Cave-Ayland June 13, 2018, 1:06 p.m. UTC | #4
On 13/06/18 12:19, Paolo Bonzini wrote:

> On 13/06/2018 12:36, Mark Cave-Ayland wrote:
>> Check out hw/dma/sparc32_dma.c for some ugly examples:
>> espdma_memory_read()/espdma_memory_write() update the DMA address
>> pointer register after each read/write, and
>> ledma_memory_read()/ledma_memory_write() need to determine if the pcnet
>> card has byte-swapping enabled: if so, then don't perform the required
>> lance 16-bit swap and if not, do perform the 16-bit swap.
> 
> Heh, those are disgusting indeed. :)  So I guess it would have to stay,
> only MIPS can use the pure MemoryRegion-based approach.

The only option I can think of is inserting an AddressSpace between the 
esp/ledma device and the IOMMU AddressSpace which intercepts the DMA 
request (addr, len, direction).

I can then grab a reference to the device from the MemoryRegion opaque, 
perform the magic, and then manually invoke address_space_rw() on iommu_as.

Is there a hook somewhere in the memory API that could allow me to do this?

> Regarding pcnet, is CSR_BSWP really a no-op on PCI cards?  If not, an
> option could be to move that handling to pcnet.c - making the ledma swap
> unconditional and removing the do_bswap argument.  The disadvantage is
> that SPARC would swap twice, and you'd have to keep the callback because
> of s->dmaregs[3], but maybe it's still worthwhile.

Hmmm good question. If we can intercept the request above, that would be 
my preferred option as something tells it me it might be useful for 
other similar situations.


ATB,

Mark.
Paolo Bonzini June 13, 2018, 2:12 p.m. UTC | #5
On 13/06/2018 15:06, Mark Cave-Ayland wrote:
>>
>> Heh, those are disgusting indeed. :)  So I guess it would have to stay,
>> only MIPS can use the pure MemoryRegion-based approach.
> 
> The only option I can think of is inserting an AddressSpace between the
> esp/ledma device and the IOMMU AddressSpace which intercepts the DMA
> request (addr, len, direction).
> 
> I can then grab a reference to the device from the MemoryRegion opaque,
> perform the magic, and then manually invoke address_space_rw() on iommu_as.
> 
> Is there a hook somewhere in the memory API that could allow me to do this?

No, I don't think so.  Only MMIO regions intercept reads/writes, and
they only do it at 1/2/4/8 byte granularity.

>> Regarding pcnet, is CSR_BSWP really a no-op on PCI cards?  If not, an
>> option could be to move that handling to pcnet.c - making the ledma swap
>> unconditional and removing the do_bswap argument.  The disadvantage is
>> that SPARC would swap twice, and you'd have to keep the callback because
>> of s->dmaregs[3], but maybe it's still worthwhile.
> 
> Hmmm good question. If we can intercept the request above, that would be
> my preferred option as something tells it me it might be useful for
> other similar situations.

Yeah, it wouldn't be a great improvement, but there would be the benefit
of more accurate emulation.

Paolo
diff mbox series

Patch

diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 90cb306f53..1afbe3ce6a 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -145,10 +145,10 @@  static void mips_jazz_init(MachineState *machine,
     ISABus *isa_bus;
     ISADevice *pit;
     DriveInfo *fds[MAX_FD];
-    qemu_irq esp_reset, dma_enable;
     MemoryRegion *ram = g_new(MemoryRegion, 1);
     MemoryRegion *bios = g_new(MemoryRegion, 1);
     MemoryRegion *bios2 = g_new(MemoryRegion, 1);
+    SysBusESPState *sysbus_esp;
     ESPState *esp;
 
     /* init CPUs */
@@ -281,8 +281,21 @@  static void mips_jazz_init(MachineState *machine,
     }
 
     /* SCSI adapter */
-    esp = esp_init(0x80002000, 0, rc4030_dma_read, rc4030_dma_write, dmas[0],
-                   qdev_get_gpio_in(rc4030, 5), &esp_reset, &dma_enable);
+    dev = qdev_create(NULL, TYPE_ESP);
+    sysbus_esp = ESP_STATE(dev);
+    esp = &sysbus_esp->esp;
+    esp->dma_memory_read = rc4030_dma_read;
+    esp->dma_memory_write = rc4030_dma_write;
+    esp->dma_opaque = dmas[0];
+    sysbus_esp->it_shift = 0;
+    /* XXX for now until rc4030 has been changed to use DMA enable signal */
+    esp->dma_enabled = 1;
+    qdev_init_nofail(dev);
+
+    sysbus = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 5));
+    sysbus_mmio_map(sysbus, 0, 0x80002000);
+
     scsi_bus_legacy_handle_cmdline(&esp->bus);
 
     /* Floppy */