rename AlphaConsole to AlphaBackdoor
[gem5.git] / src / dev / i8254xGBe.hh
index b6da53b09ac8d9c30b0b55b75a828e02ab8f960d..0daf094c15e86e6dee15ed7a447106477cedf6e5 100644 (file)
 
 #include "base/inet.hh"
 #include "base/statistics.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 PciDev
+class IGbE : public EtherDevice
 {
   private:
     IGbEInt *etherInt;
@@ -145,9 +147,10 @@ class IGbE : public PciDev
 
     /** Send an interrupt to the cpu
      */
+    void delayIntEvent();
     void cpuPostInt();
     // Event to moderate interrupts
-    EventWrapper<IGbE, &IGbE::cpuPostInt> interEvent;
+    EventWrapper<IGbE, &IGbE::delayIntEvent> interEvent;
 
     /** Clear the interupt line to the cpu
      */
@@ -175,6 +178,7 @@ class IGbE : public PciDev
         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;
@@ -278,14 +282,12 @@ class IGbE : public PciDev
 
             wbOut = max_to_wb;
 
-            for (int x = 0; x < wbOut; x++)
-                memcpy(&wbBuf[x], usedCache[x], sizeof(T));
-
             for (int x = 0; x < wbOut; x++) {
                 assert(usedCache.size());
+                memcpy(&wbBuf[x], usedCache[0], sizeof(T));
                 delete usedCache[0];
                 usedCache.pop_front();
-            };
+            }
 
 
             assert(wbOut);
@@ -300,14 +302,17 @@ class IGbE : public PciDev
         {
             size_t max_to_fetch;
 
+            if (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, (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",
@@ -315,7 +320,7 @@ class IGbE : public PciDev
                     max_to_fetch, descLeft());
 
             // Nothing to do
-            if (max_to_fetch == 0 || curFetching)
+            if (max_to_fetch == 0)
                 return;
 
             // So we don't have two descriptor fetches going on at once
@@ -325,7 +330,6 @@ class IGbE : public PciDev
                     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);
@@ -367,6 +371,7 @@ class IGbE : public PciDev
          */
         void wbComplete()
         {
+
             long  curHead = descHead();
 #ifndef NDEBUG
             long oldHead = curHead;
@@ -385,12 +390,16 @@ class IGbE : public PciDev
                     oldHead, curHead);
 
             // If we still have more to wb, call wb now
+            intAfterWb();
             if (moreToWb) {
                 DPRINTF(EthernetDesc, "Writeback has more todo\n");
                 writeback(wbAlignment);
             }
-            intAfterWb();
-            igbe->checkDrain();
+
+            if (!wbOut) {
+                igbe->checkDrain();
+            }
+            fetchAfterWb();
         }
 
 
@@ -500,6 +509,10 @@ class IGbE : public PciDev
         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;
 
@@ -512,7 +525,7 @@ class IGbE : public PciDev
          * @param packet ethernet packet to write
          * @return if the packet could be written (there was a free descriptor)
          */
-        bool writePacket(EthPacketPtr packet);
+        void writePacket(EthPacketPtr packet);
         /** Called by event when dma to write packet is completed
          */
         void pktComplete();
@@ -542,11 +555,16 @@ class IGbE : public PciDev
         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 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);
@@ -569,6 +587,14 @@ class IGbE : public PciDev
          */
         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();
@@ -585,22 +611,19 @@ class IGbE : public PciDev
     TxDescCache txDescCache;
 
   public:
-    struct Params : public PciDev::Params
+    typedef IGbEParams Params;
+    const Params *
+    params() const
     {
-        Net::EthAddr hardware_address;
-        bool use_flow_control;
-        int rx_fifo_size;
-        int tx_fifo_size;
-        int rx_desc_cache_size;
-        int tx_desc_cache_size;
-        Tick clock;
-    };
+        return dynamic_cast<const Params *>(_params);
+    }
+    IGbE(const Params *params);
+    ~IGbE() {}
 
-    IGbE(Params *params);
-    ~IGbE() {;}
+    virtual EtherInt *getEthPort(const std::string &if_name, int idx);
 
     Tick clock;
-    inline Tick cycles(int numCycles) const { return numCycles * clock; }
+    inline Tick ticks(int numCycles) const { return numCycles * clock; }
 
     virtual Tick read(PacketPtr pkt);
     virtual Tick write(PacketPtr pkt);
@@ -610,11 +633,6 @@ class IGbE : public PciDev
     bool ethRxPkt(EthPacketPtr packet);
     void ethTxDone();
 
-    void setEthInt(IGbEInt *i) { assert(!etherInt); etherInt = i; }
-
-
-    const Params *params() const {return (const Params *)_params; }
-
     virtual void serialize(std::ostream &os);
     virtual void unserialize(Checkpoint *cp, const std::string &section);
     virtual unsigned int drain(Event *de);
@@ -630,7 +648,7 @@ class IGbEInt : public EtherInt
   public:
     IGbEInt(const std::string &name, IGbE *d)
         : EtherInt(name), dev(d)
-        { dev->setEthInt(this); }
+    { }
 
     virtual bool recvPacket(EthPacketPtr pkt) { return dev->ethRxPkt(pkt); }
     virtual void sendDone() { dev->ethTxDone(); }