aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-07-10 14:45:19 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-07-10 14:45:19 +0000
commit3df3f6fd7b5d45bae588ceb17233187ba5ec5c8a (patch)
tree44b0cc1364f342819739937a6447a133447aeb6e /hw
parent2c6ab8329e870c4e4c00caa2169db421f9b42b86 (diff)
downloadqemu-3df3f6fd7b5d45bae588ceb17233187ba5ec5c8a.zip
qemu-3df3f6fd7b5d45bae588ceb17233187ba5ec5c8a.tar.gz
qemu-3df3f6fd7b5d45bae588ceb17233187ba5ec5c8a.tar.bz2
odd memory access fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@993 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw')
-rw-r--r--hw/ne2000.c73
1 files changed, 26 insertions, 47 deletions
diff --git a/hw/ne2000.c b/hw/ne2000.c
index 50a3417..0b094d1 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -440,6 +440,24 @@ static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr)
}
}
+static inline void ne2000_dma_update(NE2000State *s, int len)
+{
+ s->rsar += len;
+ /* wrap */
+ /* XXX: check what to do if rsar > stop */
+ if (s->rsar == s->stop)
+ s->rsar = s->start;
+
+ if (s->rcnt <= len) {
+ s->rcnt = 0;
+ /* signal end of transfert */
+ s->isr |= ENISR_RDC;
+ ne2000_update_irq(s);
+ } else {
+ s->rcnt -= len;
+ }
+}
+
static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
NE2000State *s = opaque;
@@ -448,25 +466,15 @@ static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
printf("NE2000: asic write val=0x%04x\n", val);
#endif
if (s->rcnt == 0)
- return;
+ return;
if (s->dcfg & 0x01) {
/* 16 bit access */
ne2000_mem_writew(s, s->rsar, val);
- s->rsar += 2;
- s->rcnt -= 2;
+ ne2000_dma_update(s, 2);
} else {
/* 8 bit access */
ne2000_mem_writeb(s, s->rsar, val);
- s->rsar++;
- s->rcnt--;
- }
- /* wrap */
- if (s->rsar == s->stop)
- s->rsar = s->start;
- if (s->rcnt == 0) {
- /* signal end of transfert */
- s->isr |= ENISR_RDC;
- ne2000_update_irq(s);
+ ne2000_dma_update(s, 1);
}
}
@@ -478,21 +486,11 @@ static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr)
if (s->dcfg & 0x01) {
/* 16 bit access */
ret = ne2000_mem_readw(s, s->rsar);
- s->rsar += 2;
- s->rcnt -= 2;
+ ne2000_dma_update(s, 2);
} else {
/* 8 bit access */
ret = ne2000_mem_readb(s, s->rsar);
- s->rsar++;
- s->rcnt--;
- }
- /* wrap */
- if (s->rsar == s->stop)
- s->rsar = s->start;
- if (s->rcnt == 0) {
- /* signal end of transfert */
- s->isr |= ENISR_RDC;
- ne2000_update_irq(s);
+ ne2000_dma_update(s, 1);
}
#ifdef DEBUG_NE2000
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)
printf("NE2000: asic writel val=0x%04x\n", val);
#endif
if (s->rcnt == 0)
- return;
+ return;
/* 32 bit access */
ne2000_mem_writel(s, s->rsar, val);
- s->rsar += 4;
- s->rcnt -= 4;
- /* wrap */
- if (s->rsar == s->stop)
- s->rsar = s->start;
- if (s->rcnt == 0) {
- /* signal end of transfert */
- s->isr |= ENISR_RDC;
- ne2000_update_irq(s);
- }
+ ne2000_dma_update(s, 4);
}
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)
/* 32 bit access */
ret = ne2000_mem_readl(s, s->rsar);
- s->rsar += 4;
- s->rcnt -= 4;
-
- /* wrap */
- if (s->rsar == s->stop)
- s->rsar = s->start;
- if (s->rcnt == 0) {
- /* signal end of transfert */
- s->isr |= ENISR_RDC;
- ne2000_update_irq(s);
- }
+ ne2000_dma_update(s, 4);
#ifdef DEBUG_NE2000
printf("NE2000: asic readl val=0x%04x\n", ret);
#endif