qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 04/10] ide: enable preallocated sg lists


From: Alexander Graf
Subject: [Qemu-devel] [PATCH 04/10] ide: enable preallocated sg lists
Date: Wed, 17 Nov 2010 02:05:30 +0100

The AHCI core does all the SG handling for us, so we need to allow it
to keep its own layouts.

This patch adds hooks into the IDE code to allow for preallocated SG lists.

Signed-off-by: Roland Elek <address@hidden>
Signed-off-by: Alexander Graf <address@hidden>
---
 hw/ide/core.c     |   38 +++++++++++++++++++++++++++++++-------
 hw/ide/internal.h |    1 +
 2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/hw/ide/core.c b/hw/ide/core.c
index 276b853..4c15ea2 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -444,8 +444,16 @@ static int dma_buf_prepare(BMDMAState *bm, int is_write)
         uint32_t addr;
         uint32_t size;
     } prd;
-    int l, len;
+    int l, len, i;
 
+    if (s->sg_third_party) {
+        /* We already have an sglist. */
+        s->io_buffer_size = 0;
+        for (i=0; i < s->sg.nsg; i++) {
+            s->io_buffer_size += s->sg.sg[i].len;
+        }
+        return s->io_buffer_size != 0;
+    }
     qemu_sglist_init(&s->sg, s->nsector / (IDE_PAGE_SIZE / 512) + 1);
     s->io_buffer_size = 0;
     for(;;) {
@@ -535,12 +543,25 @@ static int dma_buf_rw(BMDMAState *bm, int is_write)
         if (bm->cur_prd_len == 0) {
             /* end of table (with a fail safe of one page) */
             if (bm->cur_prd_last ||
-                (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE)
-                return 0;
-            cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8);
-            bm->cur_addr += 8;
-            prd.addr = le32_to_cpu(prd.addr);
-            prd.size = le32_to_cpu(prd.size);
+                (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE) {
+                    s->sg.sg -= s->sg.nsg; //XXX
+                    return 0;
+                }
+            if (s->sg_third_party) {
+                /* We've already parsed the guest RAM PRDT.
+                 * This is essential for AHCI, where the PRDT is in a different
+                 * format than in IDE BMDMA.
+                 */
+                memcpy((uint8_t *)&prd, s->sg.sg, sizeof(prd));
+                s->sg.sg++;
+            } else {
+                cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8);
+                bm->cur_addr += 8;
+                prd.addr = le32_to_cpu(prd.addr);
+                prd.size = le32_to_cpu(prd.size);
+            }
+
+
             len = prd.size & 0xfffe;
             if (len == 0)
                 len = 0x10000;
@@ -2715,6 +2736,9 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs,
     } else {
         pstrcpy(s->version, sizeof(s->version), QEMU_VERSION);
     }
+
+    s->sg_third_party = 0;
+
     ide_reset(s);
     bdrv_set_removable(bs, s->drive_kind == IDE_CD);
     return 0;
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 19e5efb..005283c 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -422,6 +422,7 @@ struct IDEState {
     /* ATA DMA state */
     int io_buffer_size;
     QEMUSGList sg;
+    int sg_third_party;
     /* PIO transfer handling */
     int req_nb_sectors; /* number of sectors per interrupt */
     EndTransferFunc *end_transfer_func;
-- 
1.6.0.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]