some more fixes... non-tso stuff seems to work
--HG-- extra : convert_revision : da604d20443376d04826397d0aaff0bdd744053b
This commit is contained in:
parent
01ac962a06
commit
e95bc9d8f9
3 changed files with 106 additions and 53 deletions
|
@ -57,8 +57,8 @@ using namespace Net;
|
||||||
IGbE::IGbE(Params *p)
|
IGbE::IGbE(Params *p)
|
||||||
: PciDev(p), etherInt(NULL), useFlowControl(p->use_flow_control),
|
: PciDev(p), etherInt(NULL), useFlowControl(p->use_flow_control),
|
||||||
rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxTick(false),
|
rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size), rxTick(false),
|
||||||
txTick(false), rdtrEvent(this), radvEvent(this), tadvEvent(this),
|
txTick(false), txFifoTick(false), rdtrEvent(this), radvEvent(this),
|
||||||
tidvEvent(this), tickEvent(this), interEvent(this),
|
tadvEvent(this), tidvEvent(this), tickEvent(this), interEvent(this),
|
||||||
rxDescCache(this, name()+".RxDesc", p->rx_desc_cache_size),
|
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)
|
||||||
{
|
{
|
||||||
|
@ -223,6 +223,7 @@ IGbE::read(PacketPtr pkt)
|
||||||
pkt->set<uint32_t>(regs.rdtr());
|
pkt->set<uint32_t>(regs.rdtr());
|
||||||
if (regs.rdtr.fpd()) {
|
if (regs.rdtr.fpd()) {
|
||||||
rxDescCache.writeback(0);
|
rxDescCache.writeback(0);
|
||||||
|
DPRINTF(EthernetIntr, "Posting interrupt because of RDTR.FPD write\n");
|
||||||
postInterrupt(IT_RXT);
|
postInterrupt(IT_RXT);
|
||||||
regs.rdtr.fpd(0);
|
regs.rdtr.fpd(0);
|
||||||
}
|
}
|
||||||
|
@ -411,6 +412,7 @@ IGbE::write(PacketPtr pkt)
|
||||||
regs.itr = val;
|
regs.itr = val;
|
||||||
break;
|
break;
|
||||||
case REG_ICS:
|
case REG_ICS:
|
||||||
|
DPRINTF(EthernetIntr, "Posting interrupt because of ICS write\n");
|
||||||
postInterrupt((IntTypes)val);
|
postInterrupt((IntTypes)val);
|
||||||
break;
|
break;
|
||||||
case REG_IMS:
|
case REG_IMS:
|
||||||
|
@ -429,6 +431,7 @@ IGbE::write(PacketPtr pkt)
|
||||||
regs.rctl = val;
|
regs.rctl = val;
|
||||||
if (regs.rctl.rst()) {
|
if (regs.rctl.rst()) {
|
||||||
rxDescCache.reset();
|
rxDescCache.reset();
|
||||||
|
DPRINTF(EthernetSM, "RXS: Got RESET!\n");
|
||||||
rxFifo.clear();
|
rxFifo.clear();
|
||||||
regs.rctl.rst(0);
|
regs.rctl.rst(0);
|
||||||
}
|
}
|
||||||
|
@ -568,8 +571,8 @@ IGbE::postInterrupt(IntTypes t, bool now)
|
||||||
} else {
|
} else {
|
||||||
DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for %d ticks\n",
|
DPRINTF(EthernetIntr, "EINT: Scheduling timer interrupt for %d ticks\n",
|
||||||
Clock::Int::ns * 256 * regs.itr.interval());
|
Clock::Int::ns * 256 * regs.itr.interval());
|
||||||
assert(!interEvent.scheduled());
|
if (!interEvent.scheduled())
|
||||||
interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval());
|
interEvent.schedule(curTick + Clock::Int::ns * 256 * regs.itr.interval());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -676,39 +679,39 @@ IGbE::RxDescCache::pktComplete()
|
||||||
// no support for anything but starting at 0
|
// no support for anything but starting at 0
|
||||||
assert(igbe->regs.rxcsum.pcss() == 0);
|
assert(igbe->regs.rxcsum.pcss() == 0);
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "RxDesc: Packet written to memory updating Descriptor\n");
|
DPRINTF(EthernetDesc, "Packet written to memory updating Descriptor\n");
|
||||||
|
|
||||||
uint8_t status = RXDS_DD | RXDS_EOP;
|
uint8_t status = RXDS_DD | RXDS_EOP;
|
||||||
uint8_t err = 0;
|
uint8_t err = 0;
|
||||||
IpPtr ip(pktPtr);
|
IpPtr ip(pktPtr);
|
||||||
if (ip) {
|
if (ip) {
|
||||||
if (igbe->regs.rxcsum.ipofld()) {
|
if (igbe->regs.rxcsum.ipofld()) {
|
||||||
DPRINTF(EthernetDesc, "RxDesc: Checking IP checksum\n");
|
DPRINTF(EthernetDesc, "Checking IP checksum\n");
|
||||||
status |= RXDS_IPCS;
|
status |= RXDS_IPCS;
|
||||||
desc->csum = htole(cksum(ip));
|
desc->csum = htole(cksum(ip));
|
||||||
if (cksum(ip) != 0) {
|
if (cksum(ip) != 0) {
|
||||||
err |= RXDE_IPE;
|
err |= RXDE_IPE;
|
||||||
DPRINTF(EthernetDesc, "RxDesc: Checksum is bad!!\n");
|
DPRINTF(EthernetDesc, "Checksum is bad!!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TcpPtr tcp(ip);
|
TcpPtr tcp(ip);
|
||||||
if (tcp && igbe->regs.rxcsum.tuofld()) {
|
if (tcp && igbe->regs.rxcsum.tuofld()) {
|
||||||
DPRINTF(EthernetDesc, "RxDesc: Checking TCP checksum\n");
|
DPRINTF(EthernetDesc, "Checking TCP checksum\n");
|
||||||
status |= RXDS_TCPCS;
|
status |= RXDS_TCPCS;
|
||||||
desc->csum = htole(cksum(tcp));
|
desc->csum = htole(cksum(tcp));
|
||||||
if (cksum(tcp) != 0) {
|
if (cksum(tcp) != 0) {
|
||||||
DPRINTF(EthernetDesc, "RxDesc: Checksum is bad!!\n");
|
DPRINTF(EthernetDesc, "Checksum is bad!!\n");
|
||||||
err |= RXDE_TCPE;
|
err |= RXDE_TCPE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UdpPtr udp(ip);
|
UdpPtr udp(ip);
|
||||||
if (udp && igbe->regs.rxcsum.tuofld()) {
|
if (udp && igbe->regs.rxcsum.tuofld()) {
|
||||||
DPRINTF(EthernetDesc, "RxDesc: Checking UDP checksum\n");
|
DPRINTF(EthernetDesc, "Checking UDP checksum\n");
|
||||||
status |= RXDS_UDPCS;
|
status |= RXDS_UDPCS;
|
||||||
desc->csum = htole(cksum(udp));
|
desc->csum = htole(cksum(udp));
|
||||||
if (cksum(tcp) != 0) {
|
if (cksum(tcp) != 0) {
|
||||||
DPRINTF(EthernetDesc, "RxDesc: Checksum is bad!!\n");
|
DPRINTF(EthernetDesc, "Checksum is bad!!\n");
|
||||||
err |= RXDE_TCPE;
|
err |= RXDE_TCPE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -748,10 +751,12 @@ IGbE::RxDescCache::pktComplete()
|
||||||
|
|
||||||
// If the packet is small enough, interrupt appropriately
|
// If the packet is small enough, interrupt appropriately
|
||||||
// I wonder if this is delayed or not?!
|
// I wonder if this is delayed or not?!
|
||||||
if (pktPtr->length <= igbe->regs.rsrpd.idv())
|
if (pktPtr->length <= igbe->regs.rsrpd.idv()) {
|
||||||
|
DPRINTF(EthernetSM, "RXS: Posting IT_SRPD beacuse small packet received\n");
|
||||||
igbe->postInterrupt(IT_SRPD);
|
igbe->postInterrupt(IT_SRPD);
|
||||||
|
}
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "RxDesc: Processing of this descriptor complete\n");
|
DPRINTF(EthernetDesc, "Processing of this descriptor complete\n");
|
||||||
unusedCache.pop_front();
|
unusedCache.pop_front();
|
||||||
usedCache.push_back(desc);
|
usedCache.push_back(desc);
|
||||||
pktPtr = NULL;
|
pktPtr = NULL;
|
||||||
|
@ -792,10 +797,10 @@ IGbE::TxDescCache::getPacketSize()
|
||||||
|
|
||||||
TxDesc *desc;
|
TxDesc *desc;
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "TxDesc: Starting processing of descriptor\n");
|
DPRINTF(EthernetDesc, "Starting processing of descriptor\n");
|
||||||
|
|
||||||
while (unusedCache.size() && TxdOp::isContext(unusedCache.front())) {
|
while (unusedCache.size() && TxdOp::isContext(unusedCache.front())) {
|
||||||
DPRINTF(EthernetDesc, "TxDesc: Got context descriptor type... skipping\n");
|
DPRINTF(EthernetDesc, "Got context descriptor type... skipping\n");
|
||||||
|
|
||||||
// I think we can just ignore these for now?
|
// I think we can just ignore these for now?
|
||||||
desc = unusedCache.front();
|
desc = unusedCache.front();
|
||||||
|
@ -813,7 +818,7 @@ IGbE::TxDescCache::getPacketSize()
|
||||||
if (!unusedCache.size())
|
if (!unusedCache.size())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "TxDesc: Next TX packet is %d bytes\n",
|
DPRINTF(EthernetDesc, "Next TX packet is %d bytes\n",
|
||||||
TxdOp::getLen(unusedCache.front()));
|
TxdOp::getLen(unusedCache.front()));
|
||||||
|
|
||||||
return TxdOp::getLen(unusedCache.front());
|
return TxdOp::getLen(unusedCache.front());
|
||||||
|
@ -833,7 +838,7 @@ IGbE::TxDescCache::getPacketData(EthPacketPtr p)
|
||||||
|
|
||||||
pktWaiting = true;
|
pktWaiting = true;
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "TxDesc: Starting DMA of packet\n");
|
DPRINTF(EthernetDesc, "Starting DMA of packet\n");
|
||||||
igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)),
|
igbe->dmaRead(igbe->platform->pciToDma(TxdOp::getBuf(desc)),
|
||||||
TxdOp::getLen(desc), &pktEvent, p->data + hLen);
|
TxdOp::getLen(desc), &pktEvent, p->data + hLen);
|
||||||
|
|
||||||
|
@ -848,7 +853,7 @@ IGbE::TxDescCache::pktComplete()
|
||||||
assert(unusedCache.size());
|
assert(unusedCache.size());
|
||||||
assert(pktPtr);
|
assert(pktPtr);
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "TxDesc: DMA of packet complete\n");
|
DPRINTF(EthernetDesc, "DMA of packet complete\n");
|
||||||
|
|
||||||
|
|
||||||
desc = unusedCache.front();
|
desc = unusedCache.front();
|
||||||
|
@ -865,7 +870,7 @@ IGbE::TxDescCache::pktComplete()
|
||||||
pktWaiting = false;
|
pktWaiting = false;
|
||||||
pktPtr = NULL;
|
pktPtr = NULL;
|
||||||
|
|
||||||
DPRINTF(EthernetDesc, "TxDesc: Partial Packet Descriptor Done\n");
|
DPRINTF(EthernetDesc, "Partial Packet Descriptor Done\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,33 +893,33 @@ IGbE::TxDescCache::pktComplete()
|
||||||
|
|
||||||
// Checksums are only ofloaded for new descriptor types
|
// Checksums are only ofloaded for new descriptor types
|
||||||
if (TxdOp::isData(desc) && ( TxdOp::ixsm(desc) || TxdOp::txsm(desc)) ) {
|
if (TxdOp::isData(desc) && ( TxdOp::ixsm(desc) || TxdOp::txsm(desc)) ) {
|
||||||
DPRINTF(EthernetDesc, "TxDesc: Calculating checksums for packet\n");
|
DPRINTF(EthernetDesc, "Calculating checksums for packet\n");
|
||||||
IpPtr ip(pktPtr);
|
IpPtr ip(pktPtr);
|
||||||
if (TxdOp::ixsm(desc)) {
|
if (TxdOp::ixsm(desc)) {
|
||||||
ip->sum(0);
|
ip->sum(0);
|
||||||
ip->sum(cksum(ip));
|
ip->sum(cksum(ip));
|
||||||
DPRINTF(EthernetDesc, "TxDesc: Calculated IP checksum\n");
|
DPRINTF(EthernetDesc, "Calculated IP checksum\n");
|
||||||
}
|
}
|
||||||
if (TxdOp::txsm(desc)) {
|
if (TxdOp::txsm(desc)) {
|
||||||
if (isTcp) {
|
if (isTcp) {
|
||||||
TcpPtr tcp(ip);
|
TcpPtr tcp(ip);
|
||||||
tcp->sum(0);
|
tcp->sum(0);
|
||||||
tcp->sum(cksum(tcp));
|
tcp->sum(cksum(tcp));
|
||||||
DPRINTF(EthernetDesc, "TxDesc: Calculated TCP checksum\n");
|
DPRINTF(EthernetDesc, "Calculated TCP checksum\n");
|
||||||
} else {
|
} else {
|
||||||
UdpPtr udp(ip);
|
UdpPtr udp(ip);
|
||||||
udp->sum(0);
|
udp->sum(0);
|
||||||
udp->sum(cksum(udp));
|
udp->sum(cksum(udp));
|
||||||
DPRINTF(EthernetDesc, "TxDesc: Calculated UDP checksum\n");
|
DPRINTF(EthernetDesc, "Calculated UDP checksum\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TxdOp::ide(desc)) {
|
if (TxdOp::ide(desc)) {
|
||||||
// Deal with the rx timer interrupts
|
// Deal with the rx timer interrupts
|
||||||
DPRINTF(EthernetDesc, "TxDesc: Descriptor had IDE set\n");
|
DPRINTF(EthernetDesc, "Descriptor had IDE set\n");
|
||||||
if (igbe->regs.tidv.idv()) {
|
if (igbe->regs.tidv.idv()) {
|
||||||
DPRINTF(EthernetDesc, "TxDesc: setting tidv\n");
|
DPRINTF(EthernetDesc, "setting tidv\n");
|
||||||
if (igbe->tidvEvent.scheduled())
|
if (igbe->tidvEvent.scheduled())
|
||||||
igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() *
|
igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() *
|
||||||
igbe->intClock());
|
igbe->intClock());
|
||||||
|
@ -924,7 +929,7 @@ IGbE::TxDescCache::pktComplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) {
|
if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) {
|
||||||
DPRINTF(EthernetDesc, "TxDesc: setting tadv\n");
|
DPRINTF(EthernetDesc, "setting tadv\n");
|
||||||
if (!igbe->tadvEvent.scheduled())
|
if (!igbe->tadvEvent.scheduled())
|
||||||
igbe->tadvEvent.schedule(curTick + igbe->regs.tadv.idv() *
|
igbe->tadvEvent.schedule(curTick + igbe->regs.tadv.idv() *
|
||||||
igbe->intClock());
|
igbe->intClock());
|
||||||
|
@ -940,13 +945,13 @@ IGbE::TxDescCache::pktComplete()
|
||||||
pktPtr = NULL;
|
pktPtr = NULL;
|
||||||
|
|
||||||
hLen = 0;
|
hLen = 0;
|
||||||
DPRINTF(EthernetDesc, "TxDesc: Descriptor Done\n");
|
DPRINTF(EthernetDesc, "Descriptor Done\n");
|
||||||
|
|
||||||
if (igbe->regs.txdctl.wthresh() == 0) {
|
if (igbe->regs.txdctl.wthresh() == 0) {
|
||||||
DPRINTF(EthernetDesc, "TxDesc: WTHRESH == 0, writing back descriptor\n");
|
DPRINTF(EthernetDesc, "WTHRESH == 0, writing back descriptor\n");
|
||||||
writeback(0);
|
writeback(0);
|
||||||
} else if (igbe->regs.txdctl.wthresh() >= usedCache.size()) {
|
} else if (igbe->regs.txdctl.wthresh() >= usedCache.size()) {
|
||||||
DPRINTF(EthernetDesc, "TxDesc: used > WTHRESH, writing back descriptor\n");
|
DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");
|
||||||
writeback((igbe->cacheBlockSize()-1)>>4);
|
writeback((igbe->cacheBlockSize()-1)>>4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -998,8 +1003,10 @@ IGbE::txStateMachine()
|
||||||
bool success;
|
bool success;
|
||||||
DPRINTF(EthernetSM, "TXS: packet placed in TX FIFO\n");
|
DPRINTF(EthernetSM, "TXS: packet placed in TX FIFO\n");
|
||||||
success = txFifo.push(txPacket);
|
success = txFifo.push(txPacket);
|
||||||
|
txFifoTick = true;
|
||||||
assert(success);
|
assert(success);
|
||||||
txPacket = NULL;
|
txPacket = NULL;
|
||||||
|
txDescCache.writeback((cacheBlockSize()-1)>>4);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1021,6 +1028,7 @@ IGbE::txStateMachine()
|
||||||
txDescCache.writeback(0);
|
txDescCache.writeback(0);
|
||||||
txTick = false;
|
txTick = false;
|
||||||
postInterrupt(IT_TXQE, true);
|
postInterrupt(IT_TXQE, true);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1038,11 +1046,17 @@ IGbE::txStateMachine()
|
||||||
"DMA of next packet\n", size);
|
"DMA of next packet\n", size);
|
||||||
txFifo.reserve(size);
|
txFifo.reserve(size);
|
||||||
txDescCache.getPacketData(txPacket);
|
txDescCache.getPacketData(txPacket);
|
||||||
} else {
|
} else if (size <= 0) {
|
||||||
DPRINTF(EthernetSM, "TXS: No packets to get, writing back used descriptors\n");
|
DPRINTF(EthernetSM, "TXS: No packets to get, writing back used descriptors\n");
|
||||||
txDescCache.writeback(0);
|
txDescCache.writeback(0);
|
||||||
|
} else {
|
||||||
|
DPRINTF(EthernetSM, "TXS: FIFO full, stopping ticking until space "
|
||||||
|
"available in FIFO\n");
|
||||||
|
txDescCache.writeback((cacheBlockSize()-1)>>4);
|
||||||
|
txTick = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1095,9 +1109,9 @@ IGbE::rxStateMachine()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descLeft == 0) {
|
if (descLeft == 0) {
|
||||||
DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing writeback\n");
|
DPRINTF(EthernetSM, "RXS: No descriptors left in ring, forcing"
|
||||||
|
" writeback and stopping ticking\n");
|
||||||
rxDescCache.writeback(0);
|
rxDescCache.writeback(0);
|
||||||
DPRINTF(EthernetSM, "RXS: No descriptors left, stopping ticking\n");
|
|
||||||
rxTick = false;
|
rxTick = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1119,9 +1133,9 @@ IGbE::rxStateMachine()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rxDescCache.descUnused() == 0) {
|
if (rxDescCache.descUnused() == 0) {
|
||||||
DPRINTF(EthernetSM, "RXS: No descriptors available in cache, stopping ticking\n");
|
DPRINTF(EthernetSM, "RXS: No descriptors available in cache, "
|
||||||
|
"fetching descriptors and stopping ticking\n");
|
||||||
rxTick = false;
|
rxTick = false;
|
||||||
DPRINTF(EthernetSM, "RXS: Fetching descriptors because none available\n");
|
|
||||||
rxDescCache.fetchDescriptors();
|
rxDescCache.fetchDescriptors();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -1159,15 +1173,18 @@ void
|
||||||
IGbE::txWire()
|
IGbE::txWire()
|
||||||
{
|
{
|
||||||
if (txFifo.empty()) {
|
if (txFifo.empty()) {
|
||||||
|
txFifoTick = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
txTick = true;
|
|
||||||
|
|
||||||
if (etherInt->sendPacket(txFifo.front())) {
|
if (etherInt->sendPacket(txFifo.front())) {
|
||||||
DPRINTF(Ethernet, "TxFIFO: Successful transmit, bytes in fifo: %d\n",
|
DPRINTF(Ethernet, "TxFIFO: Successful transmit, bytes in fifo: %d\n",
|
||||||
txFifo.avail());
|
txFifo.avail());
|
||||||
txFifo.pop();
|
txFifo.pop();
|
||||||
|
} else {
|
||||||
|
// We'll get woken up when the packet ethTxDone() gets called
|
||||||
|
txFifoTick = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1180,20 +1197,26 @@ IGbE::tick()
|
||||||
if (rxTick)
|
if (rxTick)
|
||||||
rxStateMachine();
|
rxStateMachine();
|
||||||
|
|
||||||
if (txTick) {
|
if (txTick)
|
||||||
txStateMachine();
|
txStateMachine();
|
||||||
txWire();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rxTick || txTick)
|
if (txFifoTick)
|
||||||
|
txWire();
|
||||||
|
|
||||||
|
|
||||||
|
if (rxTick || txTick || txFifoTick)
|
||||||
tickEvent.schedule(curTick + cycles(1));
|
tickEvent.schedule(curTick + cycles(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
IGbE::ethTxDone()
|
IGbE::ethTxDone()
|
||||||
{
|
{
|
||||||
// restart the state machines if they are stopped
|
// 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;
|
txTick = true;
|
||||||
|
|
||||||
restartClock();
|
restartClock();
|
||||||
DPRINTF(Ethernet, "TxFIFO: Transmission complete\n");
|
DPRINTF(Ethernet, "TxFIFO: Transmission complete\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,24 +76,44 @@ class IGbE : public PciDev
|
||||||
// Should to Rx/Tx State machine tick?
|
// Should to Rx/Tx State machine tick?
|
||||||
bool rxTick;
|
bool rxTick;
|
||||||
bool txTick;
|
bool txTick;
|
||||||
|
bool txFifoTick;
|
||||||
|
|
||||||
// Event and function to deal with RDTR timer expiring
|
// Event and function to deal with RDTR timer expiring
|
||||||
void rdtrProcess() { rxDescCache.writeback(0); postInterrupt(iGbReg::IT_RXT, true); }
|
void rdtrProcess() {
|
||||||
|
rxDescCache.writeback(0);
|
||||||
|
DPRINTF(EthernetIntr, "Posting RXT interrupt because RDTR timer expired\n");
|
||||||
|
postInterrupt(iGbReg::IT_RXT, true);
|
||||||
|
}
|
||||||
|
|
||||||
//friend class EventWrapper<IGbE, &IGbE::rdtrProcess>;
|
//friend class EventWrapper<IGbE, &IGbE::rdtrProcess>;
|
||||||
EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent;
|
EventWrapper<IGbE, &IGbE::rdtrProcess> rdtrEvent;
|
||||||
|
|
||||||
// Event and function to deal with RADV timer expiring
|
// Event and function to deal with RADV timer expiring
|
||||||
void radvProcess() { rxDescCache.writeback(0); postInterrupt(iGbReg::IT_RXT, true); }
|
void radvProcess() {
|
||||||
|
rxDescCache.writeback(0);
|
||||||
|
DPRINTF(EthernetIntr, "Posting RXT interrupt because RADV timer expired\n");
|
||||||
|
postInterrupt(iGbReg::IT_RXT, true);
|
||||||
|
}
|
||||||
|
|
||||||
//friend class EventWrapper<IGbE, &IGbE::radvProcess>;
|
//friend class EventWrapper<IGbE, &IGbE::radvProcess>;
|
||||||
EventWrapper<IGbE, &IGbE::radvProcess> radvEvent;
|
EventWrapper<IGbE, &IGbE::radvProcess> radvEvent;
|
||||||
|
|
||||||
// Event and function to deal with TADV timer expiring
|
// Event and function to deal with TADV timer expiring
|
||||||
void tadvProcess() { postInterrupt(iGbReg::IT_TXDW, true); }
|
void tadvProcess() {
|
||||||
|
txDescCache.writeback(0);
|
||||||
|
DPRINTF(EthernetIntr, "Posting TXDW interrupt because TADV timer expired\n");
|
||||||
|
postInterrupt(iGbReg::IT_TXDW, true);
|
||||||
|
}
|
||||||
|
|
||||||
//friend class EventWrapper<IGbE, &IGbE::tadvProcess>;
|
//friend class EventWrapper<IGbE, &IGbE::tadvProcess>;
|
||||||
EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent;
|
EventWrapper<IGbE, &IGbE::tadvProcess> tadvEvent;
|
||||||
|
|
||||||
// Event and function to deal with TIDV timer expiring
|
// Event and function to deal with TIDV timer expiring
|
||||||
void tidvProcess() { postInterrupt(iGbReg::IT_TXDW, true); };
|
void tidvProcess() {
|
||||||
|
txDescCache.writeback(0);
|
||||||
|
DPRINTF(EthernetIntr, "Posting TXDW interrupt because TIDV timer expired\n");
|
||||||
|
postInterrupt(iGbReg::IT_TXDW, true);
|
||||||
|
}
|
||||||
//friend class EventWrapper<IGbE, &IGbE::tidvProcess>;
|
//friend class EventWrapper<IGbE, &IGbE::tidvProcess>;
|
||||||
EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent;
|
EventWrapper<IGbE, &IGbE::tidvProcess> tidvEvent;
|
||||||
|
|
||||||
|
@ -202,8 +222,10 @@ class IGbE : public PciDev
|
||||||
*/
|
*/
|
||||||
void areaChanged()
|
void areaChanged()
|
||||||
{
|
{
|
||||||
if (usedCache.size() > 0 || unusedCache.size() > 0)
|
if (usedCache.size() > 0 || curFetching || wbOut)
|
||||||
panic("Descriptor Address, Length or Head changed. Bad\n");
|
panic("Descriptor Address, Length or Head changed. Bad\n");
|
||||||
|
reset();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeback(Addr aMask)
|
void writeback(Addr aMask)
|
||||||
|
@ -229,7 +251,7 @@ class IGbE : public PciDev
|
||||||
moreToWb = false;
|
moreToWb = false;
|
||||||
wbAlignment = aMask;
|
wbAlignment = aMask;
|
||||||
|
|
||||||
if (max_to_wb + curHead > descLen()) {
|
if (max_to_wb + curHead >= descLen()) {
|
||||||
max_to_wb = descLen() - curHead;
|
max_to_wb = descLen() - curHead;
|
||||||
moreToWb = true;
|
moreToWb = true;
|
||||||
// this is by definition aligned correctly
|
// this is by definition aligned correctly
|
||||||
|
@ -265,10 +287,14 @@ class IGbE : public PciDev
|
||||||
*/
|
*/
|
||||||
void fetchDescriptors()
|
void fetchDescriptors()
|
||||||
{
|
{
|
||||||
size_t max_to_fetch = descTail() - cachePnt;
|
size_t max_to_fetch;
|
||||||
if (max_to_fetch < 0)
|
|
||||||
|
if (descTail() >= cachePnt)
|
||||||
|
max_to_fetch = descTail() - cachePnt;
|
||||||
|
else
|
||||||
max_to_fetch = descLen() - cachePnt;
|
max_to_fetch = descLen() - cachePnt;
|
||||||
|
|
||||||
|
|
||||||
max_to_fetch = std::min(max_to_fetch, (size - usedCache.size() -
|
max_to_fetch = std::min(max_to_fetch, (size - usedCache.size() -
|
||||||
unusedCache.size()));
|
unusedCache.size()));
|
||||||
|
|
||||||
|
@ -311,8 +337,9 @@ class IGbE : public PciDev
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cachePnt += curFetching;
|
cachePnt += curFetching;
|
||||||
if (cachePnt > descLen())
|
assert(cachePnt <= descLen());
|
||||||
cachePnt -= descLen();
|
if (cachePnt == descLen())
|
||||||
|
cachePnt = 0;
|
||||||
|
|
||||||
curFetching = 0;
|
curFetching = 0;
|
||||||
|
|
||||||
|
@ -337,8 +364,8 @@ class IGbE : public PciDev
|
||||||
curHead += wbOut;
|
curHead += wbOut;
|
||||||
wbOut = 0;
|
wbOut = 0;
|
||||||
|
|
||||||
if (curHead > descLen())
|
if (curHead >= descLen())
|
||||||
curHead = 0;
|
curHead -= descLen();
|
||||||
|
|
||||||
// Update the head
|
// Update the head
|
||||||
updateHead(curHead);
|
updateHead(curHead);
|
||||||
|
@ -390,6 +417,9 @@ class IGbE : public PciDev
|
||||||
|
|
||||||
usedCache.clear();
|
usedCache.clear();
|
||||||
unusedCache.clear();
|
unusedCache.clear();
|
||||||
|
|
||||||
|
cachePnt = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -162,7 +162,7 @@ struct TxDesc {
|
||||||
|
|
||||||
namespace TxdOp {
|
namespace TxdOp {
|
||||||
const uint8_t TXD_CNXT = 0x0;
|
const uint8_t TXD_CNXT = 0x0;
|
||||||
const uint8_t TXD_DATA = 0x0;
|
const uint8_t TXD_DATA = 0x1;
|
||||||
|
|
||||||
bool isLegacy(TxDesc *d) { return !bits(d->d2,29,29); }
|
bool isLegacy(TxDesc *d) { return !bits(d->d2,29,29); }
|
||||||
uint8_t getType(TxDesc *d) { return bits(d->d2, 23,20); }
|
uint8_t getType(TxDesc *d) { return bits(d->d2, 23,20); }
|
||||||
|
|
Loading…
Reference in a new issue