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);
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;
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;
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;
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;
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)) &&
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;
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);
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;
regs.rdlen = val & ~mask(7);
rxDescCache.areaChanged();
break;
+ case REG_SRRCTL:
+ regs.srrctl = val;
+ break;
case REG_RDH:
regs.rdh = val;
rxDescCache.areaChanged();
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();
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");
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)) &&
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
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)),
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");
}
}
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;
}
}
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;
}
}
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()) {
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)
{
}
// 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;
tsoPrevSeq = 0;
tsoPktHasHeader = false;
tsoPkts = 0;
+
}
TxdOp::setDd(desc);
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);
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;
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)
{
SERIALIZE_SCALAR(tsoCopyBytes);
SERIALIZE_SCALAR(tsoPkts);
-
+ SERIALIZE_SCALAR(completionAddress);
+ SERIALIZE_SCALAR(completionEnabled);
+ SERIALIZE_SCALAR(descEnd);
}
void
UNSERIALIZE_SCALAR(tsoDescBytesUsed);
UNSERIALIZE_SCALAR(tsoCopyBytes);
UNSERIALIZE_SCALAR(tsoPkts);
+
+ UNSERIALIZE_SCALAR(completionAddress);
+ UNSERIALIZE_SCALAR(completionEnabled);
+ UNSERIALIZE_SCALAR(descEnd);
}
bool
}
// 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);
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;
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;
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;
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
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;
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
{
// 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 {
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); }
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
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;
};
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
};
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
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 #####
};
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);
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);
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)
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);
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