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,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 | static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val) | 461 | static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
| 444 | { | 462 | { |
| 445 | NE2000State *s = opaque; | 463 | NE2000State *s = opaque; |
| @@ -448,25 +466,15 @@ static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -448,25 +466,15 @@ static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
| 448 | printf("NE2000: asic write val=0x%04x\n", val); | 466 | printf("NE2000: asic write val=0x%04x\n", val); |
| 449 | #endif | 467 | #endif |
| 450 | if (s->rcnt == 0) | 468 | if (s->rcnt == 0) |
| 451 | - return; | 469 | + return; |
| 452 | if (s->dcfg & 0x01) { | 470 | if (s->dcfg & 0x01) { |
| 453 | /* 16 bit access */ | 471 | /* 16 bit access */ |
| 454 | ne2000_mem_writew(s, s->rsar, val); | 472 | ne2000_mem_writew(s, s->rsar, val); |
| 455 | - s->rsar += 2; | ||
| 456 | - s->rcnt -= 2; | 473 | + ne2000_dma_update(s, 2); |
| 457 | } else { | 474 | } else { |
| 458 | /* 8 bit access */ | 475 | /* 8 bit access */ |
| 459 | ne2000_mem_writeb(s, s->rsar, val); | 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,21 +486,11 @@ static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr) | ||
| 478 | if (s->dcfg & 0x01) { | 486 | if (s->dcfg & 0x01) { |
| 479 | /* 16 bit access */ | 487 | /* 16 bit access */ |
| 480 | ret = ne2000_mem_readw(s, s->rsar); | 488 | ret = ne2000_mem_readw(s, s->rsar); |
| 481 | - s->rsar += 2; | ||
| 482 | - s->rcnt -= 2; | 489 | + ne2000_dma_update(s, 2); |
| 483 | } else { | 490 | } else { |
| 484 | /* 8 bit access */ | 491 | /* 8 bit access */ |
| 485 | ret = ne2000_mem_readb(s, s->rsar); | 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 | #ifdef DEBUG_NE2000 | 495 | #ifdef DEBUG_NE2000 |
| 498 | printf("NE2000: asic read val=0x%04x\n", ret); | 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,19 +506,10 @@ static void ne2000_asic_ioport_writel(void *opaque, uint32_t addr, uint32_t val) | ||
| 508 | printf("NE2000: asic writel val=0x%04x\n", val); | 506 | printf("NE2000: asic writel val=0x%04x\n", val); |
| 509 | #endif | 507 | #endif |
| 510 | if (s->rcnt == 0) | 508 | if (s->rcnt == 0) |
| 511 | - return; | 509 | + return; |
| 512 | /* 32 bit access */ | 510 | /* 32 bit access */ |
| 513 | ne2000_mem_writel(s, s->rsar, val); | 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 | static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr) | 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,17 +519,7 @@ static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr) | ||
| 530 | 519 | ||
| 531 | /* 32 bit access */ | 520 | /* 32 bit access */ |
| 532 | ret = ne2000_mem_readl(s, s->rsar); | 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 | #ifdef DEBUG_NE2000 | 523 | #ifdef DEBUG_NE2000 |
| 545 | printf("NE2000: asic readl val=0x%04x\n", ret); | 524 | printf("NE2000: asic readl val=0x%04x\n", ret); |
| 546 | #endif | 525 | #endif |