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