summaryrefslogtreecommitdiff
path: root/src/dev/ns_gige.cc
diff options
context:
space:
mode:
authorAndreas Sandberg <andreas.sandberg@arm.com>2015-12-10 10:35:18 +0000
committerAndreas Sandberg <andreas.sandberg@arm.com>2015-12-10 10:35:18 +0000
commit23c961a0fd97251ee7c760bc2ff2a011a417ad9b (patch)
tree0481b7552303373cd3722156b1cef92d813de215 /src/dev/ns_gige.cc
parentef097ac4381ad2f14acda640ae198f04d9f7988d (diff)
downloadgem5-23c961a0fd97251ee7c760bc2ff2a011a417ad9b.tar.xz
dev: Move network devices to src/dev/net/
--HG-- rename : src/dev/Ethernet.py => src/dev/net/Ethernet.py rename : src/dev/etherbus.cc => src/dev/net/etherbus.cc rename : src/dev/etherbus.hh => src/dev/net/etherbus.hh rename : src/dev/etherdevice.cc => src/dev/net/etherdevice.cc rename : src/dev/etherdevice.hh => src/dev/net/etherdevice.hh rename : src/dev/etherdump.cc => src/dev/net/etherdump.cc rename : src/dev/etherdump.hh => src/dev/net/etherdump.hh rename : src/dev/etherint.cc => src/dev/net/etherint.cc rename : src/dev/etherint.hh => src/dev/net/etherint.hh rename : src/dev/etherlink.cc => src/dev/net/etherlink.cc rename : src/dev/etherlink.hh => src/dev/net/etherlink.hh rename : src/dev/etherobject.hh => src/dev/net/etherobject.hh rename : src/dev/etherpkt.cc => src/dev/net/etherpkt.cc rename : src/dev/etherpkt.hh => src/dev/net/etherpkt.hh rename : src/dev/ethertap.cc => src/dev/net/ethertap.cc rename : src/dev/ethertap.hh => src/dev/net/ethertap.hh rename : src/dev/i8254xGBe.cc => src/dev/net/i8254xGBe.cc rename : src/dev/i8254xGBe.hh => src/dev/net/i8254xGBe.hh rename : src/dev/i8254xGBe_defs.hh => src/dev/net/i8254xGBe_defs.hh rename : src/dev/multi_etherlink.cc => src/dev/net/multi_etherlink.cc rename : src/dev/multi_etherlink.hh => src/dev/net/multi_etherlink.hh rename : src/dev/multi_iface.cc => src/dev/net/multi_iface.cc rename : src/dev/multi_iface.hh => src/dev/net/multi_iface.hh rename : src/dev/multi_packet.cc => src/dev/net/multi_packet.cc rename : src/dev/multi_packet.hh => src/dev/net/multi_packet.hh rename : src/dev/ns_gige.cc => src/dev/net/ns_gige.cc rename : src/dev/ns_gige.hh => src/dev/net/ns_gige.hh rename : src/dev/ns_gige_reg.h => src/dev/net/ns_gige_reg.h rename : src/dev/pktfifo.cc => src/dev/net/pktfifo.cc rename : src/dev/pktfifo.hh => src/dev/net/pktfifo.hh rename : src/dev/sinic.cc => src/dev/net/sinic.cc rename : src/dev/sinic.hh => src/dev/net/sinic.hh rename : src/dev/sinicreg.hh => src/dev/net/sinicreg.hh rename : src/dev/tcp_iface.cc => src/dev/net/tcp_iface.cc rename : src/dev/tcp_iface.hh => src/dev/net/tcp_iface.hh
Diffstat (limited to 'src/dev/ns_gige.cc')
-rw-r--r--src/dev/ns_gige.cc2481
1 files changed, 0 insertions, 2481 deletions
diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc
deleted file mode 100644
index eb4f0eb64..000000000
--- a/src/dev/ns_gige.cc
+++ /dev/null
@@ -1,2481 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Nathan Binkert
- * Lisa Hsu
- */
-
-/** @file
- * Device module for modelling the National Semiconductor
- * DP83820 ethernet controller. Does not support priority queueing
- */
-#include <deque>
-#include <memory>
-#include <string>
-
-#include "base/debug.hh"
-#include "base/inet.hh"
-#include "base/types.hh"
-#include "config/the_isa.hh"
-#include "debug/EthernetAll.hh"
-#include "dev/etherlink.hh"
-#include "dev/ns_gige.hh"
-#include "mem/packet.hh"
-#include "mem/packet_access.hh"
-#include "params/NSGigE.hh"
-#include "sim/system.hh"
-
-// clang complains about std::set being overloaded with Packet::set if
-// we open up the entire namespace std
-using std::make_shared;
-using std::min;
-using std::ostream;
-using std::string;
-
-const char *NsRxStateStrings[] =
-{
- "rxIdle",
- "rxDescRefr",
- "rxDescRead",
- "rxFifoBlock",
- "rxFragWrite",
- "rxDescWrite",
- "rxAdvance"
-};
-
-const char *NsTxStateStrings[] =
-{
- "txIdle",
- "txDescRefr",
- "txDescRead",
- "txFifoBlock",
- "txFragRead",
- "txDescWrite",
- "txAdvance"
-};
-
-const char *NsDmaState[] =
-{
- "dmaIdle",
- "dmaReading",
- "dmaWriting",
- "dmaReadWaiting",
- "dmaWriteWaiting"
-};
-
-using namespace Net;
-using namespace TheISA;
-
-///////////////////////////////////////////////////////////////////////
-//
-// NSGigE PCI Device
-//
-NSGigE::NSGigE(Params *p)
- : EtherDevBase(p), ioEnable(false),
- txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
- txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
- txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false),
- txState(txIdle), txEnable(false), CTDD(false), txHalt(false),
- txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
- rxEnable(false), CRDD(false), rxPktBytes(0), rxHalt(false),
- rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
- eepromState(eepromStart), eepromClk(false), eepromBitsToRx(0),
- eepromOpcode(0), eepromAddress(0), eepromData(0),
- dmaReadDelay(p->dma_read_delay), dmaWriteDelay(p->dma_write_delay),
- dmaReadFactor(p->dma_read_factor), dmaWriteFactor(p->dma_write_factor),
- rxDmaData(NULL), rxDmaAddr(0), rxDmaLen(0),
- txDmaData(NULL), txDmaAddr(0), txDmaLen(0),
- rxDmaReadEvent(this), rxDmaWriteEvent(this),
- txDmaReadEvent(this), txDmaWriteEvent(this),
- dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
- txDelay(p->tx_delay), rxDelay(p->rx_delay),
- rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
- txEvent(this), rxFilterEnable(p->rx_filter),
- acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false),
- acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
- intrDelay(p->intr_delay), intrTick(0), cpuPendingIntr(false),
- intrEvent(0), interface(0)
-{
-
-
- interface = new NSGigEInt(name() + ".int0", this);
-
- regsReset();
- memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN);
-
- memset(&rxDesc32, 0, sizeof(rxDesc32));
- memset(&txDesc32, 0, sizeof(txDesc32));
- memset(&rxDesc64, 0, sizeof(rxDesc64));
- memset(&txDesc64, 0, sizeof(txDesc64));
-}
-
-NSGigE::~NSGigE()
-{
- delete interface;
-}
-
-/**
- * This is to write to the PCI general configuration registers
- */
-Tick
-NSGigE::writeConfig(PacketPtr pkt)
-{
- int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
- if (offset < PCI_DEVICE_SPECIFIC)
- PciDevice::writeConfig(pkt);
- else
- panic("Device specific PCI config space not implemented!\n");
-
- switch (offset) {
- // seems to work fine without all these PCI settings, but i
- // put in the IO to double check, an assertion will fail if we
- // need to properly implement it
- case PCI_COMMAND:
- if (config.data[offset] & PCI_CMD_IOSE)
- ioEnable = true;
- else
- ioEnable = false;
- break;
- }
-
- return configDelay;
-}
-
-EtherInt*
-NSGigE::getEthPort(const std::string &if_name, int idx)
-{
- if (if_name == "interface") {
- if (interface->getPeer())
- panic("interface already connected to\n");
- return interface;
- }
- return NULL;
-}
-
-/**
- * This reads the device registers, which are detailed in the NS83820
- * spec sheet
- */
-Tick
-NSGigE::read(PacketPtr pkt)
-{
- assert(ioEnable);
-
- //The mask is to give you only the offset into the device register file
- Addr daddr = pkt->getAddr() & 0xfff;
- DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n",
- daddr, pkt->getAddr(), pkt->getSize());
-
-
- // there are some reserved registers, you can see ns_gige_reg.h and
- // the spec sheet for details
- if (daddr > LAST && daddr <= RESERVED) {
- panic("Accessing reserved register");
- } else if (daddr > RESERVED && daddr <= 0x3FC) {
- return readConfig(pkt);
- } else if (daddr >= MIB_START && daddr <= MIB_END) {
- // don't implement all the MIB's. hopefully the kernel
- // doesn't actually DEPEND upon their values
- // MIB are just hardware stats keepers
- pkt->set<uint32_t>(0);
- pkt->makeAtomicResponse();
- return pioDelay;
- } else if (daddr > 0x3FC)
- panic("Something is messed up!\n");
-
- assert(pkt->getSize() == sizeof(uint32_t));
- uint32_t &reg = *pkt->getPtr<uint32_t>();
- uint16_t rfaddr;
-
- switch (daddr) {
- case CR:
- reg = regs.command;
- //these are supposed to be cleared on a read
- reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
- break;
-
- case CFGR:
- reg = regs.config;
- break;
-
- case MEAR:
- reg = regs.mear;
- break;
-
- case PTSCR:
- reg = regs.ptscr;
- break;
-
- case ISR:
- reg = regs.isr;
- devIntrClear(ISR_ALL);
- break;
-
- case IMR:
- reg = regs.imr;
- break;
-
- case IER:
- reg = regs.ier;
- break;
-
- case IHR:
- reg = regs.ihr;
- break;
-
- case TXDP:
- reg = regs.txdp;
- break;
-
- case TXDP_HI:
- reg = regs.txdp_hi;
- break;
-
- case TX_CFG:
- reg = regs.txcfg;
- break;
-
- case GPIOR:
- reg = regs.gpior;
- break;
-
- case RXDP:
- reg = regs.rxdp;
- break;
-
- case RXDP_HI:
- reg = regs.rxdp_hi;
- break;
-
- case RX_CFG:
- reg = regs.rxcfg;
- break;
-
- case PQCR:
- reg = regs.pqcr;
- break;
-
- case WCSR:
- reg = regs.wcsr;
- break;
-
- case PCR:
- reg = regs.pcr;
- break;
-
- // see the spec sheet for how RFCR and RFDR work
- // basically, you write to RFCR to tell the machine
- // what you want to do next, then you act upon RFDR,
- // and the device will be prepared b/c of what you
- // wrote to RFCR
- case RFCR:
- reg = regs.rfcr;
- break;
-
- case RFDR:
- rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
- switch (rfaddr) {
- // Read from perfect match ROM octets
- case 0x000:
- reg = rom.perfectMatch[1];
- reg = reg << 8;
- reg += rom.perfectMatch[0];
- break;
- case 0x002:
- reg = rom.perfectMatch[3] << 8;
- reg += rom.perfectMatch[2];
- break;
- case 0x004:
- reg = rom.perfectMatch[5] << 8;
- reg += rom.perfectMatch[4];
- break;
- default:
- // Read filter hash table
- if (rfaddr >= FHASH_ADDR &&
- rfaddr < FHASH_ADDR + FHASH_SIZE) {
-
- // Only word-aligned reads supported
- if (rfaddr % 2)
- panic("unaligned read from filter hash table!");
-
- reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
- reg += rom.filterHash[rfaddr - FHASH_ADDR];
- break;
- }
-
- panic("reading RFDR for something other than pattern"
- " matching or hashing! %#x\n", rfaddr);
- }
- break;
-
- case SRR:
- reg = regs.srr;
- break;
-
- case MIBC:
- reg = regs.mibc;
- reg &= ~(MIBC_MIBS | MIBC_ACLR);
- break;
-
- case VRCR:
- reg = regs.vrcr;
- break;
-
- case VTCR:
- reg = regs.vtcr;
- break;
-
- case VDR:
- reg = regs.vdr;
- break;
-
- case CCSR:
- reg = regs.ccsr;
- break;
-
- case TBICR:
- reg = regs.tbicr;
- break;
-
- case TBISR:
- reg = regs.tbisr;
- break;
-
- case TANAR:
- reg = regs.tanar;
- break;
-
- case TANLPAR:
- reg = regs.tanlpar;
- break;
-
- case TANER:
- reg = regs.taner;
- break;
-
- case TESR:
- reg = regs.tesr;
- break;
-
- case M5REG:
- reg = 0;
- if (params()->rx_thread)
- reg |= M5REG_RX_THREAD;
- if (params()->tx_thread)
- reg |= M5REG_TX_THREAD;
- if (params()->rss)
- reg |= M5REG_RSS;
- break;
-
- default:
- panic("reading unimplemented register: addr=%#x", daddr);
- }
-
- DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
- daddr, reg, reg);
-
- pkt->makeAtomicResponse();
- return pioDelay;
-}
-
-Tick
-NSGigE::write(PacketPtr pkt)
-{
- assert(ioEnable);
-
- Addr daddr = pkt->getAddr() & 0xfff;
- DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
- daddr, pkt->getAddr(), pkt->getSize());
-
- if (daddr > LAST && daddr <= RESERVED) {
- panic("Accessing reserved register");
- } else if (daddr > RESERVED && daddr <= 0x3FC) {
- return writeConfig(pkt);
- } else if (daddr > 0x3FC)
- panic("Something is messed up!\n");
-
- if (pkt->getSize() == sizeof(uint32_t)) {
- uint32_t reg = pkt->get<uint32_t>();
- uint16_t rfaddr;
-
- DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
-
- switch (daddr) {
- case CR:
- regs.command = reg;
- if (reg & CR_TXD) {
- txEnable = false;
- } else if (reg & CR_TXE) {
- txEnable = true;
-
- // the kernel is enabling the transmit machine
- if (txState == txIdle)
- txKick();
- }
-
- if (reg & CR_RXD) {
- rxEnable = false;
- } else if (reg & CR_RXE) {
- rxEnable = true;
-
- if (rxState == rxIdle)
- rxKick();
- }
-
- if (reg & CR_TXR)
- txReset();
-
- if (reg & CR_RXR)
- rxReset();
-
- if (reg & CR_SWI)
- devIntrPost(ISR_SWI);
-
- if (reg & CR_RST) {
- txReset();
- rxReset();
-
- regsReset();
- }
- break;
-
- case CFGR:
- if (reg & CFGR_LNKSTS ||
- reg & CFGR_SPDSTS ||
- reg & CFGR_DUPSTS ||
- reg & CFGR_RESERVED ||
- reg & CFGR_T64ADDR ||
- reg & CFGR_PCI64_DET) {
- // First clear all writable bits
- regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
- CFGR_RESERVED | CFGR_T64ADDR |
- CFGR_PCI64_DET;
- // Now set the appropriate writable bits
- regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
- CFGR_RESERVED | CFGR_T64ADDR |
- CFGR_PCI64_DET);
- }
-
-// all these #if 0's are because i don't THINK the kernel needs to
-// have these implemented. if there is a problem relating to one of
-// these, you may need to add functionality in.
-
-// grouped together and #if 0'ed to avoid empty if body and make clang happy
-#if 0
- if (reg & CFGR_TBI_EN) ;
- if (reg & CFGR_MODE_1000) ;
-
- if (reg & CFGR_PINT_DUPSTS ||
- reg & CFGR_PINT_LNKSTS ||
- reg & CFGR_PINT_SPDSTS)
- ;
-
- if (reg & CFGR_TMRTEST) ;
- if (reg & CFGR_MRM_DIS) ;
- if (reg & CFGR_MWI_DIS) ;
-
- if (reg & CFGR_DATA64_EN) ;
- if (reg & CFGR_M64ADDR) ;
- if (reg & CFGR_PHY_RST) ;
- if (reg & CFGR_PHY_DIS) ;
-
- if (reg & CFGR_REQALG) ;
- if (reg & CFGR_SB) ;
- if (reg & CFGR_POW) ;
- if (reg & CFGR_EXD) ;
- if (reg & CFGR_PESEL) ;
- if (reg & CFGR_BROM_DIS) ;
- if (reg & CFGR_EXT_125) ;
- if (reg & CFGR_BEM) ;
-
- if (reg & CFGR_T64ADDR) ;
- // panic("CFGR_T64ADDR is read only register!\n");
-#endif
- if (reg & CFGR_AUTO_1000)
- panic("CFGR_AUTO_1000 not implemented!\n");
-
- if (reg & CFGR_PCI64_DET)
- panic("CFGR_PCI64_DET is read only register!\n");
-
- if (reg & CFGR_EXTSTS_EN)
- extstsEnable = true;
- else
- extstsEnable = false;
- break;
-
- case MEAR:
- // Clear writable bits
- regs.mear &= MEAR_EEDO;
- // Set appropriate writable bits
- regs.mear |= reg & ~MEAR_EEDO;
-
- // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
- // even though it could get it through RFDR
- if (reg & MEAR_EESEL) {
- // Rising edge of clock
- if (reg & MEAR_EECLK && !eepromClk)
- eepromKick();
- }
- else {
- eepromState = eepromStart;
- regs.mear &= ~MEAR_EEDI;
- }
-
- eepromClk = reg & MEAR_EECLK;
-
- // since phy is completely faked, MEAR_MD* don't matter
-
-// grouped together and #if 0'ed to avoid empty if body and make clang happy
-#if 0
- if (reg & MEAR_MDIO) ;
- if (reg & MEAR_MDDIR) ;
- if (reg & MEAR_MDC) ;
-#endif
- break;
-
- case PTSCR:
- regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
- // these control BISTs for various parts of chip - we
- // don't care or do just fake that the BIST is done
- if (reg & PTSCR_RBIST_EN)
- regs.ptscr |= PTSCR_RBIST_DONE;
- if (reg & PTSCR_EEBIST_EN)
- regs.ptscr &= ~PTSCR_EEBIST_EN;
- if (reg & PTSCR_EELOAD_EN)
- regs.ptscr &= ~PTSCR_EELOAD_EN;
- break;
-
- case ISR: /* writing to the ISR has no effect */
- panic("ISR is a read only register!\n");
-
- case IMR:
- regs.imr = reg;
- devIntrChangeMask();
- break;
-
- case IER:
- regs.ier = reg;
- break;
-
- case IHR:
- regs.ihr = reg;
- /* not going to implement real interrupt holdoff */
- break;
-
- case TXDP:
- regs.txdp = (reg & 0xFFFFFFFC);
- assert(txState == txIdle);
- CTDD = false;
- break;
-
- case TXDP_HI:
- regs.txdp_hi = reg;
- break;
-
- case TX_CFG:
- regs.txcfg = reg;
-#if 0
- if (reg & TX_CFG_CSI) ;
- if (reg & TX_CFG_HBI) ;
- if (reg & TX_CFG_MLB) ;
- if (reg & TX_CFG_ATP) ;
- if (reg & TX_CFG_ECRETRY) {
- /*
- * this could easily be implemented, but considering
- * the network is just a fake pipe, wouldn't make
- * sense to do this
- */
- }
-
- if (reg & TX_CFG_BRST_DIS) ;
-#endif
-
-#if 0
- /* we handle our own DMA, ignore the kernel's exhortations */
- if (reg & TX_CFG_MXDMA) ;
-#endif
-
- // also, we currently don't care about fill/drain
- // thresholds though this may change in the future with
- // more realistic networks or a driver which changes it
- // according to feedback
-
- break;
-
- case GPIOR:
- // Only write writable bits
- regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
- | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN;
- regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
- | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN);
- /* these just control general purpose i/o pins, don't matter */
- break;
-
- case RXDP:
- regs.rxdp = reg;
- CRDD = false;
- break;
-
- case RXDP_HI:
- regs.rxdp_hi = reg;
- break;
-
- case RX_CFG:
- regs.rxcfg = reg;
-#if 0
- if (reg & RX_CFG_AEP) ;
- if (reg & RX_CFG_ARP) ;
- if (reg & RX_CFG_STRIPCRC) ;
- if (reg & RX_CFG_RX_RD) ;
- if (reg & RX_CFG_ALP) ;
- if (reg & RX_CFG_AIRL) ;
-
- /* we handle our own DMA, ignore what kernel says about it */
- if (reg & RX_CFG_MXDMA) ;
-
- //also, we currently don't care about fill/drain thresholds
- //though this may change in the future with more realistic
- //networks or a driver which changes it according to feedback
- if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
-#endif
- break;
-
- case PQCR:
- /* there is no priority queueing used in the linux 2.6 driver */
- regs.pqcr = reg;
- break;
-
- case WCSR:
- /* not going to implement wake on LAN */
- regs.wcsr = reg;
- break;
-
- case PCR:
- /* not going to implement pause control */
- regs.pcr = reg;
- break;
-
- case RFCR:
- regs.rfcr = reg;
-
- rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
- acceptBroadcast = (reg & RFCR_AAB) ? true : false;
- acceptMulticast = (reg & RFCR_AAM) ? true : false;
- acceptUnicast = (reg & RFCR_AAU) ? true : false;
- acceptPerfect = (reg & RFCR_APM) ? true : false;
- acceptArp = (reg & RFCR_AARP) ? true : false;
- multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
-
-#if 0
- if (reg & RFCR_APAT)
- panic("RFCR_APAT not implemented!\n");
-#endif
- if (reg & RFCR_UHEN)
- panic("Unicast hash filtering not used by drivers!\n");
-
- if (reg & RFCR_ULM)
- panic("RFCR_ULM not implemented!\n");
-
- break;
-
- case RFDR:
- rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
- switch (rfaddr) {
- case 0x000:
- rom.perfectMatch[0] = (uint8_t)reg;
- rom.perfectMatch[1] = (uint8_t)(reg >> 8);
- break;
- case 0x002:
- rom.perfectMatch[2] = (uint8_t)reg;
- rom.perfectMatch[3] = (uint8_t)(reg >> 8);
- break;
- case 0x004:
- rom.perfectMatch[4] = (uint8_t)reg;
- rom.perfectMatch[5] = (uint8_t)(reg >> 8);
- break;
- default:
-
- if (rfaddr >= FHASH_ADDR &&
- rfaddr < FHASH_ADDR + FHASH_SIZE) {
-
- // Only word-aligned writes supported
- if (rfaddr % 2)
- panic("unaligned write to filter hash table!");
-
- rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
- rom.filterHash[rfaddr - FHASH_ADDR + 1]
- = (uint8_t)(reg >> 8);
- break;
- }
- panic("writing RFDR for something other than pattern matching "
- "or hashing! %#x\n", rfaddr);
- }
-
- case BRAR:
- regs.brar = reg;
- break;
-
- case BRDR:
- panic("the driver never uses BRDR, something is wrong!\n");
-
- case SRR:
- panic("SRR is read only register!\n");
-
- case MIBC:
- panic("the driver never uses MIBC, something is wrong!\n");
-
- case VRCR:
- regs.vrcr = reg;
- break;
-
- case VTCR:
- regs.vtcr = reg;
- break;
-
- case VDR:
- panic("the driver never uses VDR, something is wrong!\n");
-
- case CCSR:
- /* not going to implement clockrun stuff */
- regs.ccsr = reg;
- break;
-
- case TBICR:
- regs.tbicr = reg;
- if (reg & TBICR_MR_LOOPBACK)
- panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
-
- if (reg & TBICR_MR_AN_ENABLE) {
- regs.tanlpar = regs.tanar;
- regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
- }
-
-#if 0
- if (reg & TBICR_MR_RESTART_AN) ;
-#endif
-
- break;
-
- case TBISR:
- panic("TBISR is read only register!\n");
-
- case TANAR:
- // Only write the writable bits
- regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED;
- regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
-
- // Pause capability unimplemented
-#if 0
- if (reg & TANAR_PS2) ;
- if (reg & TANAR_PS1) ;
-#endif
-
- break;
-
- case TANLPAR:
- panic("this should only be written to by the fake phy!\n");
-
- case TANER:
- panic("TANER is read only register!\n");
-
- case TESR:
- regs.tesr = reg;
- break;
-
- default:
- panic("invalid register access daddr=%#x", daddr);
- }
- } else {
- panic("Invalid Request Size");
- }
- pkt->makeAtomicResponse();
- return pioDelay;
-}
-
-void
-NSGigE::devIntrPost(uint32_t interrupts)
-{
- if (interrupts & ISR_RESERVE)
- panic("Cannot set a reserved interrupt");
-
- if (interrupts & ISR_NOIMPL)
- warn("interrupt not implemented %#x\n", interrupts);
-
- interrupts &= ISR_IMPL;
- regs.isr |= interrupts;
-
- if (interrupts & regs.imr) {
- if (interrupts & ISR_SWI) {
- totalSwi++;
- }
- if (interrupts & ISR_RXIDLE) {
- totalRxIdle++;
- }
- if (interrupts & ISR_RXOK) {
- totalRxOk++;
- }
- if (interrupts & ISR_RXDESC) {
- totalRxDesc++;
- }
- if (interrupts & ISR_TXOK) {
- totalTxOk++;
- }
- if (interrupts & ISR_TXIDLE) {
- totalTxIdle++;
- }
- if (interrupts & ISR_TXDESC) {
- totalTxDesc++;
- }
- if (interrupts & ISR_RXORN) {
- totalRxOrn++;
- }
- }
-
- DPRINTF(EthernetIntr,
- "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
- interrupts, regs.isr, regs.imr);
-
- if ((regs.isr & regs.imr)) {
- Tick when = curTick();
- if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
- when += intrDelay;
- postedInterrupts++;
- cpuIntrPost(when);
- }
-}
-
-/* writing this interrupt counting stats inside this means that this function
- is now limited to being used to clear all interrupts upon the kernel
- reading isr and servicing. just telling you in case you were thinking
- of expanding use.
-*/
-void
-NSGigE::devIntrClear(uint32_t interrupts)
-{
- if (interrupts & ISR_RESERVE)
- panic("Cannot clear a reserved interrupt");
-
- if (regs.isr & regs.imr & ISR_SWI) {
- postedSwi++;
- }
- if (regs.isr & regs.imr & ISR_RXIDLE) {
- postedRxIdle++;
- }
- if (regs.isr & regs.imr & ISR_RXOK) {
- postedRxOk++;
- }
- if (regs.isr & regs.imr & ISR_RXDESC) {
- postedRxDesc++;
- }
- if (regs.isr & regs.imr & ISR_TXOK) {
- postedTxOk++;
- }
- if (regs.isr & regs.imr & ISR_TXIDLE) {
- postedTxIdle++;
- }
- if (regs.isr & regs.imr & ISR_TXDESC) {
- postedTxDesc++;
- }
- if (regs.isr & regs.imr & ISR_RXORN) {
- postedRxOrn++;
- }
-
- interrupts &= ~ISR_NOIMPL;
- regs.isr &= ~interrupts;
-
- DPRINTF(EthernetIntr,
- "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
- interrupts, regs.isr, regs.imr);
-
- if (!(regs.isr & regs.imr))
- cpuIntrClear();
-}
-
-void
-NSGigE::devIntrChangeMask()
-{
- DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
- regs.isr, regs.imr, regs.isr & regs.imr);
-
- if (regs.isr & regs.imr)
- cpuIntrPost(curTick());
- else
- cpuIntrClear();
-}
-
-void
-NSGigE::cpuIntrPost(Tick when)
-{
- // If the interrupt you want to post is later than an interrupt
- // already scheduled, just let it post in the coming one and don't
- // schedule another.
- // HOWEVER, must be sure that the scheduled intrTick is in the
- // future (this was formerly the source of a bug)
- /**
- * @todo this warning should be removed and the intrTick code should
- * be fixed.
- */
- assert(when >= curTick());
- assert(intrTick >= curTick() || intrTick == 0);
- if (when > intrTick && intrTick != 0) {
- DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
- intrTick);
- return;
- }
-
- intrTick = when;
- if (intrTick < curTick()) {
- Debug::breakpoint();
- intrTick = curTick();
- }
-
- DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
- intrTick);
-
- if (intrEvent)
- intrEvent->squash();
- intrEvent = new IntrEvent(this, true);
- schedule(intrEvent, intrTick);
-}
-
-void
-NSGigE::cpuInterrupt()
-{
- assert(intrTick == curTick());
-
- // Whether or not there's a pending interrupt, we don't care about
- // it anymore
- intrEvent = 0;
- intrTick = 0;
-
- // Don't send an interrupt if there's already one
- if (cpuPendingIntr) {
- DPRINTF(EthernetIntr,
- "would send an interrupt now, but there's already pending\n");
- } else {
- // Send interrupt
- cpuPendingIntr = true;
-
- DPRINTF(EthernetIntr, "posting interrupt\n");
- intrPost();
- }
-}
-
-void
-NSGigE::cpuIntrClear()
-{
- if (!cpuPendingIntr)
- return;
-
- if (intrEvent) {
- intrEvent->squash();
- intrEvent = 0;
- }
-
- intrTick = 0;
-
- cpuPendingIntr = false;
-
- DPRINTF(EthernetIntr, "clearing interrupt\n");
- intrClear();
-}
-
-bool
-NSGigE::cpuIntrPending() const
-{ return cpuPendingIntr; }
-
-void
-NSGigE::txReset()
-{
-
- DPRINTF(Ethernet, "transmit reset\n");
-
- CTDD = false;
- txEnable = false;;
- txFragPtr = 0;
- assert(txDescCnt == 0);
- txFifo.clear();
- txState = txIdle;
- assert(txDmaState == dmaIdle);
-}
-
-void
-NSGigE::rxReset()
-{
- DPRINTF(Ethernet, "receive reset\n");
-
- CRDD = false;
- assert(rxPktBytes == 0);
- rxEnable = false;
- rxFragPtr = 0;
- assert(rxDescCnt == 0);
- assert(rxDmaState == dmaIdle);
- rxFifo.clear();
- rxState = rxIdle;
-}
-
-void
-NSGigE::regsReset()
-{
- memset(&regs, 0, sizeof(regs));
- regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
- regs.mear = 0x12;
- regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
- // fill threshold to 32 bytes
- regs.rxcfg = 0x4; // set drain threshold to 16 bytes
- regs.srr = 0x0103; // set the silicon revision to rev B or 0x103
- regs.mibc = MIBC_FRZ;
- regs.vdr = 0x81; // set the vlan tag type to 802.1q
- regs.tesr = 0xc000; // TBI capable of both full and half duplex
- regs.brar = 0xffffffff;
-
- extstsEnable = false;
- acceptBroadcast = false;
- acceptMulticast = false;
- acceptUnicast = false;
- acceptPerfect = false;
- acceptArp = false;
-}
-
-bool
-NSGigE::doRxDmaRead()
-{
- assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
- rxDmaState = dmaReading;
-
- if (dmaPending() || drainState() != DrainState::Running)
- rxDmaState = dmaReadWaiting;
- else
- dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
-
- return true;
-}
-
-void
-NSGigE::rxDmaReadDone()
-{
- assert(rxDmaState == dmaReading);
- rxDmaState = dmaIdle;
-
- DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n",
- rxDmaAddr, rxDmaLen);
- DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
-
- // If the transmit state machine has a pending DMA, let it go first
- if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
- txKick();
-
- rxKick();
-}
-
-bool
-NSGigE::doRxDmaWrite()
-{
- assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
- rxDmaState = dmaWriting;
-
- if (dmaPending() || drainState() != DrainState::Running)
- rxDmaState = dmaWriteWaiting;
- else
- dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
- return true;
-}
-
-void
-NSGigE::rxDmaWriteDone()
-{
- assert(rxDmaState == dmaWriting);
- rxDmaState = dmaIdle;
-
- DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
- rxDmaAddr, rxDmaLen);
- DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
-
- // If the transmit state machine has a pending DMA, let it go first
- if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
- txKick();
-
- rxKick();
-}
-
-void
-NSGigE::rxKick()
-{
- bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
-
- DPRINTF(EthernetSM,
- "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
- NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
-
- Addr link, bufptr;
- uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
- uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
-
- next:
- if (rxKickTick > curTick()) {
- DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
- rxKickTick);
-
- goto exit;
- }
-
- // Go to the next state machine clock tick.
- rxKickTick = clockEdge(Cycles(1));
-
- switch(rxDmaState) {
- case dmaReadWaiting:
- if (doRxDmaRead())
- goto exit;
- break;
- case dmaWriteWaiting:
- if (doRxDmaWrite())
- goto exit;
- break;
- default:
- break;
- }
-
- link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
- bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
-
- // see state machine from spec for details
- // the way this works is, if you finish work on one state and can
- // go directly to another, you do that through jumping to the
- // label "next". however, if you have intermediate work, like DMA
- // so that you can't go to the next state yet, you go to exit and
- // exit the loop. however, when the DMA is done it will trigger
- // an event and come back to this loop.
- switch (rxState) {
- case rxIdle:
- if (!rxEnable) {
- DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
- goto exit;
- }
-
- if (CRDD) {
- rxState = rxDescRefr;
-
- rxDmaAddr = regs.rxdp & 0x3fffffff;
- rxDmaData =
- is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
- rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
- rxDmaFree = dmaDescFree;
-
- descDmaReads++;
- descDmaRdBytes += rxDmaLen;
-
- if (doRxDmaRead())
- goto exit;
- } else {
- rxState = rxDescRead;
-
- rxDmaAddr = regs.rxdp & 0x3fffffff;
- rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
- rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
- rxDmaFree = dmaDescFree;
-
- descDmaReads++;
- descDmaRdBytes += rxDmaLen;
-
- if (doRxDmaRead())
- goto exit;
- }
- break;
-
- case rxDescRefr:
- if (rxDmaState != dmaIdle)
- goto exit;
-
- rxState = rxAdvance;
- break;
-
- case rxDescRead:
- if (rxDmaState != dmaIdle)
- goto exit;
-
- DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
- regs.rxdp & 0x3fffffff);
- DPRINTF(EthernetDesc,
- "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
- link, bufptr, cmdsts, extsts);
-
- if (cmdsts & CMDSTS_OWN) {
- devIntrPost(ISR_RXIDLE);
- rxState = rxIdle;
- goto exit;
- } else {
- rxState = rxFifoBlock;
- rxFragPtr = bufptr;
- rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
- }
- break;
-
- case rxFifoBlock:
- if (!rxPacket) {
- /**
- * @todo in reality, we should be able to start processing
- * the packet as it arrives, and not have to wait for the
- * full packet ot be in the receive fifo.
- */
- if (rxFifo.empty())
- goto exit;
-
- DPRINTF(EthernetSM, "****processing receive of new packet****\n");
-
- // If we don't have a packet, grab a new one from the fifo.
- rxPacket = rxFifo.front();
- rxPktBytes = rxPacket->length;
- rxPacketBufPtr = rxPacket->data;
-
-#if TRACING_ON
- if (DTRACE(Ethernet)) {
- IpPtr ip(rxPacket);
- if (ip) {
- DPRINTF(Ethernet, "ID is %d\n", ip->id());
- TcpPtr tcp(ip);
- if (tcp) {
- DPRINTF(Ethernet,
- "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
- tcp->sport(), tcp->dport(), tcp->seq(),
- tcp->ack());
- }
- }
- }
-#endif
-
- // sanity check - i think the driver behaves like this
- assert(rxDescCnt >= rxPktBytes);
- rxFifo.pop();
- }
-
-
- // dont' need the && rxDescCnt > 0 if driver sanity check
- // above holds
- if (rxPktBytes > 0) {
- rxState = rxFragWrite;
- // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
- // check holds
- rxXferLen = rxPktBytes;
-
- rxDmaAddr = rxFragPtr & 0x3fffffff;
- rxDmaData = rxPacketBufPtr;
- rxDmaLen = rxXferLen;
- rxDmaFree = dmaDataFree;
-
- if (doRxDmaWrite())
- goto exit;
-
- } else {
- rxState = rxDescWrite;
-
- //if (rxPktBytes == 0) { /* packet is done */
- assert(rxPktBytes == 0);
- DPRINTF(EthernetSM, "done with receiving packet\n");
-
- cmdsts |= CMDSTS_OWN;
- cmdsts &= ~CMDSTS_MORE;
- cmdsts |= CMDSTS_OK;
- cmdsts &= 0xffff0000;
- cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE
-
-#if 0
- /*
- * all the driver uses these are for its own stats keeping
- * which we don't care about, aren't necessary for
- * functionality and doing this would just slow us down.
- * if they end up using this in a later version for
- * functional purposes, just undef
- */
- if (rxFilterEnable) {
- cmdsts &= ~CMDSTS_DEST_MASK;
- const EthAddr &dst = rxFifoFront()->dst();
- if (dst->unicast())
- cmdsts |= CMDSTS_DEST_SELF;
- if (dst->multicast())
- cmdsts |= CMDSTS_DEST_MULTI;
- if (dst->broadcast())
- cmdsts |= CMDSTS_DEST_MASK;
- }
-#endif
-
- IpPtr ip(rxPacket);
- if (extstsEnable && ip) {
- extsts |= EXTSTS_IPPKT;
- rxIpChecksums++;
- if (cksum(ip) != 0) {
- DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
- extsts |= EXTSTS_IPERR;
- }
- TcpPtr tcp(ip);
- UdpPtr udp(ip);
- if (tcp) {
- extsts |= EXTSTS_TCPPKT;
- rxTcpChecksums++;
- if (cksum(tcp) != 0) {
- DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
- extsts |= EXTSTS_TCPERR;
-
- }
- } else if (udp) {
- extsts |= EXTSTS_UDPPKT;
- rxUdpChecksums++;
- if (cksum(udp) != 0) {
- DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
- extsts |= EXTSTS_UDPERR;
- }
- }
- }
- rxPacket = 0;
-
- /*
- * the driver seems to always receive into desc buffers
- * of size 1514, so you never have a pkt that is split
- * into multiple descriptors on the receive side, so
- * i don't implement that case, hence the assert above.
- */
-
- DPRINTF(EthernetDesc,
- "rxDesc: addr=%08x writeback cmdsts extsts\n",
- regs.rxdp & 0x3fffffff);
- DPRINTF(EthernetDesc,
- "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
- link, bufptr, cmdsts, extsts);
-
- rxDmaAddr = regs.rxdp & 0x3fffffff;
- rxDmaData = &cmdsts;
- if (is64bit) {
- rxDmaAddr += offsetof(ns_desc64, cmdsts);
- rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
- } else {
- rxDmaAddr += offsetof(ns_desc32, cmdsts);
- rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
- }
- rxDmaFree = dmaDescFree;
-
- descDmaWrites++;
- descDmaWrBytes += rxDmaLen;
-
- if (doRxDmaWrite())
- goto exit;
- }
- break;
-
- case rxFragWrite:
- if (rxDmaState != dmaIdle)
- goto exit;
-
- rxPacketBufPtr += rxXferLen;
- rxFragPtr += rxXferLen;
- rxPktBytes -= rxXferLen;
-
- rxState = rxFifoBlock;
- break;
-
- case rxDescWrite:
- if (rxDmaState != dmaIdle)
- goto exit;
-
- assert(cmdsts & CMDSTS_OWN);
-
- assert(rxPacket == 0);
- devIntrPost(ISR_RXOK);
-
- if (cmdsts & CMDSTS_INTR)
- devIntrPost(ISR_RXDESC);
-
- if (!rxEnable) {
- DPRINTF(EthernetSM, "Halting the RX state machine\n");
- rxState = rxIdle;
- goto exit;
- } else
- rxState = rxAdvance;
- break;
-
- case rxAdvance:
- if (link == 0) {
- devIntrPost(ISR_RXIDLE);
- rxState = rxIdle;
- CRDD = true;
- goto exit;
- } else {
- if (rxDmaState != dmaIdle)
- goto exit;
- rxState = rxDescRead;
- regs.rxdp = link;
- CRDD = false;
-
- rxDmaAddr = regs.rxdp & 0x3fffffff;
- rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
- rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
- rxDmaFree = dmaDescFree;
-
- if (doRxDmaRead())
- goto exit;
- }
- break;
-
- default:
- panic("Invalid rxState!");
- }
-
- DPRINTF(EthernetSM, "entering next rxState=%s\n",
- NsRxStateStrings[rxState]);
- goto next;
-
- exit:
- /**
- * @todo do we want to schedule a future kick?
- */
- DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
- NsRxStateStrings[rxState]);
-
- if (!rxKickEvent.scheduled())
- schedule(rxKickEvent, rxKickTick);
-}
-
-void
-NSGigE::transmit()
-{
- if (txFifo.empty()) {
- DPRINTF(Ethernet, "nothing to transmit\n");
- return;
- }
-
- DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
- txFifo.size());
- if (interface->sendPacket(txFifo.front())) {
-#if TRACING_ON
- if (DTRACE(Ethernet)) {
- IpPtr ip(txFifo.front());
- if (ip) {
- DPRINTF(Ethernet, "ID is %d\n", ip->id());
- TcpPtr tcp(ip);
- if (tcp) {
- DPRINTF(Ethernet,
- "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
- tcp->sport(), tcp->dport(), tcp->seq(),
- tcp->ack());
- }
- }
- }
-#endif
-
- DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
- txBytes += txFifo.front()->length;
- txPackets++;
-
- DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
- txFifo.avail());
- txFifo.pop();
-
- /*
- * normally do a writeback of the descriptor here, and ONLY
- * after that is done, send this interrupt. but since our
- * stuff never actually fails, just do this interrupt here,
- * otherwise the code has to stray from this nice format.
- * besides, it's functionally the same.
- */
- devIntrPost(ISR_TXOK);
- }
-
- if (!txFifo.empty() && !txEvent.scheduled()) {
- DPRINTF(Ethernet, "reschedule transmit\n");
- schedule(txEvent, curTick() + retryTime);
- }
-}
-
-bool
-NSGigE::doTxDmaRead()
-{
- assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
- txDmaState = dmaReading;
-
- if (dmaPending() || drainState() != DrainState::Running)
- txDmaState = dmaReadWaiting;
- else
- dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
-
- return true;
-}
-
-void
-NSGigE::txDmaReadDone()
-{
- assert(txDmaState == dmaReading);
- txDmaState = dmaIdle;
-
- DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
- txDmaAddr, txDmaLen);
- DDUMP(EthernetDMA, txDmaData, txDmaLen);
-
- // If the receive state machine has a pending DMA, let it go first
- if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
- rxKick();
-
- txKick();
-}
-
-bool
-NSGigE::doTxDmaWrite()
-{
- assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
- txDmaState = dmaWriting;
-
- if (dmaPending() || drainState() != DrainState::Running)
- txDmaState = dmaWriteWaiting;
- else
- dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
- return true;
-}
-
-void
-NSGigE::txDmaWriteDone()
-{
- assert(txDmaState == dmaWriting);
- txDmaState = dmaIdle;
-
- DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
- txDmaAddr, txDmaLen);
- DDUMP(EthernetDMA, txDmaData, txDmaLen);
-
- // If the receive state machine has a pending DMA, let it go first
- if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
- rxKick();
-
- txKick();
-}
-
-void
-NSGigE::txKick()
-{
- bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
-
- DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
- NsTxStateStrings[txState], is64bit ? 64 : 32);
-
- Addr link, bufptr;
- uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
- uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
-
- next:
- if (txKickTick > curTick()) {
- DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
- txKickTick);
- goto exit;
- }
-
- // Go to the next state machine clock tick.
- txKickTick = clockEdge(Cycles(1));
-
- switch(txDmaState) {
- case dmaReadWaiting:
- if (doTxDmaRead())
- goto exit;
- break;
- case dmaWriteWaiting:
- if (doTxDmaWrite())
- goto exit;
- break;
- default:
- break;
- }
-
- link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
- bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
- switch (txState) {
- case txIdle:
- if (!txEnable) {
- DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n");
- goto exit;
- }
-
- if (CTDD) {
- txState = txDescRefr;
-
- txDmaAddr = regs.txdp & 0x3fffffff;
- txDmaData =
- is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
- txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
- txDmaFree = dmaDescFree;
-
- descDmaReads++;
- descDmaRdBytes += txDmaLen;
-
- if (doTxDmaRead())
- goto exit;
-
- } else {
- txState = txDescRead;
-
- txDmaAddr = regs.txdp & 0x3fffffff;
- txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
- txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
- txDmaFree = dmaDescFree;
-
- descDmaReads++;
- descDmaRdBytes += txDmaLen;
-
- if (doTxDmaRead())
- goto exit;
- }
- break;
-
- case txDescRefr:
- if (txDmaState != dmaIdle)
- goto exit;
-
- txState = txAdvance;
- break;
-
- case txDescRead:
- if (txDmaState != dmaIdle)
- goto exit;
-
- DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
- regs.txdp & 0x3fffffff);
- DPRINTF(EthernetDesc,
- "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
- link, bufptr, cmdsts, extsts);
-
- if (cmdsts & CMDSTS_OWN) {
- txState = txFifoBlock;
- txFragPtr = bufptr;
- txDescCnt = cmdsts & CMDSTS_LEN_MASK;
- } else {
- devIntrPost(ISR_TXIDLE);
- txState = txIdle;
- goto exit;
- }
- break;
-
- case txFifoBlock:
- if (!txPacket) {
- DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
- txPacket = make_shared<EthPacketData>(16384);
- txPacketBufPtr = txPacket->data;
- }
-
- if (txDescCnt == 0) {
- DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
- if (cmdsts & CMDSTS_MORE) {
- DPRINTF(EthernetSM, "there are more descriptors to come\n");
- txState = txDescWrite;
-
- cmdsts &= ~CMDSTS_OWN;
-
- txDmaAddr = regs.txdp & 0x3fffffff;
- txDmaData = &cmdsts;
- if (is64bit) {
- txDmaAddr += offsetof(ns_desc64, cmdsts);
- txDmaLen = sizeof(txDesc64.cmdsts);
- } else {
- txDmaAddr += offsetof(ns_desc32, cmdsts);
- txDmaLen = sizeof(txDesc32.cmdsts);
- }
- txDmaFree = dmaDescFree;
-
- if (doTxDmaWrite())
- goto exit;
-
- } else { /* this packet is totally done */
- DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
- /* deal with the the packet that just finished */
- if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
- IpPtr ip(txPacket);
- if (extsts & EXTSTS_UDPPKT) {
- UdpPtr udp(ip);
- if (udp) {
- udp->sum(0);
- udp->sum(cksum(udp));
- txUdpChecksums++;
- } else {
- Debug::breakpoint();
- warn_once("UDPPKT set, but not UDP!\n");
- }
- } else if (extsts & EXTSTS_TCPPKT) {
- TcpPtr tcp(ip);
- if (tcp) {
- tcp->sum(0);
- tcp->sum(cksum(tcp));
- txTcpChecksums++;
- } else {
- Debug::breakpoint();
- warn_once("TCPPKT set, but not UDP!\n");
- }
- }
- if (extsts & EXTSTS_IPPKT) {
- if (ip) {
- ip->sum(0);
- ip->sum(cksum(ip));
- txIpChecksums++;
- } else {
- Debug::breakpoint();
- warn_once("IPPKT set, but not UDP!\n");
- }
- }
- }
-
- txPacket->length = txPacketBufPtr - txPacket->data;
- // this is just because the receive can't handle a
- // packet bigger want to make sure
- if (txPacket->length > 1514)
- panic("transmit packet too large, %s > 1514\n",
- txPacket->length);
-
-#ifndef NDEBUG
- bool success =
-#endif
- txFifo.push(txPacket);
- assert(success);
-
- /*
- * this following section is not tqo spec, but
- * functionally shouldn't be any different. normally,
- * the chip will wait til the transmit has occurred
- * before writing back the descriptor because it has
- * to wait to see that it was successfully transmitted
- * to decide whether to set CMDSTS_OK or not.
- * however, in the simulator since it is always
- * successfully transmitted, and writing it exactly to
- * spec would complicate the code, we just do it here
- */
-
- cmdsts &= ~CMDSTS_OWN;
- cmdsts |= CMDSTS_OK;
-
- DPRINTF(EthernetDesc,
- "txDesc writeback: cmdsts=%08x extsts=%08x\n",
- cmdsts, extsts);
-
- txDmaFree = dmaDescFree;
- txDmaAddr = regs.txdp & 0x3fffffff;
- txDmaData = &cmdsts;
- if (is64bit) {
- txDmaAddr += offsetof(ns_desc64, cmdsts);
- txDmaLen =
- sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
- } else {
- txDmaAddr += offsetof(ns_desc32, cmdsts);
- txDmaLen =
- sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
- }
-
- descDmaWrites++;
- descDmaWrBytes += txDmaLen;
-
- transmit();
- txPacket = 0;
-
- if (!txEnable) {
- DPRINTF(EthernetSM, "halting TX state machine\n");
- txState = txIdle;
- goto exit;
- } else
- txState = txAdvance;
-
- if (doTxDmaWrite())
- goto exit;
- }
- } else {
- DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
- if (!txFifo.full()) {
- txState = txFragRead;
-
- /*
- * The number of bytes transferred is either whatever
- * is left in the descriptor (txDescCnt), or if there
- * is not enough room in the fifo, just whatever room
- * is left in the fifo
- */
- txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
-
- txDmaAddr = txFragPtr & 0x3fffffff;
- txDmaData = txPacketBufPtr;
- txDmaLen = txXferLen;
- txDmaFree = dmaDataFree;
-
- if (doTxDmaRead())
- goto exit;
- } else {
- txState = txFifoBlock;
- transmit();
-
- goto exit;
- }
-
- }
- break;
-
- case txFragRead:
- if (txDmaState != dmaIdle)
- goto exit;
-
- txPacketBufPtr += txXferLen;
- txFragPtr += txXferLen;
- txDescCnt -= txXferLen;
- txFifo.reserve(txXferLen);
-
- txState = txFifoBlock;
- break;
-
- case txDescWrite:
- if (txDmaState != dmaIdle)
- goto exit;
-
- if (cmdsts & CMDSTS_INTR)
- devIntrPost(ISR_TXDESC);
-
- if (!txEnable) {
- DPRINTF(EthernetSM, "halting TX state machine\n");
- txState = txIdle;
- goto exit;
- } else
- txState = txAdvance;
- break;
-
- case txAdvance:
- if (link == 0) {
- devIntrPost(ISR_TXIDLE);
- txState = txIdle;
- goto exit;
- } else {
- if (txDmaState != dmaIdle)
- goto exit;
- txState = txDescRead;
- regs.txdp = link;
- CTDD = false;
-
- txDmaAddr = link & 0x3fffffff;
- txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
- txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
- txDmaFree = dmaDescFree;
-
- if (doTxDmaRead())
- goto exit;
- }
- break;
-
- default:
- panic("invalid state");
- }
-
- DPRINTF(EthernetSM, "entering next txState=%s\n",
- NsTxStateStrings[txState]);
- goto next;
-
- exit:
- /**
- * @todo do we want to schedule a future kick?
- */
- DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
- NsTxStateStrings[txState]);
-
- if (!txKickEvent.scheduled())
- schedule(txKickEvent, txKickTick);
-}
-
-/**
- * Advance the EEPROM state machine
- * Called on rising edge of EEPROM clock bit in MEAR
- */
-void
-NSGigE::eepromKick()
-{
- switch (eepromState) {
-
- case eepromStart:
-
- // Wait for start bit
- if (regs.mear & MEAR_EEDI) {
- // Set up to get 2 opcode bits
- eepromState = eepromGetOpcode;
- eepromBitsToRx = 2;
- eepromOpcode = 0;
- }
- break;
-
- case eepromGetOpcode:
- eepromOpcode <<= 1;
- eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
- --eepromBitsToRx;
-
- // Done getting opcode
- if (eepromBitsToRx == 0) {
- if (eepromOpcode != EEPROM_READ)
- panic("only EEPROM reads are implemented!");
-
- // Set up to get address
- eepromState = eepromGetAddress;
- eepromBitsToRx = 6;
- eepromAddress = 0;
- }
- break;
-
- case eepromGetAddress:
- eepromAddress <<= 1;
- eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
- --eepromBitsToRx;
-
- // Done getting address
- if (eepromBitsToRx == 0) {
-
- if (eepromAddress >= EEPROM_SIZE)
- panic("EEPROM read access out of range!");
-
- switch (eepromAddress) {
-
- case EEPROM_PMATCH2_ADDR:
- eepromData = rom.perfectMatch[5];
- eepromData <<= 8;
- eepromData += rom.perfectMatch[4];
- break;
-
- case EEPROM_PMATCH1_ADDR:
- eepromData = rom.perfectMatch[3];
- eepromData <<= 8;
- eepromData += rom.perfectMatch[2];
- break;
-
- case EEPROM_PMATCH0_ADDR:
- eepromData = rom.perfectMatch[1];
- eepromData <<= 8;
- eepromData += rom.perfectMatch[0];
- break;
-
- default:
- panic("FreeBSD driver only uses EEPROM to read PMATCH!");
- }
- // Set up to read data
- eepromState = eepromRead;
- eepromBitsToRx = 16;
-
- // Clear data in bit
- regs.mear &= ~MEAR_EEDI;
- }
- break;
-
- case eepromRead:
- // Clear Data Out bit
- regs.mear &= ~MEAR_EEDO;
- // Set bit to value of current EEPROM bit
- regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
-
- eepromData <<= 1;
- --eepromBitsToRx;
-
- // All done
- if (eepromBitsToRx == 0) {
- eepromState = eepromStart;
- }
- break;
-
- default:
- panic("invalid EEPROM state");
- }
-
-}
-
-void
-NSGigE::transferDone()
-{
- if (txFifo.empty()) {
- DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
- return;
- }
-
- DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
-
- reschedule(txEvent, clockEdge(Cycles(1)), true);
-}
-
-bool
-NSGigE::rxFilter(const EthPacketPtr &packet)
-{
- EthPtr eth = packet;
- bool drop = true;
- string type;
-
- const EthAddr &dst = eth->dst();
- if (dst.unicast()) {
- // If we're accepting all unicast addresses
- if (acceptUnicast)
- drop = false;
-
- // If we make a perfect match
- if (acceptPerfect && dst == rom.perfectMatch)
- drop = false;
-
- if (acceptArp && eth->type() == ETH_TYPE_ARP)
- drop = false;
-
- } else if (dst.broadcast()) {
- // if we're accepting broadcasts
- if (acceptBroadcast)
- drop = false;
-
- } else if (dst.multicast()) {
- // if we're accepting all multicasts
- if (acceptMulticast)
- drop = false;
-
- // Multicast hashing faked - all packets accepted
- if (multicastHashEnable)
- drop = false;
- }
-
- if (drop) {
- DPRINTF(Ethernet, "rxFilter drop\n");
- DDUMP(EthernetData, packet->data, packet->length);
- }
-
- return drop;
-}
-
-bool
-NSGigE::recvPacket(EthPacketPtr packet)
-{
- rxBytes += packet->length;
- rxPackets++;
-
- DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
- rxFifo.avail());
-
- if (!rxEnable) {
- DPRINTF(Ethernet, "receive disabled...packet dropped\n");
- return true;
- }
-
- if (!rxFilterEnable) {
- DPRINTF(Ethernet,
- "receive packet filtering disabled . . . packet dropped\n");
- return true;
- }
-
- if (rxFilter(packet)) {
- DPRINTF(Ethernet, "packet filtered...dropped\n");
- return true;
- }
-
- if (rxFifo.avail() < packet->length) {
-#if TRACING_ON
- IpPtr ip(packet);
- TcpPtr tcp(ip);
- if (ip) {
- DPRINTF(Ethernet,
- "packet won't fit in receive buffer...pkt ID %d dropped\n",
- ip->id());
- if (tcp) {
- DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
- }
- }
-#endif
- droppedPackets++;
- devIntrPost(ISR_RXORN);
- return false;
- }
-
- rxFifo.push(packet);
-
- rxKick();
- return true;
-}
-
-
-void
-NSGigE::drainResume()
-{
- Drainable::drainResume();
-
- // During drain we could have left the state machines in a waiting state and
- // they wouldn't get out until some other event occured to kick them.
- // This way they'll get out immediately
- txKick();
- rxKick();
-}
-
-
-//=====================================================================
-//
-//
-void
-NSGigE::serialize(CheckpointOut &cp) const
-{
- // Serialize the PciDevice base class
- PciDevice::serialize(cp);
-
- /*
- * Finalize any DMA events now.
- */
- // @todo will mem system save pending dma?
-
- /*
- * Serialize the device registers
- */
- SERIALIZE_SCALAR(regs.command);
- SERIALIZE_SCALAR(regs.config);
- SERIALIZE_SCALAR(regs.mear);
- SERIALIZE_SCALAR(regs.ptscr);
- SERIALIZE_SCALAR(regs.isr);
- SERIALIZE_SCALAR(regs.imr);
- SERIALIZE_SCALAR(regs.ier);
- SERIALIZE_SCALAR(regs.ihr);
- SERIALIZE_SCALAR(regs.txdp);
- SERIALIZE_SCALAR(regs.txdp_hi);
- SERIALIZE_SCALAR(regs.txcfg);
- SERIALIZE_SCALAR(regs.gpior);
- SERIALIZE_SCALAR(regs.rxdp);
- SERIALIZE_SCALAR(regs.rxdp_hi);
- SERIALIZE_SCALAR(regs.rxcfg);
- SERIALIZE_SCALAR(regs.pqcr);
- SERIALIZE_SCALAR(regs.wcsr);
- SERIALIZE_SCALAR(regs.pcr);
- SERIALIZE_SCALAR(regs.rfcr);
- SERIALIZE_SCALAR(regs.rfdr);
- SERIALIZE_SCALAR(regs.brar);
- SERIALIZE_SCALAR(regs.brdr);
- SERIALIZE_SCALAR(regs.srr);
- SERIALIZE_SCALAR(regs.mibc);
- SERIALIZE_SCALAR(regs.vrcr);
- SERIALIZE_SCALAR(regs.vtcr);
- SERIALIZE_SCALAR(regs.vdr);
- SERIALIZE_SCALAR(regs.ccsr);
- SERIALIZE_SCALAR(regs.tbicr);
- SERIALIZE_SCALAR(regs.tbisr);
- SERIALIZE_SCALAR(regs.tanar);
- SERIALIZE_SCALAR(regs.tanlpar);
- SERIALIZE_SCALAR(regs.taner);
- SERIALIZE_SCALAR(regs.tesr);
-
- SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
- SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
-
- SERIALIZE_SCALAR(ioEnable);
-
- /*
- * Serialize the data Fifos
- */
- rxFifo.serialize("rxFifo", cp);
- txFifo.serialize("txFifo", cp);
-
- /*
- * Serialize the various helper variables
- */
- bool txPacketExists = txPacket != nullptr;
- SERIALIZE_SCALAR(txPacketExists);
- if (txPacketExists) {
- txPacket->length = txPacketBufPtr - txPacket->data;
- txPacket->serialize("txPacket", cp);
- uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
- SERIALIZE_SCALAR(txPktBufPtr);
- }
-
- bool rxPacketExists = rxPacket != nullptr;
- SERIALIZE_SCALAR(rxPacketExists);
- if (rxPacketExists) {
- rxPacket->serialize("rxPacket", cp);
- uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
- SERIALIZE_SCALAR(rxPktBufPtr);
- }
-
- SERIALIZE_SCALAR(txXferLen);
- SERIALIZE_SCALAR(rxXferLen);
-
- /*
- * Serialize Cached Descriptors
- */
- SERIALIZE_SCALAR(rxDesc64.link);
- SERIALIZE_SCALAR(rxDesc64.bufptr);
- SERIALIZE_SCALAR(rxDesc64.cmdsts);
- SERIALIZE_SCALAR(rxDesc64.extsts);
- SERIALIZE_SCALAR(txDesc64.link);
- SERIALIZE_SCALAR(txDesc64.bufptr);
- SERIALIZE_SCALAR(txDesc64.cmdsts);
- SERIALIZE_SCALAR(txDesc64.extsts);
- SERIALIZE_SCALAR(rxDesc32.link);
- SERIALIZE_SCALAR(rxDesc32.bufptr);
- SERIALIZE_SCALAR(rxDesc32.cmdsts);
- SERIALIZE_SCALAR(rxDesc32.extsts);
- SERIALIZE_SCALAR(txDesc32.link);
- SERIALIZE_SCALAR(txDesc32.bufptr);
- SERIALIZE_SCALAR(txDesc32.cmdsts);
- SERIALIZE_SCALAR(txDesc32.extsts);
- SERIALIZE_SCALAR(extstsEnable);
-
- /*
- * Serialize tx state machine
- */
- int txState = this->txState;
- SERIALIZE_SCALAR(txState);
- SERIALIZE_SCALAR(txEnable);
- SERIALIZE_SCALAR(CTDD);
- SERIALIZE_SCALAR(txFragPtr);
- SERIALIZE_SCALAR(txDescCnt);
- int txDmaState = this->txDmaState;
- SERIALIZE_SCALAR(txDmaState);
- SERIALIZE_SCALAR(txKickTick);
-
- /*
- * Serialize rx state machine
- */
- int rxState = this->rxState;
- SERIALIZE_SCALAR(rxState);
- SERIALIZE_SCALAR(rxEnable);
- SERIALIZE_SCALAR(CRDD);
- SERIALIZE_SCALAR(rxPktBytes);
- SERIALIZE_SCALAR(rxFragPtr);
- SERIALIZE_SCALAR(rxDescCnt);
- int rxDmaState = this->rxDmaState;
- SERIALIZE_SCALAR(rxDmaState);
- SERIALIZE_SCALAR(rxKickTick);
-
- /*
- * Serialize EEPROM state machine
- */
- int eepromState = this->eepromState;
- SERIALIZE_SCALAR(eepromState);
- SERIALIZE_SCALAR(eepromClk);
- SERIALIZE_SCALAR(eepromBitsToRx);
- SERIALIZE_SCALAR(eepromOpcode);
- SERIALIZE_SCALAR(eepromAddress);
- SERIALIZE_SCALAR(eepromData);
-
- /*
- * If there's a pending transmit, store the time so we can
- * reschedule it later
- */
- Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick() : 0;
- SERIALIZE_SCALAR(transmitTick);
-
- /*
- * receive address filter settings
- */
- SERIALIZE_SCALAR(rxFilterEnable);
- SERIALIZE_SCALAR(acceptBroadcast);
- SERIALIZE_SCALAR(acceptMulticast);
- SERIALIZE_SCALAR(acceptUnicast);
- SERIALIZE_SCALAR(acceptPerfect);
- SERIALIZE_SCALAR(acceptArp);
- SERIALIZE_SCALAR(multicastHashEnable);
-
- /*
- * Keep track of pending interrupt status.
- */
- SERIALIZE_SCALAR(intrTick);
- SERIALIZE_SCALAR(cpuPendingIntr);
- Tick intrEventTick = 0;
- if (intrEvent)
- intrEventTick = intrEvent->when();
- SERIALIZE_SCALAR(intrEventTick);
-
-}
-
-void
-NSGigE::unserialize(CheckpointIn &cp)
-{
- // Unserialize the PciDevice base class
- PciDevice::unserialize(cp);
-
- UNSERIALIZE_SCALAR(regs.command);
- UNSERIALIZE_SCALAR(regs.config);
- UNSERIALIZE_SCALAR(regs.mear);
- UNSERIALIZE_SCALAR(regs.ptscr);
- UNSERIALIZE_SCALAR(regs.isr);
- UNSERIALIZE_SCALAR(regs.imr);
- UNSERIALIZE_SCALAR(regs.ier);
- UNSERIALIZE_SCALAR(regs.ihr);
- UNSERIALIZE_SCALAR(regs.txdp);
- UNSERIALIZE_SCALAR(regs.txdp_hi);
- UNSERIALIZE_SCALAR(regs.txcfg);
- UNSERIALIZE_SCALAR(regs.gpior);
- UNSERIALIZE_SCALAR(regs.rxdp);
- UNSERIALIZE_SCALAR(regs.rxdp_hi);
- UNSERIALIZE_SCALAR(regs.rxcfg);
- UNSERIALIZE_SCALAR(regs.pqcr);
- UNSERIALIZE_SCALAR(regs.wcsr);
- UNSERIALIZE_SCALAR(regs.pcr);
- UNSERIALIZE_SCALAR(regs.rfcr);
- UNSERIALIZE_SCALAR(regs.rfdr);
- UNSERIALIZE_SCALAR(regs.brar);
- UNSERIALIZE_SCALAR(regs.brdr);
- UNSERIALIZE_SCALAR(regs.srr);
- UNSERIALIZE_SCALAR(regs.mibc);
- UNSERIALIZE_SCALAR(regs.vrcr);
- UNSERIALIZE_SCALAR(regs.vtcr);
- UNSERIALIZE_SCALAR(regs.vdr);
- UNSERIALIZE_SCALAR(regs.ccsr);
- UNSERIALIZE_SCALAR(regs.tbicr);
- UNSERIALIZE_SCALAR(regs.tbisr);
- UNSERIALIZE_SCALAR(regs.tanar);
- UNSERIALIZE_SCALAR(regs.tanlpar);
- UNSERIALIZE_SCALAR(regs.taner);
- UNSERIALIZE_SCALAR(regs.tesr);
-
- UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
- UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
-
- UNSERIALIZE_SCALAR(ioEnable);
-
- /*
- * unserialize the data fifos
- */
- rxFifo.unserialize("rxFifo", cp);
- txFifo.unserialize("txFifo", cp);
-
- /*
- * unserialize the various helper variables
- */
- bool txPacketExists;
- UNSERIALIZE_SCALAR(txPacketExists);
- if (txPacketExists) {
- txPacket = make_shared<EthPacketData>(16384);
- txPacket->unserialize("txPacket", cp);
- uint32_t txPktBufPtr;
- UNSERIALIZE_SCALAR(txPktBufPtr);
- txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
- } else
- txPacket = 0;
-
- bool rxPacketExists;
- UNSERIALIZE_SCALAR(rxPacketExists);
- rxPacket = 0;
- if (rxPacketExists) {
- rxPacket = make_shared<EthPacketData>(16384);
- rxPacket->unserialize("rxPacket", cp);
- uint32_t rxPktBufPtr;
- UNSERIALIZE_SCALAR(rxPktBufPtr);
- rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
- } else
- rxPacket = 0;
-
- UNSERIALIZE_SCALAR(txXferLen);
- UNSERIALIZE_SCALAR(rxXferLen);
-
- /*
- * Unserialize Cached Descriptors
- */
- UNSERIALIZE_SCALAR(rxDesc64.link);
- UNSERIALIZE_SCALAR(rxDesc64.bufptr);
- UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
- UNSERIALIZE_SCALAR(rxDesc64.extsts);
- UNSERIALIZE_SCALAR(txDesc64.link);
- UNSERIALIZE_SCALAR(txDesc64.bufptr);
- UNSERIALIZE_SCALAR(txDesc64.cmdsts);
- UNSERIALIZE_SCALAR(txDesc64.extsts);
- UNSERIALIZE_SCALAR(rxDesc32.link);
- UNSERIALIZE_SCALAR(rxDesc32.bufptr);
- UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
- UNSERIALIZE_SCALAR(rxDesc32.extsts);
- UNSERIALIZE_SCALAR(txDesc32.link);
- UNSERIALIZE_SCALAR(txDesc32.bufptr);
- UNSERIALIZE_SCALAR(txDesc32.cmdsts);
- UNSERIALIZE_SCALAR(txDesc32.extsts);
- UNSERIALIZE_SCALAR(extstsEnable);
-
- /*
- * unserialize tx state machine
- */
- int txState;
- UNSERIALIZE_SCALAR(txState);
- this->txState = (TxState) txState;
- UNSERIALIZE_SCALAR(txEnable);
- UNSERIALIZE_SCALAR(CTDD);
- UNSERIALIZE_SCALAR(txFragPtr);
- UNSERIALIZE_SCALAR(txDescCnt);
- int txDmaState;
- UNSERIALIZE_SCALAR(txDmaState);
- this->txDmaState = (DmaState) txDmaState;
- UNSERIALIZE_SCALAR(txKickTick);
- if (txKickTick)
- schedule(txKickEvent, txKickTick);
-
- /*
- * unserialize rx state machine
- */
- int rxState;
- UNSERIALIZE_SCALAR(rxState);
- this->rxState = (RxState) rxState;
- UNSERIALIZE_SCALAR(rxEnable);
- UNSERIALIZE_SCALAR(CRDD);
- UNSERIALIZE_SCALAR(rxPktBytes);
- UNSERIALIZE_SCALAR(rxFragPtr);
- UNSERIALIZE_SCALAR(rxDescCnt);
- int rxDmaState;
- UNSERIALIZE_SCALAR(rxDmaState);
- this->rxDmaState = (DmaState) rxDmaState;
- UNSERIALIZE_SCALAR(rxKickTick);
- if (rxKickTick)
- schedule(rxKickEvent, rxKickTick);
-
- /*
- * Unserialize EEPROM state machine
- */
- int eepromState;
- UNSERIALIZE_SCALAR(eepromState);
- this->eepromState = (EEPROMState) eepromState;
- UNSERIALIZE_SCALAR(eepromClk);
- UNSERIALIZE_SCALAR(eepromBitsToRx);
- UNSERIALIZE_SCALAR(eepromOpcode);
- UNSERIALIZE_SCALAR(eepromAddress);
- UNSERIALIZE_SCALAR(eepromData);
-
- /*
- * If there's a pending transmit, reschedule it now
- */
- Tick transmitTick;
- UNSERIALIZE_SCALAR(transmitTick);
- if (transmitTick)
- schedule(txEvent, curTick() + transmitTick);
-
- /*
- * unserialize receive address filter settings
- */
- UNSERIALIZE_SCALAR(rxFilterEnable);
- UNSERIALIZE_SCALAR(acceptBroadcast);
- UNSERIALIZE_SCALAR(acceptMulticast);
- UNSERIALIZE_SCALAR(acceptUnicast);
- UNSERIALIZE_SCALAR(acceptPerfect);
- UNSERIALIZE_SCALAR(acceptArp);
- UNSERIALIZE_SCALAR(multicastHashEnable);
-
- /*
- * Keep track of pending interrupt status.
- */
- UNSERIALIZE_SCALAR(intrTick);
- UNSERIALIZE_SCALAR(cpuPendingIntr);
- Tick intrEventTick;
- UNSERIALIZE_SCALAR(intrEventTick);
- if (intrEventTick) {
- intrEvent = new IntrEvent(this, true);
- schedule(intrEvent, intrEventTick);
- }
-}
-
-NSGigE *
-NSGigEParams::create()
-{
- return new NSGigE(this);
-}