diff options
Diffstat (limited to 'src/dev')
-rw-r--r-- | src/dev/i8254xGBe.cc | 216 | ||||
-rw-r--r-- | src/dev/i8254xGBe.hh | 81 | ||||
-rw-r--r-- | src/dev/i8254xGBe_defs.hh | 85 |
3 files changed, 363 insertions, 19 deletions
diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 60ea45a60..3d08bca1e 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -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 §ion) +{ + 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 §ion) +{ + 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 §ion) { - 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)); } diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh index 3304f0862..2dec3b08c 100644 --- a/src/dev/i8254xGBe.hh +++ b/src/dev/i8254xGBe.hh @@ -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 §ion) + { + 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 §ion); }; 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 §ion); + }; 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 §ion); - + virtual unsigned int drain(Event *de); + virtual void resume(); }; diff --git a/src/dev/i8254xGBe_defs.hh b/src/dev/i8254xGBe_defs.hh index 6820b96c4..91b3eacc9 100644 --- a/src/dev/i8254xGBe_defs.hh +++ b/src/dev/i8254xGBe_defs.hh @@ -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 §ion) + { + 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 §ion) + { + 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 |