qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Li Zhi Hui <zhihuili@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	Li Zhi Hui <zhihuili@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCH 1/3 v6] add function DMA_set_return and DMA_set_channel_async in dma.c
Date: Tue, 15 May 2012 17:17:23 +0800	[thread overview]
Message-ID: <1337073445-9679-2-git-send-email-zhihuili@linux.vnet.ibm.com> (raw)
In-Reply-To: <1337073445-9679-1-git-send-email-zhihuili@linux.vnet.ibm.com>

Prepare for introducing asynchronous I/O in floppy disks by adding
support for asynchronous DMA operations.

We won't need idle bottom halves (or bottom halves in general) anymore.
QEMU works just fine without them with synchronous I/O (though the floppy
drive will stall the guest and be "impolite"), so remove all that code
for that now for simplicity.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Li Zhi Hui <zhihuili@linux.vnet.ibm.com>
---
 hw/dma.c   |   80 +++++++++++++++++++++++++++++++++++++----------------------
 hw/fdc.c   |    1 +
 hw/isa.h   |    2 +
 hw/sun4m.c |    3 ++
 hw/sun4u.c |    3 ++
 5 files changed, 59 insertions(+), 30 deletions(-)

diff --git a/hw/dma.c b/hw/dma.c
index 0a9322d..dd5c57d 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)
@@ -327,7 +331,7 @@ void DMA_release_DREQ (int nchan)
     DMA_run();
 }
 
-static void channel_run (int ncont, int ichan)
+static void channel_do_transfer(int ncont, int ichan)
 {
     int n;
     struct dma_regs *r = &dma_controllers[ncont].regs[ichan];
@@ -351,46 +355,64 @@ static void channel_run (int ncont, int ichan)
     ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
 }
 
-static QEMUBH *dma_bh;
+static void channel_run(int ncont, int nchan)
+{
+    struct dma_cont *d = &dma_controllers[ncont];
+    struct dma_regs *r = &d->regs[nchan];
+
+    int mask = 1 << nchan;
+    while ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4)))) {
+        assert(!r->channel_running);
+        r->channel_running = true;
+        channel_do_transfer(ncont, nchan);
+        if (r->channel_is_asynchronous) {
+            break;
+        }
+        r->channel_running = false;
+    }
+}
 
 static void DMA_run (void)
 {
-    struct dma_cont *d;
     int icont, ichan;
-    int rearm = 0;
-    static int running = 0;
-
-    if (running) {
-        rearm = 1;
-        goto out;
-    } else {
-        running = 1;
-    }
-
-    d = dma_controllers;
 
-    for (icont = 0; icont < 2; icont++, d++) {
+    for (icont = 0; icont < 2; icont++) {
         for (ichan = 0; ichan < 4; ichan++) {
-            int mask;
-
-            mask = 1 << ichan;
-
-            if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4)))) {
-                channel_run (icont, ichan);
-                rearm = 1;
+            struct dma_regs *r = &dma_controllers[icont].regs[ichan];
+            if (!r->channel_running) {
+                channel_run(icont, ichan);
             }
         }
     }
+}
 
-    running = 0;
-out:
-    if (rearm)
-        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;
 }
 
-static void DMA_run_bh(void *unused)
+void DMA_set_return(int nret, int nchan)
 {
-    DMA_run();
+    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;
+    channel_run(icont, ichan);
 }
 
 void DMA_register_channel (int nchan,
@@ -560,6 +582,4 @@ void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
               high_page_enable ? 0x488 : -1, cpu_request_exit);
     vmstate_register (NULL, 0, &vmstate_dma, &dma_controllers[0]);
     vmstate_register (NULL, 1, &vmstate_dma, &dma_controllers[1]);
-
-    dma_bh = qemu_bh_new(DMA_run_bh, NULL);
 }
diff --git a/hw/fdc.c b/hw/fdc.c
index cb4cd25..5684a05 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -1189,6 +1189,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
     fdctrl = opaque;
     if (fdctrl->msr & FD_MSR_RQM) {
         FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
+        DMA_release_DREQ(fdctrl->dma_chann);
         return 0;
     }
     cur_drv = get_cur_drv(fdctrl);
diff --git a/hw/isa.h b/hw/isa.h
index f7bc4b5..4f19c74 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -97,4 +97,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
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 34088ad..f3b8027 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -147,6 +147,9 @@ int DMA_write_memory (int nchan, void *buf, int pos, int size)
 {
     return 0;
 }
+
+void DMA_set_channel_async(int nchan, bool val) {}
+void DMA_set_return(int nret, int nchan) {}
 void DMA_hold_DREQ (int nchan) {}
 void DMA_release_DREQ (int nchan) {}
 void DMA_schedule(int nchan) {}
diff --git a/hw/sun4u.c b/hw/sun4u.c
index fe33138..abf3426 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -110,6 +110,9 @@ int DMA_write_memory (int nchan, void *buf, int pos, int size)
 {
     return 0;
 }
+
+void DMA_set_channel_async(int nchan, bool val) {}
+void DMA_set_return(int nret, int nchan) {}
 void DMA_hold_DREQ (int nchan) {}
 void DMA_release_DREQ (int nchan) {}
 void DMA_schedule(int nchan) {}
-- 
1.7.4.1

  reply	other threads:[~2012-05-15  9:18 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-15  9:17 [Qemu-devel] [PATCH 0/3 v6] Replace bdrv_* to bdrv_aio_* functions in DMA mode in fdc.c Li Zhi Hui
2012-05-15  9:17 ` Li Zhi Hui [this message]
2012-05-15  9:17 ` [Qemu-devel] [PATCH 2/3 " Li Zhi Hui
2012-05-15  9:27   ` Paolo Bonzini
2012-05-15  9:33     ` Kevin Wolf
2012-05-15  9:38       ` Paolo Bonzini
2012-05-16  8:23         ` Zhi Hui Li
2012-05-16  9:11           ` Paolo Bonzini
2012-05-16 10:59           ` Kevin Wolf
2012-05-15 20:49     ` Hervé Poussineau
2012-05-16  7:58     ` Zhi Hui Li
2012-05-15  9:17 ` [Qemu-devel] [PATCH 3/3 v6] fdc.c: add tracing Li Zhi Hui

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1337073445-9679-2-git-send-email-zhihuili@linux.vnet.ibm.com \
    --to=zhihuili@linux.vnet.ibm.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).