Commit 4487fd349baa6d2ae34ab86dea843642d20a036a
1 parent
b23761f9
ETRAX-FS: Add support for DMA channel resets, needed for recent linux kernels.
* Correct numeric value for the RST state. * Add emulation for reseting a DMA channel. * Add a few sanity checks. * Make it compile with debug enabled. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5147 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
21 additions
and
2 deletions
hw/etraxfs_dma.c
@@ -156,7 +156,7 @@ enum { | @@ -156,7 +156,7 @@ enum { | ||
156 | 156 | ||
157 | enum dma_ch_state | 157 | enum dma_ch_state |
158 | { | 158 | { |
159 | - RST = 0, | 159 | + RST = 1, |
160 | STOPPED = 2, | 160 | STOPPED = 2, |
161 | RUNNING = 4 | 161 | RUNNING = 4 |
162 | }; | 162 | }; |
@@ -398,7 +398,7 @@ static void channel_out_run(struct fs_dma_ctrl *ctrl, int c) | @@ -398,7 +398,7 @@ static void channel_out_run(struct fs_dma_ctrl *ctrl, int c) | ||
398 | 398 | ||
399 | saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); | 399 | saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); |
400 | 400 | ||
401 | - D(fprintf(logfile, "ch=%d buf=%x after=%x saved_data_buf=%x\n", | 401 | + D(printf("ch=%d buf=%x after=%x saved_data_buf=%x\n", |
402 | c, | 402 | c, |
403 | (uint32_t)ctrl->channels[c].current_d.buf, | 403 | (uint32_t)ctrl->channels[c].current_d.buf, |
404 | (uint32_t)ctrl->channels[c].current_d.after, | 404 | (uint32_t)ctrl->channels[c].current_d.after, |
@@ -583,6 +583,17 @@ dma_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) | @@ -583,6 +583,17 @@ dma_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
583 | } | 583 | } |
584 | 584 | ||
585 | static void | 585 | static void |
586 | +dma_update_state(struct fs_dma_ctrl *ctrl, int c) | ||
587 | +{ | ||
588 | + if ((ctrl->channels[c].regs[RW_CFG] & 1) != 3) { | ||
589 | + if (ctrl->channels[c].regs[RW_CFG] & 2) | ||
590 | + ctrl->channels[c].state = STOPPED; | ||
591 | + if (!(ctrl->channels[c].regs[RW_CFG] & 1)) | ||
592 | + ctrl->channels[c].state = RST; | ||
593 | + } | ||
594 | +} | ||
595 | + | ||
596 | +static void | ||
586 | dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | 597 | dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
587 | { | 598 | { |
588 | struct fs_dma_ctrl *ctrl = opaque; | 599 | struct fs_dma_ctrl *ctrl = opaque; |
@@ -599,9 +610,13 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | @@ -599,9 +610,13 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
599 | 610 | ||
600 | case RW_CFG: | 611 | case RW_CFG: |
601 | ctrl->channels[c].regs[addr] = value; | 612 | ctrl->channels[c].regs[addr] = value; |
613 | + dma_update_state(ctrl, c); | ||
602 | break; | 614 | break; |
603 | case RW_CMD: | 615 | case RW_CMD: |
604 | /* continue. */ | 616 | /* continue. */ |
617 | + if (value & ~1) | ||
618 | + printf("Invalid store to ch=%d RW_CMD %x\n", | ||
619 | + c, value); | ||
605 | ctrl->channels[c].regs[addr] = value; | 620 | ctrl->channels[c].regs[addr] = value; |
606 | channel_continue(ctrl, c); | 621 | channel_continue(ctrl, c); |
607 | break; | 622 | break; |
@@ -622,6 +637,10 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | @@ -622,6 +637,10 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
622 | break; | 637 | break; |
623 | 638 | ||
624 | case RW_STREAM_CMD: | 639 | case RW_STREAM_CMD: |
640 | + if (value & ~1023) | ||
641 | + printf("Invalid store to ch=%d " | ||
642 | + "RW_STREAMCMD %x\n", | ||
643 | + c, value); | ||
625 | ctrl->channels[c].regs[addr] = value; | 644 | ctrl->channels[c].regs[addr] = value; |
626 | D(printf("stream_cmd ch=%d\n", c)); | 645 | D(printf("stream_cmd ch=%d\n", c)); |
627 | channel_stream_cmd(ctrl, c, value); | 646 | channel_stream_cmd(ctrl, c, value); |