47#include "debug/Drain.hh"
48#include "debug/EthernetAll.hh"
51#include "params/IGbE.hh"
69 radvEvent([
this]{ radvProcess(); },
name()),
70 tadvEvent([
this]{ tadvProcess(); },
name()),
71 tidvEvent([
this]{ tidvProcess(); },
name()),
72 tickEvent([
this]{ tick(); },
name()),
73 interEvent([
this]{ delayIntEvent(); },
name()),
74 rxDescCache(
this,
name()+
".RxDesc",
p.rx_desc_cache_size),
75 txDescCache(
this,
name()+
".TxDesc",
p.tx_desc_cache_size),
94 regs.rxdctl.wthresh(1);
112 memcpy(flash,
p.hardware_address.bytes(), ETH_ADDR_LEN);
113 for (
int x = 0;
x < ETH_ADDR_LEN / 2;
x++)
125 macAddr =
p.hardware_address;
145 if (if_name ==
"interface")
157 panic(
"Device specific PCI config space not implemented.\n");
167#define IN_RANGE(val, base, len) (val >= base && val < (base + len))
176 panic(
"Invalid PCI memory access to unmapped memory.\n");
184 DPRINTF(Ethernet,
"Read device register %#X\n", daddr);
211 DPRINTF(Ethernet,
"Reading ICR. ICR=%#x IMR=%#x IAM=%#x IAME=%d\n",
214 if (
regs.icr.int_assert() ||
regs.imr == 0) {
216 DPRINTF(Ethernet,
"Cleared ICR. ICR=%#x\n",
regs.icr());
218 if (
regs.ctrl_ext.iame() &&
regs.icr.int_assert())
225 pkt->
setLE<uint32_t>(0);
246 pkt->
setLE<uint32_t>(0);
274 if (
regs.rdtr.fpd()) {
277 "Posting interrupt because of RDTR.FPD write\n");
348 panic(
"Read request to unknown register number: %#x\n", daddr);
350 pkt->
setLE<uint32_t>(0);
365 panic(
"Invalid PCI memory access to unmapped memory.\n");
371 assert(pkt->
getSize() ==
sizeof(uint32_t));
373 DPRINTF(Ethernet,
"Wrote device register %#X value %#X\n",
374 daddr, pkt->
getLE<uint32_t>());
379 uint32_t
val = pkt->
getLE<uint32_t>();
387 if (
regs.ctrl.tfce())
388 warn(
"TX Flow control enabled, should implement\n");
389 if (
regs.ctrl.rfce())
390 warn(
"RX Flow control enabled, should implement\n");
400 oldClk =
regs.eecd.sk();
403 if (!oldClk &&
regs.eecd.sk()) {
412 DPRINTF(EthernetEEPROM,
"EEPROM bit read: %d word: %#X\n",
422 panic(
"What's going on with eeprom interface? opcode:"
423 " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)
eeOpcode,
437 DPRINTF(EthernetEEPROM,
"EEPROM: opcode: %#X:%d addr: %#X:%d\n",
448 regs.eecd.ee_gnt(
regs.eecd.ee_req());
452 if (
regs.eerd.start()) {
457 DPRINTF(EthernetEEPROM,
"EEPROM: read addr: %#X data %#x\n",
458 regs.eerd.addr(),
regs.eerd.data());
464 panic(
"No support for interrupt on mdic complete\n");
465 if (
regs.mdic.phyadd() != 1)
466 panic(
"No support for reading anything but phy\n");
467 DPRINTF(Ethernet,
"%s phy address %x\n",
468 regs.mdic.op() == 1 ?
"Writing" :
"Reading",
470 switch (
regs.mdic.regadd()) {
472 regs.mdic.data(0x796D);
481 regs.mdic.data(0x7C00);
484 regs.mdic.data(0x3000);
487 regs.mdic.data(0x180);
495 DPRINTF(Ethernet,
"Writing ICR. ICR=%#x IMR=%#x IAM=%#x IAME=%d\n",
497 if (
regs.ctrl_ext.iame())
506 DPRINTF(EthernetIntr,
"Posting interrupt because of ICS write\n");
523 if (
regs.rctl.rst()) {
525 DPRINTF(EthernetSM,
"RXS: Got RESET!\n");
543 if (
regs.tctl.en() && !oldtctl.en()) {
564 warn(
"Writing to IVAR0, ignoring...\n");
593 DPRINTF(EthernetSM,
"RXS: RDT Updated.\n");
595 DPRINTF(EthernetSM,
"RXS: RDT Fetching Descriptors!\n");
598 DPRINTF(EthernetSM,
"RXS: RDT NOT Fetching Desc b/c draining!\n");
628 if (
regs.txdca_ctl.enabled())
629 panic(
"No support for DCA\n");
633 DPRINTF(EthernetSM,
"TXS: TX Tail pointer updated\n");
635 DPRINTF(EthernetSM,
"TXS: TDT Fetching Descriptors!\n");
638 DPRINTF(EthernetSM,
"TXS: TDT NOT Fetching Desc b/c draining!\n");
658 regs.tdwba |= (uint64_t)
val << 32;
670 if (
regs.rfctl.exsten())
671 panic(
"Extended RX descriptors not implemented\n");
678 if (
regs.fwsm.eep_fw_semaphore())
679 regs.swsm.swesmbi(0);
688 panic(
"Write request to unknown register number: %#x\n", daddr);
701 if (
t &
regs.icr() && !now)
708 "EINT: postInterrupt() curTick(): %d itr: %d interval: %d\n",
711 if (
regs.itr.interval() == 0 || now ||
719 assert(int_time > 0);
720 DPRINTF(EthernetIntr,
"EINT: Scheduling timer interrupt for tick %d\n",
742 DPRINTF(Ethernet,
"Interrupt Masked. Not Posting\n");
746 DPRINTF(Ethernet,
"Posting Interrupt\n");
770 regs.icr.int_assert(1);
771 DPRINTF(EthernetIntr,
"EINT: Posting interrupt to CPU now. Vector %#x\n",
782 if (
regs.icr.int_assert()) {
783 regs.icr.int_assert(0);
785 "EINT: Clearing interrupt to CPU now. Vector %#x\n",
794 DPRINTF(Ethernet,
"Checking interrupts icr: %#x imr: %#x\n",
regs.icr(),
798 DPRINTF(Ethernet,
"Mask cleaned all interrupts\n");
801 if (
regs.icr.int_assert())
804 DPRINTF(Ethernet,
"ITR = %#X itr.interval = %#X\n",
808 if (
regs.itr.interval() == 0) {
812 "Possibly scheduling interrupt because of imr write\n");
816 DPRINTF(Ethernet,
"Scheduling for %d\n",
t);
831 fetchDelayEvent([
this]{ fetchDescriptors1(); },
n),
832 fetchEvent([
this]{ fetchComplete(); },
n),
833 wbEvent([
this]{ wbComplete(); },
n)
835 fetchBuf =
new T[size];
852 panic(
"Descriptor Address, Length or Head changed. Bad\n");
872 "Writing back already in process, returning\n");
880 DPRINTF(EthernetDesc,
"Writing back descriptors head: %d tail: "
881 "%d len: %d cachePnt: %d max_to_wb: %d descleft: %d\n",
885 if (max_to_wb + curHead >=
descLen()) {
886 max_to_wb =
descLen() - curHead;
894 DPRINTF(EthernetDesc,
"Writing back %d descriptors\n", max_to_wb);
915 DPRINTF(EthernetDesc,
"Begining DMA of %d descriptors\n",
wbOut);
937 "Currently fetching %d descriptors, returning\n",
949 max_to_fetch = std::min(max_to_fetch, free_cache);
952 DPRINTF(EthernetDesc,
"Fetching descriptors head: %d tail: "
953 "%d len: %d cachePnt: %d max_to_fetch: %d descleft: %d\n",
958 if (max_to_fetch == 0)
978 DPRINTF(EthernetDesc,
"Fetching descriptors at %#x (%#x), size: %#x\n",
985 igbe->fetchCompDelay);
995 memcpy(newDesc, &
fetchBuf[
x],
sizeof(T));
1009 DPRINTF(EthernetDesc,
"Fetching complete cachePnt %d -> %d\n",
1022 long oldHead = curHead;
1039 DPRINTF(EthernetDesc,
"Writeback complete curHead %d -> %d\n",
1046 DPRINTF(EthernetDesc,
"Writeback has more todo\n");
1059 DPRINTF(EthernetDesc,
"Reseting descriptor cache\n");
1060 for (
typename CacheType::size_type
x = 0;
x <
usedCache.size();
x++)
1062 for (
typename CacheType::size_type
x = 0;
x <
unusedCache.size();
x++)
1082 typename CacheType::size_type usedCacheSize =
usedCache.size();
1084 for (
typename CacheType::size_type
x = 0;
x < usedCacheSize;
x++) {
1089 typename CacheType::size_type unusedCacheSize =
unusedCache.size();
1091 for (
typename CacheType::size_type
x = 0;
x < unusedCacheSize;
x++) {
1096 Tick fetch_delay = 0, wb_delay = 0;
1117 typename CacheType::size_type usedCacheSize;
1120 for (
typename CacheType::size_type
x = 0;
x < usedCacheSize;
x++) {
1123 (uint8_t *)temp,
sizeof(T));
1127 typename CacheType::size_type unusedCacheSize;
1129 for (
typename CacheType::size_type
x = 0;
x < unusedCacheSize;
x++) {
1132 (uint8_t *)temp,
sizeof(T));
1135 Tick fetch_delay = 0, wb_delay = 0;
1151 pktHdrEvent([
this]{ pktSplitDone(); },
n),
1152 pktDataEvent([
this]{ pktSplitDone(); },
n)
1155 annSmFetch =
"RX Desc Fetch";
1156 annSmWb =
"RX Desc Writeback";
1157 annUnusedDescQ =
"RX Unused Descriptors";
1158 annUnusedCacheQ =
"RX Unused Descriptor Cache";
1159 annUsedCacheQ =
"RX Used Descriptor Cache";
1160 annUsedDescQ =
"RX Used Descriptors";
1161 annDescQ =
"RX Descriptors";
1169 "Part of split packet done: splitcount now %d\n",
splitCount);
1175 "Part of split packet done: calling pktComplete()\n");
1188 unsigned buf_len, hdr_len;
1191 switch (
igbe->regs.srrctl.desctype()) {
1193 assert(pkt_offset == 0);
1195 DPRINTF(EthernetDesc,
"Packet Length: %d Desc Size: %d\n",
1196 packet->length,
igbe->regs.rctl.descSize());
1197 assert(packet->length <
igbe->regs.rctl.descSize());
1199 packet->length, &
pktEvent, packet->data,
1200 igbe->rxWriteDelay);
1203 assert(pkt_offset == 0);
1205 buf_len =
igbe->regs.rctl.lpe() ?
igbe->regs.srrctl.bufLen() :
1206 igbe->regs.rctl.descSize();
1207 DPRINTF(EthernetDesc,
"Packet Length: %d srrctl: %#x Desc Size: %d\n",
1208 packet->length,
igbe->regs.srrctl(), buf_len);
1209 assert(packet->length < buf_len);
1211 packet->length, &
pktEvent, packet->data,
1212 igbe->rxWriteDelay);
1220 buf_len =
igbe->regs.rctl.lpe() ?
igbe->regs.srrctl.bufLen() :
1221 igbe->regs.rctl.descSize();
1222 hdr_len =
igbe->regs.rctl.lpe() ?
igbe->regs.srrctl.hdrLen() : 0;
1224 "lpe: %d Packet Length: %d offset: %d srrctl: %#x "
1225 "hdr addr: %#x Hdr Size: %d desc addr: %#x Desc Size: %d\n",
1226 igbe->regs.rctl.lpe(), packet->length, pkt_offset,
1232 if (packet->length <= hdr_len) {
1234 assert(pkt_offset == 0);
1235 DPRINTF(EthernetDesc,
"Hdr split: Entire packet in header\n");
1237 packet->length, &
pktEvent, packet->data,
1238 igbe->rxWriteDelay);
1242 }
else if (split_point) {
1247 std::min(packet->length - pkt_offset, buf_len);
1250 "Hdr split: Continuing data buffer copy\n");
1253 packet->data + pkt_offset,
igbe->rxWriteDelay);
1259 std::min(packet->length - split_point, buf_len);
1262 DPRINTF(EthernetDesc,
"Hdr split: splitting at %d\n",
1266 packet->data,
igbe->rxWriteDelay);
1269 packet->data + split_point,
igbe->rxWriteDelay);
1275 panic(
"Header split not fitting within header buffer or "
1276 "undecodable packet not fitting in header unsupported\n");
1280 panic(
"Unimplemnted RX receive buffer type: %d\n",
1281 igbe->regs.srrctl.desctype());
1294 uint16_t crcfixup =
igbe->regs.rctl.secrc() ? 0 : 4 ;
1295 DPRINTF(EthernetDesc,
"pktPtr->length: %d bytesCopied: %d "
1296 "stripcrc offset: %d value written: %d %d\n",
1299 (uint16_t)(
pktPtr->length + crcfixup));
1302 assert(
igbe->regs.rxcsum.pcss() == 0);
1304 DPRINTF(EthernetDesc,
"Packet written to memory updating Descriptor\n");
1308 uint16_t ext_err = 0;
1313 assert(bytesCopied <= pktPtr->length);
1322 DPRINTF(EthernetDesc,
"Proccesing Ip packet with Id=%d\n",
1330 if (ip &&
igbe->regs.rxcsum.ipofld()) {
1331 DPRINTF(EthernetDesc,
"Checking IP checksum\n");
1334 igbe->etherDeviceStats.rxIpChecksums++;
1335 if (
cksum(ip) != 0) {
1338 DPRINTF(EthernetDesc,
"Checksum is bad!!\n");
1342 if (tcp &&
igbe->regs.rxcsum.tuofld()) {
1343 DPRINTF(EthernetDesc,
"Checking TCP checksum\n");
1347 igbe->etherDeviceStats.rxTcpChecksums++;
1348 if (
cksum(tcp) != 0) {
1349 DPRINTF(EthernetDesc,
"Checksum is bad!!\n");
1356 if (udp &&
igbe->regs.rxcsum.tuofld()) {
1357 DPRINTF(EthernetDesc,
"Checking UDP checksum\n");
1361 igbe->etherDeviceStats.rxUdpChecksums++;
1362 if (
cksum(udp) != 0) {
1363 DPRINTF(EthernetDesc,
"Checksum is bad!!\n");
1369 DPRINTF(EthernetSM,
"Proccesing Non-Ip packet\n");
1372 switch (
igbe->regs.srrctl.desctype()) {
1384 if (
igbe->regs.rxcsum.pcsd()) {
1397 panic(
"Unimplemnted RX receive buffer type %d\n",
1398 igbe->regs.srrctl.desctype());
1401 DPRINTF(EthernetDesc,
"Descriptor complete w0: %#x w1: %#x\n",
1406 "Packet completely written to descriptor buffers\n");
1408 if (
igbe->regs.rdtr.delay()) {
1409 Tick delay =
igbe->regs.rdtr.delay() *
igbe->intClock();
1410 DPRINTF(EthernetSM,
"RXS: Scheduling DTR for %d\n", delay);
1414 if (
igbe->regs.radv.idv()) {
1416 DPRINTF(EthernetSM,
"RXS: Scheduling ADV for %d\n", delay);
1417 if (!
igbe->radvEvent.scheduled()) {
1423 if (!
igbe->regs.rdtr.delay() && !
igbe->regs.radv.idv()) {
1425 "RXS: Receive interrupt delay disabled, posting IT_RXT\n");
1431 if (
pktPtr->length <=
igbe->regs.rsrpd.idv()) {
1433 "RXS: Posting IT_SRPD beacuse small packet received\n");
1444 DPRINTF(EthernetDesc,
"Processing of this descriptor complete\n");
1453 igbe->rxTick =
true;
1454 igbe->restartClock();
1506 headerEvent([
this]{ headerComplete(); },
n),
1507 nullEvent([
this]{ nullCallback(); },
n)
1509 annSmFetch =
"TX Desc Fetch";
1510 annSmWb =
"TX Desc Writeback";
1511 annUnusedDescQ =
"TX Unused Descriptors";
1512 annUnusedCacheQ =
"TX Unused Descriptor Cache";
1513 annUsedCacheQ =
"TX Used Descriptor Cache";
1514 annUsedDescQ =
"TX Used Descriptors";
1515 annDescQ =
"TX Descriptors";
1524 DPRINTF(EthernetDesc,
"Checking and processing context descriptors\n");
1528 DPRINTF(EthernetDesc,
"Got context descriptor type...\n");
1531 DPRINTF(EthernetDesc,
"Descriptor upper: %#x lower: %#X\n",
1532 desc->
d1, desc->
d2);
1544 DPRINTF(EthernetDesc,
"TCP offload enabled for packet hdrlen: "
1569 DPRINTF(EthernetDesc,
"TCP offload(adv) enabled for packet "
1570 "hdrlen: %d mss: %d paylen %d\n",
1584 DPRINTF(EthernetDesc,
"Starting DMA of TSO header\n");
1596 DPRINTF(EthernetDesc,
"TSO: Fetching TSO header complete\n");
1601 DPRINTF(EthernetDesc,
"TSO: len: %d tsoHeaderLen: %d\n",
1610 DPRINTF(EthernetDesc,
"TSO: header part of larger payload\n");
1624 DPRINTF(EthernetDesc,
"Starting processing of descriptor\n");
1630 DPRINTF(EthernetDesc,
"getPacket(): TxDescriptor data "
1631 "d1: %#llx d2: %#llx\n", desc->
d1, desc->
d2);
1632 DPRINTF(EthernetDesc,
"TSO: use: %d hdrlen: %d mss: %d total: %d "
1645 DPRINTF(EthernetDesc,
"TSO: descBytesUsed: %d copyBytes: %d "
1646 "this descLen: %d\n",
1649 DPRINTF(EthernetDesc,
"TSO: Next packet is %d bytes\n", pkt_size);
1653 DPRINTF(EthernetDesc,
"Next TX packet is %d bytes\n",
1666 DPRINTF(EthernetDesc,
"getPacketData(): TxDescriptor data "
1667 "d1: %#llx d2: %#llx\n", desc->
d1, desc->
d2);
1675 DPRINTF(EthernetDesc,
"Starting DMA of packet at offset %d\n",
p->length);
1681 "Loading TSO header (%d bytes) into start of packet\n",
1691 "Starting DMA of packet at offset %d length: %d\n",
1714 DPRINTF(EthernetDesc,
"DMA of packet complete\n");
1721 DPRINTF(EthernetDesc,
"TxDescriptor data d1: %#llx d2: %#llx\n",
1722 desc->
d1, desc->
d2);
1726 DPRINTF(EthernetDesc,
"TSO: use: %d hdrlen: %d mss: %d total: %d "
1732 DPRINTF(EthernetDesc,
"TSO: descBytesUsed: %d copyBytes: %d\n",
1753 DPRINTF(EthernetDesc,
"Partial Packet Descriptor of %d bytes Done\n",
1775 DPRINTF(EthernetDesc,
"TxDescriptor data d1: %#llx d2: %#llx\n",
1776 desc->
d1, desc->
d2);
1782 DPRINTF(EthernetDesc,
"TSO: Modifying IP header. Id + %d\n",
1792 "TSO: Modifying TCP header. old seq %d + %d\n",
1796 tcp->flags(tcp->flags() & ~9);
1800 DPRINTF(EthernetDesc,
"TSO: Modifying UDP header.\n");
1806 if (debug::EthernetDesc) {
1809 DPRINTF(EthernetDesc,
"Proccesing Ip packet with Id=%d\n",
1812 DPRINTF(EthernetSM,
"Proccesing Non-Ip packet\n");
1817 DPRINTF(EthernetDesc,
"Calculating checksums for packet\n");
1824 igbe->etherDeviceStats.txIpChecksums++;
1825 DPRINTF(EthernetDesc,
"Calculated IP checksum\n");
1832 tcp->sum(
cksum(tcp));
1833 igbe->etherDeviceStats.txTcpChecksums++;
1834 DPRINTF(EthernetDesc,
"Calculated TCP checksum\n");
1839 igbe->etherDeviceStats.txUdpChecksums++;
1840 DPRINTF(EthernetDesc,
"Calculated UDP checksum\n");
1842 panic(
"Told to checksum, but don't know how\n");
1849 DPRINTF(EthernetDesc,
"Descriptor had IDE set\n");
1850 if (
igbe->regs.tidv.idv()) {
1852 DPRINTF(EthernetDesc,
"setting tidv\n");
1856 if (
igbe->regs.tadv.idv() &&
igbe->regs.tidv.idv()) {
1858 DPRINTF(EthernetDesc,
"setting tadv\n");
1859 if (!
igbe->tadvEvent.scheduled()) {
1867 DPRINTF(EthernetDesc,
"Descriptor Done\n");
1878 "------Packet of %d bytes ready for transmission-------\n",
1885 if (
igbe->regs.txdctl.wthresh() == 0) {
1886 DPRINTF(EthernetDesc,
"WTHRESH == 0, writing back descriptor\n");
1888 }
else if (!
igbe->regs.txdctl.gran() &&
igbe->regs.txdctl.wthresh() <=
1890 DPRINTF(EthernetDesc,
"used > WTHRESH, writing back descriptor\n");
1892 }
else if (
igbe->regs.txdctl.wthresh() <=
usedCache.size()) {
1893 DPRINTF(EthernetDesc,
"used > WTHRESH, writing back descriptor\n");
1904 DPRINTF(EthernetDesc,
"actionAfterWb() completionEnabled: %d\n",
1910 "Completion writing back value: %d to addr: %#x\n",
descEnd,
1989 igbe->txTick =
true;
1990 igbe->restartClock();
2015 unsigned int count(0);
2029 DPRINTF(Drain,
"IGbE not drained\n");
2045 DPRINTF(EthernetSM,
"resuming from drain");
2059 DPRINTF(Drain,
"IGbE done draining, processing drain event\n");
2067 if (!
regs.tctl.en()) {
2069 DPRINTF(EthernetSM,
"TXS: TX disabled, stopping ticking\n");
2078 DPRINTF(EthernetSM,
"TXS: packet placed in TX FIFO\n");
2091 if (
regs.txdctl.lwthresh() &&
2093 DPRINTF(EthernetSM,
"TXS: LWTHRESH caused posting of TXDLOW\n");
2098 txPacket = std::make_shared<EthPacketData>(16384);
2106 DPRINTF(EthernetSM,
"TXS: No descriptors left in ring, forcing "
2107 "writeback stopping ticking and posting TXQE\n");
2115 DPRINTF(EthernetSM,
"TXS: No descriptors available in cache, "
2116 "fetching and stopping ticking\n");
2125 "TXS: Fetching TSO header, stopping ticking\n");
2131 if (size > 0 &&
txFifo.avail() > size) {
2132 DPRINTF(EthernetSM,
"TXS: Reserving %d bytes in FIFO and "
2133 "beginning DMA of next packet\n", size);
2136 }
else if (size == 0) {
2137 DPRINTF(EthernetSM,
"TXS: getPacketSize returned: %d\n", size);
2139 "TXS: No packets to get, writing back used descriptors\n");
2142 DPRINTF(EthernetSM,
"TXS: FIFO full, stopping ticking until space "
2143 "available in FIFO\n");
2150 DPRINTF(EthernetSM,
"TXS: Nothing to do, stopping ticking\n");
2160 DPRINTF(Ethernet,
"RxFIFO: Receiving pcakte from wire\n");
2163 if (!
regs.rctl.en()) {
2164 DPRINTF(Ethernet,
"RxFIFO: RX not enabled, dropping\n");
2172 "RXS: received packet into fifo, starting ticking\n");
2177 DPRINTF(Ethernet,
"RxFIFO: Packet won't fit in fifo... dropped\n");
2189 if (!
regs.rctl.en()) {
2191 DPRINTF(EthernetSM,
"RXS: RX disabled, stopping ticking\n");
2198 DPRINTF(EthernetSM,
"RXS: Packet completed DMA to memory\n");
2200 DPRINTF(EthernetSM,
"RXS: descLeft: %d rdmts: %d rdlen: %d\n",
2201 descLeft,
regs.rctl.rdmts(),
regs.rdlen());
2204 int ratio = (1ULL << (
regs.rctl.rdmts() + 1));
2205 if (descLeft * ratio <=
regs.rdlen()) {
2206 DPRINTF(Ethernet,
"RXS: Interrupting (RXDMT) "
2207 "because of descriptors left\n");
2214 if (descLeft == 0) {
2216 DPRINTF(EthernetSM,
"RXS: No descriptors left in ring, forcing"
2217 " writeback and stopping ticking\n");
2222 assert(
regs.rxdctl.gran());
2226 "RXS: Writing back because WTHRESH >= descUsed\n");
2235 regs.rxdctl.hthresh())) {
2236 DPRINTF(EthernetSM,
"RXS: Fetching descriptors because "
2237 "descUnused < PTHRESH\n");
2243 DPRINTF(EthernetSM,
"RXS: No descriptors available in cache, "
2244 "fetching descriptors and stopping ticking\n");
2252 "RXS: stopping ticking until packet DMA completes\n");
2259 DPRINTF(EthernetSM,
"RXS: No descriptors available in cache, "
2260 "stopping ticking\n");
2262 DPRINTF(EthernetSM,
"RXS: No descriptors available, fetching\n");
2267 DPRINTF(EthernetSM,
"RXS: RxFIFO empty, stopping ticking\n");
2277 DPRINTF(EthernetSM,
"RXS: Writing packet into memory\n");
2279 DPRINTF(EthernetSM,
"RXS: Removing packet from FIFO\n");
2284 DPRINTF(EthernetSM,
"RXS: stopping ticking until packet DMA completes\n");
2299 if (debug::EthernetSM) {
2302 DPRINTF(EthernetSM,
"Transmitting Ip packet with Id=%d\n",
2305 DPRINTF(EthernetSM,
"Transmitting Non-Ip packet\n");
2308 "TxFIFO: Successful transmit, bytes available in fifo: %d\n",
2321 DPRINTF(EthernetSM,
"IGbE: -------------- Cycle --------------\n");
2358 DPRINTF(EthernetSM,
"TxFIFO: Transmission complete\n");
2378 bool txPktExists =
txPacket !=
nullptr;
2383 Tick rdtr_time = 0, radv_time = 0, tidv_time = 0, tadv_time = 0,
2432 txPacket = std::make_shared<EthPacketData>(16384);
2440 Tick rdtr_time, radv_time, tidv_time, tadv_time, inter_time;
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Cycles is a wrapper class for representing cycle counts, i.e.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Addr cacheBlockSize() const
gem5::EtherDevice::EtherDeviceStats etherDeviceStats
EtherDevice(const Params ¶ms)
virtual long descLen() const =0
virtual long descHead() const =0
void wbComplete()
Called by event when dma to writeback descriptors is completed.
virtual void updateHead(long h)=0
virtual void actionAfterWb()
virtual Addr descBase() const =0
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void areaChanged()
If the address/len/head change when we've got descriptors that are dirty that is very bad.
EventFunctionWrapper fetchDelayEvent
virtual void fetchAfterWb()=0
void fetchComplete()
Called by event when dma to read descriptors is completed.
EventFunctionWrapper fetchEvent
virtual void enableSm()=0
unsigned descLeft() const
EthPacketPtr pktPtr
The packet that is currently being dmad to memory if any.
void serialize(CheckpointOut &cp) const override
Serialize an object.
virtual long descTail() const =0
void writeback(Addr aMask)
EventFunctionWrapper wbDelayEvent
void fetchDescriptors()
Fetch a chunk of descriptors into the descriptor cache.
EventFunctionWrapper wbEvent
DescCache(IGbE *i, const std::string n, int s)
bool hasOutstandingEvents() override
EventFunctionWrapper pktEvent
void pktComplete()
Called by event when dma to write packet is completed.
int writePacket(EthPacketPtr packet, int pkt_offset)
Write the given packet into the buffer(s) pointed to by the descriptor and update the book keeping.
void serialize(CheckpointOut &cp) const override
Serialize an object.
unsigned bytesCopied
Bytes of packet that have been copied, so we know when to set EOP.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
EventFunctionWrapper pktHdrEvent
int splitCount
Variable to head with header/data completion events.
bool packetDone()
Check if the dma on the packet has completed and RX state machine can continue.
RxDescCache(IGbE *i, std::string n, int s)
EventFunctionWrapper pktDataEvent
unsigned descInBlock(unsigned num_desc)
Return the number of dsecriptors in a cache block for threshold operations.
bool packetAvailable()
Ask if the packet has been transfered so the state machine can give it to the fifo.
void getPacketData(EthPacketPtr p)
EventFunctionWrapper pktEvent
void processContextDesc()
TxDescCache(IGbE *i, std::string n, int s)
bool hasOutstandingEvents() override
unsigned getPacketSize(EthPacketPtr p)
Tell the cache to DMA a packet from main memory into its buffer and return the size the of the packet...
EventFunctionWrapper headerEvent
EventFunctionWrapper nullEvent
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void pktComplete()
Called by event when dma to write packet is completed.
void actionAfterWb() override
void serialize(CheckpointOut &cp) const override
Serialize an object.
EventFunctionWrapper interEvent
void postInterrupt(igbreg::IntTypes t, bool now=false)
Write an interrupt into the interrupt pending register and check mask and interrupt limit timer befor...
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
void chkInterrupt()
Check and see if changes to the mask register have caused an interrupt to need to be sent or perhaps ...
EventFunctionWrapper tickEvent
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
IGbE(const Params ¶ms)
uint16_t flash[igbreg::EEPROM_SIZE]
void drainResume() override
Resume execution after a successful drain.
void cpuClearInt()
Clear the interupt line to the cpu.
EventFunctionWrapper radvEvent
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
EventFunctionWrapper tidvEvent
void serialize(CheckpointOut &cp) const override
Serialize an object.
Tick writeConfig(PacketPtr pkt) override
Write to the PCI config space data that is stored locally.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
EventFunctionWrapper tadvEvent
void checkDrain()
Check if all the draining things that need to occur have occured and handle the drain event if so.
bool ethRxPkt(EthPacketPtr packet)
void delayIntEvent()
Send an interrupt to the cpu.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
void restartClock()
This function is used to restart the clock so it can handle things like draining and resume in one pl...
EventFunctionWrapper rdtrEvent
void setLE(T v)
Set the value in the data pointer to v as little endian.
void makeAtomicResponse()
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
bool getBAR(Addr addr, int &num, Addr &offs)
Which base address register (if any) maps the given address?
Addr pciToDma(Addr pci_addr) const
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Tick writeConfig(PacketPtr pkt) override
Write to the PCI config space data that is stored locally.
Ports are used to interface objects to each other.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
constexpr T mbits(T val, unsigned first, unsigned last)
Mask off the given bits in place like bits() but without shifting.
virtual void drainResume()
Resume execution after a successful drain.
void signalDrainDone() const
Signal that an object is drained.
DrainState drainState() const
Return the current drain state of an object.
DrainState
Object drain/handover states.
@ Draining
Draining buffers pending serialization/handover.
@ Running
Running normally.
@ Drained
Buffers drained, ready for serialization/handover.
void deschedule(Event &event)
void schedule(Event &event, Tick when)
uint16_t cksum(const IpPtr &ptr)
int hsplit(const EthPacketPtr &ptr)
#define panic(...)
This implements a cprintf based panic() function.
#define UNSERIALIZE_ARRAY(member, size)
#define SERIALIZE_ARRAY(member, size)
const Params & params() const
#define IN_RANGE(val, base, len)
const uint8_t TXD_ADVDATA
bool isContext(TxDesc *d)
bool isType(TxDesc *d, uint8_t type)
const uint8_t RCV_ADDRESS_TABLE_SIZE
const uint32_t REG_CTRL_EXT
const uint32_t REG_CRCERRS
const uint16_t RXDS_UDPCS
const uint32_t STATS_REGS_SIZE
const uint32_t REG_TXDCTL
const uint32_t REG_TDWBAL
const uint8_t PHY_PSTATUS
const uint32_t REG_RXDCTL
const uint32_t REG_RXCSUM
const uint16_t RXDS_TCPCS
const uint8_t EEPROM_SIZE
const uint32_t REG_SWFWSYNC
const uint8_t VLAN_FILTER_TABLE_SIZE
const uint8_t RXDT_ADV_SPLIT_A
const uint16_t RXDEE_TCPE
const uint8_t EEPROM_READ_OPCODE_SPI
const uint8_t PHY_EPSTATUS
const uint8_t MULTICAST_TABLE_SIZE
const uint32_t REG_STATUS
const uint8_t RXDT_ADV_ONEBUF
const uint32_t REG_LEDCTL
const uint32_t REG_TXDCA_CTL
const uint32_t REG_SRRCTL
const uint16_t EEPROM_CSUM
const uint8_t RXDT_LEGACY
const uint8_t EEPROM_RDSR_OPCODE_SPI
const uint32_t REG_TDWBAH
const uint8_t PHY_GSTATUS
Copyright (c) 2024 Arm Limited All rights reserved.
Tick curTick()
The universal simulation clock.
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
void arrayParamOut(CheckpointOut &cp, const std::string &name, const CircleBuf< T > ¶m)
uint64_t Tick
Tick count type.
std::string csprintf(const char *format, const Args &...args)
void arrayParamIn(CheckpointIn &cp, const std::string &name, CircleBuf< T > ¶m)
std::shared_ptr< EthPacketData > EthPacketPtr
Declaration of the Packet class.
#define PCI_DEVICE_SPECIFIC
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
struct gem5::igbreg::RxDesc::@174254266271271120027347137174276323165346050132::@106046215336347275366304204156344253374226160153 adv_wb
struct gem5::igbreg::RxDesc::@174254266271271120027347137174276323165346050132::@235016343146304015067065143144000173272245257246 legacy
struct gem5::igbreg::RxDesc::@174254266271271120027347137174276323165346050132::@002150301255176126043316215111060263044016023137 adv_read
const std::string & name()