From patchwork Tue May 15 09:17:23 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhi Hui Li X-Patchwork-Id: 159267 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 7C22EB6FAF for ; Tue, 15 May 2012 19:18:13 +1000 (EST) Received: from localhost ([::1]:39123 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SUDtT-0001HK-8S for incoming@patchwork.ozlabs.org; Tue, 15 May 2012 05:18:11 -0400 Received: from eggs.gnu.org ([208.118.235.92]:53300) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SUDtD-00017R-HD for qemu-devel@nongnu.org; Tue, 15 May 2012 05:18:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SUDt3-0003T9-Jj for qemu-devel@nongnu.org; Tue, 15 May 2012 05:17:55 -0400 Received: from e28smtp09.in.ibm.com ([122.248.162.9]:45751) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SUDt2-0003Rq-Me for qemu-devel@nongnu.org; Tue, 15 May 2012 05:17:45 -0400 Received: from /spool/local by e28smtp09.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 15 May 2012 14:47:37 +0530 Received: from d28relay05.in.ibm.com (9.184.220.62) by e28smtp09.in.ibm.com (192.168.1.139) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 15 May 2012 14:47:35 +0530 Received: from d28av05.in.ibm.com (d28av05.in.ibm.com [9.184.220.67]) by d28relay05.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q4F9HYDV1769764 for ; Tue, 15 May 2012 14:47:34 +0530 Received: from d28av05.in.ibm.com (loopback [127.0.0.1]) by d28av05.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q4FEm4GS005454 for ; Wed, 16 May 2012 00:48:04 +1000 Received: from mm.cn.ibm.com (mm.cn.ibm.com [9.115.116.52]) by d28av05.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q4FEluVB004843; Wed, 16 May 2012 00:48:00 +1000 From: Li Zhi Hui To: qemu-devel@nongnu.org Date: Tue, 15 May 2012 17:17:23 +0800 Message-Id: <1337073445-9679-2-git-send-email-zhihuili@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1337073445-9679-1-git-send-email-zhihuili@linux.vnet.ibm.com> References: <1337073445-9679-1-git-send-email-zhihuili@linux.vnet.ibm.com> x-cbid: 12051509-2674-0000-0000-00000478F6C3 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 122.248.162.9 Cc: Paolo Bonzini , Li Zhi Hui Subject: [Qemu-devel] [PATCH 1/3 v6] add function DMA_set_return and DMA_set_channel_async in dma.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 Signed-off-by: Li Zhi Hui --- 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) {}