Revision 16ef60c9
b/hw/eepro100.c | ||
---|---|---|
46 | 46 |
#include "net.h" |
47 | 47 |
#include "eeprom93xx.h" |
48 | 48 |
#include "sysemu.h" |
49 |
#include "dma.h" |
|
49 | 50 |
|
50 | 51 |
/* QEMU sends frames smaller than 60 bytes to ethernet nics. |
51 | 52 |
* Such frames are rejected by real nics and their emulations. |
... | ... | |
315 | 316 |
0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, |
316 | 317 |
}; |
317 | 318 |
|
318 |
/* Read a 16 bit little endian value from physical memory. */ |
|
319 |
static uint16_t e100_ldw_le_phys(target_phys_addr_t addr) |
|
320 |
{ |
|
321 |
/* Load 16 bit (little endian) word from emulated hardware. */ |
|
322 |
uint16_t val; |
|
323 |
cpu_physical_memory_read(addr, &val, sizeof(val)); |
|
324 |
return le16_to_cpu(val); |
|
325 |
} |
|
326 |
|
|
327 |
/* Read a 32 bit little endian value from physical memory. */ |
|
328 |
static uint32_t e100_ldl_le_phys(target_phys_addr_t addr) |
|
329 |
{ |
|
330 |
/* Load 32 bit (little endian) word from emulated hardware. */ |
|
331 |
uint32_t val; |
|
332 |
cpu_physical_memory_read(addr, &val, sizeof(val)); |
|
333 |
return le32_to_cpu(val); |
|
334 |
} |
|
335 |
|
|
336 |
/* Write a 16 bit little endian value to physical memory. */ |
|
337 |
static void e100_stw_le_phys(target_phys_addr_t addr, uint16_t val) |
|
338 |
{ |
|
339 |
val = cpu_to_le16(val); |
|
340 |
cpu_physical_memory_write(addr, &val, sizeof(val)); |
|
341 |
} |
|
342 |
|
|
343 |
/* Write a 32 bit little endian value to physical memory. */ |
|
344 |
static void e100_stl_le_phys(target_phys_addr_t addr, uint32_t val) |
|
345 |
{ |
|
346 |
val = cpu_to_le32(val); |
|
347 |
cpu_physical_memory_write(addr, &val, sizeof(val)); |
|
348 |
} |
|
349 |
|
|
350 | 319 |
#define POLYNOMIAL 0x04c11db6 |
351 | 320 |
|
352 | 321 |
/* From FreeBSD */ |
... | ... | |
744 | 713 |
* values which really matter. |
745 | 714 |
* Number of data should check configuration!!! |
746 | 715 |
*/ |
747 |
cpu_physical_memory_write(s->statsaddr, &s->statistics, s->stats_size); |
|
748 |
e100_stl_le_phys(s->statsaddr + 0, s->statistics.tx_good_frames); |
|
749 |
e100_stl_le_phys(s->statsaddr + 36, s->statistics.rx_good_frames); |
|
750 |
e100_stl_le_phys(s->statsaddr + 48, s->statistics.rx_resource_errors); |
|
751 |
e100_stl_le_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors); |
|
716 |
pci_dma_write(&s->dev, s->statsaddr, |
|
717 |
(uint8_t *) &s->statistics, s->stats_size); |
|
718 |
stl_le_pci_dma(&s->dev, s->statsaddr + 0, |
|
719 |
s->statistics.tx_good_frames); |
|
720 |
stl_le_pci_dma(&s->dev, s->statsaddr + 36, |
|
721 |
s->statistics.rx_good_frames); |
|
722 |
stl_le_pci_dma(&s->dev, s->statsaddr + 48, |
|
723 |
s->statistics.rx_resource_errors); |
|
724 |
stl_le_pci_dma(&s->dev, s->statsaddr + 60, |
|
725 |
s->statistics.rx_short_frame_errors); |
|
752 | 726 |
#if 0 |
753 |
e100_stw_le_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames);
|
|
754 |
e100_stw_le_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames);
|
|
727 |
stw_le_pci_dma(&s->dev, s->statsaddr + 76, s->statistics.xmt_tco_frames);
|
|
728 |
stw_le_pci_dma(&s->dev, s->statsaddr + 78, s->statistics.rcv_tco_frames);
|
|
755 | 729 |
missing("CU dump statistical counters"); |
756 | 730 |
#endif |
757 | 731 |
} |
758 | 732 |
|
759 | 733 |
static void read_cb(EEPRO100State *s) |
760 | 734 |
{ |
761 |
cpu_physical_memory_read(s->cb_address, &s->tx, sizeof(s->tx));
|
|
735 |
pci_dma_read(&s->dev, s->cb_address, (uint8_t *) &s->tx, sizeof(s->tx));
|
|
762 | 736 |
s->tx.status = le16_to_cpu(s->tx.status); |
763 | 737 |
s->tx.command = le16_to_cpu(s->tx.command); |
764 | 738 |
s->tx.link = le32_to_cpu(s->tx.link); |
... | ... | |
788 | 762 |
} |
789 | 763 |
assert(tcb_bytes <= sizeof(buf)); |
790 | 764 |
while (size < tcb_bytes) { |
791 |
uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
|
|
792 |
uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
|
|
765 |
uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address);
|
|
766 |
uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4);
|
|
793 | 767 |
#if 0 |
794 |
uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
|
|
768 |
uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6);
|
|
795 | 769 |
#endif |
796 | 770 |
tbd_address += 8; |
797 | 771 |
TRACE(RXTX, logout |
798 | 772 |
("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n", |
799 | 773 |
tx_buffer_address, tx_buffer_size)); |
800 | 774 |
tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size); |
801 |
cpu_physical_memory_read(tx_buffer_address, &buf[size], |
|
802 |
tx_buffer_size); |
|
775 |
pci_dma_read(&s->dev, tx_buffer_address, &buf[size], tx_buffer_size); |
|
803 | 776 |
size += tx_buffer_size; |
804 | 777 |
} |
805 | 778 |
if (tbd_array == 0xffffffff) { |
... | ... | |
810 | 783 |
if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) { |
811 | 784 |
/* Extended Flexible TCB. */ |
812 | 785 |
for (; tbd_count < 2; tbd_count++) { |
813 |
uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address); |
|
814 |
uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4); |
|
815 |
uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6); |
|
786 |
uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, |
|
787 |
tbd_address); |
|
788 |
uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, |
|
789 |
tbd_address + 4); |
|
790 |
uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, |
|
791 |
tbd_address + 6); |
|
816 | 792 |
tbd_address += 8; |
817 | 793 |
TRACE(RXTX, logout |
818 | 794 |
("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n", |
819 | 795 |
tx_buffer_address, tx_buffer_size)); |
820 | 796 |
tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size); |
821 |
cpu_physical_memory_read(tx_buffer_address, &buf[size],
|
|
822 |
tx_buffer_size);
|
|
797 |
pci_dma_read(&s->dev, tx_buffer_address,
|
|
798 |
&buf[size], tx_buffer_size);
|
|
823 | 799 |
size += tx_buffer_size; |
824 | 800 |
if (tx_buffer_el & 1) { |
825 | 801 |
break; |
... | ... | |
828 | 804 |
} |
829 | 805 |
tbd_address = tbd_array; |
830 | 806 |
for (; tbd_count < s->tx.tbd_count; tbd_count++) { |
831 |
uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
|
|
832 |
uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
|
|
833 |
uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
|
|
807 |
uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address);
|
|
808 |
uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4);
|
|
809 |
uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6);
|
|
834 | 810 |
tbd_address += 8; |
835 | 811 |
TRACE(RXTX, logout |
836 | 812 |
("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n", |
837 | 813 |
tx_buffer_address, tx_buffer_size)); |
838 | 814 |
tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size); |
839 |
cpu_physical_memory_read(tx_buffer_address, &buf[size],
|
|
840 |
tx_buffer_size);
|
|
815 |
pci_dma_read(&s->dev, tx_buffer_address,
|
|
816 |
&buf[size], tx_buffer_size);
|
|
841 | 817 |
size += tx_buffer_size; |
842 | 818 |
if (tx_buffer_el & 1) { |
843 | 819 |
break; |
... | ... | |
862 | 838 |
TRACE(OTHER, logout("multicast list, multicast count = %u\n", multicast_count)); |
863 | 839 |
for (i = 0; i < multicast_count; i += 6) { |
864 | 840 |
uint8_t multicast_addr[6]; |
865 |
cpu_physical_memory_read(s->cb_address + 10 + i, multicast_addr, 6);
|
|
841 |
pci_dma_read(&s->dev, s->cb_address + 10 + i, multicast_addr, 6);
|
|
866 | 842 |
TRACE(OTHER, logout("multicast entry %s\n", nic_dump(multicast_addr, 6))); |
867 | 843 |
unsigned mcast_idx = compute_mcast_idx(multicast_addr); |
868 | 844 |
assert(mcast_idx < 64); |
... | ... | |
896 | 872 |
/* Do nothing. */ |
897 | 873 |
break; |
898 | 874 |
case CmdIASetup: |
899 |
cpu_physical_memory_read(s->cb_address + 8, &s->conf.macaddr.a[0], 6);
|
|
875 |
pci_dma_read(&s->dev, s->cb_address + 8, &s->conf.macaddr.a[0], 6);
|
|
900 | 876 |
TRACE(OTHER, logout("macaddr: %s\n", nic_dump(&s->conf.macaddr.a[0], 6))); |
901 | 877 |
break; |
902 | 878 |
case CmdConfigure: |
903 |
cpu_physical_memory_read(s->cb_address + 8, &s->configuration[0],
|
|
904 |
sizeof(s->configuration));
|
|
879 |
pci_dma_read(&s->dev, s->cb_address + 8,
|
|
880 |
&s->configuration[0], sizeof(s->configuration));
|
|
905 | 881 |
TRACE(OTHER, logout("configuration: %s\n", |
906 | 882 |
nic_dump(&s->configuration[0], 16))); |
907 | 883 |
TRACE(OTHER, logout("configuration: %s\n", |
... | ... | |
938 | 914 |
break; |
939 | 915 |
} |
940 | 916 |
/* Write new status. */ |
941 |
e100_stw_le_phys(s->cb_address, s->tx.status | ok_status | STATUS_C); |
|
917 |
stw_le_pci_dma(&s->dev, s->cb_address, |
|
918 |
s->tx.status | ok_status | STATUS_C); |
|
942 | 919 |
if (bit_i) { |
943 | 920 |
/* CU completed action. */ |
944 | 921 |
eepro100_cx_interrupt(s); |
... | ... | |
1005 | 982 |
/* Dump statistical counters. */ |
1006 | 983 |
TRACE(OTHER, logout("val=0x%02x (dump stats)\n", val)); |
1007 | 984 |
dump_statistics(s); |
1008 |
e100_stl_le_phys(s->statsaddr + s->stats_size, 0xa005);
|
|
985 |
stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa005);
|
|
1009 | 986 |
break; |
1010 | 987 |
case CU_CMD_BASE: |
1011 | 988 |
/* Load CU base. */ |
... | ... | |
1016 | 993 |
/* Dump and reset statistical counters. */ |
1017 | 994 |
TRACE(OTHER, logout("val=0x%02x (dump stats and reset)\n", val)); |
1018 | 995 |
dump_statistics(s); |
1019 |
e100_stl_le_phys(s->statsaddr + s->stats_size, 0xa007);
|
|
996 |
stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa007);
|
|
1020 | 997 |
memset(&s->statistics, 0, sizeof(s->statistics)); |
1021 | 998 |
break; |
1022 | 999 |
case CU_SRESUME: |
... | ... | |
1310 | 1287 |
case PORT_SELFTEST: |
1311 | 1288 |
TRACE(OTHER, logout("selftest address=0x%08x\n", address)); |
1312 | 1289 |
eepro100_selftest_t data; |
1313 |
cpu_physical_memory_read(address, &data, sizeof(data));
|
|
1290 |
pci_dma_read(&s->dev, address, (uint8_t *) &data, sizeof(data));
|
|
1314 | 1291 |
data.st_sign = 0xffffffff; |
1315 | 1292 |
data.st_result = 0; |
1316 |
cpu_physical_memory_write(address, &data, sizeof(data));
|
|
1293 |
pci_dma_write(&s->dev, address, (uint8_t *) &data, sizeof(data));
|
|
1317 | 1294 |
break; |
1318 | 1295 |
case PORT_SELECTIVE_RESET: |
1319 | 1296 |
TRACE(OTHER, logout("selective reset, selftest address=0x%08x\n", address)); |
... | ... | |
1729 | 1706 |
} |
1730 | 1707 |
/* !!! */ |
1731 | 1708 |
eepro100_rx_t rx; |
1732 |
cpu_physical_memory_read(s->ru_base + s->ru_offset, &rx,
|
|
1733 |
sizeof(eepro100_rx_t));
|
|
1709 |
pci_dma_read(&s->dev, s->ru_base + s->ru_offset,
|
|
1710 |
(uint8_t *) &rx, sizeof(eepro100_rx_t));
|
|
1734 | 1711 |
uint16_t rfd_command = le16_to_cpu(rx.command); |
1735 | 1712 |
uint16_t rfd_size = le16_to_cpu(rx.size); |
1736 | 1713 |
|
... | ... | |
1746 | 1723 |
#endif |
1747 | 1724 |
TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n", |
1748 | 1725 |
rfd_command, rx.link, rx.rx_buf_addr, rfd_size)); |
1749 |
e100_stw_le_phys(s->ru_base + s->ru_offset +
|
|
1750 |
offsetof(eepro100_rx_t, status), rfd_status);
|
|
1751 |
e100_stw_le_phys(s->ru_base + s->ru_offset +
|
|
1752 |
offsetof(eepro100_rx_t, count), size);
|
|
1726 |
stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset +
|
|
1727 |
offsetof(eepro100_rx_t, status), rfd_status); |
|
1728 |
stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset +
|
|
1729 |
offsetof(eepro100_rx_t, count), size); |
|
1753 | 1730 |
/* Early receive interrupt not supported. */ |
1754 | 1731 |
#if 0 |
1755 | 1732 |
eepro100_er_interrupt(s); |
... | ... | |
1763 | 1740 |
#if 0 |
1764 | 1741 |
assert(!(s->configuration[17] & BIT(0))); |
1765 | 1742 |
#endif |
1766 |
cpu_physical_memory_write(s->ru_base + s->ru_offset +
|
|
1767 |
sizeof(eepro100_rx_t), buf, size);
|
|
1743 |
pci_dma_write(&s->dev, s->ru_base + s->ru_offset +
|
|
1744 |
sizeof(eepro100_rx_t), buf, size); |
|
1768 | 1745 |
s->statistics.rx_good_frames++; |
1769 | 1746 |
eepro100_fr_interrupt(s); |
1770 | 1747 |
s->ru_offset = le32_to_cpu(rx.link); |
Also available in: Unified diff