From f79ac5918bb0c5529d19ef46f5feee13190ae4a1 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Wed, 22 Feb 2012 14:12:43 +0100
Subject: [PATCH 087/109] dma-helpers: add dma_buf_read and dma_buf_write

RH-Author: Paolo Bonzini <pbonzini@redhat.com>
Message-id: <1329919979-20948-87-git-send-email-pbonzini@redhat.com>
Patchwork-id: 37567
O-Subject: [RHEL 6.3 qemu-kvm PATCH v2 086/102] dma-helpers: add dma_buf_read and dma_buf_write
Bugzilla: 782029
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>

These helpers do a full transfer from an in-memory buffer to target
memory, with support for scatter/gather lists.  It will be used to
store the reply of an emulated command into a QEMUSGList provided by
the adapter.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 dma-helpers.c |   31 +++++++++++++++++++++++++++++++
 dma.h         |    3 +++
 2 files changed, 34 insertions(+), 0 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 dma-helpers.c |   31 +++++++++++++++++++++++++++++++
 dma.h         |    3 +++
 2 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/dma-helpers.c b/dma-helpers.c
index 722e2a9..b1216d2 100644
--- a/dma-helpers.c
+++ b/dma-helpers.c
@@ -204,3 +204,34 @@ BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
 {
     return dma_bdrv_io(bs, sg, sector, cb, opaque, true);
 }
+
+
+static uint64_t dma_buf_rw(uint8_t *ptr, int32_t len, QEMUSGList *sg, bool to_dev)
+{
+    uint64_t resid;
+    int sg_cur_index;
+
+    resid = sg->size;
+    sg_cur_index = 0;
+    len = MIN(len, resid);
+    while (len > 0) {
+        ScatterGatherEntry entry = sg->sg[sg_cur_index++];
+        int32_t xfer = MIN(len, entry.len);
+        cpu_physical_memory_rw(entry.base, ptr, xfer, !to_dev);
+        ptr += xfer;
+        len -= xfer;
+        resid -= xfer;
+    }
+
+    return resid;
+}
+
+uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg)
+{
+    return dma_buf_rw(ptr, len, sg, 0);
+}
+
+uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg)
+{
+    return dma_buf_rw(ptr, len, sg, 1);
+}
diff --git a/dma.h b/dma.h
index 45e536e..375f59e 100644
--- a/dma.h
+++ b/dma.h
@@ -42,4 +42,7 @@ BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
 BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
                                  QEMUSGList *sg, uint64_t sector,
                                  BlockDriverCompletionFunc *cb, void *opaque);
+uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg);
+uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg);
+
 #endif
-- 
1.7.7.6

