7ea4c704bc094beab57569dfe12c373e555272a6
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.
43 #include "base/inet.hh"
44 #include "base/trace.hh"
45 #include "dev/i8254xGBe.hh"
46 #include "mem/packet.hh"
47 #include "mem/packet_access.hh"
48 #include "sim/builder.hh"
49 #include "sim/stats.hh"
50 #include "sim/system.hh"
54 using namespace iGbReg
;
58 : PciDev(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), 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 // Initialized internal registers per Intel documentation
66 // All registers intialized to 0 by per register constructor
71 regs
.sts
.speed(3); // Say we're 1000Mbps
72 regs
.sts
.fd(1); // full duplex
73 regs
.sts
.lu(1); // link up
79 regs
.rxdctl
.wthresh(1);
90 // clear all 64 16 bit words of the eeprom
91 memset(&flash
, 0, EEPROM_SIZE
*2);
93 // Set the MAC address
94 memcpy(flash
, p
->hardware_address
.bytes(), ETH_ADDR_LEN
);
95 for (int x
= 0; x
< ETH_ADDR_LEN
/2; x
++)
96 flash
[x
] = htobe(flash
[x
]);
99 for (int x
= 0; x
< EEPROM_SIZE
; x
++)
100 csum
+= htobe(flash
[x
]);
103 // Magic happy checksum value
104 flash
[EEPROM_SIZE
-1] = htobe((uint16_t)(EEPROM_CSUM
- csum
));
112 IGbE::writeConfig(PacketPtr pkt
)
114 int offset
= pkt
->getAddr() & PCI_CONFIG_SIZE
;
115 if (offset
< PCI_DEVICE_SPECIFIC
)
116 PciDev::writeConfig(pkt
);
118 panic("Device specific PCI config space not implemented.\n");
121 /// Some work may need to be done here based for the pci COMMAND bits.
128 IGbE::read(PacketPtr pkt
)
133 if (!getBAR(pkt
->getAddr(), bar
, daddr
))
134 panic("Invalid PCI memory access to unmapped memory.\n");
136 // Only Memory register BAR is allowed
139 // Only 32bit accesses allowed
140 assert(pkt
->getSize() == 4);
142 DPRINTF(Ethernet
, "Read device register %#X\n", daddr
);
147 /// Handle read of register here
153 pkt
->set
<uint32_t>(regs
.ctrl());
156 pkt
->set
<uint32_t>(regs
.sts());
159 pkt
->set
<uint32_t>(regs
.eecd());
162 pkt
->set
<uint32_t>(regs
.eerd());
165 pkt
->set
<uint32_t>(regs
.ctrl_ext());
168 pkt
->set
<uint32_t>(regs
.mdic());
171 DPRINTF(Ethernet
, "Reading ICR. ICR=%#x IMR=%#x IAM=%#x IAME=%d\n", regs
.icr(),
172 regs
.imr
, regs
.iam
, regs
.ctrl_ext
.iame());
173 pkt
->set
<uint32_t>(regs
.icr());
174 if (regs
.icr
.int_assert() || regs
.imr
== 0) {
175 regs
.icr
= regs
.icr() & ~mask(30);
176 DPRINTF(Ethernet
, "Cleared ICR. ICR=%#x\n", regs
.icr());
178 if (regs
.ctrl_ext
.iame() && regs
.icr
.int_assert())
179 regs
.imr
&= ~regs
.iam
;
183 pkt
->set
<uint32_t>(regs
.itr());
186 pkt
->set
<uint32_t>(regs
.rctl());
189 pkt
->set
<uint32_t>(regs
.fcttv());
192 pkt
->set
<uint32_t>(regs
.tctl());
195 pkt
->set
<uint32_t>(regs
.pba());
199 pkt
->set
<uint32_t>(0); // We don't care, so just return 0
202 pkt
->set
<uint32_t>(regs
.fcrtl());
205 pkt
->set
<uint32_t>(regs
.fcrth());
208 pkt
->set
<uint32_t>(regs
.rdba
.rdbal());
211 pkt
->set
<uint32_t>(regs
.rdba
.rdbah());
214 pkt
->set
<uint32_t>(regs
.rdlen());
217 pkt
->set
<uint32_t>(regs
.rdh());
220 pkt
->set
<uint32_t>(regs
.rdt());
223 pkt
->set
<uint32_t>(regs
.rdtr());
224 if (regs
.rdtr
.fpd()) {
225 rxDescCache
.writeback(0);
226 DPRINTF(EthernetIntr
, "Posting interrupt because of RDTR.FPD write\n");
227 postInterrupt(IT_RXT
);
232 pkt
->set
<uint32_t>(regs
.radv());
235 pkt
->set
<uint32_t>(regs
.tdba
.tdbal());
238 pkt
->set
<uint32_t>(regs
.tdba
.tdbah());
241 pkt
->set
<uint32_t>(regs
.tdlen());
244 pkt
->set
<uint32_t>(regs
.tdh());
247 pkt
->set
<uint32_t>(regs
.tdt());
250 pkt
->set
<uint32_t>(regs
.tidv());
253 pkt
->set
<uint32_t>(regs
.txdctl());
256 pkt
->set
<uint32_t>(regs
.tadv());
259 pkt
->set
<uint32_t>(regs
.rxcsum());
262 pkt
->set
<uint32_t>(regs
.manc());
265 if (!(daddr
>= REG_VFTA
&& daddr
< (REG_VFTA
+ VLAN_FILTER_TABLE_SIZE
*4)) &&
266 !(daddr
>= REG_RAL
&& daddr
< (REG_RAL
+ RCV_ADDRESS_TABLE_SIZE
*8)) &&
267 !(daddr
>= REG_MTA
&& daddr
< (REG_MTA
+ MULTICAST_TABLE_SIZE
*4)) &&
268 !(daddr
>= REG_CRCERRS
&& daddr
< (REG_CRCERRS
+ STATS_REGS_SIZE
)))
269 panic("Read request to unknown register number: %#x\n", daddr
);
271 pkt
->set
<uint32_t>(0);
274 pkt
->makeAtomicResponse();
279 IGbE::write(PacketPtr pkt
)
285 if (!getBAR(pkt
->getAddr(), bar
, daddr
))
286 panic("Invalid PCI memory access to unmapped memory.\n");
288 // Only Memory register BAR is allowed
291 // Only 32bit accesses allowed
292 assert(pkt
->getSize() == sizeof(uint32_t));
294 DPRINTF(Ethernet
, "Wrote device register %#X value %#X\n", daddr
, pkt
->get
<uint32_t>());
297 /// Handle write of register here
299 uint32_t val
= pkt
->get
<uint32_t>();
307 if (regs
.ctrl
.tfce())
308 warn("TX Flow control enabled, should implement\n");
309 if (regs
.ctrl
.rfce())
310 warn("RX Flow control enabled, should implement\n");
320 oldClk
= regs
.eecd
.sk();
322 // See if this is a eeprom access and emulate accordingly
323 if (!oldClk
&& regs
.eecd
.sk()) {
325 eeOpcode
= eeOpcode
<< 1 | regs
.eecd
.din();
327 } else if (eeAddrBits
< 8 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) {
328 eeAddr
= eeAddr
<< 1 | regs
.eecd
.din();
330 } else if (eeDataBits
< 16 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) {
331 assert(eeAddr
>>1 < EEPROM_SIZE
);
332 DPRINTF(EthernetEEPROM
, "EEPROM bit read: %d word: %#X\n",
333 flash
[eeAddr
>>1] >> eeDataBits
& 0x1, flash
[eeAddr
>>1]);
334 regs
.eecd
.dout((flash
[eeAddr
>>1] >> (15-eeDataBits
)) & 0x1);
336 } else if (eeDataBits
< 8 && eeOpcode
== EEPROM_RDSR_OPCODE_SPI
) {
340 panic("What's going on with eeprom interface? opcode:"
341 " %#x:%d addr: %#x:%d, data: %d\n", (uint32_t)eeOpcode
,
342 (uint32_t)eeOpBits
, (uint32_t)eeAddr
,
343 (uint32_t)eeAddrBits
, (uint32_t)eeDataBits
);
345 // Reset everything for the next command
346 if ((eeDataBits
== 16 && eeOpcode
== EEPROM_READ_OPCODE_SPI
) ||
347 (eeDataBits
== 8 && eeOpcode
== EEPROM_RDSR_OPCODE_SPI
)) {
355 DPRINTF(EthernetEEPROM
, "EEPROM: opcode: %#X:%d addr: %#X:%d\n",
356 (uint32_t)eeOpcode
, (uint32_t) eeOpBits
,
357 (uint32_t)eeAddr
>>1, (uint32_t)eeAddrBits
);
358 if (eeOpBits
== 8 && !(eeOpcode
== EEPROM_READ_OPCODE_SPI
||
359 eeOpcode
== EEPROM_RDSR_OPCODE_SPI
))
360 panic("Unknown eeprom opcode: %#X:%d\n", (uint32_t)eeOpcode
,
365 // If driver requests eeprom access, immediately give it to it
366 regs
.eecd
.ee_gnt(regs
.eecd
.ee_req());
374 panic("No support for interrupt on mdic complete\n");
375 if (regs
.mdic
.phyadd() != 1)
376 panic("No support for reading anything but phy\n");
377 DPRINTF(Ethernet
, "%s phy address %x\n", regs
.mdic
.op() == 1 ? "Writing"
378 : "Reading", regs
.mdic
.regadd());
379 switch (regs
.mdic
.regadd()) {
381 regs
.mdic
.data(0x796D); // link up
384 regs
.mdic
.data(0x02A8);
387 regs
.mdic
.data(0x0380);
390 regs
.mdic
.data(0x7C00);
393 regs
.mdic
.data(0x3000);
396 regs
.mdic
.data(0x180); // some random length
404 DPRINTF(Ethernet
, "Writing ICR. ICR=%#x IMR=%#x IAM=%#x IAME=%d\n", regs
.icr(),
405 regs
.imr
, regs
.iam
, regs
.ctrl_ext
.iame());
406 if (regs
.ctrl_ext
.iame())
407 regs
.imr
&= ~regs
.iam
;
408 regs
.icr
= ~bits(val
,30,0) & regs
.icr();
415 DPRINTF(EthernetIntr
, "Posting interrupt because of ICS write\n");
416 postInterrupt((IntTypes
)val
);
432 if (regs
.rctl
.rst()) {
434 DPRINTF(EthernetSM
, "RXS: Got RESET!\n");
452 if (regs
.tctl
.en() && !oldtctl
.en()) {
458 regs
.pba
.txa(64 - regs
.pba
.rxa());
468 ; // We don't care, so don't store anything
477 regs
.rdba
.rdbal( val
& ~mask(4));
478 rxDescCache
.areaChanged();
481 regs
.rdba
.rdbah(val
);
482 rxDescCache
.areaChanged();
485 regs
.rdlen
= val
& ~mask(7);
486 rxDescCache
.areaChanged();
490 rxDescCache
.areaChanged();
504 regs
.tdba
.tdbal( val
& ~mask(4));
505 txDescCache
.areaChanged();
508 regs
.tdba
.tdbah(val
);
509 txDescCache
.areaChanged();
512 regs
.tdlen
= val
& ~mask(7);
513 txDescCache
.areaChanged();
517 txDescCache
.areaChanged();
540 if (!(daddr
>= REG_VFTA
&& daddr
< (REG_VFTA
+ VLAN_FILTER_TABLE_SIZE
*4)) &&
541 !(daddr
>= REG_RAL
&& daddr
< (REG_RAL
+ RCV_ADDRESS_TABLE_SIZE
*8)) &&
542 !(daddr
>= REG_MTA
&& daddr
< (REG_MTA
+ MULTICAST_TABLE_SIZE
*4)))
543 panic("Write request to unknown register number: %#x\n", daddr
);
546 pkt
->makeAtomicResponse();
551 IGbE::postInterrupt(IntTypes t
, bool now
)
555 // Interrupt is already pending
559 if (regs
.icr() & regs
.imr
)
561 regs
.icr
= regs
.icr() | t
;
562 if (!interEvent
.scheduled())
563 interEvent
.schedule(curTick
+ Clock::Int::ns
* 256 *
564 regs
.itr
.interval());
566 regs
.icr
= regs
.icr() | t
;
567 if (regs
.itr
.interval() == 0 || now
) {
568 if (interEvent
.scheduled())
569 interEvent
.deschedule();
572 DPRINTF(EthernetIntr
, "EINT: Scheduling timer interrupt for %d ticks\n",
573 Clock::Int::ns
* 256 * regs
.itr
.interval());
574 if (!interEvent
.scheduled())
575 interEvent
.schedule(curTick
+ Clock::Int::ns
* 256 * regs
.itr
.interval());
583 if (rdtrEvent
.scheduled()) {
585 rdtrEvent
.deschedule();
587 if (radvEvent
.scheduled()) {
589 radvEvent
.deschedule();
591 if (tadvEvent
.scheduled()) {
593 tadvEvent
.deschedule();
595 if (tidvEvent
.scheduled()) {
597 tidvEvent
.deschedule();
600 regs
.icr
.int_assert(1);
601 DPRINTF(EthernetIntr
, "EINT: Posting interrupt to CPU now. Vector %#x\n",
609 if (regs
.icr
.int_assert()) {
610 regs
.icr
.int_assert(0);
611 DPRINTF(EthernetIntr
, "EINT: Clearing interrupt to CPU now. Vector %#x\n",
620 // Check if we need to clear the cpu interrupt
621 if (!(regs
.icr() & regs
.imr
)) {
622 if (interEvent
.scheduled())
623 interEvent
.deschedule();
624 if (regs
.icr
.int_assert())
628 if (regs
.icr() & regs
.imr
) {
629 if (regs
.itr
.interval() == 0) {
632 if (!interEvent
.scheduled())
633 interEvent
.schedule(curTick
+ Clock::Int::ns
* 256 * regs
.itr
.interval());
641 IGbE::RxDescCache::RxDescCache(IGbE
*i
, const std::string n
, int s
)
642 : DescCache
<RxDesc
>(i
, n
, s
), pktDone(false), pktEvent(this)
648 IGbE::RxDescCache::writePacket(EthPacketPtr packet
)
650 // We shouldn't have to deal with any of these yet
651 DPRINTF(EthernetDesc
, "Packet Length: %d Desc Size: %d\n",
652 packet
->length
, igbe
->regs
.rctl
.descSize());
653 assert(packet
->length
< igbe
->regs
.rctl
.descSize());
655 if (!unusedCache
.size())
660 igbe
->dmaWrite(igbe
->platform
->pciToDma(unusedCache
.front()->buf
),
661 packet
->length
, &pktEvent
, packet
->data
);
666 IGbE::RxDescCache::pktComplete()
668 assert(unusedCache
.size());
670 desc
= unusedCache
.front();
672 uint16_t crcfixup
= igbe
->regs
.rctl
.secrc() ? 0 : 4 ;
673 desc
->len
= htole((uint16_t)(pktPtr
->length
+ crcfixup
));
674 DPRINTF(EthernetDesc
, "pktPtr->length: %d stripcrc offset: %d value written: %d %d\n",
675 pktPtr
->length
, crcfixup
,
676 htole((uint16_t)(pktPtr
->length
+ crcfixup
)),
677 (uint16_t)(pktPtr
->length
+ crcfixup
));
679 // no support for anything but starting at 0
680 assert(igbe
->regs
.rxcsum
.pcss() == 0);
682 DPRINTF(EthernetDesc
, "Packet written to memory updating Descriptor\n");
684 uint8_t status
= RXDS_DD
| RXDS_EOP
;
690 DPRINTF(EthernetDesc
, "Proccesing Ip packet with Id=%d\n", ip
->id());
692 if (igbe
->regs
.rxcsum
.ipofld()) {
693 DPRINTF(EthernetDesc
, "Checking IP checksum\n");
695 desc
->csum
= htole(cksum(ip
));
696 if (cksum(ip
) != 0) {
698 DPRINTF(EthernetDesc
, "Checksum is bad!!\n");
702 if (tcp
&& igbe
->regs
.rxcsum
.tuofld()) {
703 DPRINTF(EthernetDesc
, "Checking TCP checksum\n");
704 status
|= RXDS_TCPCS
;
705 desc
->csum
= htole(cksum(tcp
));
706 if (cksum(tcp
) != 0) {
707 DPRINTF(EthernetDesc
, "Checksum is bad!!\n");
713 if (udp
&& igbe
->regs
.rxcsum
.tuofld()) {
714 DPRINTF(EthernetDesc
, "Checking UDP checksum\n");
715 status
|= RXDS_UDPCS
;
716 desc
->csum
= htole(cksum(udp
));
717 if (cksum(udp
) != 0) {
718 DPRINTF(EthernetDesc
, "Checksum is bad!!\n");
723 DPRINTF(EthernetSM
, "Proccesing Non-Ip packet\n");
727 desc
->status
= htole(status
);
728 desc
->errors
= htole(err
);
730 // No vlan support at this point... just set it to 0
733 // Deal with the rx timer interrupts
734 if (igbe
->regs
.rdtr
.delay()) {
735 DPRINTF(EthernetSM
, "RXS: Scheduling DTR for %d\n",
736 igbe
->regs
.rdtr
.delay() * igbe
->intClock());
737 igbe
->rdtrEvent
.reschedule(curTick
+ igbe
->regs
.rdtr
.delay() *
738 igbe
->intClock(),true);
741 if (igbe
->regs
.radv
.idv() && igbe
->regs
.rdtr
.delay()) {
742 DPRINTF(EthernetSM
, "RXS: Scheduling ADV for %d\n",
743 igbe
->regs
.radv
.idv() * igbe
->intClock());
744 if (!igbe
->radvEvent
.scheduled())
745 igbe
->radvEvent
.schedule(curTick
+ igbe
->regs
.radv
.idv() *
749 // if neither radv or rdtr, maybe itr is set...
750 if (!igbe
->regs
.rdtr
.delay()) {
751 DPRINTF(EthernetSM
, "RXS: Receive interrupt delay disabled, posting IT_RXT\n");
752 igbe
->postInterrupt(IT_RXT
);
755 // If the packet is small enough, interrupt appropriately
756 // I wonder if this is delayed or not?!
757 if (pktPtr
->length
<= igbe
->regs
.rsrpd
.idv()) {
758 DPRINTF(EthernetSM
, "RXS: Posting IT_SRPD beacuse small packet received\n");
759 igbe
->postInterrupt(IT_SRPD
);
762 DPRINTF(EthernetDesc
, "Processing of this descriptor complete\n");
763 unusedCache
.pop_front();
764 usedCache
.push_back(desc
);
772 IGbE::RxDescCache::enableSm()
775 igbe
->restartClock();
779 IGbE::RxDescCache::packetDone()
789 IGbE::RxDescCache::hasOutstandingEvents()
791 return pktEvent
.scheduled() || wbEvent
.scheduled() ||
792 fetchEvent
.scheduled();
796 IGbE::RxDescCache::serialize(std::ostream
&os
)
798 DescCache
<RxDesc
>::serialize(os
);
799 SERIALIZE_SCALAR(pktDone
);
803 IGbE::RxDescCache::unserialize(Checkpoint
*cp
, const std::string
§ion
)
805 DescCache
<RxDesc
>::unserialize(cp
, section
);
806 UNSERIALIZE_SCALAR(pktDone
);
810 ///////////////////////////////////// IGbE::TxDesc /////////////////////////////////
812 IGbE::TxDescCache::TxDescCache(IGbE
*i
, const std::string n
, int s
)
813 : DescCache
<TxDesc
>(i
,n
, s
), pktDone(false), isTcp(false), pktWaiting(false),
820 IGbE::TxDescCache::getPacketSize()
822 assert(unusedCache
.size());
826 DPRINTF(EthernetDesc
, "Starting processing of descriptor\n");
828 while (unusedCache
.size() && TxdOp::isContext(unusedCache
.front())) {
829 DPRINTF(EthernetDesc
, "Got context descriptor type... skipping\n");
831 // I think we can just ignore these for now?
832 desc
= unusedCache
.front();
833 // is this going to be a tcp or udp packet?
834 isTcp
= TxdOp::tcp(desc
) ? true : false;
836 // make sure it's ipv4
837 assert(TxdOp::ip(desc
));
840 unusedCache
.pop_front();
841 usedCache
.push_back(desc
);
844 if (!unusedCache
.size())
847 DPRINTF(EthernetDesc
, "Next TX packet is %d bytes\n",
848 TxdOp::getLen(unusedCache
.front()));
850 return TxdOp::getLen(unusedCache
.front());
854 IGbE::TxDescCache::getPacketData(EthPacketPtr p
)
856 assert(unusedCache
.size());
859 desc
= unusedCache
.front();
861 assert((TxdOp::isLegacy(desc
) || TxdOp::isData(desc
)) && TxdOp::getLen(desc
));
867 DPRINTF(EthernetDesc
, "Starting DMA of packet\n");
868 igbe
->dmaRead(igbe
->platform
->pciToDma(TxdOp::getBuf(desc
)),
869 TxdOp::getLen(desc
), &pktEvent
, p
->data
+ p
->length
);
875 IGbE::TxDescCache::pktComplete()
879 assert(unusedCache
.size());
882 DPRINTF(EthernetDesc
, "DMA of packet complete\n");
885 desc
= unusedCache
.front();
886 assert((TxdOp::isLegacy(desc
) || TxdOp::isData(desc
)) && TxdOp::getLen(desc
));
888 DPRINTF(EthernetDesc
, "TxDescriptor data d1: %#llx d2: %#llx\n", desc
->d1
, desc
->d2
);
890 if (!TxdOp::eop(desc
)) {
891 // This only supports two descriptors per tx packet
892 assert(pktPtr
->length
== 0);
893 pktPtr
->length
= TxdOp::getLen(desc
);
894 unusedCache
.pop_front();
895 usedCache
.push_back(desc
);
900 DPRINTF(EthernetDesc
, "Partial Packet Descriptor Done\n");
905 // Set the length of the data in the EtherPacket
906 pktPtr
->length
+= TxdOp::getLen(desc
);
908 // no support for vlans
909 assert(!TxdOp::vle(desc
));
911 // we alway report status
912 assert(TxdOp::rs(desc
));
914 // we only support single packet descriptors at this point
915 assert(TxdOp::eop(desc
));
917 // set that this packet is done
920 DPRINTF(EthernetDesc
, "TxDescriptor data d1: %#llx d2: %#llx\n", desc
->d1
, desc
->d2
);
922 if (DTRACE(EthernetDesc
)) {
925 DPRINTF(EthernetDesc
, "Proccesing Ip packet with Id=%d\n",
928 DPRINTF(EthernetSM
, "Proccesing Non-Ip packet\n");
931 // Checksums are only ofloaded for new descriptor types
932 if (TxdOp::isData(desc
) && ( TxdOp::ixsm(desc
) || TxdOp::txsm(desc
)) ) {
933 DPRINTF(EthernetDesc
, "Calculating checksums for packet\n");
936 if (TxdOp::ixsm(desc
)) {
939 DPRINTF(EthernetDesc
, "Calculated IP checksum\n");
941 if (TxdOp::txsm(desc
)) {
946 tcp
->sum(cksum(tcp
));
947 DPRINTF(EthernetDesc
, "Calculated TCP checksum\n");
952 udp
->sum(cksum(udp
));
953 DPRINTF(EthernetDesc
, "Calculated UDP checksum\n");
958 if (TxdOp::ide(desc
)) {
959 // Deal with the rx timer interrupts
960 DPRINTF(EthernetDesc
, "Descriptor had IDE set\n");
961 if (igbe
->regs
.tidv
.idv()) {
962 DPRINTF(EthernetDesc
, "setting tidv\n");
963 igbe
->tidvEvent
.reschedule(curTick
+ igbe
->regs
.tidv
.idv() *
964 igbe
->intClock(), true);
967 if (igbe
->regs
.tadv
.idv() && igbe
->regs
.tidv
.idv()) {
968 DPRINTF(EthernetDesc
, "setting tadv\n");
969 if (!igbe
->tadvEvent
.scheduled())
970 igbe
->tadvEvent
.schedule(curTick
+ igbe
->regs
.tadv
.idv() *
977 unusedCache
.pop_front();
978 usedCache
.push_back(desc
);
983 DPRINTF(EthernetDesc
, "Descriptor Done\n");
985 if (igbe
->regs
.txdctl
.wthresh() == 0) {
986 DPRINTF(EthernetDesc
, "WTHRESH == 0, writing back descriptor\n");
988 } else if (igbe
->regs
.txdctl
.wthresh() >= usedCache
.size()) {
989 DPRINTF(EthernetDesc
, "used > WTHRESH, writing back descriptor\n");
990 writeback((igbe
->cacheBlockSize()-1)>>4);
997 IGbE::TxDescCache::serialize(std::ostream
&os
)
999 DescCache
<TxDesc
>::serialize(os
);
1000 SERIALIZE_SCALAR(pktDone
);
1001 SERIALIZE_SCALAR(isTcp
);
1002 SERIALIZE_SCALAR(pktWaiting
);
1006 IGbE::TxDescCache::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1008 DescCache
<TxDesc
>::unserialize(cp
, section
);
1009 UNSERIALIZE_SCALAR(pktDone
);
1010 UNSERIALIZE_SCALAR(isTcp
);
1011 UNSERIALIZE_SCALAR(pktWaiting
);
1015 IGbE::TxDescCache::packetAvailable()
1025 IGbE::TxDescCache::enableSm()
1027 igbe
->txTick
= true;
1028 igbe
->restartClock();
1032 IGbE::TxDescCache::hasOutstandingEvents()
1034 return pktEvent
.scheduled() || wbEvent
.scheduled() ||
1035 fetchEvent
.scheduled();
1039 ///////////////////////////////////// IGbE /////////////////////////////////
1042 IGbE::restartClock()
1044 if (!tickEvent
.scheduled() && (rxTick
|| txTick
|| txFifoTick
) && getState() ==
1046 tickEvent
.schedule((curTick
/cycles(1)) * cycles(1) + cycles(1));
1050 IGbE::drain(Event
*de
)
1053 count
= pioPort
->drain(de
) + dmaPort
->drain(de
);
1054 if (rxDescCache
.hasOutstandingEvents() ||
1055 txDescCache
.hasOutstandingEvents()) {
1064 if (tickEvent
.scheduled())
1065 tickEvent
.deschedule();
1068 changeState(Draining
);
1070 changeState(Drained
);
1078 SimObject::resume();
1093 if (rxDescCache
.hasOutstandingEvents() ||
1094 txDescCache
.hasOutstandingEvents()) {
1095 drainEvent
->process();
1101 IGbE::txStateMachine()
1103 if (!regs
.tctl
.en()) {
1105 DPRINTF(EthernetSM
, "TXS: TX disabled, stopping ticking\n");
1109 // If we have a packet available and it's length is not 0 (meaning it's not
1110 // a multidescriptor packet) put it in the fifo, otherwise an the next
1111 // iteration we'll get the rest of the data
1112 if (txPacket
&& txDescCache
.packetAvailable() && txPacket
->length
) {
1114 DPRINTF(EthernetSM
, "TXS: packet placed in TX FIFO\n");
1115 success
= txFifo
.push(txPacket
);
1119 txDescCache
.writeback((cacheBlockSize()-1)>>4);
1123 // Only support descriptor granularity
1124 assert(regs
.txdctl
.gran());
1125 if (regs
.txdctl
.lwthresh() && txDescCache
.descLeft() < (regs
.txdctl
.lwthresh() * 8)) {
1126 DPRINTF(EthernetSM
, "TXS: LWTHRESH caused posting of TXDLOW\n");
1127 postInterrupt(IT_TXDLOW
);
1131 txPacket
= new EthPacketData(16384);
1134 if (!txDescCache
.packetWaiting()) {
1135 if (txDescCache
.descLeft() == 0) {
1136 DPRINTF(EthernetSM
, "TXS: No descriptors left in ring, forcing "
1137 "writeback stopping ticking and posting TXQE\n");
1138 txDescCache
.writeback(0);
1140 postInterrupt(IT_TXQE
, true);
1145 if (!(txDescCache
.descUnused())) {
1146 DPRINTF(EthernetSM
, "TXS: No descriptors available in cache, fetching and stopping ticking\n");
1148 txDescCache
.fetchDescriptors();
1153 size
= txDescCache
.getPacketSize();
1154 if (size
> 0 && txFifo
.avail() > size
) {
1155 DPRINTF(EthernetSM
, "TXS: Reserving %d bytes in FIFO and begining "
1156 "DMA of next packet\n", size
);
1157 txFifo
.reserve(size
);
1158 txDescCache
.getPacketData(txPacket
);
1159 } else if (size
<= 0) {
1160 DPRINTF(EthernetSM
, "TXS: No packets to get, writing back used descriptors\n");
1161 txDescCache
.writeback(0);
1163 DPRINTF(EthernetSM
, "TXS: FIFO full, stopping ticking until space "
1164 "available in FIFO\n");
1165 txDescCache
.writeback((cacheBlockSize()-1)>>4);
1172 DPRINTF(EthernetSM
, "TXS: Nothing to do, stopping ticking\n");
1177 IGbE::ethRxPkt(EthPacketPtr pkt
)
1179 DPRINTF(Ethernet
, "RxFIFO: Receiving pcakte from wire\n");
1180 if (!regs
.rctl
.en()) {
1181 DPRINTF(Ethernet
, "RxFIFO: RX not enabled, dropping\n");
1185 // restart the state machines if they are stopped
1187 if ((rxTick
|| txTick
) && !tickEvent
.scheduled()) {
1188 DPRINTF(EthernetSM
, "RXS: received packet into fifo, starting ticking\n");
1192 if (!rxFifo
.push(pkt
)) {
1193 DPRINTF(Ethernet
, "RxFIFO: Packet won't fit in fifo... dropped\n");
1194 postInterrupt(IT_RXO
, true);
1202 IGbE::rxStateMachine()
1204 if (!regs
.rctl
.en()) {
1206 DPRINTF(EthernetSM
, "RXS: RX disabled, stopping ticking\n");
1210 // If the packet is done check for interrupts/descriptors/etc
1211 if (rxDescCache
.packetDone()) {
1212 rxDmaPacket
= false;
1213 DPRINTF(EthernetSM
, "RXS: Packet completed DMA to memory\n");
1214 int descLeft
= rxDescCache
.descLeft();
1215 switch (regs
.rctl
.rdmts()) {
1216 case 2: if (descLeft
> .125 * regs
.rdlen()) break;
1217 case 1: if (descLeft
> .250 * regs
.rdlen()) break;
1218 case 0: if (descLeft
> .500 * regs
.rdlen()) break;
1219 DPRINTF(Ethernet
, "RXS: Interrupting (RXDMT) because of descriptors left\n");
1220 postInterrupt(IT_RXDMT
);
1224 if (descLeft
== 0) {
1225 DPRINTF(EthernetSM
, "RXS: No descriptors left in ring, forcing"
1226 " writeback and stopping ticking\n");
1227 rxDescCache
.writeback(0);
1231 // only support descriptor granulaties
1232 assert(regs
.rxdctl
.gran());
1234 if (regs
.rxdctl
.wthresh() >= rxDescCache
.descUsed()) {
1235 DPRINTF(EthernetSM
, "RXS: Writing back because WTHRESH >= descUsed\n");
1236 if (regs
.rxdctl
.wthresh() < (cacheBlockSize()>>4))
1237 rxDescCache
.writeback(regs
.rxdctl
.wthresh()-1);
1239 rxDescCache
.writeback((cacheBlockSize()-1)>>4);
1242 if ((rxDescCache
.descUnused() < regs
.rxdctl
.pthresh()) &&
1243 ((rxDescCache
.descLeft() - rxDescCache
.descUnused()) > regs
.rxdctl
.hthresh())) {
1244 DPRINTF(EthernetSM
, "RXS: Fetching descriptors because descUnused < PTHRESH\n");
1245 rxDescCache
.fetchDescriptors();
1248 if (rxDescCache
.descUnused() == 0) {
1249 DPRINTF(EthernetSM
, "RXS: No descriptors available in cache, "
1250 "fetching descriptors and stopping ticking\n");
1252 rxDescCache
.fetchDescriptors();
1258 DPRINTF(EthernetSM
, "RXS: stopping ticking until packet DMA completes\n");
1263 if (!rxDescCache
.descUnused()) {
1264 DPRINTF(EthernetSM
, "RXS: No descriptors available in cache, stopping ticking\n");
1266 DPRINTF(EthernetSM
, "RXS: No descriptors available, fetching\n");
1267 rxDescCache
.fetchDescriptors();
1271 if (rxFifo
.empty()) {
1272 DPRINTF(EthernetSM
, "RXS: RxFIFO empty, stopping ticking\n");
1278 pkt
= rxFifo
.front();
1280 DPRINTF(EthernetSM
, "RXS: Writing packet into memory\n");
1281 if (!rxDescCache
.writePacket(pkt
)) {
1285 DPRINTF(EthernetSM
, "RXS: Removing packet from FIFO\n");
1287 DPRINTF(EthernetSM
, "RXS: stopping ticking until packet DMA completes\n");
1295 if (txFifo
.empty()) {
1301 if (etherInt
->sendPacket(txFifo
.front())) {
1302 DPRINTF(EthernetSM
, "TxFIFO: Successful transmit, bytes available in fifo: %d\n",
1306 // We'll get woken up when the packet ethTxDone() gets called
1315 DPRINTF(EthernetSM
, "IGbE: -------------- Cycle --------------\n");
1327 if (rxTick
|| txTick
|| txFifoTick
)
1328 tickEvent
.schedule(curTick
+ cycles(1));
1334 // restart the tx state machines if they are stopped
1335 // fifo to send another packet
1336 // tx sm to put more data into the fifo
1341 DPRINTF(EthernetSM
, "TxFIFO: Transmission complete\n");
1345 IGbE::serialize(std::ostream
&os
)
1347 PciDev::serialize(os
);
1350 SERIALIZE_SCALAR(eeOpBits
);
1351 SERIALIZE_SCALAR(eeAddrBits
);
1352 SERIALIZE_SCALAR(eeDataBits
);
1353 SERIALIZE_SCALAR(eeOpcode
);
1354 SERIALIZE_SCALAR(eeAddr
);
1355 SERIALIZE_ARRAY(flash
,iGbReg::EEPROM_SIZE
);
1357 rxFifo
.serialize("rxfifo", os
);
1358 txFifo
.serialize("txfifo", os
);
1360 bool txPktExists
= txPacket
;
1361 SERIALIZE_SCALAR(txPktExists
);
1363 txPacket
->serialize("txpacket", os
);
1365 Tick rdtr_time
= 0, radv_time
= 0, tidv_time
= 0, tadv_time
= 0,
1368 if (rdtrEvent
.scheduled())
1369 rdtr_time
= rdtrEvent
.when();
1370 SERIALIZE_SCALAR(rdtr_time
);
1372 if (radvEvent
.scheduled())
1373 radv_time
= radvEvent
.when();
1374 SERIALIZE_SCALAR(radv_time
);
1376 if (tidvEvent
.scheduled())
1377 rdtr_time
= tidvEvent
.when();
1378 SERIALIZE_SCALAR(tidv_time
);
1380 if (tadvEvent
.scheduled())
1381 rdtr_time
= tadvEvent
.when();
1382 SERIALIZE_SCALAR(tadv_time
);
1384 if (interEvent
.scheduled())
1385 rdtr_time
= interEvent
.when();
1386 SERIALIZE_SCALAR(inter_time
);
1388 nameOut(os
, csprintf("%s.TxDescCache", name()));
1389 txDescCache
.serialize(os
);
1391 nameOut(os
, csprintf("%s.RxDescCache", name()));
1392 rxDescCache
.serialize(os
);
1396 IGbE::unserialize(Checkpoint
*cp
, const std::string
§ion
)
1398 PciDev::unserialize(cp
, section
);
1400 regs
.unserialize(cp
, section
);
1401 UNSERIALIZE_SCALAR(eeOpBits
);
1402 UNSERIALIZE_SCALAR(eeAddrBits
);
1403 UNSERIALIZE_SCALAR(eeDataBits
);
1404 UNSERIALIZE_SCALAR(eeOpcode
);
1405 UNSERIALIZE_SCALAR(eeAddr
);
1406 UNSERIALIZE_ARRAY(flash
,iGbReg::EEPROM_SIZE
);
1408 rxFifo
.unserialize("rxfifo", cp
, section
);
1409 txFifo
.unserialize("txfifo", cp
, section
);
1412 UNSERIALIZE_SCALAR(txPktExists
);
1414 txPacket
= new EthPacketData(16384);
1415 txPacket
->unserialize("txpacket", cp
, section
);
1422 Tick rdtr_time
, radv_time
, tidv_time
, tadv_time
, inter_time
;
1423 UNSERIALIZE_SCALAR(rdtr_time
);
1424 UNSERIALIZE_SCALAR(radv_time
);
1425 UNSERIALIZE_SCALAR(tidv_time
);
1426 UNSERIALIZE_SCALAR(tadv_time
);
1427 UNSERIALIZE_SCALAR(inter_time
);
1430 rdtrEvent
.schedule(rdtr_time
);
1433 radvEvent
.schedule(radv_time
);
1436 tidvEvent
.schedule(tidv_time
);
1439 tadvEvent
.schedule(tadv_time
);
1442 interEvent
.schedule(inter_time
);
1444 txDescCache
.unserialize(cp
, csprintf("%s.TxDescCache", section
));
1446 rxDescCache
.unserialize(cp
, csprintf("%s.RxDescCache", section
));
1450 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbEInt
)
1452 SimObjectParam
<EtherInt
*> peer
;
1453 SimObjectParam
<IGbE
*> device
;
1455 END_DECLARE_SIM_OBJECT_PARAMS(IGbEInt
)
1457 BEGIN_INIT_SIM_OBJECT_PARAMS(IGbEInt
)
1459 INIT_PARAM_DFLT(peer
, "peer interface", NULL
),
1460 INIT_PARAM(device
, "Ethernet device of this interface")
1462 END_INIT_SIM_OBJECT_PARAMS(IGbEInt
)
1464 CREATE_SIM_OBJECT(IGbEInt
)
1466 IGbEInt
*dev_int
= new IGbEInt(getInstanceName(), device
);
1468 EtherInt
*p
= (EtherInt
*)peer
;
1470 dev_int
->setPeer(p
);
1471 p
->setPeer(dev_int
);
1477 REGISTER_SIM_OBJECT("IGbEInt", IGbEInt
)
1480 BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbE
)
1482 SimObjectParam
<System
*> system
;
1483 SimObjectParam
<Platform
*> platform
;
1484 Param
<Tick
> min_backoff_delay
;
1485 Param
<Tick
> max_backoff_delay
;
1486 SimObjectParam
<PciConfigData
*> configdata
;
1487 Param
<uint32_t> pci_bus
;
1488 Param
<uint32_t> pci_dev
;
1489 Param
<uint32_t> pci_func
;
1490 Param
<Tick
> pio_latency
;
1491 Param
<Tick
> config_latency
;
1492 Param
<std::string
> hardware_address
;
1493 Param
<bool> use_flow_control
;
1494 Param
<int> rx_fifo_size
;
1495 Param
<int> tx_fifo_size
;
1496 Param
<int> rx_desc_cache_size
;
1497 Param
<int> tx_desc_cache_size
;
1501 END_DECLARE_SIM_OBJECT_PARAMS(IGbE
)
1503 BEGIN_INIT_SIM_OBJECT_PARAMS(IGbE
)
1505 INIT_PARAM(system
, "System pointer"),
1506 INIT_PARAM(platform
, "Platform pointer"),
1507 INIT_PARAM(min_backoff_delay
, "Minimum delay after receving a nack packed"),
1508 INIT_PARAM(max_backoff_delay
, "Maximum delay after receving a nack packed"),
1509 INIT_PARAM(configdata
, "PCI Config data"),
1510 INIT_PARAM(pci_bus
, "PCI bus ID"),
1511 INIT_PARAM(pci_dev
, "PCI device number"),
1512 INIT_PARAM(pci_func
, "PCI function code"),
1513 INIT_PARAM_DFLT(pio_latency
, "Programmed IO latency in bus cycles", 1),
1514 INIT_PARAM(config_latency
, "Number of cycles for a config read or write"),
1515 INIT_PARAM(hardware_address
, "Ethernet Hardware Address"),
1516 INIT_PARAM(use_flow_control
,"Should the device use xon/off packets"),
1517 INIT_PARAM(rx_fifo_size
,"Size of the RX FIFO"),
1518 INIT_PARAM(tx_fifo_size
,"Size of the TX FIFO"),
1519 INIT_PARAM(rx_desc_cache_size
,"Size of the RX descriptor cache"),
1520 INIT_PARAM(tx_desc_cache_size
,"Size of the TX descriptor cache"),
1521 INIT_PARAM(clock
,"Clock rate for the device to tick at")
1523 END_INIT_SIM_OBJECT_PARAMS(IGbE
)
1526 CREATE_SIM_OBJECT(IGbE
)
1528 IGbE::Params
*params
= new IGbE::Params
;
1530 params
->name
= getInstanceName();
1531 params
->platform
= platform
;
1532 params
->system
= system
;
1533 params
->min_backoff_delay
= min_backoff_delay
;
1534 params
->max_backoff_delay
= max_backoff_delay
;
1535 params
->configData
= configdata
;
1536 params
->busNum
= pci_bus
;
1537 params
->deviceNum
= pci_dev
;
1538 params
->functionNum
= pci_func
;
1539 params
->pio_delay
= pio_latency
;
1540 params
->config_delay
= config_latency
;
1541 params
->hardware_address
= hardware_address
;
1542 params
->use_flow_control
= use_flow_control
;
1543 params
->rx_fifo_size
= rx_fifo_size
;
1544 params
->tx_fifo_size
= tx_fifo_size
;
1545 params
->rx_desc_cache_size
= rx_desc_cache_size
;
1546 params
->tx_desc_cache_size
= tx_desc_cache_size
;
1547 params
->clock
= clock
;
1550 return new IGbE(params
);
1553 REGISTER_SIM_OBJECT("IGbE", IGbE
)