Commit 3df3f6fd7b5d45bae588ceb17233187ba5ec5c8a
1 parent
2c6ab832
odd memory access fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@993 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
26 additions
and
47 deletions
hw/ne2000.c
| ... | ... | @@ -440,6 +440,24 @@ static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr) |
| 440 | 440 | } |
| 441 | 441 | } |
| 442 | 442 | |
| 443 | +static inline void ne2000_dma_update(NE2000State *s, int len) | |
| 444 | +{ | |
| 445 | + s->rsar += len; | |
| 446 | + /* wrap */ | |
| 447 | + /* XXX: check what to do if rsar > stop */ | |
| 448 | + if (s->rsar == s->stop) | |
| 449 | + s->rsar = s->start; | |
| 450 | + | |
| 451 | + if (s->rcnt <= len) { | |
| 452 | + s->rcnt = 0; | |
| 453 | + /* signal end of transfert */ | |
| 454 | + s->isr |= ENISR_RDC; | |
| 455 | + ne2000_update_irq(s); | |
| 456 | + } else { | |
| 457 | + s->rcnt -= len; | |
| 458 | + } | |
| 459 | +} | |
| 460 | + | |
| 443 | 461 | static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
| 444 | 462 | { |
| 445 | 463 | NE2000State *s = opaque; |
| ... | ... | @@ -448,25 +466,15 @@ static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
| 448 | 466 | printf("NE2000: asic write val=0x%04x\n", val); |
| 449 | 467 | #endif |
| 450 | 468 | if (s->rcnt == 0) |
| 451 | - return; | |
| 469 | + return; | |
| 452 | 470 | if (s->dcfg & 0x01) { |
| 453 | 471 | /* 16 bit access */ |
| 454 | 472 | ne2000_mem_writew(s, s->rsar, val); |
| 455 | - s->rsar += 2; | |
| 456 | - s->rcnt -= 2; | |
| 473 | + ne2000_dma_update(s, 2); | |
| 457 | 474 | } else { |
| 458 | 475 | /* 8 bit access */ |
| 459 | 476 | ne2000_mem_writeb(s, s->rsar, val); |
| 460 | - s->rsar++; | |
| 461 | - s->rcnt--; | |
| 462 | - } | |
| 463 | - /* wrap */ | |
| 464 | - if (s->rsar == s->stop) | |
| 465 | - s->rsar = s->start; | |
| 466 | - if (s->rcnt == 0) { | |
| 467 | - /* signal end of transfert */ | |
| 468 | - s->isr |= ENISR_RDC; | |
| 469 | - ne2000_update_irq(s); | |
| 477 | + ne2000_dma_update(s, 1); | |
| 470 | 478 | } |
| 471 | 479 | } |
| 472 | 480 | |
| ... | ... | @@ -478,21 +486,11 @@ static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr) |
| 478 | 486 | if (s->dcfg & 0x01) { |
| 479 | 487 | /* 16 bit access */ |
| 480 | 488 | ret = ne2000_mem_readw(s, s->rsar); |
| 481 | - s->rsar += 2; | |
| 482 | - s->rcnt -= 2; | |
| 489 | + ne2000_dma_update(s, 2); | |
| 483 | 490 | } else { |
| 484 | 491 | /* 8 bit access */ |
| 485 | 492 | ret = ne2000_mem_readb(s, s->rsar); |
| 486 | - s->rsar++; | |
| 487 | - s->rcnt--; | |
| 488 | - } | |
| 489 | - /* wrap */ | |
| 490 | - if (s->rsar == s->stop) | |
| 491 | - s->rsar = s->start; | |
| 492 | - if (s->rcnt == 0) { | |
| 493 | - /* signal end of transfert */ | |
| 494 | - s->isr |= ENISR_RDC; | |
| 495 | - ne2000_update_irq(s); | |
| 493 | + ne2000_dma_update(s, 1); | |
| 496 | 494 | } |
| 497 | 495 | #ifdef DEBUG_NE2000 |
| 498 | 496 | printf("NE2000: asic read val=0x%04x\n", ret); |
| ... | ... | @@ -508,19 +506,10 @@ static void ne2000_asic_ioport_writel(void *opaque, uint32_t addr, uint32_t val) |
| 508 | 506 | printf("NE2000: asic writel val=0x%04x\n", val); |
| 509 | 507 | #endif |
| 510 | 508 | if (s->rcnt == 0) |
| 511 | - return; | |
| 509 | + return; | |
| 512 | 510 | /* 32 bit access */ |
| 513 | 511 | ne2000_mem_writel(s, s->rsar, val); |
| 514 | - s->rsar += 4; | |
| 515 | - s->rcnt -= 4; | |
| 516 | - /* wrap */ | |
| 517 | - if (s->rsar == s->stop) | |
| 518 | - s->rsar = s->start; | |
| 519 | - if (s->rcnt == 0) { | |
| 520 | - /* signal end of transfert */ | |
| 521 | - s->isr |= ENISR_RDC; | |
| 522 | - ne2000_update_irq(s); | |
| 523 | - } | |
| 512 | + ne2000_dma_update(s, 4); | |
| 524 | 513 | } |
| 525 | 514 | |
| 526 | 515 | static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr) |
| ... | ... | @@ -530,17 +519,7 @@ static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr) |
| 530 | 519 | |
| 531 | 520 | /* 32 bit access */ |
| 532 | 521 | ret = ne2000_mem_readl(s, s->rsar); |
| 533 | - s->rsar += 4; | |
| 534 | - s->rcnt -= 4; | |
| 535 | - | |
| 536 | - /* wrap */ | |
| 537 | - if (s->rsar == s->stop) | |
| 538 | - s->rsar = s->start; | |
| 539 | - if (s->rcnt == 0) { | |
| 540 | - /* signal end of transfert */ | |
| 541 | - s->isr |= ENISR_RDC; | |
| 542 | - ne2000_update_irq(s); | |
| 543 | - } | |
| 522 | + ne2000_dma_update(s, 4); | |
| 544 | 523 | #ifdef DEBUG_NE2000 |
| 545 | 524 | printf("NE2000: asic readl val=0x%04x\n", ret); |
| 546 | 525 | #endif | ... | ... |