Commit c01c07bbf971296be84b72341ede37b1f700022e
1 parent
70ea255d
ETRAX: Process out channels immediately when the channel is started.
* Process out channels immediately when the channel is started. * Context descriptor load does not start a channel. * Store updated descriptors after processing them regardless of eol state. * Correct control-register area size. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6208 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
31 additions
and
20 deletions
hw/etraxfs_dma.c
| ... | ... | @@ -31,21 +31,21 @@ |
| 31 | 31 | |
| 32 | 32 | #define D(x) |
| 33 | 33 | |
| 34 | -#define RW_DATA 0x0 | |
| 35 | -#define RW_SAVED_DATA 0x58 | |
| 36 | -#define RW_SAVED_DATA_BUF 0x5c | |
| 37 | -#define RW_GROUP 0x60 | |
| 38 | -#define RW_GROUP_DOWN 0x7c | |
| 39 | -#define RW_CMD 0x80 | |
| 40 | -#define RW_CFG 0x84 | |
| 41 | -#define RW_STAT 0x88 | |
| 42 | -#define RW_INTR_MASK 0x8c | |
| 43 | -#define RW_ACK_INTR 0x90 | |
| 44 | -#define R_INTR 0x94 | |
| 45 | -#define R_MASKED_INTR 0x98 | |
| 46 | -#define RW_STREAM_CMD 0x9c | |
| 47 | - | |
| 48 | -#define DMA_REG_MAX 0x100 | |
| 34 | +#define RW_DATA (0x0 / 4) | |
| 35 | +#define RW_SAVED_DATA (0x58 / 4) | |
| 36 | +#define RW_SAVED_DATA_BUF (0x5c / 4) | |
| 37 | +#define RW_GROUP (0x60 / 4) | |
| 38 | +#define RW_GROUP_DOWN (0x7c / 4) | |
| 39 | +#define RW_CMD (0x80 / 4) | |
| 40 | +#define RW_CFG (0x84 / 4) | |
| 41 | +#define RW_STAT (0x88 / 4) | |
| 42 | +#define RW_INTR_MASK (0x8c / 4) | |
| 43 | +#define RW_ACK_INTR (0x90 / 4) | |
| 44 | +#define R_INTR (0x94 / 4) | |
| 45 | +#define R_MASKED_INTR (0x98 / 4) | |
| 46 | +#define RW_STREAM_CMD (0x9c / 4) | |
| 47 | + | |
| 48 | +#define DMA_REG_MAX (0x100 / 4) | |
| 49 | 49 | |
| 50 | 50 | /* descriptors */ |
| 51 | 51 | |
| ... | ... | @@ -194,6 +194,9 @@ struct fs_dma_ctrl |
| 194 | 194 | QEMUBH *bh; |
| 195 | 195 | }; |
| 196 | 196 | |
| 197 | +static void DMA_run(void *opaque); | |
| 198 | +static int channel_out_run(struct fs_dma_ctrl *ctrl, int c); | |
| 199 | + | |
| 197 | 200 | static inline uint32_t channel_reg(struct fs_dma_ctrl *ctrl, int c, int reg) |
| 198 | 201 | { |
| 199 | 202 | return ctrl->channels[c].regs[reg]; |
| ... | ... | @@ -314,6 +317,8 @@ static inline void channel_start(struct fs_dma_ctrl *ctrl, int c) |
| 314 | 317 | { |
| 315 | 318 | ctrl->channels[c].eol = 0; |
| 316 | 319 | ctrl->channels[c].state = RUNNING; |
| 320 | + if (!ctrl->channels[c].input) | |
| 321 | + channel_out_run(ctrl, c); | |
| 317 | 322 | } else |
| 318 | 323 | printf("WARNING: starting DMA ch %d with no client\n", c); |
| 319 | 324 | |
| ... | ... | @@ -347,6 +352,9 @@ static void channel_continue(struct fs_dma_ctrl *ctrl, int c) |
| 347 | 352 | ctrl->channels[c].regs[RW_SAVED_DATA] = |
| 348 | 353 | (uint32_t)(unsigned long)ctrl->channels[c].current_d.next; |
| 349 | 354 | channel_load_d(ctrl, c); |
| 355 | + ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = | |
| 356 | + (uint32_t)(unsigned long)ctrl->channels[c].current_d.buf; | |
| 357 | + | |
| 350 | 358 | channel_start(ctrl, c); |
| 351 | 359 | } |
| 352 | 360 | ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = |
| ... | ... | @@ -367,7 +375,6 @@ static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v) |
| 367 | 375 | |
| 368 | 376 | if (cmd & regk_dma_load_c) { |
| 369 | 377 | channel_load_c(ctrl, c); |
| 370 | - channel_start(ctrl, c); | |
| 371 | 378 | } |
| 372 | 379 | } |
| 373 | 380 | |
| ... | ... | @@ -401,14 +408,14 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c) |
| 401 | 408 | return 0; |
| 402 | 409 | |
| 403 | 410 | do { |
| 404 | - saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); | |
| 405 | - | |
| 406 | 411 | D(printf("ch=%d buf=%x after=%x saved_data_buf=%x\n", |
| 407 | 412 | c, |
| 408 | 413 | (uint32_t)ctrl->channels[c].current_d.buf, |
| 409 | 414 | (uint32_t)ctrl->channels[c].current_d.after, |
| 410 | 415 | saved_data_buf)); |
| 411 | 416 | |
| 417 | + channel_load_d(ctrl, c); | |
| 418 | + saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); | |
| 412 | 419 | len = (uint32_t)(unsigned long) |
| 413 | 420 | ctrl->channels[c].current_d.after; |
| 414 | 421 | len -= saved_data_buf; |
| ... | ... | @@ -440,10 +447,12 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c) |
| 440 | 447 | if (ctrl->channels[c].current_d.intr) { |
| 441 | 448 | /* TODO: signal eop to the client. */ |
| 442 | 449 | /* data intr. */ |
| 443 | - D(printf("signal intr\n")); | |
| 450 | + D(printf("signal intr %d eol=%d\n", | |
| 451 | + len, ctrl->channels[c].current_d.eol)); | |
| 444 | 452 | ctrl->channels[c].regs[R_INTR] |= (1 << 2); |
| 445 | 453 | channel_update_irq(ctrl, c); |
| 446 | 454 | } |
| 455 | + channel_store_d(ctrl, c); | |
| 447 | 456 | if (ctrl->channels[c].current_d.eol) { |
| 448 | 457 | D(printf("channel %d EOL\n", c)); |
| 449 | 458 | ctrl->channels[c].eol = 1; |
| ... | ... | @@ -463,7 +472,6 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c) |
| 463 | 472 | ctrl->channels[c].current_d.buf; |
| 464 | 473 | } |
| 465 | 474 | |
| 466 | - channel_store_d(ctrl, c); | |
| 467 | 475 | ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = |
| 468 | 476 | saved_data_buf; |
| 469 | 477 | D(dump_d(c, &ctrl->channels[c].current_d)); |
| ... | ... | @@ -482,6 +490,7 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, |
| 482 | 490 | if (ctrl->channels[c].eol == 1) |
| 483 | 491 | return 0; |
| 484 | 492 | |
| 493 | + channel_load_d(ctrl, c); | |
| 485 | 494 | saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); |
| 486 | 495 | len = (uint32_t)(unsigned long)ctrl->channels[c].current_d.after; |
| 487 | 496 | len -= saved_data_buf; |
| ... | ... | @@ -572,6 +581,7 @@ dma_readl (void *opaque, target_phys_addr_t addr) |
| 572 | 581 | /* Make addr relative to this channel and bounded to nr regs. */ |
| 573 | 582 | c = fs_channel(addr); |
| 574 | 583 | addr &= 0xff; |
| 584 | + addr >>= 2; | |
| 575 | 585 | switch (addr) |
| 576 | 586 | { |
| 577 | 587 | case RW_STAT: |
| ... | ... | @@ -618,6 +628,7 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
| 618 | 628 | /* Make addr relative to this channel and bounded to nr regs. */ |
| 619 | 629 | c = fs_channel(addr); |
| 620 | 630 | addr &= 0xff; |
| 631 | + addr >>= 2; | |
| 621 | 632 | switch (addr) |
| 622 | 633 | { |
| 623 | 634 | case RW_DATA: | ... | ... |