make serialization at least seem to work
authorAli Saidi <saidi@eecs.umich.edu>
Fri, 30 Mar 2007 02:00:01 +0000 (22:00 -0400)
committerAli Saidi <saidi@eecs.umich.edu>
Fri, 30 Mar 2007 02:00:01 +0000 (22:00 -0400)
--HG--
extra : convert_revision : cbfdb64f9a204670b8dd0294c74a17044b9f330c

src/dev/i8254xGBe.cc
src/dev/i8254xGBe.hh
src/dev/i8254xGBe_defs.hh

index 60ea45a605f76eaa59ad35be1f83e1b47be689ce..3d08bca1e41c6199e4583f73f9d6f3d48e912980 100644 (file)
@@ -55,7 +55,7 @@ using namespace iGbReg;
 using namespace Net;
 
 IGbE::IGbE(Params *p)
-    : PciDev(p), etherInt(NULL),  useFlowControl(p->use_flow_control),
+    : PciDev(p), etherInt(NULL),  drainEvent(NULL), useFlowControl(p->use_flow_control),
       rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxTick(false),
       txTick(false), txFifoTick(false), rdtrEvent(this), radvEvent(this),
       tadvEvent(this), tidvEvent(this), tickEvent(this), interEvent(this),
@@ -762,6 +762,7 @@ IGbE::RxDescCache::pktComplete()
     pktPtr = NULL;
     enableSm();
     pktDone = true;
+    igbe->checkDrain();
 }
 
 void
@@ -781,11 +782,33 @@ IGbE::RxDescCache::packetDone()
     return false;
 }
 
+bool
+IGbE::RxDescCache::hasOutstandingEvents()
+{
+    return pktEvent.scheduled() || wbEvent.scheduled() ||
+        fetchEvent.scheduled();
+}
+
+void
+IGbE::RxDescCache::serialize(std::ostream &os)
+{
+    DescCache<RxDesc>::serialize(os);
+    SERIALIZE_SCALAR(pktDone);
+}
+
+void
+IGbE::RxDescCache::unserialize(Checkpoint *cp, const std::string &section)
+{
+    DescCache<RxDesc>::unserialize(cp, section);
+    UNSERIALIZE_SCALAR(pktDone);
+}
+
+
 ///////////////////////////////////// IGbE::TxDesc /////////////////////////////////
 
 IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s)
     : DescCache<TxDesc>(i,n, s), pktDone(false), isTcp(false), pktWaiting(false),
-      hLen(0), pktEvent(this)
+       pktEvent(this)
 
 {
 }
@@ -840,7 +863,7 @@ IGbE::TxDescCache::getPacketData(EthPacketPtr p)
 
     DPRINTF(EthernetDesc, "Starting DMA of packet\n");
     igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)),
-            TxdOp::getLen(desc), &pktEvent, p->data + hLen);
+            TxdOp::getLen(desc), &pktEvent, p->data + p->length);
 
 
 }
@@ -862,8 +885,9 @@ IGbE::TxDescCache::pktComplete()
     DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2);
 
     if (!TxdOp::eop(desc)) {
-        assert(hLen == 0);
-        hLen = TxdOp::getLen(desc);
+        // This only supports two descriptors per tx packet
+        assert(pktPtr->length == 0);
+        pktPtr->length = TxdOp::getLen(desc);
         unusedCache.pop_front();
         usedCache.push_back(desc);
         pktDone = true;
@@ -875,7 +899,7 @@ IGbE::TxDescCache::pktComplete()
     }
 
     // Set the length of the data in the EtherPacket
-    pktPtr->length = TxdOp::getLen(desc) + hLen;
+    pktPtr->length += TxdOp::getLen(desc);
 
     // no support for vlans
     assert(!TxdOp::vle(desc));
@@ -944,7 +968,6 @@ IGbE::TxDescCache::pktComplete()
     pktWaiting = false;
     pktPtr = NULL;
 
-    hLen = 0;
     DPRINTF(EthernetDesc, "Descriptor Done\n");
 
     if (igbe->regs.txdctl.wthresh() == 0) {
@@ -954,7 +977,25 @@ IGbE::TxDescCache::pktComplete()
         DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");
         writeback((igbe->cacheBlockSize()-1)>>4);
     }
+    igbe->checkDrain();
+}
 
+void
+IGbE::TxDescCache::serialize(std::ostream &os)
+{
+    DescCache<TxDesc>::serialize(os);
+    SERIALIZE_SCALAR(pktDone);
+    SERIALIZE_SCALAR(isTcp);
+    SERIALIZE_SCALAR(pktWaiting);
+}
+
+void
+IGbE::TxDescCache::unserialize(Checkpoint *cp, const std::string &section)
+{
+    DescCache<TxDesc>::unserialize(cp, section);
+    UNSERIALIZE_SCALAR(pktDone);
+    UNSERIALIZE_SCALAR(isTcp);
+    UNSERIALIZE_SCALAR(pktWaiting);
 }
 
 bool
@@ -974,7 +1015,12 @@ IGbE::TxDescCache::enableSm()
     igbe->restartClock();
 }
 
-
+bool
+IGbE::TxDescCache::hasOutstandingEvents()
+{
+    return pktEvent.scheduled() || wbEvent.scheduled() ||
+        fetchEvent.scheduled();
+}
 
 
 ///////////////////////////////////// IGbE /////////////////////////////////
@@ -982,10 +1028,61 @@ IGbE::TxDescCache::enableSm()
 void
 IGbE::restartClock()
 {
-    if (!tickEvent.scheduled() && (rxTick || txTick))
+    if (!tickEvent.scheduled() && (rxTick || txTick) && getState() ==
+            SimObject::Running)
         tickEvent.schedule((curTick/cycles(1)) * cycles(1) + cycles(1));
 }
 
+unsigned int
+IGbE::drain(Event *de)
+{
+    unsigned int count;
+    count = pioPort->drain(de) + dmaPort->drain(de);
+    if (rxDescCache.hasOutstandingEvents() ||
+            txDescCache.hasOutstandingEvents()) {
+        count++;
+        drainEvent = de;
+    }
+
+    txFifoTick = false;
+    txTick = false;
+    rxTick = false;
+
+    if (tickEvent.scheduled())
+        tickEvent.deschedule();
+
+    if (count)
+        changeState(Draining);
+    else
+        changeState(Drained);
+
+    return count;
+}
+
+void
+IGbE::resume()
+{
+    SimObject::resume();
+
+    txFifoTick = true;
+    txTick = true;
+    rxTick = true;
+
+    restartClock();
+}
+
+void
+IGbE::checkDrain()
+{
+    if (!drainEvent)
+        return;
+
+    if (rxDescCache.hasOutstandingEvents() ||
+            txDescCache.hasOutstandingEvents()) {
+        drainEvent->process();
+        drainEvent = NULL;
+    }
+}
 
 void
 IGbE::txStateMachine()
@@ -1179,7 +1276,7 @@ IGbE::txWire()
 
 
     if (etherInt->sendPacket(txFifo.front())) {
-        DPRINTF(Ethernet, "TxFIFO: Successful transmit, bytes in fifo: %d\n",
+        DPRINTF(EthernetSM, "TxFIFO: Successful transmit, bytes available in fifo: %d\n",
                 txFifo.avail());
         txFifo.pop();
     } else {
@@ -1218,19 +1315,112 @@ IGbE::ethTxDone()
     txTick = true;
 
     restartClock();
-    DPRINTF(Ethernet, "TxFIFO: Transmission complete\n");
+    DPRINTF(EthernetSM, "TxFIFO: Transmission complete\n");
 }
 
 void
 IGbE::serialize(std::ostream &os)
 {
-    panic("Need to implemenet\n");
+    PciDev::serialize(os);
+
+    regs.serialize(os);
+    SERIALIZE_SCALAR(eeOpBits);
+    SERIALIZE_SCALAR(eeAddrBits);
+    SERIALIZE_SCALAR(eeDataBits);
+    SERIALIZE_SCALAR(eeOpcode);
+    SERIALIZE_SCALAR(eeAddr);
+    SERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE);
+
+    rxFifo.serialize("rxfifo", os);
+    txFifo.serialize("txfifo", os);
+
+    bool txPktExists = txPacket;
+    SERIALIZE_SCALAR(txPktExists);
+    if (txPktExists)
+        txPacket->serialize("txpacket", os);
+
+    Tick rdtr_time = 0, radv_time = 0, tidv_time = 0, tadv_time = 0,
+         inter_time = 0;
+
+    if (rdtrEvent.scheduled())
+       rdtr_time = rdtrEvent.when();
+    SERIALIZE_SCALAR(rdtr_time);
+
+    if (radvEvent.scheduled())
+       radv_time = radvEvent.when();
+    SERIALIZE_SCALAR(radv_time);
+
+    if (tidvEvent.scheduled())
+       rdtr_time = tidvEvent.when();
+    SERIALIZE_SCALAR(tidv_time);
+
+    if (tadvEvent.scheduled())
+       rdtr_time = tadvEvent.when();
+    SERIALIZE_SCALAR(tadv_time);
+
+    if (interEvent.scheduled())
+       rdtr_time = interEvent.when();
+    SERIALIZE_SCALAR(inter_time);
+
+    nameOut(os, csprintf("%s.TxDescCache", name()));
+    txDescCache.serialize(os);
+
+    nameOut(os, csprintf("%s.RxDescCache", name()));
+    rxDescCache.serialize(os);
 }
 
 void
 IGbE::unserialize(Checkpoint *cp, const std::string &section)
 {
-    panic("Need to implemenet\n");
+    PciDev::unserialize(cp, section);
+
+    regs.unserialize(cp, section);
+    UNSERIALIZE_SCALAR(eeOpBits);
+    UNSERIALIZE_SCALAR(eeAddrBits);
+    UNSERIALIZE_SCALAR(eeDataBits);
+    UNSERIALIZE_SCALAR(eeOpcode);
+    UNSERIALIZE_SCALAR(eeAddr);
+    UNSERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE);
+
+    rxFifo.unserialize("rxfifo", cp, section);
+    txFifo.unserialize("txfifo", cp, section);
+
+    bool txPktExists;
+    UNSERIALIZE_SCALAR(txPktExists);
+    if (txPktExists) {
+        txPacket = new EthPacketData(16384);
+        txPacket->unserialize("txpacket", cp, section);
+    }
+
+    rxTick = true;
+    txTick = true;
+    txFifoTick = true;
+
+    Tick rdtr_time, radv_time, tidv_time, tadv_time, inter_time;
+    UNSERIALIZE_SCALAR(rdtr_time);
+    UNSERIALIZE_SCALAR(radv_time);
+    UNSERIALIZE_SCALAR(tidv_time);
+    UNSERIALIZE_SCALAR(tadv_time);
+    UNSERIALIZE_SCALAR(inter_time);
+
+    if (rdtr_time)
+        rdtrEvent.schedule(rdtr_time);
+
+    if (radv_time)
+        radvEvent.schedule(radv_time);
+
+    if (tidv_time)
+        tidvEvent.schedule(tidv_time);
+
+    if (tadv_time)
+        tadvEvent.schedule(tadv_time);
+
+    if (inter_time)
+        interEvent.schedule(inter_time);
+
+    txDescCache.unserialize(cp, csprintf("%s.TxDescCache", section));
+
+    rxDescCache.unserialize(cp, csprintf("%s.RxDescCache", section));
 }
 
 
index 3304f0862a57f3a00166b0926243563b486f71cc..2dec3b08ceded70b17d47ce2ed7f11460b9a9920 100644 (file)
@@ -62,8 +62,10 @@ class IGbE : public PciDev
     uint8_t eeOpcode, eeAddr;
     uint16_t flash[iGbReg::EEPROM_SIZE];
 
+    // The drain event if we have one
+    Event *drainEvent;
+
     // cached parameters from params struct
-    Tick tickRate;
     bool useFlowControl;
 
     // packet fifos
@@ -151,8 +153,15 @@ class IGbE : public PciDev
 
     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
     {
@@ -347,7 +356,7 @@ class IGbE : public PciDev
                     oldCp, cachePnt);
 
             enableSm();
-
+            igbe->checkDrain();
         }
 
         EventWrapper<DescCache, &DescCache::fetchComplete> fetchEvent;
@@ -379,6 +388,7 @@ class IGbE : public PciDev
                 writeback(wbAlignment);
             }
             intAfterWb();
+            igbe->checkDrain();
         }
 
 
@@ -422,6 +432,60 @@ class IGbE : public PciDev
 
         }
 
+        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));
+            }
+        }
+
+        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);
+            }
+        }
+        virtual bool hasOutstandingEvents() {
+            return wbEvent.scheduled() || fetchEvent.scheduled();
+        }
+
      };
 
 
@@ -458,6 +522,10 @@ class IGbE : public PciDev
 
         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;
 
@@ -477,7 +545,6 @@ class IGbE : public PciDev
         bool pktDone;
         bool isTcp;
         bool pktWaiting;
-        int hLen;
 
       public:
         TxDescCache(IGbE *i, std::string n, int s);
@@ -505,6 +572,11 @@ class IGbE : public PciDev
         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;
 
@@ -543,7 +615,8 @@ class IGbE : public PciDev
 
     virtual void serialize(std::ostream &os);
     virtual void unserialize(Checkpoint *cp, const std::string &section);
-
+    virtual unsigned int drain(Event *de);
+    virtual void resume();
 
 };
 
index 6820b96c4b3c0ca4bcbd3ca268f4ff75b1c6f6d4..91b3eacc9d8e92d8b40705a1f1dddd89fb03713d 100644 (file)
@@ -220,6 +220,14 @@ struct Regs {
         bool operator==(T d) { return d == _data; }
         void operator()(T d) { _data = d; }
         Reg() { _data = 0; }
+        void serialize(std::ostream &os)
+        {
+            SERIALIZE_SCALAR(_data);
+        }
+        void unserialize(Checkpoint *cp, const std::string &section)
+        {
+            UNSERIALIZE_SCALAR(_data);
+        }
     };
 
     struct CTRL : public Reg<uint32_t> { // 0x0000 CTRL Register
@@ -595,6 +603,79 @@ struct Regs {
         ADD_FIELD32(smbclkout,30,1); // smb clock out
     };
     MANC manc;
-};
 
-}; // iGbReg namespace
+    void serialize(std::ostream &os)
+    {
+        paramOut(os, "ctrl", ctrl._data);
+        paramOut(os, "sts", sts._data);
+        paramOut(os, "eecd", eecd._data);
+        paramOut(os, "eerd", eerd._data);
+        paramOut(os, "ctrl_ext", ctrl_ext._data);
+        paramOut(os, "mdic", mdic._data);
+        paramOut(os, "icr", icr._data);
+        SERIALIZE_SCALAR(imr);
+        paramOut(os, "itr", itr._data);
+        SERIALIZE_SCALAR(iam);
+        paramOut(os, "rctl", rctl._data);
+        paramOut(os, "fcttv", fcttv._data);
+        paramOut(os, "tctl", tctl._data);
+        paramOut(os, "pba", pba._data);
+        paramOut(os, "fcrtl", fcrtl._data);
+        paramOut(os, "fcrth", fcrth._data);
+        paramOut(os, "rdba", rdba._data);
+        paramOut(os, "rdlen", rdlen._data);
+        paramOut(os, "rdh", rdh._data);
+        paramOut(os, "rdt", rdt._data);
+        paramOut(os, "rdtr", rdtr._data);
+        paramOut(os, "rxdctl", rxdctl._data);
+        paramOut(os, "radv", radv._data);
+        paramOut(os, "rsrpd", rsrpd._data);
+        paramOut(os, "tdba", tdba._data);
+        paramOut(os, "tdlen", tdlen._data);
+        paramOut(os, "tdh", tdh._data);
+        paramOut(os, "tdt", tdt._data);
+        paramOut(os, "tidv", tidv._data);
+        paramOut(os, "txdctl", txdctl._data);
+        paramOut(os, "tadv", tadv._data);
+        paramOut(os, "rxcsum", rxcsum._data);
+        paramOut(os, "manc", manc._data);
+    }
+
+    void unserialize(Checkpoint *cp, const std::string &section)
+    {
+        paramIn(cp, section, "ctrl", ctrl._data);
+        paramIn(cp, section, "sts", sts._data);
+        paramIn(cp, section, "eecd", eecd._data);
+        paramIn(cp, section, "eerd", eerd._data);
+        paramIn(cp, section, "ctrl_ext", ctrl_ext._data);
+        paramIn(cp, section, "mdic", mdic._data);
+        paramIn(cp, section, "icr", icr._data);
+        UNSERIALIZE_SCALAR(imr);
+        paramIn(cp, section, "itr", itr._data);
+        UNSERIALIZE_SCALAR(iam);
+        paramIn(cp, section, "rctl", rctl._data);
+        paramIn(cp, section, "fcttv", fcttv._data);
+        paramIn(cp, section, "tctl", tctl._data);
+        paramIn(cp, section, "pba", pba._data);
+        paramIn(cp, section, "fcrtl", fcrtl._data);
+        paramIn(cp, section, "fcrth", fcrth._data);
+        paramIn(cp, section, "rdba", rdba._data);
+        paramIn(cp, section, "rdlen", rdlen._data);
+        paramIn(cp, section, "rdh", rdh._data);
+        paramIn(cp, section, "rdt", rdt._data);
+        paramIn(cp, section, "rdtr", rdtr._data);
+        paramIn(cp, section, "rxdctl", rxdctl._data);
+        paramIn(cp, section, "radv", radv._data);
+        paramIn(cp, section, "rsrpd", rsrpd._data);
+        paramIn(cp, section, "tdba", tdba._data);
+        paramIn(cp, section, "tdlen", tdlen._data);
+        paramIn(cp, section, "tdh", tdh._data);
+        paramIn(cp, section, "tdt", tdt._data);
+        paramIn(cp, section, "tidv", tidv._data);
+        paramIn(cp, section, "txdctl", txdctl._data);
+        paramIn(cp, section, "tadv", tadv._data);
+        paramIn(cp, section, "rxcsum", rxcsum._data);
+        paramIn(cp, section, "manc", manc._data);
+    }
+};
+} // iGbReg namespace