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);
{
size_t max_to_fetch;
+ if (curFetching)
+ return;
+
if (descTail() >= cachePnt)
max_to_fetch = descTail() - cachePnt;
else
max_to_fetch = descLen() - cachePnt;
- max_to_fetch = std::min(max_to_fetch, (size - usedCache.size() -
- unusedCache.size()));
+ 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",
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
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);
#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;
oldHead, curHead);
// If we still have more to wb, call wb now
- bool oldMoreToWb = moreToWb;
+ intAfterWb();
if (moreToWb) {
DPRINTF(EthernetDesc, "Writeback has more todo\n");
writeback(wbAlignment);
}
- intAfterWb();
- if (!oldMoreToWb) {
+ if (!wbOut) {
igbe->checkDrain();
}
fetchAfterWb();
* @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();
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);
*/
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();
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);