qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 1/2 v5-test] add function DMA_set_return and DMA_set


From: Li Zhi Hui
Subject: [Qemu-devel] [PATCH 1/2 v5-test] add function DMA_set_return and DMA_set_channel_async in dma.c
Date: Thu, 19 Apr 2012 22:07:39 +0800

To avoid re-enter function fdctrl_transfer_handler, according paolo's 
suggestion, the patch is used to test.

Signed-off-by: Li Zhi Hui <address@hidden>
---
 hw/dma.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++--
 hw/isa.h |    2 ++
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/hw/dma.c b/hw/dma.c
index 0a9322d..0a59164 100644
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -45,6 +45,8 @@ struct dma_regs {
     uint8_t eop;
     DMA_transfer_handler transfer_handler;
     void *opaque;
+    bool channel_running;
+    bool channel_is_asynchronous;
 };
 
 #define ADDR 0
@@ -138,6 +140,8 @@ static inline void init_chan (struct dma_cont *d, int ichan)
     r = d->regs + ichan;
     r->now[ADDR] = r->base[ADDR] << d->dshift;
     r->now[COUNT] = 0;
+    r->channel_running = false;
+    r->channel_is_asynchronous = false;
 }
 
 static inline int getff (struct dma_cont *d)
@@ -375,9 +379,20 @@ static void DMA_run (void)
 
             mask = 1 << ichan;
 
-            if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4)))) {
-                channel_run (icont, ichan);
+            while ((0 == (d->mask & mask)) &&
+                   (0 != (d->status & (mask << 4)))) {
+                struct dma_regs *r = &dma_controllers[icont].regs[ichan];
+                if (r->channel_running) {
+                    assert(r->channel_is_asynchronous);
+                    break;
+                }
+                r->channel_running = true;
+                channel_run(icont, ichan);
                 rearm = 1;
+                if (r->channel_is_asynchronous) {
+                    break;
+                }
+                r->channel_running = false;
             }
         }
     }
@@ -388,6 +403,35 @@ out:
         qemu_bh_schedule_idle(dma_bh);
 }
 
+void DMA_set_channel_async(int nchan, bool val)
+{
+    int icont, ichan;
+    struct dma_regs *r;
+
+    icont = nchan > 3;
+    ichan = nchan & 3;
+    r = &dma_controllers[icont].regs[ichan];
+    r->channel_is_asynchronous = val;
+}
+
+void DMA_set_return(int nret, int nchan)
+{
+    struct dma_regs *r;
+    struct dma_cont *d;
+    int icont, ichan;
+
+    icont = nchan > 3;
+    ichan = nchan & 3;
+    d = dma_controllers;
+    r = &d[icont].regs[ichan];
+    r->now[COUNT] = nret;
+    assert(r->channel_is_asynchronous);
+    assert(r->channel_running);
+    r->channel_running = false;
+    r->channel_is_asynchronous = false;
+}
+
+
 static void DMA_run_bh(void *unused)
 {
     DMA_run();
diff --git a/hw/isa.h b/hw/isa.h
index 40373fb..07293d0 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -92,4 +92,6 @@ void DMA_init(int high_page_enable, qemu_irq 
*cpu_request_exit);
 void DMA_register_channel (int nchan,
                            DMA_transfer_handler transfer_handler,
                            void *opaque);
+void DMA_set_channel_async(int nchan, bool val);
+void DMA_set_return(int nret, int nchan);
 #endif
-- 
1.7.4.1




reply via email to

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