/* * 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 */ #ifndef __DEV_NET_NS_GIGE_HH__ #define __DEV_NET_NS_GIGE_HH__ #include "base/inet.hh" #include "dev/io_device.hh" #include "dev/net/etherdevice.hh" #include "dev/net/etherint.hh" #include "dev/net/etherpkt.hh" #include "dev/net/ns_gige_reg.h" #include "dev/net/pktfifo.hh" #include "params/NSGigE.hh" #include "sim/eventq.hh" // Hash filtering constants const uint16_t FHASH_ADDR = 0x100; const uint16_t FHASH_SIZE = 0x100; // 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 */ struct dp_regs { uint32_t command; uint32_t config; uint32_t mear; uint32_t ptscr; uint32_t isr; uint32_t imr; uint32_t ier; uint32_t ihr; uint32_t txdp; uint32_t txdp_hi; uint32_t txcfg; uint32_t gpior; uint32_t rxdp; uint32_t rxdp_hi; uint32_t rxcfg; uint32_t pqcr; uint32_t wcsr; 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 vtcr; uint32_t vdr; uint32_t ccsr; uint32_t tbicr; uint32_t tbisr; uint32_t tanar; uint32_t tanlpar; uint32_t taner; uint32_t tesr; }; struct dp_rom { /** * for perfect match memory. * the linux driver doesn't use any other ROM */ uint8_t perfectMatch[ETH_ADDR_LEN]; /** * for hash table memory. * used by the freebsd driver */ uint8_t filterHash[FHASH_SIZE]; }; class NSGigEInt; class Packet; /** * NS DP83820 Ethernet device model */ class NSGigE : public EtherDevBase { 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 }; protected: /** device register file */ dp_regs regs; dp_rom rom; /** pci settings */ bool ioEnable; #if 0 bool memEnable; bool bmEnable; #endif /*** BASIC STRUCTURES FOR TX/RX ***/ /* Data FIFOs */ PacketFifo txFifo; PacketFifo rxFifo; /** various helper vars */ EthPacketPtr txPacket; EthPacketPtr rxPacket; uint8_t *txPacketBufPtr; uint8_t *rxPacketBufPtr; uint32_t txXferLen; uint32_t rxXferLen; bool rxDmaFree; bool txDmaFree; /** DescCaches */ ns_desc32 txDesc32; ns_desc32 rxDesc32; ns_desc64 txDesc64; ns_desc64 rxDesc64; /* tx State Machine */ TxState txState; bool txEnable; /** Current Transmit Descriptor Done */ bool CTDD; /** halt the tx state machine after next packet */ bool txHalt; /** 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 */ 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; /** 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; /** EEPROM State Machine */ EEPROMState eepromState; bool eepromClk; uint8_t eepromBitsToRx; uint8_t eepromOpcode; uint8_t eepromAddress; uint16_t eepromData; protected: Tick dmaReadDelay; Tick dmaWriteDelay; Tick dmaReadFactor; Tick dmaWriteFactor; void *rxDmaData; Addr rxDmaAddr; int rxDmaLen; bool doRxDmaRead(); bool doRxDmaWrite(); void *txDmaData; Addr txDmaAddr; int txDmaLen; bool doTxDmaRead(); bool doTxDmaWrite(); void rxDmaReadDone(); EventFunctionWrapper rxDmaReadEvent; void rxDmaWriteDone(); EventFunctionWrapper rxDmaWriteEvent; void txDmaReadDone(); EventFunctionWrapper txDmaReadEvent; void txDmaWriteDone(); EventFunctionWrapper txDmaWriteEvent; bool dmaDescFree; bool dmaDataFree; protected: Tick txDelay; Tick rxDelay; void txReset(); void rxReset(); void regsReset(); void rxKick(); Tick rxKickTick; EventFunctionWrapper rxKickEvent; void txKick(); Tick txKickTick; EventFunctionWrapper txKickEvent; void eepromKick(); /** * Retransmit event */ void transmit(); void txEventTransmit() { transmit(); if (txState == txFifoBlock) txKick(); } EventFunctionWrapper txEvent; void txDump() const; void rxDump() const; /** * receive address filter */ bool rxFilterEnable; bool rxFilter(const EthPacketPtr &packet); bool acceptBroadcast; bool acceptMulticast; bool acceptUnicast; bool acceptPerfect; bool acceptArp; bool multicastHashEnable; /** * Interrupt management */ void devIntrPost(uint32_t interrupts); void devIntrClear(uint32_t interrupts); void devIntrChangeMask(); Tick intrDelay; Tick intrTick; bool cpuPendingIntr; void cpuIntrPost(Tick when); void cpuInterrupt(); void cpuIntrClear(); EventFunctionWrapper *intrEvent; NSGigEInt *interface; public: typedef NSGigEParams Params; const Params *params() const { return dynamic_cast(_params); } NSGigE(Params *params); ~NSGigE(); EtherInt *getEthPort(const std::string &if_name, int idx) override; Tick writeConfig(PacketPtr pkt) override; Tick read(PacketPtr pkt) override; Tick write(PacketPtr pkt) override; bool cpuIntrPending() const; void cpuIntrAck() { cpuIntrClear(); } bool recvPacket(EthPacketPtr packet); void transferDone(); void serialize(CheckpointOut &cp) const override; void unserialize(CheckpointIn &cp) override; void drainResume() override; }; /* * Ethernet Interface for an Ethernet Device */ class NSGigEInt : public EtherInt { private: NSGigE *dev; public: NSGigEInt(const std::string &name, NSGigE *d) : EtherInt(name), dev(d) { } virtual bool recvPacket(EthPacketPtr pkt) { return dev->recvPacket(pkt); } virtual void sendDone() { dev->transferDone(); } }; #endif // __DEV_NET_NS_GIGE_HH__