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,21 +31,21 @@ | ||
| 31 | 31 | ||
| 32 | #define D(x) | 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 | /* descriptors */ | 50 | /* descriptors */ |
| 51 | 51 | ||
| @@ -194,6 +194,9 @@ struct fs_dma_ctrl | @@ -194,6 +194,9 @@ struct fs_dma_ctrl | ||
| 194 | QEMUBH *bh; | 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 | static inline uint32_t channel_reg(struct fs_dma_ctrl *ctrl, int c, int reg) | 200 | static inline uint32_t channel_reg(struct fs_dma_ctrl *ctrl, int c, int reg) |
| 198 | { | 201 | { |
| 199 | return ctrl->channels[c].regs[reg]; | 202 | return ctrl->channels[c].regs[reg]; |
| @@ -314,6 +317,8 @@ static inline void channel_start(struct fs_dma_ctrl *ctrl, int c) | @@ -314,6 +317,8 @@ static inline void channel_start(struct fs_dma_ctrl *ctrl, int c) | ||
| 314 | { | 317 | { |
| 315 | ctrl->channels[c].eol = 0; | 318 | ctrl->channels[c].eol = 0; |
| 316 | ctrl->channels[c].state = RUNNING; | 319 | ctrl->channels[c].state = RUNNING; |
| 320 | + if (!ctrl->channels[c].input) | ||
| 321 | + channel_out_run(ctrl, c); | ||
| 317 | } else | 322 | } else |
| 318 | printf("WARNING: starting DMA ch %d with no client\n", c); | 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,6 +352,9 @@ static void channel_continue(struct fs_dma_ctrl *ctrl, int c) | ||
| 347 | ctrl->channels[c].regs[RW_SAVED_DATA] = | 352 | ctrl->channels[c].regs[RW_SAVED_DATA] = |
| 348 | (uint32_t)(unsigned long)ctrl->channels[c].current_d.next; | 353 | (uint32_t)(unsigned long)ctrl->channels[c].current_d.next; |
| 349 | channel_load_d(ctrl, c); | 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 | channel_start(ctrl, c); | 358 | channel_start(ctrl, c); |
| 351 | } | 359 | } |
| 352 | ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = | 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,7 +375,6 @@ static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v) | ||
| 367 | 375 | ||
| 368 | if (cmd & regk_dma_load_c) { | 376 | if (cmd & regk_dma_load_c) { |
| 369 | channel_load_c(ctrl, c); | 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,14 +408,14 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c) | ||
| 401 | return 0; | 408 | return 0; |
| 402 | 409 | ||
| 403 | do { | 410 | do { |
| 404 | - saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); | ||
| 405 | - | ||
| 406 | D(printf("ch=%d buf=%x after=%x saved_data_buf=%x\n", | 411 | D(printf("ch=%d buf=%x after=%x saved_data_buf=%x\n", |
| 407 | c, | 412 | c, |
| 408 | (uint32_t)ctrl->channels[c].current_d.buf, | 413 | (uint32_t)ctrl->channels[c].current_d.buf, |
| 409 | (uint32_t)ctrl->channels[c].current_d.after, | 414 | (uint32_t)ctrl->channels[c].current_d.after, |
| 410 | saved_data_buf)); | 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 | len = (uint32_t)(unsigned long) | 419 | len = (uint32_t)(unsigned long) |
| 413 | ctrl->channels[c].current_d.after; | 420 | ctrl->channels[c].current_d.after; |
| 414 | len -= saved_data_buf; | 421 | len -= saved_data_buf; |
| @@ -440,10 +447,12 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c) | @@ -440,10 +447,12 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c) | ||
| 440 | if (ctrl->channels[c].current_d.intr) { | 447 | if (ctrl->channels[c].current_d.intr) { |
| 441 | /* TODO: signal eop to the client. */ | 448 | /* TODO: signal eop to the client. */ |
| 442 | /* data intr. */ | 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 | ctrl->channels[c].regs[R_INTR] |= (1 << 2); | 452 | ctrl->channels[c].regs[R_INTR] |= (1 << 2); |
| 445 | channel_update_irq(ctrl, c); | 453 | channel_update_irq(ctrl, c); |
| 446 | } | 454 | } |
| 455 | + channel_store_d(ctrl, c); | ||
| 447 | if (ctrl->channels[c].current_d.eol) { | 456 | if (ctrl->channels[c].current_d.eol) { |
| 448 | D(printf("channel %d EOL\n", c)); | 457 | D(printf("channel %d EOL\n", c)); |
| 449 | ctrl->channels[c].eol = 1; | 458 | ctrl->channels[c].eol = 1; |
| @@ -463,7 +472,6 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c) | @@ -463,7 +472,6 @@ static int channel_out_run(struct fs_dma_ctrl *ctrl, int c) | ||
| 463 | ctrl->channels[c].current_d.buf; | 472 | ctrl->channels[c].current_d.buf; |
| 464 | } | 473 | } |
| 465 | 474 | ||
| 466 | - channel_store_d(ctrl, c); | ||
| 467 | ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = | 475 | ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = |
| 468 | saved_data_buf; | 476 | saved_data_buf; |
| 469 | D(dump_d(c, &ctrl->channels[c].current_d)); | 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,6 +490,7 @@ static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, | ||
| 482 | if (ctrl->channels[c].eol == 1) | 490 | if (ctrl->channels[c].eol == 1) |
| 483 | return 0; | 491 | return 0; |
| 484 | 492 | ||
| 493 | + channel_load_d(ctrl, c); | ||
| 485 | saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); | 494 | saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF); |
| 486 | len = (uint32_t)(unsigned long)ctrl->channels[c].current_d.after; | 495 | len = (uint32_t)(unsigned long)ctrl->channels[c].current_d.after; |
| 487 | len -= saved_data_buf; | 496 | len -= saved_data_buf; |
| @@ -572,6 +581,7 @@ dma_readl (void *opaque, target_phys_addr_t addr) | @@ -572,6 +581,7 @@ dma_readl (void *opaque, target_phys_addr_t addr) | ||
| 572 | /* Make addr relative to this channel and bounded to nr regs. */ | 581 | /* Make addr relative to this channel and bounded to nr regs. */ |
| 573 | c = fs_channel(addr); | 582 | c = fs_channel(addr); |
| 574 | addr &= 0xff; | 583 | addr &= 0xff; |
| 584 | + addr >>= 2; | ||
| 575 | switch (addr) | 585 | switch (addr) |
| 576 | { | 586 | { |
| 577 | case RW_STAT: | 587 | case RW_STAT: |
| @@ -618,6 +628,7 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | @@ -618,6 +628,7 @@ dma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
| 618 | /* Make addr relative to this channel and bounded to nr regs. */ | 628 | /* Make addr relative to this channel and bounded to nr regs. */ |
| 619 | c = fs_channel(addr); | 629 | c = fs_channel(addr); |
| 620 | addr &= 0xff; | 630 | addr &= 0xff; |
| 631 | + addr >>= 2; | ||
| 621 | switch (addr) | 632 | switch (addr) |
| 622 | { | 633 | { |
| 623 | case RW_DATA: | 634 | case RW_DATA: |