2 * Copyright (c) 2006 The Regents of The University of Michigan
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.
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.
32 * Device model for Intel's 8254x line of gigabit ethernet controllers.
33 * In particular an 82547 revision 2 (82547GI) MAC because it seems to have the
34 * fewest workarounds in the driver. It will probably work with most of the
35 * other MACs with slight modifications.
40 * @todo really there are multiple dma engines.. we should implement them.
45 #include "base/inet.hh"
46 #include "base/trace.hh"
47 #include "dev/i8254xGBe.hh"
48 #include "mem/packet.hh"
49 #include "mem/packet_access.hh"
50 #include "params/IGbE.hh"
51 #include "sim/stats.hh"
52 #include "sim/system.hh"
54 using namespace iGbReg
;
57 IGbE::IGbE(const Params
*p
)
58 : EtherDevice(p
), etherInt(NULL
), drainEvent(NULL
), useFlowControl(p
->use_flow_control
),
59 rxFifo(p
->rx_fifo_size
), txFifo(p
->tx_fifo_size
), rxTick(false),
60 txTick(false), txFifoTick(false), rxDmaPacket(false), rdtrEvent(this), radvEvent(this),
61 tadvEvent(this), tidvEvent(this), tickEvent(this), interEvent(this),
62 rxDescCache(this, name()+".RxDesc", p
->rx_desc_cache_size
),
63 txDescCache(this, name()+".TxDesc", p
->tx_desc_cache_size
), clock(p
->clock
)
65 etherInt
= new IGbEInt(name() + ".int", this);
67 // Initialized internal registers per Intel documentation
68 // All registers intialized to 0 by per register constructor
73 regs
.sts
.speed(3); // Say we're 1000Mbps
74 regs
.sts
.fd(1); // full duplex
75 regs
.sts
.lu(1); // link up
81 regs
.rxdctl
.wthresh(1);
92 // clear all 64 16 bit words of the eeprom
93 memset(&flash
, 0, EEPROM_SIZE
*2);
95 // Set the MAC address
96 memcpy(flash
, p
->hardware_address
.bytes(), ETH_ADDR_LEN
);
97 for (int x
= 0; x
< ETH_ADDR_LEN
/2; x
++)
98 flash
[x
] = htobe(flash
[x
]);
101 for (int x
= 0; x
< EEPROM_SIZE
; x
++)
102 csum
+= htobe(flash
[x
]);
105 // Magic happy checksum value
106 flash
[EEPROM_SIZE
-1] = htobe((uint16_t)(EEPROM_CSUM
- csum
));
113 IGbE::getEthPort(const std::string
&if_name
, int idx
)
116 if (if_name
== "interface") {
117 if (etherInt
->getPeer())
118 panic("Port already connected to\n");
125 IGbE::writeConfig(PacketPtr pkt
)
127 int offset
= pkt
->getAddr() & PCI_CONFIG_SIZE
;
128 if (offset
< PCI_DEVICE_SPECIFIC
)
129 PciDev::writeConfig(pkt
);
131 panic("Device specific PCI config space not implemented.\n");
134 /// Some work may need to be done here based for the pci COMMAND bits.
141 IGbE::read(PacketPtr pkt
)
146 if (!getBAR(pkt
->getAddr(), bar
, daddr
))
147 panic("Invalid PCI memory access to unmapped memory.\n");
149 // Only Memory register BAR is allowed
152 // Only 32bit accesses allowed
153 assert(pkt
->getSize() == 4);
155 DPRINTF(Ethernet
, "Read device register %#X\n", daddr
);
160 /// Handle read of register here
166 pkt
->set
<uint32_t>(regs
.ctrl());
169 pkt
->set
<uint32_t>(regs
.sts());
172 pkt
->set
<uint32_t>(regs
.eecd());
175 pkt
->set
<uint32_t>(regs
.eerd());
178 pkt
->set
<uint32_t>(regs
.ctrl_ext());
181 pkt
->set
<uint32_t>(regs
.mdic());
184 DPRINTF(Ethernet
, "Reading ICR. ICR=%#x IMR=%#x IAM=%#x IAME=%d\n", regs
.icr(),
185 regs
.imr
, regs
.iam
, regs
.ctrl_ext
.iame());
186 pkt
->set
<uint32_t>(regs
.icr());
187 if (regs
.icr
.int_assert() || regs
.imr
== 0) {
188 regs
.icr
= regs
.icr() & ~mask(30);
189 DPRINTF(Ethernet
, "Cleared ICR. ICR=%#x\n", regs
.icr());
191 if (regs
.ctrl_ext
.iame() && regs
.icr
.int_assert())
192 regs
.imr
&= ~regs
.iam
;
196 pkt
->set
<uint32_t>(regs
.itr());
199 pkt
->set
<uint32_t>(regs
.rctl());
202 pkt
->set
<uint32_t>(regs
.fcttv());
205 pkt
->set
<uint32_t>(regs
.tctl());
208 pkt
->set
<uint32_t>(regs
.pba());
212 pkt
->set
<uint32_t>(0); // We don't care, so just return 0
215 pkt
->set
<uint32_t>(regs
.fcrtl());
218 pkt
->set
<uint32_t>(regs
.fcrth());
221 pkt
->set
<uint32_t>(regs
.rdba
.rdbal());
224 pkt
->set
<uint32_t>(regs
.rdba
.rdbah());
227 pkt
->set
<uint32_t>(regs
.rdlen());
230 pkt
->set
<uint32_t>(regs
.rdh());
233 pkt
->set
<uint32_t>(regs
.rdt());
236 pkt
->set
<uint32_t>(regs
.rdtr());
237 if (regs
.rdtr
.fpd()) {
238 rxDescCache
.writeback(0);
239 DPRINTF(EthernetIntr
, "Posting interrupt because of RDTR.FPD write\n");
240 postInterrupt(IT_RXT
);
245 pkt
->set
<uint32_t>(regs
.radv());
248 pkt
->set
<uint32_t>(regs
.tdba
.tdbal());
251 pkt
->set
<uint32_t>(regs
.tdba
.tdbah());
254 pkt
->set
<uint32_t>(regs
.tdlen());
257 pkt
->set
<uint32_t>(regs
.tdh());
260 pkt
->set
<uint32_t>(regs
.tdt());
263 pkt
->set
<uint32_t>(regs
.tidv());
266 pkt
->set
<uint32_t>(regs
.txdctl());
269 pkt
->set
<uint32_t>(regs
.tadv());
272 pkt
->set
<uint32_t>(regs
.rxcsum());
275 pkt
->set
<uint32_t>(regs
.manc());
278 if (!(daddr
>= REG_VFTA
&& daddr
< (REG_VFTA
+ VLAN_FILTER_TABLE_SIZE
*4)) &&
279 !(daddr
>= REG_RAL
&& daddr
< (REG_RAL
+ RCV_ADDRESS_TABLE_SIZE
*8)) &&
280 !(daddr
>= REG_MTA
&& daddr
< (REG_MTA
+ MULTICAST_TABLE_SIZE
*4)) &&
281 !(daddr
>= REG_CRCERRS
&& daddr
< (REG_CRCERRS
+ STATS_REGS_SIZE
)))
282 panic("Read request to unknown register number: %#x\n", daddr
);
284 pkt
->set
<uint32_t>(0);
287 pkt
->makeAtomicResponse();
292 IGbE::write(PacketPtr pkt
)
298 if (!getBAR(pkt
->getAddr(), bar
, daddr
))
299 panic("Invalid PCI memory access to unmapped memory.\n");
301 // Only Memory register BAR is allowed
304 // Only 32bit accesses allowed
305 assert(pkt
->getSize() == sizeof(uint32_t));
307 DPRINTF(Ethernet
, "Wrote device register %#X value %#X\n", daddr
, pkt
->get
<uint32_t>());
310 /// Handle write of register here
312 uint32_t val
= pkt
->get
<uint32_t>();
320 if (regs
.ctrl
.tfce())
321 warn("TX Flow control enabled, should implement\n");
322 if (regs
.ctrl
.rfce())
323 warn("RX Flow control enabled, should implement\n");
333 oldClk
= regs
.eecd
.sk();
335 // See if this is a eeprom access and emulate accordingly
336 if (!oldClk
&& regs
.eecd
.sk()) {
338 eeOpcode
= eeOpcode
<< 1 | regs
.eecd
.din();
340 } else if (eeAddrBits
< 8 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) {
341 eeAddr
= eeAddr
<< 1 | regs
.eecd
.din();
343 } else if (eeDataBits
< 16 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) {
344 assert(eeAddr
>>1 < EEPROM_SIZE
);
345 DPRINTF(EthernetEEPROM
, "EEPROM bit read: %d word: %#X\n",
346 flash
[eeAddr
>>1] >> eeDataBits
& 0x1, flash
[eeAddr
>>1]);
347 regs
.eecd
.dout((flash
[eeAddr
>>1] >> (15-eeDataBits
)) & 0x1);
349 } else if (eeDataBits
< 8 && eeOpcode
== EEPROM_RDSR_OPCODE_SPI
) {
353 panic("What's going on with eeprom interface? opcode:"
354 " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode
,
355 (uint32_t)eeOpBits
, (uint32_t)eeAddr
,
356 (uint32_t)eeAddrBits
, (uint32_t)eeDataBits
);
358 // Reset everything for the next command
359 if ((eeDataBits
== 16 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) ||
360 (eeDataBits
== 8 && eeOpcode
== EEPROM_RDSR_OPCODE_SPI
)) {
368 DPRINTF(EthernetEEPROM
, "EEPROM: opcode: %#X:%d addr: %#X:%d\n",
369 (uint32_t)eeOpcode
, (uint32_t) eeOpBits
,
370 (uint32_t)eeAddr
>>1, (uint32_t)eeAddrBits
);
371 if (eeOpBits
== 8 && !(eeOpcode
== EEPROM_READ_OPCODE_SPI
||
372 eeOpcode
== EEPROM_RDSR_OPCODE_SPI
))
373 panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode
,
378 // If driver requests eeprom access, immediately give it to it
379 regs
.eecd
.ee_gnt(regs
.eecd
.ee_req());
387 panic("No support for interrupt on mdic complete\n");
388 if (regs
.mdic
.phyadd() != 1)
389 panic("No support for reading anything but phy\n");
390 DPRINTF(Ethernet
, "%s phy address %x\n", regs
.mdic
.op() == 1 ? "Writing"
391 : "Reading", regs
.mdic
.regadd());
392 switch (regs
.mdic
.regadd()) {
394 regs
.mdic
.data(0x796D); // link up
397 regs
.mdic
.data(0x02A8);
400 regs
.mdic
.data(0x0380);
403 regs
.mdic
.data(0x7C00);
406 regs
.mdic
.data(0x3000);
409 regs
.mdic
.data(0x180); // some random length
417 DPRINTF(Ethernet
, "Writing ICR. ICR=%#x IMR=%#x IAM=%#x IAME=%d\n", regs
.icr(),
418 regs
.imr
, regs
.iam
, regs
.ctrl_ext
.iame());
419 if (regs
.ctrl_ext
.iame())
420 regs
.imr
&= ~regs
.iam
;
421 regs
.icr
= ~bits(val
,30,0) & regs
.icr();
428 DPRINTF(EthernetIntr
, "Posting interrupt because of ICS write\n");
429 postInterrupt((IntTypes
)val
);
445 if (regs
.rctl
.rst()) {
447 DPRINTF(EthernetSM
, "RXS: Got RESET!\n");
465 if (regs
.tctl
.en() && !oldtctl
.en()) {
471 regs
.pba
.txa(64 - regs
.pba
.rxa());
481 ; // We don't care, so don't store anything
490 regs
.rdba
.rdbal( val
& ~mask(4));
491 rxDescCache
.areaChanged();
494 regs
.rdba
.rdbah(val
);
495 rxDescCache
.areaChanged();
498 regs
.rdlen
= val
& ~mask(7);
499 rxDescCache
.areaChanged();
503 rxDescCache
.areaChanged();
507 DPRINTF(EthernetSM
, "RXS: RDT Updated.\n");
508 if (getState() == SimObject::Running
) {
509 DPRINTF(EthernetSM
, "RXS: RDT Fetching Descriptors!\n");
510 rxDescCache
.fetchDescriptors();
512 DPRINTF(EthernetSM
, "RXS: RDT NOT Fetching Desc b/c draining!\n");
522 regs
.tdba
.tdbal( val
& ~mask(4));
523 txDescCache
.areaChanged();
526 regs
.tdba
.tdbah(val
);
527 txDescCache
.areaChanged();
530 regs
.tdlen
= val
& ~mask(7);
531 txDescCache
.areaChanged();
535 txDescCache
.areaChanged();
539 DPRINTF(EthernetSM
, "TXS: TX Tail pointer updated\n");
540 if (getState() == SimObject::Running
) {
541 DPRINTF(EthernetSM
, "TXS: TDT Fetching Descriptors!\n");
542 txDescCache
.fetchDescriptors();
544 DPRINTF(EthernetSM
, "TXS: TDT NOT Fetching Desc b/c draining!\n");
563 if (!(daddr
>= REG_VFTA
&& daddr
< (REG_VFTA
+ VLAN_FILTER_TABLE_SIZE
*4)) &&
564 !(daddr
>= REG_RAL
&& daddr
< (REG_RAL
+ RCV_ADDRESS_TABLE_SIZE
*8)) &&
565 !(daddr
>= REG_MTA
&& daddr
< (REG_MTA
+ MULTICAST_TABLE_SIZE
*4)))
566 panic("Write request to unknown register number: %#x\n", daddr
);
569 pkt
->makeAtomicResponse();
574 IGbE::postInterrupt(IntTypes t
, bool now
)
578 // Interrupt is already pending
579 if (t
& regs
.icr() && !now
)
582 regs
.icr
= regs
.icr() | t
;
583 if (regs
.itr
.interval() == 0 || now
) {
584 if (interEvent
.scheduled()) {
585 interEvent
.deschedule();
590 DPRINTF(EthernetIntr
, "EINT: Scheduling timer interrupt for %d ticks\n",
591 Clock::Int::ns
* 256 * regs
.itr
.interval());
592 if (!interEvent
.scheduled()) {
593 interEvent
.schedule(curTick
+ Clock::Int::ns
* 256 * regs
.itr
.interval());
599 IGbE::delayIntEvent()
609 if (!(regs
.icr() & regs
.imr
)) {
610 DPRINTF(Ethernet
, "Interrupt Masked. Not Posting\n");
614 DPRINTF(Ethernet
, "Posting Interrupt\n");
617 if (interEvent
.scheduled()) {
618 interEvent
.deschedule();
621 if (rdtrEvent
.scheduled()) {
623 rdtrEvent
.deschedule();
625 if (radvEvent
.scheduled()) {
627 radvEvent
.deschedule();
629 if (tadvEvent
.scheduled()) {
631 tadvEvent
.deschedule();
633 if (tidvEvent
.scheduled()) {
635 tidvEvent
.deschedule();
638 regs
.icr
.int_assert(1);
639 DPRINTF(EthernetIntr
, "EINT: Posting interrupt to CPU now. Vector %#x\n",
649 if (regs
.icr
.int_assert()) {
650 regs
.icr
.int_assert(0);
651 DPRINTF(EthernetIntr
, "EINT: Clearing interrupt to CPU now. Vector %#x\n",
660 DPRINTF(Ethernet
, "Checking interrupts icr: %#x imr: %#x\n", regs
.icr(),
662 // Check if we need to clear the cpu interrupt
663 if (!(regs
.icr() & regs
.imr
)) {
664 DPRINTF(Ethernet
, "Mask cleaned all interrupts\n");
665 if (interEvent
.scheduled())
666 interEvent
.deschedule();
667 if (regs
.icr
.int_assert())
670 DPRINTF(Ethernet
, "ITR = %#X itr.interval = %#X\n", regs
.itr(), regs
.itr
.interval());
672 if (regs
.icr() & regs
.imr
) {
673 if (regs
.itr
.interval() == 0) {
676 DPRINTF(Ethernet
, "Possibly scheduling interrupt because of imr write\n");
677 if (!interEvent
.scheduled()) {
678 DPRINTF(Ethernet
, "Scheduling for %d\n", curTick
+ Clock::Int::ns
679 * 256 * regs
.itr
.interval());
680 interEvent
.schedule(curTick
+ Clock::Int::ns
* 256 * regs
.itr
.interval());
689 IGbE::RxDescCache::RxDescCache(IGbE
*i
, const std::string n
, int s
)
690 : DescCache
<RxDesc
>(i
, n
, s
), pktDone(false), pktEvent(this)
696 IGbE::RxDescCache::writePacket(EthPacketPtr packet
)
698 // We shouldn't have to deal with any of these yet
699 DPRINTF(EthernetDesc
, "Packet Length: %d Desc Size: %d\n",
700 packet
->length
, igbe
->regs
.rctl
.descSize());
701 assert(packet
->length
< igbe
->regs
.rctl
.descSize());
703 assert(unusedCache
.size());
704 //if (!unusedCache.size())
709 igbe
->dmaWrite(igbe
->platform
->pciToDma(unusedCache
.front()->buf
),
710 packet
->length
, &pktEvent
, packet
->data
);
714 IGbE::RxDescCache::pktComplete()
716 assert(unusedCache
.size());
718 desc
= unusedCache
.front();
720 uint16_t crcfixup
= igbe
->regs
.rctl
.secrc() ? 0 : 4 ;
721 desc
->len
= htole((uint16_t)(pktPtr
->length
+ crcfixup
));
722 DPRINTF(EthernetDesc
, "pktPtr->length: %d stripcrc offset: %d value written: %d %d\n",
723 pktPtr
->length
, crcfixup
,
724 htole((uint16_t)(pktPtr
->length
+ crcfixup
)),
725 (uint16_t)(pktPtr
->length
+ crcfixup
));
727 // no support for anything but starting at 0
728 assert(igbe
->regs
.rxcsum
.pcss() == 0);
730 DPRINTF(EthernetDesc
, "Packet written to memory updating Descriptor\n");
732 uint8_t status
= RXDS_DD
| RXDS_EOP
;
738 DPRINTF(EthernetDesc
, "Proccesing Ip packet with Id=%d\n", ip
->id());
740 if (igbe
->regs
.rxcsum
.ipofld()) {
741 DPRINTF(EthernetDesc
, "Checking IP checksum\n");
743 desc
->csum
= htole(cksum(ip
));
744 igbe
->rxIpChecksums
++;
745 if (cksum(ip
) != 0) {
747 DPRINTF(EthernetDesc
, "Checksum is bad!!\n");
751 if (tcp
&& igbe
->regs
.rxcsum
.tuofld()) {
752 DPRINTF(EthernetDesc
, "Checking TCP checksum\n");
753 status
|= RXDS_TCPCS
;
754 desc
->csum
= htole(cksum(tcp
));
755 igbe
->rxTcpChecksums
++;
756 if (cksum(tcp
) != 0) {
757 DPRINTF(EthernetDesc
, "Checksum is bad!!\n");
763 if (udp
&& igbe
->regs
.rxcsum
.tuofld()) {
764 DPRINTF(EthernetDesc
, "Checking UDP checksum\n");
765 status
|= RXDS_UDPCS
;
766 desc
->csum
= htole(cksum(udp
));
767 igbe
->rxUdpChecksums
++;
768 if (cksum(udp
) != 0) {
769 DPRINTF(EthernetDesc
, "Checksum is bad!!\n");
774 DPRINTF(EthernetSM
, "Proccesing Non-Ip packet\n");
778 desc
->status
= htole(status
);
779 desc
->errors
= htole(err
);
781 // No vlan support at this point... just set it to 0
784 // Deal with the rx timer interrupts
785 if (igbe
->regs
.rdtr
.delay()) {
786 DPRINTF(EthernetSM
, "RXS: Scheduling DTR for %d\n",
787 igbe
->regs
.rdtr
.delay() * igbe
->intClock());
788 igbe
->rdtrEvent
.reschedule(curTick
+ igbe
->regs
.rdtr
.delay() *
789 igbe
->intClock(),true);
792 if (igbe
->regs
.radv
.idv() && igbe
->regs
.rdtr
.delay()) {
793 DPRINTF(EthernetSM
, "RXS: Scheduling ADV for %d\n",
794 igbe
->regs
.radv
.idv() * igbe
->intClock());
795 if (!igbe
->radvEvent
.scheduled()) {
796 igbe
->radvEvent
.schedule(curTick
+ igbe
->regs
.radv
.idv() *
801 // if neither radv or rdtr, maybe itr is set...
802 if (!igbe
->regs
.rdtr
.delay()) {
803 DPRINTF(EthernetSM
, "RXS: Receive interrupt delay disabled, posting IT_RXT\n");
804 igbe
->postInterrupt(IT_RXT
);
807 // If the packet is small enough, interrupt appropriately
808 // I wonder if this is delayed or not?!
809 if (pktPtr
->length
<= igbe
->regs
.rsrpd
.idv()) {
810 DPRINTF(EthernetSM
, "RXS: Posting IT_SRPD beacuse small packet received\n");
811 igbe
->postInterrupt(IT_SRPD
);
814 DPRINTF(EthernetDesc
, "Processing of this descriptor complete\n");
815 unusedCache
.pop_front();
816 usedCache
.push_back(desc
);
827 IGbE::RxDescCache::enableSm()
829 if (!igbe
->drainEvent
) {
831 igbe
->restartClock();
836 IGbE::RxDescCache::packetDone()
846 IGbE::RxDescCache::hasOutstandingEvents()
848 return pktEvent
.scheduled() || wbEvent
.scheduled() ||
849 fetchEvent
.scheduled();
853 IGbE::RxDescCache::serialize(std::ostream
&os
)
855 DescCache
<RxDesc
>::serialize(os
);
856 SERIALIZE_SCALAR(pktDone
);
860 IGbE::RxDescCache::unserialize(Checkpoint
*cp
, const std::string
§ion
)
862 DescCache
<RxDesc
>::unserialize(cp
, section
);
863 UNSERIALIZE_SCALAR(pktDone
);
867 ///////////////////////////////////// IGbE::TxDesc /////////////////////////////////
869 IGbE::TxDescCache::TxDescCache(IGbE
*i
, const std::string n
, int s
)
870 : DescCache
<TxDesc
>(i
,n
, s
), pktDone(false), isTcp(false), pktWaiting(false),
877 IGbE::TxDescCache::getPacketSize()
879 assert(unusedCache
.size());
883 DPRINTF(EthernetDesc
, "Starting processing of descriptor\n");
885 while (unusedCache
.size() && TxdOp::isContext(unusedCache
.front())) {
886 DPRINTF(EthernetDesc
, "Got context descriptor type... skipping\n");
888 // I think we can just ignore these for now?
889 desc
= unusedCache
.front();
890 DPRINTF(EthernetDesc
, "Descriptor upper: %#x lower: %#X\n", desc
->d1
,
892 // is this going to be a tcp or udp packet?
893 isTcp
= TxdOp::tcp(desc
) ? true : false;
895 // make sure it's ipv4
896 //assert(TxdOp::ip(desc));
899 unusedCache
.pop_front();
900 usedCache
.push_back(desc
);
903 if (!unusedCache
.size())
906 DPRINTF(EthernetDesc
, "Next TX packet is %d bytes\n",
907 TxdOp::getLen(unusedCache
.front()));
909 return TxdOp::getLen(unusedCache
.front());
913 IGbE::TxDescCache::getPacketData(EthPacketPtr p
)
915 assert(unusedCache
.size());
918 desc
= unusedCache
.front();
920 assert((TxdOp::isLegacy(desc
) || TxdOp::isData(desc
)) && TxdOp::getLen(desc
));
926 DPRINTF(EthernetDesc
, "Starting DMA of packet at offset %d\n", p
->length
);
927 igbe
->dmaRead(igbe
->platform
->pciToDma(TxdOp::getBuf(desc
)),
928 TxdOp::getLen(desc
), &pktEvent
, p
->data
+ p
->length
);
934 IGbE::TxDescCache::pktComplete()
938 assert(unusedCache
.size());
941 DPRINTF(EthernetDesc
, "DMA of packet complete\n");
944 desc
= unusedCache
.front();
945 assert((TxdOp::isLegacy(desc
) || TxdOp::isData(desc
)) && TxdOp::getLen(desc
));
947 DPRINTF(EthernetDesc
, "TxDescriptor data d1: %#llx d2: %#llx\n", desc
->d1
, desc
->d2
);
949 if (!TxdOp::eop(desc
)) {
950 pktPtr
->length
+= TxdOp::getLen(desc
);
951 unusedCache
.pop_front();
952 usedCache
.push_back(desc
);
957 DPRINTF(EthernetDesc
, "Partial Packet Descriptor of %d bytes Done\n",
965 pktMultiDesc
= false;
967 // Set the length of the data in the EtherPacket
968 pktPtr
->length
+= TxdOp::getLen(desc
);
970 // no support for vlans
971 assert(!TxdOp::vle(desc
));
973 // we alway report status
974 assert(TxdOp::rs(desc
));
976 // we only support single packet descriptors at this point
977 assert(TxdOp::eop(desc
));
979 // set that this packet is done
982 DPRINTF(EthernetDesc
, "TxDescriptor data d1: %#llx d2: %#llx\n", desc
->d1
, desc
->d2
);
984 if (DTRACE(EthernetDesc
)) {
987 DPRINTF(EthernetDesc
, "Proccesing Ip packet with Id=%d\n",
990 DPRINTF(EthernetSM
, "Proccesing Non-Ip packet\n");
993 // Checksums are only ofloaded for new descriptor types
994 if (TxdOp::isData(desc
) && ( TxdOp::ixsm(desc
) || TxdOp::txsm(desc
)) ) {
995 DPRINTF(EthernetDesc
, "Calculating checksums for packet\n");
998 if (TxdOp::ixsm(desc
)) {
1001 igbe
->txIpChecksums
++;
1002 DPRINTF(EthernetDesc
, "Calculated IP checksum\n");
1004 if (TxdOp::txsm(desc
)) {
1009 tcp
->sum(cksum(tcp
));
1010 igbe
->txTcpChecksums
++;
1011 DPRINTF(EthernetDesc
, "Calculated TCP checksum\n");
1015 udp
->sum(cksum(udp
));
1016 igbe
->txUdpChecksums
++;
1017 DPRINTF(EthernetDesc
, "Calculated UDP checksum\n");
1019 panic("Told to checksum, but don't know how\n");
1024 if (TxdOp::ide(desc
)) {
1025 // Deal with the rx timer interrupts
1026 DPRINTF(EthernetDesc
, "Descriptor had IDE set\n");
1027 if (igbe
->regs
.tidv
.idv()) {
1028 DPRINTF(EthernetDesc
, "setting tidv\n");
1029 igbe
->tidvEvent
.reschedule(curTick
+ igbe
->regs
.tidv
.idv() *
1030 igbe
->intClock(), true);
1033 if (igbe
->regs
.tadv
.idv() && igbe
->regs
.tidv
.idv()) {
1034 DPRINTF(EthernetDesc
, "setting tadv\n");
1035 if (!igbe
->tadvEvent
.scheduled()) {
1036 igbe
->tadvEvent
.schedule(curTick
+ igbe
->regs
.tadv
.idv() *
1044 unusedCache
.pop_front();
1045 usedCache
.push_back(desc
);
1050 DPRINTF(EthernetDesc
, "Descriptor Done\n");
1052 if (igbe
->regs
.txdctl
.wthresh() == 0) {
1053 DPRINTF(EthernetDesc
, "WTHRESH == 0, writing back descriptor\n");
1055 } else if (igbe
->regs
.txdctl
.wthresh() >= usedCache
.size()) {
1056 DPRINTF(EthernetDesc
, "used > WTHRESH, writing back descriptor\n");
1057 writeback((igbe
->cacheBlockSize()-1)>>4);
1064 IGbE::TxDescCache::serialize(std::ostream
&os
)
1066 DescCache
<TxDesc
>::serialize(os
);
1067 SERIALIZE_SCALAR(pktDone
);
1068 SERIALIZE_SCALAR(isTcp
);
1069 SERIALIZE_SCALAR(pktWaiting
);
1070 SERIALIZE_SCALAR(pktMultiDesc
);
1074 IGbE::TxDescCache::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1076 DescCache
<TxDesc
>::unserialize(cp
, section
);
1077 UNSERIALIZE_SCALAR(pktDone
);
1078 UNSERIALIZE_SCALAR(isTcp
);
1079 UNSERIALIZE_SCALAR(pktWaiting
);
1080 UNSERIALIZE_SCALAR(pktMultiDesc
);
1084 IGbE::TxDescCache::packetAvailable()
1094 IGbE::TxDescCache::enableSm()
1096 if (!igbe
->drainEvent
) {
1097 igbe
->txTick
= true;
1098 igbe
->restartClock();
1103 IGbE::TxDescCache::hasOutstandingEvents()
1105 return pktEvent
.scheduled() || wbEvent
.scheduled() ||
1106 fetchEvent
.scheduled();
1110 ///////////////////////////////////// IGbE /////////////////////////////////
1113 IGbE::restartClock()
1115 if (!tickEvent
.scheduled() && (rxTick
|| txTick
|| txFifoTick
) && getState() ==
1117 tickEvent
.schedule((curTick
/ticks(1)) * ticks(1) + ticks(1));
1121 IGbE::drain(Event
*de
)
1124 count
= pioPort
->drain(de
) + dmaPort
->drain(de
);
1125 if (rxDescCache
.hasOutstandingEvents() ||
1126 txDescCache
.hasOutstandingEvents()) {
1135 if (tickEvent
.scheduled())
1136 tickEvent
.deschedule();
1139 changeState(Draining
);
1141 changeState(Drained
);
1149 SimObject::resume();
1167 if (!rxDescCache
.hasOutstandingEvents() &&
1168 !txDescCache
.hasOutstandingEvents()) {
1169 drainEvent
->process();
1175 IGbE::txStateMachine()
1177 if (!regs
.tctl
.en()) {
1179 DPRINTF(EthernetSM
, "TXS: TX disabled, stopping ticking\n");
1183 // If we have a packet available and it's length is not 0 (meaning it's not
1184 // a multidescriptor packet) put it in the fifo, otherwise an the next
1185 // iteration we'll get the rest of the data
1186 if (txPacket
&& txDescCache
.packetAvailable()
1187 && !txDescCache
.packetMultiDesc() && txPacket
->length
) {
1190 DPRINTF(EthernetSM
, "TXS: packet placed in TX FIFO\n");
1191 success
= txFifo
.push(txPacket
);
1192 txFifoTick
= true && !drainEvent
;
1195 txDescCache
.writeback((cacheBlockSize()-1)>>4);
1199 // Only support descriptor granularity
1200 assert(regs
.txdctl
.gran());
1201 if (regs
.txdctl
.lwthresh() && txDescCache
.descLeft() < (regs
.txdctl
.lwthresh() * 8)) {
1202 DPRINTF(EthernetSM
, "TXS: LWTHRESH caused posting of TXDLOW\n");
1203 postInterrupt(IT_TXDLOW
);
1207 txPacket
= new EthPacketData(16384);
1210 if (!txDescCache
.packetWaiting()) {
1211 if (txDescCache
.descLeft() == 0) {
1212 postInterrupt(IT_TXQE
);
1213 txDescCache
.writeback(0);
1214 txDescCache
.fetchDescriptors();
1215 DPRINTF(EthernetSM
, "TXS: No descriptors left in ring, forcing "
1216 "writeback stopping ticking and posting TXQE\n");
1222 if (!(txDescCache
.descUnused())) {
1223 txDescCache
.fetchDescriptors();
1224 DPRINTF(EthernetSM
, "TXS: No descriptors available in cache, fetching and stopping ticking\n");
1231 size
= txDescCache
.getPacketSize();
1232 if (size
> 0 && txFifo
.avail() > size
) {
1233 DPRINTF(EthernetSM
, "TXS: Reserving %d bytes in FIFO and begining "
1234 "DMA of next packet\n", size
);
1235 txFifo
.reserve(size
);
1236 txDescCache
.getPacketData(txPacket
);
1237 } else if (size
<= 0) {
1238 DPRINTF(EthernetSM
, "TXS: getPacketSize returned: %d\n", size
);
1239 DPRINTF(EthernetSM
, "TXS: No packets to get, writing back used descriptors\n");
1240 txDescCache
.writeback(0);
1242 DPRINTF(EthernetSM
, "TXS: FIFO full, stopping ticking until space "
1243 "available in FIFO\n");
1250 DPRINTF(EthernetSM
, "TXS: Nothing to do, stopping ticking\n");
1255 IGbE::ethRxPkt(EthPacketPtr pkt
)
1257 rxBytes
+= pkt
->length
;
1260 DPRINTF(Ethernet
, "RxFIFO: Receiving pcakte from wire\n");
1262 if (!regs
.rctl
.en()) {
1263 DPRINTF(Ethernet
, "RxFIFO: RX not enabled, dropping\n");
1267 // restart the state machines if they are stopped
1268 rxTick
= true && !drainEvent
;
1269 if ((rxTick
|| txTick
) && !tickEvent
.scheduled()) {
1270 DPRINTF(EthernetSM
, "RXS: received packet into fifo, starting ticking\n");
1274 if (!rxFifo
.push(pkt
)) {
1275 DPRINTF(Ethernet
, "RxFIFO: Packet won't fit in fifo... dropped\n");
1276 postInterrupt(IT_RXO
, true);
1285 IGbE::rxStateMachine()
1287 if (!regs
.rctl
.en()) {
1289 DPRINTF(EthernetSM
, "RXS: RX disabled, stopping ticking\n");
1293 // If the packet is done check for interrupts/descriptors/etc
1294 if (rxDescCache
.packetDone()) {
1295 rxDmaPacket
= false;
1296 DPRINTF(EthernetSM
, "RXS: Packet completed DMA to memory\n");
1297 int descLeft
= rxDescCache
.descLeft();
1298 switch (regs
.rctl
.rdmts()) {
1299 case 2: if (descLeft
> .125 * regs
.rdlen()) break;
1300 case 1: if (descLeft
> .250 * regs
.rdlen()) break;
1301 case 0: if (descLeft
> .500 * regs
.rdlen()) break;
1302 DPRINTF(Ethernet
, "RXS: Interrupting (RXDMT) because of descriptors left\n");
1303 postInterrupt(IT_RXDMT
);
1307 if (descLeft
== 0) {
1308 rxDescCache
.writeback(0);
1309 DPRINTF(EthernetSM
, "RXS: No descriptors left in ring, forcing"
1310 " writeback and stopping ticking\n");
1314 // only support descriptor granulaties
1315 assert(regs
.rxdctl
.gran());
1317 if (regs
.rxdctl
.wthresh() >= rxDescCache
.descUsed()) {
1318 DPRINTF(EthernetSM
, "RXS: Writing back because WTHRESH >= descUsed\n");
1319 if (regs
.rxdctl
.wthresh() < (cacheBlockSize()>>4))
1320 rxDescCache
.writeback(regs
.rxdctl
.wthresh()-1);
1322 rxDescCache
.writeback((cacheBlockSize()-1)>>4);
1325 if ((rxDescCache
.descUnused() < regs
.rxdctl
.pthresh()) &&
1326 ((rxDescCache
.descLeft() - rxDescCache
.descUnused()) > regs
.rxdctl
.hthresh())) {
1327 DPRINTF(EthernetSM
, "RXS: Fetching descriptors because descUnused < PTHRESH\n");
1328 rxDescCache
.fetchDescriptors();
1331 if (rxDescCache
.descUnused() == 0) {
1332 rxDescCache
.fetchDescriptors();
1333 DPRINTF(EthernetSM
, "RXS: No descriptors available in cache, "
1334 "fetching descriptors and stopping ticking\n");
1341 DPRINTF(EthernetSM
, "RXS: stopping ticking until packet DMA completes\n");
1346 if (!rxDescCache
.descUnused()) {
1347 rxDescCache
.fetchDescriptors();
1348 DPRINTF(EthernetSM
, "RXS: No descriptors available in cache, stopping ticking\n");
1350 DPRINTF(EthernetSM
, "RXS: No descriptors available, fetching\n");
1354 if (rxFifo
.empty()) {
1355 DPRINTF(EthernetSM
, "RXS: RxFIFO empty, stopping ticking\n");
1361 pkt
= rxFifo
.front();
1364 rxDescCache
.writePacket(pkt
);
1365 DPRINTF(EthernetSM
, "RXS: Writing packet into memory\n");
1366 DPRINTF(EthernetSM
, "RXS: Removing packet from FIFO\n");
1368 DPRINTF(EthernetSM
, "RXS: stopping ticking until packet DMA completes\n");
1376 if (txFifo
.empty()) {
1382 if (etherInt
->sendPacket(txFifo
.front())) {
1383 if (DTRACE(EthernetSM
)) {
1384 IpPtr
ip(txFifo
.front());
1386 DPRINTF(EthernetSM
, "Transmitting Ip packet with Id=%d\n",
1389 DPRINTF(EthernetSM
, "Transmitting Non-Ip packet\n");
1391 DPRINTF(EthernetSM
, "TxFIFO: Successful transmit, bytes available in fifo: %d\n",
1394 txBytes
+= txFifo
.front()->length
;
1399 // We'll get woken up when the packet ethTxDone() gets called
1407 DPRINTF(EthernetSM
, "IGbE: -------------- Cycle --------------\n");
1419 if (rxTick
|| txTick
|| txFifoTick
)
1420 tickEvent
.schedule(curTick
+ ticks(1));
1426 // restart the tx state machines if they are stopped
1427 // fifo to send another packet
1428 // tx sm to put more data into the fifo
1429 txFifoTick
= true && !drainEvent
;
1430 if (txDescCache
.descLeft() != 0 && !drainEvent
)
1435 DPRINTF(EthernetSM
, "TxFIFO: Transmission complete\n");
1439 IGbE::serialize(std::ostream
&os
)
1441 PciDev::serialize(os
);
1444 SERIALIZE_SCALAR(eeOpBits
);
1445 SERIALIZE_SCALAR(eeAddrBits
);
1446 SERIALIZE_SCALAR(eeDataBits
);
1447 SERIALIZE_SCALAR(eeOpcode
);
1448 SERIALIZE_SCALAR(eeAddr
);
1449 SERIALIZE_ARRAY(flash
,iGbReg::EEPROM_SIZE
);
1451 rxFifo
.serialize("rxfifo", os
);
1452 txFifo
.serialize("txfifo", os
);
1454 bool txPktExists
= txPacket
;
1455 SERIALIZE_SCALAR(txPktExists
);
1457 txPacket
->serialize("txpacket", os
);
1459 Tick rdtr_time
= 0, radv_time
= 0, tidv_time
= 0, tadv_time
= 0,
1462 if (rdtrEvent
.scheduled())
1463 rdtr_time
= rdtrEvent
.when();
1464 SERIALIZE_SCALAR(rdtr_time
);
1466 if (radvEvent
.scheduled())
1467 radv_time
= radvEvent
.when();
1468 SERIALIZE_SCALAR(radv_time
);
1470 if (tidvEvent
.scheduled())
1471 tidv_time
= tidvEvent
.when();
1472 SERIALIZE_SCALAR(tidv_time
);
1474 if (tadvEvent
.scheduled())
1475 tadv_time
= tadvEvent
.when();
1476 SERIALIZE_SCALAR(tadv_time
);
1478 if (interEvent
.scheduled())
1479 inter_time
= interEvent
.when();
1480 SERIALIZE_SCALAR(inter_time
);
1482 nameOut(os
, csprintf("%s.TxDescCache", name()));
1483 txDescCache
.serialize(os
);
1485 nameOut(os
, csprintf("%s.RxDescCache", name()));
1486 rxDescCache
.serialize(os
);
1490 IGbE::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1492 PciDev::unserialize(cp
, section
);
1494 regs
.unserialize(cp
, section
);
1495 UNSERIALIZE_SCALAR(eeOpBits
);
1496 UNSERIALIZE_SCALAR(eeAddrBits
);
1497 UNSERIALIZE_SCALAR(eeDataBits
);
1498 UNSERIALIZE_SCALAR(eeOpcode
);
1499 UNSERIALIZE_SCALAR(eeAddr
);
1500 UNSERIALIZE_ARRAY(flash
,iGbReg::EEPROM_SIZE
);
1502 rxFifo
.unserialize("rxfifo", cp
, section
);
1503 txFifo
.unserialize("txfifo", cp
, section
);
1506 UNSERIALIZE_SCALAR(txPktExists
);
1508 txPacket
= new EthPacketData(16384);
1509 txPacket
->unserialize("txpacket", cp
, section
);
1516 Tick rdtr_time
, radv_time
, tidv_time
, tadv_time
, inter_time
;
1517 UNSERIALIZE_SCALAR(rdtr_time
);
1518 UNSERIALIZE_SCALAR(radv_time
);
1519 UNSERIALIZE_SCALAR(tidv_time
);
1520 UNSERIALIZE_SCALAR(tadv_time
);
1521 UNSERIALIZE_SCALAR(inter_time
);
1524 rdtrEvent
.schedule(rdtr_time
);
1527 radvEvent
.schedule(radv_time
);
1530 tidvEvent
.schedule(tidv_time
);
1533 tadvEvent
.schedule(tadv_time
);
1536 interEvent
.schedule(inter_time
);
1538 txDescCache
.unserialize(cp
, csprintf("%s.TxDescCache", section
));
1540 rxDescCache
.unserialize(cp
, csprintf("%s.RxDescCache", section
));
1544 IGbEParams::create()
1546 return new IGbE(this);