i8254xGBe.hh revision 11202
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Ali Saidi
29 */
30
31/* @file
32 * Device model for Intel's 8254x line of gigabit ethernet controllers.
33 */
34
35#ifndef __DEV_I8254XGBE_HH__
36#define __DEV_I8254XGBE_HH__
37
38#include <deque>
39#include <string>
40
41#include "base/cp_annotate.hh"
42#include "base/inet.hh"
43#include "debug/EthernetDesc.hh"
44#include "debug/EthernetIntr.hh"
45#include "dev/etherdevice.hh"
46#include "dev/etherint.hh"
47#include "dev/etherpkt.hh"
48#include "dev/i8254xGBe_defs.hh"
49#include "dev/pcidev.hh"
50#include "dev/pktfifo.hh"
51#include "params/IGbE.hh"
52#include "sim/eventq.hh"
53
54class IGbEInt;
55
56class IGbE : public EtherDevice
57{
58  private:
59    IGbEInt *etherInt;
60    CPA *cpa;
61
62    // device registers
63    iGbReg::Regs regs;
64
65    // eeprom data, status and control bits
66    int eeOpBits, eeAddrBits, eeDataBits;
67    uint8_t eeOpcode, eeAddr;
68    uint16_t flash[iGbReg::EEPROM_SIZE];
69
70    // packet fifos
71    PacketFifo rxFifo;
72    PacketFifo txFifo;
73
74    // Packet that we are currently putting into the txFifo
75    EthPacketPtr txPacket;
76
77    // Should to Rx/Tx State machine tick?
78    bool rxTick;
79    bool txTick;
80    bool txFifoTick;
81
82    bool rxDmaPacket;
83
84    // Number of bytes copied from current RX packet
85    unsigned pktOffset;
86
87    // Delays in managaging descriptors
88    Tick fetchDelay, wbDelay;
89    Tick fetchCompDelay, wbCompDelay;
90    Tick rxWriteDelay, txReadDelay;
91
92    // Event and function to deal with RDTR timer expiring
93    void rdtrProcess() {
94        rxDescCache.writeback(0);
95        DPRINTF(EthernetIntr,
96                "Posting RXT interrupt because RDTR timer expired\n");
97        postInterrupt(iGbReg::IT_RXT);
98    }
99
100    //friend class EventWrapper<IGbE, &IGbE::rdtrProcess>;
101    EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent;
102
103    // Event and function to deal with RADV timer expiring
104    void radvProcess() {
105        rxDescCache.writeback(0);
106        DPRINTF(EthernetIntr,
107                "Posting RXT interrupt because RADV timer expired\n");
108        postInterrupt(iGbReg::IT_RXT);
109    }
110
111    //friend class EventWrapper<IGbE, &IGbE::radvProcess>;
112    EventWrapper<IGbE, &IGbE::radvProcess> radvEvent;
113
114    // Event and function to deal with TADV timer expiring
115    void tadvProcess() {
116        txDescCache.writeback(0);
117        DPRINTF(EthernetIntr,
118                "Posting TXDW interrupt because TADV timer expired\n");
119        postInterrupt(iGbReg::IT_TXDW);
120    }
121
122    //friend class EventWrapper<IGbE, &IGbE::tadvProcess>;
123    EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent;
124
125    // Event and function to deal with TIDV timer expiring
126    void tidvProcess() {
127        txDescCache.writeback(0);
128        DPRINTF(EthernetIntr,
129                "Posting TXDW interrupt because TIDV timer expired\n");
130        postInterrupt(iGbReg::IT_TXDW);
131    }
132    //friend class EventWrapper<IGbE, &IGbE::tidvProcess>;
133    EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent;
134
135    // Main event to tick the device
136    void tick();
137    //friend class EventWrapper<IGbE, &IGbE::tick>;
138    EventWrapper<IGbE, &IGbE::tick> tickEvent;
139
140
141    uint64_t macAddr;
142
143    void rxStateMachine();
144    void txStateMachine();
145    void txWire();
146
147    /** Write an interrupt into the interrupt pending register and check mask
148     * and interrupt limit timer before sending interrupt to CPU
149     * @param t the type of interrupt we are posting
150     * @param now should we ignore the interrupt limiting timer
151     */
152    void postInterrupt(iGbReg::IntTypes t, bool now = false);
153
154    /** Check and see if changes to the mask register have caused an interrupt
155     * to need to be sent or perhaps removed an interrupt cause.
156     */
157    void chkInterrupt();
158
159    /** Send an interrupt to the cpu
160     */
161    void delayIntEvent();
162    void cpuPostInt();
163    // Event to moderate interrupts
164    EventWrapper<IGbE, &IGbE::delayIntEvent> interEvent;
165
166    /** Clear the interupt line to the cpu
167     */
168    void cpuClearInt();
169
170    Tick intClock() { return SimClock::Int::ns * 1024; }
171
172    /** This function is used to restart the clock so it can handle things like
173     * draining and resume in one place. */
174    void restartClock();
175
176    /** Check if all the draining things that need to occur have occured and
177     * handle the drain event if so.
178     */
179    void checkDrain();
180
181    void anBegin(std::string sm, std::string st, int flags = CPA::FL_NONE) {
182        if (cpa)
183            cpa->hwBegin((CPA::flags)flags, sys, macAddr, sm, st);
184    }
185
186    void anQ(std::string sm, std::string q) {
187        if (cpa)
188            cpa->hwQ(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
189    }
190
191    void anDq(std::string sm, std::string q) {
192        if (cpa)
193            cpa->hwDq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
194    }
195
196    void anPq(std::string sm, std::string q, int num = 1) {
197        if (cpa)
198            cpa->hwPq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num);
199    }
200
201    void anRq(std::string sm, std::string q, int num = 1) {
202        if (cpa)
203            cpa->hwRq(CPA::FL_NONE, sys, macAddr, sm, q, macAddr, NULL, num);
204    }
205
206    void anWe(std::string sm, std::string q) {
207        if (cpa)
208            cpa->hwWe(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
209    }
210
211    void anWf(std::string sm, std::string q) {
212        if (cpa)
213            cpa->hwWf(CPA::FL_NONE, sys, macAddr, sm, q, macAddr);
214    }
215
216
217    template<class T>
218    class DescCache : public Serializable
219    {
220      protected:
221        virtual Addr descBase() const = 0;
222        virtual long descHead() const = 0;
223        virtual long descTail() const = 0;
224        virtual long descLen() const = 0;
225        virtual void updateHead(long h) = 0;
226        virtual void enableSm() = 0;
227        virtual void actionAfterWb() {}
228        virtual void fetchAfterWb() = 0;
229
230        typedef std::deque<T *> CacheType;
231        CacheType usedCache;
232        CacheType unusedCache;
233
234        T *fetchBuf;
235        T *wbBuf;
236
237        // Pointer to the device we cache for
238        IGbE *igbe;
239
240        // Name of this  descriptor cache
241        std::string _name;
242
243        // How far we've cached
244        int cachePnt;
245
246        // The size of the descriptor cache
247        int size;
248
249        // How many descriptors we are currently fetching
250        int curFetching;
251
252        // How many descriptors we are currently writing back
253        int wbOut;
254
255        // if the we wrote back to the end of the descriptor ring and are going
256        // to have to wrap and write more
257        bool moreToWb;
258
259        // What the alignment is of the next descriptor writeback
260        Addr wbAlignment;
261
262        /** The packet that is currently being dmad to memory if any */
263        EthPacketPtr pktPtr;
264
265        /** Shortcut for DMA address translation */
266        Addr pciToDma(Addr a) { return igbe->pciToDma(a); }
267
268      public:
269        /** Annotate sm*/
270        std::string annSmFetch, annSmWb, annUnusedDescQ, annUsedCacheQ,
271            annUsedDescQ, annUnusedCacheQ, annDescQ;
272
273        DescCache(IGbE *i, const std::string n, int s);
274        virtual ~DescCache();
275
276        std::string name() { return _name; }
277
278        /** If the address/len/head change when we've got descriptors that are
279         * dirty that is very bad. This function checks that we don't and if we
280         * do panics.
281         */
282        void areaChanged();
283
284        void writeback(Addr aMask);
285        void writeback1();
286        EventWrapper<DescCache, &DescCache::writeback1> wbDelayEvent;
287
288        /** Fetch a chunk of descriptors into the descriptor cache.
289         * Calls fetchComplete when the memory system returns the data
290         */
291        void fetchDescriptors();
292        void fetchDescriptors1();
293        EventWrapper<DescCache, &DescCache::fetchDescriptors1> fetchDelayEvent;
294
295        /** Called by event when dma to read descriptors is completed
296         */
297        void fetchComplete();
298        EventWrapper<DescCache, &DescCache::fetchComplete> fetchEvent;
299
300        /** Called by event when dma to writeback descriptors is completed
301         */
302        void wbComplete();
303        EventWrapper<DescCache, &DescCache::wbComplete> wbEvent;
304
305        /* Return the number of descriptors left in the ring, so the device has
306         * a way to figure out if it needs to interrupt.
307         */
308        unsigned
309        descLeft() const
310        {
311            unsigned left = unusedCache.size();
312            if (cachePnt > descTail())
313                left += (descLen() - cachePnt + descTail());
314            else
315                left += (descTail() - cachePnt);
316
317            return left;
318        }
319
320        /* Return the number of descriptors used and not written back.
321         */
322        unsigned descUsed() const { return usedCache.size(); }
323
324        /* Return the number of cache unused descriptors we have. */
325        unsigned descUnused() const { return unusedCache.size(); }
326
327        /* Get into a state where the descriptor address/head/etc colud be
328         * changed */
329        void reset();
330
331
332        void serialize(CheckpointOut &cp) const override;
333        void unserialize(CheckpointIn &cp) override;
334
335        virtual bool hasOutstandingEvents() {
336            return wbEvent.scheduled() || fetchEvent.scheduled();
337        }
338
339    };
340
341
342    class RxDescCache : public DescCache<iGbReg::RxDesc>
343    {
344      protected:
345        Addr descBase() const override { return igbe->regs.rdba(); }
346        long descHead() const override { return igbe->regs.rdh(); }
347        long descLen() const override { return igbe->regs.rdlen() >> 4; }
348        long descTail() const override { return igbe->regs.rdt(); }
349        void updateHead(long h) override { igbe->regs.rdh(h); }
350        void enableSm() override;
351        void fetchAfterWb() override {
352            if (!igbe->rxTick && igbe->drainState() == DrainState::Running)
353                fetchDescriptors();
354        }
355
356        bool pktDone;
357
358        /** Variable to head with header/data completion events */
359        int splitCount;
360
361        /** Bytes of packet that have been copied, so we know when to
362            set EOP */
363        unsigned bytesCopied;
364
365      public:
366        RxDescCache(IGbE *i, std::string n, int s);
367
368        /** Write the given packet into the buffer(s) pointed to by the
369         * descriptor and update the book keeping. Should only be called when
370         * there are no dma's pending.
371         * @param packet ethernet packet to write
372         * @param pkt_offset bytes already copied from the packet to memory
373         * @return pkt_offset + number of bytes copied during this call
374         */
375        int writePacket(EthPacketPtr packet, int pkt_offset);
376
377        /** Called by event when dma to write packet is completed
378         */
379        void pktComplete();
380
381        /** Check if the dma on the packet has completed and RX state machine
382         * can continue
383         */
384        bool packetDone();
385
386        EventWrapper<RxDescCache, &RxDescCache::pktComplete> pktEvent;
387
388        // Event to handle issuing header and data write at the same time
389        // and only callking pktComplete() when both are completed
390        void pktSplitDone();
391        EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktHdrEvent;
392        EventWrapper<RxDescCache, &RxDescCache::pktSplitDone> pktDataEvent;
393
394        bool hasOutstandingEvents() override;
395
396        void serialize(CheckpointOut &cp) const override;
397        void unserialize(CheckpointIn &cp) override;
398    };
399    friend class RxDescCache;
400
401    RxDescCache rxDescCache;
402
403    class TxDescCache  : public DescCache<iGbReg::TxDesc>
404    {
405      protected:
406        Addr descBase() const override { return igbe->regs.tdba(); }
407        long descHead() const override { return igbe->regs.tdh(); }
408        long descTail() const override { return igbe->regs.tdt(); }
409        long descLen() const override { return igbe->regs.tdlen() >> 4; }
410        void updateHead(long h) override { igbe->regs.tdh(h); }
411        void enableSm() override;
412        void actionAfterWb() override;
413        void fetchAfterWb() override {
414            if (!igbe->txTick && igbe->drainState() == DrainState::Running)
415                fetchDescriptors();
416        }
417
418
419
420        bool pktDone;
421        bool isTcp;
422        bool pktWaiting;
423        bool pktMultiDesc;
424        Addr completionAddress;
425        bool completionEnabled;
426        uint32_t descEnd;
427
428
429        // tso variables
430        bool useTso;
431        Addr tsoHeaderLen;
432        Addr tsoMss;
433        Addr tsoTotalLen;
434        Addr tsoUsedLen;
435        Addr tsoPrevSeq;
436        Addr tsoPktPayloadBytes;
437        bool tsoLoadedHeader;
438        bool tsoPktHasHeader;
439        uint8_t tsoHeader[256];
440        Addr tsoDescBytesUsed;
441        Addr tsoCopyBytes;
442        int tsoPkts;
443
444      public:
445        TxDescCache(IGbE *i, std::string n, int s);
446
447        /** Tell the cache to DMA a packet from main memory into its buffer and
448         * return the size the of the packet to reserve space in tx fifo.
449         * @return size of the packet
450         */
451        unsigned getPacketSize(EthPacketPtr p);
452        void getPacketData(EthPacketPtr p);
453        void processContextDesc();
454
455        /** Return the number of dsecriptors in a cache block for threshold
456         * operations.
457         */
458        unsigned
459        descInBlock(unsigned num_desc)
460        {
461            return num_desc / igbe->cacheBlockSize() / sizeof(iGbReg::TxDesc);
462        }
463
464        /** Ask if the packet has been transfered so the state machine can give
465         * it to the fifo.
466         * @return packet available in descriptor cache
467         */
468        bool packetAvailable();
469
470        /** Ask if we are still waiting for the packet to be transfered.
471         * @return packet still in transit.
472         */
473        bool packetWaiting() { return pktWaiting; }
474
475        /** Ask if this packet is composed of multiple descriptors
476         * so even if we've got data, we need to wait for more before
477         * we can send it out.
478         * @return packet can't be sent out because it's a multi-descriptor
479         * packet
480         */
481        bool packetMultiDesc() { return pktMultiDesc;}
482
483        /** Called by event when dma to write packet is completed
484         */
485        void pktComplete();
486        EventWrapper<TxDescCache, &TxDescCache::pktComplete> pktEvent;
487
488        void headerComplete();
489        EventWrapper<TxDescCache, &TxDescCache::headerComplete> headerEvent;
490
491
492        void completionWriteback(Addr a, bool enabled) {
493            DPRINTF(EthernetDesc,
494                    "Completion writeback Addr: %#x enabled: %d\n",
495                    a, enabled);
496            completionAddress = a;
497            completionEnabled = enabled;
498        }
499
500        bool hasOutstandingEvents() override;
501
502        void nullCallback() {
503            DPRINTF(EthernetDesc, "Completion writeback complete\n");
504        }
505        EventWrapper<TxDescCache, &TxDescCache::nullCallback> nullEvent;
506
507        void serialize(CheckpointOut &cp) const override;
508        void unserialize(CheckpointIn &cp) override;
509    };
510
511    friend class TxDescCache;
512
513    TxDescCache txDescCache;
514
515  public:
516    typedef IGbEParams Params;
517    const Params *
518    params() const {
519        return dynamic_cast<const Params *>(_params);
520    }
521
522    IGbE(const Params *params);
523    ~IGbE();
524    void init() override;
525
526    EtherInt *getEthPort(const std::string &if_name, int idx) override;
527
528    Tick lastInterrupt;
529
530    Tick read(PacketPtr pkt) override;
531    Tick write(PacketPtr pkt) override;
532
533    Tick writeConfig(PacketPtr pkt) override;
534
535    bool ethRxPkt(EthPacketPtr packet);
536    void ethTxDone();
537
538    void serialize(CheckpointOut &cp) const override;
539    void unserialize(CheckpointIn &cp) override;
540
541    DrainState drain() override;
542    void drainResume() override;
543
544};
545
546class IGbEInt : public EtherInt
547{
548  private:
549    IGbE *dev;
550
551  public:
552    IGbEInt(const std::string &name, IGbE *d)
553        : EtherInt(name), dev(d)
554    { }
555
556    virtual bool recvPacket(EthPacketPtr pkt) { return dev->ethRxPkt(pkt); }
557    virtual void sendDone() { dev->ethTxDone(); }
558};
559
560#endif //__DEV_I8254XGBE_HH__
561