IGbE::IGbE(const Params *p)
: EtherDevice(p), etherInt(NULL), drainEvent(NULL), useFlowControl(p->use_flow_control),
rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxTick(false),
- txTick(false), txFifoTick(false), rxDmaPacket(false), rdtrEvent(this), radvEvent(this),
+ txTick(false), txFifoTick(false), rxDmaPacket(false),
+ fetchDelay(p->fetch_delay), wbDelay(p->wb_delay),
+ fetchCompDelay(p->fetch_comp_delay), wbCompDelay(p->wb_comp_delay),
+ rxWriteDelay(p->rx_write_delay), txReadDelay(p->tx_read_delay),
+ rdtrEvent(this), radvEvent(this),
tadvEvent(this), tidvEvent(this), tickEvent(this), interEvent(this),
rxDescCache(this, name()+".RxDesc", p->rx_desc_cache_size),
- txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size), clock(p->clock)
+ txDescCache(this, name()+".TxDesc", p->tx_desc_cache_size),
+ clock(p->clock), lastInterrupt(0)
{
etherInt = new IGbEInt(name() + ".int", this);
return;
regs.icr = regs.icr() | t;
- if (regs.itr.interval() == 0 || now) {
+
+ Tick itr_interval = Clock::Int::ns * 256 * regs.itr.interval();
+ DPRINTF(EthernetIntr, "EINT: postInterrupt() curTick: %d itr: %d interval: %d\n",
+ curTick, regs.itr.interval(), itr_interval);
+
+ if (regs.itr.interval() == 0 || now || lastInterrupt + itr_interval <= curTick) {
if (interEvent.scheduled()) {
interEvent.deschedule();
}
cpuPostInt();
} else {
- DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for %d ticks\n",
- Clock::Int::ns * 256 * regs.itr.interval());
+ Tick int_time = lastInterrupt + itr_interval;
+ assert(int_time > 0);
+ DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for tick %d\n",
+ int_time);
if (!interEvent.scheduled()) {
- interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval());
+ interEvent.schedule(int_time);
}
}
}
IGbE::cpuPostInt()
{
+ postedInterrupts++;
+
if (!(regs.icr() & regs.imr)) {
DPRINTF(Ethernet, "Interrupt Masked. Not Posting\n");
return;
intrPost();
+ lastInterrupt = curTick;
}
void
pktPtr = packet;
pktDone = false;
igbe->dmaWrite(igbe->platform->pciToDma(unusedCache.front()->buf),
- packet->length, &pktEvent, packet->data);
+ packet->length, &pktEvent, packet->data, igbe->rxWriteDelay);
}
void
DPRINTF(EthernetDesc, "Checking IP checksum\n");
status |= RXDS_IPCS;
desc->csum = htole(cksum(ip));
+ igbe->rxIpChecksums++;
if (cksum(ip) != 0) {
err |= RXDE_IPE;
DPRINTF(EthernetDesc, "Checksum is bad!!\n");
DPRINTF(EthernetDesc, "Checking TCP checksum\n");
status |= RXDS_TCPCS;
desc->csum = htole(cksum(tcp));
+ igbe->rxTcpChecksums++;
if (cksum(tcp) != 0) {
DPRINTF(EthernetDesc, "Checksum is bad!!\n");
err |= RXDE_TCPE;
DPRINTF(EthernetDesc, "Checking UDP checksum\n");
status |= RXDS_UDPCS;
desc->csum = htole(cksum(udp));
+ igbe->rxUdpChecksums++;
if (cksum(udp) != 0) {
DPRINTF(EthernetDesc, "Checksum is bad!!\n");
err |= RXDE_TCPE;
igbe->intClock(),true);
}
- if (igbe->regs.radv.idv() && igbe->regs.rdtr.delay()) {
+ if (igbe->regs.radv.idv()) {
DPRINTF(EthernetSM, "RXS: Scheduling ADV for %d\n",
igbe->regs.radv.idv() * igbe->intClock());
if (!igbe->radvEvent.scheduled()) {
}
// if neither radv or rdtr, maybe itr is set...
- if (!igbe->regs.rdtr.delay()) {
+ if (!igbe->regs.rdtr.delay() && !igbe->regs.radv.idv()) {
DPRINTF(EthernetSM, "RXS: Receive interrupt delay disabled, posting IT_RXT\n");
igbe->postInterrupt(IT_RXT);
}
DPRINTF(EthernetDesc, "Starting DMA of packet at offset %d\n", p->length);
igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)),
- TxdOp::getLen(desc), &pktEvent, p->data + p->length);
+ TxdOp::getLen(desc), &pktEvent, p->data + p->length, igbe->txReadDelay);
}
if (TxdOp::ixsm(desc)) {
ip->sum(0);
ip->sum(cksum(ip));
+ igbe->txIpChecksums++;
DPRINTF(EthernetDesc, "Calculated IP checksum\n");
}
if (TxdOp::txsm(desc)) {
if (tcp) {
tcp->sum(0);
tcp->sum(cksum(tcp));
+ igbe->txTcpChecksums++;
DPRINTF(EthernetDesc, "Calculated TCP checksum\n");
} else if (udp) {
assert(udp);
udp->sum(0);
udp->sum(cksum(udp));
+ igbe->txUdpChecksums++;
DPRINTF(EthernetDesc, "Calculated UDP checksum\n");
} else {
panic("Told to checksum, but don't know how\n");
bool
IGbE::ethRxPkt(EthPacketPtr pkt)
{
+ rxBytes += pkt->length;
+ rxPackets++;
+
DPRINTF(Ethernet, "RxFIFO: Receiving pcakte from wire\n");
if (!regs.rctl.en()) {
}
DPRINTF(EthernetSM, "TxFIFO: Successful transmit, bytes available in fifo: %d\n",
txFifo.avail());
+
+ txBytes += txFifo.front()->length;
+ txPackets++;
+ txFifoTick = false;
+
txFifo.pop();
} else {
// We'll get woken up when the packet ethTxDone() gets called
SERIALIZE_SCALAR(eeDataBits);
SERIALIZE_SCALAR(eeOpcode);
SERIALIZE_SCALAR(eeAddr);
+ SERIALIZE_SCALAR(lastInterrupt);
SERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE);
rxFifo.serialize("rxfifo", os);
UNSERIALIZE_SCALAR(eeDataBits);
UNSERIALIZE_SCALAR(eeOpcode);
UNSERIALIZE_SCALAR(eeAddr);
+ UNSERIALIZE_SCALAR(lastInterrupt);
UNSERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE);
rxFifo.unserialize("rxfifo", cp, section);