+
+ 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;
+
+ /** Variable to head with header/data completion events */
+ int splitCount;
+
+ /** Bytes of packet that have been copied, so we know when to
+ set EOP */
+ unsigned bytesCopied;
+
+ 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
+ * @param pkt_offset bytes already copied from the packet to memory
+ * @return pkt_offset + number of bytes copied during this call
+ */
+ int writePacket(EthPacketPtr packet, int pkt_offset);
+
+ /** Called by event when dma to write packet is completed
+ */
+ void pktComplete();
+
+ /** Check if the dma on the packet has completed and RX state machine
+ * can continue
+ */
+ bool packetDone();
+
+ EventWrapper<RxDescCache, &RxDescCache::pktComplete> pktEvent;
+
+ // Event to handle issuing header and data write at the same time
+ // and only callking pktComplete() when both are completed
+ void pktSplitDone();
+ EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktHdrEvent;
+ EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktDataEvent;
+
+ virtual bool hasOutstandingEvents();
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string §ion);
+ };
+ 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 actionAfterWb();
+ virtual void fetchAfterWb() {
+ if (!igbe->txTick && igbe->getState() == SimObject::Running)
+ fetchDescriptors();
+ }
+
+
+
+ bool pktDone;
+ bool isTcp;
+ bool pktWaiting;
+ bool pktMultiDesc;
+ Addr completionAddress;
+ bool completionEnabled;
+ uint32_t descEnd;
+
+
+ // tso variables
+ bool useTso;
+ Addr tsoHeaderLen;
+ Addr tsoMss;
+ Addr tsoTotalLen;
+ Addr tsoUsedLen;
+ Addr tsoPrevSeq;;
+ Addr tsoPktPayloadBytes;
+ bool tsoLoadedHeader;
+ bool tsoPktHasHeader;
+ uint8_t tsoHeader[256];
+ Addr tsoDescBytesUsed;
+ Addr tsoCopyBytes;
+ int tsoPkts;
+
+ 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
+ */
+ unsigned getPacketSize(EthPacketPtr p);
+ void getPacketData(EthPacketPtr p);
+ void processContextDesc();
+
+ /** Return the number of dsecriptors in a cache block for threshold
+ * operations.
+ */
+ unsigned
+ descInBlock(unsigned num_desc)
+ {
+ return num_desc / igbe->cacheBlockSize() / sizeof(iGbReg::TxDesc);
+ }
+
+ /** 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;
+
+ void headerComplete();
+ EventWrapper<TxDescCache, &TxDescCache::headerComplete> headerEvent;
+
+
+ void completionWriteback(Addr a, bool enabled) {
+ DPRINTF(EthernetDesc,
+ "Completion writeback Addr: %#x enabled: %d\n",
+ a, enabled);
+ completionAddress = a;
+ completionEnabled = enabled;
+ }
+
+ virtual bool hasOutstandingEvents();
+
+ void nullCallback() {
+ DPRINTF(EthernetDesc, "Completion writeback complete\n");
+ }
+ EventWrapper<TxDescCache, &TxDescCache::nullCallback> nullEvent;
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string §ion);
+
+ };
+ 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 void init();
+
+ virtual EtherInt *getEthPort(const std::string &if_name, int idx);
+
+ Tick clock;
+ Tick lastInterrupt;
+ inline Tick ticks(int numCycles) const { return numCycles * clock; }