@@ -18,9 +18,15 @@
typedef struct ScatterGatherEntry ScatterGatherEntry;
#if defined(TARGET_PHYS_ADDR_BITS)
+typedef target_phys_addr_t dma_addr_t;
+typedef enum {
+ DMA_DIRECTION_TO_DEVICE = 0,
+ DMA_DIRECTION_FROM_DEVICE = 1,
+} DMADirection;
+
struct ScatterGatherEntry {
- target_phys_addr_t base;
- target_phys_addr_t len;
+ dma_addr_t base;
+ dma_addr_t len;
};
struct QEMUSGList {
@@ -31,8 +37,7 @@ struct QEMUSGList {
};
void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint);
-void qemu_sglist_add(QEMUSGList *qsg, target_phys_addr_t base,
- target_phys_addr_t len);
+void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len);
void qemu_sglist_destroy(QEMUSGList *qsg);
#endif
@@ -2129,3 +2129,56 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev)
{
return dev->bus->address_space_io;
}
+
+#define PCI_DMA_DEFINE_LDST(_lname, _sname, _end, _bits) \
+ uint##_bits##_t ld##_lname##_##_end##_pci_dma(PCIDevice *dev, \
+ dma_addr_t addr) \
+ { \
+ uint##_bits##_t val; \
+ pci_dma_read(dev, addr, &val, sizeof(val)); \
+ return _end##_bits##_to_cpu(val); \
+ } \
+ void st##_sname##_##_end##_pci_dma(PCIDevice *dev, \
+ dma_addr_t addr, uint##_bits##_t val) \
+ { \
+ val = cpu_to_##_end##_bits(val); \
+ pci_dma_write(dev, addr, &val, sizeof(val)); \
+ }
+
+uint8_t ldub_pci_dma(PCIDevice *dev, dma_addr_t addr)
+{
+ uint8_t val;
+
+ pci_dma_read(dev, addr, &val, sizeof(val));
+ return val;
+}
+
+void stb_pci_dma(PCIDevice *dev, dma_addr_t addr, uint8_t val)
+{
+ pci_dma_write(dev, addr, &val, sizeof(val));
+}
+
+PCI_DMA_DEFINE_LDST(uw, w, le, 16);
+PCI_DMA_DEFINE_LDST(uw, w, be, 16);
+PCI_DMA_DEFINE_LDST(l, l, le, 32);
+PCI_DMA_DEFINE_LDST(l, l, be, 32);
+PCI_DMA_DEFINE_LDST(q, q, le, 64);
+PCI_DMA_DEFINE_LDST(q, q, be, 64);
+
+void *pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t *plen,
+ DMADirection dir)
+{
+ target_phys_addr_t len = *plen;
+ void *buf;
+
+ buf = cpu_physical_memory_map(addr, &len, dir == DMA_DIRECTION_FROM_DEVICE);
+ *plen = len;
+ return buf;
+}
+
+void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len,
+ DMADirection dir, dma_addr_t access_len)
+{
+ cpu_physical_memory_unmap(buffer, len, dir == DMA_DIRECTION_FROM_DEVICE,
+ access_len);
+}
@@ -6,6 +6,7 @@
#include "qdev.h"
#include "memory.h"
+#include "dma.h"
/* PCI includes legacy ISA access. */
#include "isa.h"
@@ -487,4 +488,52 @@ static inline uint32_t pci_config_size(const PCIDevice *d)
return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
}
+/* DMA access functions */
+static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr,
+ void *buf, dma_addr_t len, DMADirection dir)
+{
+ cpu_physical_memory_rw(addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
+ return 0;
+}
+
+static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr,
+ void *buf, dma_addr_t len)
+{
+ return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE);
+}
+
+static inline int pci_dma_write(PCIDevice *dev, dma_addr_t addr,
+ const void *buf, dma_addr_t len)
+{
+ return pci_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE);
+}
+
+#define PCI_DMA_DECLARE_LDST(_lname, _sname, _bits) \
+ uint##_bits##_t ld##_lname##_le_pci_dma(PCIDevice *dev, dma_addr_t addr); \
+ void st##_sname##_le_pci_dma(PCIDevice *dev, dma_addr_t addr, \
+ uint##_bits##_t val); \
+ uint##_bits##_t ld##_lname##_be_pci_dma(PCIDevice *dev, dma_addr_t addr); \
+ void st##_sname##_be_pci_dma(PCIDevice *dev, dma_addr_t addr, \
+ uint##_bits##_t val);
+
+uint8_t ldub_pci_dma(PCIDevice *dev, dma_addr_t addr);
+void stb_pci_dma(PCIDevice *dev, dma_addr_t addr, uint8_t val);
+
+PCI_DMA_DECLARE_LDST(uw, w, 16);
+PCI_DMA_DECLARE_LDST(l, l, 32);
+PCI_DMA_DECLARE_LDST(q, q, 64);
+
+#undef DECLARE_LDST_DMA
+
+void *pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t *plen,
+ DMADirection dir);
+void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len,
+ DMADirection dir, dma_addr_t access_len);
+
+static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev,
+ int alloc_hint)
+{
+ qemu_sglist_init(qsg, alloc_hint);
+}
+
#endif