/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * 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
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/* @file
+/** @file
* Device module for modelling the National Semiconductor
* DP83820 ethernet controller
*/
-#ifndef __NS_GIGE_HH__
-#define __NS_GIGE_HH__
+#ifndef __DEV_NS_GIGE_HH__
+#define __DEV_NS_GIGE_HH__
-#include "dev/dma.hh"
+#include "base/inet.hh"
+#include "base/statistics.hh"
#include "dev/etherint.hh"
#include "dev/etherpkt.hh"
-#include "sim/eventq.hh"
+#include "dev/io_device.hh"
#include "dev/ns_gige_reg.h"
-#include "base/statistics.hh"
#include "dev/pcidev.hh"
-#include "dev/tsunami.hh"
-#include "dev/pciconfigall.hh"
-
-/** defined by the NS83820 data sheet */
-#define MAX_TX_FIFO_SIZE 8192
-#define MAX_RX_FIFO_SIZE 32768
-
-/** length of ethernet address in bytes */
-#define EADDR_LEN 6
+#include "dev/pktfifo.hh"
+#include "mem/bus/bus.hh"
+#include "sim/eventq.hh"
-/** Transmit State Machine states */
-enum tx_state { txIdle, txDescRefr, txDescRead, txFifoBlock, txFragRead,
- txDescWrite };
+// Hash filtering constants
+const uint16_t FHASH_ADDR = 0x100;
+const uint16_t FHASH_SIZE = 0x100;
-/** Receive State Machine States */
-enum rx_state { rxIdle, rxDescRefr, rxDescRead, rxFifoBlock, rxFragWrite,
- rxDescWrite, rxAdvance };
+// EEPROM constants
+const uint8_t EEPROM_READ = 0x2;
+const uint8_t EEPROM_SIZE = 64; // Size in words of NSC93C46 EEPROM
+const uint8_t EEPROM_PMATCH2_ADDR = 0xA; // EEPROM Address of PMATCH word 2
+const uint8_t EEPROM_PMATCH1_ADDR = 0xB; // EEPROM Address of PMATCH word 1
+const uint8_t EEPROM_PMATCH0_ADDR = 0xC; // EEPROM Address of PMATCH word 0
/**
* Ethernet device registers
uint32_t pcr;
uint32_t rfcr;
uint32_t rfdr;
+ uint32_t brar;
+ uint32_t brdr;
uint32_t srr;
uint32_t mibc;
uint32_t vrcr;
uint32_t tanlpar;
uint32_t taner;
uint32_t tesr;
+};
- /** for perfect match memory. the linux driver doesn't use any other ROM */
- uint8_t perfectMatch[EADDR_LEN];
+struct dp_rom {
+ /**
+ * for perfect match memory.
+ * the linux driver doesn't use any other ROM
+ */
+ uint8_t perfectMatch[ETH_ADDR_LEN];
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string §ion);
+ /**
+ * for hash table memory.
+ * used by the freebsd driver
+ */
+ uint8_t filterHash[FHASH_SIZE];
};
-/** an enum indicating direction, transmit or receive, used as a param for
- some fns */
-enum dir_t { tx, rx };
-
-class DmaEngine;
-class IntrControl;
-class EtherDevInt;
+class NSGigEInt;
class PhysicalMemory;
+class BaseInterface;
+class HierParams;
+class Bus;
+class PciConfigAll;
/**
- * NS DP82830 Ethernet device model
+ * NS DP83820 Ethernet device model
*/
-class EtherDev : public PciDev, public DmaHolder
+class NSGigE : public PciDev
{
+ public:
+ /** Transmit State Machine states */
+ enum TxState
+ {
+ txIdle,
+ txDescRefr,
+ txDescRead,
+ txFifoBlock,
+ txFragRead,
+ txDescWrite,
+ txAdvance
+ };
+
+ /** Receive State Machine States */
+ enum RxState
+ {
+ rxIdle,
+ rxDescRefr,
+ rxDescRead,
+ rxFifoBlock,
+ rxFragWrite,
+ rxDescWrite,
+ rxAdvance
+ };
+
+ enum DmaState
+ {
+ dmaIdle,
+ dmaReading,
+ dmaWriting,
+ dmaReadWaiting,
+ dmaWriteWaiting
+ };
+
+ /** EEPROM State Machine States */
+ enum EEPROMState
+ {
+ eepromStart,
+ eepromGetOpcode,
+ eepromGetAddress,
+ eepromRead
+ };
+
private:
- /** pointer to the chipset */
- Tsunami *tsunami;
+ Addr addr;
+ static const Addr size = sizeof(dp_regs);
protected:
- Addr addr;
- Addr mask;
+ typedef std::deque<PacketPtr> pktbuf_t;
+ typedef pktbuf_t::iterator pktiter_t;
/** device register file */
dp_regs regs;
+ dp_rom rom;
- /*** BASIC STRUCTURES FOR TX/RX ***/
- /* Data FIFOs */
- typedef std::deque<PacketPtr> pktbuf_t;
- typedef pktbuf_t::iterator pktiter_t;
- pktbuf_t txFifo;
- pktbuf_t rxFifo;
+ /** pci settings */
+ bool ioEnable;
+#if 0
+ bool memEnable;
+ bool bmEnable;
+#endif
- /** for the tx side, to track addrs to write updated cmdsts to */
- typedef std::deque<uint32_t> txdpbuf_t; /* ASSUME32 */
- txdpbuf_t descAddrFifo;
+ /*** BASIC STRUCTURES FOR TX/RX ***/
+ /* Data FIFOs */
+ PacketFifo txFifo;
+ PacketFifo rxFifo;
/** various helper vars */
- uint32_t txPacketLen;
+ PacketPtr txPacket;
+ PacketPtr rxPacket;
uint8_t *txPacketBufPtr;
uint8_t *rxPacketBufPtr;
- uint8_t *rxDescBufPtr;
- uint32_t fragLen;
- uint32_t rxCopied;
+ uint32_t txXferLen;
+ uint32_t rxXferLen;
+ bool rxDmaFree;
+ bool txDmaFree;
/** DescCaches */
ns_desc txDescCache;
ns_desc rxDescCache;
+ /* state machine cycle time */
+ Tick clock;
+ inline Tick cycles(int numCycles) const { return numCycles * clock; }
+
/* tx State Machine */
- tx_state txState;
+ TxState txState;
+ bool txEnable;
+
/** Current Transmit Descriptor Done */
bool CTDD;
- uint32_t txFifoCnt; /* amt of data in the txDataFifo in bytes (logical) */
- uint32_t txFifoAvail; /* current amt of free space in txDataFifo in byes */
+ /** halt the tx state machine after next packet */
bool txHalt;
- bool txPacketFlag; /* when set, indicates not working on a new packet */
- Addr txFragPtr; /* ptr to the next byte in the current fragment */
- uint32_t txDescCnt; /* count of bytes remaining in the current descriptor */
+ /** ptr to the next byte in the current fragment */
+ Addr txFragPtr;
+ /** count of bytes remaining in the current descriptor */
+ uint32_t txDescCnt;
+ DmaState txDmaState;
/** rx State Machine */
- rx_state rxState;
- bool CRDD; /* Current Receive Descriptor Done */
- uint32_t rxPktBytes; /* num of bytes in the current packet being drained
- from rxDataFifo */
- uint32_t rxFifoCnt; /* number of bytes in the rxFifo */
+ RxState rxState;
+ bool rxEnable;
+
+ /** Current Receive Descriptor Done */
+ bool CRDD;
+ /** num of bytes in the current packet being drained from rxDataFifo */
+ uint32_t rxPktBytes;
+ /** halt the rx state machine after current packet */
bool rxHalt;
- bool rxPacketFlag; /* when set, indicates not working on a new packet */
- Addr rxFragPtr; /* ptr to the next byte in current fragment */
- uint32_t rxDescCnt; /* count of bytes remaining in the current descriptor */
+ /** ptr to the next byte in current fragment */
+ Addr rxFragPtr;
+ /** count of bytes remaining in the current descriptor */
+ uint32_t rxDescCnt;
+ DmaState rxDmaState;
bool extstsEnable;
- uint32_t maxTxBurst;
- uint32_t maxRxBurst;
- PhysicalMemory *physmem;
+ /** EEPROM State Machine */
+ EEPROMState eepromState;
+ bool eepromClk;
+ uint8_t eepromBitsToRx;
+ uint8_t eepromOpcode;
+ uint8_t eepromAddress;
+ uint16_t eepromData;
protected:
- /**
- * Receive dma for descriptors done callback
- */
- class RxDescDone : public DmaCallback
- {
- public:
- EtherDev *ethernet;
+ Tick dmaReadDelay;
+ Tick dmaWriteDelay;
- public:
- RxDescDone(EtherDev *e);
- std::string name() const;
- virtual void process();
- };
+ Tick dmaReadFactor;
+ Tick dmaWriteFactor;
- /**
- * Receive dma done callback
- */
- class RxDone : public DmaCallback
- {
- public:
- EtherDev *ethernet;
+ void *rxDmaData;
+ Addr rxDmaAddr;
+ int rxDmaLen;
+ bool doRxDmaRead();
+ bool doRxDmaWrite();
+ void rxDmaReadCopy();
+ void rxDmaWriteCopy();
- public:
- RxDone(EtherDev *e);
- std::string name() const;
- virtual void process();
- };
+ void *txDmaData;
+ Addr txDmaAddr;
+ int txDmaLen;
+ bool doTxDmaRead();
+ bool doTxDmaWrite();
+ void txDmaReadCopy();
+ void txDmaWriteCopy();
- /**
- * Transmit dma for descriptors done callback
- */
- class TxDescDone : public DmaCallback
- {
- public:
- EtherDev *ethernet;
+ void rxDmaReadDone();
+ friend class EventWrapper<NSGigE, &NSGigE::rxDmaReadDone>;
+ EventWrapper<NSGigE, &NSGigE::rxDmaReadDone> rxDmaReadEvent;
- public:
- TxDescDone(EtherDev *e);
- std::string name() const;
- virtual void process();
- };
+ void rxDmaWriteDone();
+ friend class EventWrapper<NSGigE, &NSGigE::rxDmaWriteDone>;
+ EventWrapper<NSGigE, &NSGigE::rxDmaWriteDone> rxDmaWriteEvent;
- /*
- * Transmit dma done callback
- */
- class TxDone : public DmaCallback
- {
- public:
- EtherDev *ethernet;
- PacketPtr packet;
-
- public:
- TxDone(EtherDev *e);
- std::string name() const;
- virtual void process();
- };
+ void txDmaReadDone();
+ friend class EventWrapper<NSGigE, &NSGigE::txDmaReadDone>;
+ EventWrapper<NSGigE, &NSGigE::txDmaReadDone> txDmaReadEvent;
- friend class TxDescDone;
- friend class TxDone;
- friend class RxDescDone;
- friend class RxDone;
-
- RxDescDone rxDescDoneCB;
- RxDone rxDoneCB;
- TxDescDone txDescDoneCB;
- TxDone txDoneCB;
-
- DmaEngine *dma;
- DmaRequest readRequest;
- DmaRequest writeRequest;
- DmaRequest readDescRequest;
- DmaRequest writeDescRequest;
- PacketPtr rxPacket;
- DmaPhys readPhys;
- DmaPhys writePhys;
- DmaPhys readDescPhys;
- DmaPhys writeDescPhys;
+ void txDmaWriteDone();
+ friend class EventWrapper<NSGigE, &NSGigE::txDmaWriteDone>;
+ EventWrapper<NSGigE, &NSGigE::txDmaWriteDone> txDmaWriteEvent;
+
+ bool dmaDescFree;
+ bool dmaDataFree;
- EtherDevInt *interface;
protected:
- IntrControl *intctrl;
Tick txDelay;
Tick rxDelay;
void txReset();
void rxReset();
- void regsReset() {
- memset(®s, 0, sizeof(regs));
- regs.mear = 0x12;
- regs.isr = 0x00608000;
- regs.txcfg = 0x120;
- regs.rxcfg = 0x4;
- regs.srr = 0x0103;
- regs.mibc = 0x2;
- regs.vdr = 0x81;
- regs.tesr = 0xc000;
- }
+ void regsReset();
- void txKick();
void rxKick();
+ Tick rxKickTick;
+ typedef EventWrapper<NSGigE, &NSGigE::rxKick> RxKickEvent;
+ friend void RxKickEvent::process();
+ RxKickEvent rxKickEvent;
+
+ void txKick();
+ Tick txKickTick;
+ typedef EventWrapper<NSGigE, &NSGigE::txKick> TxKickEvent;
+ friend void TxKickEvent::process();
+ TxKickEvent txKickEvent;
- /*
+ void eepromKick();
+
+ /**
* Retransmit event
*/
- class TxEvent : public Event
+ void transmit();
+ void txEventTransmit()
{
- protected:
- EtherDev *dev;
-
- public:
- TxEvent(EtherDev *_dev)
- : Event(&mainEventQueue), dev(_dev) {}
- void process() { dev->transmit(); }
- virtual const char *description() { return "retransmit"; }
- };
- friend class TxEvent;
+ transmit();
+ if (txState == txFifoBlock)
+ txKick();
+ }
+ typedef EventWrapper<NSGigE, &NSGigE::txEventTransmit> TxEvent;
+ friend void TxEvent::process();
TxEvent txEvent;
- void transmit();
-
-
- void txDescDone();
- void rxDescDone();
- void txDone(PacketPtr packet);
- void rxDone();
void txDump() const;
void rxDump() const;
- void devIntrPost(uint32_t interrupts);
- void devIntrClear(uint32_t interrupts);
- void devIntrChangeMask();
-
- bool cpuPendingIntr;
- void cpuIntrPost();
- void cpuIntrClear();
-
+ /**
+ * receive address filter
+ */
bool rxFilterEnable;
- bool rxFilter(PacketPtr packet);
+ bool rxFilter(const PacketPtr &packet);
bool acceptBroadcast;
bool acceptMulticast;
bool acceptUnicast;
bool acceptPerfect;
bool acceptArp;
+ bool multicastHashEnable;
- bool udpChecksum(PacketPtr packet, bool gen);
- bool tcpChecksum(PacketPtr packet, bool gen);
- bool ipChecksum(PacketPtr packet, bool gen);
- uint16_t checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len);
+ PhysicalMemory *physmem;
- public:
- EtherDev(const std::string &name, DmaEngine *de, bool use_interface,
- IntrControl *i, MemoryController *mmu, PhysicalMemory *pmem,
- PCIConfigAll *cf, PciConfigData *cd, Tsunami *t, uint32_t bus,
- uint32_t dev, uint32_t func, bool rx_filter, const int eaddr[6],
- Tick tx_delay, Tick rx_delay, Addr addr, Addr mask);
- ~EtherDev();
+ /**
+ * Interrupt management
+ */
+ void devIntrPost(uint32_t interrupts);
+ void devIntrClear(uint32_t interrupts);
+ void devIntrChangeMask();
- virtual void WriteConfig(int offset, int size, uint32_t data);
- virtual void ReadConfig(int offset, int size, uint8_t *data);
+ Tick intrDelay;
+ Tick intrTick;
+ bool cpuPendingIntr;
+ void cpuIntrPost(Tick when);
+ void cpuInterrupt();
+ void cpuIntrClear();
+
+ typedef EventWrapper<NSGigE, &NSGigE::cpuInterrupt> IntrEvent;
+ friend void IntrEvent::process();
+ IntrEvent *intrEvent;
+ NSGigEInt *interface;
+ public:
+ struct Params : public PciDev::Params
+ {
+ PhysicalMemory *pmem;
+ HierParams *hier;
+ Bus *header_bus;
+ Bus *payload_bus;
+ Tick clock;
+ Tick intr_delay;
+ Tick tx_delay;
+ Tick rx_delay;
+ Tick pio_latency;
+ bool dma_desc_free;
+ bool dma_data_free;
+ Tick dma_read_delay;
+ Tick dma_write_delay;
+ Tick dma_read_factor;
+ Tick dma_write_factor;
+ bool rx_filter;
+ Net::EthAddr eaddr;
+ uint32_t tx_fifo_size;
+ uint32_t rx_fifo_size;
+ uint32_t m5reg;
+ bool dma_no_allocate;
+ };
+ NSGigE(Params *params);
+ ~NSGigE();
+ const Params *params() const { return (const Params *)_params; }
- Fault read(MemReqPtr req, uint8_t *data);
- Fault write(MemReqPtr req, const uint8_t *data);
+ virtual void writeConfig(int offset, int size, const uint8_t *data);
+ virtual void readConfig(int offset, int size, uint8_t *data);
+
+ virtual Fault read(MemReqPtr &req, uint8_t *data);
+ virtual Fault write(MemReqPtr &req, const uint8_t *data);
bool cpuIntrPending() const;
void cpuIntrAck() { cpuIntrClear(); }
bool recvPacket(PacketPtr packet);
void transferDone();
- void setInterface(EtherDevInt *i) { assert(!interface); interface = i; }
+ void setInterface(NSGigEInt *i) { assert(!interface); interface = i; }
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string §ion);
- virtual DmaRequest *find_dmareq(uint32_t &id) {
- if (id == 0)
- return(&readRequest);
- else if (id == 1)
- return(&writeRequest);
- else
- return(NULL);
- }
-
public:
void regStats();
private:
- Statistics::Scalar<> txBytes;
- Statistics::Scalar<> rxBytes;
- Statistics::Scalar<> txPackets;
- Statistics::Scalar<> rxPackets;
- Statistics::Formula txBandwidth;
- Statistics::Formula rxBandwidth;
- Statistics::Formula txPacketRate;
- Statistics::Formula rxPacketRate;
-
- void readOneDesc(dir_t dir, uint32_t len = sizeof(ns_desc));
- void readOneFrag();
- void writeOneFrag();
+ Stats::Scalar<> txBytes;
+ Stats::Scalar<> rxBytes;
+ Stats::Scalar<> txPackets;
+ Stats::Scalar<> rxPackets;
+ Stats::Scalar<> txIpChecksums;
+ Stats::Scalar<> rxIpChecksums;
+ Stats::Scalar<> txTcpChecksums;
+ Stats::Scalar<> rxTcpChecksums;
+ Stats::Scalar<> txUdpChecksums;
+ Stats::Scalar<> rxUdpChecksums;
+ Stats::Scalar<> descDmaReads;
+ Stats::Scalar<> descDmaWrites;
+ Stats::Scalar<> descDmaRdBytes;
+ Stats::Scalar<> descDmaWrBytes;
+ Stats::Formula totBandwidth;
+ Stats::Formula totPackets;
+ Stats::Formula totBytes;
+ Stats::Formula totPacketRate;
+ Stats::Formula txBandwidth;
+ Stats::Formula rxBandwidth;
+ Stats::Formula txPacketRate;
+ Stats::Formula rxPacketRate;
+ Stats::Scalar<> postedSwi;
+ Stats::Formula coalescedSwi;
+ Stats::Scalar<> totalSwi;
+ Stats::Scalar<> postedRxIdle;
+ Stats::Formula coalescedRxIdle;
+ Stats::Scalar<> totalRxIdle;
+ Stats::Scalar<> postedRxOk;
+ Stats::Formula coalescedRxOk;
+ Stats::Scalar<> totalRxOk;
+ Stats::Scalar<> postedRxDesc;
+ Stats::Formula coalescedRxDesc;
+ Stats::Scalar<> totalRxDesc;
+ Stats::Scalar<> postedTxOk;
+ Stats::Formula coalescedTxOk;
+ Stats::Scalar<> totalTxOk;
+ Stats::Scalar<> postedTxIdle;
+ Stats::Formula coalescedTxIdle;
+ Stats::Scalar<> totalTxIdle;
+ Stats::Scalar<> postedTxDesc;
+ Stats::Formula coalescedTxDesc;
+ Stats::Scalar<> totalTxDesc;
+ Stats::Scalar<> postedRxOrn;
+ Stats::Formula coalescedRxOrn;
+ Stats::Scalar<> totalRxOrn;
+ Stats::Formula coalescedTotal;
+ Stats::Scalar<> postedInterrupts;
+ Stats::Scalar<> droppedPackets;
+
+ public:
+ Tick cacheAccess(MemReqPtr &req);
};
/*
* Ethernet Interface for an Ethernet Device
*/
-class EtherDevInt : public EtherInt
+class NSGigEInt : public EtherInt
{
private:
- EtherDev *dev;
+ NSGigE *dev;
public:
- EtherDevInt(const std::string &name, EtherDev *d)
+ NSGigEInt(const std::string &name, NSGigE *d)
: EtherInt(name), dev(d) { dev->setInterface(this); }
- virtual bool recvPacket(PacketPtr &pkt) { return dev->recvPacket(pkt); }
+ virtual bool recvPacket(PacketPtr pkt) { return dev->recvPacket(pkt); }
virtual void sendDone() { dev->transferDone(); }
};
-#endif // __NS_GIGE_HH__
+#endif // __DEV_NS_GIGE_HH__