[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/3 v6] add function DMA_set_return and DMA_set_chan
From: |
Li Zhi Hui |
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 |
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 <address@hidden>
Signed-off-by: Li Zhi Hui <address@hidden>
---
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
- [Qemu-devel] [PATCH 0/3 v6] Replace bdrv_* to bdr v_aio_* functions in DMA mode in fdc.c, Li Zhi Hui, 2012/05/15
- [Qemu-devel] [PATCH 1/3 v6] add function DMA_set_return and DMA_set_channel_async in dma.c,
Li Zhi Hui <=
- [Qemu-devel] [PATCH 2/3 v6] Replace bdrv_* to bdrv_aio_* functions in DMA mode in fdc.c, Li Zhi Hui, 2012/05/15
- Re: [Qemu-devel] [PATCH 2/3 v6] Replace bdrv_* to bdrv_aio_* functions in DMA mode in fdc.c, Paolo Bonzini, 2012/05/15
- Re: [Qemu-devel] [PATCH 2/3 v6] Replace bdrv_* to bdrv_aio_* functions in DMA mode in fdc.c, Kevin Wolf, 2012/05/15
- Re: [Qemu-devel] [PATCH 2/3 v6] Replace bdrv_* to bdrv_aio_* functions in DMA mode in fdc.c, Paolo Bonzini, 2012/05/15
- Re: [Qemu-devel] [PATCH 2/3 v6] Replace bdrv_* to bdrv_aio_* functions in DMA mode in fdc.c, Zhi Hui Li, 2012/05/16
- Re: [Qemu-devel] [PATCH 2/3 v6] Replace bdrv_* to bdrv_aio_* functions in DMA mode in fdc.c, Paolo Bonzini, 2012/05/16
- Re: [Qemu-devel] [PATCH 2/3 v6] Replace bdrv_* to bdrv_aio_* functions in DMA mode in fdc.c, Kevin Wolf, 2012/05/16
- Re: [Qemu-devel] [PATCH 2/3 v6] Replace bdrv_* to bdrv_aio_* functions in DMA mode in fdc.c, Hervé Poussineau, 2012/05/15
- Re: [Qemu-devel] [PATCH 2/3 v6] Replace bdrv_* to bdrv_aio_* functions in DMA mode in fdc.c, Zhi Hui Li, 2012/05/16
[Qemu-devel] [PATCH 3/3 v6] fdc.c: add tracing, Li Zhi Hui, 2012/05/15