Revision 5fafdf24 hw/ne2000.c
b/hw/ne2000.c | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* QEMU NE2000 emulation |
3 |
*
|
|
3 |
* |
|
4 | 4 |
* Copyright (c) 2003-2004 Fabrice Bellard |
5 |
*
|
|
5 |
* |
|
6 | 6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | 7 |
* of this software and associated documentation files (the "Software"), to deal |
8 | 8 |
* in the Software without restriction, including without limitation the rights |
... | ... | |
212 | 212 |
static int ne2000_can_receive(void *opaque) |
213 | 213 |
{ |
214 | 214 |
NE2000State *s = opaque; |
215 |
|
|
215 |
|
|
216 | 216 |
if (s->cmd & E8390_STOP) |
217 | 217 |
return 1; |
218 | 218 |
return !ne2000_buffer_full(s); |
... | ... | |
226 | 226 |
uint8_t *p; |
227 | 227 |
unsigned int total_len, next, avail, len, index, mcast_idx; |
228 | 228 |
uint8_t buf1[60]; |
229 |
static const uint8_t broadcast_macaddr[6] =
|
|
229 |
static const uint8_t broadcast_macaddr[6] = |
|
230 | 230 |
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
231 |
|
|
231 |
|
|
232 | 232 |
#if defined(DEBUG_NE2000) |
233 | 233 |
printf("NE2000: received len=%d\n", size); |
234 | 234 |
#endif |
235 | 235 |
|
236 | 236 |
if (s->cmd & E8390_STOP || ne2000_buffer_full(s)) |
237 | 237 |
return; |
238 |
|
|
238 |
|
|
239 | 239 |
/* XXX: check this */ |
240 | 240 |
if (s->rxcr & 0x10) { |
241 | 241 |
/* promiscuous: receive all */ |
... | ... | |
252 | 252 |
if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) |
253 | 253 |
return; |
254 | 254 |
} else if (s->mem[0] == buf[0] && |
255 |
s->mem[2] == buf[1] &&
|
|
256 |
s->mem[4] == buf[2] &&
|
|
257 |
s->mem[6] == buf[3] &&
|
|
258 |
s->mem[8] == buf[4] &&
|
|
255 |
s->mem[2] == buf[1] && |
|
256 |
s->mem[4] == buf[2] && |
|
257 |
s->mem[6] == buf[3] && |
|
258 |
s->mem[8] == buf[4] && |
|
259 | 259 |
s->mem[10] == buf[5]) { |
260 | 260 |
/* match */ |
261 | 261 |
} else { |
... | ... | |
336 | 336 |
} |
337 | 337 |
if (val & E8390_TRANS) { |
338 | 338 |
index = (s->tpsr << 8); |
339 |
/* XXX: next 2 lines are a hack to make netware 3.11 work */
|
|
339 |
/* XXX: next 2 lines are a hack to make netware 3.11 work */ |
|
340 | 340 |
if (index >= NE2000_PMEM_END) |
341 | 341 |
index -= NE2000_PMEM_SIZE; |
342 | 342 |
/* fail safe: check range on the transmitted length */ |
... | ... | |
346 | 346 |
/* signal end of transfer */ |
347 | 347 |
s->tsr = ENTSR_PTX; |
348 | 348 |
s->isr |= ENISR_TX; |
349 |
s->cmd &= ~E8390_TRANS;
|
|
349 |
s->cmd &= ~E8390_TRANS; |
|
350 | 350 |
ne2000_update_irq(s); |
351 | 351 |
} |
352 | 352 |
} |
... | ... | |
482 | 482 |
return ret; |
483 | 483 |
} |
484 | 484 |
|
485 |
static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr,
|
|
485 |
static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr, |
|
486 | 486 |
uint32_t val) |
487 | 487 |
{ |
488 |
if (addr < 32 ||
|
|
488 |
if (addr < 32 || |
|
489 | 489 |
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
490 | 490 |
s->mem[addr] = val; |
491 | 491 |
} |
492 | 492 |
} |
493 | 493 |
|
494 |
static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr,
|
|
494 |
static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr, |
|
495 | 495 |
uint32_t val) |
496 | 496 |
{ |
497 | 497 |
addr &= ~1; /* XXX: check exact behaviour if not even */ |
498 |
if (addr < 32 ||
|
|
498 |
if (addr < 32 || |
|
499 | 499 |
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
500 | 500 |
*(uint16_t *)(s->mem + addr) = cpu_to_le16(val); |
501 | 501 |
} |
502 | 502 |
} |
503 | 503 |
|
504 |
static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr,
|
|
504 |
static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr, |
|
505 | 505 |
uint32_t val) |
506 | 506 |
{ |
507 | 507 |
addr &= ~1; /* XXX: check exact behaviour if not even */ |
508 |
if (addr < 32 ||
|
|
508 |
if (addr < 32 || |
|
509 | 509 |
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
510 | 510 |
cpu_to_le32wu((uint32_t *)(s->mem + addr), val); |
511 | 511 |
} |
... | ... | |
513 | 513 |
|
514 | 514 |
static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr) |
515 | 515 |
{ |
516 |
if (addr < 32 ||
|
|
516 |
if (addr < 32 || |
|
517 | 517 |
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
518 | 518 |
return s->mem[addr]; |
519 | 519 |
} else { |
... | ... | |
524 | 524 |
static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr) |
525 | 525 |
{ |
526 | 526 |
addr &= ~1; /* XXX: check exact behaviour if not even */ |
527 |
if (addr < 32 ||
|
|
527 |
if (addr < 32 || |
|
528 | 528 |
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
529 | 529 |
return le16_to_cpu(*(uint16_t *)(s->mem + addr)); |
530 | 530 |
} else { |
... | ... | |
535 | 535 |
static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr) |
536 | 536 |
{ |
537 | 537 |
addr &= ~1; /* XXX: check exact behaviour if not even */ |
538 |
if (addr < 32 ||
|
|
538 |
if (addr < 32 || |
|
539 | 539 |
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
540 | 540 |
return le32_to_cpupu((uint32_t *)(s->mem + addr)); |
541 | 541 |
} else { |
... | ... | |
718 | 718 |
void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd) |
719 | 719 |
{ |
720 | 720 |
NE2000State *s; |
721 |
|
|
721 |
|
|
722 | 722 |
s = qemu_mallocz(sizeof(NE2000State)); |
723 | 723 |
if (!s) |
724 | 724 |
return; |
725 |
|
|
725 |
|
|
726 | 726 |
register_ioport_write(base, 16, 1, ne2000_ioport_write, s); |
727 | 727 |
register_ioport_read(base, 16, 1, ne2000_ioport_read, s); |
728 | 728 |
|
... | ... | |
749 | 749 |
s->macaddr[3], |
750 | 750 |
s->macaddr[4], |
751 | 751 |
s->macaddr[5]); |
752 |
|
|
752 |
|
|
753 | 753 |
register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s); |
754 | 754 |
} |
755 | 755 |
|
... | ... | |
761 | 761 |
NE2000State ne2000; |
762 | 762 |
} PCINE2000State; |
763 | 763 |
|
764 |
static void ne2000_map(PCIDevice *pci_dev, int region_num,
|
|
764 |
static void ne2000_map(PCIDevice *pci_dev, int region_num, |
|
765 | 765 |
uint32_t addr, uint32_t size, int type) |
766 | 766 |
{ |
767 | 767 |
PCINE2000State *d = (PCINE2000State *)pci_dev; |
... | ... | |
786 | 786 |
PCINE2000State *d; |
787 | 787 |
NE2000State *s; |
788 | 788 |
uint8_t *pci_conf; |
789 |
|
|
789 |
|
|
790 | 790 |
d = (PCINE2000State *)pci_register_device(bus, |
791 | 791 |
"NE2000", sizeof(PCINE2000State), |
792 |
devfn,
|
|
792 |
devfn, |
|
793 | 793 |
NULL, NULL); |
794 | 794 |
pci_conf = d->dev.config; |
795 | 795 |
pci_conf[0x00] = 0xec; // Realtek 8029 |
796 | 796 |
pci_conf[0x01] = 0x10; |
797 | 797 |
pci_conf[0x02] = 0x29; |
798 | 798 |
pci_conf[0x03] = 0x80; |
799 |
pci_conf[0x0a] = 0x00; // ethernet network controller
|
|
799 |
pci_conf[0x0a] = 0x00; // ethernet network controller |
|
800 | 800 |
pci_conf[0x0b] = 0x02; |
801 | 801 |
pci_conf[0x0e] = 0x00; // header_type |
802 | 802 |
pci_conf[0x3d] = 1; // interrupt pin 0 |
803 |
|
|
804 |
pci_register_io_region(&d->dev, 0, 0x100,
|
|
803 |
|
|
804 |
pci_register_io_region(&d->dev, 0, 0x100, |
|
805 | 805 |
PCI_ADDRESS_SPACE_IO, ne2000_map); |
806 | 806 |
s = &d->ne2000; |
807 | 807 |
s->irq = d->dev.irq[0]; |
... | ... | |
819 | 819 |
s->macaddr[3], |
820 | 820 |
s->macaddr[4], |
821 | 821 |
s->macaddr[5]); |
822 |
|
|
822 |
|
|
823 | 823 |
/* XXX: instance number ? */ |
824 | 824 |
register_savevm("ne2000", 0, 3, ne2000_save, ne2000_load, s); |
825 | 825 |
} |
Also available in: Unified diff