i8254xGBe.hh revision 8902
16717Sgblack@eecs.umich.edu/* 210337SAndrew.Bardsley@arm.com * Copyright (c) 2006 The Regents of The University of Michigan 37310Sgblack@eecs.umich.edu * All rights reserved. 47310Sgblack@eecs.umich.edu * 57310Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67310Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77310Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87310Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97310Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107310Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117310Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127310Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137310Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146717Sgblack@eecs.umich.edu * this software without specific prior written permission. 156717Sgblack@eecs.umich.edu * 166717Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176717Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186717Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196717Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206717Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216717Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226717Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236717Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246717Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256717Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266717Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276717Sgblack@eecs.umich.edu * 286717Sgblack@eecs.umich.edu * Authors: Ali Saidi 296717Sgblack@eecs.umich.edu */ 306717Sgblack@eecs.umich.edu 316717Sgblack@eecs.umich.edu/* @file 326717Sgblack@eecs.umich.edu * Device model for Intel's 8254x line of gigabit ethernet controllers. 336717Sgblack@eecs.umich.edu */ 346717Sgblack@eecs.umich.edu 356717Sgblack@eecs.umich.edu#ifndef __DEV_I8254XGBE_HH__ 366717Sgblack@eecs.umich.edu#define __DEV_I8254XGBE_HH__ 376717Sgblack@eecs.umich.edu 386717Sgblack@eecs.umich.edu#include <deque> 396717Sgblack@eecs.umich.edu#include <string> 406717Sgblack@eecs.umich.edu 416717Sgblack@eecs.umich.edu#include "base/cp_annotate.hh" 426717Sgblack@eecs.umich.edu#include "base/inet.hh" 438229Snate@binkert.org#include "debug/EthernetDesc.hh" 446717Sgblack@eecs.umich.edu#include "debug/EthernetIntr.hh" 456717Sgblack@eecs.umich.edu#include "dev/etherdevice.hh" 466717Sgblack@eecs.umich.edu#include "dev/etherint.hh" 476717Sgblack@eecs.umich.edu#include "dev/etherpkt.hh" 487310Sgblack@eecs.umich.edu#include "dev/i8254xGBe_defs.hh" 497310Sgblack@eecs.umich.edu#include "dev/pcidev.hh" 506717Sgblack@eecs.umich.edu#include "dev/pktfifo.hh" 516717Sgblack@eecs.umich.edu#include "params/IGbE.hh" 526717Sgblack@eecs.umich.edu#include "sim/eventq.hh" 536717Sgblack@eecs.umich.edu 546717Sgblack@eecs.umich.educlass IGbEInt; 556717Sgblack@eecs.umich.edu 566717Sgblack@eecs.umich.educlass IGbE : public EtherDevice 576717Sgblack@eecs.umich.edu{ 586717Sgblack@eecs.umich.edu private: 596717Sgblack@eecs.umich.edu IGbEInt *etherInt; 606717Sgblack@eecs.umich.edu CPA *cpa; 616717Sgblack@eecs.umich.edu 626717Sgblack@eecs.umich.edu // device registers 636717Sgblack@eecs.umich.edu iGbReg::Regs regs; 646717Sgblack@eecs.umich.edu 656717Sgblack@eecs.umich.edu // eeprom data, status and control bits 666717Sgblack@eecs.umich.edu int eeOpBits, eeAddrBits, eeDataBits; 676717Sgblack@eecs.umich.edu uint8_t eeOpcode, eeAddr; 686717Sgblack@eecs.umich.edu uint16_t flash[iGbReg::EEPROM_SIZE]; 696717Sgblack@eecs.umich.edu 706717Sgblack@eecs.umich.edu // The drain event if we have one 716717Sgblack@eecs.umich.edu Event *drainEvent; 726717Sgblack@eecs.umich.edu 736717Sgblack@eecs.umich.edu // cached parameters from params struct 746717Sgblack@eecs.umich.edu bool useFlowControl; 756717Sgblack@eecs.umich.edu 766717Sgblack@eecs.umich.edu // packet fifos 776717Sgblack@eecs.umich.edu PacketFifo rxFifo; 786717Sgblack@eecs.umich.edu PacketFifo txFifo; 796717Sgblack@eecs.umich.edu 806717Sgblack@eecs.umich.edu // Packet that we are currently putting into the txFifo 816717Sgblack@eecs.umich.edu EthPacketPtr txPacket; 826717Sgblack@eecs.umich.edu 836717Sgblack@eecs.umich.edu // Should to Rx/Tx State machine tick? 846717Sgblack@eecs.umich.edu bool rxTick; 856717Sgblack@eecs.umich.edu bool txTick; 8610037SARM gem5 Developers bool txFifoTick; 8710037SARM gem5 Developers 8810037SARM gem5 Developers bool rxDmaPacket; 896717Sgblack@eecs.umich.edu 906717Sgblack@eecs.umich.edu // Number of bytes copied from current RX packet 916717Sgblack@eecs.umich.edu unsigned pktOffset; 926717Sgblack@eecs.umich.edu 936717Sgblack@eecs.umich.edu // Delays in managaging descriptors 946717Sgblack@eecs.umich.edu Tick fetchDelay, wbDelay; 956717Sgblack@eecs.umich.edu Tick fetchCompDelay, wbCompDelay; 966717Sgblack@eecs.umich.edu Tick rxWriteDelay, txReadDelay; 976717Sgblack@eecs.umich.edu 986717Sgblack@eecs.umich.edu // Event and function to deal with RDTR timer expiring 996717Sgblack@eecs.umich.edu void rdtrProcess() { 1006717Sgblack@eecs.umich.edu rxDescCache.writeback(0); 1016717Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, 1026717Sgblack@eecs.umich.edu "Posting RXT interrupt because RDTR timer expired\n"); 1036717Sgblack@eecs.umich.edu postInterrupt(iGbReg::IT_RXT); 1046717Sgblack@eecs.umich.edu } 1056717Sgblack@eecs.umich.edu 1066717Sgblack@eecs.umich.edu //friend class EventWrapper<IGbE, &IGbE::rdtrProcess>; 1076717Sgblack@eecs.umich.edu EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent; 1086717Sgblack@eecs.umich.edu 1096717Sgblack@eecs.umich.edu // Event and function to deal with RADV timer expiring 1106717Sgblack@eecs.umich.edu void radvProcess() { 1116717Sgblack@eecs.umich.edu rxDescCache.writeback(0); 1126717Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, 1136717Sgblack@eecs.umich.edu "Posting RXT interrupt because RADV timer expired\n"); 11410037SARM gem5 Developers postInterrupt(iGbReg::IT_RXT); 1156717Sgblack@eecs.umich.edu } 1168140SMatt.Horsnell@arm.com 1178140SMatt.Horsnell@arm.com //friend class EventWrapper<IGbE, &IGbE::radvProcess>; 11810037SARM gem5 Developers EventWrapper<IGbE, &IGbE::radvProcess> radvEvent; 11910037SARM gem5 Developers 12010037SARM gem5 Developers // Event and function to deal with TADV timer expiring 12110037SARM gem5 Developers void tadvProcess() { 12210037SARM gem5 Developers txDescCache.writeback(0); 12310037SARM gem5 Developers DPRINTF(EthernetIntr, 1246717Sgblack@eecs.umich.edu "Posting TXDW interrupt because TADV timer expired\n"); 1256717Sgblack@eecs.umich.edu postInterrupt(iGbReg::IT_TXDW); 12610037SARM gem5 Developers } 12710037SARM gem5 Developers 12810037SARM gem5 Developers //friend class EventWrapper<IGbE, &IGbE::tadvProcess>; 12910037SARM gem5 Developers EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent; 13010037SARM gem5 Developers 13110037SARM gem5 Developers // Event and function to deal with TIDV timer expiring 13210037SARM gem5 Developers void tidvProcess() { 13310037SARM gem5 Developers txDescCache.writeback(0); 13410037SARM gem5 Developers DPRINTF(EthernetIntr, 13510037SARM gem5 Developers "Posting TXDW interrupt because TIDV timer expired\n"); 13610037SARM gem5 Developers postInterrupt(iGbReg::IT_TXDW); 13710037SARM gem5 Developers } 13810037SARM gem5 Developers //friend class EventWrapper<IGbE, &IGbE::tidvProcess>; 13910037SARM gem5 Developers EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent; 14010037SARM gem5 Developers 14110037SARM gem5 Developers // Main event to tick the device 14210037SARM gem5 Developers void tick(); 14310037SARM gem5 Developers //friend class EventWrapper<IGbE, &IGbE::tick>; 14410037SARM gem5 Developers EventWrapper<IGbE, &IGbE::tick> tickEvent; 14510037SARM gem5 Developers 14610037SARM gem5 Developers 14710037SARM gem5 Developers uint64_t macAddr; 14810037SARM gem5 Developers 14910037SARM gem5 Developers void rxStateMachine(); 15010037SARM gem5 Developers void txStateMachine(); 15110037SARM gem5 Developers void txWire(); 15210037SARM gem5 Developers 15310037SARM gem5 Developers /** Write an interrupt into the interrupt pending register and check mask 15410037SARM gem5 Developers * and interrupt limit timer before sending interrupt to CPU 15510037SARM gem5 Developers * @param t the type of interrupt we are posting 15610037SARM gem5 Developers * @param now should we ignore the interrupt limiting timer 15710037SARM gem5 Developers */ 15810037SARM gem5 Developers void postInterrupt(iGbReg::IntTypes t, bool now = false); 15910037SARM gem5 Developers 16010037SARM gem5 Developers /** Check and see if changes to the mask register have caused an interrupt 16110037SARM gem5 Developers * to need to be sent or perhaps removed an interrupt cause. 16210037SARM gem5 Developers */ 1636717Sgblack@eecs.umich.edu void chkInterrupt(); 1646717Sgblack@eecs.umich.edu 16510037SARM gem5 Developers /** Send an interrupt to the cpu 1666717Sgblack@eecs.umich.edu */ 1676717Sgblack@eecs.umich.edu void delayIntEvent(); 1686717Sgblack@eecs.umich.edu void cpuPostInt(); 1696717Sgblack@eecs.umich.edu // Event to moderate interrupts 1706717Sgblack@eecs.umich.edu EventWrapper<IGbE, &IGbE::delayIntEvent> interEvent; 1716717Sgblack@eecs.umich.edu 1726717Sgblack@eecs.umich.edu /** Clear the interupt line to the cpu 1736717Sgblack@eecs.umich.edu */ 1746717Sgblack@eecs.umich.edu void cpuClearInt(); 1756717Sgblack@eecs.umich.edu 1766717Sgblack@eecs.umich.edu Tick intClock() { return SimClock::Int::ns * 1024; } 1776717Sgblack@eecs.umich.edu 1786717Sgblack@eecs.umich.edu /** This function is used to restart the clock so it can handle things like 1796717Sgblack@eecs.umich.edu * draining and resume in one place. */ 1806717Sgblack@eecs.umich.edu void restartClock(); 1816717Sgblack@eecs.umich.edu 1826717Sgblack@eecs.umich.edu /** Check if all the draining things that need to occur have occured and 1836717Sgblack@eecs.umich.edu * handle the drain event if so. 1846717Sgblack@eecs.umich.edu */ 1856717Sgblack@eecs.umich.edu void checkDrain(); 1866717Sgblack@eecs.umich.edu 1876717Sgblack@eecs.umich.edu void anBegin(std::string sm, std::string st, int flags = CPA::FL_NONE) { 1886717Sgblack@eecs.umich.edu cpa->hwBegin((CPA::flags)flags, sys, macAddr, sm, st); 1896717Sgblack@eecs.umich.edu } 1906717Sgblack@eecs.umich.edu 1916717Sgblack@eecs.umich.edu void anQ(std::string sm, std::string q) { 1926717Sgblack@eecs.umich.edu cpa->hwQ(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); 1936717Sgblack@eecs.umich.edu } 1946717Sgblack@eecs.umich.edu 1956717Sgblack@eecs.umich.edu void anDq(std::string sm, std::string q) { 1966717Sgblack@eecs.umich.edu cpa->hwDq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); 1976717Sgblack@eecs.umich.edu } 1986717Sgblack@eecs.umich.edu 1996717Sgblack@eecs.umich.edu void anPq(std::string sm, std::string q, int num = 1) { 2006717Sgblack@eecs.umich.edu cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num); 2016717Sgblack@eecs.umich.edu } 2026734Sgblack@eecs.umich.edu 2036717Sgblack@eecs.umich.edu void anRq(std::string sm, std::string q, int num = 1) { 2046717Sgblack@eecs.umich.edu cpa->hwRq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num); 2056717Sgblack@eecs.umich.edu } 2066717Sgblack@eecs.umich.edu 2076717Sgblack@eecs.umich.edu void anWe(std::string sm, std::string q) { 2086717Sgblack@eecs.umich.edu cpa->hwWe(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); 2096717Sgblack@eecs.umich.edu } 2106717Sgblack@eecs.umich.edu 2116717Sgblack@eecs.umich.edu void anWf(std::string sm, std::string q) { 2126717Sgblack@eecs.umich.edu cpa->hwWf(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); 2136717Sgblack@eecs.umich.edu } 2146717Sgblack@eecs.umich.edu 2156717Sgblack@eecs.umich.edu 2166717Sgblack@eecs.umich.edu template<class T> 2176717Sgblack@eecs.umich.edu class DescCache 2186717Sgblack@eecs.umich.edu { 2196734Sgblack@eecs.umich.edu protected: 2206717Sgblack@eecs.umich.edu virtual Addr descBase() const = 0; 2216717Sgblack@eecs.umich.edu virtual long descHead() const = 0; 2226717Sgblack@eecs.umich.edu virtual long descTail() const = 0; 2236717Sgblack@eecs.umich.edu virtual long descLen() const = 0; 2246717Sgblack@eecs.umich.edu virtual void updateHead(long h) = 0; 2256717Sgblack@eecs.umich.edu virtual void enableSm() = 0; 2266717Sgblack@eecs.umich.edu virtual void actionAfterWb() {} 2276717Sgblack@eecs.umich.edu virtual void fetchAfterWb() = 0; 2286717Sgblack@eecs.umich.edu 2296717Sgblack@eecs.umich.edu typedef std::deque<T *> CacheType; 2306717Sgblack@eecs.umich.edu CacheType usedCache; 2316717Sgblack@eecs.umich.edu CacheType unusedCache; 2326717Sgblack@eecs.umich.edu 2336717Sgblack@eecs.umich.edu T *fetchBuf; 2346717Sgblack@eecs.umich.edu T *wbBuf; 2356717Sgblack@eecs.umich.edu 2366734Sgblack@eecs.umich.edu // Pointer to the device we cache for 2376717Sgblack@eecs.umich.edu IGbE *igbe; 23810037SARM gem5 Developers 23910037SARM gem5 Developers // Name of this descriptor cache 24010037SARM gem5 Developers std::string _name; 24110037SARM gem5 Developers 24210037SARM gem5 Developers // How far we've cached 24310037SARM gem5 Developers int cachePnt; 24410037SARM gem5 Developers 24510037SARM gem5 Developers // The size of the descriptor cache 24610037SARM gem5 Developers int size; 24710037SARM gem5 Developers 24810037SARM gem5 Developers // How many descriptors we are currently fetching 24910037SARM gem5 Developers int curFetching; 25010037SARM gem5 Developers 25110037SARM gem5 Developers // How many descriptors we are currently writing back 25210037SARM gem5 Developers int wbOut; 25310037SARM gem5 Developers 25410037SARM gem5 Developers // if the we wrote back to the end of the descriptor ring and are going 25510037SARM gem5 Developers // to have to wrap and write more 25610037SARM gem5 Developers bool moreToWb; 2576717Sgblack@eecs.umich.edu 2586717Sgblack@eecs.umich.edu // What the alignment is of the next descriptor writeback 2596717Sgblack@eecs.umich.edu Addr wbAlignment; 2606717Sgblack@eecs.umich.edu 2616717Sgblack@eecs.umich.edu /** The packet that is currently being dmad to memory if any */ 2626717Sgblack@eecs.umich.edu EthPacketPtr pktPtr; 2636717Sgblack@eecs.umich.edu 2646717Sgblack@eecs.umich.edu /** Shortcut for DMA address translation */ 2656717Sgblack@eecs.umich.edu Addr pciToDma(Addr a) { return igbe->platform->pciToDma(a); } 2666717Sgblack@eecs.umich.edu 2676717Sgblack@eecs.umich.edu public: 2686717Sgblack@eecs.umich.edu /** Annotate sm*/ 2696717Sgblack@eecs.umich.edu std::string annSmFetch, annSmWb, annUnusedDescQ, annUsedCacheQ, 2706717Sgblack@eecs.umich.edu annUsedDescQ, annUnusedCacheQ, annDescQ; 2716717Sgblack@eecs.umich.edu 2726734Sgblack@eecs.umich.edu DescCache(IGbE *i, const std::string n, int s); 2736717Sgblack@eecs.umich.edu virtual ~DescCache(); 2746717Sgblack@eecs.umich.edu 2756717Sgblack@eecs.umich.edu std::string name() { return _name; } 2766717Sgblack@eecs.umich.edu 2776717Sgblack@eecs.umich.edu /** If the address/len/head change when we've got descriptors that are 2786717Sgblack@eecs.umich.edu * dirty that is very bad. This function checks that we don't and if we 2796717Sgblack@eecs.umich.edu * do panics. 2806717Sgblack@eecs.umich.edu */ 2816717Sgblack@eecs.umich.edu void areaChanged(); 2826717Sgblack@eecs.umich.edu 2836717Sgblack@eecs.umich.edu void writeback(Addr aMask); 2846717Sgblack@eecs.umich.edu void writeback1(); 2856717Sgblack@eecs.umich.edu EventWrapper<DescCache, &DescCache::writeback1> wbDelayEvent; 2866717Sgblack@eecs.umich.edu 2876717Sgblack@eecs.umich.edu /** Fetch a chunk of descriptors into the descriptor cache. 2886717Sgblack@eecs.umich.edu * Calls fetchComplete when the memory system returns the data 2896734Sgblack@eecs.umich.edu */ 2906717Sgblack@eecs.umich.edu void fetchDescriptors(); 2916717Sgblack@eecs.umich.edu void fetchDescriptors1(); 2926717Sgblack@eecs.umich.edu EventWrapper<DescCache, &DescCache::fetchDescriptors1> fetchDelayEvent; 2936717Sgblack@eecs.umich.edu 2946717Sgblack@eecs.umich.edu /** Called by event when dma to read descriptors is completed 2956717Sgblack@eecs.umich.edu */ 2966717Sgblack@eecs.umich.edu void fetchComplete(); 2976717Sgblack@eecs.umich.edu EventWrapper<DescCache, &DescCache::fetchComplete> fetchEvent; 2986717Sgblack@eecs.umich.edu 2996717Sgblack@eecs.umich.edu /** Called by event when dma to writeback descriptors is completed 3006717Sgblack@eecs.umich.edu */ 3018902Sandreas.hansson@arm.com void wbComplete(); 3026717Sgblack@eecs.umich.edu EventWrapper<DescCache, &DescCache::wbComplete> wbEvent; 3036717Sgblack@eecs.umich.edu 3046717Sgblack@eecs.umich.edu /* Return the number of descriptors left in the ring, so the device has 3056717Sgblack@eecs.umich.edu * a way to figure out if it needs to interrupt. 30610037SARM gem5 Developers */ 30710037SARM gem5 Developers unsigned 30810037SARM gem5 Developers descLeft() const 30910037SARM gem5 Developers { 31010037SARM gem5 Developers unsigned left = unusedCache.size(); 31110037SARM gem5 Developers if (cachePnt > descTail()) 31210037SARM gem5 Developers left += (descLen() - cachePnt + descTail()); 31310037SARM gem5 Developers else 31410037SARM gem5 Developers left += (descTail() - cachePnt); 31510037SARM gem5 Developers 31610037SARM gem5 Developers return left; 3176717Sgblack@eecs.umich.edu } 3186717Sgblack@eecs.umich.edu 3196717Sgblack@eecs.umich.edu /* Return the number of descriptors used and not written back. 3206717Sgblack@eecs.umich.edu */ 32110037SARM gem5 Developers unsigned descUsed() const { return usedCache.size(); } 32210037SARM gem5 Developers 32310037SARM gem5 Developers /* Return the number of cache unused descriptors we have. */ 32410037SARM gem5 Developers unsigned descUnused() const { return unusedCache.size(); } 32510037SARM gem5 Developers 3266717Sgblack@eecs.umich.edu /* Get into a state where the descriptor address/head/etc colud be 3276717Sgblack@eecs.umich.edu * changed */ 3286717Sgblack@eecs.umich.edu void reset(); 3296717Sgblack@eecs.umich.edu 3306717Sgblack@eecs.umich.edu virtual void serialize(std::ostream &os); 3316717Sgblack@eecs.umich.edu virtual void unserialize(Checkpoint *cp, const std::string §ion); 3326717Sgblack@eecs.umich.edu 3336717Sgblack@eecs.umich.edu virtual bool hasOutstandingEvents() { 3346717Sgblack@eecs.umich.edu return wbEvent.scheduled() || fetchEvent.scheduled(); 33510037SARM gem5 Developers } 33610037SARM gem5 Developers 33710037SARM gem5 Developers }; 33810037SARM gem5 Developers 33910037SARM gem5 Developers 34010037SARM gem5 Developers class RxDescCache : public DescCache<iGbReg::RxDesc> 34110037SARM gem5 Developers { 34210037SARM gem5 Developers protected: 34310037SARM gem5 Developers virtual Addr descBase() const { return igbe->regs.rdba(); } 34410037SARM gem5 Developers virtual long descHead() const { return igbe->regs.rdh(); } 34510037SARM gem5 Developers virtual long descLen() const { return igbe->regs.rdlen() >> 4; } 34610037SARM gem5 Developers virtual long descTail() const { return igbe->regs.rdt(); } 34710037SARM gem5 Developers virtual void updateHead(long h) { igbe->regs.rdh(h); } 34810037SARM gem5 Developers virtual void enableSm(); 34910037SARM gem5 Developers virtual void fetchAfterWb() { 35010037SARM gem5 Developers if (!igbe->rxTick && igbe->getState() == SimObject::Running) 35110037SARM gem5 Developers fetchDescriptors(); 35210037SARM gem5 Developers } 3536717Sgblack@eecs.umich.edu 3546717Sgblack@eecs.umich.edu bool pktDone; 3556717Sgblack@eecs.umich.edu 3566717Sgblack@eecs.umich.edu /** Variable to head with header/data completion events */ 35710037SARM gem5 Developers int splitCount; 35810037SARM gem5 Developers 35910037SARM gem5 Developers /** Bytes of packet that have been copied, so we know when to 36010037SARM gem5 Developers set EOP */ 36110037SARM gem5 Developers unsigned bytesCopied; 3626717Sgblack@eecs.umich.edu 3636717Sgblack@eecs.umich.edu public: 3646717Sgblack@eecs.umich.edu RxDescCache(IGbE *i, std::string n, int s); 3656717Sgblack@eecs.umich.edu 3666717Sgblack@eecs.umich.edu /** Write the given packet into the buffer(s) pointed to by the 3676717Sgblack@eecs.umich.edu * descriptor and update the book keeping. Should only be called when 3686717Sgblack@eecs.umich.edu * there are no dma's pending. 3696717Sgblack@eecs.umich.edu * @param packet ethernet packet to write 3706717Sgblack@eecs.umich.edu * @param pkt_offset bytes already copied from the packet to memory 3716717Sgblack@eecs.umich.edu * @return pkt_offset + number of bytes copied during this call 3726717Sgblack@eecs.umich.edu */ 3736717Sgblack@eecs.umich.edu int writePacket(EthPacketPtr packet, int pkt_offset); 3746717Sgblack@eecs.umich.edu 37510037SARM gem5 Developers /** Called by event when dma to write packet is completed 37610037SARM gem5 Developers */ 37710037SARM gem5 Developers void pktComplete(); 37810037SARM gem5 Developers 37910037SARM gem5 Developers /** Check if the dma on the packet has completed and RX state machine 3806717Sgblack@eecs.umich.edu * can continue 3816717Sgblack@eecs.umich.edu */ 3826717Sgblack@eecs.umich.edu bool packetDone(); 3836717Sgblack@eecs.umich.edu 3846717Sgblack@eecs.umich.edu EventWrapper<RxDescCache, &RxDescCache::pktComplete> pktEvent; 3856717Sgblack@eecs.umich.edu 3866717Sgblack@eecs.umich.edu // Event to handle issuing header and data write at the same time 3876717Sgblack@eecs.umich.edu // and only callking pktComplete() when both are completed 3886717Sgblack@eecs.umich.edu void pktSplitDone(); 3896717Sgblack@eecs.umich.edu EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktHdrEvent; 3906717Sgblack@eecs.umich.edu EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktDataEvent; 3916717Sgblack@eecs.umich.edu 3926717Sgblack@eecs.umich.edu virtual bool hasOutstandingEvents(); 39310037SARM gem5 Developers 39410037SARM gem5 Developers virtual void serialize(std::ostream &os); 39510037SARM gem5 Developers virtual void unserialize(Checkpoint *cp, const std::string §ion); 39610037SARM gem5 Developers }; 39710037SARM gem5 Developers friend class RxDescCache; 3986717Sgblack@eecs.umich.edu 3996717Sgblack@eecs.umich.edu RxDescCache rxDescCache; 4006717Sgblack@eecs.umich.edu 4016717Sgblack@eecs.umich.edu class TxDescCache : public DescCache<iGbReg::TxDesc> 4026717Sgblack@eecs.umich.edu { 4036717Sgblack@eecs.umich.edu protected: 4046717Sgblack@eecs.umich.edu virtual Addr descBase() const { return igbe->regs.tdba(); } 4056717Sgblack@eecs.umich.edu virtual long descHead() const { return igbe->regs.tdh(); } 4066717Sgblack@eecs.umich.edu virtual long descTail() const { return igbe->regs.tdt(); } 4076717Sgblack@eecs.umich.edu virtual long descLen() const { return igbe->regs.tdlen() >> 4; } 4086717Sgblack@eecs.umich.edu virtual void updateHead(long h) { igbe->regs.tdh(h); } 4096717Sgblack@eecs.umich.edu virtual void enableSm(); 4106717Sgblack@eecs.umich.edu virtual void actionAfterWb(); 41110037SARM gem5 Developers virtual void fetchAfterWb() { 41210037SARM gem5 Developers if (!igbe->txTick && igbe->getState() == SimObject::Running) 41310037SARM gem5 Developers fetchDescriptors(); 41410037SARM gem5 Developers } 41510037SARM gem5 Developers 4166717Sgblack@eecs.umich.edu 4176717Sgblack@eecs.umich.edu 4186717Sgblack@eecs.umich.edu bool pktDone; 4196717Sgblack@eecs.umich.edu bool isTcp; 4206717Sgblack@eecs.umich.edu bool pktWaiting; 4216717Sgblack@eecs.umich.edu bool pktMultiDesc; 4226717Sgblack@eecs.umich.edu Addr completionAddress; 4236717Sgblack@eecs.umich.edu bool completionEnabled; 4246717Sgblack@eecs.umich.edu uint32_t descEnd; 4256717Sgblack@eecs.umich.edu 4266717Sgblack@eecs.umich.edu 4276717Sgblack@eecs.umich.edu // tso variables 4286717Sgblack@eecs.umich.edu bool useTso; 42910037SARM gem5 Developers Addr tsoHeaderLen; 43010037SARM gem5 Developers Addr tsoMss; 43110037SARM gem5 Developers Addr tsoTotalLen; 43210037SARM gem5 Developers Addr tsoUsedLen; 43310037SARM gem5 Developers Addr tsoPrevSeq; 4346717Sgblack@eecs.umich.edu Addr tsoPktPayloadBytes; 4356717Sgblack@eecs.umich.edu bool tsoLoadedHeader; 4366717Sgblack@eecs.umich.edu bool tsoPktHasHeader; 4376717Sgblack@eecs.umich.edu uint8_t tsoHeader[256]; 4386717Sgblack@eecs.umich.edu Addr tsoDescBytesUsed; 4396717Sgblack@eecs.umich.edu Addr tsoCopyBytes; 4406717Sgblack@eecs.umich.edu int tsoPkts; 4416717Sgblack@eecs.umich.edu 4426717Sgblack@eecs.umich.edu public: 4436717Sgblack@eecs.umich.edu TxDescCache(IGbE *i, std::string n, int s); 4446717Sgblack@eecs.umich.edu 4456717Sgblack@eecs.umich.edu /** Tell the cache to DMA a packet from main memory into its buffer and 4466717Sgblack@eecs.umich.edu * return the size the of the packet to reserve space in tx fifo. 44710037SARM gem5 Developers * @return size of the packet 44810037SARM gem5 Developers */ 44910037SARM gem5 Developers unsigned getPacketSize(EthPacketPtr p); 45010037SARM gem5 Developers void getPacketData(EthPacketPtr p); 45110037SARM gem5 Developers void processContextDesc(); 4526717Sgblack@eecs.umich.edu 4536717Sgblack@eecs.umich.edu /** Return the number of dsecriptors in a cache block for threshold 4546717Sgblack@eecs.umich.edu * operations. 4556717Sgblack@eecs.umich.edu */ 4566717Sgblack@eecs.umich.edu unsigned 4576717Sgblack@eecs.umich.edu descInBlock(unsigned num_desc) 4586717Sgblack@eecs.umich.edu { 4596717Sgblack@eecs.umich.edu return num_desc / igbe->cacheBlockSize() / sizeof(iGbReg::TxDesc); 4606717Sgblack@eecs.umich.edu } 4617310Sgblack@eecs.umich.edu 4627310Sgblack@eecs.umich.edu /** Ask if the packet has been transfered so the state machine can give 4637310Sgblack@eecs.umich.edu * it to the fifo. 4647310Sgblack@eecs.umich.edu * @return packet available in descriptor cache 4656726Sgblack@eecs.umich.edu */ 4667310Sgblack@eecs.umich.edu bool packetAvailable(); 4677310Sgblack@eecs.umich.edu 4686726Sgblack@eecs.umich.edu /** Ask if we are still waiting for the packet to be transfered. 4696726Sgblack@eecs.umich.edu * @return packet still in transit. 47010037SARM gem5 Developers */ 47110037SARM gem5 Developers bool packetWaiting() { return pktWaiting; } 47210037SARM gem5 Developers 47310037SARM gem5 Developers /** Ask if this packet is composed of multiple descriptors 47410037SARM gem5 Developers * so even if we've got data, we need to wait for more before 47510037SARM gem5 Developers * we can send it out. 47610037SARM gem5 Developers * @return packet can't be sent out because it's a multi-descriptor 47710037SARM gem5 Developers * packet 47810037SARM gem5 Developers */ 47910037SARM gem5 Developers bool packetMultiDesc() { return pktMultiDesc;} 48010037SARM gem5 Developers 48110037SARM gem5 Developers /** Called by event when dma to write packet is completed 48210037SARM gem5 Developers */ 48310037SARM gem5 Developers void pktComplete(); 48410037SARM gem5 Developers EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent; 48510037SARM gem5 Developers 48610037SARM gem5 Developers void headerComplete(); 48710037SARM gem5 Developers EventWrapper<TxDescCache, &TxDescCache::headerComplete> headerEvent; 48810037SARM gem5 Developers 48910037SARM gem5 Developers 49010037SARM gem5 Developers void completionWriteback(Addr a, bool enabled) { 49110037SARM gem5 Developers DPRINTF(EthernetDesc, 49210037SARM gem5 Developers "Completion writeback Addr: %#x enabled: %d\n", 49310037SARM gem5 Developers a, enabled); 49410037SARM gem5 Developers completionAddress = a; 49510037SARM gem5 Developers completionEnabled = enabled; 49610037SARM gem5 Developers } 49710037SARM gem5 Developers 49810037SARM gem5 Developers virtual bool hasOutstandingEvents(); 49910037SARM gem5 Developers 50010037SARM gem5 Developers void nullCallback() { 50110037SARM gem5 Developers DPRINTF(EthernetDesc, "Completion writeback complete\n"); 50210037SARM gem5 Developers } 50310037SARM gem5 Developers EventWrapper<TxDescCache, &TxDescCache::nullCallback> nullEvent; 50410037SARM gem5 Developers 50510037SARM gem5 Developers virtual void serialize(std::ostream &os); 50610037SARM gem5 Developers virtual void unserialize(Checkpoint *cp, const std::string §ion); 50710037SARM gem5 Developers 50810337SAndrew.Bardsley@arm.com }; 50910337SAndrew.Bardsley@arm.com friend class TxDescCache; 51010337SAndrew.Bardsley@arm.com 51110337SAndrew.Bardsley@arm.com TxDescCache txDescCache; 51210337SAndrew.Bardsley@arm.com 51310337SAndrew.Bardsley@arm.com public: 51410337SAndrew.Bardsley@arm.com typedef IGbEParams Params; 51510037SARM gem5 Developers const Params * 51610037SARM gem5 Developers params() const { 51710037SARM gem5 Developers return dynamic_cast<const Params *>(_params); 51810037SARM gem5 Developers } 51910037SARM gem5 Developers 52010037SARM gem5 Developers IGbE(const Params *params); 52110037SARM gem5 Developers ~IGbE() {} 5226717Sgblack@eecs.umich.edu virtual void init(); 5236717Sgblack@eecs.umich.edu 5246717Sgblack@eecs.umich.edu virtual EtherInt *getEthPort(const std::string &if_name, int idx); 525 526 Tick clock; 527 Tick lastInterrupt; 528 inline Tick ticks(int numCycles) const { return numCycles * clock; } 529 530 virtual Tick read(PacketPtr pkt); 531 virtual Tick write(PacketPtr pkt); 532 533 virtual Tick writeConfig(PacketPtr pkt); 534 535 bool ethRxPkt(EthPacketPtr packet); 536 void ethTxDone(); 537 538 virtual void serialize(std::ostream &os); 539 virtual void unserialize(Checkpoint *cp, const std::string §ion); 540 virtual unsigned int drain(Event *de); 541 virtual void resume(); 542 543}; 544 545class IGbEInt : public EtherInt 546{ 547 private: 548 IGbE *dev; 549 550 public: 551 IGbEInt(const std::string &name, IGbE *d) 552 : EtherInt(name), dev(d) 553 { } 554 555 virtual bool recvPacket(EthPacketPtr pkt) { return dev->ethRxPkt(pkt); } 556 virtual void sendDone() { dev->ethTxDone(); } 557}; 558 559#endif //__DEV_I8254XGBE_HH__ 560