Revision ee9dbb29
b/hw/ne2000.c | ||
---|---|---|
103 | 103 |
#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */ |
104 | 104 |
#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */ |
105 | 105 |
|
106 |
#define NE2000_MEM_SIZE 32768 |
|
106 |
#define NE2000_PMEM_SIZE (32*1024) |
|
107 |
#define NE2000_PMEM_START (16*1024) |
|
108 |
#define NE2000_PMEM_END (NE2000_PMEM_SIZE+NE2000_PMEM_START) |
|
109 |
#define NE2000_MEM_SIZE NE2000_PMEM_END |
|
107 | 110 |
|
108 | 111 |
typedef struct NE2000State { |
109 | 112 |
uint8_t cmd; |
... | ... | |
244 | 247 |
/* control register */ |
245 | 248 |
s->cmd = val; |
246 | 249 |
if (val & E8390_START) { |
250 |
s->isr &= ~ENISR_RESET; |
|
247 | 251 |
/* test specific case: zero length transfert */ |
248 | 252 |
if ((val & (E8390_RREAD | E8390_RWRITE)) && |
249 | 253 |
s->rcnt == 0) { |
... | ... | |
251 | 255 |
ne2000_update_irq(s); |
252 | 256 |
} |
253 | 257 |
if (val & E8390_TRANS) { |
254 |
net_send_packet(s->nd, s->mem + (s->tpsr << 8), s->tcnt);
|
|
258 |
qemu_send_packet(s->nd, s->mem + (s->tpsr << 8), s->tcnt);
|
|
255 | 259 |
/* signal end of transfert */ |
256 | 260 |
s->tsr = ENTSR_PTX; |
257 | 261 |
s->isr |= ENISR_TX; |
... | ... | |
300 | 304 |
s->dcfg = val; |
301 | 305 |
break; |
302 | 306 |
case EN0_ISR: |
303 |
s->isr &= ~val;
|
|
307 |
s->isr &= ~(val & 0x7f);
|
|
304 | 308 |
ne2000_update_irq(s); |
305 | 309 |
break; |
306 | 310 |
case EN1_PHYS ... EN1_PHYS + 5: |
... | ... | |
337 | 341 |
case EN0_ISR: |
338 | 342 |
ret = s->isr; |
339 | 343 |
break; |
344 |
case EN0_RSARLO: |
|
345 |
ret = s->rsar & 0x00ff; |
|
346 |
break; |
|
347 |
case EN0_RSARHI: |
|
348 |
ret = s->rsar >> 8; |
|
349 |
break; |
|
340 | 350 |
case EN1_PHYS ... EN1_PHYS + 5: |
341 | 351 |
ret = s->phys[offset - EN1_PHYS]; |
342 | 352 |
break; |
... | ... | |
357 | 367 |
return ret; |
358 | 368 |
} |
359 | 369 |
|
370 |
static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr, |
|
371 |
uint32_t val) |
|
372 |
{ |
|
373 |
if (addr < 32 || |
|
374 |
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
|
375 |
s->mem[addr] = val; |
|
376 |
} |
|
377 |
} |
|
378 |
|
|
379 |
static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr, |
|
380 |
uint32_t val) |
|
381 |
{ |
|
382 |
addr &= ~1; /* XXX: check exact behaviour if not even */ |
|
383 |
if (addr < 32 || |
|
384 |
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
|
385 |
s->mem[addr] = val; |
|
386 |
s->mem[addr + 1] = val >> 8; |
|
387 |
} |
|
388 |
} |
|
389 |
|
|
390 |
static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr) |
|
391 |
{ |
|
392 |
if (addr < 32 || |
|
393 |
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
|
394 |
return s->mem[addr]; |
|
395 |
} else { |
|
396 |
return 0xff; |
|
397 |
} |
|
398 |
} |
|
399 |
|
|
400 |
static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr) |
|
401 |
{ |
|
402 |
addr &= ~1; /* XXX: check exact behaviour if not even */ |
|
403 |
if (addr < 32 || |
|
404 |
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
|
405 |
return s->mem[addr] | (s->mem[addr + 1] << 8); |
|
406 |
} else { |
|
407 |
return 0xffff; |
|
408 |
} |
|
409 |
} |
|
410 |
|
|
360 | 411 |
static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
361 | 412 |
{ |
362 | 413 |
NE2000State *s = opaque; |
363 |
uint8_t *p; |
|
364 | 414 |
|
365 | 415 |
#ifdef DEBUG_NE2000 |
366 | 416 |
printf("NE2000: asic write val=0x%04x\n", val); |
367 | 417 |
#endif |
368 |
p = s->mem + s->rsar; |
|
418 |
if (s->rcnt == 0) |
|
419 |
return; |
|
369 | 420 |
if (s->dcfg & 0x01) { |
370 | 421 |
/* 16 bit access */ |
371 |
p[0] = val; |
|
372 |
p[1] = val >> 8; |
|
422 |
ne2000_mem_writew(s, s->rsar, val); |
|
373 | 423 |
s->rsar += 2; |
374 | 424 |
s->rcnt -= 2; |
375 | 425 |
} else { |
376 | 426 |
/* 8 bit access */ |
377 |
p[0] = val;
|
|
427 |
ne2000_mem_writeb(s, s->rsar, val);
|
|
378 | 428 |
s->rsar++; |
379 | 429 |
s->rcnt--; |
380 | 430 |
} |
... | ... | |
391 | 441 |
static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr) |
392 | 442 |
{ |
393 | 443 |
NE2000State *s = opaque; |
394 |
uint8_t *p; |
|
395 | 444 |
int ret; |
396 | 445 |
|
397 |
p = s->mem + s->rsar; |
|
398 | 446 |
if (s->dcfg & 0x01) { |
399 | 447 |
/* 16 bit access */ |
400 |
ret = p[0] | (p[1] << 8);
|
|
448 |
ret = ne2000_mem_readw(s, s->rsar);
|
|
401 | 449 |
s->rsar += 2; |
402 | 450 |
s->rcnt -= 2; |
403 | 451 |
} else { |
404 | 452 |
/* 8 bit access */ |
405 |
ret = p[0];
|
|
453 |
ret = ne2000_mem_readb(s, s->rsar);
|
|
406 | 454 |
s->rsar++; |
407 | 455 |
s->rcnt--; |
408 | 456 |
} |
... | ... | |
455 | 503 |
|
456 | 504 |
ne2000_reset(s); |
457 | 505 |
|
458 |
qemu_add_fd_read_handler(nd->fd, ne2000_can_receive, ne2000_receive, s);
|
|
506 |
qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s);
|
|
459 | 507 |
} |
Also available in: Unified diff