diff options
author | edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-10-27 20:44:27 +0000 |
---|---|---|
committer | edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-10-27 20:44:27 +0000 |
commit | c968ef8df5052100683a4bb375078e46d96203a7 (patch) | |
tree | a0a943728e9c06ea705509652c189c84a866010c | |
parent | 31c18d87614063316b66faa6d7c05a876846488a (diff) |
ETRAX-FS: Process outgoing DMA channels until EOL.
For outgoing DMA channels, keep processing descriptors until hitting end
of list.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5553 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | hw/etraxfs_dma.c | 136 |
1 files changed, 69 insertions, 67 deletions
diff --git a/hw/etraxfs_dma.c b/hw/etraxfs_dma.c index f95f4f70c3..a871b0630e 100644 --- a/hw/etraxfs_dma.c +++ b/hw/etraxfs_dma.c @@ -393,72 +393,74 @@ static void channel_out_run(struct fs_dma_ctrl *ctrl, int c) uint32_t saved_data_buf; unsigned char buf[2 * 1024]; - if (ctrl->channels[c].eol == 1) - return; - - saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); - - D(printf("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)(unsigned long) 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)(unsigned long)ctrl->channels[c].current_d.after) { - /* Done. Step to next. */ - if (ctrl->channels[c].current_d.out_eop) { - /* TODO: signal eop to the client. */ - D(printf("signal eop\n")); + while (ctrl->channels[c].eol != 1) { + saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); + + D(printf("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) { + /* TODO: signal eop to the client. */ + D(printf("signal eop\n")); + } + if (ctrl->channels[c].current_d.intr) { + /* TODO: signal eop to the client. */ + /* data intr. */ + D(printf("signal intr\n")); + ctrl->channels[c].regs[R_INTR] |= (1 << 2); + channel_update_irq(ctrl, c); + } + 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)(unsigned long) + 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)); } - if (ctrl->channels[c].current_d.intr) { - /* TODO: signal eop to the client. */ - /* data intr. */ - D(printf("signal intr\n")); - ctrl->channels[c].regs[R_INTR] |= (1 << 2); - channel_update_irq(ctrl, c); - } - 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)(unsigned long) ctrl->channels[c].current_d.next; - /* Load new descriptor. */ - channel_load_d(ctrl, c); - saved_data_buf = (uint32_t)(unsigned long) - 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)); } - ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf; } static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, @@ -471,7 +473,7 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, return 0; saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); - len = (uint32_t)(unsigned long) ctrl->channels[c].current_d.after; + len = (uint32_t)ctrl->channels[c].current_d.after; len -= saved_data_buf; if (len > buflen) @@ -481,7 +483,7 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, saved_data_buf += len; if (saved_data_buf == - (uint32_t)(unsigned long)ctrl->channels[c].current_d.after + (uint32_t)ctrl->channels[c].current_d.after || eop) { uint32_t r_intr = ctrl->channels[c].regs[R_INTR]; @@ -518,10 +520,10 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, channel_stop(ctrl, c); } else { ctrl->channels[c].regs[RW_SAVED_DATA] = - (uint32_t)(unsigned long) ctrl->channels[c].current_d.next; + (uint32_t)ctrl->channels[c].current_d.next; /* Load new descriptor. */ channel_load_d(ctrl, c); - saved_data_buf = (uint32_t)(unsigned long) + saved_data_buf = (uint32_t) ctrl->channels[c].current_d.buf; } } |