i8254xGBe.hh revision 9342
17375Sgblack@eecs.umich.edu/* 27375Sgblack@eecs.umich.edu * Copyright (c) 2006 The Regents of The University of Michigan 37375Sgblack@eecs.umich.edu * All rights reserved. 47375Sgblack@eecs.umich.edu * 57375Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67375Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77375Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87375Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97375Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107375Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117375Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127375Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137375Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147375Sgblack@eecs.umich.edu * this software without specific prior written permission. 157375Sgblack@eecs.umich.edu * 167375Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177375Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187375Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197375Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207375Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217375Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227375Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237375Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247375Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257375Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267375Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277375Sgblack@eecs.umich.edu * 287375Sgblack@eecs.umich.edu * Authors: Ali Saidi 297375Sgblack@eecs.umich.edu */ 307375Sgblack@eecs.umich.edu 317375Sgblack@eecs.umich.edu/* @file 327375Sgblack@eecs.umich.edu * Device model for Intel's 8254x line of gigabit ethernet controllers. 337375Sgblack@eecs.umich.edu */ 347375Sgblack@eecs.umich.edu 357375Sgblack@eecs.umich.edu#ifndef __DEV_I8254XGBE_HH__ 367375Sgblack@eecs.umich.edu#define __DEV_I8254XGBE_HH__ 377375Sgblack@eecs.umich.edu 387375Sgblack@eecs.umich.edu#include <deque> 397375Sgblack@eecs.umich.edu#include <string> 407375Sgblack@eecs.umich.edu 417375Sgblack@eecs.umich.edu#include "base/cp_annotate.hh" 427375Sgblack@eecs.umich.edu#include "base/inet.hh" 437375Sgblack@eecs.umich.edu#include "debug/EthernetDesc.hh" 447378Sgblack@eecs.umich.edu#include "debug/EthernetIntr.hh" 457378Sgblack@eecs.umich.edu#include "dev/etherdevice.hh" 467382Sgblack@eecs.umich.edu#include "dev/etherint.hh" 477375Sgblack@eecs.umich.edu#include "dev/etherpkt.hh" 487384Sgblack@eecs.umich.edu#include "dev/i8254xGBe_defs.hh" 497384Sgblack@eecs.umich.edu#include "dev/pcidev.hh" 507384Sgblack@eecs.umich.edu#include "dev/pktfifo.hh" 517375Sgblack@eecs.umich.edu#include "params/IGbE.hh" 527375Sgblack@eecs.umich.edu#include "sim/eventq.hh" 537375Sgblack@eecs.umich.edu 547375Sgblack@eecs.umich.educlass IGbEInt; 557375Sgblack@eecs.umich.edu 567375Sgblack@eecs.umich.educlass IGbE : public EtherDevice 577375Sgblack@eecs.umich.edu{ 587375Sgblack@eecs.umich.edu private: 597375Sgblack@eecs.umich.edu IGbEInt *etherInt; 607375Sgblack@eecs.umich.edu CPA *cpa; 617375Sgblack@eecs.umich.edu 627375Sgblack@eecs.umich.edu // device registers 637375Sgblack@eecs.umich.edu iGbReg::Regs regs; 647375Sgblack@eecs.umich.edu 657375Sgblack@eecs.umich.edu // eeprom data, status and control bits 667375Sgblack@eecs.umich.edu int eeOpBits, eeAddrBits, eeDataBits; 677375Sgblack@eecs.umich.edu uint8_t eeOpcode, eeAddr; 687375Sgblack@eecs.umich.edu uint16_t flash[iGbReg::EEPROM_SIZE]; 697375Sgblack@eecs.umich.edu 707375Sgblack@eecs.umich.edu // The drain event if we have one 717375Sgblack@eecs.umich.edu DrainManager *drainManager; 727375Sgblack@eecs.umich.edu 737375Sgblack@eecs.umich.edu // cached parameters from params struct 747375Sgblack@eecs.umich.edu bool useFlowControl; 757375Sgblack@eecs.umich.edu 767375Sgblack@eecs.umich.edu // packet fifos 777376Sgblack@eecs.umich.edu PacketFifo rxFifo; 787376Sgblack@eecs.umich.edu PacketFifo txFifo; 797376Sgblack@eecs.umich.edu 807375Sgblack@eecs.umich.edu // Packet that we are currently putting into the txFifo 817375Sgblack@eecs.umich.edu EthPacketPtr txPacket; 827378Sgblack@eecs.umich.edu 837378Sgblack@eecs.umich.edu // Should to Rx/Tx State machine tick? 847378Sgblack@eecs.umich.edu bool rxTick; 857378Sgblack@eecs.umich.edu bool txTick; 867378Sgblack@eecs.umich.edu bool txFifoTick; 877378Sgblack@eecs.umich.edu 887378Sgblack@eecs.umich.edu bool rxDmaPacket; 897378Sgblack@eecs.umich.edu 907378Sgblack@eecs.umich.edu // Number of bytes copied from current RX packet 917378Sgblack@eecs.umich.edu unsigned pktOffset; 927378Sgblack@eecs.umich.edu 937378Sgblack@eecs.umich.edu // Delays in managaging descriptors 947378Sgblack@eecs.umich.edu Tick fetchDelay, wbDelay; 957378Sgblack@eecs.umich.edu Tick fetchCompDelay, wbCompDelay; 967378Sgblack@eecs.umich.edu Tick rxWriteDelay, txReadDelay; 977378Sgblack@eecs.umich.edu 987378Sgblack@eecs.umich.edu // Event and function to deal with RDTR timer expiring 997378Sgblack@eecs.umich.edu void rdtrProcess() { 1007378Sgblack@eecs.umich.edu rxDescCache.writeback(0); 1017378Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, 1027378Sgblack@eecs.umich.edu "Posting RXT interrupt because RDTR timer expired\n"); 1037378Sgblack@eecs.umich.edu postInterrupt(iGbReg::IT_RXT); 1047378Sgblack@eecs.umich.edu } 1057378Sgblack@eecs.umich.edu 1067378Sgblack@eecs.umich.edu //friend class EventWrapper<IGbE, &IGbE::rdtrProcess>; 1077378Sgblack@eecs.umich.edu EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent; 1087382Sgblack@eecs.umich.edu 1097396Sgblack@eecs.umich.edu // Event and function to deal with RADV timer expiring 1107396Sgblack@eecs.umich.edu void radvProcess() { 1117396Sgblack@eecs.umich.edu rxDescCache.writeback(0); 1127396Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, 1137396Sgblack@eecs.umich.edu "Posting RXT interrupt because RADV timer expired\n"); 1147396Sgblack@eecs.umich.edu postInterrupt(iGbReg::IT_RXT); 1157396Sgblack@eecs.umich.edu } 1167396Sgblack@eecs.umich.edu 1177396Sgblack@eecs.umich.edu //friend class EventWrapper<IGbE, &IGbE::radvProcess>; 1187396Sgblack@eecs.umich.edu EventWrapper<IGbE, &IGbE::radvProcess> radvEvent; 1197396Sgblack@eecs.umich.edu 1207396Sgblack@eecs.umich.edu // Event and function to deal with TADV timer expiring 1217396Sgblack@eecs.umich.edu void tadvProcess() { 1227396Sgblack@eecs.umich.edu txDescCache.writeback(0); 1237396Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, 1247396Sgblack@eecs.umich.edu "Posting TXDW interrupt because TADV timer expired\n"); 1257396Sgblack@eecs.umich.edu postInterrupt(iGbReg::IT_TXDW); 1267396Sgblack@eecs.umich.edu } 1277396Sgblack@eecs.umich.edu 1287396Sgblack@eecs.umich.edu //friend class EventWrapper<IGbE, &IGbE::tadvProcess>; 1297396Sgblack@eecs.umich.edu EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent; 1307397Sgblack@eecs.umich.edu 1317397Sgblack@eecs.umich.edu // Event and function to deal with TIDV timer expiring 1327397Sgblack@eecs.umich.edu void tidvProcess() { 1337397Sgblack@eecs.umich.edu txDescCache.writeback(0); 1347397Sgblack@eecs.umich.edu DPRINTF(EthernetIntr, 1357397Sgblack@eecs.umich.edu "Posting TXDW interrupt because TIDV timer expired\n"); 1367397Sgblack@eecs.umich.edu postInterrupt(iGbReg::IT_TXDW); 1377397Sgblack@eecs.umich.edu } 1387397Sgblack@eecs.umich.edu //friend class EventWrapper<IGbE, &IGbE::tidvProcess>; 1397397Sgblack@eecs.umich.edu EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent; 1407397Sgblack@eecs.umich.edu 1417397Sgblack@eecs.umich.edu // Main event to tick the device 1427397Sgblack@eecs.umich.edu void tick(); 1437397Sgblack@eecs.umich.edu //friend class EventWrapper<IGbE, &IGbE::tick>; 1447397Sgblack@eecs.umich.edu EventWrapper<IGbE, &IGbE::tick> tickEvent; 1457397Sgblack@eecs.umich.edu 1467397Sgblack@eecs.umich.edu 1477384Sgblack@eecs.umich.edu uint64_t macAddr; 1487384Sgblack@eecs.umich.edu 1497384Sgblack@eecs.umich.edu void rxStateMachine(); 1507384Sgblack@eecs.umich.edu void txStateMachine(); 1517384Sgblack@eecs.umich.edu void txWire(); 1527384Sgblack@eecs.umich.edu 1537384Sgblack@eecs.umich.edu /** Write an interrupt into the interrupt pending register and check mask 1547384Sgblack@eecs.umich.edu * and interrupt limit timer before sending interrupt to CPU 1557384Sgblack@eecs.umich.edu * @param t the type of interrupt we are posting 1567384Sgblack@eecs.umich.edu * @param now should we ignore the interrupt limiting timer 1577384Sgblack@eecs.umich.edu */ 1587384Sgblack@eecs.umich.edu void postInterrupt(iGbReg::IntTypes t, bool now = false); 1597384Sgblack@eecs.umich.edu 1607384Sgblack@eecs.umich.edu /** Check and see if changes to the mask register have caused an interrupt 1617384Sgblack@eecs.umich.edu * to need to be sent or perhaps removed an interrupt cause. 1627384Sgblack@eecs.umich.edu */ 1637384Sgblack@eecs.umich.edu void chkInterrupt(); 1647384Sgblack@eecs.umich.edu 1657384Sgblack@eecs.umich.edu /** Send an interrupt to the cpu 1667384Sgblack@eecs.umich.edu */ 1677384Sgblack@eecs.umich.edu void delayIntEvent(); 1687384Sgblack@eecs.umich.edu void cpuPostInt(); 1697384Sgblack@eecs.umich.edu // Event to moderate interrupts 1707384Sgblack@eecs.umich.edu EventWrapper<IGbE, &IGbE::delayIntEvent> interEvent; 1717384Sgblack@eecs.umich.edu 1727384Sgblack@eecs.umich.edu /** Clear the interupt line to the cpu 1737384Sgblack@eecs.umich.edu */ 1747384Sgblack@eecs.umich.edu void cpuClearInt(); 1757384Sgblack@eecs.umich.edu 1767384Sgblack@eecs.umich.edu Tick intClock() { return SimClock::Int::ns * 1024; } 1777384Sgblack@eecs.umich.edu 1787384Sgblack@eecs.umich.edu /** This function is used to restart the clock so it can handle things like 1797384Sgblack@eecs.umich.edu * draining and resume in one place. */ 1807384Sgblack@eecs.umich.edu void restartClock(); 1817384Sgblack@eecs.umich.edu 1827384Sgblack@eecs.umich.edu /** Check if all the draining things that need to occur have occured and 1837384Sgblack@eecs.umich.edu * handle the drain event if so. 1847384Sgblack@eecs.umich.edu */ 1857384Sgblack@eecs.umich.edu void checkDrain(); 1867384Sgblack@eecs.umich.edu 1877384Sgblack@eecs.umich.edu void anBegin(std::string sm, std::string st, int flags = CPA::FL_NONE) { 1887384Sgblack@eecs.umich.edu cpa->hwBegin((CPA::flags)flags, sys, macAddr, sm, st); 1897384Sgblack@eecs.umich.edu } 1907384Sgblack@eecs.umich.edu 1917384Sgblack@eecs.umich.edu void anQ(std::string sm, std::string q) { 1927384Sgblack@eecs.umich.edu cpa->hwQ(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); 1937384Sgblack@eecs.umich.edu } 1947384Sgblack@eecs.umich.edu 1957396Sgblack@eecs.umich.edu void anDq(std::string sm, std::string q) { 1967396Sgblack@eecs.umich.edu cpa->hwDq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); 1977396Sgblack@eecs.umich.edu } 1987396Sgblack@eecs.umich.edu 1997396Sgblack@eecs.umich.edu void anPq(std::string sm, std::string q, int num = 1) { 2007396Sgblack@eecs.umich.edu cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num); 2017396Sgblack@eecs.umich.edu } 2027396Sgblack@eecs.umich.edu 2037396Sgblack@eecs.umich.edu void anRq(std::string sm, std::string q, int num = 1) { 2047396Sgblack@eecs.umich.edu cpa->hwRq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num); 2057396Sgblack@eecs.umich.edu } 2067396Sgblack@eecs.umich.edu 2077396Sgblack@eecs.umich.edu void anWe(std::string sm, std::string q) { 2087396Sgblack@eecs.umich.edu cpa->hwWe(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); 2097396Sgblack@eecs.umich.edu } 2107396Sgblack@eecs.umich.edu 2117396Sgblack@eecs.umich.edu void anWf(std::string sm, std::string q) { 2127396Sgblack@eecs.umich.edu cpa->hwWf(CPA::FL_NONE, sys, macAddr, sm, q, macAddr); 2137396Sgblack@eecs.umich.edu } 2147396Sgblack@eecs.umich.edu 2157396Sgblack@eecs.umich.edu 2167396Sgblack@eecs.umich.edu template<class T> 2177396Sgblack@eecs.umich.edu class DescCache 2187396Sgblack@eecs.umich.edu { 2197396Sgblack@eecs.umich.edu protected: 2207396Sgblack@eecs.umich.edu virtual Addr descBase() const = 0; 2217396Sgblack@eecs.umich.edu virtual long descHead() const = 0; 2227396Sgblack@eecs.umich.edu virtual long descTail() const = 0; 2237396Sgblack@eecs.umich.edu virtual long descLen() const = 0; 2247396Sgblack@eecs.umich.edu virtual void updateHead(long h) = 0; 2257396Sgblack@eecs.umich.edu virtual void enableSm() = 0; 2267396Sgblack@eecs.umich.edu virtual void actionAfterWb() {} 2277396Sgblack@eecs.umich.edu virtual void fetchAfterWb() = 0; 2287396Sgblack@eecs.umich.edu 2297396Sgblack@eecs.umich.edu typedef std::deque<T *> CacheType; 2307396Sgblack@eecs.umich.edu CacheType usedCache; 2317396Sgblack@eecs.umich.edu CacheType unusedCache; 2327396Sgblack@eecs.umich.edu 2337396Sgblack@eecs.umich.edu T *fetchBuf; 2347396Sgblack@eecs.umich.edu T *wbBuf; 2357396Sgblack@eecs.umich.edu 2367396Sgblack@eecs.umich.edu // Pointer to the device we cache for 2377396Sgblack@eecs.umich.edu IGbE *igbe; 2387396Sgblack@eecs.umich.edu 2397396Sgblack@eecs.umich.edu // Name of this descriptor cache 2407396Sgblack@eecs.umich.edu std::string _name; 2417396Sgblack@eecs.umich.edu 2427396Sgblack@eecs.umich.edu // How far we've cached 2437384Sgblack@eecs.umich.edu int cachePnt; 2447384Sgblack@eecs.umich.edu 2457386Sgblack@eecs.umich.edu // The size of the descriptor cache 2467386Sgblack@eecs.umich.edu int size; 2477386Sgblack@eecs.umich.edu 2487386Sgblack@eecs.umich.edu // How many descriptors we are currently fetching 2497386Sgblack@eecs.umich.edu int curFetching; 2507386Sgblack@eecs.umich.edu 2517386Sgblack@eecs.umich.edu // How many descriptors we are currently writing back 2527386Sgblack@eecs.umich.edu int wbOut; 2537386Sgblack@eecs.umich.edu 2547386Sgblack@eecs.umich.edu // if the we wrote back to the end of the descriptor ring and are going 2557386Sgblack@eecs.umich.edu // to have to wrap and write more 2567386Sgblack@eecs.umich.edu bool moreToWb; 2577386Sgblack@eecs.umich.edu 2587386Sgblack@eecs.umich.edu // What the alignment is of the next descriptor writeback 2597386Sgblack@eecs.umich.edu Addr wbAlignment; 2607386Sgblack@eecs.umich.edu 2617386Sgblack@eecs.umich.edu /** The packet that is currently being dmad to memory if any */ 2627396Sgblack@eecs.umich.edu EthPacketPtr pktPtr; 2637386Sgblack@eecs.umich.edu 2647386Sgblack@eecs.umich.edu /** Shortcut for DMA address translation */ 2657386Sgblack@eecs.umich.edu Addr pciToDma(Addr a) { return igbe->platform->pciToDma(a); } 2667386Sgblack@eecs.umich.edu 2677386Sgblack@eecs.umich.edu public: 2687386Sgblack@eecs.umich.edu /** Annotate sm*/ 2697386Sgblack@eecs.umich.edu std::string annSmFetch, annSmWb, annUnusedDescQ, annUsedCacheQ, 2707385Sgblack@eecs.umich.edu annUsedDescQ, annUnusedCacheQ, annDescQ; 2717384Sgblack@eecs.umich.edu 2727385Sgblack@eecs.umich.edu DescCache(IGbE *i, const std::string n, int s); 2737385Sgblack@eecs.umich.edu virtual ~DescCache(); 2747385Sgblack@eecs.umich.edu 2757384Sgblack@eecs.umich.edu std::string name() { return _name; } 2767384Sgblack@eecs.umich.edu 2777384Sgblack@eecs.umich.edu /** If the address/len/head change when we've got descriptors that are 2787384Sgblack@eecs.umich.edu * dirty that is very bad. This function checks that we don't and if we 2797384Sgblack@eecs.umich.edu * do panics. 2807384Sgblack@eecs.umich.edu */ 2817384Sgblack@eecs.umich.edu void areaChanged(); 2827384Sgblack@eecs.umich.edu 2837384Sgblack@eecs.umich.edu void writeback(Addr aMask); 2847384Sgblack@eecs.umich.edu void writeback1(); 2857384Sgblack@eecs.umich.edu EventWrapper<DescCache, &DescCache::writeback1> wbDelayEvent; 2867384Sgblack@eecs.umich.edu 2877384Sgblack@eecs.umich.edu /** Fetch a chunk of descriptors into the descriptor cache. 2887384Sgblack@eecs.umich.edu * Calls fetchComplete when the memory system returns the data 2897384Sgblack@eecs.umich.edu */ 2907384Sgblack@eecs.umich.edu void fetchDescriptors(); 2917384Sgblack@eecs.umich.edu void fetchDescriptors1(); 2927385Sgblack@eecs.umich.edu EventWrapper<DescCache, &DescCache::fetchDescriptors1> fetchDelayEvent; 2937385Sgblack@eecs.umich.edu 2947385Sgblack@eecs.umich.edu /** Called by event when dma to read descriptors is completed 2957385Sgblack@eecs.umich.edu */ 2967396Sgblack@eecs.umich.edu void fetchComplete(); 2977385Sgblack@eecs.umich.edu EventWrapper<DescCache, &DescCache::fetchComplete> fetchEvent; 2987384Sgblack@eecs.umich.edu 2997384Sgblack@eecs.umich.edu /** Called by event when dma to writeback descriptors is completed 3007384Sgblack@eecs.umich.edu */ 3017384Sgblack@eecs.umich.edu void wbComplete(); 3027386Sgblack@eecs.umich.edu EventWrapper<DescCache, &DescCache::wbComplete> wbEvent; 3037386Sgblack@eecs.umich.edu 3047386Sgblack@eecs.umich.edu /* Return the number of descriptors left in the ring, so the device has 3057386Sgblack@eecs.umich.edu * a way to figure out if it needs to interrupt. 3067386Sgblack@eecs.umich.edu */ 3077386Sgblack@eecs.umich.edu unsigned 3087386Sgblack@eecs.umich.edu descLeft() const 3097386Sgblack@eecs.umich.edu { 3107386Sgblack@eecs.umich.edu unsigned left = unusedCache.size(); 3117386Sgblack@eecs.umich.edu if (cachePnt > descTail()) 3127386Sgblack@eecs.umich.edu left += (descLen() - cachePnt + descTail()); 3137386Sgblack@eecs.umich.edu else 3147386Sgblack@eecs.umich.edu left += (descTail() - cachePnt); 3157386Sgblack@eecs.umich.edu 3167386Sgblack@eecs.umich.edu return left; 3177386Sgblack@eecs.umich.edu } 3187386Sgblack@eecs.umich.edu 3197396Sgblack@eecs.umich.edu /* Return the number of descriptors used and not written back. 3207386Sgblack@eecs.umich.edu */ 3217396Sgblack@eecs.umich.edu unsigned descUsed() const { return usedCache.size(); } 3227396Sgblack@eecs.umich.edu 3237396Sgblack@eecs.umich.edu /* Return the number of cache unused descriptors we have. */ 3247396Sgblack@eecs.umich.edu unsigned descUnused() const { return unusedCache.size(); } 3257386Sgblack@eecs.umich.edu 3267386Sgblack@eecs.umich.edu /* Get into a state where the descriptor address/head/etc colud be 3277386Sgblack@eecs.umich.edu * changed */ 3287386Sgblack@eecs.umich.edu void reset(); 3297386Sgblack@eecs.umich.edu 3307386Sgblack@eecs.umich.edu virtual void serialize(std::ostream &os); 3317386Sgblack@eecs.umich.edu virtual void unserialize(Checkpoint *cp, const std::string §ion); 3327386Sgblack@eecs.umich.edu 3337386Sgblack@eecs.umich.edu virtual bool hasOutstandingEvents() { 3347386Sgblack@eecs.umich.edu return wbEvent.scheduled() || fetchEvent.scheduled(); 3357386Sgblack@eecs.umich.edu } 3367386Sgblack@eecs.umich.edu 3377386Sgblack@eecs.umich.edu }; 3387386Sgblack@eecs.umich.edu 3397386Sgblack@eecs.umich.edu 3407386Sgblack@eecs.umich.edu class RxDescCache : public DescCache<iGbReg::RxDesc> 3417386Sgblack@eecs.umich.edu { 3427386Sgblack@eecs.umich.edu protected: 3437386Sgblack@eecs.umich.edu virtual Addr descBase() const { return igbe->regs.rdba(); } 3447396Sgblack@eecs.umich.edu virtual long descHead() const { return igbe->regs.rdh(); } 3457396Sgblack@eecs.umich.edu virtual long descLen() const { return igbe->regs.rdlen() >> 4; } 3467396Sgblack@eecs.umich.edu virtual long descTail() const { return igbe->regs.rdt(); } 3477396Sgblack@eecs.umich.edu virtual void updateHead(long h) { igbe->regs.rdh(h); } 3487386Sgblack@eecs.umich.edu virtual void enableSm(); 3497386Sgblack@eecs.umich.edu virtual void fetchAfterWb() { 3507386Sgblack@eecs.umich.edu if (!igbe->rxTick && igbe->getDrainState() == Drainable::Running) 3517386Sgblack@eecs.umich.edu fetchDescriptors(); 3527386Sgblack@eecs.umich.edu } 3537386Sgblack@eecs.umich.edu 3547386Sgblack@eecs.umich.edu bool pktDone; 3557396Sgblack@eecs.umich.edu 3567386Sgblack@eecs.umich.edu /** Variable to head with header/data completion events */ 3577396Sgblack@eecs.umich.edu int splitCount; 3587396Sgblack@eecs.umich.edu 3597396Sgblack@eecs.umich.edu /** Bytes of packet that have been copied, so we know when to 3607396Sgblack@eecs.umich.edu set EOP */ 3617386Sgblack@eecs.umich.edu unsigned bytesCopied; 3627386Sgblack@eecs.umich.edu 3637386Sgblack@eecs.umich.edu public: 3647386Sgblack@eecs.umich.edu RxDescCache(IGbE *i, std::string n, int s); 3657386Sgblack@eecs.umich.edu 3667386Sgblack@eecs.umich.edu /** Write the given packet into the buffer(s) pointed to by the 3677396Sgblack@eecs.umich.edu * descriptor and update the book keeping. Should only be called when 3687396Sgblack@eecs.umich.edu * there are no dma's pending. 3697396Sgblack@eecs.umich.edu * @param packet ethernet packet to write 3707396Sgblack@eecs.umich.edu * @param pkt_offset bytes already copied from the packet to memory 3717396Sgblack@eecs.umich.edu * @return pkt_offset + number of bytes copied during this call 3727396Sgblack@eecs.umich.edu */ 3737396Sgblack@eecs.umich.edu int writePacket(EthPacketPtr packet, int pkt_offset); 3747396Sgblack@eecs.umich.edu 3757396Sgblack@eecs.umich.edu /** Called by event when dma to write packet is completed 3767396Sgblack@eecs.umich.edu */ 3777396Sgblack@eecs.umich.edu void pktComplete(); 3787396Sgblack@eecs.umich.edu 3797396Sgblack@eecs.umich.edu /** Check if the dma on the packet has completed and RX state machine 3807396Sgblack@eecs.umich.edu * can continue 3817396Sgblack@eecs.umich.edu */ 3827396Sgblack@eecs.umich.edu bool packetDone(); 3837396Sgblack@eecs.umich.edu 3847396Sgblack@eecs.umich.edu EventWrapper<RxDescCache, &RxDescCache::pktComplete> pktEvent; 3857396Sgblack@eecs.umich.edu 3867396Sgblack@eecs.umich.edu // Event to handle issuing header and data write at the same time 3877396Sgblack@eecs.umich.edu // and only callking pktComplete() when both are completed 3887396Sgblack@eecs.umich.edu void pktSplitDone(); 3897396Sgblack@eecs.umich.edu EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktHdrEvent; 3907396Sgblack@eecs.umich.edu EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktDataEvent; 3917396Sgblack@eecs.umich.edu 3927396Sgblack@eecs.umich.edu virtual bool hasOutstandingEvents(); 3937396Sgblack@eecs.umich.edu 3947396Sgblack@eecs.umich.edu virtual void serialize(std::ostream &os); 3957396Sgblack@eecs.umich.edu virtual void unserialize(Checkpoint *cp, const std::string §ion); 3967396Sgblack@eecs.umich.edu }; 3977396Sgblack@eecs.umich.edu friend class RxDescCache; 3987396Sgblack@eecs.umich.edu 3997398Sgblack@eecs.umich.edu RxDescCache rxDescCache; 4007398Sgblack@eecs.umich.edu 4017398Sgblack@eecs.umich.edu class TxDescCache : public DescCache<iGbReg::TxDesc> 4027398Sgblack@eecs.umich.edu { 4037398Sgblack@eecs.umich.edu protected: 4047398Sgblack@eecs.umich.edu virtual Addr descBase() const { return igbe->regs.tdba(); } 4057398Sgblack@eecs.umich.edu virtual long descHead() const { return igbe->regs.tdh(); } 4067398Sgblack@eecs.umich.edu virtual long descTail() const { return igbe->regs.tdt(); } 4077398Sgblack@eecs.umich.edu virtual long descLen() const { return igbe->regs.tdlen() >> 4; } 4087398Sgblack@eecs.umich.edu virtual void updateHead(long h) { igbe->regs.tdh(h); } 4097398Sgblack@eecs.umich.edu virtual void enableSm(); 4107398Sgblack@eecs.umich.edu virtual void actionAfterWb(); 4117398Sgblack@eecs.umich.edu virtual void fetchAfterWb() { 4127398Sgblack@eecs.umich.edu if (!igbe->txTick && igbe->getDrainState() == Drainable::Running) 4137398Sgblack@eecs.umich.edu fetchDescriptors(); 4147398Sgblack@eecs.umich.edu } 4157398Sgblack@eecs.umich.edu 4167398Sgblack@eecs.umich.edu 4177398Sgblack@eecs.umich.edu 4187398Sgblack@eecs.umich.edu bool pktDone; 4197398Sgblack@eecs.umich.edu bool isTcp; 4207398Sgblack@eecs.umich.edu bool pktWaiting; 4217398Sgblack@eecs.umich.edu bool pktMultiDesc; 4227398Sgblack@eecs.umich.edu Addr completionAddress; 4237398Sgblack@eecs.umich.edu bool completionEnabled; 4247398Sgblack@eecs.umich.edu uint32_t descEnd; 4257398Sgblack@eecs.umich.edu 4267398Sgblack@eecs.umich.edu 4277398Sgblack@eecs.umich.edu // tso variables 4287398Sgblack@eecs.umich.edu bool useTso; 4297398Sgblack@eecs.umich.edu Addr tsoHeaderLen; 4307398Sgblack@eecs.umich.edu Addr tsoMss; 4317398Sgblack@eecs.umich.edu Addr tsoTotalLen; 4327398Sgblack@eecs.umich.edu Addr tsoUsedLen; 4337398Sgblack@eecs.umich.edu Addr tsoPrevSeq; 4347398Sgblack@eecs.umich.edu Addr tsoPktPayloadBytes; 4357398Sgblack@eecs.umich.edu bool tsoLoadedHeader; 4367398Sgblack@eecs.umich.edu bool tsoPktHasHeader; 4377398Sgblack@eecs.umich.edu uint8_t tsoHeader[256]; 4387398Sgblack@eecs.umich.edu Addr tsoDescBytesUsed; 4397398Sgblack@eecs.umich.edu Addr tsoCopyBytes; 4407398Sgblack@eecs.umich.edu int tsoPkts; 4417398Sgblack@eecs.umich.edu 4427398Sgblack@eecs.umich.edu public: 4437398Sgblack@eecs.umich.edu TxDescCache(IGbE *i, std::string n, int s); 4447398Sgblack@eecs.umich.edu 4457398Sgblack@eecs.umich.edu /** Tell the cache to DMA a packet from main memory into its buffer and 4467398Sgblack@eecs.umich.edu * return the size the of the packet to reserve space in tx fifo. 4477398Sgblack@eecs.umich.edu * @return size of the packet 4487398Sgblack@eecs.umich.edu */ 4497398Sgblack@eecs.umich.edu unsigned getPacketSize(EthPacketPtr p); 4507398Sgblack@eecs.umich.edu void getPacketData(EthPacketPtr p); 4517398Sgblack@eecs.umich.edu void processContextDesc(); 4527398Sgblack@eecs.umich.edu 4537398Sgblack@eecs.umich.edu /** Return the number of dsecriptors in a cache block for threshold 4547398Sgblack@eecs.umich.edu * operations. 4557398Sgblack@eecs.umich.edu */ 4567398Sgblack@eecs.umich.edu unsigned 4577398Sgblack@eecs.umich.edu descInBlock(unsigned num_desc) 4587398Sgblack@eecs.umich.edu { 4597398Sgblack@eecs.umich.edu return num_desc / igbe->cacheBlockSize() / sizeof(iGbReg::TxDesc); 4607398Sgblack@eecs.umich.edu } 4617398Sgblack@eecs.umich.edu 4627398Sgblack@eecs.umich.edu /** Ask if the packet has been transfered so the state machine can give 4637398Sgblack@eecs.umich.edu * it to the fifo. 4647398Sgblack@eecs.umich.edu * @return packet available in descriptor cache 4657398Sgblack@eecs.umich.edu */ 4667398Sgblack@eecs.umich.edu bool packetAvailable(); 4677398Sgblack@eecs.umich.edu 4687398Sgblack@eecs.umich.edu /** Ask if we are still waiting for the packet to be transfered. 4697398Sgblack@eecs.umich.edu * @return packet still in transit. 4707398Sgblack@eecs.umich.edu */ 4717398Sgblack@eecs.umich.edu bool packetWaiting() { return pktWaiting; } 4727398Sgblack@eecs.umich.edu 4737398Sgblack@eecs.umich.edu /** Ask if this packet is composed of multiple descriptors 4747398Sgblack@eecs.umich.edu * so even if we've got data, we need to wait for more before 4757398Sgblack@eecs.umich.edu * we can send it out. 4767398Sgblack@eecs.umich.edu * @return packet can't be sent out because it's a multi-descriptor 4777398Sgblack@eecs.umich.edu * packet 4787398Sgblack@eecs.umich.edu */ 4797398Sgblack@eecs.umich.edu bool packetMultiDesc() { return pktMultiDesc;} 4807398Sgblack@eecs.umich.edu 4817398Sgblack@eecs.umich.edu /** Called by event when dma to write packet is completed 4827398Sgblack@eecs.umich.edu */ 4837398Sgblack@eecs.umich.edu void pktComplete(); 4847398Sgblack@eecs.umich.edu EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent; 4857398Sgblack@eecs.umich.edu 4867398Sgblack@eecs.umich.edu void headerComplete(); 4877398Sgblack@eecs.umich.edu EventWrapper<TxDescCache, &TxDescCache::headerComplete> headerEvent; 4887398Sgblack@eecs.umich.edu 4897398Sgblack@eecs.umich.edu 4907398Sgblack@eecs.umich.edu void completionWriteback(Addr a, bool enabled) { 4917398Sgblack@eecs.umich.edu DPRINTF(EthernetDesc, 4927398Sgblack@eecs.umich.edu "Completion writeback Addr: %#x enabled: %d\n", 4937398Sgblack@eecs.umich.edu a, enabled); 4947398Sgblack@eecs.umich.edu completionAddress = a; 4957398Sgblack@eecs.umich.edu completionEnabled = enabled; 4967398Sgblack@eecs.umich.edu } 4977398Sgblack@eecs.umich.edu 4987398Sgblack@eecs.umich.edu virtual bool hasOutstandingEvents(); 4997398Sgblack@eecs.umich.edu 5007398Sgblack@eecs.umich.edu void nullCallback() { 5017398Sgblack@eecs.umich.edu DPRINTF(EthernetDesc, "Completion writeback complete\n"); 5027398Sgblack@eecs.umich.edu } 5037398Sgblack@eecs.umich.edu EventWrapper<TxDescCache, &TxDescCache::nullCallback> nullEvent; 5047398Sgblack@eecs.umich.edu 5057398Sgblack@eecs.umich.edu virtual void serialize(std::ostream &os); 5067398Sgblack@eecs.umich.edu virtual void unserialize(Checkpoint *cp, const std::string §ion); 5077398Sgblack@eecs.umich.edu 5087398Sgblack@eecs.umich.edu }; 5097398Sgblack@eecs.umich.edu friend class TxDescCache; 5107398Sgblack@eecs.umich.edu 5117398Sgblack@eecs.umich.edu TxDescCache txDescCache; 5127398Sgblack@eecs.umich.edu 5137398Sgblack@eecs.umich.edu public: 5147398Sgblack@eecs.umich.edu typedef IGbEParams Params; 5157398Sgblack@eecs.umich.edu const Params * 5167398Sgblack@eecs.umich.edu params() const { 5177398Sgblack@eecs.umich.edu return dynamic_cast<const Params *>(_params); 5187398Sgblack@eecs.umich.edu } 5197398Sgblack@eecs.umich.edu 5207398Sgblack@eecs.umich.edu IGbE(const Params *params); 5217398Sgblack@eecs.umich.edu ~IGbE(); 5227398Sgblack@eecs.umich.edu virtual void init(); 5237398Sgblack@eecs.umich.edu 5247398Sgblack@eecs.umich.edu virtual EtherInt *getEthPort(const std::string &if_name, int idx); 5257398Sgblack@eecs.umich.edu 5267398Sgblack@eecs.umich.edu Tick lastInterrupt; 5277398Sgblack@eecs.umich.edu 5287398Sgblack@eecs.umich.edu virtual Tick read(PacketPtr pkt); 5297398Sgblack@eecs.umich.edu virtual Tick write(PacketPtr pkt); 5307398Sgblack@eecs.umich.edu 5317398Sgblack@eecs.umich.edu virtual Tick writeConfig(PacketPtr pkt); 5327398Sgblack@eecs.umich.edu 5337398Sgblack@eecs.umich.edu bool ethRxPkt(EthPacketPtr packet); 5347398Sgblack@eecs.umich.edu void ethTxDone(); 5357398Sgblack@eecs.umich.edu 5367398Sgblack@eecs.umich.edu virtual void serialize(std::ostream &os); 5377398Sgblack@eecs.umich.edu virtual void unserialize(Checkpoint *cp, const std::string §ion); 5387398Sgblack@eecs.umich.edu 5397398Sgblack@eecs.umich.edu unsigned int drain(DrainManager *dm); 5407398Sgblack@eecs.umich.edu void drainResume(); 5417398Sgblack@eecs.umich.edu 5427398Sgblack@eecs.umich.edu}; 5437398Sgblack@eecs.umich.edu 5447398Sgblack@eecs.umich.educlass IGbEInt : public EtherInt 5457398Sgblack@eecs.umich.edu{ 5467398Sgblack@eecs.umich.edu private: 5477398Sgblack@eecs.umich.edu IGbE *dev; 5487398Sgblack@eecs.umich.edu 5497398Sgblack@eecs.umich.edu public: 5507398Sgblack@eecs.umich.edu IGbEInt(const std::string &name, IGbE *d) 5517398Sgblack@eecs.umich.edu : EtherInt(name), dev(d) 5527398Sgblack@eecs.umich.edu { } 5537398Sgblack@eecs.umich.edu 5547398Sgblack@eecs.umich.edu virtual bool recvPacket(EthPacketPtr pkt) { return dev->ethRxPkt(pkt); } 5557398Sgblack@eecs.umich.edu virtual void sendDone() { dev->ethTxDone(); } 5567398Sgblack@eecs.umich.edu}; 5577398Sgblack@eecs.umich.edu 5587398Sgblack@eecs.umich.edu#endif //__DEV_I8254XGBE_HH__ 5597398Sgblack@eecs.umich.edu