i8254xGBe.hh revision 9342
17375Sgblack@eecs.umich.edu/*
27375Sgblack@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan
37375Sgblack@eecs.umich.edu * All rights reserved.
47375Sgblack@eecs.umich.edu *
57375Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67375Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77375Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87375Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97375Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107375Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117375Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127375Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137375Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147375Sgblack@eecs.umich.edu * this software without specific prior written permission.
157375Sgblack@eecs.umich.edu *
167375Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177375Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187375Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197375Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207375Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217375Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227375Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237375Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247375Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257375Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267375Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277375Sgblack@eecs.umich.edu *
287375Sgblack@eecs.umich.edu * Authors: Ali Saidi
297375Sgblack@eecs.umich.edu */
307375Sgblack@eecs.umich.edu
317375Sgblack@eecs.umich.edu/* @file
327375Sgblack@eecs.umich.edu * Device model for Intel's 8254x line of gigabit ethernet controllers.
337375Sgblack@eecs.umich.edu */
347375Sgblack@eecs.umich.edu
357375Sgblack@eecs.umich.edu#ifndef __DEV_I8254XGBE_HH__
367375Sgblack@eecs.umich.edu#define __DEV_I8254XGBE_HH__
377375Sgblack@eecs.umich.edu
387375Sgblack@eecs.umich.edu#include <deque>
397375Sgblack@eecs.umich.edu#include <string>
407375Sgblack@eecs.umich.edu
417375Sgblack@eecs.umich.edu#include "base/cp_annotate.hh"
427375Sgblack@eecs.umich.edu#include "base/inet.hh"
437375Sgblack@eecs.umich.edu#include "debug/EthernetDesc.hh"
447378Sgblack@eecs.umich.edu#include "debug/EthernetIntr.hh"
457378Sgblack@eecs.umich.edu#include "dev/etherdevice.hh"
467382Sgblack@eecs.umich.edu#include "dev/etherint.hh"
477375Sgblack@eecs.umich.edu#include "dev/etherpkt.hh"
487384Sgblack@eecs.umich.edu#include "dev/i8254xGBe_defs.hh"
497384Sgblack@eecs.umich.edu#include "dev/pcidev.hh"
507384Sgblack@eecs.umich.edu#include "dev/pktfifo.hh"
517375Sgblack@eecs.umich.edu#include "params/IGbE.hh"
527375Sgblack@eecs.umich.edu#include "sim/eventq.hh"
537375Sgblack@eecs.umich.edu
547375Sgblack@eecs.umich.educlass IGbEInt;
557375Sgblack@eecs.umich.edu
567375Sgblack@eecs.umich.educlass IGbE : public EtherDevice
577375Sgblack@eecs.umich.edu{
587375Sgblack@eecs.umich.edu  private:
597375Sgblack@eecs.umich.edu    IGbEInt *etherInt;
607375Sgblack@eecs.umich.edu    CPA *cpa;
617375Sgblack@eecs.umich.edu
627375Sgblack@eecs.umich.edu    // device registers
637375Sgblack@eecs.umich.edu    iGbReg::Regs regs;
647375Sgblack@eecs.umich.edu
657375Sgblack@eecs.umich.edu    // eeprom data, status and control bits
667375Sgblack@eecs.umich.edu    int eeOpBits, eeAddrBits, eeDataBits;
677375Sgblack@eecs.umich.edu    uint8_t eeOpcode, eeAddr;
687375Sgblack@eecs.umich.edu    uint16_t flash[iGbReg::EEPROM_SIZE];
697375Sgblack@eecs.umich.edu
707375Sgblack@eecs.umich.edu    // The drain event if we have one
717375Sgblack@eecs.umich.edu    DrainManager *drainManager;
727375Sgblack@eecs.umich.edu
737375Sgblack@eecs.umich.edu    // cached parameters from params struct
747375Sgblack@eecs.umich.edu    bool useFlowControl;
757375Sgblack@eecs.umich.edu
767375Sgblack@eecs.umich.edu    // packet fifos
777376Sgblack@eecs.umich.edu    PacketFifo rxFifo;
787376Sgblack@eecs.umich.edu    PacketFifo txFifo;
797376Sgblack@eecs.umich.edu
807375Sgblack@eecs.umich.edu    // Packet that we are currently putting into the txFifo
817375Sgblack@eecs.umich.edu    EthPacketPtr txPacket;
827378Sgblack@eecs.umich.edu
837378Sgblack@eecs.umich.edu    // Should to Rx/Tx State machine tick?
847378Sgblack@eecs.umich.edu    bool rxTick;
857378Sgblack@eecs.umich.edu    bool txTick;
867378Sgblack@eecs.umich.edu    bool txFifoTick;
877378Sgblack@eecs.umich.edu
887378Sgblack@eecs.umich.edu    bool rxDmaPacket;
897378Sgblack@eecs.umich.edu
907378Sgblack@eecs.umich.edu    // Number of bytes copied from current RX packet
917378Sgblack@eecs.umich.edu    unsigned pktOffset;
927378Sgblack@eecs.umich.edu
937378Sgblack@eecs.umich.edu    // Delays in managaging descriptors
947378Sgblack@eecs.umich.edu    Tick fetchDelay, wbDelay;
957378Sgblack@eecs.umich.edu    Tick fetchCompDelay, wbCompDelay;
967378Sgblack@eecs.umich.edu    Tick rxWriteDelay, txReadDelay;
977378Sgblack@eecs.umich.edu
987378Sgblack@eecs.umich.edu    // Event and function to deal with RDTR timer expiring
997378Sgblack@eecs.umich.edu    void rdtrProcess() {
1007378Sgblack@eecs.umich.edu        rxDescCache.writeback(0);
1017378Sgblack@eecs.umich.edu        DPRINTF(EthernetIntr,
1027378Sgblack@eecs.umich.edu                "Posting RXT interrupt because RDTR timer expired\n");
1037378Sgblack@eecs.umich.edu        postInterrupt(iGbReg::IT_RXT);
1047378Sgblack@eecs.umich.edu    }
1057378Sgblack@eecs.umich.edu
1067378Sgblack@eecs.umich.edu    //friend class EventWrapper<IGbE, &IGbE::rdtrProcess>;
1077378Sgblack@eecs.umich.edu    EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent;
1087382Sgblack@eecs.umich.edu
1097396Sgblack@eecs.umich.edu    // Event and function to deal with RADV timer expiring
1107396Sgblack@eecs.umich.edu    void radvProcess() {
1117396Sgblack@eecs.umich.edu        rxDescCache.writeback(0);
1127396Sgblack@eecs.umich.edu        DPRINTF(EthernetIntr,
1137396Sgblack@eecs.umich.edu                "Posting RXT interrupt because RADV timer expired\n");
1147396Sgblack@eecs.umich.edu        postInterrupt(iGbReg::IT_RXT);
1157396Sgblack@eecs.umich.edu    }
1167396Sgblack@eecs.umich.edu
1177396Sgblack@eecs.umich.edu    //friend class EventWrapper<IGbE, &IGbE::radvProcess>;
1187396Sgblack@eecs.umich.edu    EventWrapper<IGbE, &IGbE::radvProcess> radvEvent;
1197396Sgblack@eecs.umich.edu
1207396Sgblack@eecs.umich.edu    // Event and function to deal with TADV timer expiring
1217396Sgblack@eecs.umich.edu    void tadvProcess() {
1227396Sgblack@eecs.umich.edu        txDescCache.writeback(0);
1237396Sgblack@eecs.umich.edu        DPRINTF(EthernetIntr,
1247396Sgblack@eecs.umich.edu                "Posting TXDW interrupt because TADV timer expired\n");
1257396Sgblack@eecs.umich.edu        postInterrupt(iGbReg::IT_TXDW);
1267396Sgblack@eecs.umich.edu    }
1277396Sgblack@eecs.umich.edu
1287396Sgblack@eecs.umich.edu    //friend class EventWrapper<IGbE, &IGbE::tadvProcess>;
1297396Sgblack@eecs.umich.edu    EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent;
1307397Sgblack@eecs.umich.edu
1317397Sgblack@eecs.umich.edu    // Event and function to deal with TIDV timer expiring
1327397Sgblack@eecs.umich.edu    void tidvProcess() {
1337397Sgblack@eecs.umich.edu        txDescCache.writeback(0);
1347397Sgblack@eecs.umich.edu        DPRINTF(EthernetIntr,
1357397Sgblack@eecs.umich.edu                "Posting TXDW interrupt because TIDV timer expired\n");
1367397Sgblack@eecs.umich.edu        postInterrupt(iGbReg::IT_TXDW);
1377397Sgblack@eecs.umich.edu    }
1387397Sgblack@eecs.umich.edu    //friend class EventWrapper<IGbE, &IGbE::tidvProcess>;
1397397Sgblack@eecs.umich.edu    EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent;
1407397Sgblack@eecs.umich.edu
1417397Sgblack@eecs.umich.edu    // Main event to tick the device
1427397Sgblack@eecs.umich.edu    void tick();
1437397Sgblack@eecs.umich.edu    //friend class EventWrapper<IGbE, &IGbE::tick>;
1447397Sgblack@eecs.umich.edu    EventWrapper<IGbE, &IGbE::tick> tickEvent;
1457397Sgblack@eecs.umich.edu
1467397Sgblack@eecs.umich.edu
1477384Sgblack@eecs.umich.edu    uint64_t macAddr;
1487384Sgblack@eecs.umich.edu
1497384Sgblack@eecs.umich.edu    void rxStateMachine();
1507384Sgblack@eecs.umich.edu    void txStateMachine();
1517384Sgblack@eecs.umich.edu    void txWire();
1527384Sgblack@eecs.umich.edu
1537384Sgblack@eecs.umich.edu    /** Write an interrupt into the interrupt pending register and check mask
1547384Sgblack@eecs.umich.edu     * and interrupt limit timer before sending interrupt to CPU
1557384Sgblack@eecs.umich.edu     * @param t the type of interrupt we are posting
1567384Sgblack@eecs.umich.edu     * @param now should we ignore the interrupt limiting timer
1577384Sgblack@eecs.umich.edu     */
1587384Sgblack@eecs.umich.edu    void postInterrupt(iGbReg::IntTypes t, bool now = false);
1597384Sgblack@eecs.umich.edu
1607384Sgblack@eecs.umich.edu    /** Check and see if changes to the mask register have caused an interrupt
1617384Sgblack@eecs.umich.edu     * to need to be sent or perhaps removed an interrupt cause.
1627384Sgblack@eecs.umich.edu     */
1637384Sgblack@eecs.umich.edu    void chkInterrupt();
1647384Sgblack@eecs.umich.edu
1657384Sgblack@eecs.umich.edu    /** Send an interrupt to the cpu
1667384Sgblack@eecs.umich.edu     */
1677384Sgblack@eecs.umich.edu    void delayIntEvent();
1687384Sgblack@eecs.umich.edu    void cpuPostInt();
1697384Sgblack@eecs.umich.edu    // Event to moderate interrupts
1707384Sgblack@eecs.umich.edu    EventWrapper<IGbE, &IGbE::delayIntEvent> interEvent;
1717384Sgblack@eecs.umich.edu
1727384Sgblack@eecs.umich.edu    /** Clear the interupt line to the cpu
1737384Sgblack@eecs.umich.edu     */
1747384Sgblack@eecs.umich.edu    void cpuClearInt();
1757384Sgblack@eecs.umich.edu
1767384Sgblack@eecs.umich.edu    Tick intClock() { return SimClock::Int::ns * 1024; }
1777384Sgblack@eecs.umich.edu
1787384Sgblack@eecs.umich.edu    /** This function is used to restart the clock so it can handle things like
1797384Sgblack@eecs.umich.edu     * draining and resume in one place. */
1807384Sgblack@eecs.umich.edu    void restartClock();
1817384Sgblack@eecs.umich.edu
1827384Sgblack@eecs.umich.edu    /** Check if all the draining things that need to occur have occured and
1837384Sgblack@eecs.umich.edu     * handle the drain event if so.
1847384Sgblack@eecs.umich.edu     */
1857384Sgblack@eecs.umich.edu    void checkDrain();
1867384Sgblack@eecs.umich.edu
1877384Sgblack@eecs.umich.edu    void anBegin(std::string sm, std::string st, int flags = CPA::FL_NONE) {
1887384Sgblack@eecs.umich.edu        cpa->hwBegin((CPA::flags)flags, sys, macAddr, sm, st);
1897384Sgblack@eecs.umich.edu    }
1907384Sgblack@eecs.umich.edu
1917384Sgblack@eecs.umich.edu    void anQ(std::string sm, std::string q) {
1927384Sgblack@eecs.umich.edu        cpa->hwQ(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
1937384Sgblack@eecs.umich.edu    }
1947384Sgblack@eecs.umich.edu
1957396Sgblack@eecs.umich.edu    void anDq(std::string sm, std::string q) {
1967396Sgblack@eecs.umich.edu        cpa->hwDq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
1977396Sgblack@eecs.umich.edu    }
1987396Sgblack@eecs.umich.edu
1997396Sgblack@eecs.umich.edu    void anPq(std::string sm, std::string q, int num = 1) {
2007396Sgblack@eecs.umich.edu        cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num);
2017396Sgblack@eecs.umich.edu    }
2027396Sgblack@eecs.umich.edu
2037396Sgblack@eecs.umich.edu    void anRq(std::string sm, std::string q, int num = 1) {
2047396Sgblack@eecs.umich.edu        cpa->hwRq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num);
2057396Sgblack@eecs.umich.edu    }
2067396Sgblack@eecs.umich.edu
2077396Sgblack@eecs.umich.edu    void anWe(std::string sm, std::string q) {
2087396Sgblack@eecs.umich.edu        cpa->hwWe(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
2097396Sgblack@eecs.umich.edu    }
2107396Sgblack@eecs.umich.edu
2117396Sgblack@eecs.umich.edu    void anWf(std::string sm, std::string q) {
2127396Sgblack@eecs.umich.edu        cpa->hwWf(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
2137396Sgblack@eecs.umich.edu    }
2147396Sgblack@eecs.umich.edu
2157396Sgblack@eecs.umich.edu
2167396Sgblack@eecs.umich.edu    template<class T>
2177396Sgblack@eecs.umich.edu    class DescCache
2187396Sgblack@eecs.umich.edu    {
2197396Sgblack@eecs.umich.edu      protected:
2207396Sgblack@eecs.umich.edu        virtual Addr descBase() const = 0;
2217396Sgblack@eecs.umich.edu        virtual long descHead() const = 0;
2227396Sgblack@eecs.umich.edu        virtual long descTail() const = 0;
2237396Sgblack@eecs.umich.edu        virtual long descLen() const = 0;
2247396Sgblack@eecs.umich.edu        virtual void updateHead(long h) = 0;
2257396Sgblack@eecs.umich.edu        virtual void enableSm() = 0;
2267396Sgblack@eecs.umich.edu        virtual void actionAfterWb() {}
2277396Sgblack@eecs.umich.edu        virtual void fetchAfterWb() = 0;
2287396Sgblack@eecs.umich.edu
2297396Sgblack@eecs.umich.edu        typedef std::deque<T *> CacheType;
2307396Sgblack@eecs.umich.edu        CacheType usedCache;
2317396Sgblack@eecs.umich.edu        CacheType unusedCache;
2327396Sgblack@eecs.umich.edu
2337396Sgblack@eecs.umich.edu        T *fetchBuf;
2347396Sgblack@eecs.umich.edu        T *wbBuf;
2357396Sgblack@eecs.umich.edu
2367396Sgblack@eecs.umich.edu        // Pointer to the device we cache for
2377396Sgblack@eecs.umich.edu        IGbE *igbe;
2387396Sgblack@eecs.umich.edu
2397396Sgblack@eecs.umich.edu        // Name of this  descriptor cache
2407396Sgblack@eecs.umich.edu        std::string _name;
2417396Sgblack@eecs.umich.edu
2427396Sgblack@eecs.umich.edu        // How far we've cached
2437384Sgblack@eecs.umich.edu        int cachePnt;
2447384Sgblack@eecs.umich.edu
2457386Sgblack@eecs.umich.edu        // The size of the descriptor cache
2467386Sgblack@eecs.umich.edu        int size;
2477386Sgblack@eecs.umich.edu
2487386Sgblack@eecs.umich.edu        // How many descriptors we are currently fetching
2497386Sgblack@eecs.umich.edu        int curFetching;
2507386Sgblack@eecs.umich.edu
2517386Sgblack@eecs.umich.edu        // How many descriptors we are currently writing back
2527386Sgblack@eecs.umich.edu        int wbOut;
2537386Sgblack@eecs.umich.edu
2547386Sgblack@eecs.umich.edu        // if the we wrote back to the end of the descriptor ring and are going
2557386Sgblack@eecs.umich.edu        // to have to wrap and write more
2567386Sgblack@eecs.umich.edu        bool moreToWb;
2577386Sgblack@eecs.umich.edu
2587386Sgblack@eecs.umich.edu        // What the alignment is of the next descriptor writeback
2597386Sgblack@eecs.umich.edu        Addr wbAlignment;
2607386Sgblack@eecs.umich.edu
2617386Sgblack@eecs.umich.edu        /** The packet that is currently being dmad to memory if any */
2627396Sgblack@eecs.umich.edu        EthPacketPtr pktPtr;
2637386Sgblack@eecs.umich.edu
2647386Sgblack@eecs.umich.edu        /** Shortcut for DMA address translation */
2657386Sgblack@eecs.umich.edu        Addr pciToDma(Addr a) { return igbe->platform->pciToDma(a); }
2667386Sgblack@eecs.umich.edu
2677386Sgblack@eecs.umich.edu      public:
2687386Sgblack@eecs.umich.edu        /** Annotate sm*/
2697386Sgblack@eecs.umich.edu        std::string annSmFetch, annSmWb, annUnusedDescQ, annUsedCacheQ,
2707385Sgblack@eecs.umich.edu            annUsedDescQ, annUnusedCacheQ, annDescQ;
2717384Sgblack@eecs.umich.edu
2727385Sgblack@eecs.umich.edu        DescCache(IGbE *i, const std::string n, int s);
2737385Sgblack@eecs.umich.edu        virtual ~DescCache();
2747385Sgblack@eecs.umich.edu
2757384Sgblack@eecs.umich.edu        std::string name() { return _name; }
2767384Sgblack@eecs.umich.edu
2777384Sgblack@eecs.umich.edu        /** If the address/len/head change when we've got descriptors that are
2787384Sgblack@eecs.umich.edu         * dirty that is very bad. This function checks that we don't and if we
2797384Sgblack@eecs.umich.edu         * do panics.
2807384Sgblack@eecs.umich.edu         */
2817384Sgblack@eecs.umich.edu        void areaChanged();
2827384Sgblack@eecs.umich.edu
2837384Sgblack@eecs.umich.edu        void writeback(Addr aMask);
2847384Sgblack@eecs.umich.edu        void writeback1();
2857384Sgblack@eecs.umich.edu        EventWrapper<DescCache, &DescCache::writeback1> wbDelayEvent;
2867384Sgblack@eecs.umich.edu
2877384Sgblack@eecs.umich.edu        /** Fetch a chunk of descriptors into the descriptor cache.
2887384Sgblack@eecs.umich.edu         * Calls fetchComplete when the memory system returns the data
2897384Sgblack@eecs.umich.edu         */
2907384Sgblack@eecs.umich.edu        void fetchDescriptors();
2917384Sgblack@eecs.umich.edu        void fetchDescriptors1();
2927385Sgblack@eecs.umich.edu        EventWrapper<DescCache, &DescCache::fetchDescriptors1> fetchDelayEvent;
2937385Sgblack@eecs.umich.edu
2947385Sgblack@eecs.umich.edu        /** Called by event when dma to read descriptors is completed
2957385Sgblack@eecs.umich.edu         */
2967396Sgblack@eecs.umich.edu        void fetchComplete();
2977385Sgblack@eecs.umich.edu        EventWrapper<DescCache, &DescCache::fetchComplete> fetchEvent;
2987384Sgblack@eecs.umich.edu
2997384Sgblack@eecs.umich.edu        /** Called by event when dma to writeback descriptors is completed
3007384Sgblack@eecs.umich.edu         */
3017384Sgblack@eecs.umich.edu        void wbComplete();
3027386Sgblack@eecs.umich.edu        EventWrapper<DescCache, &DescCache::wbComplete> wbEvent;
3037386Sgblack@eecs.umich.edu
3047386Sgblack@eecs.umich.edu        /* Return the number of descriptors left in the ring, so the device has
3057386Sgblack@eecs.umich.edu         * a way to figure out if it needs to interrupt.
3067386Sgblack@eecs.umich.edu         */
3077386Sgblack@eecs.umich.edu        unsigned
3087386Sgblack@eecs.umich.edu        descLeft() const
3097386Sgblack@eecs.umich.edu        {
3107386Sgblack@eecs.umich.edu            unsigned left = unusedCache.size();
3117386Sgblack@eecs.umich.edu            if (cachePnt > descTail())
3127386Sgblack@eecs.umich.edu                left += (descLen() - cachePnt + descTail());
3137386Sgblack@eecs.umich.edu            else
3147386Sgblack@eecs.umich.edu                left += (descTail() - cachePnt);
3157386Sgblack@eecs.umich.edu
3167386Sgblack@eecs.umich.edu            return left;
3177386Sgblack@eecs.umich.edu        }
3187386Sgblack@eecs.umich.edu
3197396Sgblack@eecs.umich.edu        /* Return the number of descriptors used and not written back.
3207386Sgblack@eecs.umich.edu         */
3217396Sgblack@eecs.umich.edu        unsigned descUsed() const { return usedCache.size(); }
3227396Sgblack@eecs.umich.edu
3237396Sgblack@eecs.umich.edu        /* Return the number of cache unused descriptors we have. */
3247396Sgblack@eecs.umich.edu        unsigned descUnused() const { return unusedCache.size(); }
3257386Sgblack@eecs.umich.edu
3267386Sgblack@eecs.umich.edu        /* Get into a state where the descriptor address/head/etc colud be
3277386Sgblack@eecs.umich.edu         * changed */
3287386Sgblack@eecs.umich.edu        void reset();
3297386Sgblack@eecs.umich.edu
3307386Sgblack@eecs.umich.edu        virtual void serialize(std::ostream &os);
3317386Sgblack@eecs.umich.edu        virtual void unserialize(Checkpoint *cp, const std::string &section);
3327386Sgblack@eecs.umich.edu
3337386Sgblack@eecs.umich.edu        virtual bool hasOutstandingEvents() {
3347386Sgblack@eecs.umich.edu            return wbEvent.scheduled() || fetchEvent.scheduled();
3357386Sgblack@eecs.umich.edu        }
3367386Sgblack@eecs.umich.edu
3377386Sgblack@eecs.umich.edu    };
3387386Sgblack@eecs.umich.edu
3397386Sgblack@eecs.umich.edu
3407386Sgblack@eecs.umich.edu    class RxDescCache : public DescCache<iGbReg::RxDesc>
3417386Sgblack@eecs.umich.edu    {
3427386Sgblack@eecs.umich.edu      protected:
3437386Sgblack@eecs.umich.edu        virtual Addr descBase() const { return igbe->regs.rdba(); }
3447396Sgblack@eecs.umich.edu        virtual long descHead() const { return igbe->regs.rdh(); }
3457396Sgblack@eecs.umich.edu        virtual long descLen() const { return igbe->regs.rdlen() >> 4; }
3467396Sgblack@eecs.umich.edu        virtual long descTail() const { return igbe->regs.rdt(); }
3477396Sgblack@eecs.umich.edu        virtual void updateHead(long h) { igbe->regs.rdh(h); }
3487386Sgblack@eecs.umich.edu        virtual void enableSm();
3497386Sgblack@eecs.umich.edu        virtual void fetchAfterWb() {
3507386Sgblack@eecs.umich.edu            if (!igbe->rxTick && igbe->getDrainState() == Drainable::Running)
3517386Sgblack@eecs.umich.edu                fetchDescriptors();
3527386Sgblack@eecs.umich.edu        }
3537386Sgblack@eecs.umich.edu
3547386Sgblack@eecs.umich.edu        bool pktDone;
3557396Sgblack@eecs.umich.edu
3567386Sgblack@eecs.umich.edu        /** Variable to head with header/data completion events */
3577396Sgblack@eecs.umich.edu        int splitCount;
3587396Sgblack@eecs.umich.edu
3597396Sgblack@eecs.umich.edu        /** Bytes of packet that have been copied, so we know when to
3607396Sgblack@eecs.umich.edu            set EOP */
3617386Sgblack@eecs.umich.edu        unsigned bytesCopied;
3627386Sgblack@eecs.umich.edu
3637386Sgblack@eecs.umich.edu      public:
3647386Sgblack@eecs.umich.edu        RxDescCache(IGbE *i, std::string n, int s);
3657386Sgblack@eecs.umich.edu
3667386Sgblack@eecs.umich.edu        /** Write the given packet into the buffer(s) pointed to by the
3677396Sgblack@eecs.umich.edu         * descriptor and update the book keeping. Should only be called when
3687396Sgblack@eecs.umich.edu         * there are no dma's pending.
3697396Sgblack@eecs.umich.edu         * @param packet ethernet packet to write
3707396Sgblack@eecs.umich.edu         * @param pkt_offset bytes already copied from the packet to memory
3717396Sgblack@eecs.umich.edu         * @return pkt_offset + number of bytes copied during this call
3727396Sgblack@eecs.umich.edu         */
3737396Sgblack@eecs.umich.edu        int writePacket(EthPacketPtr packet, int pkt_offset);
3747396Sgblack@eecs.umich.edu
3757396Sgblack@eecs.umich.edu        /** Called by event when dma to write packet is completed
3767396Sgblack@eecs.umich.edu         */
3777396Sgblack@eecs.umich.edu        void pktComplete();
3787396Sgblack@eecs.umich.edu
3797396Sgblack@eecs.umich.edu        /** Check if the dma on the packet has completed and RX state machine
3807396Sgblack@eecs.umich.edu         * can continue
3817396Sgblack@eecs.umich.edu         */
3827396Sgblack@eecs.umich.edu        bool packetDone();
3837396Sgblack@eecs.umich.edu
3847396Sgblack@eecs.umich.edu        EventWrapper<RxDescCache, &RxDescCache::pktComplete> pktEvent;
3857396Sgblack@eecs.umich.edu
3867396Sgblack@eecs.umich.edu        // Event to handle issuing header and data write at the same time
3877396Sgblack@eecs.umich.edu        // and only callking pktComplete() when both are completed
3887396Sgblack@eecs.umich.edu        void pktSplitDone();
3897396Sgblack@eecs.umich.edu        EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktHdrEvent;
3907396Sgblack@eecs.umich.edu        EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktDataEvent;
3917396Sgblack@eecs.umich.edu
3927396Sgblack@eecs.umich.edu        virtual bool hasOutstandingEvents();
3937396Sgblack@eecs.umich.edu
3947396Sgblack@eecs.umich.edu        virtual void serialize(std::ostream &os);
3957396Sgblack@eecs.umich.edu        virtual void unserialize(Checkpoint *cp, const std::string &section);
3967396Sgblack@eecs.umich.edu    };
3977396Sgblack@eecs.umich.edu    friend class RxDescCache;
3987396Sgblack@eecs.umich.edu
3997398Sgblack@eecs.umich.edu    RxDescCache rxDescCache;
4007398Sgblack@eecs.umich.edu
4017398Sgblack@eecs.umich.edu    class TxDescCache  : public DescCache<iGbReg::TxDesc>
4027398Sgblack@eecs.umich.edu    {
4037398Sgblack@eecs.umich.edu      protected:
4047398Sgblack@eecs.umich.edu        virtual Addr descBase() const { return igbe->regs.tdba(); }
4057398Sgblack@eecs.umich.edu        virtual long descHead() const { return igbe->regs.tdh(); }
4067398Sgblack@eecs.umich.edu        virtual long descTail() const { return igbe->regs.tdt(); }
4077398Sgblack@eecs.umich.edu        virtual long descLen() const { return igbe->regs.tdlen() >> 4; }
4087398Sgblack@eecs.umich.edu        virtual void updateHead(long h) { igbe->regs.tdh(h); }
4097398Sgblack@eecs.umich.edu        virtual void enableSm();
4107398Sgblack@eecs.umich.edu        virtual void actionAfterWb();
4117398Sgblack@eecs.umich.edu        virtual void fetchAfterWb() {
4127398Sgblack@eecs.umich.edu            if (!igbe->txTick && igbe->getDrainState() == Drainable::Running)
4137398Sgblack@eecs.umich.edu                fetchDescriptors();
4147398Sgblack@eecs.umich.edu        }
4157398Sgblack@eecs.umich.edu
4167398Sgblack@eecs.umich.edu
4177398Sgblack@eecs.umich.edu
4187398Sgblack@eecs.umich.edu        bool pktDone;
4197398Sgblack@eecs.umich.edu        bool isTcp;
4207398Sgblack@eecs.umich.edu        bool pktWaiting;
4217398Sgblack@eecs.umich.edu        bool pktMultiDesc;
4227398Sgblack@eecs.umich.edu        Addr completionAddress;
4237398Sgblack@eecs.umich.edu        bool completionEnabled;
4247398Sgblack@eecs.umich.edu        uint32_t descEnd;
4257398Sgblack@eecs.umich.edu
4267398Sgblack@eecs.umich.edu
4277398Sgblack@eecs.umich.edu        // tso variables
4287398Sgblack@eecs.umich.edu        bool useTso;
4297398Sgblack@eecs.umich.edu        Addr tsoHeaderLen;
4307398Sgblack@eecs.umich.edu        Addr tsoMss;
4317398Sgblack@eecs.umich.edu        Addr tsoTotalLen;
4327398Sgblack@eecs.umich.edu        Addr tsoUsedLen;
4337398Sgblack@eecs.umich.edu        Addr tsoPrevSeq;
4347398Sgblack@eecs.umich.edu        Addr tsoPktPayloadBytes;
4357398Sgblack@eecs.umich.edu        bool tsoLoadedHeader;
4367398Sgblack@eecs.umich.edu        bool tsoPktHasHeader;
4377398Sgblack@eecs.umich.edu        uint8_t tsoHeader[256];
4387398Sgblack@eecs.umich.edu        Addr tsoDescBytesUsed;
4397398Sgblack@eecs.umich.edu        Addr tsoCopyBytes;
4407398Sgblack@eecs.umich.edu        int tsoPkts;
4417398Sgblack@eecs.umich.edu
4427398Sgblack@eecs.umich.edu      public:
4437398Sgblack@eecs.umich.edu        TxDescCache(IGbE *i, std::string n, int s);
4447398Sgblack@eecs.umich.edu
4457398Sgblack@eecs.umich.edu        /** Tell the cache to DMA a packet from main memory into its buffer and
4467398Sgblack@eecs.umich.edu         * return the size the of the packet to reserve space in tx fifo.
4477398Sgblack@eecs.umich.edu         * @return size of the packet
4487398Sgblack@eecs.umich.edu         */
4497398Sgblack@eecs.umich.edu        unsigned getPacketSize(EthPacketPtr p);
4507398Sgblack@eecs.umich.edu        void getPacketData(EthPacketPtr p);
4517398Sgblack@eecs.umich.edu        void processContextDesc();
4527398Sgblack@eecs.umich.edu
4537398Sgblack@eecs.umich.edu        /** Return the number of dsecriptors in a cache block for threshold
4547398Sgblack@eecs.umich.edu         * operations.
4557398Sgblack@eecs.umich.edu         */
4567398Sgblack@eecs.umich.edu        unsigned
4577398Sgblack@eecs.umich.edu        descInBlock(unsigned num_desc)
4587398Sgblack@eecs.umich.edu        {
4597398Sgblack@eecs.umich.edu            return num_desc / igbe->cacheBlockSize() / sizeof(iGbReg::TxDesc);
4607398Sgblack@eecs.umich.edu        }
4617398Sgblack@eecs.umich.edu
4627398Sgblack@eecs.umich.edu        /** Ask if the packet has been transfered so the state machine can give
4637398Sgblack@eecs.umich.edu         * it to the fifo.
4647398Sgblack@eecs.umich.edu         * @return packet available in descriptor cache
4657398Sgblack@eecs.umich.edu         */
4667398Sgblack@eecs.umich.edu        bool packetAvailable();
4677398Sgblack@eecs.umich.edu
4687398Sgblack@eecs.umich.edu        /** Ask if we are still waiting for the packet to be transfered.
4697398Sgblack@eecs.umich.edu         * @return packet still in transit.
4707398Sgblack@eecs.umich.edu         */
4717398Sgblack@eecs.umich.edu        bool packetWaiting() { return pktWaiting; }
4727398Sgblack@eecs.umich.edu
4737398Sgblack@eecs.umich.edu        /** Ask if this packet is composed of multiple descriptors
4747398Sgblack@eecs.umich.edu         * so even if we've got data, we need to wait for more before
4757398Sgblack@eecs.umich.edu         * we can send it out.
4767398Sgblack@eecs.umich.edu         * @return packet can't be sent out because it's a multi-descriptor
4777398Sgblack@eecs.umich.edu         * packet
4787398Sgblack@eecs.umich.edu         */
4797398Sgblack@eecs.umich.edu        bool packetMultiDesc() { return pktMultiDesc;}
4807398Sgblack@eecs.umich.edu
4817398Sgblack@eecs.umich.edu        /** Called by event when dma to write packet is completed
4827398Sgblack@eecs.umich.edu         */
4837398Sgblack@eecs.umich.edu        void pktComplete();
4847398Sgblack@eecs.umich.edu        EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent;
4857398Sgblack@eecs.umich.edu
4867398Sgblack@eecs.umich.edu        void headerComplete();
4877398Sgblack@eecs.umich.edu        EventWrapper<TxDescCache, &TxDescCache::headerComplete> headerEvent;
4887398Sgblack@eecs.umich.edu
4897398Sgblack@eecs.umich.edu
4907398Sgblack@eecs.umich.edu        void completionWriteback(Addr a, bool enabled) {
4917398Sgblack@eecs.umich.edu            DPRINTF(EthernetDesc,
4927398Sgblack@eecs.umich.edu                    "Completion writeback Addr: %#x enabled: %d\n",
4937398Sgblack@eecs.umich.edu                    a, enabled);
4947398Sgblack@eecs.umich.edu            completionAddress = a;
4957398Sgblack@eecs.umich.edu            completionEnabled = enabled;
4967398Sgblack@eecs.umich.edu        }
4977398Sgblack@eecs.umich.edu
4987398Sgblack@eecs.umich.edu        virtual bool hasOutstandingEvents();
4997398Sgblack@eecs.umich.edu
5007398Sgblack@eecs.umich.edu        void nullCallback() {
5017398Sgblack@eecs.umich.edu            DPRINTF(EthernetDesc, "Completion writeback complete\n");
5027398Sgblack@eecs.umich.edu        }
5037398Sgblack@eecs.umich.edu        EventWrapper<TxDescCache, &TxDescCache::nullCallback> nullEvent;
5047398Sgblack@eecs.umich.edu
5057398Sgblack@eecs.umich.edu        virtual void serialize(std::ostream &os);
5067398Sgblack@eecs.umich.edu        virtual void unserialize(Checkpoint *cp, const std::string &section);
5077398Sgblack@eecs.umich.edu
5087398Sgblack@eecs.umich.edu    };
5097398Sgblack@eecs.umich.edu    friend class TxDescCache;
5107398Sgblack@eecs.umich.edu
5117398Sgblack@eecs.umich.edu    TxDescCache txDescCache;
5127398Sgblack@eecs.umich.edu
5137398Sgblack@eecs.umich.edu  public:
5147398Sgblack@eecs.umich.edu    typedef IGbEParams Params;
5157398Sgblack@eecs.umich.edu    const Params *
5167398Sgblack@eecs.umich.edu    params() const {
5177398Sgblack@eecs.umich.edu        return dynamic_cast<const Params *>(_params);
5187398Sgblack@eecs.umich.edu    }
5197398Sgblack@eecs.umich.edu
5207398Sgblack@eecs.umich.edu    IGbE(const Params *params);
5217398Sgblack@eecs.umich.edu    ~IGbE();
5227398Sgblack@eecs.umich.edu    virtual void init();
5237398Sgblack@eecs.umich.edu
5247398Sgblack@eecs.umich.edu    virtual EtherInt *getEthPort(const std::string &if_name, int idx);
5257398Sgblack@eecs.umich.edu
5267398Sgblack@eecs.umich.edu    Tick lastInterrupt;
5277398Sgblack@eecs.umich.edu
5287398Sgblack@eecs.umich.edu    virtual Tick read(PacketPtr pkt);
5297398Sgblack@eecs.umich.edu    virtual Tick write(PacketPtr pkt);
5307398Sgblack@eecs.umich.edu
5317398Sgblack@eecs.umich.edu    virtual Tick writeConfig(PacketPtr pkt);
5327398Sgblack@eecs.umich.edu
5337398Sgblack@eecs.umich.edu    bool ethRxPkt(EthPacketPtr packet);
5347398Sgblack@eecs.umich.edu    void ethTxDone();
5357398Sgblack@eecs.umich.edu
5367398Sgblack@eecs.umich.edu    virtual void serialize(std::ostream &os);
5377398Sgblack@eecs.umich.edu    virtual void unserialize(Checkpoint *cp, const std::string &section);
5387398Sgblack@eecs.umich.edu
5397398Sgblack@eecs.umich.edu    unsigned int drain(DrainManager *dm);
5407398Sgblack@eecs.umich.edu    void drainResume();
5417398Sgblack@eecs.umich.edu
5427398Sgblack@eecs.umich.edu};
5437398Sgblack@eecs.umich.edu
5447398Sgblack@eecs.umich.educlass IGbEInt : public EtherInt
5457398Sgblack@eecs.umich.edu{
5467398Sgblack@eecs.umich.edu  private:
5477398Sgblack@eecs.umich.edu    IGbE *dev;
5487398Sgblack@eecs.umich.edu
5497398Sgblack@eecs.umich.edu  public:
5507398Sgblack@eecs.umich.edu    IGbEInt(const std::string &name, IGbE *d)
5517398Sgblack@eecs.umich.edu        : EtherInt(name), dev(d)
5527398Sgblack@eecs.umich.edu    { }
5537398Sgblack@eecs.umich.edu
5547398Sgblack@eecs.umich.edu    virtual bool recvPacket(EthPacketPtr pkt) { return dev->ethRxPkt(pkt); }
5557398Sgblack@eecs.umich.edu    virtual void sendDone() { dev->ethTxDone(); }
5567398Sgblack@eecs.umich.edu};
5577398Sgblack@eecs.umich.edu
5587398Sgblack@eecs.umich.edu#endif //__DEV_I8254XGBE_HH__
5597398Sgblack@eecs.umich.edu