gem5  v21.1.0.2
i8254xGBe.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006 The Regents of The University of Michigan
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /* @file
30  * Device model for Intel's 8254x line of gigabit ethernet controllers.
31  * In particular an 82547 revision 2 (82547GI) MAC because it seems to have the
32  * fewest workarounds in the driver. It will probably work with most of the
33  * other MACs with slight modifications.
34  */
35 
36 #include "dev/net/i8254xGBe.hh"
37 
38 /*
39  * @todo really there are multiple dma engines.. we should implement them.
40  */
41 
42 #include <algorithm>
43 #include <memory>
44 
45 #include "base/inet.hh"
46 #include "base/trace.hh"
47 #include "debug/Drain.hh"
48 #include "debug/EthernetAll.hh"
49 #include "mem/packet.hh"
50 #include "mem/packet_access.hh"
51 #include "params/IGbE.hh"
52 #include "sim/stats.hh"
53 #include "sim/system.hh"
54 
55 namespace gem5
56 {
57 
58 using namespace igbreg;
59 using namespace networking;
60 
62  : EtherDevice(p), etherInt(NULL),
63  rxFifo(p.rx_fifo_size), txFifo(p.tx_fifo_size), inTick(false),
64  rxTick(false), txTick(false), txFifoTick(false), rxDmaPacket(false),
65  pktOffset(0), fetchDelay(p.fetch_delay), wbDelay(p.wb_delay),
66  fetchCompDelay(p.fetch_comp_delay), wbCompDelay(p.wb_comp_delay),
67  rxWriteDelay(p.rx_write_delay), txReadDelay(p.tx_read_delay),
68  rdtrEvent([this]{ rdtrProcess(); }, name()),
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),
76  lastInterrupt(0)
77 {
78  etherInt = new IGbEInt(name() + ".int", this);
79 
80  // Initialized internal registers per Intel documentation
81  // All registers intialized to 0 by per register constructor
82  regs.ctrl.fd(1);
83  regs.ctrl.lrst(1);
84  regs.ctrl.speed(2);
85  regs.ctrl.frcspd(1);
86  regs.sts.speed(3); // Say we're 1000Mbps
87  regs.sts.fd(1); // full duplex
88  regs.sts.lu(1); // link up
89  regs.eecd.fwe(1);
90  regs.eecd.ee_type(1);
91  regs.imr = 0;
92  regs.iam = 0;
93  regs.rxdctl.gran(1);
94  regs.rxdctl.wthresh(1);
95  regs.fcrth(1);
96  regs.tdwba = 0;
97  regs.rlpml = 0;
98  regs.sw_fw_sync = 0;
99 
100  regs.pba.rxa(0x30);
101  regs.pba.txa(0x10);
102 
103  eeOpBits = 0;
104  eeAddrBits = 0;
105  eeDataBits = 0;
106  eeOpcode = 0;
107 
108  // clear all 64 16 bit words of the eeprom
109  memset(&flash, 0, EEPROM_SIZE*2);
110 
111  // Set the MAC address
112  memcpy(flash, p.hardware_address.bytes(), ETH_ADDR_LEN);
113  for (int x = 0; x < ETH_ADDR_LEN/2; x++)
114  flash[x] = htobe(flash[x]);
115 
116  uint16_t csum = 0;
117  for (int x = 0; x < EEPROM_SIZE; x++)
118  csum += htobe(flash[x]);
119 
120 
121  // Magic happy checksum value
122  flash[EEPROM_SIZE-1] = htobe((uint16_t)(EEPROM_CSUM - csum));
123 
124  // Store the MAC address as queue ID
125  macAddr = p.hardware_address;
126 
127  rxFifo.clear();
128  txFifo.clear();
129 }
130 
132 {
133  delete etherInt;
134 }
135 
136 void
138 {
139  PciDevice::init();
140 }
141 
142 Port &
143 IGbE::getPort(const std::string &if_name, PortID idx)
144 {
145  if (if_name == "interface")
146  return *etherInt;
147  return EtherDevice::getPort(if_name, idx);
148 }
149 
150 Tick
152 {
153  int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
156  else
157  panic("Device specific PCI config space not implemented.\n");
158 
159  //
160  // Some work may need to be done here based for the pci COMMAND bits.
161  //
162 
163  return configDelay;
164 }
165 
166 // Handy macro for range-testing register access addresses
167 #define IN_RANGE(val, base, len) (val >= base && val < (base + len))
168 
169 Tick
171 {
172  int bar;
173  Addr daddr;
174 
175  if (!getBAR(pkt->getAddr(), bar, daddr))
176  panic("Invalid PCI memory access to unmapped memory.\n");
177 
178  // Only Memory register BAR is allowed
179  assert(bar == 0);
180 
181  // Only 32bit accesses allowed
182  assert(pkt->getSize() == 4);
183 
184  DPRINTF(Ethernet, "Read device register %#X\n", daddr);
185 
186  //
187  // Handle read of register here
188  //
189 
190 
191  switch (daddr) {
192  case REG_CTRL:
193  pkt->setLE<uint32_t>(regs.ctrl());
194  break;
195  case REG_STATUS:
196  pkt->setLE<uint32_t>(regs.sts());
197  break;
198  case REG_EECD:
199  pkt->setLE<uint32_t>(regs.eecd());
200  break;
201  case REG_EERD:
202  pkt->setLE<uint32_t>(regs.eerd());
203  break;
204  case REG_CTRL_EXT:
205  pkt->setLE<uint32_t>(regs.ctrl_ext());
206  break;
207  case REG_MDIC:
208  pkt->setLE<uint32_t>(regs.mdic());
209  break;
210  case REG_ICR:
211  DPRINTF(Ethernet, "Reading ICR. ICR=%#x IMR=%#x IAM=%#x IAME=%d\n",
212  regs.icr(), regs.imr, regs.iam, regs.ctrl_ext.iame());
213  pkt->setLE<uint32_t>(regs.icr());
214  if (regs.icr.int_assert() || regs.imr == 0) {
215  regs.icr = regs.icr() & ~mask(30);
216  DPRINTF(Ethernet, "Cleared ICR. ICR=%#x\n", regs.icr());
217  }
218  if (regs.ctrl_ext.iame() && regs.icr.int_assert())
219  regs.imr &= ~regs.iam;
220  chkInterrupt();
221  break;
222  case REG_EICR:
223  // This is only useful for MSI, but the driver reads it every time
224  // Just don't do anything
225  pkt->setLE<uint32_t>(0);
226  break;
227  case REG_ITR:
228  pkt->setLE<uint32_t>(regs.itr());
229  break;
230  case REG_RCTL:
231  pkt->setLE<uint32_t>(regs.rctl());
232  break;
233  case REG_FCTTV:
234  pkt->setLE<uint32_t>(regs.fcttv());
235  break;
236  case REG_TCTL:
237  pkt->setLE<uint32_t>(regs.tctl());
238  break;
239  case REG_PBA:
240  pkt->setLE<uint32_t>(regs.pba());
241  break;
242  case REG_WUC:
243  case REG_WUFC:
244  case REG_WUS:
245  case REG_LEDCTL:
246  pkt->setLE<uint32_t>(0); // We don't care, so just return 0
247  break;
248  case REG_FCRTL:
249  pkt->setLE<uint32_t>(regs.fcrtl());
250  break;
251  case REG_FCRTH:
252  pkt->setLE<uint32_t>(regs.fcrth());
253  break;
254  case REG_RDBAL:
255  pkt->setLE<uint32_t>(regs.rdba.rdbal());
256  break;
257  case REG_RDBAH:
258  pkt->setLE<uint32_t>(regs.rdba.rdbah());
259  break;
260  case REG_RDLEN:
261  pkt->setLE<uint32_t>(regs.rdlen());
262  break;
263  case REG_SRRCTL:
264  pkt->setLE<uint32_t>(regs.srrctl());
265  break;
266  case REG_RDH:
267  pkt->setLE<uint32_t>(regs.rdh());
268  break;
269  case REG_RDT:
270  pkt->setLE<uint32_t>(regs.rdt());
271  break;
272  case REG_RDTR:
273  pkt->setLE<uint32_t>(regs.rdtr());
274  if (regs.rdtr.fpd()) {
276  DPRINTF(EthernetIntr,
277  "Posting interrupt because of RDTR.FPD write\n");
279  regs.rdtr.fpd(0);
280  }
281  break;
282  case REG_RXDCTL:
283  pkt->setLE<uint32_t>(regs.rxdctl());
284  break;
285  case REG_RADV:
286  pkt->setLE<uint32_t>(regs.radv());
287  break;
288  case REG_TDBAL:
289  pkt->setLE<uint32_t>(regs.tdba.tdbal());
290  break;
291  case REG_TDBAH:
292  pkt->setLE<uint32_t>(regs.tdba.tdbah());
293  break;
294  case REG_TDLEN:
295  pkt->setLE<uint32_t>(regs.tdlen());
296  break;
297  case REG_TDH:
298  pkt->setLE<uint32_t>(regs.tdh());
299  break;
300  case REG_TXDCA_CTL:
301  pkt->setLE<uint32_t>(regs.txdca_ctl());
302  break;
303  case REG_TDT:
304  pkt->setLE<uint32_t>(regs.tdt());
305  break;
306  case REG_TIDV:
307  pkt->setLE<uint32_t>(regs.tidv());
308  break;
309  case REG_TXDCTL:
310  pkt->setLE<uint32_t>(regs.txdctl());
311  break;
312  case REG_TADV:
313  pkt->setLE<uint32_t>(regs.tadv());
314  break;
315  case REG_TDWBAL:
316  pkt->setLE<uint32_t>(regs.tdwba & mask(32));
317  break;
318  case REG_TDWBAH:
319  pkt->setLE<uint32_t>(regs.tdwba >> 32);
320  break;
321  case REG_RXCSUM:
322  pkt->setLE<uint32_t>(regs.rxcsum());
323  break;
324  case REG_RLPML:
325  pkt->setLE<uint32_t>(regs.rlpml);
326  break;
327  case REG_RFCTL:
328  pkt->setLE<uint32_t>(regs.rfctl());
329  break;
330  case REG_MANC:
331  pkt->setLE<uint32_t>(regs.manc());
332  break;
333  case REG_SWSM:
334  pkt->setLE<uint32_t>(regs.swsm());
335  regs.swsm.smbi(1);
336  break;
337  case REG_FWSM:
338  pkt->setLE<uint32_t>(regs.fwsm());
339  break;
340  case REG_SWFWSYNC:
341  pkt->setLE<uint32_t>(regs.sw_fw_sync);
342  break;
343  default:
344  if (!IN_RANGE(daddr, REG_VFTA, VLAN_FILTER_TABLE_SIZE*4) &&
346  !IN_RANGE(daddr, REG_MTA, MULTICAST_TABLE_SIZE*4) &&
348  panic("Read request to unknown register number: %#x\n", daddr);
349  else
350  pkt->setLE<uint32_t>(0);
351  };
352 
353  pkt->makeAtomicResponse();
354  return pioDelay;
355 }
356 
357 Tick
359 {
360  int bar;
361  Addr daddr;
362 
363 
364  if (!getBAR(pkt->getAddr(), bar, daddr))
365  panic("Invalid PCI memory access to unmapped memory.\n");
366 
367  // Only Memory register BAR is allowed
368  assert(bar == 0);
369 
370  // Only 32bit accesses allowed
371  assert(pkt->getSize() == sizeof(uint32_t));
372 
373  DPRINTF(Ethernet, "Wrote device register %#X value %#X\n",
374  daddr, pkt->getLE<uint32_t>());
375 
376  //
377  // Handle write of register here
378  //
379  uint32_t val = pkt->getLE<uint32_t>();
380 
381  Regs::RCTL oldrctl;
382  Regs::TCTL oldtctl;
383 
384  switch (daddr) {
385  case REG_CTRL:
386  regs.ctrl = val;
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");
391  break;
392  case REG_CTRL_EXT:
393  regs.ctrl_ext = val;
394  break;
395  case REG_STATUS:
396  regs.sts = val;
397  break;
398  case REG_EECD:
399  int oldClk;
400  oldClk = regs.eecd.sk();
401  regs.eecd = val;
402  // See if this is a eeprom access and emulate accordingly
403  if (!oldClk && regs.eecd.sk()) {
404  if (eeOpBits < 8) {
405  eeOpcode = eeOpcode << 1 | regs.eecd.din();
406  eeOpBits++;
407  } else if (eeAddrBits < 8 && eeOpcode == EEPROM_READ_OPCODE_SPI) {
408  eeAddr = eeAddr << 1 | regs.eecd.din();
409  eeAddrBits++;
410  } else if (eeDataBits < 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) {
411  assert(eeAddr>>1 < EEPROM_SIZE);
412  DPRINTF(EthernetEEPROM, "EEPROM bit read: %d word: %#X\n",
413  flash[eeAddr>>1] >> eeDataBits & 0x1,
414  flash[eeAddr>>1]);
415  regs.eecd.dout((flash[eeAddr>>1] >> (15-eeDataBits)) & 0x1);
416  eeDataBits++;
417  } else if (eeDataBits < 8 && eeOpcode == EEPROM_RDSR_OPCODE_SPI) {
418  regs.eecd.dout(0);
419  eeDataBits++;
420  } else
421  panic("What's going on with eeprom interface? opcode:"
422  " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode,
423  (uint32_t)eeOpBits, (uint32_t)eeAddr,
424  (uint32_t)eeAddrBits, (uint32_t)eeDataBits);
425 
426  // Reset everything for the next command
427  if ((eeDataBits == 16 && eeOpcode == EEPROM_READ_OPCODE_SPI) ||
429  eeOpBits = 0;
430  eeAddrBits = 0;
431  eeDataBits = 0;
432  eeOpcode = 0;
433  eeAddr = 0;
434  }
435 
436  DPRINTF(EthernetEEPROM, "EEPROM: opcode: %#X:%d addr: %#X:%d\n",
437  (uint32_t)eeOpcode, (uint32_t) eeOpBits,
438  (uint32_t)eeAddr>>1, (uint32_t)eeAddrBits);
439  if (eeOpBits == 8 && !(eeOpcode == EEPROM_READ_OPCODE_SPI ||
441  panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode,
442  (uint32_t)eeOpBits);
443 
444 
445  }
446  // If driver requests eeprom access, immediately give it to it
447  regs.eecd.ee_gnt(regs.eecd.ee_req());
448  break;
449  case REG_EERD:
450  regs.eerd = val;
451  if (regs.eerd.start()) {
452  regs.eerd.done(1);
453  assert(regs.eerd.addr() < EEPROM_SIZE);
454  regs.eerd.data(flash[regs.eerd.addr()]);
455  regs.eerd.start(0);
456  DPRINTF(EthernetEEPROM, "EEPROM: read addr: %#X data %#x\n",
457  regs.eerd.addr(), regs.eerd.data());
458  }
459  break;
460  case REG_MDIC:
461  regs.mdic = val;
462  if (regs.mdic.i())
463  panic("No support for interrupt on mdic complete\n");
464  if (regs.mdic.phyadd() != 1)
465  panic("No support for reading anything but phy\n");
466  DPRINTF(Ethernet, "%s phy address %x\n",
467  regs.mdic.op() == 1 ? "Writing" : "Reading",
468  regs.mdic.regadd());
469  switch (regs.mdic.regadd()) {
470  case PHY_PSTATUS:
471  regs.mdic.data(0x796D); // link up
472  break;
473  case PHY_PID:
474  regs.mdic.data(params().phy_pid);
475  break;
476  case PHY_EPID:
477  regs.mdic.data(params().phy_epid);
478  break;
479  case PHY_GSTATUS:
480  regs.mdic.data(0x7C00);
481  break;
482  case PHY_EPSTATUS:
483  regs.mdic.data(0x3000);
484  break;
485  case PHY_AGC:
486  regs.mdic.data(0x180); // some random length
487  break;
488  default:
489  regs.mdic.data(0);
490  }
491  regs.mdic.r(1);
492  break;
493  case REG_ICR:
494  DPRINTF(Ethernet, "Writing ICR. ICR=%#x IMR=%#x IAM=%#x IAME=%d\n",
495  regs.icr(), regs.imr, regs.iam, regs.ctrl_ext.iame());
496  if (regs.ctrl_ext.iame())
497  regs.imr &= ~regs.iam;
498  regs.icr = ~bits(val,30,0) & regs.icr();
499  chkInterrupt();
500  break;
501  case REG_ITR:
502  regs.itr = val;
503  break;
504  case REG_ICS:
505  DPRINTF(EthernetIntr, "Posting interrupt because of ICS write\n");
507  break;
508  case REG_IMS:
509  regs.imr |= val;
510  chkInterrupt();
511  break;
512  case REG_IMC:
513  regs.imr &= ~val;
514  chkInterrupt();
515  break;
516  case REG_IAM:
517  regs.iam = val;
518  break;
519  case REG_RCTL:
520  oldrctl = regs.rctl;
521  regs.rctl = val;
522  if (regs.rctl.rst()) {
523  rxDescCache.reset();
524  DPRINTF(EthernetSM, "RXS: Got RESET!\n");
525  rxFifo.clear();
526  regs.rctl.rst(0);
527  }
528  if (regs.rctl.en())
529  rxTick = true;
530  restartClock();
531  break;
532  case REG_FCTTV:
533  regs.fcttv = val;
534  break;
535  case REG_TCTL:
536  regs.tctl = val;
537  oldtctl = regs.tctl;
538  regs.tctl = val;
539  if (regs.tctl.en())
540  txTick = true;
541  restartClock();
542  if (regs.tctl.en() && !oldtctl.en()) {
543  txDescCache.reset();
544  }
545  break;
546  case REG_PBA:
547  regs.pba.rxa(val);
548  regs.pba.txa(64 - regs.pba.rxa());
549  break;
550  case REG_WUC:
551  case REG_WUFC:
552  case REG_WUS:
553  case REG_LEDCTL:
554  case REG_FCAL:
555  case REG_FCAH:
556  case REG_FCT:
557  case REG_VET:
558  case REG_AIFS:
559  case REG_TIPG:
560  ; // We don't care, so don't store anything
561  break;
562  case REG_IVAR0:
563  warn("Writing to IVAR0, ignoring...\n");
564  break;
565  case REG_FCRTL:
566  regs.fcrtl = val;
567  break;
568  case REG_FCRTH:
569  regs.fcrth = val;
570  break;
571  case REG_RDBAL:
572  regs.rdba.rdbal( val & ~mask(4));
574  break;
575  case REG_RDBAH:
576  regs.rdba.rdbah(val);
578  break;
579  case REG_RDLEN:
580  regs.rdlen = val & ~mask(7);
582  break;
583  case REG_SRRCTL:
584  regs.srrctl = val;
585  break;
586  case REG_RDH:
587  regs.rdh = val;
589  break;
590  case REG_RDT:
591  regs.rdt = val;
592  DPRINTF(EthernetSM, "RXS: RDT Updated.\n");
593  if (drainState() == DrainState::Running) {
594  DPRINTF(EthernetSM, "RXS: RDT Fetching Descriptors!\n");
596  } else {
597  DPRINTF(EthernetSM, "RXS: RDT NOT Fetching Desc b/c draining!\n");
598  }
599  break;
600  case REG_RDTR:
601  regs.rdtr = val;
602  break;
603  case REG_RADV:
604  regs.radv = val;
605  break;
606  case REG_RXDCTL:
607  regs.rxdctl = val;
608  break;
609  case REG_TDBAL:
610  regs.tdba.tdbal( val & ~mask(4));
612  break;
613  case REG_TDBAH:
614  regs.tdba.tdbah(val);
616  break;
617  case REG_TDLEN:
618  regs.tdlen = val & ~mask(7);
620  break;
621  case REG_TDH:
622  regs.tdh = val;
624  break;
625  case REG_TXDCA_CTL:
626  regs.txdca_ctl = val;
627  if (regs.txdca_ctl.enabled())
628  panic("No support for DCA\n");
629  break;
630  case REG_TDT:
631  regs.tdt = val;
632  DPRINTF(EthernetSM, "TXS: TX Tail pointer updated\n");
633  if (drainState() == DrainState::Running) {
634  DPRINTF(EthernetSM, "TXS: TDT Fetching Descriptors!\n");
636  } else {
637  DPRINTF(EthernetSM, "TXS: TDT NOT Fetching Desc b/c draining!\n");
638  }
639  break;
640  case REG_TIDV:
641  regs.tidv = val;
642  break;
643  case REG_TXDCTL:
644  regs.txdctl = val;
645  break;
646  case REG_TADV:
647  regs.tadv = val;
648  break;
649  case REG_TDWBAL:
650  regs.tdwba &= ~mask(32);
651  regs.tdwba |= val;
653  regs.tdwba & mask(1));
654  break;
655  case REG_TDWBAH:
656  regs.tdwba &= mask(32);
657  regs.tdwba |= (uint64_t)val << 32;
659  regs.tdwba & mask(1));
660  break;
661  case REG_RXCSUM:
662  regs.rxcsum = val;
663  break;
664  case REG_RLPML:
665  regs.rlpml = val;
666  break;
667  case REG_RFCTL:
668  regs.rfctl = val;
669  if (regs.rfctl.exsten())
670  panic("Extended RX descriptors not implemented\n");
671  break;
672  case REG_MANC:
673  regs.manc = val;
674  break;
675  case REG_SWSM:
676  regs.swsm = val;
677  if (regs.fwsm.eep_fw_semaphore())
678  regs.swsm.swesmbi(0);
679  break;
680  case REG_SWFWSYNC:
681  regs.sw_fw_sync = val;
682  break;
683  default:
684  if (!IN_RANGE(daddr, REG_VFTA, VLAN_FILTER_TABLE_SIZE*4) &&
687  panic("Write request to unknown register number: %#x\n", daddr);
688  };
689 
690  pkt->makeAtomicResponse();
691  return pioDelay;
692 }
693 
694 void
696 {
697  assert(t);
698 
699  // Interrupt is already pending
700  if (t & regs.icr() && !now)
701  return;
702 
703  regs.icr = regs.icr() | t;
704 
705  Tick itr_interval = sim_clock::as_int::ns * 256 * regs.itr.interval();
706  DPRINTF(EthernetIntr,
707  "EINT: postInterrupt() curTick(): %d itr: %d interval: %d\n",
708  curTick(), regs.itr.interval(), itr_interval);
709 
710  if (regs.itr.interval() == 0 || now ||
711  lastInterrupt + itr_interval <= curTick()) {
712  if (interEvent.scheduled()) {
714  }
715  cpuPostInt();
716  } else {
717  Tick int_time = lastInterrupt + itr_interval;
718  assert(int_time > 0);
719  DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for tick %d\n",
720  int_time);
721  if (!interEvent.scheduled()) {
722  schedule(interEvent, int_time);
723  }
724  }
725 }
726 
727 void
729 {
730  cpuPostInt();
731 }
732 
733 
734 void
736 {
737 
739 
740  if (!(regs.icr() & regs.imr)) {
741  DPRINTF(Ethernet, "Interrupt Masked. Not Posting\n");
742  return;
743  }
744 
745  DPRINTF(Ethernet, "Posting Interrupt\n");
746 
747 
748  if (interEvent.scheduled()) {
750  }
751 
752  if (rdtrEvent.scheduled()) {
753  regs.icr.rxt0(1);
755  }
756  if (radvEvent.scheduled()) {
757  regs.icr.rxt0(1);
759  }
760  if (tadvEvent.scheduled()) {
761  regs.icr.txdw(1);
763  }
764  if (tidvEvent.scheduled()) {
765  regs.icr.txdw(1);
767  }
768 
769  regs.icr.int_assert(1);
770  DPRINTF(EthernetIntr, "EINT: Posting interrupt to CPU now. Vector %#x\n",
771  regs.icr());
772 
773  intrPost();
774 
776 }
777 
778 void
780 {
781  if (regs.icr.int_assert()) {
782  regs.icr.int_assert(0);
783  DPRINTF(EthernetIntr,
784  "EINT: Clearing interrupt to CPU now. Vector %#x\n",
785  regs.icr());
786  intrClear();
787  }
788 }
789 
790 void
792 {
793  DPRINTF(Ethernet, "Checking interrupts icr: %#x imr: %#x\n", regs.icr(),
794  regs.imr);
795  // Check if we need to clear the cpu interrupt
796  if (!(regs.icr() & regs.imr)) {
797  DPRINTF(Ethernet, "Mask cleaned all interrupts\n");
798  if (interEvent.scheduled())
800  if (regs.icr.int_assert())
801  cpuClearInt();
802  }
803  DPRINTF(Ethernet, "ITR = %#X itr.interval = %#X\n",
804  regs.itr(), regs.itr.interval());
805 
806  if (regs.icr() & regs.imr) {
807  if (regs.itr.interval() == 0) {
808  cpuPostInt();
809  } else {
810  DPRINTF(Ethernet,
811  "Possibly scheduling interrupt because of imr write\n");
812  if (!interEvent.scheduled()) {
813  Tick t = curTick() +
814  sim_clock::as_int::ns * 256 * regs.itr.interval();
815  DPRINTF(Ethernet, "Scheduling for %d\n", t);
817  }
818  }
819  }
820 }
821 
822 
824 
825 template<class T>
826 IGbE::DescCache<T>::DescCache(IGbE *i, const std::string n, int s)
827  : igbe(i), _name(n), cachePnt(0), size(s), curFetching(0),
828  wbOut(0), moreToWb(false), wbAlignment(0), pktPtr(NULL),
829  wbDelayEvent([this]{ writeback1(); }, n),
830  fetchDelayEvent([this]{ fetchDescriptors1(); }, n),
831  fetchEvent([this]{ fetchComplete(); }, n),
832  wbEvent([this]{ wbComplete(); }, n)
833 {
834  fetchBuf = new T[size];
835  wbBuf = new T[size];
836 }
837 
838 template<class T>
840 {
841  reset();
842  delete[] fetchBuf;
843  delete[] wbBuf;
844 }
845 
846 template<class T>
847 void
849 {
850  if (usedCache.size() > 0 || curFetching || wbOut)
851  panic("Descriptor Address, Length or Head changed. Bad\n");
852  reset();
853 
854 }
855 
856 template<class T>
857 void
859 {
860  int curHead = descHead();
861  int max_to_wb = usedCache.size();
862 
863  // Check if this writeback is less restrictive that the previous
864  // and if so setup another one immediately following it
865  if (wbOut) {
866  if (aMask < wbAlignment) {
867  moreToWb = true;
868  wbAlignment = aMask;
869  }
870  DPRINTF(EthernetDesc,
871  "Writing back already in process, returning\n");
872  return;
873  }
874 
875  moreToWb = false;
876  wbAlignment = aMask;
877 
878 
879  DPRINTF(EthernetDesc, "Writing back descriptors head: %d tail: "
880  "%d len: %d cachePnt: %d max_to_wb: %d descleft: %d\n",
881  curHead, descTail(), descLen(), cachePnt, max_to_wb,
882  descLeft());
883 
884  if (max_to_wb + curHead >= descLen()) {
885  max_to_wb = descLen() - curHead;
886  moreToWb = true;
887  // this is by definition aligned correctly
888  } else if (wbAlignment != 0) {
889  // align the wb point to the mask
890  max_to_wb = max_to_wb & ~wbAlignment;
891  }
892 
893  DPRINTF(EthernetDesc, "Writing back %d descriptors\n", max_to_wb);
894 
895  if (max_to_wb <= 0)
896  return;
897 
898  wbOut = max_to_wb;
899 
900  assert(!wbDelayEvent.scheduled());
901  igbe->schedule(wbDelayEvent, curTick() + igbe->wbDelay);
902 }
903 
904 template<class T>
905 void
907 {
908  // If we're draining delay issuing this DMA
909  if (igbe->drainState() != DrainState::Running) {
910  igbe->schedule(wbDelayEvent, curTick() + igbe->wbDelay);
911  return;
912  }
913 
914  DPRINTF(EthernetDesc, "Begining DMA of %d descriptors\n", wbOut);
915 
916  for (int x = 0; x < wbOut; x++) {
917  assert(usedCache.size());
918  memcpy(&wbBuf[x], usedCache[x], sizeof(T));
919  }
920 
921 
922  assert(wbOut);
923  igbe->dmaWrite(pciToDma(descBase() + descHead() * sizeof(T)),
924  wbOut * sizeof(T), &wbEvent, (uint8_t*)wbBuf,
925  igbe->wbCompDelay);
926 }
927 
928 template<class T>
929 void
931 {
932  size_t max_to_fetch;
933 
934  if (curFetching) {
935  DPRINTF(EthernetDesc,
936  "Currently fetching %d descriptors, returning\n",
937  curFetching);
938  return;
939  }
940 
941  if (descTail() >= cachePnt)
942  max_to_fetch = descTail() - cachePnt;
943  else
944  max_to_fetch = descLen() - cachePnt;
945 
946  size_t free_cache = size - usedCache.size() - unusedCache.size();
947 
948  max_to_fetch = std::min(max_to_fetch, free_cache);
949 
950 
951  DPRINTF(EthernetDesc, "Fetching descriptors head: %d tail: "
952  "%d len: %d cachePnt: %d max_to_fetch: %d descleft: %d\n",
953  descHead(), descTail(), descLen(), cachePnt,
954  max_to_fetch, descLeft());
955 
956  // Nothing to do
957  if (max_to_fetch == 0)
958  return;
959 
960  // So we don't have two descriptor fetches going on at once
961  curFetching = max_to_fetch;
962 
963  assert(!fetchDelayEvent.scheduled());
964  igbe->schedule(fetchDelayEvent, curTick() + igbe->fetchDelay);
965 }
966 
967 template<class T>
968 void
970 {
971  // If we're draining delay issuing this DMA
972  if (igbe->drainState() != DrainState::Running) {
973  igbe->schedule(fetchDelayEvent, curTick() + igbe->fetchDelay);
974  return;
975  }
976 
977  DPRINTF(EthernetDesc, "Fetching descriptors at %#x (%#x), size: %#x\n",
978  descBase() + cachePnt * sizeof(T),
979  pciToDma(descBase() + cachePnt * sizeof(T)),
980  curFetching * sizeof(T));
981  assert(curFetching);
982  igbe->dmaRead(pciToDma(descBase() + cachePnt * sizeof(T)),
983  curFetching * sizeof(T), &fetchEvent, (uint8_t*)fetchBuf,
984  igbe->fetchCompDelay);
985 }
986 
987 template<class T>
988 void
990 {
991  T *newDesc;
992  for (int x = 0; x < curFetching; x++) {
993  newDesc = new T;
994  memcpy(newDesc, &fetchBuf[x], sizeof(T));
995  unusedCache.push_back(newDesc);
996  }
997 
998 
999  int oldCp = cachePnt;
1000 
1001  cachePnt += curFetching;
1002  assert(cachePnt <= descLen());
1003  if (cachePnt == descLen())
1004  cachePnt = 0;
1005 
1006  curFetching = 0;
1007 
1008  DPRINTF(EthernetDesc, "Fetching complete cachePnt %d -> %d\n",
1009  oldCp, cachePnt);
1010 
1011  enableSm();
1012  igbe->checkDrain();
1013 }
1014 
1015 template<class T>
1016 void
1018 {
1019 
1020  long curHead = descHead();
1021  long oldHead = curHead;
1022 
1023  for (int x = 0; x < wbOut; x++) {
1024  assert(usedCache.size());
1025  delete usedCache[0];
1026  usedCache.pop_front();
1027  }
1028 
1029  curHead += wbOut;
1030  wbOut = 0;
1031 
1032  if (curHead >= descLen())
1033  curHead -= descLen();
1034 
1035  // Update the head
1036  updateHead(curHead);
1037 
1038  DPRINTF(EthernetDesc, "Writeback complete curHead %d -> %d\n",
1039  oldHead, curHead);
1040 
1041  // If we still have more to wb, call wb now
1042  actionAfterWb();
1043  if (moreToWb) {
1044  moreToWb = false;
1045  DPRINTF(EthernetDesc, "Writeback has more todo\n");
1046  writeback(wbAlignment);
1047  }
1048 
1049  if (!wbOut)
1050  igbe->checkDrain();
1051  fetchAfterWb();
1052 }
1053 
1054 template<class T>
1055 void
1057 {
1058  DPRINTF(EthernetDesc, "Reseting descriptor cache\n");
1059  for (typename CacheType::size_type x = 0; x < usedCache.size(); x++)
1060  delete usedCache[x];
1061  for (typename CacheType::size_type x = 0; x < unusedCache.size(); x++)
1062  delete unusedCache[x];
1063 
1064  usedCache.clear();
1065  unusedCache.clear();
1066 
1067  cachePnt = 0;
1068 
1069 }
1070 
1071 template<class T>
1072 void
1074 {
1075  SERIALIZE_SCALAR(cachePnt);
1076  SERIALIZE_SCALAR(curFetching);
1077  SERIALIZE_SCALAR(wbOut);
1078  SERIALIZE_SCALAR(moreToWb);
1079  SERIALIZE_SCALAR(wbAlignment);
1080 
1081  typename CacheType::size_type usedCacheSize = usedCache.size();
1082  SERIALIZE_SCALAR(usedCacheSize);
1083  for (typename CacheType::size_type x = 0; x < usedCacheSize; x++) {
1084  arrayParamOut(cp, csprintf("usedCache_%d", x),
1085  (uint8_t*)usedCache[x],sizeof(T));
1086  }
1087 
1088  typename CacheType::size_type unusedCacheSize = unusedCache.size();
1089  SERIALIZE_SCALAR(unusedCacheSize);
1090  for (typename CacheType::size_type x = 0; x < unusedCacheSize; x++) {
1091  arrayParamOut(cp, csprintf("unusedCache_%d", x),
1092  (uint8_t*)unusedCache[x],sizeof(T));
1093  }
1094 
1095  Tick fetch_delay = 0, wb_delay = 0;
1096  if (fetchDelayEvent.scheduled())
1097  fetch_delay = fetchDelayEvent.when();
1098  SERIALIZE_SCALAR(fetch_delay);
1099  if (wbDelayEvent.scheduled())
1100  wb_delay = wbDelayEvent.when();
1101  SERIALIZE_SCALAR(wb_delay);
1102 
1103 
1104 }
1105 
1106 template<class T>
1107 void
1109 {
1110  UNSERIALIZE_SCALAR(cachePnt);
1111  UNSERIALIZE_SCALAR(curFetching);
1112  UNSERIALIZE_SCALAR(wbOut);
1113  UNSERIALIZE_SCALAR(moreToWb);
1114  UNSERIALIZE_SCALAR(wbAlignment);
1115 
1116  typename CacheType::size_type usedCacheSize;
1117  UNSERIALIZE_SCALAR(usedCacheSize);
1118  T *temp;
1119  for (typename CacheType::size_type x = 0; x < usedCacheSize; x++) {
1120  temp = new T;
1121  arrayParamIn(cp, csprintf("usedCache_%d", x),
1122  (uint8_t*)temp,sizeof(T));
1123  usedCache.push_back(temp);
1124  }
1125 
1126  typename CacheType::size_type unusedCacheSize;
1127  UNSERIALIZE_SCALAR(unusedCacheSize);
1128  for (typename CacheType::size_type x = 0; x < unusedCacheSize; x++) {
1129  temp = new T;
1130  arrayParamIn(cp, csprintf("unusedCache_%d", x),
1131  (uint8_t*)temp,sizeof(T));
1132  unusedCache.push_back(temp);
1133  }
1134  Tick fetch_delay = 0, wb_delay = 0;
1135  UNSERIALIZE_SCALAR(fetch_delay);
1136  UNSERIALIZE_SCALAR(wb_delay);
1137  if (fetch_delay)
1138  igbe->schedule(fetchDelayEvent, fetch_delay);
1139  if (wb_delay)
1140  igbe->schedule(wbDelayEvent, wb_delay);
1141 
1142 
1143 }
1144 
1146 
1147 IGbE::RxDescCache::RxDescCache(IGbE *i, const std::string n, int s)
1148  : DescCache<RxDesc>(i, n, s), pktDone(false), splitCount(0),
1149  pktEvent([this]{ pktComplete(); }, n),
1150  pktHdrEvent([this]{ pktSplitDone(); }, n),
1151  pktDataEvent([this]{ pktSplitDone(); }, n)
1152 
1153 {
1154  annSmFetch = "RX Desc Fetch";
1155  annSmWb = "RX Desc Writeback";
1156  annUnusedDescQ = "RX Unused Descriptors";
1157  annUnusedCacheQ = "RX Unused Descriptor Cache";
1158  annUsedCacheQ = "RX Used Descriptor Cache";
1159  annUsedDescQ = "RX Used Descriptors";
1160  annDescQ = "RX Descriptors";
1161 }
1162 
1163 void
1165 {
1166  splitCount++;
1167  DPRINTF(EthernetDesc,
1168  "Part of split packet done: splitcount now %d\n", splitCount);
1169  assert(splitCount <= 2);
1170  if (splitCount != 2)
1171  return;
1172  splitCount = 0;
1173  DPRINTF(EthernetDesc,
1174  "Part of split packet done: calling pktComplete()\n");
1175  pktComplete();
1176 }
1177 
1178 int
1180 {
1181  assert(unusedCache.size());
1182  //if (!unusedCache.size())
1183  // return false;
1184 
1185  pktPtr = packet;
1186  pktDone = false;
1187  unsigned buf_len, hdr_len;
1188 
1189  RxDesc *desc = unusedCache.front();
1190  switch (igbe->regs.srrctl.desctype()) {
1191  case RXDT_LEGACY:
1192  assert(pkt_offset == 0);
1193  bytesCopied = packet->length;
1194  DPRINTF(EthernetDesc, "Packet Length: %d Desc Size: %d\n",
1195  packet->length, igbe->regs.rctl.descSize());
1196  assert(packet->length < igbe->regs.rctl.descSize());
1197  igbe->dmaWrite(pciToDma(desc->legacy.buf),
1198  packet->length, &pktEvent, packet->data,
1199  igbe->rxWriteDelay);
1200  break;
1201  case RXDT_ADV_ONEBUF:
1202  assert(pkt_offset == 0);
1203  bytesCopied = packet->length;
1204  buf_len = igbe->regs.rctl.lpe() ? igbe->regs.srrctl.bufLen() :
1205  igbe->regs.rctl.descSize();
1206  DPRINTF(EthernetDesc, "Packet Length: %d srrctl: %#x Desc Size: %d\n",
1207  packet->length, igbe->regs.srrctl(), buf_len);
1208  assert(packet->length < buf_len);
1209  igbe->dmaWrite(pciToDma(desc->adv_read.pkt),
1210  packet->length, &pktEvent, packet->data,
1211  igbe->rxWriteDelay);
1212  desc->adv_wb.header_len = htole(0);
1213  desc->adv_wb.sph = htole(0);
1214  desc->adv_wb.pkt_len = htole((uint16_t)(pktPtr->length));
1215  break;
1216  case RXDT_ADV_SPLIT_A:
1217  int split_point;
1218 
1219  buf_len = igbe->regs.rctl.lpe() ? igbe->regs.srrctl.bufLen() :
1220  igbe->regs.rctl.descSize();
1221  hdr_len = igbe->regs.rctl.lpe() ? igbe->regs.srrctl.hdrLen() : 0;
1222  DPRINTF(EthernetDesc,
1223  "lpe: %d Packet Length: %d offset: %d srrctl: %#x "
1224  "hdr addr: %#x Hdr Size: %d desc addr: %#x Desc Size: %d\n",
1225  igbe->regs.rctl.lpe(), packet->length, pkt_offset,
1226  igbe->regs.srrctl(), desc->adv_read.hdr, hdr_len,
1227  desc->adv_read.pkt, buf_len);
1228 
1229  split_point = hsplit(pktPtr);
1230 
1231  if (packet->length <= hdr_len) {
1232  bytesCopied = packet->length;
1233  assert(pkt_offset == 0);
1234  DPRINTF(EthernetDesc, "Hdr split: Entire packet in header\n");
1235  igbe->dmaWrite(pciToDma(desc->adv_read.hdr),
1236  packet->length, &pktEvent, packet->data,
1237  igbe->rxWriteDelay);
1238  desc->adv_wb.header_len = htole((uint16_t)packet->length);
1239  desc->adv_wb.sph = htole(0);
1240  desc->adv_wb.pkt_len = htole(0);
1241  } else if (split_point) {
1242  if (pkt_offset) {
1243  // we are only copying some data, header/data has already been
1244  // copied
1245  int max_to_copy =
1246  std::min(packet->length - pkt_offset, buf_len);
1247  bytesCopied += max_to_copy;
1248  DPRINTF(EthernetDesc,
1249  "Hdr split: Continuing data buffer copy\n");
1250  igbe->dmaWrite(pciToDma(desc->adv_read.pkt),
1251  max_to_copy, &pktEvent,
1252  packet->data + pkt_offset, igbe->rxWriteDelay);
1253  desc->adv_wb.header_len = htole(0);
1254  desc->adv_wb.pkt_len = htole((uint16_t)max_to_copy);
1255  desc->adv_wb.sph = htole(0);
1256  } else {
1257  int max_to_copy =
1258  std::min(packet->length - split_point, buf_len);
1259  bytesCopied += max_to_copy + split_point;
1260 
1261  DPRINTF(EthernetDesc, "Hdr split: splitting at %d\n",
1262  split_point);
1263  igbe->dmaWrite(pciToDma(desc->adv_read.hdr),
1264  split_point, &pktHdrEvent,
1265  packet->data, igbe->rxWriteDelay);
1266  igbe->dmaWrite(pciToDma(desc->adv_read.pkt),
1267  max_to_copy, &pktDataEvent,
1268  packet->data + split_point, igbe->rxWriteDelay);
1269  desc->adv_wb.header_len = htole(split_point);
1270  desc->adv_wb.sph = 1;
1271  desc->adv_wb.pkt_len = htole((uint16_t)(max_to_copy));
1272  }
1273  } else {
1274  panic("Header split not fitting within header buffer or "
1275  "undecodable packet not fitting in header unsupported\n");
1276  }
1277  break;
1278  default:
1279  panic("Unimplemnted RX receive buffer type: %d\n",
1280  igbe->regs.srrctl.desctype());
1281  }
1282  return bytesCopied;
1283 
1284 }
1285 
1286 void
1288 {
1289  assert(unusedCache.size());
1290  RxDesc *desc;
1291  desc = unusedCache.front();
1292 
1293  uint16_t crcfixup = igbe->regs.rctl.secrc() ? 0 : 4 ;
1294  DPRINTF(EthernetDesc, "pktPtr->length: %d bytesCopied: %d "
1295  "stripcrc offset: %d value written: %d %d\n",
1296  pktPtr->length, bytesCopied, crcfixup,
1297  htole((uint16_t)(pktPtr->length + crcfixup)),
1298  (uint16_t)(pktPtr->length + crcfixup));
1299 
1300  // no support for anything but starting at 0
1301  assert(igbe->regs.rxcsum.pcss() == 0);
1302 
1303  DPRINTF(EthernetDesc, "Packet written to memory updating Descriptor\n");
1304 
1305  uint16_t status = RXDS_DD;
1306  uint8_t err = 0;
1307  uint16_t ext_err = 0;
1308  uint16_t csum = 0;
1309  uint16_t ptype = 0;
1310  uint16_t ip_id = 0;
1311 
1312  assert(bytesCopied <= pktPtr->length);
1313  if (bytesCopied == pktPtr->length)
1314  status |= RXDS_EOP;
1315 
1316  IpPtr ip(pktPtr);
1317  Ip6Ptr ip6(pktPtr);
1318 
1319  if (ip || ip6) {
1320  if (ip) {
1321  DPRINTF(EthernetDesc, "Proccesing Ip packet with Id=%d\n",
1322  ip->id());
1323  ptype |= RXDP_IPV4;
1324  ip_id = ip->id();
1325  }
1326  if (ip6)
1327  ptype |= RXDP_IPV6;
1328 
1329  if (ip && igbe->regs.rxcsum.ipofld()) {
1330  DPRINTF(EthernetDesc, "Checking IP checksum\n");
1331  status |= RXDS_IPCS;
1332  csum = htole(cksum(ip));
1333  igbe->etherDeviceStats.rxIpChecksums++;
1334  if (cksum(ip) != 0) {
1335  err |= RXDE_IPE;
1336  ext_err |= RXDEE_IPE;
1337  DPRINTF(EthernetDesc, "Checksum is bad!!\n");
1338  }
1339  }
1340  TcpPtr tcp = ip ? TcpPtr(ip) : TcpPtr(ip6);
1341  if (tcp && igbe->regs.rxcsum.tuofld()) {
1342  DPRINTF(EthernetDesc, "Checking TCP checksum\n");
1343  status |= RXDS_TCPCS;
1344  ptype |= RXDP_TCP;
1345  csum = htole(cksum(tcp));
1346  igbe->etherDeviceStats.rxTcpChecksums++;
1347  if (cksum(tcp) != 0) {
1348  DPRINTF(EthernetDesc, "Checksum is bad!!\n");
1349  err |= RXDE_TCPE;
1350  ext_err |= RXDEE_TCPE;
1351  }
1352  }
1353 
1354  UdpPtr udp = ip ? UdpPtr(ip) : UdpPtr(ip6);
1355  if (udp && igbe->regs.rxcsum.tuofld()) {
1356  DPRINTF(EthernetDesc, "Checking UDP checksum\n");
1357  status |= RXDS_UDPCS;
1358  ptype |= RXDP_UDP;
1359  csum = htole(cksum(udp));
1360  igbe->etherDeviceStats.rxUdpChecksums++;
1361  if (cksum(udp) != 0) {
1362  DPRINTF(EthernetDesc, "Checksum is bad!!\n");
1363  ext_err |= RXDEE_TCPE;
1364  err |= RXDE_TCPE;
1365  }
1366  }
1367  } else { // if ip
1368  DPRINTF(EthernetSM, "Proccesing Non-Ip packet\n");
1369  }
1370 
1371  switch (igbe->regs.srrctl.desctype()) {
1372  case RXDT_LEGACY:
1373  desc->legacy.len = htole((uint16_t)(pktPtr->length + crcfixup));
1374  desc->legacy.status = htole(status);
1375  desc->legacy.errors = htole(err);
1376  // No vlan support at this point... just set it to 0
1377  desc->legacy.vlan = 0;
1378  break;
1379  case RXDT_ADV_SPLIT_A:
1380  case RXDT_ADV_ONEBUF:
1381  desc->adv_wb.rss_type = htole(0);
1382  desc->adv_wb.pkt_type = htole(ptype);
1383  if (igbe->regs.rxcsum.pcsd()) {
1384  // no rss support right now
1385  desc->adv_wb.rss_hash = htole(0);
1386  } else {
1387  desc->adv_wb.id = htole(ip_id);
1388  desc->adv_wb.csum = htole(csum);
1389  }
1390  desc->adv_wb.status = htole(status);
1391  desc->adv_wb.errors = htole(ext_err);
1392  // no vlan support
1393  desc->adv_wb.vlan_tag = htole(0);
1394  break;
1395  default:
1396  panic("Unimplemnted RX receive buffer type %d\n",
1397  igbe->regs.srrctl.desctype());
1398  }
1399 
1400  DPRINTF(EthernetDesc, "Descriptor complete w0: %#x w1: %#x\n",
1401  desc->adv_read.pkt, desc->adv_read.hdr);
1402 
1403  if (bytesCopied == pktPtr->length) {
1404  DPRINTF(EthernetDesc,
1405  "Packet completely written to descriptor buffers\n");
1406  // Deal with the rx timer interrupts
1407  if (igbe->regs.rdtr.delay()) {
1408  Tick delay = igbe->regs.rdtr.delay() * igbe->intClock();
1409  DPRINTF(EthernetSM, "RXS: Scheduling DTR for %d\n", delay);
1410  igbe->reschedule(igbe->rdtrEvent, curTick() + delay);
1411  }
1412 
1413  if (igbe->regs.radv.idv()) {
1414  Tick delay = igbe->regs.radv.idv() * igbe->intClock();
1415  DPRINTF(EthernetSM, "RXS: Scheduling ADV for %d\n", delay);
1416  if (!igbe->radvEvent.scheduled()) {
1417  igbe->schedule(igbe->radvEvent, curTick() + delay);
1418  }
1419  }
1420 
1421  // if neither radv or rdtr, maybe itr is set...
1422  if (!igbe->regs.rdtr.delay() && !igbe->regs.radv.idv()) {
1423  DPRINTF(EthernetSM,
1424  "RXS: Receive interrupt delay disabled, posting IT_RXT\n");
1425  igbe->postInterrupt(IT_RXT);
1426  }
1427 
1428  // If the packet is small enough, interrupt appropriately
1429  // I wonder if this is delayed or not?!
1430  if (pktPtr->length <= igbe->regs.rsrpd.idv()) {
1431  DPRINTF(EthernetSM,
1432  "RXS: Posting IT_SRPD beacuse small packet received\n");
1433  igbe->postInterrupt(IT_SRPD);
1434  }
1435  bytesCopied = 0;
1436  }
1437 
1438  pktPtr = NULL;
1439  igbe->checkDrain();
1440  enableSm();
1441  pktDone = true;
1442 
1443  DPRINTF(EthernetDesc, "Processing of this descriptor complete\n");
1444  unusedCache.pop_front();
1445  usedCache.push_back(desc);
1446 }
1447 
1448 void
1450 {
1451  if (igbe->drainState() != DrainState::Draining) {
1452  igbe->rxTick = true;
1453  igbe->restartClock();
1454  }
1455 }
1456 
1457 bool
1459 {
1460  if (pktDone) {
1461  pktDone = false;
1462  return true;
1463  }
1464  return false;
1465 }
1466 
1467 bool
1469 {
1470  return pktEvent.scheduled() || wbEvent.scheduled() ||
1471  fetchEvent.scheduled() || pktHdrEvent.scheduled() ||
1472  pktDataEvent.scheduled();
1473 
1474 }
1475 
1476 void
1478 {
1480  SERIALIZE_SCALAR(pktDone);
1481  SERIALIZE_SCALAR(splitCount);
1482  SERIALIZE_SCALAR(bytesCopied);
1483 }
1484 
1485 void
1487 {
1489  UNSERIALIZE_SCALAR(pktDone);
1490  UNSERIALIZE_SCALAR(splitCount);
1491  UNSERIALIZE_SCALAR(bytesCopied);
1492 }
1493 
1494 
1496 
1497 IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s)
1498  : DescCache<TxDesc>(i,n, s), pktDone(false), isTcp(false),
1499  pktWaiting(false), pktMultiDesc(false),
1500  completionAddress(0), completionEnabled(false),
1501  useTso(false), tsoHeaderLen(0), tsoMss(0), tsoTotalLen(0), tsoUsedLen(0),
1502  tsoPrevSeq(0), tsoPktPayloadBytes(0), tsoLoadedHeader(false),
1503  tsoPktHasHeader(false), tsoDescBytesUsed(0), tsoCopyBytes(0), tsoPkts(0),
1504  pktEvent([this]{ pktComplete(); }, n),
1505  headerEvent([this]{ headerComplete(); }, n),
1506  nullEvent([this]{ nullCallback(); }, n)
1507 {
1508  annSmFetch = "TX Desc Fetch";
1509  annSmWb = "TX Desc Writeback";
1510  annUnusedDescQ = "TX Unused Descriptors";
1511  annUnusedCacheQ = "TX Unused Descriptor Cache";
1512  annUsedCacheQ = "TX Used Descriptor Cache";
1513  annUsedDescQ = "TX Used Descriptors";
1514  annDescQ = "TX Descriptors";
1515 }
1516 
1517 void
1519 {
1520  assert(unusedCache.size());
1521  TxDesc *desc;
1522 
1523  DPRINTF(EthernetDesc, "Checking and processing context descriptors\n");
1524 
1525  while (!useTso && unusedCache.size() &&
1526  txd_op::isContext(unusedCache.front())) {
1527  DPRINTF(EthernetDesc, "Got context descriptor type...\n");
1528 
1529  desc = unusedCache.front();
1530  DPRINTF(EthernetDesc, "Descriptor upper: %#x lower: %#X\n",
1531  desc->d1, desc->d2);
1532 
1533 
1534  // is this going to be a tcp or udp packet?
1535  isTcp = txd_op::tcp(desc) ? true : false;
1536 
1537  // setup all the TSO variables, they'll be ignored if we don't use
1538  // tso for this connection
1539  tsoHeaderLen = txd_op::hdrlen(desc);
1540  tsoMss = txd_op::mss(desc);
1541 
1542  if (txd_op::isType(desc, txd_op::TXD_CNXT) && txd_op::tse(desc)) {
1543  DPRINTF(EthernetDesc, "TCP offload enabled for packet hdrlen: "
1544  "%d mss: %d paylen %d\n", txd_op::hdrlen(desc),
1545  txd_op::mss(desc), txd_op::getLen(desc));
1546  useTso = true;
1547  tsoTotalLen = txd_op::getLen(desc);
1548  tsoLoadedHeader = false;
1549  tsoDescBytesUsed = 0;
1550  tsoUsedLen = 0;
1551  tsoPrevSeq = 0;
1552  tsoPktHasHeader = false;
1553  tsoPkts = 0;
1554  tsoCopyBytes = 0;
1555  }
1556 
1557  txd_op::setDd(desc);
1558  unusedCache.pop_front();
1559  usedCache.push_back(desc);
1560  }
1561 
1562  if (!unusedCache.size())
1563  return;
1564 
1565  desc = unusedCache.front();
1566  if (!useTso && txd_op::isType(desc, txd_op::TXD_ADVDATA) &&
1567  txd_op::tse(desc)) {
1568  DPRINTF(EthernetDesc, "TCP offload(adv) enabled for packet "
1569  "hdrlen: %d mss: %d paylen %d\n",
1570  tsoHeaderLen, tsoMss, txd_op::getTsoLen(desc));
1571  useTso = true;
1572  tsoTotalLen = txd_op::getTsoLen(desc);
1573  tsoLoadedHeader = false;
1574  tsoDescBytesUsed = 0;
1575  tsoUsedLen = 0;
1576  tsoPrevSeq = 0;
1577  tsoPktHasHeader = false;
1578  tsoPkts = 0;
1579  }
1580 
1581  if (useTso && !tsoLoadedHeader) {
1582  // we need to fetch a header
1583  DPRINTF(EthernetDesc, "Starting DMA of TSO header\n");
1584  assert(txd_op::isData(desc) && txd_op::getLen(desc) >= tsoHeaderLen);
1585  pktWaiting = true;
1586  assert(tsoHeaderLen <= 256);
1587  igbe->dmaRead(pciToDma(txd_op::getBuf(desc)),
1588  tsoHeaderLen, &headerEvent, tsoHeader, 0);
1589  }
1590 }
1591 
1592 void
1594 {
1595  DPRINTF(EthernetDesc, "TSO: Fetching TSO header complete\n");
1596  pktWaiting = false;
1597 
1598  assert(unusedCache.size());
1599  TxDesc *desc = unusedCache.front();
1600  DPRINTF(EthernetDesc, "TSO: len: %d tsoHeaderLen: %d\n",
1601  txd_op::getLen(desc), tsoHeaderLen);
1602 
1603  if (txd_op::getLen(desc) == tsoHeaderLen) {
1604  tsoDescBytesUsed = 0;
1605  tsoLoadedHeader = true;
1606  unusedCache.pop_front();
1607  usedCache.push_back(desc);
1608  } else {
1609  DPRINTF(EthernetDesc, "TSO: header part of larger payload\n");
1610  tsoDescBytesUsed = tsoHeaderLen;
1611  tsoLoadedHeader = true;
1612  }
1613  enableSm();
1614  igbe->checkDrain();
1615 }
1616 
1617 unsigned
1619 {
1620  if (!unusedCache.size())
1621  return 0;
1622 
1623  DPRINTF(EthernetDesc, "Starting processing of descriptor\n");
1624 
1625  assert(!useTso || tsoLoadedHeader);
1626  TxDesc *desc = unusedCache.front();
1627 
1628  if (useTso) {
1629  DPRINTF(EthernetDesc, "getPacket(): TxDescriptor data "
1630  "d1: %#llx d2: %#llx\n", desc->d1, desc->d2);
1631  DPRINTF(EthernetDesc, "TSO: use: %d hdrlen: %d mss: %d total: %d "
1632  "used: %d loaded hdr: %d\n", useTso, tsoHeaderLen, tsoMss,
1633  tsoTotalLen, tsoUsedLen, tsoLoadedHeader);
1634 
1635  if (tsoPktHasHeader)
1636  tsoCopyBytes = std::min((tsoMss + tsoHeaderLen) - p->length,
1637  txd_op::getLen(desc) - tsoDescBytesUsed);
1638  else
1639  tsoCopyBytes = std::min(tsoMss,
1640  txd_op::getLen(desc) - tsoDescBytesUsed);
1641  unsigned pkt_size =
1642  tsoCopyBytes + (tsoPktHasHeader ? 0 : tsoHeaderLen);
1643 
1644  DPRINTF(EthernetDesc, "TSO: descBytesUsed: %d copyBytes: %d "
1645  "this descLen: %d\n",
1646  tsoDescBytesUsed, tsoCopyBytes, txd_op::getLen(desc));
1647  DPRINTF(EthernetDesc, "TSO: pktHasHeader: %d\n", tsoPktHasHeader);
1648  DPRINTF(EthernetDesc, "TSO: Next packet is %d bytes\n", pkt_size);
1649  return pkt_size;
1650  }
1651 
1652  DPRINTF(EthernetDesc, "Next TX packet is %d bytes\n",
1653  txd_op::getLen(unusedCache.front()));
1654  return txd_op::getLen(desc);
1655 }
1656 
1657 void
1659 {
1660  assert(unusedCache.size());
1661 
1662  TxDesc *desc;
1663  desc = unusedCache.front();
1664 
1665  DPRINTF(EthernetDesc, "getPacketData(): TxDescriptor data "
1666  "d1: %#llx d2: %#llx\n", desc->d1, desc->d2);
1667  assert((txd_op::isLegacy(desc) || txd_op::isData(desc)) &&
1668  txd_op::getLen(desc));
1669 
1670  pktPtr = p;
1671 
1672  pktWaiting = true;
1673 
1674  DPRINTF(EthernetDesc, "Starting DMA of packet at offset %d\n", p->length);
1675 
1676  if (useTso) {
1677  assert(tsoLoadedHeader);
1678  if (!tsoPktHasHeader) {
1679  DPRINTF(EthernetDesc,
1680  "Loading TSO header (%d bytes) into start of packet\n",
1681  tsoHeaderLen);
1682  memcpy(p->data, &tsoHeader,tsoHeaderLen);
1683  p->length +=tsoHeaderLen;
1684  tsoPktHasHeader = true;
1685  }
1686  }
1687 
1688  if (useTso) {
1689  DPRINTF(EthernetDesc,
1690  "Starting DMA of packet at offset %d length: %d\n",
1691  p->length, tsoCopyBytes);
1692  igbe->dmaRead(pciToDma(txd_op::getBuf(desc))
1693  + tsoDescBytesUsed,
1694  tsoCopyBytes, &pktEvent, p->data + p->length,
1695  igbe->txReadDelay);
1696  tsoDescBytesUsed += tsoCopyBytes;
1697  assert(tsoDescBytesUsed <= txd_op::getLen(desc));
1698  } else {
1699  igbe->dmaRead(pciToDma(txd_op::getBuf(desc)),
1700  txd_op::getLen(desc), &pktEvent, p->data + p->length,
1701  igbe->txReadDelay);
1702  }
1703 }
1704 
1705 void
1707 {
1708 
1709  TxDesc *desc;
1710  assert(unusedCache.size());
1711  assert(pktPtr);
1712 
1713  DPRINTF(EthernetDesc, "DMA of packet complete\n");
1714 
1715 
1716  desc = unusedCache.front();
1717  assert((txd_op::isLegacy(desc) || txd_op::isData(desc)) &&
1718  txd_op::getLen(desc));
1719 
1720  DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n",
1721  desc->d1, desc->d2);
1722 
1723  // Set the length of the data in the EtherPacket
1724  if (useTso) {
1725  DPRINTF(EthernetDesc, "TSO: use: %d hdrlen: %d mss: %d total: %d "
1726  "used: %d loaded hdr: %d\n", useTso, tsoHeaderLen, tsoMss,
1727  tsoTotalLen, tsoUsedLen, tsoLoadedHeader);
1728  pktPtr->simLength += tsoCopyBytes;
1729  pktPtr->length += tsoCopyBytes;
1730  tsoUsedLen += tsoCopyBytes;
1731  DPRINTF(EthernetDesc, "TSO: descBytesUsed: %d copyBytes: %d\n",
1732  tsoDescBytesUsed, tsoCopyBytes);
1733  } else {
1734  pktPtr->simLength += txd_op::getLen(desc);
1735  pktPtr->length += txd_op::getLen(desc);
1736  }
1737 
1738 
1739 
1740  if ((!txd_op::eop(desc) && !useTso) ||
1741  (pktPtr->length < ( tsoMss + tsoHeaderLen) &&
1742  tsoTotalLen != tsoUsedLen && useTso)) {
1743  assert(!useTso || (tsoDescBytesUsed == txd_op::getLen(desc)));
1744  unusedCache.pop_front();
1745  usedCache.push_back(desc);
1746 
1747  tsoDescBytesUsed = 0;
1748  pktDone = true;
1749  pktWaiting = false;
1750  pktMultiDesc = true;
1751 
1752  DPRINTF(EthernetDesc, "Partial Packet Descriptor of %d bytes Done\n",
1753  pktPtr->length);
1754  pktPtr = NULL;
1755 
1756  enableSm();
1757  igbe->checkDrain();
1758  return;
1759  }
1760 
1761 
1762  pktMultiDesc = false;
1763  // no support for vlans
1764  assert(!txd_op::vle(desc));
1765 
1766  // we only support single packet descriptors at this point
1767  if (!useTso)
1768  assert(txd_op::eop(desc));
1769 
1770  // set that this packet is done
1771  if (txd_op::rs(desc))
1772  txd_op::setDd(desc);
1773 
1774  DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n",
1775  desc->d1, desc->d2);
1776 
1777  if (useTso) {
1778  IpPtr ip(pktPtr);
1779  Ip6Ptr ip6(pktPtr);
1780  if (ip) {
1781  DPRINTF(EthernetDesc, "TSO: Modifying IP header. Id + %d\n",
1782  tsoPkts);
1783  ip->id(ip->id() + tsoPkts++);
1784  ip->len(pktPtr->length - EthPtr(pktPtr)->size());
1785  }
1786  if (ip6)
1787  ip6->plen(pktPtr->length - EthPtr(pktPtr)->size());
1788  TcpPtr tcp = ip ? TcpPtr(ip) : TcpPtr(ip6);
1789  if (tcp) {
1790  DPRINTF(EthernetDesc,
1791  "TSO: Modifying TCP header. old seq %d + %d\n",
1792  tcp->seq(), tsoPrevSeq);
1793  tcp->seq(tcp->seq() + tsoPrevSeq);
1794  if (tsoUsedLen != tsoTotalLen)
1795  tcp->flags(tcp->flags() & ~9); // clear fin & psh
1796  }
1797  UdpPtr udp = ip ? UdpPtr(ip) : UdpPtr(ip6);
1798  if (udp) {
1799  DPRINTF(EthernetDesc, "TSO: Modifying UDP header.\n");
1800  udp->len(pktPtr->length - EthPtr(pktPtr)->size());
1801  }
1802  tsoPrevSeq = tsoUsedLen;
1803  }
1804 
1805  if (debug::EthernetDesc) {
1806  IpPtr ip(pktPtr);
1807  if (ip)
1808  DPRINTF(EthernetDesc, "Proccesing Ip packet with Id=%d\n",
1809  ip->id());
1810  else
1811  DPRINTF(EthernetSM, "Proccesing Non-Ip packet\n");
1812  }
1813 
1814  // Checksums are only ofloaded for new descriptor types
1815  if (txd_op::isData(desc) && (txd_op::ixsm(desc) || txd_op::txsm(desc))) {
1816  DPRINTF(EthernetDesc, "Calculating checksums for packet\n");
1817  IpPtr ip(pktPtr);
1818  Ip6Ptr ip6(pktPtr);
1819  assert(ip || ip6);
1820  if (ip && txd_op::ixsm(desc)) {
1821  ip->sum(0);
1822  ip->sum(cksum(ip));
1823  igbe->etherDeviceStats.txIpChecksums++;
1824  DPRINTF(EthernetDesc, "Calculated IP checksum\n");
1825  }
1826  if (txd_op::txsm(desc)) {
1827  TcpPtr tcp = ip ? TcpPtr(ip) : TcpPtr(ip6);
1828  UdpPtr udp = ip ? UdpPtr(ip) : UdpPtr(ip6);
1829  if (tcp) {
1830  tcp->sum(0);
1831  tcp->sum(cksum(tcp));
1832  igbe->etherDeviceStats.txTcpChecksums++;
1833  DPRINTF(EthernetDesc, "Calculated TCP checksum\n");
1834  } else if (udp) {
1835  assert(udp);
1836  udp->sum(0);
1837  udp->sum(cksum(udp));
1838  igbe->etherDeviceStats.txUdpChecksums++;
1839  DPRINTF(EthernetDesc, "Calculated UDP checksum\n");
1840  } else {
1841  panic("Told to checksum, but don't know how\n");
1842  }
1843  }
1844  }
1845 
1846  if (txd_op::ide(desc)) {
1847  // Deal with the rx timer interrupts
1848  DPRINTF(EthernetDesc, "Descriptor had IDE set\n");
1849  if (igbe->regs.tidv.idv()) {
1850  Tick delay = igbe->regs.tidv.idv() * igbe->intClock();
1851  DPRINTF(EthernetDesc, "setting tidv\n");
1852  igbe->reschedule(igbe->tidvEvent, curTick() + delay, true);
1853  }
1854 
1855  if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) {
1856  Tick delay = igbe->regs.tadv.idv() * igbe->intClock();
1857  DPRINTF(EthernetDesc, "setting tadv\n");
1858  if (!igbe->tadvEvent.scheduled()) {
1859  igbe->schedule(igbe->tadvEvent, curTick() + delay);
1860  }
1861  }
1862  }
1863 
1864 
1865  if (!useTso || txd_op::getLen(desc) == tsoDescBytesUsed) {
1866  DPRINTF(EthernetDesc, "Descriptor Done\n");
1867  unusedCache.pop_front();
1868  usedCache.push_back(desc);
1869  tsoDescBytesUsed = 0;
1870  }
1871 
1872  if (useTso && tsoUsedLen == tsoTotalLen)
1873  useTso = false;
1874 
1875 
1876  DPRINTF(EthernetDesc,
1877  "------Packet of %d bytes ready for transmission-------\n",
1878  pktPtr->length);
1879  pktDone = true;
1880  pktWaiting = false;
1881  pktPtr = NULL;
1882  tsoPktHasHeader = false;
1883 
1884  if (igbe->regs.txdctl.wthresh() == 0) {
1885  DPRINTF(EthernetDesc, "WTHRESH == 0, writing back descriptor\n");
1886  writeback(0);
1887  } else if (!igbe->regs.txdctl.gran() && igbe->regs.txdctl.wthresh() <=
1888  descInBlock(usedCache.size())) {
1889  DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");
1890  writeback((igbe->cacheBlockSize()-1)>>4);
1891  } else if (igbe->regs.txdctl.wthresh() <= usedCache.size()) {
1892  DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");
1893  writeback((igbe->cacheBlockSize()-1)>>4);
1894  }
1895 
1896  enableSm();
1897  igbe->checkDrain();
1898 }
1899 
1900 void
1902 {
1903  DPRINTF(EthernetDesc, "actionAfterWb() completionEnabled: %d\n",
1904  completionEnabled);
1905  igbe->postInterrupt(igbreg::IT_TXDW);
1906  if (completionEnabled) {
1907  descEnd = igbe->regs.tdh();
1908  DPRINTF(EthernetDesc,
1909  "Completion writing back value: %d to addr: %#x\n", descEnd,
1910  completionAddress);
1911  igbe->dmaWrite(pciToDma(mbits(completionAddress, 63, 2)),
1912  sizeof(descEnd), &nullEvent, (uint8_t*)&descEnd, 0);
1913  }
1914 }
1915 
1916 void
1918 {
1920 
1921  SERIALIZE_SCALAR(pktDone);
1922  SERIALIZE_SCALAR(isTcp);
1923  SERIALIZE_SCALAR(pktWaiting);
1924  SERIALIZE_SCALAR(pktMultiDesc);
1925 
1926  SERIALIZE_SCALAR(useTso);
1927  SERIALIZE_SCALAR(tsoHeaderLen);
1928  SERIALIZE_SCALAR(tsoMss);
1929  SERIALIZE_SCALAR(tsoTotalLen);
1930  SERIALIZE_SCALAR(tsoUsedLen);
1931  SERIALIZE_SCALAR(tsoPrevSeq);;
1932  SERIALIZE_SCALAR(tsoPktPayloadBytes);
1933  SERIALIZE_SCALAR(tsoLoadedHeader);
1934  SERIALIZE_SCALAR(tsoPktHasHeader);
1935  SERIALIZE_ARRAY(tsoHeader, 256);
1936  SERIALIZE_SCALAR(tsoDescBytesUsed);
1937  SERIALIZE_SCALAR(tsoCopyBytes);
1938  SERIALIZE_SCALAR(tsoPkts);
1939 
1940  SERIALIZE_SCALAR(completionAddress);
1941  SERIALIZE_SCALAR(completionEnabled);
1942  SERIALIZE_SCALAR(descEnd);
1943 }
1944 
1945 void
1947 {
1949 
1950  UNSERIALIZE_SCALAR(pktDone);
1951  UNSERIALIZE_SCALAR(isTcp);
1952  UNSERIALIZE_SCALAR(pktWaiting);
1953  UNSERIALIZE_SCALAR(pktMultiDesc);
1954 
1955  UNSERIALIZE_SCALAR(useTso);
1956  UNSERIALIZE_SCALAR(tsoHeaderLen);
1957  UNSERIALIZE_SCALAR(tsoMss);
1958  UNSERIALIZE_SCALAR(tsoTotalLen);
1959  UNSERIALIZE_SCALAR(tsoUsedLen);
1960  UNSERIALIZE_SCALAR(tsoPrevSeq);;
1961  UNSERIALIZE_SCALAR(tsoPktPayloadBytes);
1962  UNSERIALIZE_SCALAR(tsoLoadedHeader);
1963  UNSERIALIZE_SCALAR(tsoPktHasHeader);
1964  UNSERIALIZE_ARRAY(tsoHeader, 256);
1965  UNSERIALIZE_SCALAR(tsoDescBytesUsed);
1966  UNSERIALIZE_SCALAR(tsoCopyBytes);
1967  UNSERIALIZE_SCALAR(tsoPkts);
1968 
1969  UNSERIALIZE_SCALAR(completionAddress);
1970  UNSERIALIZE_SCALAR(completionEnabled);
1971  UNSERIALIZE_SCALAR(descEnd);
1972 }
1973 
1974 bool
1976 {
1977  if (pktDone) {
1978  pktDone = false;
1979  return true;
1980  }
1981  return false;
1982 }
1983 
1984 void
1986 {
1987  if (igbe->drainState() != DrainState::Draining) {
1988  igbe->txTick = true;
1989  igbe->restartClock();
1990  }
1991 }
1992 
1993 bool
1995 {
1996  return pktEvent.scheduled() || wbEvent.scheduled() ||
1997  fetchEvent.scheduled();
1998 }
1999 
2000 
2002 
2003 void
2005 {
2006  if (!tickEvent.scheduled() && (rxTick || txTick || txFifoTick) &&
2009 }
2010 
2011 DrainState
2013 {
2014  unsigned int count(0);
2017  count++;
2018  }
2019 
2020  txFifoTick = false;
2021  txTick = false;
2022  rxTick = false;
2023 
2024  if (tickEvent.scheduled())
2026 
2027  if (count) {
2028  DPRINTF(Drain, "IGbE not drained\n");
2029  return DrainState::Draining;
2030  } else
2031  return DrainState::Drained;
2032 }
2033 
2034 void
2036 {
2038 
2039  txFifoTick = true;
2040  txTick = true;
2041  rxTick = true;
2042 
2043  restartClock();
2044  DPRINTF(EthernetSM, "resuming from drain");
2045 }
2046 
2047 void
2049 {
2051  return;
2052 
2053  txFifoTick = false;
2054  txTick = false;
2055  rxTick = false;
2058  DPRINTF(Drain, "IGbE done draining, processing drain event\n");
2059  signalDrainDone();
2060  }
2061 }
2062 
2063 void
2065 {
2066  if (!regs.tctl.en()) {
2067  txTick = false;
2068  DPRINTF(EthernetSM, "TXS: TX disabled, stopping ticking\n");
2069  return;
2070  }
2071 
2072  // If we have a packet available and it's length is not 0 (meaning it's not
2073  // a multidescriptor packet) put it in the fifo, otherwise an the next
2074  // iteration we'll get the rest of the data
2076  && !txDescCache.packetMultiDesc() && txPacket->length) {
2077  DPRINTF(EthernetSM, "TXS: packet placed in TX FIFO\n");
2078 #ifndef NDEBUG
2079  bool success =
2080 #endif
2081  txFifo.push(txPacket);
2083  assert(success);
2084  txPacket = NULL;
2086  return;
2087  }
2088 
2089  // Only support descriptor granularity
2090  if (regs.txdctl.lwthresh() &&
2091  txDescCache.descLeft() < (regs.txdctl.lwthresh() * 8)) {
2092  DPRINTF(EthernetSM, "TXS: LWTHRESH caused posting of TXDLOW\n");
2094  }
2095 
2096  if (!txPacket) {
2097  txPacket = std::make_shared<EthPacketData>(16384);
2098  }
2099 
2100  if (!txDescCache.packetWaiting()) {
2101  if (txDescCache.descLeft() == 0) {
2105  DPRINTF(EthernetSM, "TXS: No descriptors left in ring, forcing "
2106  "writeback stopping ticking and posting TXQE\n");
2107  txTick = false;
2108  return;
2109  }
2110 
2111 
2112  if (!(txDescCache.descUnused())) {
2114  DPRINTF(EthernetSM, "TXS: No descriptors available in cache, "
2115  "fetching and stopping ticking\n");
2116  txTick = false;
2117  return;
2118  }
2119 
2120 
2122  if (txDescCache.packetWaiting()) {
2123  DPRINTF(EthernetSM,
2124  "TXS: Fetching TSO header, stopping ticking\n");
2125  txTick = false;
2126  return;
2127  }
2128 
2129  unsigned size = txDescCache.getPacketSize(txPacket);
2130  if (size > 0 && txFifo.avail() > size) {
2131  DPRINTF(EthernetSM, "TXS: Reserving %d bytes in FIFO and "
2132  "beginning DMA of next packet\n", size);
2133  txFifo.reserve(size);
2135  } else if (size == 0) {
2136  DPRINTF(EthernetSM, "TXS: getPacketSize returned: %d\n", size);
2137  DPRINTF(EthernetSM,
2138  "TXS: No packets to get, writing back used descriptors\n");
2140  } else {
2141  DPRINTF(EthernetSM, "TXS: FIFO full, stopping ticking until space "
2142  "available in FIFO\n");
2143  txTick = false;
2144  }
2145 
2146 
2147  return;
2148  }
2149  DPRINTF(EthernetSM, "TXS: Nothing to do, stopping ticking\n");
2150  txTick = false;
2151 }
2152 
2153 bool
2155 {
2156  etherDeviceStats.rxBytes += pkt->length;
2158 
2159  DPRINTF(Ethernet, "RxFIFO: Receiving pcakte from wire\n");
2160 
2161 
2162  if (!regs.rctl.en()) {
2163  DPRINTF(Ethernet, "RxFIFO: RX not enabled, dropping\n");
2164  return true;
2165  }
2166 
2167  // restart the state machines if they are stopped
2168  rxTick = true && drainState() != DrainState::Draining;
2169  if ((rxTick || txTick) && !tickEvent.scheduled()) {
2170  DPRINTF(EthernetSM,
2171  "RXS: received packet into fifo, starting ticking\n");
2172  restartClock();
2173  }
2174 
2175  if (!rxFifo.push(pkt)) {
2176  DPRINTF(Ethernet, "RxFIFO: Packet won't fit in fifo... dropped\n");
2177  postInterrupt(IT_RXO, true);
2178  return false;
2179  }
2180 
2181  return true;
2182 }
2183 
2184 
2185 void
2187 {
2188  if (!regs.rctl.en()) {
2189  rxTick = false;
2190  DPRINTF(EthernetSM, "RXS: RX disabled, stopping ticking\n");
2191  return;
2192  }
2193 
2194  // If the packet is done check for interrupts/descriptors/etc
2195  if (rxDescCache.packetDone()) {
2196  rxDmaPacket = false;
2197  DPRINTF(EthernetSM, "RXS: Packet completed DMA to memory\n");
2198  int descLeft = rxDescCache.descLeft();
2199  DPRINTF(EthernetSM, "RXS: descLeft: %d rdmts: %d rdlen: %d\n",
2200  descLeft, regs.rctl.rdmts(), regs.rdlen());
2201 
2202  // rdmts 2->1/8, 1->1/4, 0->1/2
2203  int ratio = (1ULL << (regs.rctl.rdmts() + 1));
2204  if (descLeft * ratio <= regs.rdlen()) {
2205  DPRINTF(Ethernet, "RXS: Interrupting (RXDMT) "
2206  "because of descriptors left\n");
2208  }
2209 
2210  if (rxFifo.empty())
2212 
2213  if (descLeft == 0) {
2215  DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing"
2216  " writeback and stopping ticking\n");
2217  rxTick = false;
2218  }
2219 
2220  // only support descriptor granulaties
2221  assert(regs.rxdctl.gran());
2222 
2223  if (regs.rxdctl.wthresh() >= rxDescCache.descUsed()) {
2224  DPRINTF(EthernetSM,
2225  "RXS: Writing back because WTHRESH >= descUsed\n");
2226  if (regs.rxdctl.wthresh() < (cacheBlockSize()>>4))
2227  rxDescCache.writeback(regs.rxdctl.wthresh()-1);
2228  else
2230  }
2231 
2232  if ((rxDescCache.descUnused() < regs.rxdctl.pthresh()) &&
2234  regs.rxdctl.hthresh())) {
2235  DPRINTF(EthernetSM, "RXS: Fetching descriptors because "
2236  "descUnused < PTHRESH\n");
2238  }
2239 
2240  if (rxDescCache.descUnused() == 0) {
2242  DPRINTF(EthernetSM, "RXS: No descriptors available in cache, "
2243  "fetching descriptors and stopping ticking\n");
2244  rxTick = false;
2245  }
2246  return;
2247  }
2248 
2249  if (rxDmaPacket) {
2250  DPRINTF(EthernetSM,
2251  "RXS: stopping ticking until packet DMA completes\n");
2252  rxTick = false;
2253  return;
2254  }
2255 
2256  if (!rxDescCache.descUnused()) {
2258  DPRINTF(EthernetSM, "RXS: No descriptors available in cache, "
2259  "stopping ticking\n");
2260  rxTick = false;
2261  DPRINTF(EthernetSM, "RXS: No descriptors available, fetching\n");
2262  return;
2263  }
2264 
2265  if (rxFifo.empty()) {
2266  DPRINTF(EthernetSM, "RXS: RxFIFO empty, stopping ticking\n");
2267  rxTick = false;
2268  return;
2269  }
2270 
2271  EthPacketPtr pkt;
2272  pkt = rxFifo.front();
2273 
2274 
2276  DPRINTF(EthernetSM, "RXS: Writing packet into memory\n");
2277  if (pktOffset == pkt->length) {
2278  DPRINTF(EthernetSM, "RXS: Removing packet from FIFO\n");
2279  pktOffset = 0;
2280  rxFifo.pop();
2281  }
2282 
2283  DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n");
2284  rxTick = false;
2285  rxDmaPacket = true;
2286 }
2287 
2288 void
2290 {
2291  txFifoTick = false;
2292 
2293  if (txFifo.empty())
2294  return;
2295 
2296 
2297  if (etherInt->sendPacket(txFifo.front())) {
2298  if (debug::EthernetSM) {
2299  IpPtr ip(txFifo.front());
2300  if (ip)
2301  DPRINTF(EthernetSM, "Transmitting Ip packet with Id=%d\n",
2302  ip->id());
2303  else
2304  DPRINTF(EthernetSM, "Transmitting Non-Ip packet\n");
2305  }
2306  DPRINTF(EthernetSM,
2307  "TxFIFO: Successful transmit, bytes available in fifo: %d\n",
2308  txFifo.avail());
2309 
2310  etherDeviceStats.txBytes += txFifo.front()->length;
2312 
2313  txFifo.pop();
2314  }
2315 }
2316 
2317 void
2319 {
2320  DPRINTF(EthernetSM, "IGbE: -------------- Cycle --------------\n");
2321 
2322  inTick = true;
2323 
2324  if (rxTick)
2325  rxStateMachine();
2326 
2327  if (txTick)
2328  txStateMachine();
2329 
2330  // If txWire returns and txFifoTick is still set, that means the data we
2331  // sent to the other end was already accepted and we can send another
2332  // frame right away. This is consistent with the previous behavior which
2333  // would send another frame if one was ready in ethTxDone. This version
2334  // avoids growing the stack with each frame sent which can cause stack
2335  // overflow.
2336  while (txFifoTick)
2337  txWire();
2338 
2339  if (rxTick || txTick || txFifoTick)
2341 
2342  inTick = false;
2343 }
2344 
2345 void
2347 {
2348  // restart the tx state machines if they are stopped
2349  // fifo to send another packet
2350  // tx sm to put more data into the fifo
2353  txTick = true;
2354 
2355  if (!inTick)
2356  restartClock();
2357  DPRINTF(EthernetSM, "TxFIFO: Transmission complete\n");
2358 }
2359 
2360 void
2362 {
2364 
2365  regs.serialize(cp);
2373 
2374  rxFifo.serialize("rxfifo", cp);
2375  txFifo.serialize("txfifo", cp);
2376 
2377  bool txPktExists = txPacket != nullptr;
2378  SERIALIZE_SCALAR(txPktExists);
2379  if (txPktExists)
2380  txPacket->serialize("txpacket", cp);
2381 
2382  Tick rdtr_time = 0, radv_time = 0, tidv_time = 0, tadv_time = 0,
2383  inter_time = 0;
2384 
2385  if (rdtrEvent.scheduled())
2386  rdtr_time = rdtrEvent.when();
2387  SERIALIZE_SCALAR(rdtr_time);
2388 
2389  if (radvEvent.scheduled())
2390  radv_time = radvEvent.when();
2391  SERIALIZE_SCALAR(radv_time);
2392 
2393  if (tidvEvent.scheduled())
2394  tidv_time = tidvEvent.when();
2395  SERIALIZE_SCALAR(tidv_time);
2396 
2397  if (tadvEvent.scheduled())
2398  tadv_time = tadvEvent.when();
2399  SERIALIZE_SCALAR(tadv_time);
2400 
2401  if (interEvent.scheduled())
2402  inter_time = interEvent.when();
2403  SERIALIZE_SCALAR(inter_time);
2404 
2406 
2407  txDescCache.serializeSection(cp, "TxDescCache");
2408  rxDescCache.serializeSection(cp, "RxDescCache");
2409 }
2410 
2411 void
2413 {
2415 
2416  regs.unserialize(cp);
2424 
2425  rxFifo.unserialize("rxfifo", cp);
2426  txFifo.unserialize("txfifo", cp);
2427 
2428  bool txPktExists;
2429  UNSERIALIZE_SCALAR(txPktExists);
2430  if (txPktExists) {
2431  txPacket = std::make_shared<EthPacketData>(16384);
2432  txPacket->unserialize("txpacket", cp);
2433  }
2434 
2435  rxTick = true;
2436  txTick = true;
2437  txFifoTick = true;
2438 
2439  Tick rdtr_time, radv_time, tidv_time, tadv_time, inter_time;
2440  UNSERIALIZE_SCALAR(rdtr_time);
2441  UNSERIALIZE_SCALAR(radv_time);
2442  UNSERIALIZE_SCALAR(tidv_time);
2443  UNSERIALIZE_SCALAR(tadv_time);
2444  UNSERIALIZE_SCALAR(inter_time);
2445 
2446  if (rdtr_time)
2447  schedule(rdtrEvent, rdtr_time);
2448 
2449  if (radv_time)
2450  schedule(radvEvent, radv_time);
2451 
2452  if (tidv_time)
2453  schedule(tidvEvent, tidv_time);
2454 
2455  if (tadv_time)
2456  schedule(tadvEvent, tadv_time);
2457 
2458  if (inter_time)
2459  schedule(interEvent, inter_time);
2460 
2462 
2463  txDescCache.unserializeSection(cp, "TxDescCache");
2464  rxDescCache.unserializeSection(cp, "RxDescCache");
2465 }
2466 
2467 } // namespace gem5
gem5::igbreg::RXDS_IPCS
const uint16_t RXDS_IPCS
Definition: i8254xGBe_defs.hh:131
gem5::igbreg::Regs::rctl
RCTL rctl
Definition: i8254xGBe_defs.hh:532
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:252
gem5::MipsISA::ip6
Bitfield< 14 > ip6
Definition: pra_constants.hh:190
gem5::unserialize
void unserialize(ThreadContext &tc, CheckpointIn &cp)
Definition: thread_context.cc:206
gem5::igbreg::REG_FCT
const uint32_t REG_FCT
Definition: i8254xGBe_defs.hh:51
gem5::IGbE::TxDescCache::getPacketData
void getPacketData(EthPacketPtr p)
Definition: i8254xGBe.cc:1658
gem5::Event::when
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:508
gem5::ArmISA::ide
Bitfield< 15 > ide
Definition: misc_types.hh:443
gem5::igbreg::Regs::TCTL
Definition: i8254xGBe_defs.hh:542
gem5::igbreg::txd_op::mss
int mss(TxDesc *d)
Definition: i8254xGBe_defs.hh:292
gem5::igbreg::REG_RDTR
const uint32_t REG_RDTR
Definition: i8254xGBe_defs.hh:75
gem5::IGbE::read
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: i8254xGBe.cc:170
gem5::igbreg::txd_op::isContext
bool isContext(TxDesc *d)
Definition: i8254xGBe_defs.hh:256
gem5::IGbE
Definition: i8254xGBe.hh:60
gem5::igbreg::RxDesc::adv_read
struct gem5::igbreg::RxDesc::@79::@82 adv_read
gem5::igbreg::REG_CRCERRS
const uint32_t REG_CRCERRS
Definition: i8254xGBe_defs.hh:90
gem5::igbreg::REG_PBA
const uint32_t REG_PBA
Definition: i8254xGBe_defs.hh:53
warn
#define warn(...)
Definition: logging.hh:245
gem5::igbreg::Regs::tadv
TADV tadv
Definition: i8254xGBe_defs.hh:747
gem5::igbreg::REG_WUFC
const uint32_t REG_WUFC
Definition: i8254xGBe_defs.hh:100
gem5::igbreg::REG_MTA
const uint32_t REG_MTA
Definition: i8254xGBe_defs.hh:94
gem5::igbreg::Regs::imr
uint32_t imr
Definition: i8254xGBe_defs.hh:481
gem5::igbreg::REG_VFTA
const uint32_t REG_VFTA
Definition: i8254xGBe_defs.hh:97
gem5::igbreg::Regs::pba
PBA pba
Definition: i8254xGBe_defs.hh:567
gem5::igbreg::Regs::txdctl
TXDCTL txdctl
Definition: i8254xGBe_defs.hh:739
gem5::igbreg::RxDesc::legacy
struct gem5::igbreg::RxDesc::@79::@81 legacy
system.hh
gem5::igbreg::RXDP_UDP
const uint16_t RXDP_UDP
Definition: i8254xGBe_defs.hh:169
gem5::igbreg::REG_RXDCTL
const uint32_t REG_RXDCTL
Definition: i8254xGBe_defs.hh:76
gem5::igbreg::REG_SWSM
const uint32_t REG_SWSM
Definition: i8254xGBe_defs.hh:103
i8254xGBe.hh
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
gem5::IGbE::writeConfig
Tick writeConfig(PacketPtr pkt) override
Write to the PCI config space data that is stored locally.
Definition: i8254xGBe.cc:151
gem5::Drainable::drainState
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:324
gem5::PciDevice::serialize
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
Definition: device.cc:401
gem5::DmaDevice::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: dma_device.cc:363
gem5::igbreg::RXDE_TCPE
const uint8_t RXDE_TCPE
Definition: i8254xGBe_defs.hh:142
gem5::igbreg::REG_CTRL
const uint32_t REG_CTRL
Definition: i8254xGBe_defs.hh:43
gem5::igbreg::TxDesc
Definition: i8254xGBe_defs.hh:236
gem5::IGbE::postInterrupt
void postInterrupt(igbreg::IntTypes t, bool now=false)
Write an interrupt into the interrupt pending register and check mask and interrupt limit timer befor...
Definition: i8254xGBe.cc:695
gem5::EEPROM_SIZE
const uint8_t EEPROM_SIZE
Definition: ns_gige.hh:56
gem5::PciDevice::unserialize
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Definition: device.cc:464
gem5::igbreg::txd_op::eop
bool eop(TxDesc *d)
Definition: i8254xGBe_defs.hh:276
gem5::IGbE::inTick
bool inTick
Definition: i8254xGBe.hh:81
gem5::networking::cksum
uint16_t cksum(const IpPtr &ptr)
Definition: inet.cc:208
gem5::ArmISA::writeback
Bitfield< 21 > writeback
Definition: types.hh:126
gem5::IGbE::rxDmaPacket
bool rxDmaPacket
Definition: i8254xGBe.hh:86
gem5::igbreg::Regs::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: i8254xGBe_defs.hh:854
gem5::igbreg::REG_TDWBAL
const uint32_t REG_TDWBAL
Definition: i8254xGBe_defs.hh:88
gem5::IGbE::TxDescCache::completionWriteback
void completionWriteback(Addr a, bool enabled)
Definition: i8254xGBe.hh:455
gem5::igbreg::Regs::ctrl
CTRL ctrl
Definition: i8254xGBe_defs.hh:370
gem5::IGbE::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: i8254xGBe.cc:2412
gem5::IGbE::DescCache::areaChanged
void areaChanged()
If the address/len/head change when we've got descriptors that are dirty that is very bad.
Definition: i8254xGBe.cc:848
gem5::igbreg::Regs::fcrth
FCRTH fcrth
Definition: i8254xGBe_defs.hh:587
gem5::igbreg::REG_TIDV
const uint32_t REG_TIDV
Definition: i8254xGBe_defs.hh:85
gem5::networking::hsplit
int hsplit(const EthPacketPtr &ptr)
Definition: inet.cc:386
gem5::igbreg::REG_RLPML
const uint32_t REG_RLPML
Definition: i8254xGBe_defs.hh:92
gem5::igbreg::IT_TXDW
@ IT_TXDW
Definition: i8254xGBe_defs.hh:177
gem5::IGbE::cpuClearInt
void cpuClearInt()
Clear the interupt line to the cpu.
Definition: i8254xGBe.cc:779
gem5::igbreg::txd_op::isData
bool isData(TxDesc *d)
Definition: i8254xGBe_defs.hh:257
gem5::CheckpointIn
Definition: serialize.hh:68
gem5::igbreg::VLAN_FILTER_TABLE_SIZE
const uint8_t VLAN_FILTER_TABLE_SIZE
Definition: i8254xGBe_defs.hh:112
gem5::igbreg::REG_IAM
const uint32_t REG_IAM
Definition: i8254xGBe_defs.hh:59
gem5::PciDevice::pioDelay
Tick pioDelay
Definition: device.hh:354
gem5::igbreg::Regs::fcttv
FCTTV fcttv
Definition: i8254xGBe_defs.hh:540
gem5::IGbE::TxDescCache::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: i8254xGBe.cc:1946
gem5::Serializable::serializeSection
void serializeSection(CheckpointOut &cp, const char *name) const
Serialize an object into a new section.
Definition: serialize.cc:74
gem5::igbreg::REG_ICS
const uint32_t REG_ICS
Definition: i8254xGBe_defs.hh:56
gem5::ArmISA::err
Bitfield< 6 > err
Definition: misc_types.hh:750
gem5::networking::Ip6Ptr
Definition: inet.hh:487
gem5::igbreg::Regs::mdic
MDIC mdic
Definition: i8254xGBe_defs.hh:455
gem5::IGbE::DescCache
Definition: i8254xGBe.hh:181
gem5::igbreg::REG_RCTL
const uint32_t REG_RCTL
Definition: i8254xGBe_defs.hh:60
gem5::IGbE::RxDescCache::pktSplitDone
void pktSplitDone()
Definition: i8254xGBe.cc:1164
gem5::X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:775
gem5::igbreg::txd_op::isType
bool isType(TxDesc *d, uint8_t type)
Definition: i8254xGBe_defs.hh:253
gem5::igbreg::REG_RADV
const uint32_t REG_RADV
Definition: i8254xGBe_defs.hh:77
gem5::igbreg::RCV_ADDRESS_TABLE_SIZE
const uint8_t RCV_ADDRESS_TABLE_SIZE
Definition: i8254xGBe_defs.hh:113
gem5::igbreg::RxDesc
Definition: i8254xGBe_defs.hh:194
gem5::IGbE::DescCache::writeback
void writeback(Addr aMask)
Definition: i8254xGBe.cc:858
gem5::igbreg::Regs::sw_fw_sync
uint32_t sw_fw_sync
Definition: i8254xGBe_defs.hh:852
gem5::EtherInt::sendPacket
bool sendPacket(EthPacketPtr packet)
Definition: etherint.hh:73
gem5::igbreg::Regs::tdlen
TDLEN tdlen
Definition: i8254xGBe_defs.hh:688
gem5::IGbE::RxDescCache::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: i8254xGBe.cc:1486
gem5::igbreg::EEPROM_CSUM
const uint16_t EEPROM_CSUM
Definition: i8254xGBe_defs.hh:110
gem5::EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
gem5::PciDevice::intrClear
void intrClear()
Definition: device.hh:365
gem5::igbreg::REG_EECD
const uint32_t REG_EECD
Definition: i8254xGBe_defs.hh:45
gem5::csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
gem5::Packet::makeAtomicResponse
void makeAtomicResponse()
Definition: packet.hh:1043
gem5::igbreg::REG_RDT
const uint32_t REG_RDT
Definition: i8254xGBe_defs.hh:74
gem5::igbreg::REG_IVAR0
const uint32_t REG_IVAR0
Definition: i8254xGBe_defs.hh:66
gem5::mbits
constexpr T mbits(T val, unsigned first, unsigned last)
Mask off the given bits in place like bits() but without shifting.
Definition: bitfield.hh:103
gem5::IGbE::drainResume
void drainResume() override
Resume execution after a successful drain.
Definition: i8254xGBe.cc:2035
gem5::IGbE::drain
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
Definition: i8254xGBe.cc:2012
gem5::EtherDevice
Definition: etherdevice.hh:48
gem5::htobe
T htobe(T value)
Definition: byteswap.hh:174
gem5::IGbE::chkInterrupt
void chkInterrupt()
Check and see if changes to the mask register have caused an interrupt to need to be sent or perhaps ...
Definition: i8254xGBe.cc:791
gem5::igbreg::txd_op::TXD_CNXT
const uint8_t TXD_CNXT
Definition: i8254xGBe_defs.hh:246
gem5::igbreg::RXDEE_TCPE
const uint16_t RXDEE_TCPE
Definition: i8254xGBe_defs.hh:154
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:66
gem5::igbreg::txd_op::TXD_ADVDATA
const uint8_t TXD_ADVDATA
Definition: i8254xGBe_defs.hh:249
gem5::IGbE::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: i8254xGBe.cc:143
gem5::IGbE::~IGbE
~IGbE()
Definition: i8254xGBe.cc:131
gem5::igbreg::txd_op::setDd
void setDd(TxDesc *d)
Definition: i8254xGBe_defs.hh:261
gem5::igbreg::Regs::rdh
RDH rdh
Definition: i8254xGBe_defs.hh:625
gem5::igbreg::REG_FCAL
const uint32_t REG_FCAL
Definition: i8254xGBe_defs.hh:49
IN_RANGE
#define IN_RANGE(val, base, len)
Definition: i8254xGBe.cc:167
PCI_DEVICE_SPECIFIC
#define PCI_DEVICE_SPECIFIC
Definition: pcireg.h:164
gem5::igbreg::IT_TXDLOW
@ IT_TXDLOW
Definition: i8254xGBe_defs.hh:188
gem5::IGbE::eeOpBits
int eeOpBits
Definition: i8254xGBe.hh:69
gem5::IGbE::IGbE
IGbE(const Params &params)
Definition: i8254xGBe.cc:61
gem5::igbreg::Regs::tdba
TDBA tdba
Definition: i8254xGBe_defs.hh:680
gem5::IGbE::TxDescCache::packetAvailable
bool packetAvailable()
Ask if the packet has been transfered so the state machine can give it to the fifo.
Definition: i8254xGBe.cc:1975
gem5::igbreg::Regs::eecd
EECD eecd
Definition: i8254xGBe_defs.hh:408
gem5::PciDevice::configDelay
Tick configDelay
Definition: device.hh:355
gem5::IGbE::DescCache::DescCache
DescCache(IGbE *i, const std::string n, int s)
Definition: i8254xGBe.cc:826
gem5::mask
constexpr uint64_t mask(unsigned nbits)
Generate a 64-bit mask of 'nbits' 1s, right justified.
Definition: bitfield.hh:63
gem5::igbreg::IT_RXDMT
@ IT_RXDMT
Definition: i8254xGBe_defs.hh:181
packet.hh
gem5::EtherDevice::EtherDeviceStats::txPackets
statistics::Scalar txPackets
Definition: etherdevice.hh:67
gem5::IGbE::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: i8254xGBe.cc:2361
gem5::igbreg::txd_op::getBuf
Addr getBuf(TxDesc *d)
Definition: i8254xGBe_defs.hh:259
gem5::IGbE::etherInt
IGbEInt * etherInt
Definition: i8254xGBe.hh:63
gem5::EtherDevice::EtherDeviceStats::postedInterrupts
statistics::Scalar postedInterrupts
Definition: etherdevice.hh:62
gem5::IGbE::TxDescCache::pktComplete
void pktComplete()
Called by event when dma to write packet is completed.
Definition: i8254xGBe.cc:1706
gem5::igbreg::REG_TXDCA_CTL
const uint32_t REG_TXDCA_CTL
Definition: i8254xGBe_defs.hh:83
gem5::Cycles
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:78
gem5::igbreg::Regs::radv
RADV radv
Definition: i8254xGBe_defs.hh:663
gem5::PacketFifo::unserialize
void unserialize(const std::string &base, CheckpointIn &cp)
Definition: pktfifo.cc:100
gem5::IGbE::RxDescCache::pktComplete
void pktComplete()
Called by event when dma to write packet is completed.
Definition: i8254xGBe.cc:1287
gem5::IGbE::DescCache::descUnused
unsigned descUnused() const
Definition: i8254xGBe.hh:288
gem5::PciDevice::writeConfig
virtual Tick writeConfig(PacketPtr pkt)
Write to the PCI config space data that is stored locally.
Definition: device.cc:283
stats.hh
gem5::IGbE::eeAddrBits
int eeAddrBits
Definition: i8254xGBe.hh:69
gem5::IGbE::TxDescCache::hasOutstandingEvents
bool hasOutstandingEvents() override
Definition: i8254xGBe.cc:1994
gem5::IGbE::restartClock
void restartClock()
This function is used to restart the clock so it can handle things like draining and resume in one pl...
Definition: i8254xGBe.cc:2004
gem5::igbreg::REG_STATUS
const uint32_t REG_STATUS
Definition: i8254xGBe_defs.hh:44
gem5::IGbE::macAddr
uint64_t macAddr
Definition: i8254xGBe.hh:140
gem5::IGbE::txStateMachine
void txStateMachine()
Definition: i8254xGBe.cc:2064
gem5::igbreg::Regs::rxdctl
RXDCTL rxdctl
Definition: i8254xGBe_defs.hh:655
gem5::igbreg::REG_ICR
const uint32_t REG_ICR
Definition: i8254xGBe_defs.hh:54
gem5::igbreg::Regs::tctl
TCTL tctl
Definition: i8254xGBe_defs.hh:558
gem5::DrainState
DrainState
Object drain/handover states.
Definition: drain.hh:74
gem5::igbreg::IntTypes
IntTypes
Definition: i8254xGBe_defs.hh:174
gem5::igbreg::REG_EERD
const uint32_t REG_EERD
Definition: i8254xGBe_defs.hh:46
gem5::IGbE::txDescCache
TxDescCache txDescCache
Definition: i8254xGBe.hh:476
gem5::igbreg::Regs::itr
ITR itr
Definition: i8254xGBe_defs.hh:490
gem5::igbreg::RXDP_IPV6
const uint16_t RXDP_IPV6
Definition: i8254xGBe_defs.hh:166
gem5::igbreg::REG_FCRTL
const uint32_t REG_FCRTL
Definition: i8254xGBe_defs.hh:67
gem5::PacketFifo::clear
void clear()
Definition: pktfifo.hh:152
gem5::IGbE::tadvEvent
EventFunctionWrapper tadvEvent
Definition: i8254xGBe.hh:124
gem5::igbreg::REG_TCTL
const uint32_t REG_TCTL
Definition: i8254xGBe_defs.hh:78
gem5::IGbE::eeOpcode
uint8_t eeOpcode
Definition: i8254xGBe.hh:70
gem5::IGbE::txPacket
EthPacketPtr txPacket
Definition: i8254xGBe.hh:78
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
gem5::Serializable::unserializeSection
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
Definition: serialize.cc:81
gem5::EthPacketPtr
std::shared_ptr< EthPacketData > EthPacketPtr
Definition: etherpkt.hh:90
gem5::SimObject::params
const Params & params() const
Definition: sim_object.hh:176
gem5::igbreg::REG_IMC
const uint32_t REG_IMC
Definition: i8254xGBe_defs.hh:58
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
gem5::X86ISA::count
count
Definition: misc.hh:709
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:283
gem5::igbreg::Regs::tdwba
uint64_t tdwba
Definition: i8254xGBe_defs.hh:758
gem5::networking::IpPtr
Definition: inet.hh:357
gem5::igbreg::REG_RDLEN
const uint32_t REG_RDLEN
Definition: i8254xGBe_defs.hh:71
gem5::igbreg::REG_FCTTV
const uint32_t REG_FCTTV
Definition: i8254xGBe_defs.hh:61
gem5::igbreg::REG_RDBAH
const uint32_t REG_RDBAH
Definition: i8254xGBe_defs.hh:70
gem5::EtherDevice::etherDeviceStats
gem5::EtherDevice::EtherDeviceStats etherDeviceStats
gem5::igbreg::txd_op::hdrlen
int hdrlen(TxDesc *d)
Definition: i8254xGBe_defs.hh:293
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
gem5::IGbE::TxDescCache::TxDescCache
TxDescCache(IGbE *i, std::string n, int s)
Definition: i8254xGBe.cc:1497
gem5::igbreg::RXDT_ADV_SPLIT_A
const uint8_t RXDT_ADV_SPLIT_A
Definition: i8254xGBe_defs.hh:161
gem5::IGbE::txFifoTick
bool txFifoTick
Definition: i8254xGBe.hh:84
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::DmaDevice::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: dma_device.cc:148
gem5::igbreg::EEPROM_RDSR_OPCODE_SPI
const uint8_t EEPROM_RDSR_OPCODE_SPI
Definition: i8254xGBe_defs.hh:108
gem5::IGbE::lastInterrupt
Tick lastInterrupt
Definition: i8254xGBe.hh:488
gem5::IGbE::TxDescCache::actionAfterWb
void actionAfterWb() override
Definition: i8254xGBe.cc:1901
gem5::igbreg::txd_op::txsm
bool txsm(TxDesc *d)
Definition: i8254xGBe_defs.hh:284
gem5::igbreg::Regs::tdh
TDH tdh
Definition: i8254xGBe_defs.hh:696
gem5::IGbE::RxDescCache::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: i8254xGBe.cc:1477
gem5::ArmISA::s
Bitfield< 4 > s
Definition: misc_types.hh:561
gem5::igbreg::PHY_GSTATUS
const uint8_t PHY_GSTATUS
Definition: i8254xGBe_defs.hh:122
gem5::statistics::reset
void reset()
Definition: statistics.cc:304
gem5::igbreg::REG_WUC
const uint32_t REG_WUC
Definition: i8254xGBe_defs.hh:99
gem5::igbreg::Regs::srrctl
SRRCTL srrctl
Definition: i8254xGBe_defs.hh:617
gem5::igbreg::REG_MANC
const uint32_t REG_MANC
Definition: i8254xGBe_defs.hh:102
gem5::igbreg::MULTICAST_TABLE_SIZE
const uint8_t MULTICAST_TABLE_SIZE
Definition: i8254xGBe_defs.hh:114
gem5::igbreg::txd_op::ixsm
bool ixsm(TxDesc *d)
Definition: i8254xGBe_defs.hh:283
gem5::igbreg::REG_FWSM
const uint32_t REG_FWSM
Definition: i8254xGBe_defs.hh:104
gem5::IGbE::write
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: i8254xGBe.cc:358
gem5::PciDevice::getBAR
bool getBAR(Addr addr, int &num, Addr &offs)
Which base address register (if any) maps the given address?
Definition: device.hh:320
gem5::DmaDevice::cacheBlockSize
unsigned int cacheBlockSize() const
Definition: dma_device.hh:245
gem5::ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:144
gem5::igbreg::REG_AIFS
const uint32_t REG_AIFS
Definition: i8254xGBe_defs.hh:63
gem5::DmaDevice::Params
DmaDeviceParams Params
Definition: dma_device.hh:209
gem5::igbreg::Regs::sts
STATUS sts
Definition: i8254xGBe_defs.hh:389
gem5::IGbE::RxDescCache::hasOutstandingEvents
bool hasOutstandingEvents() override
Definition: i8254xGBe.cc:1468
gem5::IGbE::RxDescCache::enableSm
void enableSm() override
Definition: i8254xGBe.cc:1449
gem5::igbreg::REG_RDBAL
const uint32_t REG_RDBAL
Definition: i8254xGBe_defs.hh:69
gem5::igbreg::REG_RDH
const uint32_t REG_RDH
Definition: i8254xGBe_defs.hh:73
gem5::bits
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:76
gem5::igbreg::REG_WUS
const uint32_t REG_WUS
Definition: i8254xGBe_defs.hh:101
gem5::igbreg::REG_ITR
const uint32_t REG_ITR
Definition: i8254xGBe_defs.hh:55
gem5::PacketFifo::front
EthPacketPtr front()
Definition: pktfifo.hh:121
gem5::IGbE::rxStateMachine
void rxStateMachine()
Definition: i8254xGBe.cc:2186
SERIALIZE_ARRAY
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:610
gem5::DrainState::Drained
@ Drained
Buffers drained, ready for serialization/handover.
gem5::igbreg::Regs::rxcsum
RXCSUM rxcsum
Definition: i8254xGBe_defs.hh:769
gem5::serialize
void serialize(const ThreadContext &tc, CheckpointOut &cp)
Thread context serialization helpers.
Definition: thread_context.cc:157
gem5::igbreg::EEPROM_SIZE
const uint8_t EEPROM_SIZE
Definition: i8254xGBe_defs.hh:109
gem5::IGbE::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: i8254xGBe.cc:137
gem5::igbreg::REG_LEDCTL
const uint32_t REG_LEDCTL
Definition: i8254xGBe_defs.hh:64
gem5::igbreg::REG_RFCTL
const uint32_t REG_RFCTL
Definition: i8254xGBe_defs.hh:93
gem5::igbreg::REG_TDLEN
const uint32_t REG_TDLEN
Definition: i8254xGBe_defs.hh:81
gem5::igbreg::RXDS_UDPCS
const uint16_t RXDS_UDPCS
Definition: i8254xGBe_defs.hh:133
gem5::igbreg::RXDE_IPE
const uint8_t RXDE_IPE
Definition: i8254xGBe_defs.hh:141
gem5::IGbE::DescCache::descUsed
unsigned descUsed() const
Definition: i8254xGBe.hh:285
gem5::ArmISA::t
Bitfield< 5 > t
Definition: misc_types.hh:70
gem5::networking::UdpHdr::len
uint16_t len() const
Definition: inet.hh:747
gem5::igbreg::RXDT_LEGACY
const uint8_t RXDT_LEGACY
Definition: i8254xGBe_defs.hh:159
gem5::igbreg::Regs::rlpml
uint32_t rlpml
Definition: i8254xGBe_defs.hh:771
gem5::igbreg::Regs::manc
MANC manc
Definition: i8254xGBe_defs.hh:822
gem5::PacketFifo::push
bool push(EthPacketPtr ptr)
Definition: pktfifo.hh:123
gem5::igbreg::EEPROM_READ_OPCODE_SPI
const uint8_t EEPROM_READ_OPCODE_SPI
Definition: i8254xGBe_defs.hh:107
gem5::statistics::size_type
unsigned int size_type
Definition: types.hh:60
gem5::igbreg::RXDT_ADV_ONEBUF
const uint8_t RXDT_ADV_ONEBUF
Definition: i8254xGBe_defs.hh:160
gem5::EtherDevice::EtherDeviceStats::rxBytes
statistics::Scalar rxBytes
Definition: etherdevice.hh:65
gem5::igbreg::Regs::rdtr
RDTR rdtr
Definition: i8254xGBe_defs.hh:642
gem5::igbreg::txd_op::ip
bool ip(TxDesc *d)
Definition: i8254xGBe_defs.hh:277
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::IGbE::tick
void tick()
Definition: i8254xGBe.cc:2318
gem5::igbreg::RXDP_IPV4
const uint16_t RXDP_IPV4
Definition: i8254xGBe_defs.hh:164
gem5::igbreg::Regs::icr
ICR icr
Definition: i8254xGBe_defs.hh:479
gem5::igbreg::IT_TXQE
@ IT_TXQE
Definition: i8254xGBe_defs.hh:178
gem5::igbreg::REG_SWFWSYNC
const uint32_t REG_SWFWSYNC
Definition: i8254xGBe_defs.hh:105
gem5::IGbE::regs
igbreg::Regs regs
Definition: i8254xGBe.hh:66
gem5::igbreg::IT_RXO
@ IT_RXO
Definition: i8254xGBe_defs.hh:182
name
const std::string & name()
Definition: trace.cc:49
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568
packet_access.hh
gem5::arrayParamOut
decltype(std::begin(std::declval< const T & >()), std::end(std::declval< const T & >()), void()) arrayParamOut(CheckpointOut &os, const std::string &name, const T &param)
Definition: serialize.hh:409
gem5::Clocked::clockEdge
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...
Definition: clocked_object.hh:177
gem5::EventManager::deschedule
void deschedule(Event &event)
Definition: eventq.hh:1028
gem5::igbreg::REG_TXDCTL
const uint32_t REG_TXDCTL
Definition: i8254xGBe_defs.hh:86
gem5::igbreg::REG_TADV
const uint32_t REG_TADV
Definition: i8254xGBe_defs.hh:87
gem5::IGbE::interEvent
EventFunctionWrapper interEvent
Definition: i8254xGBe.hh:163
gem5::IGbE::TxDescCache::packetMultiDesc
bool packetMultiDesc()
Ask if this packet is composed of multiple descriptors so even if we've got data, we need to wait for...
Definition: i8254xGBe.hh:444
gem5::IGbE::tidvEvent
EventFunctionWrapper tidvEvent
Definition: i8254xGBe.hh:133
gem5::IGbE::cpuPostInt
void cpuPostInt()
Definition: i8254xGBe.cc:735
gem5::Drainable::signalDrainDone
void signalDrainDone() const
Signal that an object is drained.
Definition: drain.hh:305
gem5::IGbE::TxDescCache::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: i8254xGBe.cc:1917
gem5::igbreg::REG_TDT
const uint32_t REG_TDT
Definition: i8254xGBe_defs.hh:84
gem5::igbreg::Regs::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: i8254xGBe_defs.hh:900
gem5::igbreg::REG_VET
const uint32_t REG_VET
Definition: i8254xGBe_defs.hh:52
gem5::igbreg::PHY_AGC
const uint8_t PHY_AGC
Definition: i8254xGBe_defs.hh:124
gem5::igbreg::Regs::ctrl_ext
CTRL_EXT ctrl_ext
Definition: i8254xGBe_defs.hh:441
gem5::igbreg::REG_TDWBAH
const uint32_t REG_TDWBAH
Definition: i8254xGBe_defs.hh:89
gem5::IGbE::checkDrain
void checkDrain()
Check if all the draining things that need to occur have occured and handle the drain event if so.
Definition: i8254xGBe.cc:2048
gem5::IGbE::TxDescCache::enableSm
void enableSm() override
Definition: i8254xGBe.cc:1985
gem5::IGbE::radvEvent
EventFunctionWrapper radvEvent
Definition: i8254xGBe.hh:114
gem5::IGbE::rxTick
bool rxTick
Definition: i8254xGBe.hh:82
gem5::igbreg::PHY_PID
const uint8_t PHY_PID
Definition: i8254xGBe_defs.hh:120
gem5::igbreg::Regs::fcrtl
FCRTL fcrtl
Definition: i8254xGBe_defs.hh:577
gem5::igbreg::REG_MDIC
const uint32_t REG_MDIC
Definition: i8254xGBe_defs.hh:48
gem5::RiscvISA::x
Bitfield< 3 > x
Definition: pagetable.hh:73
gem5::igbreg::IT_RXT
@ IT_RXT
Definition: i8254xGBe_defs.hh:183
gem5::IGbE::eeAddr
uint8_t eeAddr
Definition: i8254xGBe.hh:70
gem5::Drainable::drainResume
virtual void drainResume()
Resume execution after a successful drain.
Definition: drain.hh:293
gem5::igbreg::RXDS_DD
const uint16_t RXDS_DD
Definition: i8254xGBe_defs.hh:137
gem5::igbreg::REG_EICR
const uint32_t REG_EICR
Definition: i8254xGBe_defs.hh:65
gem5::Port
Ports are used to interface objects to each other.
Definition: port.hh:61
gem5::IGbE::pktOffset
unsigned pktOffset
Definition: i8254xGBe.hh:89
UNSERIALIZE_ARRAY
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:618
gem5::igbreg::PHY_PSTATUS
const uint8_t PHY_PSTATUS
Definition: i8254xGBe_defs.hh:119
gem5::IGbE::TxDescCache::processContextDesc
void processContextDesc()
Definition: i8254xGBe.cc:1518
gem5::ArmISA::n
Bitfield< 31 > n
Definition: misc_types.hh:455
gem5::IGbE::txWire
void txWire()
Definition: i8254xGBe.cc:2289
gem5::igbreg::STATS_REGS_SIZE
const uint32_t STATS_REGS_SIZE
Definition: i8254xGBe_defs.hh:115
gem5::IGbE::DescCache::descLeft
unsigned descLeft() const
Definition: i8254xGBe.hh:272
gem5::igbreg::txd_op::isLegacy
bool isLegacy(TxDesc *d)
Definition: i8254xGBe_defs.hh:251
gem5::igbreg::Regs::swsm
SWSM swsm
Definition: i8254xGBe_defs.hh:833
gem5::igbreg::RxDesc::adv_wb
struct gem5::igbreg::RxDesc::@79::@83 adv_wb
gem5::igbreg::txd_op::getLen
Addr getLen(TxDesc *d)
Definition: i8254xGBe_defs.hh:260
gem5::igbreg::REG_TDH
const uint32_t REG_TDH
Definition: i8254xGBe_defs.hh:82
gem5::EtherDevice::EtherDeviceStats::rxPackets
statistics::Scalar rxPackets
Definition: etherdevice.hh:68
gem5::igbreg::IT_SRPD
@ IT_SRPD
Definition: i8254xGBe_defs.hh:189
gem5::igbreg::TxDesc::d2
uint64_t d2
Definition: i8254xGBe_defs.hh:239
gem5::igbreg::Regs::rdlen
RDLEN rdlen
Definition: i8254xGBe_defs.hh:604
gem5::IGbE::DescCache::reset
void reset()
Definition: i8254xGBe.cc:1056
gem5::EtherDevice::EtherDeviceStats::txBytes
statistics::Scalar txBytes
Definition: etherdevice.hh:64
gem5::igbreg::txd_op::getTsoLen
int getTsoLen(TxDesc *d)
Definition: i8254xGBe_defs.hh:300
gem5::PacketFifo::avail
unsigned avail() const
Definition: pktfifo.hh:103
gem5::PacketFifo::reserve
unsigned reserve(unsigned len=0)
Definition: pktfifo.hh:108
gem5::htole
T htole(T value)
Definition: byteswap.hh:172
gem5::igbreg::REG_FCRTH
const uint32_t REG_FCRTH
Definition: i8254xGBe_defs.hh:68
gem5::igbreg::RXDEE_IPE
const uint16_t RXDEE_IPE
Definition: i8254xGBe_defs.hh:155
gem5::igbreg::REG_TDBAL
const uint32_t REG_TDBAL
Definition: i8254xGBe_defs.hh:79
gem5::IGbE::delayIntEvent
void delayIntEvent()
Send an interrupt to the cpu.
Definition: i8254xGBe.cc:728
gem5::igbreg::Regs::tdt
TDT tdt
Definition: i8254xGBe_defs.hh:714
gem5::igbreg::REG_SRRCTL
const uint32_t REG_SRRCTL
Definition: i8254xGBe_defs.hh:72
gem5::igbreg::txd_op::tse
bool tse(TxDesc *d)
Definition: i8254xGBe_defs.hh:267
gem5::igbreg::PHY_EPSTATUS
const uint8_t PHY_EPSTATUS
Definition: i8254xGBe_defs.hh:123
gem5::Packet::getLE
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Definition: packet_access.hh:78
gem5::igbreg::REG_RXCSUM
const uint32_t REG_RXCSUM
Definition: i8254xGBe_defs.hh:91
gem5::igbreg::TxDesc::d1
uint64_t d1
Definition: i8254xGBe_defs.hh:238
gem5::IGbE::TxDescCache::getPacketSize
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...
Definition: i8254xGBe.cc:1618
gem5::igbreg::Regs::txdca_ctl
TXDCA_CTL txdca_ctl
Definition: i8254xGBe_defs.hh:706
gem5::networking::EthPtr
Definition: inet.hh:192
gem5::IGbE::ethTxDone
void ethTxDone()
Definition: i8254xGBe.cc:2346
gem5::CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:66
gem5::networking::UdpHdr::sum
uint16_t sum() const
Definition: inet.hh:748
gem5::igbreg::RXDP_TCP
const uint16_t RXDP_TCP
Definition: i8254xGBe_defs.hh:168
gem5::IGbE::flash
uint16_t flash[igbreg::EEPROM_SIZE]
Definition: i8254xGBe.hh:71
gem5::igbreg::REG_RAL
const uint32_t REG_RAL
Definition: i8254xGBe_defs.hh:95
gem5::igbreg::Regs::iam
uint32_t iam
Definition: i8254xGBe_defs.hh:495
gem5::igbreg::REG_IMS
const uint32_t REG_IMS
Definition: i8254xGBe_defs.hh:57
gem5::igbreg::REG_TDBAH
const uint32_t REG_TDBAH
Definition: i8254xGBe_defs.hh:80
trace.hh
gem5::igbreg::REG_CTRL_EXT
const uint32_t REG_CTRL_EXT
Definition: i8254xGBe_defs.hh:47
gem5::Packet::setLE
void setLE(T v)
Set the value in the data pointer to v as little endian.
Definition: packet_access.hh:108
gem5::IGbE::RxDescCache::packetDone
bool packetDone()
Check if the dma on the packet has completed and RX state machine can continue.
Definition: i8254xGBe.cc:1458
gem5::igbreg::Regs::tidv
TIDV tidv
Definition: i8254xGBe_defs.hh:722
gem5::DrainState::Running
@ Running
Running normally.
gem5::arrayParamIn
void arrayParamIn(CheckpointIn &cp, const std::string &name, CircleBuf< T > &param)
Definition: circlebuf.hh:257
gem5::PciDevice::pciToDma
Addr pciToDma(Addr pci_addr) const
Definition: device.hh:359
gem5::Packet::getAddr
Addr getAddr() const
Definition: packet.hh:781
gem5::IGbE::ethRxPkt
bool ethRxPkt(EthPacketPtr packet)
Definition: i8254xGBe.cc:2154
gem5::IGbE::DescCache::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: i8254xGBe.cc:1108
PCI_CONFIG_SIZE
#define PCI_CONFIG_SIZE
Definition: pcireg.h:165
gem5::igbreg::Regs::fwsm
FWSM fwsm
Definition: i8254xGBe_defs.hh:850
inet.hh
gem5::igbreg::RXDS_TCPCS
const uint16_t RXDS_TCPCS
Definition: i8254xGBe_defs.hh:132
gem5::igbreg::REG_FCAH
const uint32_t REG_FCAH
Definition: i8254xGBe_defs.hh:50
gem5::IGbE::tickEvent
EventFunctionWrapper tickEvent
Definition: i8254xGBe.hh:137
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
gem5::PciDevice::intrPost
void intrPost()
Definition: device.hh:364
gem5::igbreg::Regs::rdt
RDT rdt
Definition: i8254xGBe_defs.hh:633
gem5::igbreg::RXDS_EOP
const uint16_t RXDS_EOP
Definition: i8254xGBe_defs.hh:136
gem5::igbreg::txd_op::vle
bool vle(TxDesc *d)
Definition: i8254xGBe_defs.hh:264
gem5::PacketFifo::pop
void pop()
Definition: pktfifo.hh:140
gem5::igbreg::Regs::rfctl
RFCTL rfctl
Definition: i8254xGBe_defs.hh:788
gem5::IGbE::rxDescCache
RxDescCache rxDescCache
Definition: i8254xGBe.hh:364
gem5::networking::UdpPtr
Definition: inet.hh:760
gem5::IGbE::DescCache::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: i8254xGBe.cc:1073
gem5::igbreg::Regs::eerd
EERD eerd
Definition: i8254xGBe_defs.hh:419
gem5::IGbE::txFifo
PacketFifo txFifo
Definition: i8254xGBe.hh:75
gem5::IGbE::rdtrProcess
void rdtrProcess()
Definition: i8254xGBe.hh:97
gem5::igbreg::PHY_EPID
const uint8_t PHY_EPID
Definition: i8254xGBe_defs.hh:121
gem5::IGbE::rdtrEvent
EventFunctionWrapper rdtrEvent
Definition: i8254xGBe.hh:104
gem5::igbreg::txd_op::tcp
bool tcp(TxDesc *d)
Definition: i8254xGBe_defs.hh:278
gem5::PacketFifo::empty
bool empty() const
Definition: pktfifo.hh:104
gem5::Packet::getSize
unsigned getSize() const
Definition: packet.hh:791
gem5::ArmISA::rs
Bitfield< 9, 8 > rs
Definition: misc_types.hh:376
gem5::DrainState::Draining
@ Draining
Draining buffers pending serialization/handover.
gem5::igbreg::REG_TIPG
const uint32_t REG_TIPG
Definition: i8254xGBe_defs.hh:62
gem5::Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
gem5::IGbE::TxDescCache::headerComplete
void headerComplete()
Definition: i8254xGBe.cc:1593
gem5::IGbE::RxDescCache::writePacket
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.
Definition: i8254xGBe.cc:1179
gem5::networking::TcpPtr
Definition: inet.hh:646
gem5::PacketFifo::serialize
void serialize(const std::string &base, CheckpointOut &cp) const
Serialization stuff.
Definition: pktfifo.cc:87
gem5::IGbE::DescCache::fetchDescriptors
void fetchDescriptors()
Fetch a chunk of descriptors into the descriptor cache.
Definition: i8254xGBe.cc:930
gem5::IGbE::TxDescCache::packetWaiting
bool packetWaiting()
Ask if we are still waiting for the packet to be transfered.
Definition: i8254xGBe.hh:436
gem5::IGbE::eeDataBits
int eeDataBits
Definition: i8254xGBe.hh:69
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:177
gem5::IGbE::txTick
bool txTick
Definition: i8254xGBe.hh:83
gem5::igbreg::Regs::RCTL
Definition: i8254xGBe_defs.hh:497
gem5::IGbE::rxFifo
PacketFifo rxFifo
Definition: i8254xGBe.hh:74
gem5::ArmISA::status
Bitfield< 5, 0 > status
Definition: misc_types.hh:422
gem5::Clocked::clockPeriod
Tick clockPeriod() const
Definition: clocked_object.hh:217
gem5::igbreg::Regs::rdba
RDBA rdba
Definition: i8254xGBe_defs.hh:596
gem5::sim_clock::as_int::ns
Tick ns
nanosecond
Definition: core.cc:71

Generated on Tue Sep 21 2021 12:25:17 for gem5 by doxygen 1.8.17