IGbE: Add support for newer 8257x based Intel NICs
This commit is contained in:
parent
400e516261
commit
dd788a23c9
5 changed files with 458 additions and 60 deletions
|
@ -67,7 +67,9 @@ class EtherDevice(PciDevice):
|
|||
interface = Port("Ethernet Interrface")
|
||||
|
||||
class IGbE(EtherDevice):
|
||||
# Base class for two IGbE adapters listed above
|
||||
type = 'IGbE'
|
||||
#abstract = True
|
||||
hardware_address = Param.EthernetAddr(NextEthernetAddr,
|
||||
"Ethernet Hardware Address")
|
||||
use_flow_control = Param.Bool(False,
|
||||
|
@ -80,7 +82,6 @@ class IGbE(EtherDevice):
|
|||
"Number of enteries in the rx descriptor cache")
|
||||
clock = Param.Clock('500MHz', "Clock speed of the device")
|
||||
VendorID = 0x8086
|
||||
DeviceID = 0x1075
|
||||
SubsystemID = 0x1008
|
||||
SubsystemVendorID = 0x8086
|
||||
Status = 0x0000
|
||||
|
@ -104,8 +105,21 @@ class IGbE(EtherDevice):
|
|||
wb_comp_delay = Param.Latency('10ns', "delay after desc wb occurs")
|
||||
tx_read_delay = Param.Latency('0ns', "delay after tx dma read")
|
||||
rx_write_delay = Param.Latency('0ns', "delay after rx dma read")
|
||||
is8257 = Param.Bool("Select between and 8254x and 8257x device")
|
||||
|
||||
|
||||
class IGbE_e1000(IGbE):
|
||||
# Older Intel 8254x based gigabit ethernet adapter
|
||||
# Uses Intel e1000 driver
|
||||
DeviceID = 0x1075
|
||||
is8257 = False
|
||||
|
||||
class IGbE_igb(IGbE):
|
||||
# Newer Intel 8257x based gigabit ethernet adapter
|
||||
# Uses Intel igb driver and in theory supports packet splitting and LRO
|
||||
DeviceID = 0x10C9
|
||||
is8257 = True
|
||||
|
||||
class EtherDevBase(EtherDevice):
|
||||
type = 'EtherDevBase'
|
||||
abstract = True
|
||||
|
|
|
@ -98,7 +98,7 @@ if env['FULL_SYSTEM']:
|
|||
CompoundFlag('DiskImageAll', [ 'DiskImageRead', 'DiskImageWrite' ])
|
||||
CompoundFlag('EthernetAll', [ 'Ethernet', 'EthernetPIO', 'EthernetDMA',
|
||||
'EthernetData' , 'EthernetDesc', 'EthernetIntr', 'EthernetSM',
|
||||
'EthernetCksum' ])
|
||||
'EthernetCksum', 'EthernetEEPROM' ])
|
||||
CompoundFlag('EthernetNoData', [ 'Ethernet', 'EthernetPIO', 'EthernetDesc',
|
||||
'EthernetIntr', 'EthernetSM', 'EthernetCksum' ])
|
||||
CompoundFlag('IdeAll', [ 'IdeCtrl', 'IdeDisk' ])
|
||||
|
|
|
@ -85,6 +85,9 @@ IGbE::IGbE(const Params *p)
|
|||
regs.rxdctl.gran(1);
|
||||
regs.rxdctl.wthresh(1);
|
||||
regs.fcrth(1);
|
||||
regs.tdwba = 0;
|
||||
regs.rlpml = 0;
|
||||
regs.sw_fw_sync = 0;
|
||||
|
||||
regs.pba.rxa(0x30);
|
||||
regs.pba.txa(0x10);
|
||||
|
@ -197,6 +200,11 @@ IGbE::read(PacketPtr pkt)
|
|||
regs.imr &= ~regs.iam;
|
||||
chkInterrupt();
|
||||
break;
|
||||
case REG_EICR:
|
||||
// This is only useful for MSI, but the driver reads it every time
|
||||
// Just don't do anything
|
||||
pkt->set<uint32_t>(0);
|
||||
break;
|
||||
case REG_ITR:
|
||||
pkt->set<uint32_t>(regs.itr());
|
||||
break;
|
||||
|
@ -231,6 +239,9 @@ IGbE::read(PacketPtr pkt)
|
|||
case REG_RDLEN:
|
||||
pkt->set<uint32_t>(regs.rdlen());
|
||||
break;
|
||||
case REG_SRRCTL:
|
||||
pkt->set<uint32_t>(regs.srrctl());
|
||||
break;
|
||||
case REG_RDH:
|
||||
pkt->set<uint32_t>(regs.rdh());
|
||||
break;
|
||||
|
@ -246,6 +257,9 @@ IGbE::read(PacketPtr pkt)
|
|||
regs.rdtr.fpd(0);
|
||||
}
|
||||
break;
|
||||
case REG_RXDCTL:
|
||||
pkt->set<uint32_t>(regs.rxdctl());
|
||||
break;
|
||||
case REG_RADV:
|
||||
pkt->set<uint32_t>(regs.radv());
|
||||
break;
|
||||
|
@ -261,6 +275,9 @@ IGbE::read(PacketPtr pkt)
|
|||
case REG_TDH:
|
||||
pkt->set<uint32_t>(regs.tdh());
|
||||
break;
|
||||
case REG_TXDCA_CTL:
|
||||
pkt->set<uint32_t>(regs.txdca_ctl());
|
||||
break;
|
||||
case REG_TDT:
|
||||
pkt->set<uint32_t>(regs.tdt());
|
||||
break;
|
||||
|
@ -273,12 +290,34 @@ IGbE::read(PacketPtr pkt)
|
|||
case REG_TADV:
|
||||
pkt->set<uint32_t>(regs.tadv());
|
||||
break;
|
||||
case REG_TDWBAL:
|
||||
pkt->set<uint32_t>(regs.tdwba & mask(32));
|
||||
break;
|
||||
case REG_TDWBAH:
|
||||
pkt->set<uint32_t>(regs.tdwba >> 32);
|
||||
break;
|
||||
case REG_RXCSUM:
|
||||
pkt->set<uint32_t>(regs.rxcsum());
|
||||
break;
|
||||
case REG_RLPML:
|
||||
pkt->set<uint32_t>(regs.rlpml);
|
||||
break;
|
||||
case REG_RFCTL:
|
||||
pkt->set<uint32_t>(regs.rfctl());
|
||||
break;
|
||||
case REG_MANC:
|
||||
pkt->set<uint32_t>(regs.manc());
|
||||
break;
|
||||
case REG_SWSM:
|
||||
pkt->set<uint32_t>(regs.swsm());
|
||||
regs.swsm.smbi(1);
|
||||
break;
|
||||
case REG_FWSM:
|
||||
pkt->set<uint32_t>(regs.fwsm());
|
||||
break;
|
||||
case REG_SWFWSYNC:
|
||||
pkt->set<uint32_t>(regs.sw_fw_sync);
|
||||
break;
|
||||
default:
|
||||
if (!(daddr >= REG_VFTA && daddr < (REG_VFTA + VLAN_FILTER_TABLE_SIZE*4)) &&
|
||||
!(daddr >= REG_RAL && daddr < (REG_RAL + RCV_ADDRESS_TABLE_SIZE*8)) &&
|
||||
|
@ -385,6 +424,14 @@ IGbE::write(PacketPtr pkt)
|
|||
break;
|
||||
case REG_EERD:
|
||||
regs.eerd = val;
|
||||
if (regs.eerd.start()) {
|
||||
regs.eerd.done(1);
|
||||
assert(regs.eerd.addr() < EEPROM_SIZE);
|
||||
regs.eerd.data(flash[regs.eerd.addr()]);
|
||||
regs.eerd.start(0);
|
||||
DPRINTF(EthernetEEPROM, "EEPROM: read addr: %#X data %#x\n",
|
||||
regs.eerd.addr(), regs.eerd.data());
|
||||
}
|
||||
break;
|
||||
case REG_MDIC:
|
||||
regs.mdic = val;
|
||||
|
@ -399,10 +446,16 @@ IGbE::write(PacketPtr pkt)
|
|||
regs.mdic.data(0x796D); // link up
|
||||
break;
|
||||
case PHY_PID:
|
||||
regs.mdic.data(0x02A8);
|
||||
if (params()->is8257)
|
||||
regs.mdic.data(0x0141);
|
||||
else
|
||||
regs.mdic.data(0x02A8);
|
||||
break;
|
||||
case PHY_EPID:
|
||||
regs.mdic.data(0x0380);
|
||||
if (params()->is8257)
|
||||
regs.mdic.data(0x0CC0);
|
||||
else
|
||||
regs.mdic.data(0x0380);
|
||||
break;
|
||||
case PHY_GSTATUS:
|
||||
regs.mdic.data(0x7C00);
|
||||
|
@ -485,6 +538,9 @@ IGbE::write(PacketPtr pkt)
|
|||
case REG_TIPG:
|
||||
; // We don't care, so don't store anything
|
||||
break;
|
||||
case REG_IVAR0:
|
||||
warn("Writing to IVAR0, ignoring...\n");
|
||||
break;
|
||||
case REG_FCRTL:
|
||||
regs.fcrtl = val;
|
||||
break;
|
||||
|
@ -503,6 +559,9 @@ IGbE::write(PacketPtr pkt)
|
|||
regs.rdlen = val & ~mask(7);
|
||||
rxDescCache.areaChanged();
|
||||
break;
|
||||
case REG_SRRCTL:
|
||||
regs.srrctl = val;
|
||||
break;
|
||||
case REG_RDH:
|
||||
regs.rdh = val;
|
||||
rxDescCache.areaChanged();
|
||||
|
@ -523,6 +582,9 @@ IGbE::write(PacketPtr pkt)
|
|||
case REG_RADV:
|
||||
regs.radv = val;
|
||||
break;
|
||||
case REG_RXDCTL:
|
||||
regs.rxdctl = val;
|
||||
break;
|
||||
case REG_TDBAL:
|
||||
regs.tdba.tdbal( val & ~mask(4));
|
||||
txDescCache.areaChanged();
|
||||
|
@ -539,6 +601,11 @@ IGbE::write(PacketPtr pkt)
|
|||
regs.tdh = val;
|
||||
txDescCache.areaChanged();
|
||||
break;
|
||||
case REG_TXDCA_CTL:
|
||||
regs.txdca_ctl = val;
|
||||
if (regs.txdca_ctl.enabled())
|
||||
panic("No support for DCA\n");
|
||||
break;
|
||||
case REG_TDT:
|
||||
regs.tdt = val;
|
||||
DPRINTF(EthernetSM, "TXS: TX Tail pointer updated\n");
|
||||
|
@ -558,12 +625,38 @@ IGbE::write(PacketPtr pkt)
|
|||
case REG_TADV:
|
||||
regs.tadv = val;
|
||||
break;
|
||||
case REG_TDWBAL:
|
||||
regs.tdwba &= ~mask(32);
|
||||
regs.tdwba |= val;
|
||||
txDescCache.completionWriteback(regs.tdwba & ~mask(1), regs.tdwba & mask(1));
|
||||
break;
|
||||
case REG_TDWBAH:
|
||||
regs.tdwba &= mask(32);
|
||||
regs.tdwba |= (uint64_t)val << 32;
|
||||
txDescCache.completionWriteback(regs.tdwba & ~mask(1), regs.tdwba & mask(1));
|
||||
break;
|
||||
case REG_RXCSUM:
|
||||
regs.rxcsum = val;
|
||||
break;
|
||||
case REG_RLPML:
|
||||
regs.rlpml = val;
|
||||
break;
|
||||
case REG_RFCTL:
|
||||
regs.rfctl = val;
|
||||
if (regs.rfctl.exsten())
|
||||
panic("Extended RX descriptors not implemented\n");
|
||||
break;
|
||||
case REG_MANC:
|
||||
regs.manc = val;
|
||||
break;
|
||||
case REG_SWSM:
|
||||
regs.swsm = val;
|
||||
if (regs.fwsm.eep_fw_semaphore())
|
||||
regs.swsm.swesmbi(0);
|
||||
break;
|
||||
case REG_SWFWSYNC:
|
||||
regs.sw_fw_sync = val;
|
||||
break;
|
||||
default:
|
||||
if (!(daddr >= REG_VFTA && daddr < (REG_VFTA + VLAN_FILTER_TABLE_SIZE*4)) &&
|
||||
!(daddr >= REG_RAL && daddr < (REG_RAL + RCV_ADDRESS_TABLE_SIZE*8)) &&
|
||||
|
@ -710,19 +803,38 @@ IGbE::RxDescCache::RxDescCache(IGbE *i, const std::string n, int s)
|
|||
void
|
||||
IGbE::RxDescCache::writePacket(EthPacketPtr packet)
|
||||
{
|
||||
// We shouldn't have to deal with any of these yet
|
||||
DPRINTF(EthernetDesc, "Packet Length: %d Desc Size: %d\n",
|
||||
packet->length, igbe->regs.rctl.descSize());
|
||||
assert(packet->length < igbe->regs.rctl.descSize());
|
||||
|
||||
assert(unusedCache.size());
|
||||
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, igbe->rxWriteDelay);
|
||||
|
||||
Addr buf;
|
||||
RxDesc *desc = unusedCache.front();
|
||||
switch (igbe->regs.srrctl.desctype()) {
|
||||
case RXDT_LEGACY:
|
||||
buf = desc->legacy.buf;
|
||||
DPRINTF(EthernetDesc, "Packet Length: %d Desc Size: %d\n",
|
||||
packet->length, igbe->regs.rctl.descSize());
|
||||
assert(packet->length < igbe->regs.rctl.descSize());
|
||||
break;
|
||||
case RXDT_ADV_ONEBUF:
|
||||
int buf_len;
|
||||
buf_len = igbe->regs.rctl.lpe() ? igbe->regs.srrctl.bufLen() :
|
||||
igbe->regs.rctl.descSize();
|
||||
DPRINTF(EthernetDesc, "Packet Length: %d srrctl: %#x Desc Size: %d\n",
|
||||
packet->length, igbe->regs.srrctl(), buf_len);
|
||||
assert(packet->length < buf_len);
|
||||
buf = desc->adv_read.pkt;
|
||||
break;
|
||||
default:
|
||||
panic("Unimplemnted RX receive buffer type: %d\n",
|
||||
igbe->regs.srrctl.desctype());
|
||||
}
|
||||
|
||||
igbe->dmaWrite(igbe->platform->pciToDma(buf), packet->length, &pktEvent,
|
||||
packet->data, igbe->rxWriteDelay);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -733,7 +845,6 @@ IGbE::RxDescCache::pktComplete()
|
|||
desc = unusedCache.front();
|
||||
|
||||
uint16_t crcfixup = igbe->regs.rctl.secrc() ? 0 : 4 ;
|
||||
desc->len = htole((uint16_t)(pktPtr->length + crcfixup));
|
||||
DPRINTF(EthernetDesc, "pktPtr->length: %d stripcrc offset: %d value written: %d %d\n",
|
||||
pktPtr->length, crcfixup,
|
||||
htole((uint16_t)(pktPtr->length + crcfixup)),
|
||||
|
@ -744,21 +855,28 @@ IGbE::RxDescCache::pktComplete()
|
|||
|
||||
DPRINTF(EthernetDesc, "Packet written to memory updating Descriptor\n");
|
||||
|
||||
uint8_t status = RXDS_DD | RXDS_EOP;
|
||||
uint16_t status = RXDS_DD | RXDS_EOP;
|
||||
uint8_t err = 0;
|
||||
uint16_t ext_err = 0;
|
||||
uint16_t csum = 0;
|
||||
uint16_t ptype = 0;
|
||||
uint16_t ip_id = 0;
|
||||
|
||||
IpPtr ip(pktPtr);
|
||||
|
||||
if (ip) {
|
||||
DPRINTF(EthernetDesc, "Proccesing Ip packet with Id=%d\n", ip->id());
|
||||
ptype |= RXDP_IPV4;
|
||||
ip_id = ip->id();
|
||||
|
||||
if (igbe->regs.rxcsum.ipofld()) {
|
||||
DPRINTF(EthernetDesc, "Checking IP checksum\n");
|
||||
status |= RXDS_IPCS;
|
||||
desc->csum = htole(cksum(ip));
|
||||
csum = htole(cksum(ip));
|
||||
igbe->rxIpChecksums++;
|
||||
if (cksum(ip) != 0) {
|
||||
err |= RXDE_IPE;
|
||||
ext_err |= RXDEE_IPE;
|
||||
DPRINTF(EthernetDesc, "Checksum is bad!!\n");
|
||||
}
|
||||
}
|
||||
|
@ -766,11 +884,13 @@ IGbE::RxDescCache::pktComplete()
|
|||
if (tcp && igbe->regs.rxcsum.tuofld()) {
|
||||
DPRINTF(EthernetDesc, "Checking TCP checksum\n");
|
||||
status |= RXDS_TCPCS;
|
||||
desc->csum = htole(cksum(tcp));
|
||||
ptype |= RXDP_TCP;
|
||||
csum = htole(cksum(tcp));
|
||||
igbe->rxTcpChecksums++;
|
||||
if (cksum(tcp) != 0) {
|
||||
DPRINTF(EthernetDesc, "Checksum is bad!!\n");
|
||||
err |= RXDE_TCPE;
|
||||
ext_err |= RXDEE_TCPE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -778,10 +898,12 @@ IGbE::RxDescCache::pktComplete()
|
|||
if (udp && igbe->regs.rxcsum.tuofld()) {
|
||||
DPRINTF(EthernetDesc, "Checking UDP checksum\n");
|
||||
status |= RXDS_UDPCS;
|
||||
desc->csum = htole(cksum(udp));
|
||||
ptype |= RXDP_UDP;
|
||||
csum = htole(cksum(udp));
|
||||
igbe->rxUdpChecksums++;
|
||||
if (cksum(udp) != 0) {
|
||||
DPRINTF(EthernetDesc, "Checksum is bad!!\n");
|
||||
ext_err |= RXDEE_TCPE;
|
||||
err |= RXDE_TCPE;
|
||||
}
|
||||
}
|
||||
|
@ -789,12 +911,38 @@ IGbE::RxDescCache::pktComplete()
|
|||
DPRINTF(EthernetSM, "Proccesing Non-Ip packet\n");
|
||||
}
|
||||
|
||||
switch (igbe->regs.srrctl.desctype()) {
|
||||
case RXDT_LEGACY:
|
||||
desc->legacy.len = htole((uint16_t)(pktPtr->length + crcfixup));
|
||||
desc->legacy.status = htole(status);
|
||||
desc->legacy.errors = htole(err);
|
||||
// No vlan support at this point... just set it to 0
|
||||
desc->legacy.vlan = 0;
|
||||
break;
|
||||
case RXDT_ADV_ONEBUF:
|
||||
desc->adv_wb.pkt_len = htole((uint16_t)(pktPtr->length + crcfixup));
|
||||
desc->adv_wb.rss_type = htole(0);
|
||||
desc->adv_wb.pkt_type = htole(ptype);
|
||||
// no header splititng support yet
|
||||
desc->adv_wb.header_len = htole(0);
|
||||
desc->adv_wb.sph = htole(0);
|
||||
if (igbe->regs.rxcsum.pcsd()) {
|
||||
// no rss support right now
|
||||
desc->adv_wb.rss_hash = htole(0);
|
||||
} else {
|
||||
desc->adv_wb.id = htole(ip_id);
|
||||
desc->adv_wb.csum = htole(csum);
|
||||
}
|
||||
desc->adv_wb.status = htole(status);
|
||||
desc->adv_wb.errors = htole(ext_err);
|
||||
// no vlan support
|
||||
desc->adv_wb.vlan_tag = htole(0);
|
||||
break;
|
||||
default:
|
||||
panic("Unimplemnted RX receive buffer type %d\n",
|
||||
igbe->regs.srrctl.desctype());
|
||||
}
|
||||
|
||||
desc->status = htole(status);
|
||||
desc->errors = htole(err);
|
||||
|
||||
// No vlan support at this point... just set it to 0
|
||||
desc->vlan = 0;
|
||||
|
||||
// Deal with the rx timer interrupts
|
||||
if (igbe->regs.rdtr.delay()) {
|
||||
|
@ -883,7 +1031,7 @@ IGbE::RxDescCache::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
|
||||
IGbE::TxDescCache::TxDescCache(IGbE *i, const std::string n, int s)
|
||||
: DescCache<TxDesc>(i,n, s), pktDone(false), isTcp(false), pktWaiting(false),
|
||||
useTso(false), pktEvent(this), headerEvent(this)
|
||||
useTso(false), pktEvent(this), headerEvent(this), nullEvent(this)
|
||||
|
||||
{
|
||||
}
|
||||
|
@ -907,13 +1055,15 @@ IGbE::TxDescCache::processContextDesc()
|
|||
// is this going to be a tcp or udp packet?
|
||||
isTcp = TxdOp::tcp(desc) ? true : false;
|
||||
|
||||
if (TxdOp::tse(desc)) {
|
||||
// setup all the TSO variables, they'll be ignored if we don't use
|
||||
// tso for this connection
|
||||
tsoHeaderLen = TxdOp::hdrlen(desc);
|
||||
tsoMss = TxdOp::mss(desc);
|
||||
|
||||
if (TxdOp::isType(desc, TxdOp::TXD_CNXT) && TxdOp::tse(desc)) {
|
||||
DPRINTF(EthernetDesc, "TCP offload enabled for packet hdrlen: %d mss: %d paylen %d\n",
|
||||
TxdOp::hdrlen(desc), TxdOp::mss(desc), TxdOp::getLen(desc));
|
||||
// setup all the TSO variables
|
||||
useTso = true;
|
||||
tsoHeaderLen = TxdOp::hdrlen(desc);
|
||||
tsoMss = TxdOp::mss(desc);
|
||||
tsoTotalLen = TxdOp::getLen(desc);
|
||||
tsoLoadedHeader = false;
|
||||
tsoDescBytesUsed = 0;
|
||||
|
@ -921,6 +1071,7 @@ IGbE::TxDescCache::processContextDesc()
|
|||
tsoPrevSeq = 0;
|
||||
tsoPktHasHeader = false;
|
||||
tsoPkts = 0;
|
||||
|
||||
}
|
||||
|
||||
TxdOp::setDd(desc);
|
||||
|
@ -931,10 +1082,23 @@ IGbE::TxDescCache::processContextDesc()
|
|||
if (!unusedCache.size())
|
||||
return;
|
||||
|
||||
desc = unusedCache.front();
|
||||
if (!useTso && TxdOp::isType(desc, TxdOp::TXD_ADVDATA) && TxdOp::tse(desc)) {
|
||||
DPRINTF(EthernetDesc, "TCP offload(adv) enabled for packet hdrlen: %d mss: %d paylen %d\n",
|
||||
tsoHeaderLen, tsoMss, TxdOp::getTsoLen(desc));
|
||||
useTso = true;
|
||||
tsoTotalLen = TxdOp::getTsoLen(desc);
|
||||
tsoLoadedHeader = false;
|
||||
tsoDescBytesUsed = 0;
|
||||
tsoUsedLen = 0;
|
||||
tsoPrevSeq = 0;
|
||||
tsoPktHasHeader = false;
|
||||
tsoPkts = 0;
|
||||
}
|
||||
|
||||
if (useTso && !tsoLoadedHeader) {
|
||||
// we need to fetch a header
|
||||
DPRINTF(EthernetDesc, "Starting DMA of TSO header\n");
|
||||
desc = unusedCache.front();
|
||||
assert(TxdOp::isData(desc) && TxdOp::getLen(desc) >= tsoHeaderLen);
|
||||
pktWaiting = true;
|
||||
assert(tsoHeaderLen <= 256);
|
||||
|
@ -1015,6 +1179,7 @@ IGbE::TxDescCache::getPacketData(EthPacketPtr p)
|
|||
TxDesc *desc;
|
||||
desc = unusedCache.front();
|
||||
|
||||
DPRINTF(EthernetDesc, "getPacketData(): TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2);
|
||||
assert((TxdOp::isLegacy(desc) || TxdOp::isData(desc)) && TxdOp::getLen(desc));
|
||||
|
||||
pktPtr = p;
|
||||
|
@ -1216,14 +1381,34 @@ IGbE::TxDescCache::pktComplete()
|
|||
if (igbe->regs.txdctl.wthresh() == 0) {
|
||||
DPRINTF(EthernetDesc, "WTHRESH == 0, writing back descriptor\n");
|
||||
writeback(0);
|
||||
} else if (igbe->regs.txdctl.gran() && igbe->regs.txdctl.wthresh() >=
|
||||
descInBlock(usedCache.size())) {
|
||||
DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");
|
||||
writeback((igbe->cacheBlockSize()-1)>>4);
|
||||
} else if (igbe->regs.txdctl.wthresh() >= usedCache.size()) {
|
||||
DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");
|
||||
writeback((igbe->cacheBlockSize()-1)>>4);
|
||||
}
|
||||
|
||||
enableSm();
|
||||
igbe->checkDrain();
|
||||
}
|
||||
|
||||
void
|
||||
IGbE::TxDescCache::actionAfterWb()
|
||||
{
|
||||
DPRINTF(EthernetDesc, "actionAfterWb() completionEnabled: %d\n",
|
||||
completionEnabled);
|
||||
igbe->postInterrupt(iGbReg::IT_TXDW);
|
||||
if (completionEnabled) {
|
||||
descEnd = igbe->regs.tdh();
|
||||
DPRINTF(EthernetDesc, "Completion writing back value: %d to addr: %#x\n", descEnd,
|
||||
completionAddress);
|
||||
igbe->dmaWrite(igbe->platform->pciToDma(mbits(completionAddress, 63, 2)),
|
||||
sizeof(descEnd), &nullEvent, (uint8_t*)&descEnd, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IGbE::TxDescCache::serialize(std::ostream &os)
|
||||
{
|
||||
|
@ -1247,7 +1432,9 @@ IGbE::TxDescCache::serialize(std::ostream &os)
|
|||
SERIALIZE_SCALAR(tsoCopyBytes);
|
||||
SERIALIZE_SCALAR(tsoPkts);
|
||||
|
||||
|
||||
SERIALIZE_SCALAR(completionAddress);
|
||||
SERIALIZE_SCALAR(completionEnabled);
|
||||
SERIALIZE_SCALAR(descEnd);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1272,6 +1459,10 @@ IGbE::TxDescCache::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
UNSERIALIZE_SCALAR(tsoDescBytesUsed);
|
||||
UNSERIALIZE_SCALAR(tsoCopyBytes);
|
||||
UNSERIALIZE_SCALAR(tsoPkts);
|
||||
|
||||
UNSERIALIZE_SCALAR(completionAddress);
|
||||
UNSERIALIZE_SCALAR(completionEnabled);
|
||||
UNSERIALIZE_SCALAR(descEnd);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1391,7 +1582,6 @@ IGbE::txStateMachine()
|
|||
}
|
||||
|
||||
// Only support descriptor granularity
|
||||
assert(regs.txdctl.gran());
|
||||
if (regs.txdctl.lwthresh() && txDescCache.descLeft() < (regs.txdctl.lwthresh() * 8)) {
|
||||
DPRINTF(EthernetSM, "TXS: LWTHRESH caused posting of TXDLOW\n");
|
||||
postInterrupt(IT_TXDLOW);
|
||||
|
|
|
@ -183,7 +183,7 @@ class IGbE : public EtherDevice
|
|||
virtual long descLen() const = 0;
|
||||
virtual void updateHead(long h) = 0;
|
||||
virtual void enableSm() = 0;
|
||||
virtual void intAfterWb() const {}
|
||||
virtual void actionAfterWb() {}
|
||||
virtual void fetchAfterWb() = 0;
|
||||
|
||||
std::deque<T*> usedCache;
|
||||
|
@ -440,7 +440,7 @@ class IGbE : public EtherDevice
|
|||
oldHead, curHead);
|
||||
|
||||
// If we still have more to wb, call wb now
|
||||
intAfterWb();
|
||||
actionAfterWb();
|
||||
if (moreToWb) {
|
||||
moreToWb = false;
|
||||
DPRINTF(EthernetDesc, "Writeback has more todo\n");
|
||||
|
@ -625,16 +625,22 @@ class IGbE : public EtherDevice
|
|||
virtual long descLen() const { return igbe->regs.tdlen() >> 4; }
|
||||
virtual void updateHead(long h) { igbe->regs.tdh(h); }
|
||||
virtual void enableSm();
|
||||
virtual void intAfterWb() const { igbe->postInterrupt(iGbReg::IT_TXDW); }
|
||||
virtual void actionAfterWb();
|
||||
virtual void fetchAfterWb() {
|
||||
if (!igbe->txTick && igbe->getState() == SimObject::Running)
|
||||
fetchDescriptors();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool pktDone;
|
||||
bool isTcp;
|
||||
bool pktWaiting;
|
||||
bool pktMultiDesc;
|
||||
Addr completionAddress;
|
||||
bool completionEnabled;
|
||||
uint32_t descEnd;
|
||||
|
||||
|
||||
// tso variables
|
||||
bool useTso;
|
||||
|
@ -662,6 +668,11 @@ class IGbE : public EtherDevice
|
|||
void getPacketData(EthPacketPtr p);
|
||||
void processContextDesc();
|
||||
|
||||
/** Return the number of dsecriptors in a cache block for threshold
|
||||
* operations.
|
||||
*/
|
||||
int descInBlock(int num_desc) { return num_desc /
|
||||
igbe->cacheBlockSize() / sizeof(iGbReg::TxDesc); }
|
||||
/** Ask if the packet has been transfered so the state machine can give
|
||||
* it to the fifo.
|
||||
* @return packet available in descriptor cache
|
||||
|
@ -689,8 +700,19 @@ class IGbE : public EtherDevice
|
|||
void headerComplete();
|
||||
EventWrapper<TxDescCache, &TxDescCache::headerComplete> headerEvent;
|
||||
|
||||
|
||||
void completionWriteback(Addr a, bool enabled) {
|
||||
DPRINTF(EthernetDesc, "Completion writeback Addr: %#x enabled: %d\n",
|
||||
a, enabled);
|
||||
completionAddress = a;
|
||||
completionEnabled = enabled;
|
||||
}
|
||||
|
||||
virtual bool hasOutstandingEvents();
|
||||
|
||||
void nullCallback() { DPRINTF(EthernetDesc, "Completion writeback complete\n"); }
|
||||
EventWrapper<TxDescCache, &TxDescCache::nullCallback> nullEvent;
|
||||
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
|
|
|
@ -59,11 +59,14 @@ const uint32_t REG_FCTTV = 0x00170;
|
|||
const uint32_t REG_TIPG = 0x00410;
|
||||
const uint32_t REG_AIFS = 0x00458;
|
||||
const uint32_t REG_LEDCTL = 0x00e00;
|
||||
const uint32_t REG_EICR = 0x01580;
|
||||
const uint32_t REG_IVAR0 = 0x01700;
|
||||
const uint32_t REG_FCRTL = 0x02160;
|
||||
const uint32_t REG_FCRTH = 0x02168;
|
||||
const uint32_t REG_RDBAL = 0x02800;
|
||||
const uint32_t REG_RDBAH = 0x02804;
|
||||
const uint32_t REG_RDLEN = 0x02808;
|
||||
const uint32_t REG_SRRCTL = 0x0280C;
|
||||
const uint32_t REG_RDH = 0x02810;
|
||||
const uint32_t REG_RDT = 0x02818;
|
||||
const uint32_t REG_RDTR = 0x02820;
|
||||
|
@ -74,12 +77,17 @@ const uint32_t REG_TDBAL = 0x03800;
|
|||
const uint32_t REG_TDBAH = 0x03804;
|
||||
const uint32_t REG_TDLEN = 0x03808;
|
||||
const uint32_t REG_TDH = 0x03810;
|
||||
const uint32_t REG_TXDCA_CTL = 0x03814;
|
||||
const uint32_t REG_TDT = 0x03818;
|
||||
const uint32_t REG_TIDV = 0x03820;
|
||||
const uint32_t REG_TXDCTL = 0x03828;
|
||||
const uint32_t REG_TADV = 0x0382C;
|
||||
const uint32_t REG_TDWBAL = 0x03838;
|
||||
const uint32_t REG_TDWBAH = 0x0383C;
|
||||
const uint32_t REG_CRCERRS = 0x04000;
|
||||
const uint32_t REG_RXCSUM = 0x05000;
|
||||
const uint32_t REG_RLPML = 0x05004;
|
||||
const uint32_t REG_RFCTL = 0x05008;
|
||||
const uint32_t REG_MTA = 0x05200;
|
||||
const uint32_t REG_RAL = 0x05400;
|
||||
const uint32_t REG_RAH = 0x05404;
|
||||
|
@ -87,6 +95,9 @@ const uint32_t REG_VFTA = 0x05600;
|
|||
|
||||
const uint32_t REG_WUC = 0x05800;
|
||||
const uint32_t REG_MANC = 0x05820;
|
||||
const uint32_t REG_SWSM = 0x05B50;
|
||||
const uint32_t REG_FWSM = 0x05B54;
|
||||
const uint32_t REG_SWFWSYNC = 0x05B5C;
|
||||
|
||||
const uint8_t EEPROM_READ_OPCODE_SPI = 0x03;
|
||||
const uint8_t EEPROM_RDSR_OPCODE_SPI = 0x05;
|
||||
|
@ -94,9 +105,9 @@ const uint8_t EEPROM_SIZE = 64;
|
|||
const uint16_t EEPROM_CSUM = 0xBABA;
|
||||
|
||||
const uint8_t VLAN_FILTER_TABLE_SIZE = 128;
|
||||
const uint8_t RCV_ADDRESS_TABLE_SIZE = 16;
|
||||
const uint8_t RCV_ADDRESS_TABLE_SIZE = 24;
|
||||
const uint8_t MULTICAST_TABLE_SIZE = 128;
|
||||
const uint32_t STATS_REGS_SIZE = 0x124;
|
||||
const uint32_t STATS_REGS_SIZE = 0x228;
|
||||
|
||||
|
||||
// Registers in that are accessed in the PHY
|
||||
|
@ -108,14 +119,17 @@ const uint8_t PHY_EPSTATUS = 15;
|
|||
const uint8_t PHY_AGC = 18;
|
||||
|
||||
// Receive Descriptor Status Flags
|
||||
const uint8_t RXDS_PIF = 0x80;
|
||||
const uint8_t RXDS_IPCS = 0x40;
|
||||
const uint8_t RXDS_TCPCS = 0x20;
|
||||
const uint8_t RXDS_UDPCS = 0x10;
|
||||
const uint8_t RXDS_VP = 0x08;
|
||||
const uint8_t RXDS_IXSM = 0x04;
|
||||
const uint8_t RXDS_EOP = 0x02;
|
||||
const uint8_t RXDS_DD = 0x01;
|
||||
const uint16_t RXDS_DYNINT = 0x800;
|
||||
const uint16_t RXDS_UDPV = 0x400;
|
||||
const uint16_t RXDS_CRCV = 0x100;
|
||||
const uint16_t RXDS_PIF = 0x080;
|
||||
const uint16_t RXDS_IPCS = 0x040;
|
||||
const uint16_t RXDS_TCPCS = 0x020;
|
||||
const uint16_t RXDS_UDPCS = 0x010;
|
||||
const uint16_t RXDS_VP = 0x008;
|
||||
const uint16_t RXDS_IXSM = 0x004;
|
||||
const uint16_t RXDS_EOP = 0x002;
|
||||
const uint16_t RXDS_DD = 0x001;
|
||||
|
||||
// Receive Descriptor Error Flags
|
||||
const uint8_t RXDE_RXE = 0x80;
|
||||
|
@ -125,6 +139,32 @@ const uint8_t RXDE_SEQ = 0x04;
|
|||
const uint8_t RXDE_SE = 0x02;
|
||||
const uint8_t RXDE_CE = 0x01;
|
||||
|
||||
// Receive Descriptor Extended Error Flags
|
||||
const uint16_t RXDEE_HBO = 0x008;
|
||||
const uint16_t RXDEE_CE = 0x010;
|
||||
const uint16_t RXDEE_LE = 0x020;
|
||||
const uint16_t RXDEE_PE = 0x080;
|
||||
const uint16_t RXDEE_OSE = 0x100;
|
||||
const uint16_t RXDEE_USE = 0x200;
|
||||
const uint16_t RXDEE_TCPE = 0x400;
|
||||
const uint16_t RXDEE_IPE = 0x800;
|
||||
|
||||
|
||||
// Receive Descriptor Types
|
||||
const uint8_t RXDT_LEGACY = 0x00;
|
||||
const uint8_t RXDT_ADV_ONEBUF = 0x01;
|
||||
const uint8_t RXDT_ADV_SPLIT_A = 0x05;
|
||||
|
||||
// Receive Descriptor Packet Types
|
||||
const uint16_t RXDP_IPV4 = 0x001;
|
||||
const uint16_t RXDP_IPV4E = 0x002;
|
||||
const uint16_t RXDP_IPV6 = 0x004;
|
||||
const uint16_t RXDP_IPV6E = 0x008;
|
||||
const uint16_t RXDP_TCP = 0x010;
|
||||
const uint16_t RXDP_UDP = 0x020;
|
||||
const uint16_t RXDP_SCTP = 0x040;
|
||||
const uint16_t RXDP_NFS = 0x080;
|
||||
|
||||
// Interrupt types
|
||||
enum IntTypes
|
||||
{
|
||||
|
@ -147,12 +187,38 @@ enum IntTypes
|
|||
|
||||
// Receive Descriptor struct
|
||||
struct RxDesc {
|
||||
Addr buf;
|
||||
uint16_t len;
|
||||
uint16_t csum;
|
||||
uint8_t status;
|
||||
uint8_t errors;
|
||||
uint16_t vlan;
|
||||
union {
|
||||
struct {
|
||||
Addr buf;
|
||||
uint16_t len;
|
||||
uint16_t csum;
|
||||
uint8_t status;
|
||||
uint8_t errors;
|
||||
uint16_t vlan;
|
||||
} legacy;
|
||||
struct {
|
||||
Addr pkt;
|
||||
Addr hdr;
|
||||
} adv_read;
|
||||
struct {
|
||||
uint16_t rss_type:4;
|
||||
uint16_t pkt_type:12;
|
||||
uint16_t __reserved1:5;
|
||||
uint16_t header_len:10;
|
||||
uint16_t sph:1;
|
||||
union {
|
||||
struct {
|
||||
uint16_t id;
|
||||
uint16_t csum;
|
||||
};
|
||||
uint32_t rss_hash;
|
||||
};
|
||||
uint32_t status:20;
|
||||
uint32_t errors:12;
|
||||
uint16_t pkt_len;
|
||||
uint16_t vlan_tag;
|
||||
} adv_wb ;
|
||||
};
|
||||
};
|
||||
|
||||
struct TxDesc {
|
||||
|
@ -163,24 +229,33 @@ struct TxDesc {
|
|||
namespace TxdOp {
|
||||
const uint8_t TXD_CNXT = 0x0;
|
||||
const uint8_t TXD_DATA = 0x1;
|
||||
const uint8_t TXD_ADVCNXT = 0x2;
|
||||
const uint8_t TXD_ADVDATA = 0x3;
|
||||
|
||||
bool isLegacy(TxDesc *d) { return !bits(d->d2,29,29); }
|
||||
uint8_t getType(TxDesc *d) { return bits(d->d2, 23,20); }
|
||||
bool isContext(TxDesc *d) { return !isLegacy(d) && getType(d) == TXD_CNXT; }
|
||||
bool isData(TxDesc *d) { return !isLegacy(d) && getType(d) == TXD_DATA; }
|
||||
bool isType(TxDesc *d, uint8_t type) { return getType(d) == type; }
|
||||
bool isTypes(TxDesc *d, uint8_t t1, uint8_t t2) { return isType(d, t1) || isType(d, t2); }
|
||||
bool isAdvDesc(TxDesc *d) { return !isLegacy(d) && isTypes(d, TXD_ADVDATA,TXD_ADVCNXT); }
|
||||
bool isContext(TxDesc *d) { return !isLegacy(d) && isTypes(d,TXD_CNXT, TXD_ADVCNXT); }
|
||||
bool isData(TxDesc *d) { return !isLegacy(d) && isTypes(d, TXD_DATA, TXD_ADVDATA); }
|
||||
|
||||
Addr getBuf(TxDesc *d) { assert(isLegacy(d) || isData(d)); return d->d1; }
|
||||
Addr getLen(TxDesc *d) { if (isLegacy(d)) return bits(d->d2,15,0); else return bits(d->d2, 19,0); }
|
||||
void setDd(TxDesc *d)
|
||||
{
|
||||
replaceBits(d->d2, 35, 32, ULL(1));
|
||||
}
|
||||
void setDd(TxDesc *d) { replaceBits(d->d2, 35, 32, ULL(1)); }
|
||||
|
||||
bool ide(TxDesc *d) { return bits(d->d2, 31,31); }
|
||||
bool ide(TxDesc *d) { return bits(d->d2, 31,31) && (getType(d) == TXD_DATA || isLegacy(d)); }
|
||||
bool vle(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 30,30); }
|
||||
bool rs(TxDesc *d) { return bits(d->d2, 27,27); }
|
||||
bool ic(TxDesc *d) { assert(isLegacy(d) || isData(d)); return isLegacy(d) && bits(d->d2, 26,26); }
|
||||
bool tse(TxDesc *d) { return (isData(d) || isContext(d)) && bits(d->d2, 26,26); }
|
||||
bool tse(TxDesc *d) {
|
||||
if (isTypes(d, TXD_CNXT, TXD_DATA))
|
||||
return bits(d->d2, 26,26);
|
||||
if (isType(d, TXD_ADVDATA))
|
||||
return bits(d->d2, 31, 31);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ifcs(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 25,25); }
|
||||
bool eop(TxDesc *d) { assert(isLegacy(d) || isData(d)); return bits(d->d2, 24,24); }
|
||||
bool ip(TxDesc *d) { assert(isContext(d)); return bits(d->d2, 25,25); }
|
||||
|
@ -199,7 +274,14 @@ int ipcse(TxDesc *d) { assert(isContext(d)); return bits(d->d1,31,16); }
|
|||
int ipcso(TxDesc *d) { assert(isContext(d)); return bits(d->d1,15,8); }
|
||||
int ipcss(TxDesc *d) { assert(isContext(d)); return bits(d->d1,7,0); }
|
||||
int mss(TxDesc *d) { assert(isContext(d)); return bits(d->d2,63,48); }
|
||||
int hdrlen(TxDesc *d) { assert(isContext(d)); return bits(d->d2,47,40); }
|
||||
int hdrlen(TxDesc *d) {
|
||||
assert(isContext(d));
|
||||
if (!isAdvDesc(d))
|
||||
return bits(d->d2,47,40);
|
||||
return bits(d->d2, 47,40) + bits(d->d1, 8,0) + bits(d->d1, 15, 9);
|
||||
}
|
||||
|
||||
int getTsoLen(TxDesc *d) { assert(isType(d, TXD_ADVDATA)); return bits(d->d2, 63,46); }
|
||||
int utcmd(TxDesc *d) { assert(isContext(d)); return bits(d->d2,24,31); }
|
||||
} // namespace TxdOp
|
||||
|
||||
|
@ -304,8 +386,8 @@ struct Regs {
|
|||
struct EERD : public Reg<uint32_t> { // 0x0014 EERD Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(start,0,1); // start read
|
||||
ADD_FIELD32(done,4,1); // done read
|
||||
ADD_FIELD32(addr,8,8); // address
|
||||
ADD_FIELD32(done,1,1); // done read
|
||||
ADD_FIELD32(addr,2,14); // address
|
||||
ADD_FIELD32(data,16,16); // data
|
||||
};
|
||||
EERD eerd;
|
||||
|
@ -471,6 +553,17 @@ struct Regs {
|
|||
};
|
||||
RDLEN rdlen;
|
||||
|
||||
struct SRRCTL : public Reg<uint32_t> { // 0x280C SRRCTL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(pktlen, 0, 7);
|
||||
ADD_FIELD32(hdrlen, 16, 7); // guess based on header, not documented
|
||||
ADD_FIELD32(desctype, 25,3); // type of descriptor 000 legacy, 001 adv,
|
||||
//101 hdr split
|
||||
int bufLen() { return pktlen() << 10; }
|
||||
int hdrLen() { return hdrlen() << 6; }
|
||||
};
|
||||
SRRCTL srrctl;
|
||||
|
||||
struct RDH : public Reg<uint32_t> { // 0x2810 RDH Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(rdh,0,16); // head of the descriptor ring
|
||||
|
@ -532,6 +625,14 @@ struct Regs {
|
|||
};
|
||||
TDH tdh;
|
||||
|
||||
struct TXDCA_CTL : public Reg<uint32_t> { // 0x3814 TXDCA_CTL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(cpu_mask, 0, 5);
|
||||
ADD_FIELD32(enabled, 5,1);
|
||||
ADD_FIELD32(relax_ordering, 6, 1);
|
||||
};
|
||||
TXDCA_CTL txdca_ctl;
|
||||
|
||||
struct TDT : public Reg<uint32_t> { // 0x3818 TDT Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(tdt,0,16); // tail of the descriptor ring
|
||||
|
@ -564,15 +665,42 @@ struct Regs {
|
|||
ADD_FIELD32(idv,0,16); // absolute interrupt delay
|
||||
};
|
||||
TADV tadv;
|
||||
/*
|
||||
struct TDWBA : public Reg<uint64_t> { // 0x3838 TDWBA Register
|
||||
using Reg<uint64_t>::operator=;
|
||||
ADD_FIELD64(en,0,1); // enable transmit description ring address writeback
|
||||
ADD_FIELD64(tdwbal,2,32); // base address of transmit descriptor ring address writeback
|
||||
ADD_FIELD64(tdwbah,32,32); // base address of transmit descriptor ring
|
||||
};
|
||||
TDWBA tdwba;*/
|
||||
uint64_t tdwba;
|
||||
|
||||
struct RXCSUM : public Reg<uint32_t> { // 0x5000 RXCSUM Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(pcss,0,8);
|
||||
ADD_FIELD32(ipofld,8,1);
|
||||
ADD_FIELD32(tuofld,9,1);
|
||||
ADD_FIELD32(pcsd, 13,1);
|
||||
};
|
||||
RXCSUM rxcsum;
|
||||
|
||||
uint32_t rlpml; // 0x5004 RLPML probably maximum accepted packet size
|
||||
|
||||
struct RFCTL : public Reg<uint32_t> { // 0x5008 RFCTL Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(iscsi_dis,0,1);
|
||||
ADD_FIELD32(iscsi_dwc,1,5);
|
||||
ADD_FIELD32(nfsw_dis,6,1);
|
||||
ADD_FIELD32(nfsr_dis,7,1);
|
||||
ADD_FIELD32(nfs_ver,8,2);
|
||||
ADD_FIELD32(ipv6_dis,10,1);
|
||||
ADD_FIELD32(ipv6xsum_dis,11,1);
|
||||
ADD_FIELD32(ackdis,13,1);
|
||||
ADD_FIELD32(ipfrsp_dis,14,1);
|
||||
ADD_FIELD32(exsten,15,1);
|
||||
};
|
||||
RFCTL rfctl;
|
||||
|
||||
struct MANC : public Reg<uint32_t> { // 0x5820 MANC Register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(smbus,0,1); // SMBus enabled #####
|
||||
|
@ -605,6 +733,32 @@ struct Regs {
|
|||
};
|
||||
MANC manc;
|
||||
|
||||
struct SWSM : public Reg<uint32_t> { // 0x5B50 SWSM register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(smbi,0,1); // Semaphone bit
|
||||
ADD_FIELD32(swesmbi, 1,1); // Software eeporm semaphore
|
||||
ADD_FIELD32(wmng, 2,1); // Wake MNG clock
|
||||
ADD_FIELD32(reserved, 3, 29);
|
||||
};
|
||||
SWSM swsm;
|
||||
|
||||
struct FWSM : public Reg<uint32_t> { // 0x5B54 FWSM register
|
||||
using Reg<uint32_t>::operator=;
|
||||
ADD_FIELD32(eep_fw_semaphore,0,1);
|
||||
ADD_FIELD32(fw_mode, 1,3);
|
||||
ADD_FIELD32(ide, 4,1);
|
||||
ADD_FIELD32(sol, 5,1);
|
||||
ADD_FIELD32(eep_roload, 6,1);
|
||||
ADD_FIELD32(reserved, 7,8);
|
||||
ADD_FIELD32(fw_val_bit, 15, 1);
|
||||
ADD_FIELD32(reset_cnt, 16, 3);
|
||||
ADD_FIELD32(ext_err_ind, 19, 6);
|
||||
ADD_FIELD32(reserved2, 25, 7);
|
||||
};
|
||||
FWSM fwsm;
|
||||
|
||||
uint32_t sw_fw_sync;
|
||||
|
||||
void serialize(std::ostream &os)
|
||||
{
|
||||
paramOut(os, "ctrl", ctrl._data);
|
||||
|
@ -625,6 +779,7 @@ struct Regs {
|
|||
paramOut(os, "fcrth", fcrth._data);
|
||||
paramOut(os, "rdba", rdba._data);
|
||||
paramOut(os, "rdlen", rdlen._data);
|
||||
paramOut(os, "srrctl", srrctl._data);
|
||||
paramOut(os, "rdh", rdh._data);
|
||||
paramOut(os, "rdt", rdt._data);
|
||||
paramOut(os, "rdtr", rdtr._data);
|
||||
|
@ -634,12 +789,20 @@ struct Regs {
|
|||
paramOut(os, "tdba", tdba._data);
|
||||
paramOut(os, "tdlen", tdlen._data);
|
||||
paramOut(os, "tdh", tdh._data);
|
||||
paramOut(os, "txdca_ctl", txdca_ctl._data);
|
||||
paramOut(os, "tdt", tdt._data);
|
||||
paramOut(os, "tidv", tidv._data);
|
||||
paramOut(os, "txdctl", txdctl._data);
|
||||
paramOut(os, "tadv", tadv._data);
|
||||
//paramOut(os, "tdwba", tdwba._data);
|
||||
SERIALIZE_SCALAR(tdwba);
|
||||
paramOut(os, "rxcsum", rxcsum._data);
|
||||
SERIALIZE_SCALAR(rlpml);
|
||||
paramOut(os, "rfctl", rfctl._data);
|
||||
paramOut(os, "manc", manc._data);
|
||||
paramOut(os, "swsm", swsm._data);
|
||||
paramOut(os, "fwsm", fwsm._data);
|
||||
SERIALIZE_SCALAR(sw_fw_sync);
|
||||
}
|
||||
|
||||
void unserialize(Checkpoint *cp, const std::string §ion)
|
||||
|
@ -662,6 +825,7 @@ struct Regs {
|
|||
paramIn(cp, section, "fcrth", fcrth._data);
|
||||
paramIn(cp, section, "rdba", rdba._data);
|
||||
paramIn(cp, section, "rdlen", rdlen._data);
|
||||
paramIn(cp, section, "srrctl", srrctl._data);
|
||||
paramIn(cp, section, "rdh", rdh._data);
|
||||
paramIn(cp, section, "rdt", rdt._data);
|
||||
paramIn(cp, section, "rdtr", rdtr._data);
|
||||
|
@ -671,12 +835,20 @@ struct Regs {
|
|||
paramIn(cp, section, "tdba", tdba._data);
|
||||
paramIn(cp, section, "tdlen", tdlen._data);
|
||||
paramIn(cp, section, "tdh", tdh._data);
|
||||
paramIn(cp, section, "txdca_ctl", txdca_ctl._data);
|
||||
paramIn(cp, section, "tdt", tdt._data);
|
||||
paramIn(cp, section, "tidv", tidv._data);
|
||||
paramIn(cp, section, "txdctl", txdctl._data);
|
||||
paramIn(cp, section, "tadv", tadv._data);
|
||||
UNSERIALIZE_SCALAR(tdwba);
|
||||
//paramIn(cp, section, "tdwba", tdwba._data);
|
||||
paramIn(cp, section, "rxcsum", rxcsum._data);
|
||||
UNSERIALIZE_SCALAR(rlpml);
|
||||
paramIn(cp, section, "rfctl", rfctl._data);
|
||||
paramIn(cp, section, "manc", manc._data);
|
||||
paramIn(cp, section, "swsm", swsm._data);
|
||||
paramIn(cp, section, "fwsm", fwsm._data);
|
||||
UNSERIALIZE_SCALAR(sw_fw_sync);
|
||||
}
|
||||
};
|
||||
} // iGbReg namespace
|
||||
|
|
Loading…
Reference in a new issue