gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ns_gige.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004-2005 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  * Authors: Nathan Binkert
29  * Lisa Hsu
30  */
31 
37 #include "dev/net/ns_gige.hh"
38 
39 #include <deque>
40 #include <memory>
41 #include <string>
42 
43 #include "base/debug.hh"
44 #include "base/inet.hh"
45 #include "base/types.hh"
46 #include "config/the_isa.hh"
47 #include "debug/EthernetAll.hh"
48 #include "dev/net/etherlink.hh"
49 #include "mem/packet.hh"
50 #include "mem/packet_access.hh"
51 #include "params/NSGigE.hh"
52 #include "sim/system.hh"
53 
54 // clang complains about std::set being overloaded with Packet::set if
55 // we open up the entire namespace std
56 using std::make_shared;
57 using std::min;
58 using std::ostream;
59 using std::string;
60 
61 const char *NsRxStateStrings[] =
62 {
63  "rxIdle",
64  "rxDescRefr",
65  "rxDescRead",
66  "rxFifoBlock",
67  "rxFragWrite",
68  "rxDescWrite",
69  "rxAdvance"
70 };
71 
72 const char *NsTxStateStrings[] =
73 {
74  "txIdle",
75  "txDescRefr",
76  "txDescRead",
77  "txFifoBlock",
78  "txFragRead",
79  "txDescWrite",
80  "txAdvance"
81 };
82 
83 const char *NsDmaState[] =
84 {
85  "dmaIdle",
86  "dmaReading",
87  "dmaWriting",
88  "dmaReadWaiting",
89  "dmaWriteWaiting"
90 };
91 
92 using namespace Net;
93 using namespace TheISA;
94 
96 //
97 // NSGigE PCI Device
98 //
100  : EtherDevBase(p), ioEnable(false),
101  txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
102  txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
103  txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false),
104  txState(txIdle), txEnable(false), CTDD(false), txHalt(false),
105  txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
106  rxEnable(false), CRDD(false), rxPktBytes(0), rxHalt(false),
107  rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
108  eepromState(eepromStart), eepromClk(false), eepromBitsToRx(0),
109  eepromOpcode(0), eepromAddress(0), eepromData(0),
110  dmaReadDelay(p->dma_read_delay), dmaWriteDelay(p->dma_write_delay),
111  dmaReadFactor(p->dma_read_factor), dmaWriteFactor(p->dma_write_factor),
112  rxDmaData(NULL), rxDmaAddr(0), rxDmaLen(0),
113  txDmaData(NULL), txDmaAddr(0), txDmaLen(0),
114  rxDmaReadEvent(this), rxDmaWriteEvent(this),
115  txDmaReadEvent(this), txDmaWriteEvent(this),
116  dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
117  txDelay(p->tx_delay), rxDelay(p->rx_delay),
118  rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
119  txEvent(this), rxFilterEnable(p->rx_filter),
120  acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false),
121  acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
122  intrDelay(p->intr_delay), intrTick(0), cpuPendingIntr(false),
123  intrEvent(0), interface(0)
124 {
125 
126 
127  interface = new NSGigEInt(name() + ".int0", this);
128 
129  regsReset();
130  memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN);
131 
132  memset(&rxDesc32, 0, sizeof(rxDesc32));
133  memset(&txDesc32, 0, sizeof(txDesc32));
134  memset(&rxDesc64, 0, sizeof(rxDesc64));
135  memset(&txDesc64, 0, sizeof(txDesc64));
136 }
137 
139 {
140  delete interface;
141 }
142 
146 Tick
148 {
149  int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
150  if (offset < PCI_DEVICE_SPECIFIC)
152  else
153  panic("Device specific PCI config space not implemented!\n");
154 
155  switch (offset) {
156  // seems to work fine without all these PCI settings, but i
157  // put in the IO to double check, an assertion will fail if we
158  // need to properly implement it
159  case PCI_COMMAND:
160  if (config.data[offset] & PCI_CMD_IOSE)
161  ioEnable = true;
162  else
163  ioEnable = false;
164  break;
165  }
166 
167  return configDelay;
168 }
169 
170 EtherInt*
171 NSGigE::getEthPort(const std::string &if_name, int idx)
172 {
173  if (if_name == "interface") {
174  if (interface->getPeer())
175  panic("interface already connected to\n");
176  return interface;
177  }
178  return NULL;
179 }
180 
185 Tick
187 {
188  assert(ioEnable);
189 
190  //The mask is to give you only the offset into the device register file
191  Addr daddr = pkt->getAddr() & 0xfff;
192  DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n",
193  daddr, pkt->getAddr(), pkt->getSize());
194 
195 
196  // there are some reserved registers, you can see ns_gige_reg.h and
197  // the spec sheet for details
198  if (daddr > LAST && daddr <= RESERVED) {
199  panic("Accessing reserved register");
200  } else if (daddr > RESERVED && daddr <= 0x3FC) {
201  return readConfig(pkt);
202  } else if (daddr >= MIB_START && daddr <= MIB_END) {
203  // don't implement all the MIB's. hopefully the kernel
204  // doesn't actually DEPEND upon their values
205  // MIB are just hardware stats keepers
206  pkt->set<uint32_t>(0);
207  pkt->makeAtomicResponse();
208  return pioDelay;
209  } else if (daddr > 0x3FC)
210  panic("Something is messed up!\n");
211 
212  assert(pkt->getSize() == sizeof(uint32_t));
213  uint32_t &reg = *pkt->getPtr<uint32_t>();
214  uint16_t rfaddr;
215 
216  switch (daddr) {
217  case CR:
218  reg = regs.command;
219  //these are supposed to be cleared on a read
220  reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
221  break;
222 
223  case CFGR:
224  reg = regs.config;
225  break;
226 
227  case MEAR:
228  reg = regs.mear;
229  break;
230 
231  case PTSCR:
232  reg = regs.ptscr;
233  break;
234 
235  case ISR:
236  reg = regs.isr;
238  break;
239 
240  case IMR:
241  reg = regs.imr;
242  break;
243 
244  case IER:
245  reg = regs.ier;
246  break;
247 
248  case IHR:
249  reg = regs.ihr;
250  break;
251 
252  case TXDP:
253  reg = regs.txdp;
254  break;
255 
256  case TXDP_HI:
257  reg = regs.txdp_hi;
258  break;
259 
260  case TX_CFG:
261  reg = regs.txcfg;
262  break;
263 
264  case GPIOR:
265  reg = regs.gpior;
266  break;
267 
268  case RXDP:
269  reg = regs.rxdp;
270  break;
271 
272  case RXDP_HI:
273  reg = regs.rxdp_hi;
274  break;
275 
276  case RX_CFG:
277  reg = regs.rxcfg;
278  break;
279 
280  case PQCR:
281  reg = regs.pqcr;
282  break;
283 
284  case WCSR:
285  reg = regs.wcsr;
286  break;
287 
288  case PCR:
289  reg = regs.pcr;
290  break;
291 
292  // see the spec sheet for how RFCR and RFDR work
293  // basically, you write to RFCR to tell the machine
294  // what you want to do next, then you act upon RFDR,
295  // and the device will be prepared b/c of what you
296  // wrote to RFCR
297  case RFCR:
298  reg = regs.rfcr;
299  break;
300 
301  case RFDR:
302  rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
303  switch (rfaddr) {
304  // Read from perfect match ROM octets
305  case 0x000:
306  reg = rom.perfectMatch[1];
307  reg = reg << 8;
308  reg += rom.perfectMatch[0];
309  break;
310  case 0x002:
311  reg = rom.perfectMatch[3] << 8;
312  reg += rom.perfectMatch[2];
313  break;
314  case 0x004:
315  reg = rom.perfectMatch[5] << 8;
316  reg += rom.perfectMatch[4];
317  break;
318  default:
319  // Read filter hash table
320  if (rfaddr >= FHASH_ADDR &&
321  rfaddr < FHASH_ADDR + FHASH_SIZE) {
322 
323  // Only word-aligned reads supported
324  if (rfaddr % 2)
325  panic("unaligned read from filter hash table!");
326 
327  reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
328  reg += rom.filterHash[rfaddr - FHASH_ADDR];
329  break;
330  }
331 
332  panic("reading RFDR for something other than pattern"
333  " matching or hashing! %#x\n", rfaddr);
334  }
335  break;
336 
337  case SRR:
338  reg = regs.srr;
339  break;
340 
341  case MIBC:
342  reg = regs.mibc;
343  reg &= ~(MIBC_MIBS | MIBC_ACLR);
344  break;
345 
346  case VRCR:
347  reg = regs.vrcr;
348  break;
349 
350  case VTCR:
351  reg = regs.vtcr;
352  break;
353 
354  case VDR:
355  reg = regs.vdr;
356  break;
357 
358  case CCSR:
359  reg = regs.ccsr;
360  break;
361 
362  case TBICR:
363  reg = regs.tbicr;
364  break;
365 
366  case TBISR:
367  reg = regs.tbisr;
368  break;
369 
370  case TANAR:
371  reg = regs.tanar;
372  break;
373 
374  case TANLPAR:
375  reg = regs.tanlpar;
376  break;
377 
378  case TANER:
379  reg = regs.taner;
380  break;
381 
382  case TESR:
383  reg = regs.tesr;
384  break;
385 
386  case M5REG:
387  reg = 0;
388  if (params()->rx_thread)
389  reg |= M5REG_RX_THREAD;
390  if (params()->tx_thread)
391  reg |= M5REG_TX_THREAD;
392  if (params()->rss)
393  reg |= M5REG_RSS;
394  break;
395 
396  default:
397  panic("reading unimplemented register: addr=%#x", daddr);
398  }
399 
400  DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
401  daddr, reg, reg);
402 
403  pkt->makeAtomicResponse();
404  return pioDelay;
405 }
406 
407 Tick
409 {
410  assert(ioEnable);
411 
412  Addr daddr = pkt->getAddr() & 0xfff;
413  DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
414  daddr, pkt->getAddr(), pkt->getSize());
415 
416  if (daddr > LAST && daddr <= RESERVED) {
417  panic("Accessing reserved register");
418  } else if (daddr > RESERVED && daddr <= 0x3FC) {
419  return writeConfig(pkt);
420  } else if (daddr > 0x3FC)
421  panic("Something is messed up!\n");
422 
423  if (pkt->getSize() == sizeof(uint32_t)) {
424  uint32_t reg = pkt->get<uint32_t>();
425  uint16_t rfaddr;
426 
427  DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
428 
429  switch (daddr) {
430  case CR:
431  regs.command = reg;
432  if (reg & CR_TXD) {
433  txEnable = false;
434  } else if (reg & CR_TXE) {
435  txEnable = true;
436 
437  // the kernel is enabling the transmit machine
438  if (txState == txIdle)
439  txKick();
440  }
441 
442  if (reg & CR_RXD) {
443  rxEnable = false;
444  } else if (reg & CR_RXE) {
445  rxEnable = true;
446 
447  if (rxState == rxIdle)
448  rxKick();
449  }
450 
451  if (reg & CR_TXR)
452  txReset();
453 
454  if (reg & CR_RXR)
455  rxReset();
456 
457  if (reg & CR_SWI)
459 
460  if (reg & CR_RST) {
461  txReset();
462  rxReset();
463 
464  regsReset();
465  }
466  break;
467 
468  case CFGR:
469  if (reg & CFGR_LNKSTS ||
470  reg & CFGR_SPDSTS ||
471  reg & CFGR_DUPSTS ||
472  reg & CFGR_RESERVED ||
473  reg & CFGR_T64ADDR ||
474  reg & CFGR_PCI64_DET) {
475  // First clear all writable bits
479  // Now set the appropriate writable bits
483  }
484 
485 // all these #if 0's are because i don't THINK the kernel needs to
486 // have these implemented. if there is a problem relating to one of
487 // these, you may need to add functionality in.
488 
489 // grouped together and #if 0'ed to avoid empty if body and make clang happy
490 #if 0
491  if (reg & CFGR_TBI_EN) ;
492  if (reg & CFGR_MODE_1000) ;
493 
494  if (reg & CFGR_PINT_DUPSTS ||
495  reg & CFGR_PINT_LNKSTS ||
496  reg & CFGR_PINT_SPDSTS)
497  ;
498 
499  if (reg & CFGR_TMRTEST) ;
500  if (reg & CFGR_MRM_DIS) ;
501  if (reg & CFGR_MWI_DIS) ;
502 
503  if (reg & CFGR_DATA64_EN) ;
504  if (reg & CFGR_M64ADDR) ;
505  if (reg & CFGR_PHY_RST) ;
506  if (reg & CFGR_PHY_DIS) ;
507 
508  if (reg & CFGR_REQALG) ;
509  if (reg & CFGR_SB) ;
510  if (reg & CFGR_POW) ;
511  if (reg & CFGR_EXD) ;
512  if (reg & CFGR_PESEL) ;
513  if (reg & CFGR_BROM_DIS) ;
514  if (reg & CFGR_EXT_125) ;
515  if (reg & CFGR_BEM) ;
516 
517  if (reg & CFGR_T64ADDR) ;
518  // panic("CFGR_T64ADDR is read only register!\n");
519 #endif
520  if (reg & CFGR_AUTO_1000)
521  panic("CFGR_AUTO_1000 not implemented!\n");
522 
523  if (reg & CFGR_PCI64_DET)
524  panic("CFGR_PCI64_DET is read only register!\n");
525 
526  if (reg & CFGR_EXTSTS_EN)
527  extstsEnable = true;
528  else
529  extstsEnable = false;
530  break;
531 
532  case MEAR:
533  // Clear writable bits
534  regs.mear &= MEAR_EEDO;
535  // Set appropriate writable bits
536  regs.mear |= reg & ~MEAR_EEDO;
537 
538  // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
539  // even though it could get it through RFDR
540  if (reg & MEAR_EESEL) {
541  // Rising edge of clock
542  if (reg & MEAR_EECLK && !eepromClk)
543  eepromKick();
544  }
545  else {
547  regs.mear &= ~MEAR_EEDI;
548  }
549 
550  eepromClk = reg & MEAR_EECLK;
551 
552  // since phy is completely faked, MEAR_MD* don't matter
553 
554 // grouped together and #if 0'ed to avoid empty if body and make clang happy
555 #if 0
556  if (reg & MEAR_MDIO) ;
557  if (reg & MEAR_MDDIR) ;
558  if (reg & MEAR_MDC) ;
559 #endif
560  break;
561 
562  case PTSCR:
563  regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
564  // these control BISTs for various parts of chip - we
565  // don't care or do just fake that the BIST is done
566  if (reg & PTSCR_RBIST_EN)
568  if (reg & PTSCR_EEBIST_EN)
569  regs.ptscr &= ~PTSCR_EEBIST_EN;
570  if (reg & PTSCR_EELOAD_EN)
571  regs.ptscr &= ~PTSCR_EELOAD_EN;
572  break;
573 
574  case ISR: /* writing to the ISR has no effect */
575  panic("ISR is a read only register!\n");
576 
577  case IMR:
578  regs.imr = reg;
580  break;
581 
582  case IER:
583  regs.ier = reg;
584  break;
585 
586  case IHR:
587  regs.ihr = reg;
588  /* not going to implement real interrupt holdoff */
589  break;
590 
591  case TXDP:
592  regs.txdp = (reg & 0xFFFFFFFC);
593  assert(txState == txIdle);
594  CTDD = false;
595  break;
596 
597  case TXDP_HI:
598  regs.txdp_hi = reg;
599  break;
600 
601  case TX_CFG:
602  regs.txcfg = reg;
603 #if 0
604  if (reg & TX_CFG_CSI) ;
605  if (reg & TX_CFG_HBI) ;
606  if (reg & TX_CFG_MLB) ;
607  if (reg & TX_CFG_ATP) ;
608  if (reg & TX_CFG_ECRETRY) {
609  /*
610  * this could easily be implemented, but considering
611  * the network is just a fake pipe, wouldn't make
612  * sense to do this
613  */
614  }
615 
616  if (reg & TX_CFG_BRST_DIS) ;
617 #endif
618 
619 #if 0
620  /* we handle our own DMA, ignore the kernel's exhortations */
621  if (reg & TX_CFG_MXDMA) ;
622 #endif
623 
624  // also, we currently don't care about fill/drain
625  // thresholds though this may change in the future with
626  // more realistic networks or a driver which changes it
627  // according to feedback
628 
629  break;
630 
631  case GPIOR:
632  // Only write writable bits
637  /* these just control general purpose i/o pins, don't matter */
638  break;
639 
640  case RXDP:
641  regs.rxdp = reg;
642  CRDD = false;
643  break;
644 
645  case RXDP_HI:
646  regs.rxdp_hi = reg;
647  break;
648 
649  case RX_CFG:
650  regs.rxcfg = reg;
651 #if 0
652  if (reg & RX_CFG_AEP) ;
653  if (reg & RX_CFG_ARP) ;
654  if (reg & RX_CFG_STRIPCRC) ;
655  if (reg & RX_CFG_RX_RD) ;
656  if (reg & RX_CFG_ALP) ;
657  if (reg & RX_CFG_AIRL) ;
658 
659  /* we handle our own DMA, ignore what kernel says about it */
660  if (reg & RX_CFG_MXDMA) ;
661 
662  //also, we currently don't care about fill/drain thresholds
663  //though this may change in the future with more realistic
664  //networks or a driver which changes it according to feedback
665  if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
666 #endif
667  break;
668 
669  case PQCR:
670  /* there is no priority queueing used in the linux 2.6 driver */
671  regs.pqcr = reg;
672  break;
673 
674  case WCSR:
675  /* not going to implement wake on LAN */
676  regs.wcsr = reg;
677  break;
678 
679  case PCR:
680  /* not going to implement pause control */
681  regs.pcr = reg;
682  break;
683 
684  case RFCR:
685  regs.rfcr = reg;
686 
687  rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
688  acceptBroadcast = (reg & RFCR_AAB) ? true : false;
689  acceptMulticast = (reg & RFCR_AAM) ? true : false;
690  acceptUnicast = (reg & RFCR_AAU) ? true : false;
691  acceptPerfect = (reg & RFCR_APM) ? true : false;
692  acceptArp = (reg & RFCR_AARP) ? true : false;
693  multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
694 
695 #if 0
696  if (reg & RFCR_APAT)
697  panic("RFCR_APAT not implemented!\n");
698 #endif
699  if (reg & RFCR_UHEN)
700  panic("Unicast hash filtering not used by drivers!\n");
701 
702  if (reg & RFCR_ULM)
703  panic("RFCR_ULM not implemented!\n");
704 
705  break;
706 
707  case RFDR:
708  rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
709  switch (rfaddr) {
710  case 0x000:
711  rom.perfectMatch[0] = (uint8_t)reg;
712  rom.perfectMatch[1] = (uint8_t)(reg >> 8);
713  break;
714  case 0x002:
715  rom.perfectMatch[2] = (uint8_t)reg;
716  rom.perfectMatch[3] = (uint8_t)(reg >> 8);
717  break;
718  case 0x004:
719  rom.perfectMatch[4] = (uint8_t)reg;
720  rom.perfectMatch[5] = (uint8_t)(reg >> 8);
721  break;
722  default:
723 
724  if (rfaddr >= FHASH_ADDR &&
725  rfaddr < FHASH_ADDR + FHASH_SIZE) {
726 
727  // Only word-aligned writes supported
728  if (rfaddr % 2)
729  panic("unaligned write to filter hash table!");
730 
731  rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
732  rom.filterHash[rfaddr - FHASH_ADDR + 1]
733  = (uint8_t)(reg >> 8);
734  break;
735  }
736  panic("writing RFDR for something other than pattern matching "
737  "or hashing! %#x\n", rfaddr);
738  }
739 
740  case BRAR:
741  regs.brar = reg;
742  break;
743 
744  case BRDR:
745  panic("the driver never uses BRDR, something is wrong!\n");
746 
747  case SRR:
748  panic("SRR is read only register!\n");
749 
750  case MIBC:
751  panic("the driver never uses MIBC, something is wrong!\n");
752 
753  case VRCR:
754  regs.vrcr = reg;
755  break;
756 
757  case VTCR:
758  regs.vtcr = reg;
759  break;
760 
761  case VDR:
762  panic("the driver never uses VDR, something is wrong!\n");
763 
764  case CCSR:
765  /* not going to implement clockrun stuff */
766  regs.ccsr = reg;
767  break;
768 
769  case TBICR:
770  regs.tbicr = reg;
771  if (reg & TBICR_MR_LOOPBACK)
772  panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
773 
774  if (reg & TBICR_MR_AN_ENABLE) {
777  }
778 
779 #if 0
780  if (reg & TBICR_MR_RESTART_AN) ;
781 #endif
782 
783  break;
784 
785  case TBISR:
786  panic("TBISR is read only register!\n");
787 
788  case TANAR:
789  // Only write the writable bits
791  regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
792 
793  // Pause capability unimplemented
794 #if 0
795  if (reg & TANAR_PS2) ;
796  if (reg & TANAR_PS1) ;
797 #endif
798 
799  break;
800 
801  case TANLPAR:
802  panic("this should only be written to by the fake phy!\n");
803 
804  case TANER:
805  panic("TANER is read only register!\n");
806 
807  case TESR:
808  regs.tesr = reg;
809  break;
810 
811  default:
812  panic("invalid register access daddr=%#x", daddr);
813  }
814  } else {
815  panic("Invalid Request Size");
816  }
817  pkt->makeAtomicResponse();
818  return pioDelay;
819 }
820 
821 void
822 NSGigE::devIntrPost(uint32_t interrupts)
823 {
824  if (interrupts & ISR_RESERVE)
825  panic("Cannot set a reserved interrupt");
826 
827  if (interrupts & ISR_NOIMPL)
828  warn("interrupt not implemented %#x\n", interrupts);
829 
830  interrupts &= ISR_IMPL;
831  regs.isr |= interrupts;
832 
833  if (interrupts & regs.imr) {
834  if (interrupts & ISR_SWI) {
835  totalSwi++;
836  }
837  if (interrupts & ISR_RXIDLE) {
838  totalRxIdle++;
839  }
840  if (interrupts & ISR_RXOK) {
841  totalRxOk++;
842  }
843  if (interrupts & ISR_RXDESC) {
844  totalRxDesc++;
845  }
846  if (interrupts & ISR_TXOK) {
847  totalTxOk++;
848  }
849  if (interrupts & ISR_TXIDLE) {
850  totalTxIdle++;
851  }
852  if (interrupts & ISR_TXDESC) {
853  totalTxDesc++;
854  }
855  if (interrupts & ISR_RXORN) {
856  totalRxOrn++;
857  }
858  }
859 
860  DPRINTF(EthernetIntr,
861  "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
862  interrupts, regs.isr, regs.imr);
863 
864  if ((regs.isr & regs.imr)) {
865  Tick when = curTick();
866  if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
867  when += intrDelay;
869  cpuIntrPost(when);
870  }
871 }
872 
873 /* writing this interrupt counting stats inside this means that this function
874  is now limited to being used to clear all interrupts upon the kernel
875  reading isr and servicing. just telling you in case you were thinking
876  of expanding use.
877 */
878 void
879 NSGigE::devIntrClear(uint32_t interrupts)
880 {
881  if (interrupts & ISR_RESERVE)
882  panic("Cannot clear a reserved interrupt");
883 
884  if (regs.isr & regs.imr & ISR_SWI) {
885  postedSwi++;
886  }
887  if (regs.isr & regs.imr & ISR_RXIDLE) {
888  postedRxIdle++;
889  }
890  if (regs.isr & regs.imr & ISR_RXOK) {
891  postedRxOk++;
892  }
893  if (regs.isr & regs.imr & ISR_RXDESC) {
894  postedRxDesc++;
895  }
896  if (regs.isr & regs.imr & ISR_TXOK) {
897  postedTxOk++;
898  }
899  if (regs.isr & regs.imr & ISR_TXIDLE) {
900  postedTxIdle++;
901  }
902  if (regs.isr & regs.imr & ISR_TXDESC) {
903  postedTxDesc++;
904  }
905  if (regs.isr & regs.imr & ISR_RXORN) {
906  postedRxOrn++;
907  }
908 
909  interrupts &= ~ISR_NOIMPL;
910  regs.isr &= ~interrupts;
911 
912  DPRINTF(EthernetIntr,
913  "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
914  interrupts, regs.isr, regs.imr);
915 
916  if (!(regs.isr & regs.imr))
917  cpuIntrClear();
918 }
919 
920 void
922 {
923  DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
924  regs.isr, regs.imr, regs.isr & regs.imr);
925 
926  if (regs.isr & regs.imr)
927  cpuIntrPost(curTick());
928  else
929  cpuIntrClear();
930 }
931 
932 void
934 {
935  // If the interrupt you want to post is later than an interrupt
936  // already scheduled, just let it post in the coming one and don't
937  // schedule another.
938  // HOWEVER, must be sure that the scheduled intrTick is in the
939  // future (this was formerly the source of a bug)
944  assert(when >= curTick());
945  assert(intrTick >= curTick() || intrTick == 0);
946  if (when > intrTick && intrTick != 0) {
947  DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
948  intrTick);
949  return;
950  }
951 
952  intrTick = when;
953  if (intrTick < curTick()) {
954  intrTick = curTick();
955  }
956 
957  DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
958  intrTick);
959 
960  if (intrEvent)
961  intrEvent->squash();
962  intrEvent = new IntrEvent(this, true);
964 }
965 
966 void
968 {
969  assert(intrTick == curTick());
970 
971  // Whether or not there's a pending interrupt, we don't care about
972  // it anymore
973  intrEvent = 0;
974  intrTick = 0;
975 
976  // Don't send an interrupt if there's already one
977  if (cpuPendingIntr) {
978  DPRINTF(EthernetIntr,
979  "would send an interrupt now, but there's already pending\n");
980  } else {
981  // Send interrupt
982  cpuPendingIntr = true;
983 
984  DPRINTF(EthernetIntr, "posting interrupt\n");
985  intrPost();
986  }
987 }
988 
989 void
991 {
992  if (!cpuPendingIntr)
993  return;
994 
995  if (intrEvent) {
996  intrEvent->squash();
997  intrEvent = 0;
998  }
999 
1000  intrTick = 0;
1001 
1002  cpuPendingIntr = false;
1003 
1004  DPRINTF(EthernetIntr, "clearing interrupt\n");
1005  intrClear();
1006 }
1007 
1008 bool
1010 { return cpuPendingIntr; }
1011 
1012 void
1014 {
1015 
1016  DPRINTF(Ethernet, "transmit reset\n");
1017 
1018  CTDD = false;
1019  txEnable = false;;
1020  txFragPtr = 0;
1021  assert(txDescCnt == 0);
1022  txFifo.clear();
1023  txState = txIdle;
1024  assert(txDmaState == dmaIdle);
1025 }
1026 
1027 void
1029 {
1030  DPRINTF(Ethernet, "receive reset\n");
1031 
1032  CRDD = false;
1033  assert(rxPktBytes == 0);
1034  rxEnable = false;
1035  rxFragPtr = 0;
1036  assert(rxDescCnt == 0);
1037  assert(rxDmaState == dmaIdle);
1038  rxFifo.clear();
1039  rxState = rxIdle;
1040 }
1041 
1042 void
1044 {
1045  memset(&regs, 0, sizeof(regs));
1047  regs.mear = 0x12;
1048  regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
1049  // fill threshold to 32 bytes
1050  regs.rxcfg = 0x4; // set drain threshold to 16 bytes
1051  regs.srr = 0x0103; // set the silicon revision to rev B or 0x103
1052  regs.mibc = MIBC_FRZ;
1053  regs.vdr = 0x81; // set the vlan tag type to 802.1q
1054  regs.tesr = 0xc000; // TBI capable of both full and half duplex
1055  regs.brar = 0xffffffff;
1056 
1057  extstsEnable = false;
1058  acceptBroadcast = false;
1059  acceptMulticast = false;
1060  acceptUnicast = false;
1061  acceptPerfect = false;
1062  acceptArp = false;
1063 }
1064 
1065 bool
1067 {
1068  assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
1070 
1073  else
1075 
1076  return true;
1077 }
1078 
1079 void
1081 {
1082  assert(rxDmaState == dmaReading);
1083  rxDmaState = dmaIdle;
1084 
1085  DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n",
1086  rxDmaAddr, rxDmaLen);
1087  DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1088 
1089  // If the transmit state machine has a pending DMA, let it go first
1091  txKick();
1092 
1093  rxKick();
1094 }
1095 
1096 bool
1098 {
1099  assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
1101 
1104  else
1106  return true;
1107 }
1108 
1109 void
1111 {
1112  assert(rxDmaState == dmaWriting);
1113  rxDmaState = dmaIdle;
1114 
1115  DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
1116  rxDmaAddr, rxDmaLen);
1117  DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1118 
1119  // If the transmit state machine has a pending DMA, let it go first
1121  txKick();
1122 
1123  rxKick();
1124 }
1125 
1126 void
1128 {
1129  bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1130 
1131  DPRINTF(EthernetSM,
1132  "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
1133  NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
1134 
1135  Addr link, bufptr;
1136  uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
1137  uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
1138 
1139  next:
1140  if (rxKickTick > curTick()) {
1141  DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
1142  rxKickTick);
1143 
1144  goto exit;
1145  }
1146 
1147  // Go to the next state machine clock tick.
1148  rxKickTick = clockEdge(Cycles(1));
1149 
1150  switch(rxDmaState) {
1151  case dmaReadWaiting:
1152  if (doRxDmaRead())
1153  goto exit;
1154  break;
1155  case dmaWriteWaiting:
1156  if (doRxDmaWrite())
1157  goto exit;
1158  break;
1159  default:
1160  break;
1161  }
1162 
1163  link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
1164  bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
1165 
1166  // see state machine from spec for details
1167  // the way this works is, if you finish work on one state and can
1168  // go directly to another, you do that through jumping to the
1169  // label "next". however, if you have intermediate work, like DMA
1170  // so that you can't go to the next state yet, you go to exit and
1171  // exit the loop. however, when the DMA is done it will trigger
1172  // an event and come back to this loop.
1173  switch (rxState) {
1174  case rxIdle:
1175  if (!rxEnable) {
1176  DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
1177  goto exit;
1178  }
1179 
1180  if (CRDD) {
1181  rxState = rxDescRefr;
1182 
1183  rxDmaAddr = regs.rxdp & 0x3fffffff;
1184  rxDmaData =
1185  is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
1186  rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
1188 
1189  descDmaReads++;
1191 
1192  if (doRxDmaRead())
1193  goto exit;
1194  } else {
1195  rxState = rxDescRead;
1196 
1197  rxDmaAddr = regs.rxdp & 0x3fffffff;
1198  rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1199  rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1201 
1202  descDmaReads++;
1204 
1205  if (doRxDmaRead())
1206  goto exit;
1207  }
1208  break;
1209 
1210  case rxDescRefr:
1211  if (rxDmaState != dmaIdle)
1212  goto exit;
1213 
1214  rxState = rxAdvance;
1215  break;
1216 
1217  case rxDescRead:
1218  if (rxDmaState != dmaIdle)
1219  goto exit;
1220 
1221  DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
1222  regs.rxdp & 0x3fffffff);
1223  DPRINTF(EthernetDesc,
1224  "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1225  link, bufptr, cmdsts, extsts);
1226 
1227  if (cmdsts & CMDSTS_OWN) {
1229  rxState = rxIdle;
1230  goto exit;
1231  } else {
1232  rxState = rxFifoBlock;
1233  rxFragPtr = bufptr;
1234  rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
1235  }
1236  break;
1237 
1238  case rxFifoBlock:
1239  if (!rxPacket) {
1245  if (rxFifo.empty())
1246  goto exit;
1247 
1248  DPRINTF(EthernetSM, "****processing receive of new packet****\n");
1249 
1250  // If we don't have a packet, grab a new one from the fifo.
1251  rxPacket = rxFifo.front();
1252  rxPktBytes = rxPacket->length;
1253  rxPacketBufPtr = rxPacket->data;
1254 
1255 #if TRACING_ON
1256  if (DTRACE(Ethernet)) {
1257  IpPtr ip(rxPacket);
1258  if (ip) {
1259  DPRINTF(Ethernet, "ID is %d\n", ip->id());
1260  TcpPtr tcp(ip);
1261  if (tcp) {
1262  DPRINTF(Ethernet,
1263  "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1264  tcp->sport(), tcp->dport(), tcp->seq(),
1265  tcp->ack());
1266  }
1267  }
1268  }
1269 #endif
1270 
1271  // sanity check - i think the driver behaves like this
1272  assert(rxDescCnt >= rxPktBytes);
1273  rxFifo.pop();
1274  }
1275 
1276 
1277  // dont' need the && rxDescCnt > 0 if driver sanity check
1278  // above holds
1279  if (rxPktBytes > 0) {
1280  rxState = rxFragWrite;
1281  // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
1282  // check holds
1284 
1285  rxDmaAddr = rxFragPtr & 0x3fffffff;
1287  rxDmaLen = rxXferLen;
1289 
1290  if (doRxDmaWrite())
1291  goto exit;
1292 
1293  } else {
1294  rxState = rxDescWrite;
1295 
1296  //if (rxPktBytes == 0) { /* packet is done */
1297  assert(rxPktBytes == 0);
1298  DPRINTF(EthernetSM, "done with receiving packet\n");
1299 
1300  cmdsts |= CMDSTS_OWN;
1301  cmdsts &= ~CMDSTS_MORE;
1302  cmdsts |= CMDSTS_OK;
1303  cmdsts &= 0xffff0000;
1304  cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE
1305 
1306 #if 0
1307  /*
1308  * all the driver uses these are for its own stats keeping
1309  * which we don't care about, aren't necessary for
1310  * functionality and doing this would just slow us down.
1311  * if they end up using this in a later version for
1312  * functional purposes, just undef
1313  */
1314  if (rxFilterEnable) {
1315  cmdsts &= ~CMDSTS_DEST_MASK;
1316  const EthAddr &dst = rxFifoFront()->dst();
1317  if (dst->unicast())
1318  cmdsts |= CMDSTS_DEST_SELF;
1319  if (dst->multicast())
1320  cmdsts |= CMDSTS_DEST_MULTI;
1321  if (dst->broadcast())
1322  cmdsts |= CMDSTS_DEST_MASK;
1323  }
1324 #endif
1325 
1326  IpPtr ip(rxPacket);
1327  if (extstsEnable && ip) {
1328  extsts |= EXTSTS_IPPKT;
1329  rxIpChecksums++;
1330  if (cksum(ip) != 0) {
1331  DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
1332  extsts |= EXTSTS_IPERR;
1333  }
1334  TcpPtr tcp(ip);
1335  UdpPtr udp(ip);
1336  if (tcp) {
1337  extsts |= EXTSTS_TCPPKT;
1338  rxTcpChecksums++;
1339  if (cksum(tcp) != 0) {
1340  DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
1341  extsts |= EXTSTS_TCPERR;
1342 
1343  }
1344  } else if (udp) {
1345  extsts |= EXTSTS_UDPPKT;
1346  rxUdpChecksums++;
1347  if (cksum(udp) != 0) {
1348  DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
1349  extsts |= EXTSTS_UDPERR;
1350  }
1351  }
1352  }
1353  rxPacket = 0;
1354 
1355  /*
1356  * the driver seems to always receive into desc buffers
1357  * of size 1514, so you never have a pkt that is split
1358  * into multiple descriptors on the receive side, so
1359  * i don't implement that case, hence the assert above.
1360  */
1361 
1362  DPRINTF(EthernetDesc,
1363  "rxDesc: addr=%08x writeback cmdsts extsts\n",
1364  regs.rxdp & 0x3fffffff);
1365  DPRINTF(EthernetDesc,
1366  "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1367  link, bufptr, cmdsts, extsts);
1368 
1369  rxDmaAddr = regs.rxdp & 0x3fffffff;
1370  rxDmaData = &cmdsts;
1371  if (is64bit) {
1372  rxDmaAddr += offsetof(ns_desc64, cmdsts);
1373  rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
1374  } else {
1375  rxDmaAddr += offsetof(ns_desc32, cmdsts);
1376  rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
1377  }
1379 
1380  descDmaWrites++;
1382 
1383  if (doRxDmaWrite())
1384  goto exit;
1385  }
1386  break;
1387 
1388  case rxFragWrite:
1389  if (rxDmaState != dmaIdle)
1390  goto exit;
1391 
1393  rxFragPtr += rxXferLen;
1394  rxPktBytes -= rxXferLen;
1395 
1396  rxState = rxFifoBlock;
1397  break;
1398 
1399  case rxDescWrite:
1400  if (rxDmaState != dmaIdle)
1401  goto exit;
1402 
1403  assert(cmdsts & CMDSTS_OWN);
1404 
1405  assert(rxPacket == 0);
1407 
1408  if (cmdsts & CMDSTS_INTR)
1410 
1411  if (!rxEnable) {
1412  DPRINTF(EthernetSM, "Halting the RX state machine\n");
1413  rxState = rxIdle;
1414  goto exit;
1415  } else
1416  rxState = rxAdvance;
1417  break;
1418 
1419  case rxAdvance:
1420  if (link == 0) {
1422  rxState = rxIdle;
1423  CRDD = true;
1424  goto exit;
1425  } else {
1426  if (rxDmaState != dmaIdle)
1427  goto exit;
1428  rxState = rxDescRead;
1429  regs.rxdp = link;
1430  CRDD = false;
1431 
1432  rxDmaAddr = regs.rxdp & 0x3fffffff;
1433  rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1434  rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1436 
1437  if (doRxDmaRead())
1438  goto exit;
1439  }
1440  break;
1441 
1442  default:
1443  panic("Invalid rxState!");
1444  }
1445 
1446  DPRINTF(EthernetSM, "entering next rxState=%s\n",
1447  NsRxStateStrings[rxState]);
1448  goto next;
1449 
1450  exit:
1454  DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
1455  NsRxStateStrings[rxState]);
1456 
1457  if (!rxKickEvent.scheduled())
1459 }
1460 
1461 void
1463 {
1464  if (txFifo.empty()) {
1465  DPRINTF(Ethernet, "nothing to transmit\n");
1466  return;
1467  }
1468 
1469  DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
1470  txFifo.size());
1471  if (interface->sendPacket(txFifo.front())) {
1472 #if TRACING_ON
1473  if (DTRACE(Ethernet)) {
1474  IpPtr ip(txFifo.front());
1475  if (ip) {
1476  DPRINTF(Ethernet, "ID is %d\n", ip->id());
1477  TcpPtr tcp(ip);
1478  if (tcp) {
1479  DPRINTF(Ethernet,
1480  "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1481  tcp->sport(), tcp->dport(), tcp->seq(),
1482  tcp->ack());
1483  }
1484  }
1485  }
1486 #endif
1487 
1488  DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
1489  txBytes += txFifo.front()->length;
1490  txPackets++;
1491 
1492  DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
1493  txFifo.avail());
1494  txFifo.pop();
1495 
1496  /*
1497  * normally do a writeback of the descriptor here, and ONLY
1498  * after that is done, send this interrupt. but since our
1499  * stuff never actually fails, just do this interrupt here,
1500  * otherwise the code has to stray from this nice format.
1501  * besides, it's functionally the same.
1502  */
1504  }
1505 
1506  if (!txFifo.empty() && !txEvent.scheduled()) {
1507  DPRINTF(Ethernet, "reschedule transmit\n");
1509  }
1510 }
1511 
1512 bool
1514 {
1515  assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
1517 
1520  else
1522 
1523  return true;
1524 }
1525 
1526 void
1528 {
1529  assert(txDmaState == dmaReading);
1530  txDmaState = dmaIdle;
1531 
1532  DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
1533  txDmaAddr, txDmaLen);
1534  DDUMP(EthernetDMA, txDmaData, txDmaLen);
1535 
1536  // If the receive state machine has a pending DMA, let it go first
1538  rxKick();
1539 
1540  txKick();
1541 }
1542 
1543 bool
1545 {
1546  assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
1548 
1551  else
1553  return true;
1554 }
1555 
1556 void
1558 {
1559  assert(txDmaState == dmaWriting);
1560  txDmaState = dmaIdle;
1561 
1562  DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
1563  txDmaAddr, txDmaLen);
1564  DDUMP(EthernetDMA, txDmaData, txDmaLen);
1565 
1566  // If the receive state machine has a pending DMA, let it go first
1568  rxKick();
1569 
1570  txKick();
1571 }
1572 
1573 void
1575 {
1576  bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1577 
1578  DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
1579  NsTxStateStrings[txState], is64bit ? 64 : 32);
1580 
1581  Addr link, bufptr;
1582  uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
1583  uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
1584 
1585  next:
1586  if (txKickTick > curTick()) {
1587  DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
1588  txKickTick);
1589  goto exit;
1590  }
1591 
1592  // Go to the next state machine clock tick.
1593  txKickTick = clockEdge(Cycles(1));
1594 
1595  switch(txDmaState) {
1596  case dmaReadWaiting:
1597  if (doTxDmaRead())
1598  goto exit;
1599  break;
1600  case dmaWriteWaiting:
1601  if (doTxDmaWrite())
1602  goto exit;
1603  break;
1604  default:
1605  break;
1606  }
1607 
1608  link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
1609  bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
1610  switch (txState) {
1611  case txIdle:
1612  if (!txEnable) {
1613  DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n");
1614  goto exit;
1615  }
1616 
1617  if (CTDD) {
1618  txState = txDescRefr;
1619 
1620  txDmaAddr = regs.txdp & 0x3fffffff;
1621  txDmaData =
1622  is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
1623  txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
1625 
1626  descDmaReads++;
1628 
1629  if (doTxDmaRead())
1630  goto exit;
1631 
1632  } else {
1633  txState = txDescRead;
1634 
1635  txDmaAddr = regs.txdp & 0x3fffffff;
1636  txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1637  txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1639 
1640  descDmaReads++;
1642 
1643  if (doTxDmaRead())
1644  goto exit;
1645  }
1646  break;
1647 
1648  case txDescRefr:
1649  if (txDmaState != dmaIdle)
1650  goto exit;
1651 
1652  txState = txAdvance;
1653  break;
1654 
1655  case txDescRead:
1656  if (txDmaState != dmaIdle)
1657  goto exit;
1658 
1659  DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
1660  regs.txdp & 0x3fffffff);
1661  DPRINTF(EthernetDesc,
1662  "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
1663  link, bufptr, cmdsts, extsts);
1664 
1665  if (cmdsts & CMDSTS_OWN) {
1666  txState = txFifoBlock;
1667  txFragPtr = bufptr;
1668  txDescCnt = cmdsts & CMDSTS_LEN_MASK;
1669  } else {
1671  txState = txIdle;
1672  goto exit;
1673  }
1674  break;
1675 
1676  case txFifoBlock:
1677  if (!txPacket) {
1678  DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
1679  txPacket = make_shared<EthPacketData>(16384);
1680  txPacketBufPtr = txPacket->data;
1681  }
1682 
1683  if (txDescCnt == 0) {
1684  DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
1685  if (cmdsts & CMDSTS_MORE) {
1686  DPRINTF(EthernetSM, "there are more descriptors to come\n");
1687  txState = txDescWrite;
1688 
1689  cmdsts &= ~CMDSTS_OWN;
1690 
1691  txDmaAddr = regs.txdp & 0x3fffffff;
1692  txDmaData = &cmdsts;
1693  if (is64bit) {
1694  txDmaAddr += offsetof(ns_desc64, cmdsts);
1695  txDmaLen = sizeof(txDesc64.cmdsts);
1696  } else {
1697  txDmaAddr += offsetof(ns_desc32, cmdsts);
1698  txDmaLen = sizeof(txDesc32.cmdsts);
1699  }
1701 
1702  if (doTxDmaWrite())
1703  goto exit;
1704 
1705  } else { /* this packet is totally done */
1706  DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
1707  /* deal with the the packet that just finished */
1708  if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
1709  IpPtr ip(txPacket);
1710  if (extsts & EXTSTS_UDPPKT) {
1711  UdpPtr udp(ip);
1712  if (udp) {
1713  udp->sum(0);
1714  udp->sum(cksum(udp));
1715  txUdpChecksums++;
1716  } else {
1718  warn_once("UDPPKT set, but not UDP!\n");
1719  }
1720  } else if (extsts & EXTSTS_TCPPKT) {
1721  TcpPtr tcp(ip);
1722  if (tcp) {
1723  tcp->sum(0);
1724  tcp->sum(cksum(tcp));
1725  txTcpChecksums++;
1726  } else {
1727  warn_once("TCPPKT set, but not UDP!\n");
1728  }
1729  }
1730  if (extsts & EXTSTS_IPPKT) {
1731  if (ip) {
1732  ip->sum(0);
1733  ip->sum(cksum(ip));
1734  txIpChecksums++;
1735  } else {
1736  warn_once("IPPKT set, but not UDP!\n");
1737  }
1738  }
1739  }
1740 
1741  txPacket->simLength = txPacketBufPtr - txPacket->data;
1742  txPacket->length = txPacketBufPtr - txPacket->data;
1743  // this is just because the receive can't handle a
1744  // packet bigger want to make sure
1745  if (txPacket->length > 1514)
1746  panic("transmit packet too large, %s > 1514\n",
1747  txPacket->length);
1748 
1749 #ifndef NDEBUG
1750  bool success =
1751 #endif
1752  txFifo.push(txPacket);
1753  assert(success);
1754 
1755  /*
1756  * this following section is not tqo spec, but
1757  * functionally shouldn't be any different. normally,
1758  * the chip will wait til the transmit has occurred
1759  * before writing back the descriptor because it has
1760  * to wait to see that it was successfully transmitted
1761  * to decide whether to set CMDSTS_OK or not.
1762  * however, in the simulator since it is always
1763  * successfully transmitted, and writing it exactly to
1764  * spec would complicate the code, we just do it here
1765  */
1766 
1767  cmdsts &= ~CMDSTS_OWN;
1768  cmdsts |= CMDSTS_OK;
1769 
1770  DPRINTF(EthernetDesc,
1771  "txDesc writeback: cmdsts=%08x extsts=%08x\n",
1772  cmdsts, extsts);
1773 
1775  txDmaAddr = regs.txdp & 0x3fffffff;
1776  txDmaData = &cmdsts;
1777  if (is64bit) {
1778  txDmaAddr += offsetof(ns_desc64, cmdsts);
1779  txDmaLen =
1780  sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
1781  } else {
1782  txDmaAddr += offsetof(ns_desc32, cmdsts);
1783  txDmaLen =
1784  sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
1785  }
1786 
1787  descDmaWrites++;
1789 
1790  transmit();
1791  txPacket = 0;
1792 
1793  if (!txEnable) {
1794  DPRINTF(EthernetSM, "halting TX state machine\n");
1795  txState = txIdle;
1796  goto exit;
1797  } else
1798  txState = txAdvance;
1799 
1800  if (doTxDmaWrite())
1801  goto exit;
1802  }
1803  } else {
1804  DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
1805  if (!txFifo.full()) {
1806  txState = txFragRead;
1807 
1808  /*
1809  * The number of bytes transferred is either whatever
1810  * is left in the descriptor (txDescCnt), or if there
1811  * is not enough room in the fifo, just whatever room
1812  * is left in the fifo
1813  */
1814  txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
1815 
1816  txDmaAddr = txFragPtr & 0x3fffffff;
1818  txDmaLen = txXferLen;
1820 
1821  if (doTxDmaRead())
1822  goto exit;
1823  } else {
1824  txState = txFifoBlock;
1825  transmit();
1826 
1827  goto exit;
1828  }
1829 
1830  }
1831  break;
1832 
1833  case txFragRead:
1834  if (txDmaState != dmaIdle)
1835  goto exit;
1836 
1838  txFragPtr += txXferLen;
1839  txDescCnt -= txXferLen;
1841 
1842  txState = txFifoBlock;
1843  break;
1844 
1845  case txDescWrite:
1846  if (txDmaState != dmaIdle)
1847  goto exit;
1848 
1849  if (cmdsts & CMDSTS_INTR)
1851 
1852  if (!txEnable) {
1853  DPRINTF(EthernetSM, "halting TX state machine\n");
1854  txState = txIdle;
1855  goto exit;
1856  } else
1857  txState = txAdvance;
1858  break;
1859 
1860  case txAdvance:
1861  if (link == 0) {
1863  txState = txIdle;
1864  goto exit;
1865  } else {
1866  if (txDmaState != dmaIdle)
1867  goto exit;
1868  txState = txDescRead;
1869  regs.txdp = link;
1870  CTDD = false;
1871 
1872  txDmaAddr = link & 0x3fffffff;
1873  txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1874  txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1876 
1877  if (doTxDmaRead())
1878  goto exit;
1879  }
1880  break;
1881 
1882  default:
1883  panic("invalid state");
1884  }
1885 
1886  DPRINTF(EthernetSM, "entering next txState=%s\n",
1887  NsTxStateStrings[txState]);
1888  goto next;
1889 
1890  exit:
1894  DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
1895  NsTxStateStrings[txState]);
1896 
1897  if (!txKickEvent.scheduled())
1899 }
1900 
1905 void
1907 {
1908  switch (eepromState) {
1909 
1910  case eepromStart:
1911 
1912  // Wait for start bit
1913  if (regs.mear & MEAR_EEDI) {
1914  // Set up to get 2 opcode bits
1916  eepromBitsToRx = 2;
1917  eepromOpcode = 0;
1918  }
1919  break;
1920 
1921  case eepromGetOpcode:
1922  eepromOpcode <<= 1;
1923  eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
1924  --eepromBitsToRx;
1925 
1926  // Done getting opcode
1927  if (eepromBitsToRx == 0) {
1928  if (eepromOpcode != EEPROM_READ)
1929  panic("only EEPROM reads are implemented!");
1930 
1931  // Set up to get address
1933  eepromBitsToRx = 6;
1934  eepromAddress = 0;
1935  }
1936  break;
1937 
1938  case eepromGetAddress:
1939  eepromAddress <<= 1;
1940  eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
1941  --eepromBitsToRx;
1942 
1943  // Done getting address
1944  if (eepromBitsToRx == 0) {
1945 
1946  if (eepromAddress >= EEPROM_SIZE)
1947  panic("EEPROM read access out of range!");
1948 
1949  switch (eepromAddress) {
1950 
1951  case EEPROM_PMATCH2_ADDR:
1953  eepromData <<= 8;
1954  eepromData += rom.perfectMatch[4];
1955  break;
1956 
1957  case EEPROM_PMATCH1_ADDR:
1959  eepromData <<= 8;
1960  eepromData += rom.perfectMatch[2];
1961  break;
1962 
1963  case EEPROM_PMATCH0_ADDR:
1965  eepromData <<= 8;
1966  eepromData += rom.perfectMatch[0];
1967  break;
1968 
1969  default:
1970  panic("FreeBSD driver only uses EEPROM to read PMATCH!");
1971  }
1972  // Set up to read data
1974  eepromBitsToRx = 16;
1975 
1976  // Clear data in bit
1977  regs.mear &= ~MEAR_EEDI;
1978  }
1979  break;
1980 
1981  case eepromRead:
1982  // Clear Data Out bit
1983  regs.mear &= ~MEAR_EEDO;
1984  // Set bit to value of current EEPROM bit
1985  regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
1986 
1987  eepromData <<= 1;
1988  --eepromBitsToRx;
1989 
1990  // All done
1991  if (eepromBitsToRx == 0) {
1993  }
1994  break;
1995 
1996  default:
1997  panic("invalid EEPROM state");
1998  }
1999 
2000 }
2001 
2002 void
2004 {
2005  if (txFifo.empty()) {
2006  DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
2007  return;
2008  }
2009 
2010  DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
2011 
2012  reschedule(txEvent, clockEdge(Cycles(1)), true);
2013 }
2014 
2015 bool
2017 {
2018  EthPtr eth = packet;
2019  bool drop = true;
2020  string type;
2021 
2022  const EthAddr &dst = eth->dst();
2023  if (dst.unicast()) {
2024  // If we're accepting all unicast addresses
2025  if (acceptUnicast)
2026  drop = false;
2027 
2028  // If we make a perfect match
2029  if (acceptPerfect && dst == rom.perfectMatch)
2030  drop = false;
2031 
2032  if (acceptArp && eth->type() == ETH_TYPE_ARP)
2033  drop = false;
2034 
2035  } else if (dst.broadcast()) {
2036  // if we're accepting broadcasts
2037  if (acceptBroadcast)
2038  drop = false;
2039 
2040  } else if (dst.multicast()) {
2041  // if we're accepting all multicasts
2042  if (acceptMulticast)
2043  drop = false;
2044 
2045  // Multicast hashing faked - all packets accepted
2046  if (multicastHashEnable)
2047  drop = false;
2048  }
2049 
2050  if (drop) {
2051  DPRINTF(Ethernet, "rxFilter drop\n");
2052  DDUMP(EthernetData, packet->data, packet->length);
2053  }
2054 
2055  return drop;
2056 }
2057 
2058 bool
2060 {
2061  rxBytes += packet->length;
2062  rxPackets++;
2063 
2064  DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
2065  rxFifo.avail());
2066 
2067  if (!rxEnable) {
2068  DPRINTF(Ethernet, "receive disabled...packet dropped\n");
2069  return true;
2070  }
2071 
2072  if (!rxFilterEnable) {
2073  DPRINTF(Ethernet,
2074  "receive packet filtering disabled . . . packet dropped\n");
2075  return true;
2076  }
2077 
2078  if (rxFilter(packet)) {
2079  DPRINTF(Ethernet, "packet filtered...dropped\n");
2080  return true;
2081  }
2082 
2083  if (rxFifo.avail() < packet->length) {
2084 #if TRACING_ON
2085  IpPtr ip(packet);
2086  TcpPtr tcp(ip);
2087  if (ip) {
2088  DPRINTF(Ethernet,
2089  "packet won't fit in receive buffer...pkt ID %d dropped\n",
2090  ip->id());
2091  if (tcp) {
2092  DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
2093  }
2094  }
2095 #endif
2096  droppedPackets++;
2098  return false;
2099  }
2100 
2101  rxFifo.push(packet);
2102 
2103  rxKick();
2104  return true;
2105 }
2106 
2107 
2108 void
2110 {
2112 
2113  // During drain we could have left the state machines in a waiting state and
2114  // they wouldn't get out until some other event occured to kick them.
2115  // This way they'll get out immediately
2116  txKick();
2117  rxKick();
2118 }
2119 
2120 
2121 //=====================================================================
2122 //
2123 //
2124 void
2126 {
2127  // Serialize the PciDevice base class
2129 
2130  /*
2131  * Finalize any DMA events now.
2132  */
2133  // @todo will mem system save pending dma?
2134 
2135  /*
2136  * Serialize the device registers
2137  */
2172 
2173  SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2175 
2177 
2178  /*
2179  * Serialize the data Fifos
2180  */
2181  rxFifo.serialize("rxFifo", cp);
2182  txFifo.serialize("txFifo", cp);
2183 
2184  /*
2185  * Serialize the various helper variables
2186  */
2187  bool txPacketExists = txPacket != nullptr;
2188  SERIALIZE_SCALAR(txPacketExists);
2189  if (txPacketExists) {
2190  txPacket->simLength = txPacketBufPtr - txPacket->data;
2191  txPacket->length = txPacketBufPtr - txPacket->data;
2192  txPacket->serialize("txPacket", cp);
2193  uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
2194  SERIALIZE_SCALAR(txPktBufPtr);
2195  }
2196 
2197  bool rxPacketExists = rxPacket != nullptr;
2198  SERIALIZE_SCALAR(rxPacketExists);
2199  if (rxPacketExists) {
2200  rxPacket->serialize("rxPacket", cp);
2201  uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
2202  SERIALIZE_SCALAR(rxPktBufPtr);
2203  }
2204 
2207 
2208  /*
2209  * Serialize Cached Descriptors
2210  */
2228 
2229  /*
2230  * Serialize tx state machine
2231  */
2232  int txState = this->txState;
2233  SERIALIZE_SCALAR(txState);
2238  int txDmaState = this->txDmaState;
2239  SERIALIZE_SCALAR(txDmaState);
2241 
2242  /*
2243  * Serialize rx state machine
2244  */
2245  int rxState = this->rxState;
2246  SERIALIZE_SCALAR(rxState);
2252  int rxDmaState = this->rxDmaState;
2253  SERIALIZE_SCALAR(rxDmaState);
2255 
2256  /*
2257  * Serialize EEPROM state machine
2258  */
2259  int eepromState = this->eepromState;
2260  SERIALIZE_SCALAR(eepromState);
2266 
2267  /*
2268  * If there's a pending transmit, store the time so we can
2269  * reschedule it later
2270  */
2271  Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick() : 0;
2272  SERIALIZE_SCALAR(transmitTick);
2273 
2274  /*
2275  * receive address filter settings
2276  */
2284 
2285  /*
2286  * Keep track of pending interrupt status.
2287  */
2290  Tick intrEventTick = 0;
2291  if (intrEvent)
2292  intrEventTick = intrEvent->when();
2293  SERIALIZE_SCALAR(intrEventTick);
2294 
2295 }
2296 
2297 void
2299 {
2300  // Unserialize the PciDevice base class
2302 
2337 
2338  UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2340 
2342 
2343  /*
2344  * unserialize the data fifos
2345  */
2346  rxFifo.unserialize("rxFifo", cp);
2347  txFifo.unserialize("txFifo", cp);
2348 
2349  /*
2350  * unserialize the various helper variables
2351  */
2352  bool txPacketExists;
2353  UNSERIALIZE_SCALAR(txPacketExists);
2354  if (txPacketExists) {
2355  txPacket = make_shared<EthPacketData>(16384);
2356  txPacket->unserialize("txPacket", cp);
2357  uint32_t txPktBufPtr;
2358  UNSERIALIZE_SCALAR(txPktBufPtr);
2359  txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2360  } else
2361  txPacket = 0;
2362 
2363  bool rxPacketExists;
2364  UNSERIALIZE_SCALAR(rxPacketExists);
2365  rxPacket = 0;
2366  if (rxPacketExists) {
2367  rxPacket = make_shared<EthPacketData>();
2368  rxPacket->unserialize("rxPacket", cp);
2369  uint32_t rxPktBufPtr;
2370  UNSERIALIZE_SCALAR(rxPktBufPtr);
2371  rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2372  } else
2373  rxPacket = 0;
2374 
2377 
2378  /*
2379  * Unserialize Cached Descriptors
2380  */
2398 
2399  /*
2400  * unserialize tx state machine
2401  */
2402  int txState;
2403  UNSERIALIZE_SCALAR(txState);
2404  this->txState = (TxState) txState;
2409  int txDmaState;
2410  UNSERIALIZE_SCALAR(txDmaState);
2411  this->txDmaState = (DmaState) txDmaState;
2413  if (txKickTick)
2415 
2416  /*
2417  * unserialize rx state machine
2418  */
2419  int rxState;
2420  UNSERIALIZE_SCALAR(rxState);
2421  this->rxState = (RxState) rxState;
2427  int rxDmaState;
2428  UNSERIALIZE_SCALAR(rxDmaState);
2429  this->rxDmaState = (DmaState) rxDmaState;
2431  if (rxKickTick)
2433 
2434  /*
2435  * Unserialize EEPROM state machine
2436  */
2437  int eepromState;
2438  UNSERIALIZE_SCALAR(eepromState);
2439  this->eepromState = (EEPROMState) eepromState;
2445 
2446  /*
2447  * If there's a pending transmit, reschedule it now
2448  */
2449  Tick transmitTick;
2450  UNSERIALIZE_SCALAR(transmitTick);
2451  if (transmitTick)
2452  schedule(txEvent, curTick() + transmitTick);
2453 
2454  /*
2455  * unserialize receive address filter settings
2456  */
2464 
2465  /*
2466  * Keep track of pending interrupt status.
2467  */
2470  Tick intrEventTick;
2471  UNSERIALIZE_SCALAR(intrEventTick);
2472  if (intrEventTick) {
2473  intrEvent = new IntrEvent(this, true);
2474  schedule(intrEvent, intrEventTick);
2475  }
2476 }
2477 
2478 NSGigE *
2479 NSGigEParams::create()
2480 {
2481  return new NSGigE(this);
2482 }
#define DPRINTF(x,...)
Definition: trace.hh:212
void txDmaWriteDone()
Definition: ns_gige.cc:1557
uint16_t type() const
Definition: inet.hh:130
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: ns_gige.cc:2298
EthPacketPtr front()
Definition: pktfifo.hh:120
void set(T v, ByteOrder endian)
Set the value in the data pointer to v using the specified endianness.
bool cpuPendingIntr
Definition: ns_gige.hh:337
EventWrapper< NSGigE,&NSGigE::cpuInterrupt > IntrEvent
Definition: ns_gige.hh:342
bool multicast() const
Definition: inet.hh:97
Stats::Scalar postedSwi
Definition: etherdevice.hh:95
Bitfield< 5, 3 > reg
Definition: types.hh:89
uint32_t cmdsts
Definition: ns_gige_reg.h:366
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Definition: device.cc:490
Stats::Scalar totalRxIdle
Definition: etherdevice.hh:100
TxEvent txEvent
Definition: ns_gige.hh:311
NSGigE(Params *params)
Definition: ns_gige.cc:99
void breakpoint()
Definition: debug.cc:52
Addr rxDmaAddr
Definition: ns_gige.hh:247
const uint8_t EEPROM_READ
Definition: ns_gige.hh:55
bool rxEnable
Definition: ns_gige.hh:215
void dmaRead(Addr addr, int size, Event *event, uint8_t *data, Tick delay=0)
Definition: dma_device.hh:170
Stats::Scalar descDmaReads
Definition: etherdevice.hh:83
Addr rxFragPtr
ptr to the next byte in current fragment
Definition: ns_gige.hh:224
void unserialize(const std::string &base, CheckpointIn &cp)
Definition: pktfifo.cc:101
Stats::Scalar descDmaWrites
Definition: etherdevice.hh:84
uint16_t sum() const
Definition: inet.hh:264
uint32_t mibc
Definition: ns_gige.hh:88
bool eepromClk
Definition: ns_gige.hh:233
void cpuIntrPost(Tick when)
Definition: ns_gige.cc:933
#define panic(...)
Definition: misc.hh:153
void rxDmaWriteDone()
Definition: ns_gige.cc:1110
Dummy class to keep the Python class hierarchy in sync with the C++ object hierarchy.
Definition: etherdevice.hh:134
uint8_t * txPacketBufPtr
Definition: ns_gige.hh:186
Tick intrDelay
Definition: ns_gige.hh:335
DmaState txDmaState
Definition: ns_gige.hh:211
Stats::Scalar totalRxOk
Definition: etherdevice.hh:103
dp_regs regs
device register file
Definition: ns_gige.hh:168
uint16_t cksum(const IpPtr &ptr)
Definition: inet.cc:207
uint32_t tbisr
Definition: ns_gige.hh:94
#define PCI_CONFIG_SIZE
Definition: pcireg.h:152
EEPROMState
EEPROM State Machine States.
Definition: ns_gige.hh:158
bool empty() const
Definition: pktfifo.hh:103
const char * NsRxStateStrings[]
Definition: ns_gige.cc:61
Bitfield< 3 > exit
Definition: misc.hh:849
Stats::Scalar totalTxOk
Definition: etherdevice.hh:109
bool cpuIntrPending() const
Definition: ns_gige.cc:1009
TxState txState
Definition: ns_gige.hh:200
Stats::Scalar rxIpChecksums
Definition: etherdevice.hh:78
void rxDmaReadDone()
Definition: ns_gige.cc:1080
const uint8_t EEPROM_PMATCH2_ADDR
Definition: ns_gige.hh:57
bool broadcast() const
Definition: inet.hh:98
bool acceptBroadcast
Definition: ns_gige.hh:321
void cpuInterrupt()
Definition: ns_gige.cc:967
Stats::Scalar rxUdpChecksums
Definition: etherdevice.hh:82
uint32_t tesr
Definition: ns_gige.hh:98
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:381
#define DDUMP(x, data, count)
Definition: trace.hh:211
EventWrapper< NSGigE,&NSGigE::txDmaReadDone > txDmaReadEvent
Definition: ns_gige.hh:268
uint32_t command
Definition: ns_gige.hh:65
EtherInt * getPeer()
Definition: etherint.hh:63
TxState
Transmit State Machine states.
Definition: ns_gige.hh:125
PacketFifo txFifo
Definition: ns_gige.hh:180
IntrEvent * intrEvent
Definition: ns_gige.hh:344
#define warn_once(...)
Definition: misc.hh:226
bool acceptPerfect
Definition: ns_gige.hh:324
TxKickEvent txKickEvent
Definition: ns_gige.hh:295
Stats::Scalar postedRxIdle
Definition: etherdevice.hh:98
EEPROMState eepromState
EEPROM State Machine.
Definition: ns_gige.hh:232
void dmaWrite(Addr addr, int size, Event *event, uint8_t *data, Tick delay=0)
Definition: dma_device.hh:164
Stats::Scalar totalRxDesc
Definition: etherdevice.hh:106
Bitfield< 23, 0 > offset
Definition: types.hh:149
NSGigEInt * interface
Definition: ns_gige.hh:345
uint32_t ptscr
Definition: ns_gige.hh:68
uint32_t extsts
Definition: ns_gige_reg.h:360
Stats::Scalar rxTcpChecksums
Definition: etherdevice.hh:80
ns_desc64 rxDesc64
Definition: ns_gige.hh:197
const uint16_t FHASH_SIZE
Definition: ns_gige.hh:52
bool doTxDmaRead()
Definition: ns_gige.cc:1513
Stats::Scalar txBytes
Definition: etherdevice.hh:73
ns_desc64 txDesc64
Definition: ns_gige.hh:196
T * getPtr()
get a pointer to the data ptr.
Definition: packet.hh:959
uint64_t link
Definition: ns_gige_reg.h:364
uint32_t rxDescCnt
count of bytes remaining in the current descriptor
Definition: ns_gige.hh:226
void serialize(const std::string &base, CheckpointOut &cp) const
Serialization stuff.
Definition: pktfifo.cc:88
uint32_t rxdp
Definition: ns_gige.hh:77
DmaState rxDmaState
Definition: ns_gige.hh:227
uint32_t cmdsts
Definition: ns_gige_reg.h:359
bool extstsEnable
Definition: ns_gige.hh:229
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
bool rxDmaFree
Definition: ns_gige.hh:190
uint8_t eepromAddress
Definition: ns_gige.hh:236
bool full() const
Definition: pktfifo.hh:104
Tick intrTick
Definition: ns_gige.hh:336
uint32_t wcsr
Definition: ns_gige.hh:81
bool dmaDescFree
Definition: ns_gige.hh:274
void txKick()
Definition: ns_gige.cc:1574
uint16_t id() const
Definition: inet.hh:259
Stats::Scalar postedTxDesc
Definition: etherdevice.hh:113
void transferDone()
Definition: ns_gige.cc:2003
Device module for modelling the National Semiconductor DP83820 ethernet controller.
uint8_t eepromBitsToRx
Definition: ns_gige.hh:234
#define warn(...)
Definition: misc.hh:219
dp_rom rom
Definition: ns_gige.hh:169
Addr txFragPtr
ptr to the next byte in the current fragment
Definition: ns_gige.hh:208
uint32_t ccsr
Definition: ns_gige.hh:92
bool unicast() const
Definition: inet.hh:96
Stats::Scalar postedTxOk
Definition: etherdevice.hh:107
uint32_t brdr
Definition: ns_gige.hh:86
Stats::Scalar rxPackets
Definition: etherdevice.hh:76
int txDmaLen
Definition: ns_gige.hh:254
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:145
ns_desc32 txDesc32
DescCaches.
Definition: ns_gige.hh:194
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...
void regsReset()
Definition: ns_gige.cc:1043
Tick curTick()
The current simulated tick.
Definition: core.hh:47
uint32_t txdp
Definition: ns_gige.hh:73
EthPacketPtr rxPacket
Definition: ns_gige.hh:185
uint32_t bufptr
Definition: ns_gige_reg.h:358
#define DTRACE(x)
Definition: trace.hh:210
const uint8_t EEPROM_PMATCH0_ADDR
Definition: ns_gige.hh:59
DmaState
Definition: ns_gige.hh:148
uint32_t extsts
Definition: ns_gige_reg.h:367
unsigned avail() const
Definition: pktfifo.hh:102
bool tcp(TxDesc *d)
bool acceptUnicast
Definition: ns_gige.hh:323
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:397
PacketFifo rxFifo
Definition: ns_gige.hh:181
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: ns_gige.cc:408
void makeAtomicResponse()
Definition: packet.hh:857
Stats::Scalar totalTxDesc
Definition: etherdevice.hh:115
uint32_t ihr
Definition: ns_gige.hh:72
uint32_t txcfg
Definition: ns_gige.hh:75
DmaDeviceParams Params
Definition: dma_device.hh:160
uint64_t Tick
Tick count type.
Definition: types.hh:63
void * rxDmaData
Definition: ns_gige.hh:246
void devIntrChangeMask()
Definition: ns_gige.cc:921
const uint8_t EEPROM_SIZE
Definition: ns_gige.hh:56
void rxKick()
Definition: ns_gige.cc:1127
bool doTxDmaWrite()
Definition: ns_gige.cc:1544
virtual Tick writeConfig(PacketPtr pkt)
Write to the PCI config space data that is stored locally.
Definition: device.cc:288
uint32_t rxdp_hi
Definition: ns_gige.hh:78
const Params * params() const
Definition: ns_gige.hh:349
void txDmaReadDone()
Definition: ns_gige.cc:1527
void drainResume() override
Resume execution after a successful drain.
Definition: ns_gige.cc:2109
const uint8_t EEPROM_PMATCH1_ADDR
Definition: ns_gige.hh:58
uint32_t gpior
Definition: ns_gige.hh:76
Tick rxKickTick
Definition: ns_gige.hh:286
uint32_t rfdr
Definition: ns_gige.hh:84
uint32_t tanlpar
Definition: ns_gige.hh:96
Addr txDmaAddr
Definition: ns_gige.hh:253
uint32_t rfcr
Definition: ns_gige.hh:83
bool dmaDataFree
Definition: ns_gige.hh:275
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:158
bool CTDD
Current Transmit Descriptor Done.
Definition: ns_gige.hh:204
unsigned size() const
Definition: pktfifo.hh:100
virtual Tick readConfig(PacketPtr pkt)
Read from the PCI config space data that is stored locally.
Definition: device.cc:220
bool acceptMulticast
Definition: ns_gige.hh:322
EventWrapper< NSGigE,&NSGigE::txDmaWriteDone > txDmaWriteEvent
Definition: ns_gige.hh:272
Stats::Scalar totalRxOrn
Definition: etherdevice.hh:118
Stats::Scalar descDmaWrBytes
Definition: etherdevice.hh:86
Stats::Scalar txIpChecksums
Definition: etherdevice.hh:77
bool acceptArp
Definition: ns_gige.hh:325
Stats::Scalar postedTxIdle
Definition: etherdevice.hh:110
~NSGigE()
Definition: ns_gige.cc:138
std::shared_ptr< EthPacketData > EthPacketPtr
Definition: etherpkt.hh:90
uint16_t sum() const
Definition: inet.hh:619
Stats::Scalar droppedPackets
Definition: etherdevice.hh:121
uint32_t config
Definition: ns_gige.hh:66
bool multicastHashEnable
Definition: ns_gige.hh:326
Stats::Scalar descDmaRdBytes
Definition: etherdevice.hh:85
#define PCI_DEVICE_SPECIFIC
Definition: pcireg.h:151
unsigned reserve(unsigned len=0)
Definition: pktfifo.hh:107
uint32_t pqcr
Definition: ns_gige.hh:80
Tick pioDelay
Definition: device.hh:185
void txReset()
Definition: ns_gige.cc:1013
uint32_t srr
Definition: ns_gige.hh:87
void squash()
Squash the current event.
Definition: eventq.hh:384
void * txDmaData
Definition: ns_gige.hh:252
void transmit()
Retransmit event.
Definition: ns_gige.cc:1462
Tick configDelay
Definition: device.hh:186
bool ioEnable
pci settings
Definition: ns_gige.hh:172
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
int rxDmaLen
Definition: ns_gige.hh:248
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
EtherInt * getEthPort(const std::string &if_name, int idx) override
Additional function to return the Port of a memory object.
Definition: ns_gige.cc:171
const uint16_t FHASH_ADDR
Definition: ns_gige.hh:51
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
bool rxFilter(const EthPacketPtr &packet)
Definition: ns_gige.cc:2016
Stats::Scalar postedRxOk
Definition: etherdevice.hh:101
Stats::Scalar rxBytes
Definition: etherdevice.hh:74
Stats::Scalar totalTxIdle
Definition: etherdevice.hh:112
RxState
Receive State Machine States.
Definition: ns_gige.hh:137
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:143
const char * NsTxStateStrings[]
Definition: ns_gige.cc:72
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:161
uint32_t vrcr
Definition: ns_gige.hh:89
bool sendPacket(EthPacketPtr packet)
Definition: etherint.hh:68
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: ns_gige.cc:2125
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:740
Stats::Scalar txUdpChecksums
Definition: etherdevice.hh:81
EthPacketPtr txPacket
various helper vars
Definition: ns_gige.hh:184
Stats::Scalar postedRxOrn
Definition: etherdevice.hh:116
uint8_t filterHash[FHASH_SIZE]
for hash table memory.
Definition: ns_gige.hh:112
type
Definition: misc.hh:728
ns_desc32 rxDesc32
Definition: ns_gige.hh:195
uint32_t vdr
Definition: ns_gige.hh:91
Stats::Scalar postedRxDesc
Definition: etherdevice.hh:104
uint32_t rxcfg
Definition: ns_gige.hh:79
Tick writeConfig(PacketPtr pkt) override
This is to write to the PCI general configuration registers.
Definition: ns_gige.cc:147
EventWrapper< NSGigE,&NSGigE::rxDmaReadDone > rxDmaReadEvent
Definition: ns_gige.hh:260
Tick read(PacketPtr pkt) override
This reads the device registers, which are detailed in the NS83820 spec sheet.
Definition: ns_gige.cc:186
Declaration of the Packet class.
uint32_t vtcr
Definition: ns_gige.hh:90
std::ostream CheckpointOut
Definition: serialize.hh:67
void cpuIntrClear()
Definition: ns_gige.cc:990
uint32_t brar
Definition: ns_gige.hh:85
uint16_t eepromData
Definition: ns_gige.hh:237
bool doRxDmaWrite()
Definition: ns_gige.cc:1097
RxKickEvent rxKickEvent
Definition: ns_gige.hh:289
uint64_t bufptr
Definition: ns_gige_reg.h:365
uint8_t data[64]
Definition: pcireg.h:57
uint32_t tbicr
Definition: ns_gige.hh:93
#define PCI_CMD_IOSE
Definition: pcireg.h:106
Definition: ns_gige_reg.h:41
virtual void drainResume()
Resume execution after a successful drain.
Definition: drain.hh:257
bool txEnable
Definition: ns_gige.hh:201
uint32_t txXferLen
Definition: ns_gige.hh:188
const EthAddr & dst() const
Definition: inet.hh:146
uint8_t perfectMatch[ETH_ADDR_LEN]
for perfect match memory.
Definition: ns_gige.hh:106
uint32_t txDescCnt
count of bytes remaining in the current descriptor
Definition: ns_gige.hh:210
const Tick retryTime
Definition: core.hh:49
void schedule(Event &event, Tick when)
Definition: eventq.hh:728
uint8_t eepromOpcode
Definition: ns_gige.hh:235
EventWrapper< NSGigE,&NSGigE::rxDmaWriteDone > rxDmaWriteEvent
Definition: ns_gige.hh:264
uint32_t link
Definition: ns_gige_reg.h:357
uint32_t tanar
Definition: ns_gige.hh:95
void devIntrPost(uint32_t interrupts)
Interrupt management.
Definition: ns_gige.cc:822
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:282
uint32_t isr
Definition: ns_gige.hh:69
uint32_t pcr
Definition: ns_gige.hh:82
void rxReset()
Definition: ns_gige.cc:1028
Stats::Scalar totalSwi
Definition: etherdevice.hh:97
bool ip(TxDesc *d)
bool rxFilterEnable
receive address filter
Definition: ns_gige.hh:319
uint16_t sum() const
Definition: inet.hh:519
RxState rxState
rx State Machine
Definition: ns_gige.hh:214
NS DP83820 Ethernet device model.
Definition: ns_gige.hh:121
uint32_t imr
Definition: ns_gige.hh:70
unsigned getSize() const
Definition: packet.hh:649
bool doRxDmaRead()
Definition: ns_gige.cc:1066
bool CRDD
Current Receive Descriptor Done.
Definition: ns_gige.hh:218
bool dmaPending() const
Definition: dma_device.hh:176
bool txDmaFree
Definition: ns_gige.hh:191
void pop()
Definition: pktfifo.hh:139
void clear()
Definition: pktfifo.hh:151
void devIntrClear(uint32_t interrupts)
Definition: ns_gige.cc:879
uint8_t * rxPacketBufPtr
Definition: ns_gige.hh:187
void intrPost()
Definition: device.hh:193
bool push(EthPacketPtr ptr)
Definition: pktfifo.hh:122
PCIConfig config
The current config space.
Definition: device.hh:76
Stats::Scalar postedInterrupts
Definition: etherdevice.hh:120
Bitfield< 0 > p
uint32_t taner
Definition: ns_gige.hh:97
uint32_t txdp_hi
Definition: ns_gige.hh:74
uint32_t seq() const
Definition: inet.hh:514
const char * NsDmaState[]
Definition: ns_gige.cc:83
void eepromKick()
Advance the EEPROM state machine Called on rising edge of EEPROM clock bit in MEAR.
Definition: ns_gige.cc:1906
uint32_t mear
Definition: ns_gige.hh:67
void intrClear()
Definition: device.hh:194
uint32_t ier
Definition: ns_gige.hh:71
uint32_t rxPktBytes
num of bytes in the current packet being drained from rxDataFifo
Definition: ns_gige.hh:220
uint32_t rxXferLen
Definition: ns_gige.hh:189
Tick txKickTick
Definition: ns_gige.hh:292
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
Definition: device.cc:425
Stats::Scalar txTcpChecksums
Definition: etherdevice.hh:79
Addr getAddr() const
Definition: packet.hh:639
Stats::Scalar txPackets
Definition: etherdevice.hh:75
bool recvPacket(EthPacketPtr packet)
Definition: ns_gige.cc:2059
#define PCI_COMMAND
Definition: pcireg.h:92

Generated on Fri Jun 9 2017 13:03:46 for gem5 by doxygen 1.8.6