/*
 * Copyright (c) 2006 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: Ali Saidi
 */

/* @file
 * Device model for Intel's 8254x line of gigabit ethernet controllers.
 */

#ifndef __DEV_I8254XGBE_HH__
#define __DEV_I8254XGBE_HH__

#include <deque>
#include <string>

#include "base/inet.hh"
#include "dev/etherdevice.hh"
#include "dev/etherint.hh"
#include "dev/etherpkt.hh"
#include "dev/i8254xGBe_defs.hh"
#include "dev/pcidev.hh"
#include "dev/pktfifo.hh"
#include "params/IGbE.hh"
#include "sim/eventq.hh"

class IGbEInt;

class IGbE : public EtherDevice
{
  private:
    IGbEInt *etherInt;

    // device registers
    iGbReg::Regs regs;

    // eeprom data, status and control bits
    int eeOpBits, eeAddrBits, eeDataBits;
    uint8_t eeOpcode, eeAddr;
    uint16_t flash[iGbReg::EEPROM_SIZE];

    // The drain event if we have one
    Event *drainEvent;

    // cached parameters from params struct
    bool useFlowControl;

    // packet fifos
    PacketFifo rxFifo;
    PacketFifo txFifo;

    // Packet that we are currently putting into the txFifo
    EthPacketPtr txPacket;

    // Should to Rx/Tx State machine tick?
    bool rxTick;
    bool txTick;
    bool txFifoTick;

    bool rxDmaPacket;

    // Delays in managaging descriptors
    Tick fetchDelay, wbDelay;
    Tick fetchCompDelay, wbCompDelay;
    Tick rxWriteDelay, txReadDelay;

    // Event and function to deal with RDTR timer expiring
    void rdtrProcess() {
        rxDescCache.writeback(0);
        DPRINTF(EthernetIntr, "Posting RXT interrupt because RDTR timer expired\n");
        postInterrupt(iGbReg::IT_RXT);
    }

    //friend class EventWrapper<IGbE, &IGbE::rdtrProcess>;
    EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent;

    // Event and function to deal with RADV timer expiring
    void radvProcess() {
        rxDescCache.writeback(0);
        DPRINTF(EthernetIntr, "Posting RXT interrupt because RADV timer expired\n");
        postInterrupt(iGbReg::IT_RXT);
    }

    //friend class EventWrapper<IGbE, &IGbE::radvProcess>;
    EventWrapper<IGbE, &IGbE::radvProcess> radvEvent;

    // Event and function to deal with TADV timer expiring
    void tadvProcess() {
        txDescCache.writeback(0);
        DPRINTF(EthernetIntr, "Posting TXDW interrupt because TADV timer expired\n");
        postInterrupt(iGbReg::IT_TXDW);
    }

    //friend class EventWrapper<IGbE, &IGbE::tadvProcess>;
    EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent;

    // Event and function to deal with TIDV timer expiring
    void tidvProcess() {
        txDescCache.writeback(0);
        DPRINTF(EthernetIntr, "Posting TXDW interrupt because TIDV timer expired\n");
        postInterrupt(iGbReg::IT_TXDW);
    }
    //friend class EventWrapper<IGbE, &IGbE::tidvProcess>;
    EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent;

    // Main event to tick the device
    void tick();
    //friend class EventWrapper<IGbE, &IGbE::tick>;
    EventWrapper<IGbE, &IGbE::tick> tickEvent;


    uint64_t macAddr;

    void rxStateMachine();
    void txStateMachine();
    void txWire();

    /** Write an interrupt into the interrupt pending register and check mask
     * and interrupt limit timer before sending interrupt to CPU
     * @param t the type of interrupt we are posting
     * @param now should we ignore the interrupt limiting timer
     */
    void postInterrupt(iGbReg::IntTypes t, bool now = false);

    /** Check and see if changes to the mask register have caused an interrupt
     * to need to be sent or perhaps removed an interrupt cause.
     */
    void chkInterrupt();

    /** Send an interrupt to the cpu
     */
    void delayIntEvent();
    void cpuPostInt();
    // Event to moderate interrupts
    EventWrapper<IGbE, &IGbE::delayIntEvent> interEvent;

    /** Clear the interupt line to the cpu
     */
    void cpuClearInt();

    Tick intClock() { return Clock::Int::ns * 1024; }

    /** This function is used to restart the clock so it can handle things like
     * draining and resume in one place. */
    void restartClock();

    /** Check if all the draining things that need to occur have occured and
     * handle the drain event if so.
     */
    void checkDrain();

    template<class T>
    class DescCache
    {
      protected:
        virtual Addr descBase() const = 0;
        virtual long descHead() const = 0;
        virtual long descTail() const = 0;
        virtual long descLen() const = 0;
        virtual void updateHead(long h) = 0;
        virtual void enableSm() = 0;
        virtual void intAfterWb() const {}
        virtual void fetchAfterWb() = 0;

        std::deque<T*> usedCache;
        std::deque<T*> unusedCache;

        T *fetchBuf;
        T *wbBuf;

        // Pointer to the device we cache for
        IGbE *igbe;

        // Name of this  descriptor cache
        std::string _name;

        // How far we've cached
        int cachePnt;

        // The size of the descriptor cache
        int size;

        // How many descriptors we are currently fetching
        int curFetching;

        // How many descriptors we are currently writing back
        int wbOut;

        // if the we wrote back to the end of the descriptor ring and are going
        // to have to wrap and write more
        bool moreToWb;

        // What the alignment is of the next descriptor writeback
        Addr wbAlignment;

       /** The packet that is currently being dmad to memory if any
         */
        EthPacketPtr pktPtr;

      public:
        DescCache(IGbE *i, const std::string n, int s)
            : igbe(i), _name(n), cachePnt(0), size(s), curFetching(0), wbOut(0),
              pktPtr(NULL), wbDelayEvent(this), fetchDelayEvent(this), 
              fetchEvent(this), wbEvent(this)
        {
            fetchBuf = new T[size];
            wbBuf = new T[size];
        }

        virtual ~DescCache()
        {
            reset();
        }

        std::string name() { return _name; }

        /** If the address/len/head change when we've got descriptors that are
         * dirty that is very bad. This function checks that we don't and if we
         * do panics.
         */
        void areaChanged()
        {
            if (usedCache.size() > 0 || curFetching || wbOut)
                panic("Descriptor Address, Length or Head changed. Bad\n");
            reset();

        }

        void writeback(Addr aMask)
        {
            int curHead = descHead();
            int max_to_wb = usedCache.size();

            // Check if this writeback is less restrictive that the previous
            // and if so setup another one immediately following it
            if (wbOut) {
                if (aMask < wbAlignment) {
                    moreToWb = true;
                    wbAlignment = aMask;
                }
                DPRINTF(EthernetDesc, "Writing back already in process, returning\n");
                return;
            }

            moreToWb = false;
            wbAlignment = aMask;
   

            DPRINTF(EthernetDesc, "Writing back descriptors head: %d tail: "
                    "%d len: %d cachePnt: %d max_to_wb: %d descleft: %d\n",
                    curHead, descTail(), descLen(), cachePnt, max_to_wb,
                    descLeft());

            if (max_to_wb + curHead >= descLen()) {
                max_to_wb = descLen() - curHead;
                moreToWb = true;
                // this is by definition aligned correctly
            } else if (wbAlignment != 0) {
                // align the wb point to the mask
                max_to_wb = max_to_wb & ~wbAlignment;
            }

            DPRINTF(EthernetDesc, "Writing back %d descriptors\n", max_to_wb);

            if (max_to_wb <= 0) {
                return;
            }

            wbOut = max_to_wb;

            assert(!wbDelayEvent.scheduled()); 
            wbDelayEvent.schedule(igbe->wbDelay + curTick);
        }
            
        void writeback1()
        {
            // If we're draining delay issuing this DMA
            if (igbe->drainEvent) {
                wbDelayEvent.schedule(igbe->wbDelay + curTick);
                return;
            }

            DPRINTF(EthernetDesc, "Beining DMA of %d descriptors\n", wbOut);
            
            for (int x = 0; x < wbOut; x++) {
                assert(usedCache.size());
                memcpy(&wbBuf[x], usedCache[x], sizeof(T));
                 //delete usedCache[0];
                //usedCache.pop_front();
            }

            assert(wbOut);
            igbe->dmaWrite(igbe->platform->pciToDma(descBase() + descHead() * sizeof(T)),
                    wbOut * sizeof(T), &wbEvent, (uint8_t*)wbBuf,
                    igbe->wbCompDelay);
        }
        EventWrapper<DescCache, &DescCache::writeback1> wbDelayEvent;

        /** Fetch a chunk of descriptors into the descriptor cache.
         * Calls fetchComplete when the memory system returns the data
         */

        void fetchDescriptors()
        {
            size_t max_to_fetch;

            if (curFetching) {
                DPRINTF(EthernetDesc, "Currently fetching %d descriptors, returning\n", curFetching);
                return;
            }

            if (descTail() >= cachePnt)
                max_to_fetch = descTail() - cachePnt;
            else
                max_to_fetch = descLen() - cachePnt;

            size_t free_cache = size - usedCache.size() - unusedCache.size();

            max_to_fetch = std::min(max_to_fetch, free_cache);
            

            DPRINTF(EthernetDesc, "Fetching descriptors head: %d tail: "
                    "%d len: %d cachePnt: %d max_to_fetch: %d descleft: %d\n",
                    descHead(), descTail(), descLen(), cachePnt,
                    max_to_fetch, descLeft());

            // Nothing to do
            if (max_to_fetch == 0)
                return;
            
            // So we don't have two descriptor fetches going on at once
            curFetching = max_to_fetch;

            assert(!fetchDelayEvent.scheduled());
            fetchDelayEvent.schedule(igbe->fetchDelay + curTick);
        }

        void fetchDescriptors1()
        {
            // If we're draining delay issuing this DMA
            if (igbe->drainEvent) {
                fetchDelayEvent.schedule(igbe->fetchDelay + curTick);
                return;
            }

            DPRINTF(EthernetDesc, "Fetching descriptors at %#x (%#x), size: %#x\n",
                    descBase() + cachePnt * sizeof(T),
                    igbe->platform->pciToDma(descBase() + cachePnt * sizeof(T)),
                    curFetching * sizeof(T));
            assert(curFetching);
            igbe->dmaRead(igbe->platform->pciToDma(descBase() + cachePnt * sizeof(T)),
                    curFetching * sizeof(T), &fetchEvent, (uint8_t*)fetchBuf,
                    igbe->fetchCompDelay);
        }

        EventWrapper<DescCache, &DescCache::fetchDescriptors1> fetchDelayEvent;

        /** Called by event when dma to read descriptors is completed
         */
        void fetchComplete()
        {
            T *newDesc;
            for (int x = 0; x < curFetching; x++) {
                newDesc = new T;
                memcpy(newDesc, &fetchBuf[x], sizeof(T));
                unusedCache.push_back(newDesc);
            }


#ifndef NDEBUG
            int oldCp = cachePnt;
#endif

            cachePnt += curFetching;
            assert(cachePnt <= descLen());
            if (cachePnt == descLen())
                cachePnt = 0;

            curFetching = 0;

            DPRINTF(EthernetDesc, "Fetching complete cachePnt %d -> %d\n",
                    oldCp, cachePnt);

            enableSm();
            igbe->checkDrain();
        }

        EventWrapper<DescCache, &DescCache::fetchComplete> fetchEvent;

        /** Called by event when dma to writeback descriptors is completed
         */
        void wbComplete()
        {

            long  curHead = descHead();
#ifndef NDEBUG
            long oldHead = curHead;
#endif
            
            for (int x = 0; x < wbOut; x++) {
                assert(usedCache.size());
                delete usedCache[0];
                usedCache.pop_front();
            }

            curHead += wbOut;
            wbOut = 0;

            if (curHead >= descLen())
                curHead -= descLen();

            // Update the head
            updateHead(curHead);

            DPRINTF(EthernetDesc, "Writeback complete curHead %d -> %d\n",
                    oldHead, curHead);

            // If we still have more to wb, call wb now
            intAfterWb();
            if (moreToWb) {
                moreToWb = false;
                DPRINTF(EthernetDesc, "Writeback has more todo\n");
                writeback(wbAlignment);
            }

            if (!wbOut) {
                igbe->checkDrain();
            }
            fetchAfterWb();
        }


        EventWrapper<DescCache, &DescCache::wbComplete> wbEvent;

        /* Return the number of descriptors left in the ring, so the device has
         * a way to figure out if it needs to interrupt.
         */
        int descLeft() const
        {
            int left = unusedCache.size();
            if (cachePnt - descTail() >= 0)
                left += (cachePnt - descTail());
            else
                left += (descTail() - cachePnt);

            return left;
        }

        /* Return the number of descriptors used and not written back.
         */
        int descUsed() const { return usedCache.size(); }

        /* Return the number of cache unused descriptors we have. */
        int descUnused() const {return unusedCache.size(); }

        /* Get into a state where the descriptor address/head/etc colud be
         * changed */
        void reset()
        {
            DPRINTF(EthernetDesc, "Reseting descriptor cache\n");
            for (int x = 0; x < usedCache.size(); x++)
                delete usedCache[x];
            for (int x = 0; x < unusedCache.size(); x++)
                delete unusedCache[x];

            usedCache.clear();
            unusedCache.clear();

            cachePnt = 0;

        }

        virtual void serialize(std::ostream &os)
        {
            SERIALIZE_SCALAR(cachePnt);
            SERIALIZE_SCALAR(curFetching);
            SERIALIZE_SCALAR(wbOut);
            SERIALIZE_SCALAR(moreToWb);
            SERIALIZE_SCALAR(wbAlignment);

            int usedCacheSize = usedCache.size();
            SERIALIZE_SCALAR(usedCacheSize);
            for(int x = 0; x < usedCacheSize; x++) {
                arrayParamOut(os, csprintf("usedCache_%d", x),
                        (uint8_t*)usedCache[x],sizeof(T));
            }

            int unusedCacheSize = unusedCache.size();
            SERIALIZE_SCALAR(unusedCacheSize);
            for(int x = 0; x < unusedCacheSize; x++) {
                arrayParamOut(os, csprintf("unusedCache_%d", x),
                        (uint8_t*)unusedCache[x],sizeof(T));
            }

            Tick fetch_delay = 0, wb_delay = 0;
            if (fetchDelayEvent.scheduled())
                fetch_delay = fetchDelayEvent.when();
            SERIALIZE_SCALAR(fetch_delay);
            if (wbDelayEvent.scheduled())
                wb_delay = wbDelayEvent.when();
            SERIALIZE_SCALAR(wb_delay);


        }

        virtual void unserialize(Checkpoint *cp, const std::string &section)
        {
            UNSERIALIZE_SCALAR(cachePnt);
            UNSERIALIZE_SCALAR(curFetching);
            UNSERIALIZE_SCALAR(wbOut);
            UNSERIALIZE_SCALAR(moreToWb);
            UNSERIALIZE_SCALAR(wbAlignment);

            int usedCacheSize;
            UNSERIALIZE_SCALAR(usedCacheSize);
            T *temp;
            for(int x = 0; x < usedCacheSize; x++) {
                temp = new T;
                arrayParamIn(cp, section, csprintf("usedCache_%d", x),
                        (uint8_t*)temp,sizeof(T));
                usedCache.push_back(temp);
            }

            int unusedCacheSize;
            UNSERIALIZE_SCALAR(unusedCacheSize);
            for(int x = 0; x < unusedCacheSize; x++) {
                temp = new T;
                arrayParamIn(cp, section, csprintf("unusedCache_%d", x),
                        (uint8_t*)temp,sizeof(T));
                unusedCache.push_back(temp);
            }
            Tick fetch_delay = 0, wb_delay = 0;
            UNSERIALIZE_SCALAR(fetch_delay);
            UNSERIALIZE_SCALAR(wb_delay);
            if (fetch_delay)
                fetchDelayEvent.schedule(fetch_delay);
            if (wb_delay)
                wbDelayEvent.schedule(wb_delay);


        }
        virtual bool hasOutstandingEvents() {
            return wbEvent.scheduled() || fetchEvent.scheduled();
        }

     };


    class RxDescCache : public DescCache<iGbReg::RxDesc>
    {
      protected:
        virtual Addr descBase() const { return igbe->regs.rdba(); }
        virtual long descHead() const { return igbe->regs.rdh(); }
        virtual long descLen() const { return igbe->regs.rdlen() >> 4; }
        virtual long descTail() const { return igbe->regs.rdt(); }
        virtual void updateHead(long h) { igbe->regs.rdh(h); }
        virtual void enableSm();
        virtual void fetchAfterWb() {
            if (!igbe->rxTick && igbe->getState() == SimObject::Running)
                fetchDescriptors();
        }

        bool pktDone;

      public:
        RxDescCache(IGbE *i, std::string n, int s);

        /** Write the given packet into the buffer(s) pointed to by the
         * descriptor and update the book keeping. Should only be called when
         * there are no dma's pending.
         * @param packet ethernet packet to write
         * @return if the packet could be written (there was a free descriptor)
         */
        void writePacket(EthPacketPtr packet);
        /** Called by event when dma to write packet is completed
         */
        void pktComplete();

        /** Check if the dma on the packet has completed.
         */

        bool packetDone();

        EventWrapper<RxDescCache, &RxDescCache::pktComplete> pktEvent;

        virtual bool hasOutstandingEvents();

        virtual void serialize(std::ostream &os);
        virtual void unserialize(Checkpoint *cp, const std::string &section);
    };
    friend class RxDescCache;

    RxDescCache rxDescCache;

    class TxDescCache  : public DescCache<iGbReg::TxDesc>
    {
      protected:
        virtual Addr descBase() const { return igbe->regs.tdba(); }
        virtual long descHead() const { return igbe->regs.tdh(); }
        virtual long descTail() const { return igbe->regs.tdt(); }
        virtual long descLen() const { return igbe->regs.tdlen() >> 4; }
        virtual void updateHead(long h) { igbe->regs.tdh(h); }
        virtual void enableSm();
        virtual void intAfterWb() const { igbe->postInterrupt(iGbReg::IT_TXDW); }
        virtual void fetchAfterWb() {
            if (!igbe->txTick && igbe->getState() == SimObject::Running)
                fetchDescriptors();
        }

        bool pktDone;
        bool isTcp;
        bool pktWaiting;
        bool pktMultiDesc;

      public:
        TxDescCache(IGbE *i, std::string n, int s);

        /** Tell the cache to DMA a packet from main memory into its buffer and
         * return the size the of the packet to reserve space in tx fifo.
         * @return size of the packet
         */
        int getPacketSize();
        void getPacketData(EthPacketPtr p);

        /** Ask if the packet has been transfered so the state machine can give
         * it to the fifo.
         * @return packet available in descriptor cache
         */
        bool packetAvailable();

        /** Ask if we are still waiting for the packet to be transfered.
         * @return packet still in transit.
         */
        bool packetWaiting() { return pktWaiting; }

        /** Ask if this packet is composed of multiple descriptors
         * so even if we've got data, we need to wait for more before
         * we can send it out.
         * @return packet can't be sent out because it's a multi-descriptor
         * packet
         */
        bool packetMultiDesc() { return pktMultiDesc;}

        /** Called by event when dma to write packet is completed
         */
        void pktComplete();
        EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent;

        virtual bool hasOutstandingEvents();

        virtual void serialize(std::ostream &os);
        virtual void unserialize(Checkpoint *cp, const std::string &section);

    };
    friend class TxDescCache;

    TxDescCache txDescCache;

  public:
    typedef IGbEParams Params;
    const Params *
    params() const
    {
        return dynamic_cast<const Params *>(_params);
    }
    IGbE(const Params *params);
    ~IGbE() {}

    virtual EtherInt *getEthPort(const std::string &if_name, int idx);

    Tick clock;
    Tick lastInterrupt;
    inline Tick ticks(int numCycles) const { return numCycles * clock; }

    virtual Tick read(PacketPtr pkt);
    virtual Tick write(PacketPtr pkt);

    virtual Tick writeConfig(PacketPtr pkt);

    bool ethRxPkt(EthPacketPtr packet);
    void ethTxDone();

    virtual void serialize(std::ostream &os);
    virtual void unserialize(Checkpoint *cp, const std::string &section);
    virtual unsigned int drain(Event *de);
    virtual void resume();

};

class IGbEInt : public EtherInt
{
  private:
    IGbE *dev;

  public:
    IGbEInt(const std::string &name, IGbE *d)
        : EtherInt(name), dev(d)
    { }

    virtual bool recvPacket(EthPacketPtr pkt) { return dev->ethRxPkt(pkt); }
    virtual void sendDone() { dev->ethTxDone(); }
};





#endif //__DEV_I8254XGBE_HH__

