}
void
-Device::prepareIO(int cpu)
+Device::prepareIO(int cpu, int index)
{
- if (cpu >= writeQueue.size())
- writeQueue.resize(cpu + 1);
+ int size = virtualRegs.size();
+ if (index < size)
+ return;
+
+ virtualRegs.resize(index + 1);
+ for (int i = size; i <= index; ++i)
+ virtualRegs[i].rxPacket = rxFifo.end();
}
void
-Device::prepareRead(int cpu)
+Device::prepareRead(int cpu, int index)
{
using namespace Regs;
+ prepareIO(cpu, index);
+
+ VirtualReg &vnic = virtualRegs[index];
// update rx registers
- regs.RxDone = set_RxDone_Packets(regs.RxDone, rxFifo.packets());
- regs.RxWait = regs.RxDone;
+ uint64_t rxdone = vnic.RxDone;
+ rxdone = set_RxDone_Packets(rxdone, rxFifo.packets());
+ regs.RxData = vnic.RxData;
+ regs.RxDone = rxdone;
+ regs.RxWait = rxdone;
// update tx regsiters
- regs.TxDone = set_TxDone_Packets(regs.TxDone, txFifo.packets());
- regs.TxDone = set_TxDone_Full(regs.TxDone,
- txFifo.avail() < regs.TxMaxCopy);
- regs.TxDone = set_TxDone_Low(regs.TxDone,
- txFifo.size() < regs.TxFifoMark);
- regs.TxWait = regs.TxDone;
+ uint64_t txdone = vnic.TxDone;
+ txdone = set_TxDone_Packets(txdone, txFifo.packets());
+ txdone = set_TxDone_Full(txdone, txFifo.avail() < regs.TxMaxCopy);
+ txdone = set_TxDone_Low(txdone, txFifo.size() < regs.TxFifoMark);
+ regs.TxData = vnic.TxData;
+ regs.TxDone = txdone;
+ regs.TxWait = txdone;
}
void
-Device::prepareWrite(int cpu)
+Device::prepareWrite(int cpu, int index)
{
- prepareIO(cpu);
+ if (cpu >= writeQueue.size())
+ writeQueue.resize(cpu + 1);
+
+ prepareIO(cpu, index);
}
/**
Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data)
{
int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
+ Addr index = daddr >> Regs::VirtualShift;
+ Addr raddr = daddr & Regs::VirtualMask;
- if (!regValid(daddr))
+ if (!regValid(raddr))
panic("invalid register: cpu=%d, da=%#x pa=%#x va=%#x size=%d",
cpu, daddr, req->paddr, req->vaddr, req->size);
- const Regs::Info &info = regInfo(daddr);
+ const Regs::Info &info = regInfo(raddr);
if (!info.read)
panic("reading %s (write only): cpu=%d da=%#x pa=%#x va=%#x size=%d",
info.name, cpu, daddr, req->paddr, req->vaddr, req->size);
panic("invalid size for reg %s: cpu=%d da=%#x pa=%#x va=%#x size=%d",
info.name, cpu, daddr, req->paddr, req->vaddr, req->size);
- prepareRead(cpu);
+ prepareRead(cpu, index);
uint64_t value = 0;
if (req->size == 4) {
uint32_t ® = *(uint32_t *)data;
- reg = regData32(daddr);
+ reg = regData32(raddr);
value = reg;
}
if (req->size == 8) {
uint64_t ® = *(uint64_t *)data;
- reg = regData64(daddr);
+ reg = regData64(raddr);
value = reg;
}
// reading the interrupt status register has the side effect of
// clearing it
- if (daddr == Regs::IntrStatus)
+ if (raddr == Regs::IntrStatus)
devIntrClear();
return No_Fault;
DPRINTF(EthernetPIO, "IPR read %s: cpu=%d da=%#x\n",
info.name, cpu, daddr);
- prepareRead(cpu);
+ prepareRead(cpu, 0);
if (info.size == 4)
result = regData32(daddr);
Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data)
{
int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff;
+ Addr index = daddr >> Regs::VirtualShift;
+ Addr raddr = daddr & Regs::VirtualMask;
- if (!regValid(daddr))
+ if (!regValid(raddr))
panic("invalid address: cpu=%d da=%#x pa=%#x va=%#x size=%d",
cpu, daddr, req->paddr, req->vaddr, req->size);
- const Regs::Info &info = regInfo(daddr);
+ const Regs::Info &info = regInfo(raddr);
if (!info.write)
- panic("writing %s (read only): cpu=%d da=%#x", info.name, cpu, daddr);
+ panic("writing %s (read only): cpu=%d da=%#x",
+ info.name, cpu, daddr);
if (req->size != info.size)
panic("invalid size for %s: cpu=%d da=%#x pa=%#x va=%#x size=%d",
info.name, cpu, info.size == 4 ? reg32 : reg64, daddr,
req->paddr, req->vaddr, req->size);
+ prepareWrite(cpu, index);
if (pioDelayWrite)
writeQueue[cpu].push_back(RegWriteData(daddr, reg64));
void
Device::regWrite(Addr daddr, int cpu, const uint8_t *data)
{
+ Addr index = daddr >> Regs::VirtualShift;
+ Addr raddr = daddr & Regs::VirtualMask;
+
uint32_t reg32 = *(uint32_t *)data;
uint64_t reg64 = *(uint64_t *)data;
+ VirtualReg &vnic = virtualRegs[index];
- switch (daddr) {
+ switch (raddr) {
case Regs::Config:
changeConfig(reg32);
break;
break;
case Regs::RxData:
- if (rxState != rxIdle)
+ if (Regs::get_RxDone_Busy(vnic.RxDone))
panic("receive machine busy with another request! rxState=%s",
RxStateStrings[rxState]);
- regs.RxDone = Regs::RxDone_Busy;
- regs.RxData = reg64;
- if (rxEnable) {
+ vnic.RxDone = Regs::RxDone_Busy;
+ vnic.RxData = reg64;
+ rxList.push_back(index);
+ if (rxEnable && rxState == rxIdle) {
rxState = rxFifoBlock;
rxKick();
}
break;
case Regs::TxData:
- if (txState != txIdle)
+ if (Regs::get_TxDone_Busy(vnic.TxDone))
panic("transmit machine busy with another request! txState=%s",
TxStateStrings[txState]);
- regs.TxDone = Regs::TxDone_Busy;
- regs.TxData = reg64;
- if (txEnable) {
+ vnic.TxDone = Regs::TxDone_Busy;
+ vnic.TxData = reg64;
+ if (txList.empty() || txList.front() != index)
+ txList.push_back(index);
+ if (txEnable && txState == txIdle) {
txState = txFifoBlock;
txKick();
}
void
Device::command(uint32_t command)
{
+ if (command & Regs::Command_Intr)
+ devIntrPost(Regs::Intr_Soft);
+
if (command & Regs::Command_Reset)
reset();
}
memset(®s, 0, sizeof(regs));
regs.Config = 0;
- if (params()->dedicated)
- regs.Config |= Config_Thread;
- regs.IntrMask = Intr_RxHigh | Intr_RxDMA | Intr_TxLow;
+ if (params()->rx_thread)
+ regs.Config |= Config_RxThread;
+ if (params()->tx_thread)
+ regs.Config |= Config_TxThread;
+ regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow;
regs.RxMaxCopy = params()->rx_max_copy;
regs.TxMaxCopy = params()->tx_max_copy;
regs.RxMaxIntr = params()->rx_max_intr;
regs.TxFifoMark = params()->tx_fifo_threshold;
regs.HwAddr = params()->eaddr;
+ rxList.clear();
+ txList.clear();
+
rxState = rxIdle;
txState = txIdle;
rxFifo.clear();
+ rxFifoPtr = rxFifo.end();
txFifo.clear();
rxEmpty = false;
txFull = false;
+
+ int size = virtualRegs.size();
+ virtualRegs.clear();
+ virtualRegs.resize(size);
+ for (int i = 0; i < size; ++i)
+ virtualRegs[i].rxPacket = rxFifo.end();
}
void
void
Device::rxKick()
{
+ VirtualReg *vnic;
+
DPRINTF(EthernetSM, "receive kick rxState=%s (rxFifo.size=%d)\n",
RxStateStrings[rxState], rxFifo.size());
}
next:
- switch (rxState) {
- case rxIdle:
+ if (rxState == rxIdle)
goto exit;
+ assert(!rxList.empty());
+ vnic = &virtualRegs[rxList.front()];
+
+ DPRINTF(EthernetSM, "processing rxState=%s for virtual nic %d\n",
+ RxStateStrings[rxState], rxList.front());
+
+ switch (rxState) {
case rxFifoBlock:
- if (rxPacket) {
+ if (vnic->rxPacket != rxFifo.end()) {
rxState = rxBeginCopy;
break;
}
- if (rxFifo.empty()) {
+ if (rxFifoPtr == rxFifo.end()) {
DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n");
goto exit;
}
+ assert(!rxFifo.empty());
+
// Grab a new packet from the fifo.
- rxPacket = rxFifo.front();
- rxPacketBufPtr = rxPacket->data;
- rxPktBytes = rxPacket->length;
- assert(rxPktBytes);
+ vnic->rxPacket = rxFifoPtr++;
+ vnic->rxPacketOffset = 0;
+ vnic->rxPacketBytes = (*vnic->rxPacket)->length;
+ assert(vnic->rxPacketBytes);
- rxDoneData = 0;
+ vnic->rxDoneData = 0;
/* scope for variables */ {
- IpPtr ip(rxPacket);
+ IpPtr ip(*vnic->rxPacket);
if (ip) {
- rxDoneData |= Regs::RxDone_IpPacket;
+ vnic->rxDoneData |= Regs::RxDone_IpPacket;
rxIpChecksums++;
if (cksum(ip) != 0) {
DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
- rxDoneData |= Regs::RxDone_IpError;
+ vnic->rxDoneData |= Regs::RxDone_IpError;
}
TcpPtr tcp(ip);
UdpPtr udp(ip);
if (tcp) {
- rxDoneData |= Regs::RxDone_TcpPacket;
+ vnic->rxDoneData |= Regs::RxDone_TcpPacket;
rxTcpChecksums++;
if (cksum(tcp) != 0) {
DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
- rxDoneData |= Regs::RxDone_TcpError;
+ vnic->rxDoneData |= Regs::RxDone_TcpError;
}
} else if (udp) {
- rxDoneData |= Regs::RxDone_UdpPacket;
+ vnic->rxDoneData |= Regs::RxDone_UdpPacket;
rxUdpChecksums++;
if (cksum(udp) != 0) {
DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
- rxDoneData |= Regs::RxDone_UdpError;
+ vnic->rxDoneData |= Regs::RxDone_UdpError;
}
}
}
if (dmaInterface && dmaInterface->busy())
goto exit;
- rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(regs.RxData));
- rxDmaLen = min<int>(Regs::get_RxData_Len(regs.RxData), rxPktBytes);
- rxDmaData = rxPacketBufPtr;
+ rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(vnic->RxData));
+ rxDmaLen = min<int>(Regs::get_RxData_Len(vnic->RxData),
+ vnic->rxPacketBytes);
+ rxDmaData = (*vnic->rxPacket)->data + vnic->rxPacketOffset;
rxState = rxCopy;
if (dmaInterface) {
goto exit;
case rxCopyDone:
- regs.RxDone = rxDoneData | rxDmaLen;
+ vnic->RxDone = vnic->rxDoneData | rxDmaLen;
+ vnic->RxDone |= Regs::RxDone_Complete;
- if (rxPktBytes == rxDmaLen) {
- rxPacket = NULL;
- rxFifo.pop();
+ if (vnic->rxPacketBytes == rxDmaLen) {
+ rxFifo.remove(vnic->rxPacket);
+ vnic->rxPacket = rxFifo.end();
} else {
- regs.RxDone |= Regs::RxDone_More;
- rxPktBytes -= rxDmaLen;
- rxPacketBufPtr += rxDmaLen;
+ vnic->RxDone |= Regs::RxDone_More;
+ vnic->rxPacketBytes -= rxDmaLen;
+ vnic->rxPacketOffset += rxDmaLen;
+ }
+
+ rxList.pop_front();
+ rxState = rxList.empty() ? rxIdle : rxFifoBlock;
+
+ if (rxFifo.empty()) {
+ devIntrPost(Regs::Intr_RxEmpty);
+ rxEmpty = true;
}
- regs.RxDone |= Regs::RxDone_Complete;
devIntrPost(Regs::Intr_RxDMA);
- rxState = rxIdle;
break;
default:
void
Device::txKick()
{
+ VirtualReg *vnic;
DPRINTF(EthernetSM, "transmit kick txState=%s (txFifo.size=%d)\n",
TxStateStrings[txState], txFifo.size());
}
next:
- switch (txState) {
- case txIdle:
+ if (txState == txIdle)
goto exit;
+ assert(!txList.empty());
+ vnic = &virtualRegs[txList.front()];
+
+ switch (txState) {
case txFifoBlock:
if (!txPacket) {
// Grab a new packet from the fifo.
txPacket = new PacketData(16384);
- txPacketBufPtr = txPacket->data;
+ txPacketOffset = 0;
}
if (txFifo.avail() - txPacket->length <
- Regs::get_TxData_Len(regs.TxData)) {
+ Regs::get_TxData_Len(vnic->TxData)) {
DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n");
goto exit;
}
if (dmaInterface && dmaInterface->busy())
goto exit;
- txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(regs.TxData));
- txDmaLen = Regs::get_TxData_Len(regs.TxData);
- txDmaData = txPacketBufPtr;
+ txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(vnic->TxData));
+ txDmaLen = Regs::get_TxData_Len(vnic->TxData);
+ txDmaData = txPacket->data + txPacketOffset;
txState = txCopy;
if (dmaInterface) {
goto exit;
case txCopyDone:
+ vnic->TxDone = txDmaLen | Regs::TxDone_Complete;
txPacket->length += txDmaLen;
- if ((regs.TxData & Regs::TxData_More)) {
- txPacketBufPtr += txDmaLen;
- } else {
- assert(txPacket->length <= txFifo.avail());
- if ((regs.TxData & Regs::TxData_Checksum)) {
- IpPtr ip(txPacket);
- if (ip) {
- TcpPtr tcp(ip);
- if (tcp) {
- tcp->sum(0);
- tcp->sum(cksum(tcp));
- txTcpChecksums++;
- }
+ if ((vnic->TxData & Regs::TxData_More)) {
+ txPacketOffset += txDmaLen;
+ txState = txIdle;
+ devIntrPost(Regs::Intr_TxDMA);
+ break;
+ }
- UdpPtr udp(ip);
- if (udp) {
- udp->sum(0);
- udp->sum(cksum(udp));
- txUdpChecksums++;
- }
+ assert(txPacket->length <= txFifo.avail());
+ if ((vnic->TxData & Regs::TxData_Checksum)) {
+ IpPtr ip(txPacket);
+ if (ip) {
+ TcpPtr tcp(ip);
+ if (tcp) {
+ tcp->sum(0);
+ tcp->sum(cksum(tcp));
+ txTcpChecksums++;
+ }
- ip->sum(0);
- ip->sum(cksum(ip));
- txIpChecksums++;
+ UdpPtr udp(ip);
+ if (udp) {
+ udp->sum(0);
+ udp->sum(cksum(udp));
+ txUdpChecksums++;
}
+
+ ip->sum(0);
+ ip->sum(cksum(ip));
+ txIpChecksums++;
}
- txFifo.push(txPacket);
- if (txFifo.avail() < regs.TxMaxCopy) {
- devIntrPost(Regs::Intr_TxFull);
- txFull = true;
- }
- txPacket = 0;
- transmit();
}
- regs.TxDone = txDmaLen | Regs::TxDone_Complete;
+ txFifo.push(txPacket);
+ if (txFifo.avail() < regs.TxMaxCopy) {
+ devIntrPost(Regs::Intr_TxFull);
+ txFull = true;
+ }
+ txPacket = 0;
+ transmit();
+ txList.pop_front();
+ txState = txList.empty() ? txIdle : txFifoBlock;
devIntrPost(Regs::Intr_TxDMA);
- txState = txIdle;
break;
default:
return false;
}
+ // If we were at the last element, back up one ot go to the new
+ // last element of the list.
+ if (rxFifoPtr == rxFifo.end())
+ --rxFifoPtr;
+
devIntrPost(Regs::Intr_RxPacket);
rxKick();
return true;
SERIALIZE_SCALAR(regs.TxData);
SERIALIZE_SCALAR(regs.TxDone);
+ /*
+ * Serialize the virtual nic state
+ */
+ int virtualRegsSize = virtualRegs.size();
+ SERIALIZE_SCALAR(virtualRegsSize);
+ for (int i = 0; i < virtualRegsSize; ++i) {
+ VirtualReg *vnic = &virtualRegs[i];
+
+ string reg = csprintf("vnic%d", i);
+ paramOut(os, reg + ".RxData", vnic->RxData);
+ paramOut(os, reg + ".RxDone", vnic->RxDone);
+ paramOut(os, reg + ".TxData", vnic->TxData);
+ paramOut(os, reg + ".TxDone", vnic->TxDone);
+
+ PacketFifo::iterator rxFifoPtr;
+
+ bool rxPacketExists = vnic->rxPacket != rxFifo.end();
+ paramOut(os, reg + ".rxPacketExists", rxPacketExists);
+ if (rxPacketExists) {
+ int rxPacket = 0;
+ PacketFifo::iterator i = rxFifo.begin();
+ while (i != vnic->rxPacket) {
+ assert(i != rxFifo.end());
+ ++i;
+ ++rxPacket;
+ }
+
+ paramOut(os, reg + ".rxPacket", rxPacket);
+ paramOut(os, reg + ".rxPacketOffset", vnic->rxPacketOffset);
+ paramOut(os, reg + ".rxPacketBytes", vnic->rxPacketBytes);
+ }
+ paramOut(os, reg + ".rxDoneData", vnic->rxDoneData);
+ }
+
+ VirtualList::iterator i, end;
+ int count;
+
+ int rxListSize = rxList.size();
+ SERIALIZE_SCALAR(rxListSize);
+ for (count = 0, i = rxList.begin(), end = rxList.end(); i != end; ++i)
+ paramOut(os, csprintf("rxList%d", count++), *i);
+
+ int txListSize = txList.size();
+ SERIALIZE_SCALAR(txListSize);
+ for (count = 0, i = txList.begin(), end = txList.end(); i != end; ++i)
+ paramOut(os, csprintf("txList%d", count++), *i);
+
/*
* Serialize rx state machine
*/
SERIALIZE_SCALAR(rxState);
SERIALIZE_SCALAR(rxEmpty);
rxFifo.serialize("rxFifo", os);
- bool rxPacketExists = rxPacket;
- SERIALIZE_SCALAR(rxPacketExists);
- if (rxPacketExists) {
- rxPacket->serialize("rxPacket", os);
- uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
- SERIALIZE_SCALAR(rxPktBufPtr);
- SERIALIZE_SCALAR(rxPktBytes);
- }
- SERIALIZE_SCALAR(rxDoneData);
/*
* Serialize tx state machine
SERIALIZE_SCALAR(txPacketExists);
if (txPacketExists) {
txPacket->serialize("txPacket", os);
- uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
- SERIALIZE_SCALAR(txPktBufPtr);
- SERIALIZE_SCALAR(txPktBytes);
+ SERIALIZE_SCALAR(txPacketOffset);
+ SERIALIZE_SCALAR(txPacketBytes);
}
/*
UNSERIALIZE_SCALAR(regs.TxData);
UNSERIALIZE_SCALAR(regs.TxDone);
+ int rxListSize;
+ UNSERIALIZE_SCALAR(rxListSize);
+ rxList.clear();
+ for (int i = 0; i < rxListSize; ++i) {
+ int value;
+ paramIn(cp, section, csprintf("rxList%d", i), value);
+ rxList.push_back(value);
+ }
+
+ int txListSize;
+ UNSERIALIZE_SCALAR(txListSize);
+ txList.clear();
+ for (int i = 0; i < txListSize; ++i) {
+ int value;
+ paramIn(cp, section, csprintf("txList%d", i), value);
+ txList.push_back(value);
+ }
+
/*
* Unserialize rx state machine
*/
UNSERIALIZE_SCALAR(rxEmpty);
this->rxState = (RxState) rxState;
rxFifo.unserialize("rxFifo", cp, section);
- bool rxPacketExists;
- UNSERIALIZE_SCALAR(rxPacketExists);
- rxPacket = 0;
- if (rxPacketExists) {
- rxPacket = new PacketData(16384);
- rxPacket->unserialize("rxPacket", cp, section);
- uint32_t rxPktBufPtr;
- UNSERIALIZE_SCALAR(rxPktBufPtr);
- this->rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
- UNSERIALIZE_SCALAR(rxPktBytes);
- }
- UNSERIALIZE_SCALAR(rxDoneData);
/*
* Unserialize tx state machine
if (txPacketExists) {
txPacket = new PacketData(16384);
txPacket->unserialize("txPacket", cp, section);
- uint32_t txPktBufPtr;
- UNSERIALIZE_SCALAR(txPktBufPtr);
- this->txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
- UNSERIALIZE_SCALAR(txPktBytes);
+ UNSERIALIZE_SCALAR(txPacketOffset);
+ UNSERIALIZE_SCALAR(txPacketBytes);
+ }
+
+ /*
+ * unserialize the virtual nic registers/state
+ *
+ * this must be done after the unserialization of the rxFifo
+ * because the packet iterators depend on the fifo being populated
+ */
+ int virtualRegsSize;
+ UNSERIALIZE_SCALAR(virtualRegsSize);
+ virtualRegs.clear();
+ virtualRegs.resize(virtualRegsSize);
+ for (int i = 0; i < virtualRegsSize; ++i) {
+ VirtualReg *vnic = &virtualRegs[i];
+ string reg = csprintf("vnic%d", i);
+
+ paramIn(cp, section, reg + ".RxData", vnic->RxData);
+ paramIn(cp, section, reg + ".RxDone", vnic->RxDone);
+ paramIn(cp, section, reg + ".TxData", vnic->TxData);
+ paramIn(cp, section, reg + ".TxDone", vnic->TxDone);
+
+ bool rxPacketExists;
+ paramIn(cp, section, reg + ".rxPacketExists", rxPacketExists);
+ if (rxPacketExists) {
+ int rxPacket;
+ paramIn(cp, section, reg + ".rxPacket", rxPacket);
+ vnic->rxPacket = rxFifo.begin();
+ while (rxPacket--)
+ ++vnic->rxPacket;
+
+ paramIn(cp, section, reg + ".rxPacketOffset",
+ vnic->rxPacketOffset);
+ paramIn(cp, section, reg + ".rxPacketBytes", vnic->rxPacketBytes);
+ } else {
+ vnic->rxPacket = rxFifo.end();
+ }
+ paramIn(cp, section, reg + ".rxDoneData", vnic->rxDoneData);
}
/*
Param<bool> rx_filter;
Param<string> hardware_address;
- Param<bool> dedicated;
+ Param<bool> rx_thread;
+ Param<bool> tx_thread;
END_DECLARE_SIM_OBJECT_PARAMS(Device)
INIT_PARAM(rx_filter, "Enable Receive Filter"),
INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
- INIT_PARAM(dedicated, "dedicate a kernel thread to the driver")
+ INIT_PARAM(rx_thread, ""),
+ INIT_PARAM(tx_thread, "")
END_INIT_SIM_OBJECT_PARAMS(Device)
params->rx_filter = rx_filter;
params->eaddr = hardware_address;
- params->dedicated = dedicated;
+ params->rx_thread = rx_thread;
+ params->tx_thread = tx_thread;
return new Device(params);
}
namespace Sinic {
namespace Regs {
+static const int VirtualMask = 0xff;
+static const int VirtualShift = 8;
+
// Registers
__SINIC_REG32(Config, 0x00); // 32: configuration register
__SINIC_REG32(Command, 0x04); // 32: command register
__SINIC_REG32(Size, 0x68); // register addres space size
// Config register bits
-__SINIC_VAL32(Config_Thread, 8, 1); // enable receive filter
-__SINIC_VAL32(Config_Filter, 7, 1); // enable receive filter
-__SINIC_VAL32(Config_Vlan, 6, 1); // enable vlan tagging
-__SINIC_VAL32(Config_Virtual, 5, 1); // enable virtual addressing
-__SINIC_VAL32(Config_Desc, 4, 1); // enable tx/rx descriptors
-__SINIC_VAL32(Config_Poll, 3, 1); // enable polling
-__SINIC_VAL32(Config_IntEn, 2, 1); // enable interrupts
-__SINIC_VAL32(Config_TxEn, 1, 1); // enable transmit
-__SINIC_VAL32(Config_RxEn, 0, 1); // enable receive
+__SINIC_VAL32(Config_RxThread, 9, 1); // enable receive threads
+__SINIC_VAL32(Config_TxThread, 8, 1); // enable transmit thread
+__SINIC_VAL32(Config_Filter, 7, 1); // enable receive filter
+__SINIC_VAL32(Config_Vlan, 6, 1); // enable vlan tagging
+__SINIC_VAL32(Config_Virtual, 5, 1); // enable virtual addressing
+__SINIC_VAL32(Config_Desc, 4, 1); // enable tx/rx descriptors
+__SINIC_VAL32(Config_Poll, 3, 1); // enable polling
+__SINIC_VAL32(Config_IntEn, 2, 1); // enable interrupts
+__SINIC_VAL32(Config_TxEn, 1, 1); // enable transmit
+__SINIC_VAL32(Config_RxEn, 0, 1); // enable receive
// Command register bits
+__SINIC_VAL32(Command_Intr, 1, 1); // software interrupt
__SINIC_VAL32(Command_Reset, 0, 1); // reset chip
// Interrupt register bits
+__SINIC_VAL32(Intr_Soft, 8, 1); // software interrupt
__SINIC_VAL32(Intr_TxLow, 7, 1); // tx fifo dropped below watermark
__SINIC_VAL32(Intr_TxFull, 6, 1); // tx fifo full
__SINIC_VAL32(Intr_TxDMA, 5, 1); // tx dma completed w/ interrupt
__SINIC_VAL32(Intr_RxEmpty, 2, 1); // rx fifo empty
__SINIC_VAL32(Intr_RxDMA, 1, 1); // rx dma completed w/ interrupt
__SINIC_VAL32(Intr_RxPacket, 0, 1); // packet received
-__SINIC_REG32(Intr_All, 0xff); // all valid interrupts
-__SINIC_REG32(Intr_NoDelay, 0xcc); // interrupts that shouldn't be coalesced
-__SINIC_REG32(Intr_Res, ~0xff); // reserved interrupt bits
+__SINIC_REG32(Intr_All, 0x01ff); // all valid interrupts
+__SINIC_REG32(Intr_NoDelay, 0x01cc); // interrupts that aren't coalesced
+__SINIC_REG32(Intr_Res, ~0x01ff); // reserved interrupt bits
// RX Data Description
__SINIC_VAL64(RxData_Len, 40, 20); // 0 - 1M
__SINIC_VAL64(RxDone_Busy, 31, 1); // receive dma busy copying
__SINIC_VAL64(RxDone_Complete, 30, 1); // valid data (packet complete)
__SINIC_VAL64(RxDone_More, 29, 1); // Packet has more data (dma again)
+__SINIC_VAL64(RxDone_Res0, 28, 1); // reserved
+__SINIC_VAL64(RxDone_Res1, 27, 1); // reserved
+__SINIC_VAL64(RxDone_Res2, 26, 1); // reserved
__SINIC_VAL64(RxDone_TcpError, 25, 1); // TCP packet error (bad checksum)
__SINIC_VAL64(RxDone_UdpError, 24, 1); // UDP packet error (bad checksum)
__SINIC_VAL64(RxDone_IpError, 23, 1); // IP packet error (bad checksum)
__SINIC_VAL64(TxDone_Complete, 30, 1); // valid data (packet complete)
__SINIC_VAL64(TxDone_Full, 29, 1); // tx fifo is full
__SINIC_VAL64(TxDone_Low, 28, 1); // tx fifo is below the watermark
+__SINIC_VAL64(TxDone_Res0, 27, 1); // reserved
+__SINIC_VAL64(TxDone_Res1, 26, 1); // reserved
+__SINIC_VAL64(TxDone_Res2, 25, 1); // reserved
+__SINIC_VAL64(TxDone_Res3, 24, 1); // reserved
+__SINIC_VAL64(TxDone_Res4, 23, 1); // reserved
+__SINIC_VAL64(TxDone_Res5, 22, 1); // reserved
+__SINIC_VAL64(TxDone_Res6, 21, 1); // reserved
+__SINIC_VAL64(TxDone_Res7, 20, 1); // reserved
__SINIC_VAL64(TxDone_CopyLen, 0, 20); // up to 256k
struct Info