X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fdev%2Fi8254xGBe.cc;h=0fbda1897a67a37699202450f273bbbf48e66775;hb=27e8f3c98a4b1c56e16ce5f80c7ad992083ccef9;hp=7ea4c704bc094beab57569dfe12c373e555272a6;hpb=6ab53415efe3e06c06589a8a6ef38185ff6f94b7;p=gem5.git diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc index 7ea4c704b..0fbda1897 100644 --- a/src/dev/i8254xGBe.cc +++ b/src/dev/i8254xGBe.cc @@ -40,28 +40,35 @@ * @todo really there are multiple dma engines.. we should implement them. */ +#include + #include "base/inet.hh" #include "base/trace.hh" #include "dev/i8254xGBe.hh" #include "mem/packet.hh" #include "mem/packet_access.hh" -#include "sim/builder.hh" +#include "params/IGbE.hh" #include "sim/stats.hh" #include "sim/system.hh" -#include - using namespace iGbReg; using namespace Net; -IGbE::IGbE(Params *p) - : PciDev(p), etherInt(NULL), drainEvent(NULL), useFlowControl(p->use_flow_control), +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), 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); + // Initialized internal registers per Intel documentation // All registers intialized to 0 by per register constructor regs.ctrl.fd(1); @@ -107,6 +114,17 @@ IGbE::IGbE(Params *p) txFifo.clear(); } +EtherInt* +IGbE::getEthPort(const std::string &if_name, int idx) +{ + + if (if_name == "interface") { + if (etherInt->getPeer()) + panic("Port already connected to\n"); + return etherInt; + } + return NULL; +} Tick IGbE::writeConfig(PacketPtr pkt) @@ -491,8 +509,13 @@ IGbE::write(PacketPtr pkt) break; case REG_RDT: regs.rdt = val; - rxTick = true; - restartClock(); + DPRINTF(EthernetSM, "RXS: RDT Updated.\n"); + if (getState() == SimObject::Running) { + DPRINTF(EthernetSM, "RXS: RDT Fetching Descriptors!\n"); + rxDescCache.fetchDescriptors(); + } else { + DPRINTF(EthernetSM, "RXS: RDT NOT Fetching Desc b/c draining!\n"); + } break; case REG_RDTR: regs.rdtr = val; @@ -518,8 +541,13 @@ IGbE::write(PacketPtr pkt) break; case REG_TDT: regs.tdt = val; - txTick = true; - restartClock(); + DPRINTF(EthernetSM, "TXS: TX Tail pointer updated\n"); + if (getState() == SimObject::Running) { + DPRINTF(EthernetSM, "TXS: TDT Fetching Descriptors!\n"); + txDescCache.fetchDescriptors(); + } else { + DPRINTF(EthernetSM, "TXS: TDT NOT Fetching Desc b/c draining!\n"); + } break; case REG_TIDV: regs.tidv = val; @@ -553,54 +581,80 @@ IGbE::postInterrupt(IntTypes t, bool now) assert(t); // Interrupt is already pending - if (t & regs.icr()) + if (t & regs.icr() && !now) return; - if (regs.icr() & regs.imr) - { - regs.icr = regs.icr() | t; - if (!interEvent.scheduled()) - interEvent.schedule(curTick + Clock::Int::ns * 256 * - regs.itr.interval()); - } else { - regs.icr = regs.icr() | t; - if (regs.itr.interval() == 0 || now) { - if (interEvent.scheduled()) - interEvent.deschedule(); - cpuPostInt(); - } else { - DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for %d ticks\n", - Clock::Int::ns * 256 * regs.itr.interval()); - if (!interEvent.scheduled()) - interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval()); + regs.icr = regs.icr() | t; + + 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()) { + deschedule(interEvent); } + cpuPostInt(); + } else { + 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()) { + schedule(interEvent, int_time); + } } } +void +IGbE::delayIntEvent() +{ + cpuPostInt(); +} + + void IGbE::cpuPostInt() { + + postedInterrupts++; + + if (!(regs.icr() & regs.imr)) { + DPRINTF(Ethernet, "Interrupt Masked. Not Posting\n"); + return; + } + + DPRINTF(Ethernet, "Posting Interrupt\n"); + + + if (interEvent.scheduled()) { + deschedule(interEvent); + } + if (rdtrEvent.scheduled()) { regs.icr.rxt0(1); - rdtrEvent.deschedule(); + deschedule(rdtrEvent); } if (radvEvent.scheduled()) { regs.icr.rxt0(1); - radvEvent.deschedule(); + deschedule(radvEvent); } if (tadvEvent.scheduled()) { regs.icr.txdw(1); - tadvEvent.deschedule(); + deschedule(tadvEvent); } if (tidvEvent.scheduled()) { regs.icr.txdw(1); - tidvEvent.deschedule(); + deschedule(tidvEvent); } regs.icr.int_assert(1); DPRINTF(EthernetIntr, "EINT: Posting interrupt to CPU now. Vector %#x\n", regs.icr()); + intrPost(); + + lastInterrupt = curTick; } void @@ -617,20 +671,29 @@ IGbE::cpuClearInt() void IGbE::chkInterrupt() { + DPRINTF(Ethernet, "Checking interrupts icr: %#x imr: %#x\n", regs.icr(), + regs.imr); // Check if we need to clear the cpu interrupt if (!(regs.icr() & regs.imr)) { + DPRINTF(Ethernet, "Mask cleaned all interrupts\n"); if (interEvent.scheduled()) - interEvent.deschedule(); + deschedule(interEvent); if (regs.icr.int_assert()) cpuClearInt(); } + DPRINTF(Ethernet, "ITR = %#X itr.interval = %#X\n", regs.itr(), regs.itr.interval()); if (regs.icr() & regs.imr) { if (regs.itr.interval() == 0) { cpuPostInt(); } else { - if (!interEvent.scheduled()) - interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval()); + DPRINTF(Ethernet, "Possibly scheduling interrupt because of imr write\n"); + if (!interEvent.scheduled()) { + DPRINTF(Ethernet, "Scheduling for %d\n", curTick + Clock::Int::ns + * 256 * regs.itr.interval()); + schedule(interEvent, + curTick + Clock::Int::ns * 256 * regs.itr.interval()); + } } } @@ -644,7 +707,7 @@ IGbE::RxDescCache::RxDescCache(IGbE *i, const std::string n, int s) { } -bool +void IGbE::RxDescCache::writePacket(EthPacketPtr packet) { // We shouldn't have to deal with any of these yet @@ -652,14 +715,14 @@ IGbE::RxDescCache::writePacket(EthPacketPtr packet) packet->length, igbe->regs.rctl.descSize()); assert(packet->length < igbe->regs.rctl.descSize()); - if (!unusedCache.size()) - return false; + assert(unusedCache.size()); + //if (!unusedCache.size()) + // return false; pktPtr = packet; pktDone = false; igbe->dmaWrite(igbe->platform->pciToDma(unusedCache.front()->buf), - packet->length, &pktEvent, packet->data); - return true; + packet->length, &pktEvent, packet->data, igbe->rxWriteDelay); } void @@ -693,6 +756,7 @@ IGbE::RxDescCache::pktComplete() 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"); @@ -703,6 +767,7 @@ IGbE::RxDescCache::pktComplete() 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; @@ -714,6 +779,7 @@ IGbE::RxDescCache::pktComplete() 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; @@ -734,20 +800,21 @@ IGbE::RxDescCache::pktComplete() if (igbe->regs.rdtr.delay()) { DPRINTF(EthernetSM, "RXS: Scheduling DTR for %d\n", igbe->regs.rdtr.delay() * igbe->intClock()); - igbe->rdtrEvent.reschedule(curTick + igbe->regs.rdtr.delay() * - igbe->intClock(),true); + igbe->reschedule(igbe->rdtrEvent, + curTick + igbe->regs.rdtr.delay() * 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()) - igbe->radvEvent.schedule(curTick + igbe->regs.radv.idv() * - igbe->intClock()); + if (!igbe->radvEvent.scheduled()) { + igbe->schedule(igbe->radvEvent, + curTick + igbe->regs.radv.idv() * igbe->intClock()); + } } // 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); } @@ -762,17 +829,22 @@ IGbE::RxDescCache::pktComplete() DPRINTF(EthernetDesc, "Processing of this descriptor complete\n"); unusedCache.pop_front(); usedCache.push_back(desc); + + pktPtr = NULL; enableSm(); pktDone = true; igbe->checkDrain(); + } void IGbE::RxDescCache::enableSm() { - igbe->rxTick = true; - igbe->restartClock(); + if (!igbe->drainEvent) { + igbe->rxTick = true; + igbe->restartClock(); + } } bool @@ -830,11 +902,13 @@ IGbE::TxDescCache::getPacketSize() // I think we can just ignore these for now? desc = unusedCache.front(); + DPRINTF(EthernetDesc, "Descriptor upper: %#x lower: %#X\n", desc->d1, + desc->d2); // is this going to be a tcp or udp packet? isTcp = TxdOp::tcp(desc) ? true : false; // make sure it's ipv4 - assert(TxdOp::ip(desc)); + //assert(TxdOp::ip(desc)); TxdOp::setDd(desc); unusedCache.pop_front(); @@ -864,9 +938,9 @@ IGbE::TxDescCache::getPacketData(EthPacketPtr p) pktWaiting = true; - DPRINTF(EthernetDesc, "Starting DMA of packet\n"); + 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); } @@ -888,19 +962,22 @@ IGbE::TxDescCache::pktComplete() DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2); if (!TxdOp::eop(desc)) { - // This only supports two descriptors per tx packet - assert(pktPtr->length == 0); - pktPtr->length = TxdOp::getLen(desc); + pktPtr->length += TxdOp::getLen(desc); unusedCache.pop_front(); usedCache.push_back(desc); pktDone = true; pktWaiting = false; + pktMultiDesc = true; + + DPRINTF(EthernetDesc, "Partial Packet Descriptor of %d bytes Done\n", + pktPtr->length); pktPtr = NULL; - DPRINTF(EthernetDesc, "Partial Packet Descriptor Done\n"); enableSm(); + igbe->checkDrain(); return; } + pktMultiDesc = false; // Set the length of the data in the EtherPacket pktPtr->length += TxdOp::getLen(desc); @@ -932,26 +1009,30 @@ IGbE::TxDescCache::pktComplete() if (TxdOp::isData(desc) && ( TxdOp::ixsm(desc) || TxdOp::txsm(desc)) ) { DPRINTF(EthernetDesc, "Calculating checksums for packet\n"); IpPtr ip(pktPtr); - + assert(ip); if (TxdOp::ixsm(desc)) { ip->sum(0); ip->sum(cksum(ip)); + igbe->txIpChecksums++; DPRINTF(EthernetDesc, "Calculated IP checksum\n"); } - if (TxdOp::txsm(desc)) { - if (isTcp) { - TcpPtr tcp(ip); - assert(tcp); - tcp->sum(0); - tcp->sum(cksum(tcp)); - DPRINTF(EthernetDesc, "Calculated TCP checksum\n"); - } else { - UdpPtr udp(ip); - assert(udp); - udp->sum(0); - udp->sum(cksum(udp)); - DPRINTF(EthernetDesc, "Calculated UDP checksum\n"); - } + if (TxdOp::txsm(desc)) { + TcpPtr tcp(ip); + UdpPtr udp(ip); + 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"); + } } } @@ -960,15 +1041,16 @@ IGbE::TxDescCache::pktComplete() DPRINTF(EthernetDesc, "Descriptor had IDE set\n"); if (igbe->regs.tidv.idv()) { DPRINTF(EthernetDesc, "setting tidv\n"); - igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() * - igbe->intClock(), true); + igbe->reschedule(igbe->tidvEvent, + curTick + igbe->regs.tidv.idv() * igbe->intClock(), true); } if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) { DPRINTF(EthernetDesc, "setting tadv\n"); - if (!igbe->tadvEvent.scheduled()) - igbe->tadvEvent.schedule(curTick + igbe->regs.tadv.idv() * - igbe->intClock()); + if (!igbe->tadvEvent.scheduled()) { + igbe->schedule(igbe->tadvEvent, + curTick + igbe->regs.tadv.idv() * igbe->intClock()); + } } } @@ -1000,6 +1082,7 @@ IGbE::TxDescCache::serialize(std::ostream &os) SERIALIZE_SCALAR(pktDone); SERIALIZE_SCALAR(isTcp); SERIALIZE_SCALAR(pktWaiting); + SERIALIZE_SCALAR(pktMultiDesc); } void @@ -1009,6 +1092,7 @@ IGbE::TxDescCache::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(pktDone); UNSERIALIZE_SCALAR(isTcp); UNSERIALIZE_SCALAR(pktWaiting); + UNSERIALIZE_SCALAR(pktMultiDesc); } bool @@ -1024,8 +1108,10 @@ IGbE::TxDescCache::packetAvailable() void IGbE::TxDescCache::enableSm() { - igbe->txTick = true; - igbe->restartClock(); + if (!igbe->drainEvent) { + igbe->txTick = true; + igbe->restartClock(); + } } bool @@ -1041,9 +1127,9 @@ IGbE::TxDescCache::hasOutstandingEvents() void IGbE::restartClock() { - if (!tickEvent.scheduled() && (rxTick || txTick || txFifoTick) && getState() == - SimObject::Running) - tickEvent.schedule((curTick/cycles(1)) * cycles(1) + cycles(1)); + if (!tickEvent.scheduled() && (rxTick || txTick || txFifoTick) && + getState() == SimObject::Running) + schedule(tickEvent, (curTick / ticks(1)) * ticks(1) + ticks(1)); } unsigned int @@ -1062,7 +1148,7 @@ IGbE::drain(Event *de) rxTick = false; if (tickEvent.scheduled()) - tickEvent.deschedule(); + deschedule(tickEvent); if (count) changeState(Draining); @@ -1090,8 +1176,11 @@ IGbE::checkDrain() if (!drainEvent) return; - if (rxDescCache.hasOutstandingEvents() || - txDescCache.hasOutstandingEvents()) { + txFifoTick = false; + txTick = false; + rxTick = false; + if (!rxDescCache.hasOutstandingEvents() && + !txDescCache.hasOutstandingEvents()) { drainEvent->process(); drainEvent = NULL; } @@ -1109,11 +1198,13 @@ IGbE::txStateMachine() // If we have a packet available and it's length is not 0 (meaning it's not // a multidescriptor packet) put it in the fifo, otherwise an the next // iteration we'll get the rest of the data - if (txPacket && txDescCache.packetAvailable() && txPacket->length) { + if (txPacket && txDescCache.packetAvailable() + && !txDescCache.packetMultiDesc() && txPacket->length) { bool success; + DPRINTF(EthernetSM, "TXS: packet placed in TX FIFO\n"); success = txFifo.push(txPacket); - txFifoTick = true; + txFifoTick = true && !drainEvent; assert(success); txPacket = NULL; txDescCache.writeback((cacheBlockSize()-1)>>4); @@ -1133,22 +1224,24 @@ IGbE::txStateMachine() if (!txDescCache.packetWaiting()) { if (txDescCache.descLeft() == 0) { + postInterrupt(IT_TXQE); + txDescCache.writeback(0); + txDescCache.fetchDescriptors(); DPRINTF(EthernetSM, "TXS: No descriptors left in ring, forcing " "writeback stopping ticking and posting TXQE\n"); - txDescCache.writeback(0); txTick = false; - postInterrupt(IT_TXQE, true); return; } if (!(txDescCache.descUnused())) { + txDescCache.fetchDescriptors(); DPRINTF(EthernetSM, "TXS: No descriptors available in cache, fetching and stopping ticking\n"); txTick = false; - txDescCache.fetchDescriptors(); return; } + int size; size = txDescCache.getPacketSize(); if (size > 0 && txFifo.avail() > size) { @@ -1157,12 +1250,12 @@ IGbE::txStateMachine() txFifo.reserve(size); txDescCache.getPacketData(txPacket); } else if (size <= 0) { + DPRINTF(EthernetSM, "TXS: getPacketSize returned: %d\n", size); DPRINTF(EthernetSM, "TXS: No packets to get, writing back used descriptors\n"); txDescCache.writeback(0); } else { DPRINTF(EthernetSM, "TXS: FIFO full, stopping ticking until space " "available in FIFO\n"); - txDescCache.writeback((cacheBlockSize()-1)>>4); txTick = false; } @@ -1176,14 +1269,18 @@ IGbE::txStateMachine() bool IGbE::ethRxPkt(EthPacketPtr pkt) { + rxBytes += pkt->length; + rxPackets++; + DPRINTF(Ethernet, "RxFIFO: Receiving pcakte from wire\n"); + if (!regs.rctl.en()) { DPRINTF(Ethernet, "RxFIFO: RX not enabled, dropping\n"); return true; } // restart the state machines if they are stopped - rxTick = true; + rxTick = true && !drainEvent; if ((rxTick || txTick) && !tickEvent.scheduled()) { DPRINTF(EthernetSM, "RXS: received packet into fifo, starting ticking\n"); restartClock(); @@ -1194,6 +1291,7 @@ IGbE::ethRxPkt(EthPacketPtr pkt) postInterrupt(IT_RXO, true); return false; } + return true; } @@ -1222,9 +1320,9 @@ IGbE::rxStateMachine() } if (descLeft == 0) { + rxDescCache.writeback(0); DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing" " writeback and stopping ticking\n"); - rxDescCache.writeback(0); rxTick = false; } @@ -1246,10 +1344,10 @@ IGbE::rxStateMachine() } if (rxDescCache.descUnused() == 0) { + rxDescCache.fetchDescriptors(); DPRINTF(EthernetSM, "RXS: No descriptors available in cache, " "fetching descriptors and stopping ticking\n"); rxTick = false; - rxDescCache.fetchDescriptors(); } return; } @@ -1261,10 +1359,10 @@ IGbE::rxStateMachine() } if (!rxDescCache.descUnused()) { + rxDescCache.fetchDescriptors(); DPRINTF(EthernetSM, "RXS: No descriptors available in cache, stopping ticking\n"); rxTick = false; DPRINTF(EthernetSM, "RXS: No descriptors available, fetching\n"); - rxDescCache.fetchDescriptors(); return; } @@ -1277,11 +1375,9 @@ IGbE::rxStateMachine() EthPacketPtr pkt; pkt = rxFifo.front(); - DPRINTF(EthernetSM, "RXS: Writing packet into memory\n"); - if (!rxDescCache.writePacket(pkt)) { - return; - } + rxDescCache.writePacket(pkt); + DPRINTF(EthernetSM, "RXS: Writing packet into memory\n"); DPRINTF(EthernetSM, "RXS: Removing packet from FIFO\n"); rxFifo.pop(); DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n"); @@ -1299,14 +1395,26 @@ IGbE::txWire() if (etherInt->sendPacket(txFifo.front())) { + if (DTRACE(EthernetSM)) { + IpPtr ip(txFifo.front()); + if (ip) + DPRINTF(EthernetSM, "Transmitting Ip packet with Id=%d\n", + ip->id()); + else + DPRINTF(EthernetSM, "Transmitting Non-Ip packet\n"); + } 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 txFifoTick = false; } - } void @@ -1325,7 +1433,7 @@ IGbE::tick() if (rxTick || txTick || txFifoTick) - tickEvent.schedule(curTick + cycles(1)); + schedule(tickEvent, curTick + ticks(1)); } void @@ -1334,10 +1442,12 @@ IGbE::ethTxDone() // restart the tx state machines if they are stopped // fifo to send another packet // tx sm to put more data into the fifo - txFifoTick = true; - txTick = true; + txFifoTick = true && !drainEvent; + if (txDescCache.descLeft() != 0 && !drainEvent) + txTick = true; restartClock(); + txWire(); DPRINTF(EthernetSM, "TxFIFO: Transmission complete\n"); } @@ -1352,6 +1462,7 @@ IGbE::serialize(std::ostream &os) SERIALIZE_SCALAR(eeDataBits); SERIALIZE_SCALAR(eeOpcode); SERIALIZE_SCALAR(eeAddr); + SERIALIZE_SCALAR(lastInterrupt); SERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE); rxFifo.serialize("rxfifo", os); @@ -1374,15 +1485,15 @@ IGbE::serialize(std::ostream &os) SERIALIZE_SCALAR(radv_time); if (tidvEvent.scheduled()) - rdtr_time = tidvEvent.when(); + tidv_time = tidvEvent.when(); SERIALIZE_SCALAR(tidv_time); if (tadvEvent.scheduled()) - rdtr_time = tadvEvent.when(); + tadv_time = tadvEvent.when(); SERIALIZE_SCALAR(tadv_time); if (interEvent.scheduled()) - rdtr_time = interEvent.when(); + inter_time = interEvent.when(); SERIALIZE_SCALAR(inter_time); nameOut(os, csprintf("%s.TxDescCache", name())); @@ -1403,6 +1514,7 @@ IGbE::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(eeDataBits); UNSERIALIZE_SCALAR(eeOpcode); UNSERIALIZE_SCALAR(eeAddr); + UNSERIALIZE_SCALAR(lastInterrupt); UNSERIALIZE_ARRAY(flash,iGbReg::EEPROM_SIZE); rxFifo.unserialize("rxfifo", cp, section); @@ -1427,127 +1539,27 @@ IGbE::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(inter_time); if (rdtr_time) - rdtrEvent.schedule(rdtr_time); + schedule(rdtrEvent, rdtr_time); if (radv_time) - radvEvent.schedule(radv_time); + schedule(radvEvent, radv_time); if (tidv_time) - tidvEvent.schedule(tidv_time); + schedule(tidvEvent, tidv_time); if (tadv_time) - tadvEvent.schedule(tadv_time); + schedule(tadvEvent, tadv_time); if (inter_time) - interEvent.schedule(inter_time); + schedule(interEvent, inter_time); txDescCache.unserialize(cp, csprintf("%s.TxDescCache", section)); rxDescCache.unserialize(cp, csprintf("%s.RxDescCache", section)); } - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbEInt) - - SimObjectParam peer; - SimObjectParam device; - -END_DECLARE_SIM_OBJECT_PARAMS(IGbEInt) - -BEGIN_INIT_SIM_OBJECT_PARAMS(IGbEInt) - - INIT_PARAM_DFLT(peer, "peer interface", NULL), - INIT_PARAM(device, "Ethernet device of this interface") - -END_INIT_SIM_OBJECT_PARAMS(IGbEInt) - -CREATE_SIM_OBJECT(IGbEInt) -{ - IGbEInt *dev_int = new IGbEInt(getInstanceName(), device); - - EtherInt *p = (EtherInt *)peer; - if (p) { - dev_int->setPeer(p); - p->setPeer(dev_int); - } - - return dev_int; -} - -REGISTER_SIM_OBJECT("IGbEInt", IGbEInt) - - -BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbE) - - SimObjectParam system; - SimObjectParam platform; - Param min_backoff_delay; - Param max_backoff_delay; - SimObjectParam configdata; - Param pci_bus; - Param pci_dev; - Param pci_func; - Param pio_latency; - Param config_latency; - Param hardware_address; - Param use_flow_control; - Param rx_fifo_size; - Param tx_fifo_size; - Param rx_desc_cache_size; - Param tx_desc_cache_size; - Param clock; - - -END_DECLARE_SIM_OBJECT_PARAMS(IGbE) - -BEGIN_INIT_SIM_OBJECT_PARAMS(IGbE) - - INIT_PARAM(system, "System pointer"), - INIT_PARAM(platform, "Platform pointer"), - INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"), - INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"), - INIT_PARAM(configdata, "PCI Config data"), - INIT_PARAM(pci_bus, "PCI bus ID"), - INIT_PARAM(pci_dev, "PCI device number"), - INIT_PARAM(pci_func, "PCI function code"), - INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), - INIT_PARAM(config_latency, "Number of cycles for a config read or write"), - INIT_PARAM(hardware_address, "Ethernet Hardware Address"), - INIT_PARAM(use_flow_control,"Should the device use xon/off packets"), - INIT_PARAM(rx_fifo_size,"Size of the RX FIFO"), - INIT_PARAM(tx_fifo_size,"Size of the TX FIFO"), - INIT_PARAM(rx_desc_cache_size,"Size of the RX descriptor cache"), - INIT_PARAM(tx_desc_cache_size,"Size of the TX descriptor cache"), - INIT_PARAM(clock,"Clock rate for the device to tick at") - -END_INIT_SIM_OBJECT_PARAMS(IGbE) - - -CREATE_SIM_OBJECT(IGbE) +IGbE * +IGbEParams::create() { - IGbE::Params *params = new IGbE::Params; - - params->name = getInstanceName(); - params->platform = platform; - params->system = system; - params->min_backoff_delay = min_backoff_delay; - params->max_backoff_delay = max_backoff_delay; - params->configData = configdata; - params->busNum = pci_bus; - params->deviceNum = pci_dev; - params->functionNum = pci_func; - params->pio_delay = pio_latency; - params->config_delay = config_latency; - params->hardware_address = hardware_address; - params->use_flow_control = use_flow_control; - params->rx_fifo_size = rx_fifo_size; - params->tx_fifo_size = tx_fifo_size; - params->rx_desc_cache_size = rx_desc_cache_size; - params->tx_desc_cache_size = tx_desc_cache_size; - params->clock = clock; - - - return new IGbE(params); + return new IGbE(this); } - -REGISTER_SIM_OBJECT("IGbE", IGbE)