From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1K5rSq-0000Rb-K8 for qemu-devel@nongnu.org; Mon, 09 Jun 2008 20:11:52 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1K5rSp-0000RP-R2 for qemu-devel@nongnu.org; Mon, 09 Jun 2008 20:11:52 -0400 Received: from [199.232.76.173] (port=33629 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1K5rSp-0000RM-OL for qemu-devel@nongnu.org; Mon, 09 Jun 2008 20:11:51 -0400 Received: from savannah.gnu.org ([199.232.41.3]:48250 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1K5rSp-0005ea-ID for qemu-devel@nongnu.org; Mon, 09 Jun 2008 20:11:51 -0400 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1K5rSo-0000ae-NC for qemu-devel@nongnu.org; Tue, 10 Jun 2008 00:11:50 +0000 Received: from edgar_igl by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1K5rSn-0000aY-Vd for qemu-devel@nongnu.org; Tue, 10 Jun 2008 00:11:50 +0000 MIME-Version: 1.0 Errors-To: edgar_igl Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: "Edgar E. Iglesias" Message-Id: Date: Tue, 10 Jun 2008 00:11:50 +0000 Subject: [Qemu-devel] [4723] ETRAX: More DMA context level related fixes. Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 4723 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4723 Author: edgar_igl Date: 2008-06-10 00:11:48 +0000 (Tue, 10 Jun 2008) Log Message: ----------- ETRAX: More DMA context level related fixes. * When hitting EOL (end of list) at the data descriptor level, the DMA should mark the current context-descriptor as disabled and perform a context-store so software can see whats goin on. * Context loads update RW_SAVED_DATA_BUF, data loads dont. This fixes an issue with ethernet bootstrapping. * Reorder the logic for processing out channels to be more like the one for input channels. Modified Paths: -------------- trunk/hw/etraxfs_dma.c Modified: trunk/hw/etraxfs_dma.c =================================================================== --- trunk/hw/etraxfs_dma.c 2008-06-09 23:44:44 UTC (rev 4722) +++ trunk/hw/etraxfs_dma.c 2008-06-10 00:11:48 UTC (rev 4723) @@ -267,23 +267,33 @@ target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA); /* Load and decode. FIXME: handle endianness. */ - D(printf("%s addr=%x\n", __func__, addr)); + D(printf("%s ch=%d addr=%x\n", __func__, c, addr)); cpu_physical_memory_read (addr, (void *) &ctrl->channels[c].current_d, sizeof ctrl->channels[c].current_d); D(dump_d(c, &ctrl->channels[c].current_d)); ctrl->channels[c].regs[RW_DATA] = addr; - ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = - (uint32_t)ctrl->channels[c].current_d.buf; } +static void channel_store_c(struct fs_dma_ctrl *ctrl, int c) +{ + target_phys_addr_t addr = channel_reg(ctrl, c, RW_GROUP_DOWN); + + /* Encode and store. FIXME: handle endianness. */ + D(printf("%s ch=%d addr=%x\n", __func__, c, addr)); + D(dump_d(c, &ctrl->channels[c].current_d)); + cpu_physical_memory_write (addr, + (void *) &ctrl->channels[c].current_c, + sizeof ctrl->channels[c].current_c); +} + static void channel_store_d(struct fs_dma_ctrl *ctrl, int c) { target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA); - /* Load and decode. FIXME: handle endianness. */ - D(printf("%s addr=%x\n", __func__, addr)); + /* Encode and store. FIXME: handle endianness. */ + D(printf("%s ch=%d addr=%x\n", __func__, c, addr)); cpu_physical_memory_write (addr, (void *) &ctrl->channels[c].current_d, sizeof ctrl->channels[c].current_d); @@ -326,20 +336,23 @@ /* If the current descriptor cleared the eol flag and we had already reached eol state, do the continue. */ if (!ctrl->channels[c].current_d.eol && ctrl->channels[c].eol) { - D(printf("continue %d ok %x\n", c, + D(printf("continue %d ok %p\n", c, ctrl->channels[c].current_d.next)); ctrl->channels[c].regs[RW_SAVED_DATA] = (uint32_t) ctrl->channels[c].current_d.next; channel_load_d(ctrl, c); channel_start(ctrl, c); } + ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = + (uint32_t) ctrl->channels[c].current_d.buf; } static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v) { unsigned int cmd = v & ((1 << 10) - 1); - D(printf("%s cmd=%x\n", __func__, cmd)); + D(printf("%s ch=%d cmd=%x pc=%x\n", + __func__, c, cmd, ctrl->env->pc)); if (cmd & regk_dma_load_d) { channel_load_d(ctrl, c); if (cmd & regk_dma_burst) @@ -348,6 +361,7 @@ if (cmd & regk_dma_load_c) { channel_load_c(ctrl, c); + channel_start(ctrl, c); } } @@ -382,11 +396,30 @@ saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); - D(printf("buf=%x after=%x saved_data_buf=%x\n", + D(fprintf(logfile, "ch=%d buf=%x after=%x saved_data_buf=%x\n", + c, (uint32_t)ctrl->channels[c].current_d.buf, (uint32_t)ctrl->channels[c].current_d.after, saved_data_buf)); + len = (uint32_t) ctrl->channels[c].current_d.after; + len -= saved_data_buf; + + if (len > sizeof buf) + len = sizeof buf; + cpu_physical_memory_read (saved_data_buf, buf, len); + + D(printf("channel %d pushes %x %u bytes\n", c, + saved_data_buf, len)); + + if (ctrl->channels[c].client->client.push) + ctrl->channels[c].client->client.push( + ctrl->channels[c].client->client.opaque, buf, len); + else + printf("WARNING: DMA ch%d dataloss, no attached client.\n", c); + + saved_data_buf += len; + if (saved_data_buf == (uint32_t)ctrl->channels[c].current_d.after) { /* Done. Step to next. */ if (ctrl->channels[c].current_d.out_eop) { @@ -403,36 +436,26 @@ if (ctrl->channels[c].current_d.eol) { D(printf("channel %d EOL\n", c)); ctrl->channels[c].eol = 1; + + /* Mark the context as disabled. */ + ctrl->channels[c].current_c.dis = 1; + channel_store_c(ctrl, c); + channel_stop(ctrl, c); } else { ctrl->channels[c].regs[RW_SAVED_DATA] = (uint32_t) ctrl->channels[c].current_d.next; /* Load new descriptor. */ channel_load_d(ctrl, c); + saved_data_buf = (uint32_t) + ctrl->channels[c].current_d.buf; } channel_store_d(ctrl, c); + ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf; D(dump_d(c, &ctrl->channels[c].current_d)); - return; } - - len = (uint32_t) ctrl->channels[c].current_d.after; - len -= saved_data_buf; - - if (len > sizeof buf) - len = sizeof buf; - cpu_physical_memory_read (saved_data_buf, buf, len); - - D(printf("channel %d pushes %x %u bytes\n", c, - saved_data_buf, len)); - /* TODO: Push content. */ - if (ctrl->channels[c].client->client.push) - ctrl->channels[c].client->client.push( - ctrl->channels[c].client->client.opaque, buf, len); - else - printf("WARNING: DMA ch%d dataloss, no attached client.\n", c); - - ctrl->channels[c].regs[RW_SAVED_DATA_BUF] += len; + ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf; } static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, @@ -483,14 +506,19 @@ if (ctrl->channels[c].current_d.eol) { D(printf("channel %d EOL\n", c)); ctrl->channels[c].eol = 1; + + /* Mark the context as disabled. */ + ctrl->channels[c].current_c.dis = 1; + channel_store_c(ctrl, c); + channel_stop(ctrl, c); } else { ctrl->channels[c].regs[RW_SAVED_DATA] = (uint32_t) ctrl->channels[c].current_d.next; /* Load new descriptor. */ channel_load_d(ctrl, c); - saved_data_buf = - ctrl->channels[c].regs[RW_SAVED_DATA_BUF]; + saved_data_buf = (uint32_t) + ctrl->channels[c].current_d.buf; } } @@ -523,21 +551,21 @@ /* Make addr relative to this instances base. */ c = fs_channel(ctrl->base, addr); - addr &= 0x1fff; + addr &= 0x1fff; switch (addr) - { + { case RW_STAT: r = ctrl->channels[c].state & 7; r |= ctrl->channels[c].eol << 5; r |= ctrl->channels[c].stream_cmd_src << 8; break; - default: + default: r = ctrl->channels[c].regs[addr]; D(printf ("%s c=%d addr=%x pc=%x\n", - __func__, c, addr, env->pc)); - break; - } + __func__, c, addr, ctrl->env->pc)); + break; + } return r; } @@ -560,7 +588,7 @@ c = fs_channel(ctrl->base, addr); addr &= 0x1fff; switch (addr) - { + { case RW_DATA: ctrl->channels[c].regs[addr] = value; break; @@ -591,13 +619,15 @@ case RW_STREAM_CMD: ctrl->channels[c].regs[addr] = value; + D(printf("stream_cmd ch=%d pc=%x\n", + c, ctrl->env->pc)); channel_stream_cmd(ctrl, c, value); break; - default: - D(printf ("%s c=%d %x %x pc=%x\n", - __func__, c, addr, value, env->pc)); - break; + default: + D(printf ("%s c=%d %x %x pc=%x\n", + __func__, c, addr, value, ctrl->env->pc)); + break; } }