Commit 3df3f6fd7b5d45bae588ceb17233187ba5ec5c8a

Authored by bellard
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