|  | /* | 
|  | * 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; | 
|  |  | 
|  | /*** 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<const Params *>(_params); | 
|  | } | 
|  |  | 
|  | NSGigE(Params *params); | 
|  | ~NSGigE(); | 
|  |  | 
|  | Port &getPort(const std::string &if_name, | 
|  | PortID idx=InvalidPortID) 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__ |