i8254xGBe.hh revision 11263
13116SN/A/*
23116SN/A * Copyright (c) 2006 The Regents of The University of Michigan
33116SN/A * All rights reserved.
43116SN/A *
53116SN/A * Redistribution and use in source and binary forms, with or without
63116SN/A * modification, are permitted provided that the following conditions are
73116SN/A * met: redistributions of source code must retain the above copyright
83116SN/A * notice, this list of conditions and the following disclaimer;
93116SN/A * redistributions in binary form must reproduce the above copyright
103116SN/A * notice, this list of conditions and the following disclaimer in the
113116SN/A * documentation and/or other materials provided with the distribution;
123116SN/A * neither the name of the copyright holders nor the names of its
133116SN/A * contributors may be used to endorse or promote products derived from
143116SN/A * this software without specific prior written permission.
153116SN/A *
163116SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173116SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183116SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193116SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203116SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213116SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223116SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233116SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243116SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253116SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263116SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273116SN/A *
283116SN/A * Authors: Ali Saidi
293116SN/A */
303116SN/A
313116SN/A/* @file
323116SN/A * Device model for Intel's 8254x line of gigabit ethernet controllers.
333116SN/A */
343116SN/A
3511263Sandreas.sandberg@arm.com#ifndef __DEV_NET_I8254XGBE_HH__
3611263Sandreas.sandberg@arm.com#define __DEV_NET_I8254XGBE_HH__
373116SN/A
384263SN/A#include <deque>
394263SN/A#include <string>
404263SN/A
415954SN/A#include "base/cp_annotate.hh"
423116SN/A#include "base/inet.hh"
438232SN/A#include "debug/EthernetDesc.hh"
448232SN/A#include "debug/EthernetIntr.hh"
4511263Sandreas.sandberg@arm.com#include "dev/net/etherdevice.hh"
4611263Sandreas.sandberg@arm.com#include "dev/net/etherint.hh"
4711263Sandreas.sandberg@arm.com#include "dev/net/etherpkt.hh"
4811263Sandreas.sandberg@arm.com#include "dev/net/i8254xGBe_defs.hh"
4911263Sandreas.sandberg@arm.com#include "dev/net/pktfifo.hh"
5011260SN/A#include "dev/pci/device.hh"
514762SN/A#include "params/IGbE.hh"
523116SN/A#include "sim/eventq.hh"
533116SN/A
543116SN/Aclass IGbEInt;
553116SN/A
564981SN/Aclass IGbE : public EtherDevice
573116SN/A{
583116SN/A  private:
593116SN/A    IGbEInt *etherInt;
605954SN/A    CPA *cpa;
614263SN/A
624263SN/A    // device registers
633318SN/A    iGbReg::Regs regs;
644263SN/A
654263SN/A    // eeprom data, status and control bits
663318SN/A    int eeOpBits, eeAddrBits, eeDataBits;
673318SN/A    uint8_t eeOpcode, eeAddr;
684263SN/A    uint16_t flash[iGbReg::EEPROM_SIZE];
693318SN/A
704263SN/A    // packet fifos
714263SN/A    PacketFifo rxFifo;
724263SN/A    PacketFifo txFifo;
733318SN/A
744263SN/A    // Packet that we are currently putting into the txFifo
754263SN/A    EthPacketPtr txPacket;
764263SN/A
774263SN/A    // Should to Rx/Tx State machine tick?
784263SN/A    bool rxTick;
794263SN/A    bool txTick;
804291SN/A    bool txFifoTick;
814263SN/A
824452SN/A    bool rxDmaPacket;
834452SN/A
845783SN/A    // Number of bytes copied from current RX packet
856227SN/A    unsigned pktOffset;
865783SN/A
875535SN/A    // Delays in managaging descriptors
885535SN/A    Tick fetchDelay, wbDelay;
895535SN/A    Tick fetchCompDelay, wbCompDelay;
905535SN/A    Tick rxWriteDelay, txReadDelay;
915535SN/A
924263SN/A    // Event and function to deal with RDTR timer expiring
934291SN/A    void rdtrProcess() {
944291SN/A        rxDescCache.writeback(0);
956124SN/A        DPRINTF(EthernetIntr,
966124SN/A                "Posting RXT interrupt because RDTR timer expired\n");
975533SN/A        postInterrupt(iGbReg::IT_RXT);
984291SN/A    }
994291SN/A
1004263SN/A    //friend class EventWrapper<IGbE, &IGbE::rdtrProcess>;
1014263SN/A    EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent;
1024263SN/A
1034263SN/A    // Event and function to deal with RADV timer expiring
1044291SN/A    void radvProcess() {
1054291SN/A        rxDescCache.writeback(0);
1066124SN/A        DPRINTF(EthernetIntr,
1076124SN/A                "Posting RXT interrupt because RADV timer expired\n");
1085533SN/A        postInterrupt(iGbReg::IT_RXT);
1094291SN/A    }
1104291SN/A
1114263SN/A    //friend class EventWrapper<IGbE, &IGbE::radvProcess>;
1124263SN/A    EventWrapper<IGbE, &IGbE::radvProcess> radvEvent;
1134263SN/A
1144263SN/A    // Event and function to deal with TADV timer expiring
1154291SN/A    void tadvProcess() {
1164291SN/A        txDescCache.writeback(0);
1176124SN/A        DPRINTF(EthernetIntr,
1186124SN/A                "Posting TXDW interrupt because TADV timer expired\n");
1195533SN/A        postInterrupt(iGbReg::IT_TXDW);
1204291SN/A    }
1214291SN/A
1224263SN/A    //friend class EventWrapper<IGbE, &IGbE::tadvProcess>;
1234263SN/A    EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent;
1244263SN/A
1254263SN/A    // Event and function to deal with TIDV timer expiring
1264291SN/A    void tidvProcess() {
1274291SN/A        txDescCache.writeback(0);
1286124SN/A        DPRINTF(EthernetIntr,
1296124SN/A                "Posting TXDW interrupt because TIDV timer expired\n");
1305533SN/A        postInterrupt(iGbReg::IT_TXDW);
1314291SN/A    }
1324263SN/A    //friend class EventWrapper<IGbE, &IGbE::tidvProcess>;
1334263SN/A    EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent;
1344263SN/A
1354263SN/A    // Main event to tick the device
1364263SN/A    void tick();
1374263SN/A    //friend class EventWrapper<IGbE, &IGbE::tick>;
1384263SN/A    EventWrapper<IGbE, &IGbE::tick> tickEvent;
1394263SN/A
1404263SN/A
1415538SN/A    uint64_t macAddr;
1425538SN/A
1434263SN/A    void rxStateMachine();
1444263SN/A    void txStateMachine();
1454263SN/A    void txWire();
1464263SN/A
1474263SN/A    /** Write an interrupt into the interrupt pending register and check mask
1484263SN/A     * and interrupt limit timer before sending interrupt to CPU
1494263SN/A     * @param t the type of interrupt we are posting
1504263SN/A     * @param now should we ignore the interrupt limiting timer
1514263SN/A     */
1524263SN/A    void postInterrupt(iGbReg::IntTypes t, bool now = false);
1534263SN/A
1544263SN/A    /** Check and see if changes to the mask register have caused an interrupt
1554263SN/A     * to need to be sent or perhaps removed an interrupt cause.
1564263SN/A     */
1574263SN/A    void chkInterrupt();
1584263SN/A
1594263SN/A    /** Send an interrupt to the cpu
1604263SN/A     */
1614987SN/A    void delayIntEvent();
1624263SN/A    void cpuPostInt();
1634263SN/A    // Event to moderate interrupts
1644987SN/A    EventWrapper<IGbE, &IGbE::delayIntEvent> interEvent;
1654263SN/A
1664263SN/A    /** Clear the interupt line to the cpu
1674263SN/A     */
1684263SN/A    void cpuClearInt();
1694263SN/A
1707064SN/A    Tick intClock() { return SimClock::Int::ns * 1024; }
1714263SN/A
1724294SN/A    /** This function is used to restart the clock so it can handle things like
1734294SN/A     * draining and resume in one place. */
1744283SN/A    void restartClock();
1754283SN/A
1764294SN/A    /** Check if all the draining things that need to occur have occured and
1774294SN/A     * handle the drain event if so.
1784294SN/A     */
1794294SN/A    void checkDrain();
1804294SN/A
1815954SN/A    void anBegin(std::string sm, std::string st, int flags = CPA::FL_NONE) {
18210702SN/A        if (cpa)
18310702SN/A            cpa->hwBegin((CPA::flags)flags, sys, macAddr, sm, st);
1845954SN/A    }
1855954SN/A
18610702SN/A    void anQ(std::string sm, std::string q) {
18710702SN/A        if (cpa)
18810702SN/A            cpa->hwQ(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
1895954SN/A    }
1905954SN/A
1915954SN/A    void anDq(std::string sm, std::string q) {
19210702SN/A        if (cpa)
19310702SN/A            cpa->hwDq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
1945954SN/A    }
1955954SN/A
1965954SN/A    void anPq(std::string sm, std::string q, int num = 1) {
19710702SN/A        if (cpa)
19810702SN/A            cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num);
1995954SN/A    }
2005954SN/A
2015954SN/A    void anRq(std::string sm, std::string q, int num = 1) {
20210702SN/A        if (cpa)
20310702SN/A            cpa->hwRq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num);
2045954SN/A    }
2055954SN/A
2065954SN/A    void anWe(std::string sm, std::string q) {
20710702SN/A        if (cpa)
20810702SN/A            cpa->hwWe(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
2095954SN/A    }
2105954SN/A
2115954SN/A    void anWf(std::string sm, std::string q) {
21210702SN/A        if (cpa)
21310702SN/A            cpa->hwWf(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
2145954SN/A    }
2155954SN/A
2165954SN/A
2174263SN/A    template<class T>
21810905SN/A    class DescCache : public Serializable
2194263SN/A    {
2204263SN/A      protected:
2214263SN/A        virtual Addr descBase() const = 0;
2224263SN/A        virtual long descHead() const = 0;
2234263SN/A        virtual long descTail() const = 0;
2244263SN/A        virtual long descLen() const = 0;
2254263SN/A        virtual void updateHead(long h) = 0;
2264263SN/A        virtual void enableSm() = 0;
2275763SN/A        virtual void actionAfterWb() {}
2284987SN/A        virtual void fetchAfterWb() = 0;
2294263SN/A
2306227SN/A        typedef std::deque<T *> CacheType;
2316227SN/A        CacheType usedCache;
2326227SN/A        CacheType unusedCache;
2334263SN/A
2344263SN/A        T *fetchBuf;
2354263SN/A        T *wbBuf;
2364263SN/A
2374263SN/A        // Pointer to the device we cache for
2384263SN/A        IGbE *igbe;
2394263SN/A
2404263SN/A        // Name of this  descriptor cache
2414263SN/A        std::string _name;
2424263SN/A
2434263SN/A        // How far we've cached
2444263SN/A        int cachePnt;
2454263SN/A
2464263SN/A        // The size of the descriptor cache
2474263SN/A        int size;
2484263SN/A
2494263SN/A        // How many descriptors we are currently fetching
2504263SN/A        int curFetching;
2514263SN/A
2524263SN/A        // How many descriptors we are currently writing back
2534263SN/A        int wbOut;
2544263SN/A
2554263SN/A        // if the we wrote back to the end of the descriptor ring and are going
2564263SN/A        // to have to wrap and write more
2574263SN/A        bool moreToWb;
2584263SN/A
2594263SN/A        // What the alignment is of the next descriptor writeback
2604263SN/A        Addr wbAlignment;
2614263SN/A
2626124SN/A        /** The packet that is currently being dmad to memory if any */
2634263SN/A        EthPacketPtr pktPtr;
2644263SN/A
2656124SN/A        /** Shortcut for DMA address translation */
26611202SN/A        Addr pciToDma(Addr a) { return igbe->pciToDma(a); }
2676124SN/A
2684263SN/A      public:
2695954SN/A        /** Annotate sm*/
2705954SN/A        std::string annSmFetch, annSmWb, annUnusedDescQ, annUsedCacheQ,
2715954SN/A            annUsedDescQ, annUnusedCacheQ, annDescQ;
2725954SN/A
2736124SN/A        DescCache(IGbE *i, const std::string n, int s);
2746124SN/A        virtual ~DescCache();
2754263SN/A
2764263SN/A        std::string name() { return _name; }
2774263SN/A
2784263SN/A        /** If the address/len/head change when we've got descriptors that are
2794263SN/A         * dirty that is very bad. This function checks that we don't and if we
2804263SN/A         * do panics.
2814263SN/A         */
2826124SN/A        void areaChanged();
2834291SN/A
2846124SN/A        void writeback(Addr aMask);
2856124SN/A        void writeback1();
2865535SN/A        EventWrapper<DescCache, &DescCache::writeback1> wbDelayEvent;
2874263SN/A
2884263SN/A        /** Fetch a chunk of descriptors into the descriptor cache.
2894263SN/A         * Calls fetchComplete when the memory system returns the data
2904263SN/A         */
2916124SN/A        void fetchDescriptors();
2926124SN/A        void fetchDescriptors1();
2935535SN/A        EventWrapper<DescCache, &DescCache::fetchDescriptors1> fetchDelayEvent;
2944263SN/A
2954263SN/A        /** Called by event when dma to read descriptors is completed
2964263SN/A         */
2976124SN/A        void fetchComplete();
2984263SN/A        EventWrapper<DescCache, &DescCache::fetchComplete> fetchEvent;
2994263SN/A
3004263SN/A        /** Called by event when dma to writeback descriptors is completed
3014263SN/A         */
3026124SN/A        void wbComplete();
3034263SN/A        EventWrapper<DescCache, &DescCache::wbComplete> wbEvent;
3044263SN/A
3054263SN/A        /* Return the number of descriptors left in the ring, so the device has
3064263SN/A         * a way to figure out if it needs to interrupt.
3074263SN/A         */
3086227SN/A        unsigned
3096227SN/A        descLeft() const
3104263SN/A        {
3116227SN/A            unsigned left = unusedCache.size();
3126217SN/A            if (cachePnt > descTail())
3135762SN/A                left += (descLen() - cachePnt + descTail());
3144263SN/A            else
3154283SN/A                left += (descTail() - cachePnt);
3164263SN/A
3174263SN/A            return left;
3184263SN/A        }
3194263SN/A
3204263SN/A        /* Return the number of descriptors used and not written back.
3214263SN/A         */
3226227SN/A        unsigned descUsed() const { return usedCache.size(); }
3234263SN/A
3244263SN/A        /* Return the number of cache unused descriptors we have. */
3256227SN/A        unsigned descUnused() const { return unusedCache.size(); }
3264263SN/A
3274263SN/A        /* Get into a state where the descriptor address/head/etc colud be
3284263SN/A         * changed */
3296124SN/A        void reset();
3304263SN/A
33110905SN/A
33211168SN/A        void serialize(CheckpointOut &cp) const override;
33311168SN/A        void unserialize(CheckpointIn &cp) override;
3344291SN/A
3354294SN/A        virtual bool hasOutstandingEvents() {
3364294SN/A            return wbEvent.scheduled() || fetchEvent.scheduled();
3374294SN/A        }
3384294SN/A
3396124SN/A    };
3404263SN/A
3414263SN/A
3424263SN/A    class RxDescCache : public DescCache<iGbReg::RxDesc>
3434263SN/A    {
3444263SN/A      protected:
34511169SN/A        Addr descBase() const override { return igbe->regs.rdba(); }
34611169SN/A        long descHead() const override { return igbe->regs.rdh(); }
34711169SN/A        long descLen() const override { return igbe->regs.rdlen() >> 4; }
34811169SN/A        long descTail() const override { return igbe->regs.rdt(); }
34911169SN/A        void updateHead(long h) override { igbe->regs.rdh(h); }
35011169SN/A        void enableSm() override;
35111169SN/A        void fetchAfterWb() override {
35210913SN/A            if (!igbe->rxTick && igbe->drainState() == DrainState::Running)
3534987SN/A                fetchDescriptors();
3544987SN/A        }
3554263SN/A
3564263SN/A        bool pktDone;
3574263SN/A
3585783SN/A        /** Variable to head with header/data completion events */
3595783SN/A        int splitCount;
3605783SN/A
3616124SN/A        /** Bytes of packet that have been copied, so we know when to
3626124SN/A            set EOP */
3636227SN/A        unsigned bytesCopied;
3645783SN/A
3654263SN/A      public:
3664263SN/A        RxDescCache(IGbE *i, std::string n, int s);
3674263SN/A
3684263SN/A        /** Write the given packet into the buffer(s) pointed to by the
3694263SN/A         * descriptor and update the book keeping. Should only be called when
3704263SN/A         * there are no dma's pending.
3714263SN/A         * @param packet ethernet packet to write
3725783SN/A         * @param pkt_offset bytes already copied from the packet to memory
3735783SN/A         * @return pkt_offset + number of bytes copied during this call
3744263SN/A         */
3755783SN/A        int writePacket(EthPacketPtr packet, int pkt_offset);
3765783SN/A
3774263SN/A        /** Called by event when dma to write packet is completed
3784263SN/A         */
3794263SN/A        void pktComplete();
3804263SN/A
3815783SN/A        /** Check if the dma on the packet has completed and RX state machine
3825783SN/A         * can continue
3834263SN/A         */
3844263SN/A        bool packetDone();
3854263SN/A
3864263SN/A        EventWrapper<RxDescCache, &RxDescCache::pktComplete> pktEvent;
3874263SN/A
3885783SN/A        // Event to handle issuing header and data write at the same time
3895783SN/A        // and only callking pktComplete() when both are completed
3905783SN/A        void pktSplitDone();
3915783SN/A        EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktHdrEvent;
3925783SN/A        EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktDataEvent;
3935783SN/A
39411169SN/A        bool hasOutstandingEvents() override;
3954294SN/A
39611168SN/A        void serialize(CheckpointOut &cp) const override;
39711168SN/A        void unserialize(CheckpointIn &cp) override;
3984263SN/A    };
3994263SN/A    friend class RxDescCache;
4004263SN/A
4014263SN/A    RxDescCache rxDescCache;
4024263SN/A
4034263SN/A    class TxDescCache  : public DescCache<iGbReg::TxDesc>
4044263SN/A    {
4054263SN/A      protected:
40611169SN/A        Addr descBase() const override { return igbe->regs.tdba(); }
40711169SN/A        long descHead() const override { return igbe->regs.tdh(); }
40811169SN/A        long descTail() const override { return igbe->regs.tdt(); }
40911169SN/A        long descLen() const override { return igbe->regs.tdlen() >> 4; }
41011169SN/A        void updateHead(long h) override { igbe->regs.tdh(h); }
41111169SN/A        void enableSm() override;
41211169SN/A        void actionAfterWb() override;
41311169SN/A        void fetchAfterWb() override {
41410913SN/A            if (!igbe->txTick && igbe->drainState() == DrainState::Running)
4154987SN/A                fetchDescriptors();
4164987SN/A        }
4175763SN/A
4185763SN/A
4194263SN/A
4204263SN/A        bool pktDone;
4214263SN/A        bool isTcp;
4224263SN/A        bool pktWaiting;
4235404SN/A        bool pktMultiDesc;
4245763SN/A        Addr completionAddress;
4255763SN/A        bool completionEnabled;
4265763SN/A        uint32_t descEnd;
4275763SN/A
4284263SN/A
4295762SN/A        // tso variables
4305762SN/A        bool useTso;
4315762SN/A        Addr tsoHeaderLen;
4325762SN/A        Addr tsoMss;
4335762SN/A        Addr tsoTotalLen;
4345762SN/A        Addr tsoUsedLen;
4358902SN/A        Addr tsoPrevSeq;
4365762SN/A        Addr tsoPktPayloadBytes;
4375762SN/A        bool tsoLoadedHeader;
4385762SN/A        bool tsoPktHasHeader;
4395762SN/A        uint8_t tsoHeader[256];
4405762SN/A        Addr tsoDescBytesUsed;
4415762SN/A        Addr tsoCopyBytes;
4425762SN/A        int tsoPkts;
4435762SN/A
4444263SN/A      public:
4454263SN/A        TxDescCache(IGbE *i, std::string n, int s);
4464263SN/A
4474263SN/A        /** Tell the cache to DMA a packet from main memory into its buffer and
4484263SN/A         * return the size the of the packet to reserve space in tx fifo.
4494263SN/A         * @return size of the packet
4504263SN/A         */
4516227SN/A        unsigned getPacketSize(EthPacketPtr p);
4524263SN/A        void getPacketData(EthPacketPtr p);
4535762SN/A        void processContextDesc();
4544263SN/A
4555763SN/A        /** Return the number of dsecriptors in a cache block for threshold
4565763SN/A         * operations.
4575763SN/A         */
4586227SN/A        unsigned
4596227SN/A        descInBlock(unsigned num_desc)
4606227SN/A        {
4616227SN/A            return num_desc / igbe->cacheBlockSize() / sizeof(iGbReg::TxDesc);
4626227SN/A        }
4636227SN/A
4644263SN/A        /** Ask if the packet has been transfered so the state machine can give
4654263SN/A         * it to the fifo.
4664263SN/A         * @return packet available in descriptor cache
4674263SN/A         */
4684263SN/A        bool packetAvailable();
4694263SN/A
4704263SN/A        /** Ask if we are still waiting for the packet to be transfered.
4714263SN/A         * @return packet still in transit.
4724263SN/A         */
4734263SN/A        bool packetWaiting() { return pktWaiting; }
4744263SN/A
4755404SN/A        /** Ask if this packet is composed of multiple descriptors
4765404SN/A         * so even if we've got data, we need to wait for more before
4775404SN/A         * we can send it out.
4785404SN/A         * @return packet can't be sent out because it's a multi-descriptor
4795404SN/A         * packet
4805404SN/A         */
4815404SN/A        bool packetMultiDesc() { return pktMultiDesc;}
4825404SN/A
4834263SN/A        /** Called by event when dma to write packet is completed
4844263SN/A         */
4854263SN/A        void pktComplete();
4864263SN/A        EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent;
4874263SN/A
4885762SN/A        void headerComplete();
4895762SN/A        EventWrapper<TxDescCache, &TxDescCache::headerComplete> headerEvent;
4905762SN/A
4915763SN/A
4925763SN/A        void completionWriteback(Addr a, bool enabled) {
4936124SN/A            DPRINTF(EthernetDesc,
4946124SN/A                    "Completion writeback Addr: %#x enabled: %d\n",
4955763SN/A                    a, enabled);
4965763SN/A            completionAddress = a;
4975763SN/A            completionEnabled = enabled;
4985763SN/A        }
4995763SN/A
50011169SN/A        bool hasOutstandingEvents() override;
5014294SN/A
5026124SN/A        void nullCallback() {
5036124SN/A            DPRINTF(EthernetDesc, "Completion writeback complete\n");
5046124SN/A        }
5055763SN/A        EventWrapper<TxDescCache, &TxDescCache::nullCallback> nullEvent;
5065763SN/A
50711168SN/A        void serialize(CheckpointOut &cp) const override;
50811168SN/A        void unserialize(CheckpointIn &cp) override;
50910905SN/A    };
5104294SN/A
5114263SN/A    friend class TxDescCache;
5124263SN/A
5134263SN/A    TxDescCache txDescCache;
5143116SN/A
5153116SN/A  public:
5164762SN/A    typedef IGbEParams Params;
5174762SN/A    const Params *
5186124SN/A    params() const {
5194762SN/A        return dynamic_cast<const Params *>(_params);
5204762SN/A    }
5216124SN/A
5224981SN/A    IGbE(const Params *params);
5239086SN/A    ~IGbE();
52411169SN/A    void init() override;
5253116SN/A
52611169SN/A    EtherInt *getEthPort(const std::string &if_name, int idx) override;
5274981SN/A
5285500SN/A    Tick lastInterrupt;
5294263SN/A
53011169SN/A    Tick read(PacketPtr pkt) override;
53111169SN/A    Tick write(PacketPtr pkt) override;
5323116SN/A
53311169SN/A    Tick writeConfig(PacketPtr pkt) override;
5343116SN/A
5353116SN/A    bool ethRxPkt(EthPacketPtr packet);
5363116SN/A    void ethTxDone();
5373116SN/A
53811168SN/A    void serialize(CheckpointOut &cp) const override;
53911168SN/A    void unserialize(CheckpointIn &cp) override;
5409342SN/A
54111168SN/A    DrainState drain() override;
54211168SN/A    void drainResume() override;
5433116SN/A
5443116SN/A};
5453116SN/A
5463116SN/Aclass IGbEInt : public EtherInt
5473116SN/A{
5483116SN/A  private:
5493116SN/A    IGbE *dev;
5503116SN/A
5513116SN/A  public:
5523116SN/A    IGbEInt(const std::string &name, IGbE *d)
5533116SN/A        : EtherInt(name), dev(d)
5544981SN/A    { }
5553116SN/A
5563116SN/A    virtual bool recvPacket(EthPacketPtr pkt) { return dev->ethRxPkt(pkt); }
5573116SN/A    virtual void sendDone() { dev->ethTxDone(); }
5583116SN/A};
5593116SN/A
56011263Sandreas.sandberg@arm.com#endif //__DEV_NET_I8254XGBE_HH__
561