13116SN/A/* 23116SN/A * Copyright (c) 2006 The Regents of The University of Michigan 33116SN/A * All rights reserved. 43116SN/A * 53116SN/A * Redistribution and use in source and binary forms, with or without 63116SN/A * modification, are permitted provided that the following conditions are 73116SN/A * met: redistributions of source code must retain the above copyright 83116SN/A * notice, this list of conditions and the following disclaimer; 93116SN/A * redistributions in binary form must reproduce the above copyright 103116SN/A * notice, this list of conditions and the following disclaimer in the 113116SN/A * documentation and/or other materials provided with the distribution; 123116SN/A * neither the name of the copyright holders nor the names of its 133116SN/A * contributors may be used to endorse or promote products derived from 143116SN/A * this software without specific prior written permission. 153116SN/A * 163116SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173116SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183116SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193116SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203116SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213116SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223116SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233116SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243116SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253116SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263116SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273116SN/A * 283116SN/A * Authors: Ali Saidi 293116SN/A */ 303116SN/A 313116SN/A/* @file 323116SN/A * Device model for Intel's 8254x line of gigabit ethernet controllers. 333116SN/A */ 343116SN/A 3511263Sandreas.sandberg@arm.com#ifndef __DEV_NET_I8254XGBE_HH__ 3611263Sandreas.sandberg@arm.com#define __DEV_NET_I8254XGBE_HH__ 373116SN/A 384263SN/A#include <deque> 394263SN/A#include <string> 404263SN/A 415954SN/A#include "base/cp_annotate.hh" 423116SN/A#include "base/inet.hh" 438232SN/A#include "debug/EthernetDesc.hh" 448232SN/A#include "debug/EthernetIntr.hh" 4511263Sandreas.sandberg@arm.com#include "dev/net/etherdevice.hh" 4611263Sandreas.sandberg@arm.com#include "dev/net/etherint.hh" 4711263Sandreas.sandberg@arm.com#include "dev/net/etherpkt.hh" 4811263Sandreas.sandberg@arm.com#include "dev/net/i8254xGBe_defs.hh" 4911263Sandreas.sandberg@arm.com#include "dev/net/pktfifo.hh" 5011260SN/A#include "dev/pci/device.hh" 514762SN/A#include "params/IGbE.hh" 523116SN/A#include "sim/eventq.hh" 533116SN/A 543116SN/Aclass IGbEInt; 553116SN/A 564981SN/Aclass IGbE : public EtherDevice 573116SN/A{ 583116SN/A private: 593116SN/A IGbEInt *etherInt; 605954SN/A CPA *cpa; 614263SN/A 624263SN/A // device registers 633318SN/A iGbReg::Regs regs; 644263SN/A 654263SN/A // eeprom data, status and control bits 663318SN/A int eeOpBits, eeAddrBits, eeDataBits; 673318SN/A uint8_t eeOpcode, eeAddr; 684263SN/A uint16_t flash[iGbReg::EEPROM_SIZE]; 693318SN/A 704263SN/A // packet fifos 714263SN/A PacketFifo rxFifo; 724263SN/A PacketFifo txFifo; 733318SN/A 744263SN/A // Packet that we are currently putting into the txFifo 754263SN/A EthPacketPtr txPacket; 764263SN/A 774263SN/A // Should to Rx/Tx State machine tick? 7812064Sgabeblack@google.com bool inTick; 794263SN/A bool rxTick; 804263SN/A bool txTick; 814291SN/A bool txFifoTick; 824263SN/A 834452SN/A bool rxDmaPacket; 844452SN/A 855783SN/A // Number of bytes copied from current RX packet 866227SN/A unsigned pktOffset; 875783SN/A 885535SN/A // Delays in managaging descriptors 895535SN/A Tick fetchDelay, wbDelay; 905535SN/A Tick fetchCompDelay, wbCompDelay; 915535SN/A Tick rxWriteDelay, txReadDelay; 925535SN/A 934263SN/A // Event and function to deal with RDTR timer expiring 944291SN/A void rdtrProcess() { 954291SN/A rxDescCache.writeback(0); 966124SN/A DPRINTF(EthernetIntr, 976124SN/A "Posting RXT interrupt because RDTR timer expired\n"); 985533SN/A postInterrupt(iGbReg::IT_RXT); 994291SN/A } 1004291SN/A 10112087Sspwilson2@wisc.edu EventFunctionWrapper rdtrEvent; 1024263SN/A 1034263SN/A // Event and function to deal with RADV timer expiring 1044291SN/A void radvProcess() { 1054291SN/A rxDescCache.writeback(0); 1066124SN/A DPRINTF(EthernetIntr, 1076124SN/A "Posting RXT interrupt because RADV timer expired\n"); 1085533SN/A postInterrupt(iGbReg::IT_RXT); 1094291SN/A } 1104291SN/A 11112087Sspwilson2@wisc.edu EventFunctionWrapper radvEvent; 1124263SN/A 1134263SN/A // Event and function to deal with TADV timer expiring 1144291SN/A void tadvProcess() { 1154291SN/A txDescCache.writeback(0); 1166124SN/A DPRINTF(EthernetIntr, 1176124SN/A "Posting TXDW interrupt because TADV timer expired\n"); 1185533SN/A postInterrupt(iGbReg::IT_TXDW); 1194291SN/A } 1204291SN/A 12112087Sspwilson2@wisc.edu EventFunctionWrapper tadvEvent; 1224263SN/A 1234263SN/A // Event and function to deal with TIDV timer expiring 1244291SN/A void tidvProcess() { 1254291SN/A txDescCache.writeback(0); 1266124SN/A DPRINTF(EthernetIntr, 1276124SN/A "Posting TXDW interrupt because TIDV timer expired\n"); 1285533SN/A postInterrupt(iGbReg::IT_TXDW); 1294291SN/A } 13012087Sspwilson2@wisc.edu EventFunctionWrapper tidvEvent; 1314263SN/A 1324263SN/A // Main event to tick the device 1334263SN/A void tick(); 13412087Sspwilson2@wisc.edu EventFunctionWrapper tickEvent; 1354263SN/A 1364263SN/A 1375538SN/A uint64_t macAddr; 1385538SN/A 1394263SN/A void rxStateMachine(); 1404263SN/A void txStateMachine(); 1414263SN/A void txWire(); 1424263SN/A 1434263SN/A /** Write an interrupt into the interrupt pending register and check mask 1444263SN/A * and interrupt limit timer before sending interrupt to CPU 1454263SN/A * @param t the type of interrupt we are posting 1464263SN/A * @param now should we ignore the interrupt limiting timer 1474263SN/A */ 1484263SN/A void postInterrupt(iGbReg::IntTypes t, bool now = false); 1494263SN/A 1504263SN/A /** Check and see if changes to the mask register have caused an interrupt 1514263SN/A * to need to be sent or perhaps removed an interrupt cause. 1524263SN/A */ 1534263SN/A void chkInterrupt(); 1544263SN/A 1554263SN/A /** Send an interrupt to the cpu 1564263SN/A */ 1574987SN/A void delayIntEvent(); 1584263SN/A void cpuPostInt(); 1594263SN/A // Event to moderate interrupts 16012087Sspwilson2@wisc.edu EventFunctionWrapper interEvent; 1614263SN/A 1624263SN/A /** Clear the interupt line to the cpu 1634263SN/A */ 1644263SN/A void cpuClearInt(); 1654263SN/A 1667064SN/A Tick intClock() { return SimClock::Int::ns * 1024; } 1674263SN/A 1684294SN/A /** This function is used to restart the clock so it can handle things like 1694294SN/A * draining and resume in one place. */ 1704283SN/A void restartClock(); 1714283SN/A 1724294SN/A /** Check if all the draining things that need to occur have occured and 1734294SN/A * handle the drain event if so. 1744294SN/A */ 1754294SN/A void checkDrain(); 1764294SN/A 1775954SN/A void anBegin(std::string sm, std::string st, int flags = CPA::FL_NONE) { 17810702SN/A if (cpa) 17910702SN/A cpa->hwBegin((CPA::flags)flags, sys, macAddr, sm, st); 1805954SN/A } 1815954SN/A 18210702SN/A void anQ(std::string sm, std::string q) { 18310702SN/A if (cpa) 18410702SN/A cpa->hwQ(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); 1855954SN/A } 1865954SN/A 1875954SN/A void anDq(std::string sm, std::string q) { 18810702SN/A if (cpa) 18910702SN/A cpa->hwDq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); 1905954SN/A } 1915954SN/A 1925954SN/A void anPq(std::string sm, std::string q, int num = 1) { 19310702SN/A if (cpa) 19410702SN/A cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num); 1955954SN/A } 1965954SN/A 1975954SN/A void anRq(std::string sm, std::string q, int num = 1) { 19810702SN/A if (cpa) 19910702SN/A cpa->hwRq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num); 2005954SN/A } 2015954SN/A 2025954SN/A void anWe(std::string sm, std::string q) { 20310702SN/A if (cpa) 20410702SN/A cpa->hwWe(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); 2055954SN/A } 2065954SN/A 2075954SN/A void anWf(std::string sm, std::string q) { 20810702SN/A if (cpa) 20910702SN/A cpa->hwWf(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); 2105954SN/A } 2115954SN/A 2125954SN/A 2134263SN/A template<class T> 21410905SN/A class DescCache : public Serializable 2154263SN/A { 2164263SN/A protected: 2174263SN/A virtual Addr descBase() const = 0; 2184263SN/A virtual long descHead() const = 0; 2194263SN/A virtual long descTail() const = 0; 2204263SN/A virtual long descLen() const = 0; 2214263SN/A virtual void updateHead(long h) = 0; 2224263SN/A virtual void enableSm() = 0; 2235763SN/A virtual void actionAfterWb() {} 2244987SN/A virtual void fetchAfterWb() = 0; 2254263SN/A 2266227SN/A typedef std::deque<T *> CacheType; 2276227SN/A CacheType usedCache; 2286227SN/A CacheType unusedCache; 2294263SN/A 2304263SN/A T *fetchBuf; 2314263SN/A T *wbBuf; 2324263SN/A 2334263SN/A // Pointer to the device we cache for 2344263SN/A IGbE *igbe; 2354263SN/A 2364263SN/A // Name of this descriptor cache 2374263SN/A std::string _name; 2384263SN/A 2394263SN/A // How far we've cached 2404263SN/A int cachePnt; 2414263SN/A 2424263SN/A // The size of the descriptor cache 2434263SN/A int size; 2444263SN/A 2454263SN/A // How many descriptors we are currently fetching 2464263SN/A int curFetching; 2474263SN/A 2484263SN/A // How many descriptors we are currently writing back 2494263SN/A int wbOut; 2504263SN/A 2514263SN/A // if the we wrote back to the end of the descriptor ring and are going 2524263SN/A // to have to wrap and write more 2534263SN/A bool moreToWb; 2544263SN/A 2554263SN/A // What the alignment is of the next descriptor writeback 2564263SN/A Addr wbAlignment; 2574263SN/A 2586124SN/A /** The packet that is currently being dmad to memory if any */ 2594263SN/A EthPacketPtr pktPtr; 2604263SN/A 2616124SN/A /** Shortcut for DMA address translation */ 26211202SN/A Addr pciToDma(Addr a) { return igbe->pciToDma(a); } 2636124SN/A 2644263SN/A public: 2655954SN/A /** Annotate sm*/ 2665954SN/A std::string annSmFetch, annSmWb, annUnusedDescQ, annUsedCacheQ, 2675954SN/A annUsedDescQ, annUnusedCacheQ, annDescQ; 2685954SN/A 2696124SN/A DescCache(IGbE *i, const std::string n, int s); 2706124SN/A virtual ~DescCache(); 2714263SN/A 2724263SN/A std::string name() { return _name; } 2734263SN/A 2744263SN/A /** If the address/len/head change when we've got descriptors that are 2754263SN/A * dirty that is very bad. This function checks that we don't and if we 2764263SN/A * do panics. 2774263SN/A */ 2786124SN/A void areaChanged(); 2794291SN/A 2806124SN/A void writeback(Addr aMask); 2816124SN/A void writeback1(); 28212087Sspwilson2@wisc.edu EventFunctionWrapper wbDelayEvent; 2834263SN/A 2844263SN/A /** Fetch a chunk of descriptors into the descriptor cache. 2854263SN/A * Calls fetchComplete when the memory system returns the data 2864263SN/A */ 2876124SN/A void fetchDescriptors(); 2886124SN/A void fetchDescriptors1(); 28912087Sspwilson2@wisc.edu EventFunctionWrapper fetchDelayEvent; 2904263SN/A 2914263SN/A /** Called by event when dma to read descriptors is completed 2924263SN/A */ 2936124SN/A void fetchComplete(); 29412087Sspwilson2@wisc.edu EventFunctionWrapper fetchEvent; 2954263SN/A 2964263SN/A /** Called by event when dma to writeback descriptors is completed 2974263SN/A */ 2986124SN/A void wbComplete(); 29912087Sspwilson2@wisc.edu EventFunctionWrapper wbEvent; 3004263SN/A 3014263SN/A /* Return the number of descriptors left in the ring, so the device has 3024263SN/A * a way to figure out if it needs to interrupt. 3034263SN/A */ 3046227SN/A unsigned 3056227SN/A descLeft() const 3064263SN/A { 3076227SN/A unsigned left = unusedCache.size(); 3086217SN/A if (cachePnt > descTail()) 3095762SN/A left += (descLen() - cachePnt + descTail()); 3104263SN/A else 3114283SN/A left += (descTail() - cachePnt); 3124263SN/A 3134263SN/A return left; 3144263SN/A } 3154263SN/A 3164263SN/A /* Return the number of descriptors used and not written back. 3174263SN/A */ 3186227SN/A unsigned descUsed() const { return usedCache.size(); } 3194263SN/A 3204263SN/A /* Return the number of cache unused descriptors we have. */ 3216227SN/A unsigned descUnused() const { return unusedCache.size(); } 3224263SN/A 3234263SN/A /* Get into a state where the descriptor address/head/etc colud be 3244263SN/A * changed */ 3256124SN/A void reset(); 3264263SN/A 32710905SN/A 32811168SN/A void serialize(CheckpointOut &cp) const override; 32911168SN/A void unserialize(CheckpointIn &cp) override; 3304291SN/A 3314294SN/A virtual bool hasOutstandingEvents() { 3324294SN/A return wbEvent.scheduled() || fetchEvent.scheduled(); 3334294SN/A } 3344294SN/A 3356124SN/A }; 3364263SN/A 3374263SN/A 3384263SN/A class RxDescCache : public DescCache<iGbReg::RxDesc> 3394263SN/A { 3404263SN/A protected: 34111169SN/A Addr descBase() const override { return igbe->regs.rdba(); } 34211169SN/A long descHead() const override { return igbe->regs.rdh(); } 34311169SN/A long descLen() const override { return igbe->regs.rdlen() >> 4; } 34411169SN/A long descTail() const override { return igbe->regs.rdt(); } 34511169SN/A void updateHead(long h) override { igbe->regs.rdh(h); } 34611169SN/A void enableSm() override; 34711169SN/A void fetchAfterWb() override { 34810913SN/A if (!igbe->rxTick && igbe->drainState() == DrainState::Running) 3494987SN/A fetchDescriptors(); 3504987SN/A } 3514263SN/A 3524263SN/A bool pktDone; 3534263SN/A 3545783SN/A /** Variable to head with header/data completion events */ 3555783SN/A int splitCount; 3565783SN/A 3576124SN/A /** Bytes of packet that have been copied, so we know when to 3586124SN/A set EOP */ 3596227SN/A unsigned bytesCopied; 3605783SN/A 3614263SN/A public: 3624263SN/A RxDescCache(IGbE *i, std::string n, int s); 3634263SN/A 3644263SN/A /** Write the given packet into the buffer(s) pointed to by the 3654263SN/A * descriptor and update the book keeping. Should only be called when 3664263SN/A * there are no dma's pending. 3674263SN/A * @param packet ethernet packet to write 3685783SN/A * @param pkt_offset bytes already copied from the packet to memory 3695783SN/A * @return pkt_offset + number of bytes copied during this call 3704263SN/A */ 3715783SN/A int writePacket(EthPacketPtr packet, int pkt_offset); 3725783SN/A 3734263SN/A /** Called by event when dma to write packet is completed 3744263SN/A */ 3754263SN/A void pktComplete(); 3764263SN/A 3775783SN/A /** Check if the dma on the packet has completed and RX state machine 3785783SN/A * can continue 3794263SN/A */ 3804263SN/A bool packetDone(); 3814263SN/A 38212087Sspwilson2@wisc.edu EventFunctionWrapper pktEvent; 3834263SN/A 3845783SN/A // Event to handle issuing header and data write at the same time 3855783SN/A // and only callking pktComplete() when both are completed 3865783SN/A void pktSplitDone(); 38712087Sspwilson2@wisc.edu EventFunctionWrapper pktHdrEvent; 38812087Sspwilson2@wisc.edu EventFunctionWrapper pktDataEvent; 3895783SN/A 39011169SN/A bool hasOutstandingEvents() override; 3914294SN/A 39211168SN/A void serialize(CheckpointOut &cp) const override; 39311168SN/A void unserialize(CheckpointIn &cp) override; 3944263SN/A }; 3954263SN/A friend class RxDescCache; 3964263SN/A 3974263SN/A RxDescCache rxDescCache; 3984263SN/A 3994263SN/A class TxDescCache : public DescCache<iGbReg::TxDesc> 4004263SN/A { 4014263SN/A protected: 40211169SN/A Addr descBase() const override { return igbe->regs.tdba(); } 40311169SN/A long descHead() const override { return igbe->regs.tdh(); } 40411169SN/A long descTail() const override { return igbe->regs.tdt(); } 40511169SN/A long descLen() const override { return igbe->regs.tdlen() >> 4; } 40611169SN/A void updateHead(long h) override { igbe->regs.tdh(h); } 40711169SN/A void enableSm() override; 40811169SN/A void actionAfterWb() override; 40911169SN/A void fetchAfterWb() override { 41010913SN/A if (!igbe->txTick && igbe->drainState() == DrainState::Running) 4114987SN/A fetchDescriptors(); 4124987SN/A } 41311320Ssteve.reinhardt@amd.com 4145763SN/A 4154263SN/A 4164263SN/A bool pktDone; 4174263SN/A bool isTcp; 4184263SN/A bool pktWaiting; 4195404SN/A bool pktMultiDesc; 4205763SN/A Addr completionAddress; 4215763SN/A bool completionEnabled; 4225763SN/A uint32_t descEnd; 42311320Ssteve.reinhardt@amd.com 4244263SN/A 4255762SN/A // tso variables 4265762SN/A bool useTso; 4275762SN/A Addr tsoHeaderLen; 4285762SN/A Addr tsoMss; 4295762SN/A Addr tsoTotalLen; 4305762SN/A Addr tsoUsedLen; 4318902SN/A Addr tsoPrevSeq; 4325762SN/A Addr tsoPktPayloadBytes; 4335762SN/A bool tsoLoadedHeader; 4345762SN/A bool tsoPktHasHeader; 4355762SN/A uint8_t tsoHeader[256]; 4365762SN/A Addr tsoDescBytesUsed; 4375762SN/A Addr tsoCopyBytes; 4385762SN/A int tsoPkts; 4395762SN/A 4404263SN/A public: 4414263SN/A TxDescCache(IGbE *i, std::string n, int s); 4424263SN/A 4434263SN/A /** Tell the cache to DMA a packet from main memory into its buffer and 4444263SN/A * return the size the of the packet to reserve space in tx fifo. 4454263SN/A * @return size of the packet 4464263SN/A */ 4476227SN/A unsigned getPacketSize(EthPacketPtr p); 4484263SN/A void getPacketData(EthPacketPtr p); 4495762SN/A void processContextDesc(); 4504263SN/A 4515763SN/A /** Return the number of dsecriptors in a cache block for threshold 4525763SN/A * operations. 4535763SN/A */ 4546227SN/A unsigned 4556227SN/A descInBlock(unsigned num_desc) 4566227SN/A { 4576227SN/A return num_desc / igbe->cacheBlockSize() / sizeof(iGbReg::TxDesc); 4586227SN/A } 4596227SN/A 4604263SN/A /** Ask if the packet has been transfered so the state machine can give 4614263SN/A * it to the fifo. 4624263SN/A * @return packet available in descriptor cache 4634263SN/A */ 4644263SN/A bool packetAvailable(); 4654263SN/A 4664263SN/A /** Ask if we are still waiting for the packet to be transfered. 4674263SN/A * @return packet still in transit. 4684263SN/A */ 4694263SN/A bool packetWaiting() { return pktWaiting; } 4704263SN/A 4715404SN/A /** Ask if this packet is composed of multiple descriptors 4725404SN/A * so even if we've got data, we need to wait for more before 4735404SN/A * we can send it out. 4745404SN/A * @return packet can't be sent out because it's a multi-descriptor 4755404SN/A * packet 4765404SN/A */ 4775404SN/A bool packetMultiDesc() { return pktMultiDesc;} 4785404SN/A 4794263SN/A /** Called by event when dma to write packet is completed 4804263SN/A */ 4814263SN/A void pktComplete(); 48212087Sspwilson2@wisc.edu EventFunctionWrapper pktEvent; 4834263SN/A 4845762SN/A void headerComplete(); 48512087Sspwilson2@wisc.edu EventFunctionWrapper headerEvent; 4865762SN/A 4875763SN/A 4885763SN/A void completionWriteback(Addr a, bool enabled) { 4896124SN/A DPRINTF(EthernetDesc, 49011320Ssteve.reinhardt@amd.com "Completion writeback Addr: %#x enabled: %d\n", 4915763SN/A a, enabled); 4925763SN/A completionAddress = a; 4935763SN/A completionEnabled = enabled; 4945763SN/A } 4955763SN/A 49611169SN/A bool hasOutstandingEvents() override; 4974294SN/A 4986124SN/A void nullCallback() { 4996124SN/A DPRINTF(EthernetDesc, "Completion writeback complete\n"); 5006124SN/A } 50112087Sspwilson2@wisc.edu EventFunctionWrapper nullEvent; 5025763SN/A 50311168SN/A void serialize(CheckpointOut &cp) const override; 50411168SN/A void unserialize(CheckpointIn &cp) override; 50510905SN/A }; 5064294SN/A 5074263SN/A friend class TxDescCache; 5084263SN/A 5094263SN/A TxDescCache txDescCache; 5103116SN/A 5113116SN/A public: 5124762SN/A typedef IGbEParams Params; 5134762SN/A const Params * 5146124SN/A params() const { 5154762SN/A return dynamic_cast<const Params *>(_params); 5164762SN/A } 5176124SN/A 5184981SN/A IGbE(const Params *params); 5199086SN/A ~IGbE(); 52011169SN/A void init() override; 5213116SN/A 52213784Sgabeblack@google.com Port &getPort(const std::string &if_name, 52313784Sgabeblack@google.com PortID idx=InvalidPortID) override; 5244981SN/A 5255500SN/A Tick lastInterrupt; 5264263SN/A 52711169SN/A Tick read(PacketPtr pkt) override; 52811169SN/A Tick write(PacketPtr pkt) override; 5293116SN/A 53011169SN/A Tick writeConfig(PacketPtr pkt) override; 5313116SN/A 5323116SN/A bool ethRxPkt(EthPacketPtr packet); 5333116SN/A void ethTxDone(); 5343116SN/A 53511168SN/A void serialize(CheckpointOut &cp) const override; 53611168SN/A void unserialize(CheckpointIn &cp) override; 5379342SN/A 53811168SN/A DrainState drain() override; 53911168SN/A void drainResume() override; 5403116SN/A 5413116SN/A}; 5423116SN/A 5433116SN/Aclass IGbEInt : public EtherInt 5443116SN/A{ 5453116SN/A private: 5463116SN/A IGbE *dev; 5473116SN/A 5483116SN/A public: 5493116SN/A IGbEInt(const std::string &name, IGbE *d) 5503116SN/A : EtherInt(name), dev(d) 5514981SN/A { } 5523116SN/A 5533116SN/A virtual bool recvPacket(EthPacketPtr pkt) { return dev->ethRxPkt(pkt); } 5543116SN/A virtual void sendDone() { dev->ethTxDone(); } 5553116SN/A}; 5563116SN/A 55711263Sandreas.sandberg@arm.com#endif //__DEV_NET_I8254XGBE_HH__ 558