Merge zizzer:/bk/m5
into zeep.eecs.umich.edu:/z/saidi/work/m5 --HG-- extra : convert_revision : 3cc23080d19cc464a8ba7c1c93b6e5d45af7d463
This commit is contained in:
@@ -127,7 +127,7 @@ NSGigE::NSGigE(Params *p)
|
||||
p->header_bus, 1,
|
||||
p->dma_no_allocate);
|
||||
} else if (p->payload_bus) {
|
||||
pioInterface = newPioInterface(name() + ".pio2", p->hier,
|
||||
pioInterface = newPioInterface(name() + ".pio", p->hier,
|
||||
p->payload_bus, this,
|
||||
&NSGigE::cacheAccess);
|
||||
|
||||
@@ -2531,20 +2531,17 @@ NSGigE::recvPacket(PacketPtr packet)
|
||||
|
||||
if (!rxEnable) {
|
||||
DPRINTF(Ethernet, "receive disabled...packet dropped\n");
|
||||
interface->recvDone();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!rxFilterEnable) {
|
||||
DPRINTF(Ethernet,
|
||||
"receive packet filtering disabled . . . packet dropped\n");
|
||||
interface->recvDone();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rxFilter(packet)) {
|
||||
DPRINTF(Ethernet, "packet filtered...dropped\n");
|
||||
interface->recvDone();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2567,7 +2564,6 @@ NSGigE::recvPacket(PacketPtr packet)
|
||||
}
|
||||
|
||||
rxFifo.push(packet);
|
||||
interface->recvDone();
|
||||
|
||||
rxKick();
|
||||
return true;
|
||||
|
||||
362
dev/sinic.cc
362
dev/sinic.cc
@@ -94,8 +94,8 @@ Device::Device(Params *p)
|
||||
reset();
|
||||
|
||||
if (p->io_bus) {
|
||||
pioInterface = newPioInterface(p->name, p->hier, p->io_bus, this,
|
||||
&Device::cacheAccess);
|
||||
pioInterface = newPioInterface(p->name + ".pio", p->hier, p->io_bus,
|
||||
this, &Device::cacheAccess);
|
||||
|
||||
pioLatency = p->pio_latency * p->io_bus->clockRate;
|
||||
|
||||
@@ -108,7 +108,8 @@ Device::Device(Params *p)
|
||||
p->io_bus, 1,
|
||||
p->dma_no_allocate);
|
||||
} else if (p->payload_bus) {
|
||||
pioInterface = newPioInterface(p->name, p->hier, p->payload_bus, this,
|
||||
pioInterface = newPioInterface(p->name + ".pio", p->hier,
|
||||
p->payload_bus, this,
|
||||
&Device::cacheAccess);
|
||||
|
||||
pioLatency = p->pio_latency * p->payload_bus->clockRate;
|
||||
@@ -315,9 +316,26 @@ Device::writeConfig(int offset, int size, const uint8_t *data)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Device::prepareRead()
|
||||
{
|
||||
using namespace Regs;
|
||||
|
||||
// update rx registers
|
||||
regs.RxDone = set_RxDone_Packets(regs.RxDone, rxFifo.packets());
|
||||
regs.RxWait = regs.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;
|
||||
}
|
||||
|
||||
/**
|
||||
* This reads the device registers, which are detailed in the NS83820
|
||||
* spec sheet
|
||||
* I/O read of device register
|
||||
*/
|
||||
Fault
|
||||
Device::read(MemReqPtr &req, uint8_t *data)
|
||||
@@ -327,118 +345,115 @@ Device::read(MemReqPtr &req, uint8_t *data)
|
||||
//The mask is to give you only the offset into the device register file
|
||||
Addr daddr = req->paddr & 0xfff;
|
||||
|
||||
if (Regs::regSize(daddr) == 0)
|
||||
panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
|
||||
if (!regValid(daddr))
|
||||
panic("invalid register: da=%#x pa=%#x va=%#x size=%d",
|
||||
daddr, req->paddr, req->vaddr, req->size);
|
||||
|
||||
if (req->size != Regs::regSize(daddr))
|
||||
const Regs::Info &info = regInfo(daddr);
|
||||
if (!info.read)
|
||||
panic("reading write only register: %s: da=%#x pa=%#x va=%#x size=%d",
|
||||
info.name, daddr, req->paddr, req->vaddr, req->size);
|
||||
|
||||
if (req->size != info.size)
|
||||
panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d",
|
||||
Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
|
||||
info.name, daddr, req->paddr, req->vaddr, req->size);
|
||||
|
||||
DPRINTF(EthernetPIO, "read reg=%s da=%#x pa=%#x va=%#x size=%d\n",
|
||||
Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
|
||||
prepareRead();
|
||||
|
||||
uint32_t ®32 = *(uint32_t *)data;
|
||||
uint64_t ®64 = *(uint64_t *)data;
|
||||
|
||||
switch (daddr) {
|
||||
case Regs::Config:
|
||||
reg32 = regs.Config;
|
||||
break;
|
||||
|
||||
case Regs::RxMaxCopy:
|
||||
reg32 = regs.RxMaxCopy;
|
||||
break;
|
||||
|
||||
case Regs::TxMaxCopy:
|
||||
reg32 = regs.TxMaxCopy;
|
||||
break;
|
||||
|
||||
case Regs::RxThreshold:
|
||||
reg32 = regs.RxThreshold;
|
||||
break;
|
||||
|
||||
case Regs::TxThreshold:
|
||||
reg32 = regs.TxThreshold;
|
||||
break;
|
||||
|
||||
case Regs::IntrStatus:
|
||||
reg32 = regs.IntrStatus;
|
||||
devIntrClear();
|
||||
break;
|
||||
|
||||
case Regs::IntrMask:
|
||||
reg32 = regs.IntrMask;
|
||||
break;
|
||||
|
||||
case Regs::RxData:
|
||||
reg64 = regs.RxData;
|
||||
break;
|
||||
|
||||
case Regs::RxDone:
|
||||
case Regs::RxWait:
|
||||
reg64 = Regs::set_RxDone_FifoLen(regs.RxDone,
|
||||
min(rxFifo.packets(), 255));
|
||||
break;
|
||||
|
||||
case Regs::TxData:
|
||||
reg64 = regs.TxData;
|
||||
break;
|
||||
|
||||
case Regs::TxDone:
|
||||
case Regs::TxWait:
|
||||
reg64 = Regs::set_TxDone_FifoLen(regs.TxDone,
|
||||
min(txFifo.packets(), 255));
|
||||
break;
|
||||
|
||||
case Regs::HwAddr:
|
||||
reg64 = params()->eaddr;
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("reading write only register %s: da=%#x pa=%#x va=%#x size=%d",
|
||||
Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
|
||||
uint64_t value = 0;
|
||||
if (req->size == 4) {
|
||||
uint32_t ® = *(uint32_t *)data;
|
||||
reg = regData32(daddr);
|
||||
value = reg;
|
||||
}
|
||||
|
||||
DPRINTF(EthernetPIO, "read reg=%s done val=%#x\n", Regs::regName(daddr),
|
||||
Regs::regSize(daddr) == 4 ? reg32 : reg64);
|
||||
if (req->size == 8) {
|
||||
uint64_t ® = *(uint64_t *)data;
|
||||
reg = regData64(daddr);
|
||||
value = reg;
|
||||
}
|
||||
|
||||
DPRINTF(EthernetPIO, "read reg=%s da=%#x pa=%#x va=%#x size=%d val=%#x\n",
|
||||
info.name, daddr, req->paddr, req->vaddr, req->size, value);
|
||||
|
||||
// reading the interrupt status register has the side effect of
|
||||
// clearing it
|
||||
if (daddr == Regs::IntrStatus)
|
||||
devIntrClear();
|
||||
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
/**
|
||||
* IPR read of device register
|
||||
*/
|
||||
Fault
|
||||
Device::iprRead(Addr daddr, uint64_t &result)
|
||||
{
|
||||
if (!regValid(daddr))
|
||||
panic("invalid address: da=%#x", daddr);
|
||||
|
||||
const Regs::Info &info = regInfo(daddr);
|
||||
if (!info.read)
|
||||
panic("reading write only register %s: da=%#x", info.name, daddr);
|
||||
|
||||
DPRINTF(EthernetPIO, "read reg=%s da=%#x\n", info.name, daddr);
|
||||
|
||||
prepareRead();
|
||||
|
||||
if (info.size == 4)
|
||||
result = regData32(daddr);
|
||||
|
||||
if (info.size == 8)
|
||||
result = regData64(daddr);
|
||||
|
||||
DPRINTF(EthernetPIO, "IPR read reg=%s da=%#x val=%#x\n",
|
||||
info.name, result);
|
||||
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
/**
|
||||
* I/O write of device register
|
||||
*/
|
||||
Fault
|
||||
Device::write(MemReqPtr &req, const uint8_t *data)
|
||||
{
|
||||
assert(config.command & PCI_CMD_MSE);
|
||||
|
||||
//The mask is to give you only the offset into the device register file
|
||||
Addr daddr = req->paddr & 0xfff;
|
||||
|
||||
if (Regs::regSize(daddr) == 0)
|
||||
if (!regValid(daddr))
|
||||
panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
|
||||
daddr, req->paddr, req->vaddr, req->size);
|
||||
|
||||
if (req->size != Regs::regSize(daddr))
|
||||
panic("invalid size: reg=%s da=%#x pa=%#x va=%#x size=%d",
|
||||
Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
|
||||
const Regs::Info &info = regInfo(daddr);
|
||||
if (!info.write)
|
||||
panic("writing read only register %s: da=%#x", info.name, daddr);
|
||||
|
||||
if (req->size != info.size)
|
||||
panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d",
|
||||
info.name, daddr, req->paddr, req->vaddr, req->size);
|
||||
|
||||
uint32_t reg32 = *(uint32_t *)data;
|
||||
uint64_t reg64 = *(uint64_t *)data;
|
||||
|
||||
DPRINTF(EthernetPIO, "write reg=%s val=%#x da=%#x pa=%#x va=%#x size=%d\n",
|
||||
Regs::regName(daddr), Regs::regSize(daddr) == 4 ? reg32 : reg64,
|
||||
daddr, req->paddr, req->vaddr, req->size);
|
||||
|
||||
info.name, info.size == 4 ? reg32 : reg64, daddr, req->paddr,
|
||||
req->vaddr, req->size);
|
||||
|
||||
switch (daddr) {
|
||||
case Regs::Config:
|
||||
changeConfig(reg32);
|
||||
break;
|
||||
|
||||
case Regs::RxThreshold:
|
||||
regs.RxThreshold = reg32;
|
||||
case Regs::Command:
|
||||
command(reg32);
|
||||
break;
|
||||
|
||||
case Regs::TxThreshold:
|
||||
regs.TxThreshold = reg32;
|
||||
case Regs::IntrStatus:
|
||||
devIntrClear(regs.IntrStatus & reg32);
|
||||
break;
|
||||
|
||||
case Regs::IntrMask:
|
||||
@@ -447,9 +462,10 @@ Device::write(MemReqPtr &req, const uint8_t *data)
|
||||
|
||||
case Regs::RxData:
|
||||
if (rxState != rxIdle)
|
||||
panic("receive machine busy with another request!");
|
||||
panic("receive machine busy with another request! rxState=%s",
|
||||
RxStateStrings[rxState]);
|
||||
|
||||
regs.RxDone = 0;
|
||||
regs.RxDone = Regs::RxDone_Busy;
|
||||
regs.RxData = reg64;
|
||||
if (rxEnable) {
|
||||
rxState = rxFifoBlock;
|
||||
@@ -459,19 +475,16 @@ Device::write(MemReqPtr &req, const uint8_t *data)
|
||||
|
||||
case Regs::TxData:
|
||||
if (txState != txIdle)
|
||||
panic("transmit machine busy with another request!");
|
||||
panic("transmit machine busy with another request! txState=%s",
|
||||
TxStateStrings[txState]);
|
||||
|
||||
regs.TxDone = 0;
|
||||
regs.TxDone = Regs::TxDone_Busy;
|
||||
regs.TxData = reg64;
|
||||
if (txEnable) {
|
||||
txState = txFifoBlock;
|
||||
txKick();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("writing read only register %s: da=%#x pa=%#x va=%#x size=%d",
|
||||
Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
|
||||
}
|
||||
|
||||
return No_Fault;
|
||||
@@ -489,9 +502,25 @@ Device::devIntrPost(uint32_t interrupts)
|
||||
"interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
|
||||
interrupts, regs.IntrStatus, regs.IntrMask);
|
||||
|
||||
if ((regs.IntrStatus & regs.IntrMask)) {
|
||||
interrupts = regs.IntrStatus & regs.IntrMask;
|
||||
|
||||
// Intr_RxHigh is special, we only signal it if we've emptied the fifo
|
||||
// and then filled it above the high watermark
|
||||
if (rxEmpty)
|
||||
rxEmpty = false;
|
||||
else
|
||||
interrupts &= ~Regs::Intr_RxHigh;
|
||||
|
||||
// Intr_TxLow is special, we only signal it if we've filled up the fifo
|
||||
// and then dropped below the low watermark
|
||||
if (txFull)
|
||||
txFull = false;
|
||||
else
|
||||
interrupts &= ~Regs::Intr_TxLow;
|
||||
|
||||
if (interrupts) {
|
||||
Tick when = curTick;
|
||||
if ((regs.IntrStatus & regs.IntrMask & Regs::Intr_NoDelay) == 0)
|
||||
if ((interrupts & Regs::Intr_NoDelay) == 0)
|
||||
when += intrDelay;
|
||||
cpuIntrPost(when);
|
||||
}
|
||||
@@ -627,12 +656,6 @@ Device::changeConfig(uint32_t newconf)
|
||||
|
||||
regs.Config = newconf;
|
||||
|
||||
if ((changed & Regs::Config_Reset)) {
|
||||
assert(regs.Config & Regs::Config_Reset);
|
||||
reset();
|
||||
regs.Config &= ~Regs::Config_Reset;
|
||||
}
|
||||
|
||||
if ((changed & Regs::Config_IntEn)) {
|
||||
cpuIntrEnable = regs.Config & Regs::Config_IntEn;
|
||||
if (cpuIntrEnable) {
|
||||
@@ -656,20 +679,40 @@ Device::changeConfig(uint32_t newconf)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Device::command(uint32_t command)
|
||||
{
|
||||
if (command & Regs::Command_Reset)
|
||||
reset();
|
||||
}
|
||||
|
||||
void
|
||||
Device::reset()
|
||||
{
|
||||
using namespace Regs;
|
||||
|
||||
memset(®s, 0, sizeof(regs));
|
||||
|
||||
regs.Config = 0;
|
||||
if (params()->dedicated)
|
||||
regs.Config |= Config_Thread;
|
||||
regs.IntrMask = Intr_RxHigh | Intr_RxDMA | Intr_TxLow;
|
||||
regs.RxMaxCopy = params()->rx_max_copy;
|
||||
regs.TxMaxCopy = params()->tx_max_copy;
|
||||
regs.IntrMask = Intr_TxFifo | Intr_RxFifo | Intr_RxData;
|
||||
regs.RxMaxIntr = params()->rx_max_intr;
|
||||
regs.RxFifoSize = params()->rx_fifo_size;
|
||||
regs.TxFifoSize = params()->tx_fifo_size;
|
||||
regs.RxFifoMark = params()->rx_fifo_threshold;
|
||||
regs.TxFifoMark = params()->tx_fifo_threshold;
|
||||
regs.HwAddr = params()->eaddr;
|
||||
|
||||
rxState = rxIdle;
|
||||
txState = txIdle;
|
||||
|
||||
rxFifo.clear();
|
||||
txFifo.clear();
|
||||
rxEmpty = false;
|
||||
txFull = false;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -680,13 +723,18 @@ Device::rxDmaCopy()
|
||||
physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen);
|
||||
DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
|
||||
rxDmaAddr, rxDmaLen);
|
||||
DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
|
||||
DDUMP(EthernetData, rxDmaData, rxDmaLen);
|
||||
}
|
||||
|
||||
void
|
||||
Device::rxDmaDone()
|
||||
{
|
||||
rxDmaCopy();
|
||||
|
||||
// If the transmit state machine has a pending DMA, let it go first
|
||||
if (txState == txBeginCopy)
|
||||
txKick();
|
||||
|
||||
rxKick();
|
||||
}
|
||||
|
||||
@@ -706,6 +754,8 @@ Device::rxKick()
|
||||
switch (rxState) {
|
||||
case rxIdle:
|
||||
if (rxPioRequest) {
|
||||
DPRINTF(EthernetPIO, "rxIdle: PIO waiting responding at %d\n",
|
||||
curTick + pioLatency);
|
||||
pioInterface->respond(rxPioRequest, curTick);
|
||||
rxPioRequest = 0;
|
||||
}
|
||||
@@ -761,20 +811,20 @@ Device::rxKick()
|
||||
break;
|
||||
|
||||
case rxBeginCopy:
|
||||
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;
|
||||
rxState = rxCopy;
|
||||
|
||||
if (dmaInterface) {
|
||||
if (!dmaInterface->busy()) {
|
||||
dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen,
|
||||
curTick, &rxDmaEvent, true);
|
||||
rxState = rxCopy;
|
||||
}
|
||||
dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen,
|
||||
curTick, &rxDmaEvent, true);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rxState = rxCopy;
|
||||
if (dmaWriteDelay != 0 || dmaWriteFactor != 0) {
|
||||
Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor;
|
||||
Tick start = curTick + dmaWriteDelay + factor;
|
||||
@@ -802,7 +852,7 @@ Device::rxKick()
|
||||
}
|
||||
|
||||
regs.RxDone |= Regs::RxDone_Complete;
|
||||
devIntrPost(Regs::Intr_RxData);
|
||||
devIntrPost(Regs::Intr_RxDMA);
|
||||
rxState = rxIdle;
|
||||
break;
|
||||
|
||||
@@ -831,13 +881,18 @@ Device::txDmaCopy()
|
||||
physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen);
|
||||
DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
|
||||
txDmaAddr, txDmaLen);
|
||||
DDUMP(EthernetDMA, txDmaData, txDmaLen);
|
||||
DDUMP(EthernetData, txDmaData, txDmaLen);
|
||||
}
|
||||
|
||||
void
|
||||
Device::txDmaDone()
|
||||
{
|
||||
txDmaCopy();
|
||||
|
||||
// If the receive state machine has a pending DMA, let it go first
|
||||
if (rxState == rxBeginCopy)
|
||||
rxKick();
|
||||
|
||||
txKick();
|
||||
}
|
||||
|
||||
@@ -849,6 +904,7 @@ Device::transmit()
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t interrupts;
|
||||
PacketPtr packet = txFifo.front();
|
||||
if (!interface->sendPacket(packet)) {
|
||||
DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n",
|
||||
@@ -857,7 +913,6 @@ Device::transmit()
|
||||
}
|
||||
|
||||
txFifo.pop();
|
||||
|
||||
#if TRACING_ON
|
||||
if (DTRACE(Ethernet)) {
|
||||
IpPtr ip(packet);
|
||||
@@ -872,17 +927,17 @@ Device::transmit()
|
||||
}
|
||||
#endif
|
||||
|
||||
DDUMP(Ethernet, packet->data, packet->length);
|
||||
DDUMP(EthernetData, packet->data, packet->length);
|
||||
txBytes += packet->length;
|
||||
txPackets++;
|
||||
|
||||
DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n",
|
||||
txFifo.avail());
|
||||
|
||||
if (txFifo.size() <= params()->tx_fifo_threshold)
|
||||
devIntrPost(Regs::Intr_TxFifo);
|
||||
|
||||
devIntrPost(Regs::Intr_TxDone);
|
||||
interrupts = Regs::Intr_TxPacket;
|
||||
if (txFifo.size() < regs.TxFifoMark)
|
||||
interrupts |= Regs::Intr_TxLow;
|
||||
devIntrPost(interrupts);
|
||||
|
||||
reschedule:
|
||||
if (!txFifo.empty() && !txEvent.scheduled()) {
|
||||
@@ -907,6 +962,8 @@ Device::txKick()
|
||||
switch (txState) {
|
||||
case txIdle:
|
||||
if (txPioRequest) {
|
||||
DPRINTF(EthernetPIO, "txIdle: PIO waiting responding at %d\n",
|
||||
curTick + pioLatency);
|
||||
pioInterface->respond(txPioRequest, curTick + pioLatency);
|
||||
txPioRequest = 0;
|
||||
}
|
||||
@@ -929,21 +986,20 @@ Device::txKick()
|
||||
break;
|
||||
|
||||
case txBeginCopy:
|
||||
if (dmaInterface && dmaInterface->busy())
|
||||
goto exit;
|
||||
|
||||
txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(regs.TxData));
|
||||
txDmaLen = Regs::get_TxData_Len(regs.TxData);
|
||||
txDmaData = txPacketBufPtr;
|
||||
txState = txCopy;
|
||||
|
||||
if (dmaInterface) {
|
||||
if (!dmaInterface->busy()) {
|
||||
dmaInterface->doDMA(Read, txDmaAddr, txDmaLen,
|
||||
curTick, &txDmaEvent, true);
|
||||
txState = txCopy;
|
||||
}
|
||||
|
||||
dmaInterface->doDMA(Read, txDmaAddr, txDmaLen,
|
||||
curTick, &txDmaEvent, true);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
txState = txCopy;
|
||||
if (dmaReadDelay != 0 || dmaReadFactor != 0) {
|
||||
Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
|
||||
Tick start = curTick + dmaReadDelay + factor;
|
||||
@@ -987,12 +1043,16 @@ Device::txKick()
|
||||
}
|
||||
}
|
||||
txFifo.push(txPacket);
|
||||
if (txFifo.avail() < regs.TxMaxCopy) {
|
||||
devIntrPost(Regs::Intr_TxFull);
|
||||
txFull = true;
|
||||
}
|
||||
txPacket = 0;
|
||||
transmit();
|
||||
}
|
||||
|
||||
regs.TxDone = txDmaLen | Regs::TxDone_Complete;
|
||||
devIntrPost(Regs::Intr_TxData);
|
||||
devIntrPost(Regs::Intr_TxDMA);
|
||||
txState = txIdle;
|
||||
break;
|
||||
|
||||
@@ -1085,18 +1145,16 @@ Device::recvPacket(PacketPtr packet)
|
||||
|
||||
if (!rxEnable) {
|
||||
DPRINTF(Ethernet, "receive disabled...packet dropped\n");
|
||||
interface->recvDone();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rxFilter(packet)) {
|
||||
DPRINTF(Ethernet, "packet filtered...dropped\n");
|
||||
interface->recvDone();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rxFifo.size() >= params()->rx_fifo_threshold)
|
||||
devIntrPost(Regs::Intr_RxFifo);
|
||||
if (rxFifo.size() >= regs.RxFifoMark)
|
||||
devIntrPost(Regs::Intr_RxHigh);
|
||||
|
||||
if (!rxFifo.push(packet)) {
|
||||
DPRINTF(Ethernet,
|
||||
@@ -1104,8 +1162,7 @@ Device::recvPacket(PacketPtr packet)
|
||||
return false;
|
||||
}
|
||||
|
||||
interface->recvDone();
|
||||
devIntrPost(Regs::Intr_RxDone);
|
||||
devIntrPost(Regs::Intr_RxPacket);
|
||||
rxKick();
|
||||
return true;
|
||||
}
|
||||
@@ -1163,22 +1220,23 @@ Device::serialize(ostream &os)
|
||||
// Serialize the PciDev base class
|
||||
Base::serialize(os);
|
||||
|
||||
if (rxDmaEvent.scheduled())
|
||||
rxDmaCopy();
|
||||
if (rxState == rxCopy)
|
||||
panic("can't serialize with an in flight dma request rxState=%s",
|
||||
RxStateStrings[rxState]);
|
||||
|
||||
if (txDmaEvent.scheduled())
|
||||
txDmaCopy();
|
||||
if (txState == txCopy)
|
||||
panic("can't serialize with an in flight dma request txState=%s",
|
||||
TxStateStrings[txState]);
|
||||
|
||||
/*
|
||||
* Serialize the device registers
|
||||
*/
|
||||
SERIALIZE_SCALAR(regs.Config);
|
||||
SERIALIZE_SCALAR(regs.RxMaxCopy);
|
||||
SERIALIZE_SCALAR(regs.TxMaxCopy);
|
||||
SERIALIZE_SCALAR(regs.RxThreshold);
|
||||
SERIALIZE_SCALAR(regs.TxThreshold);
|
||||
SERIALIZE_SCALAR(regs.IntrStatus);
|
||||
SERIALIZE_SCALAR(regs.IntrMask);
|
||||
SERIALIZE_SCALAR(regs.RxMaxCopy);
|
||||
SERIALIZE_SCALAR(regs.TxMaxCopy);
|
||||
SERIALIZE_SCALAR(regs.RxMaxIntr);
|
||||
SERIALIZE_SCALAR(regs.RxData);
|
||||
SERIALIZE_SCALAR(regs.RxDone);
|
||||
SERIALIZE_SCALAR(regs.TxData);
|
||||
@@ -1189,6 +1247,7 @@ Device::serialize(ostream &os)
|
||||
*/
|
||||
int rxState = this->rxState;
|
||||
SERIALIZE_SCALAR(rxState);
|
||||
SERIALIZE_SCALAR(rxEmpty);
|
||||
rxFifo.serialize("rxFifo", os);
|
||||
bool rxPacketExists = rxPacket;
|
||||
SERIALIZE_SCALAR(rxPacketExists);
|
||||
@@ -1205,6 +1264,7 @@ Device::serialize(ostream &os)
|
||||
*/
|
||||
int txState = this->txState;
|
||||
SERIALIZE_SCALAR(txState);
|
||||
SERIALIZE_SCALAR(txFull);
|
||||
txFifo.serialize("txFifo", os);
|
||||
bool txPacketExists = txPacket;
|
||||
SERIALIZE_SCALAR(txPacketExists);
|
||||
@@ -1233,12 +1293,11 @@ Device::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
* Unserialize the device registers
|
||||
*/
|
||||
UNSERIALIZE_SCALAR(regs.Config);
|
||||
UNSERIALIZE_SCALAR(regs.RxMaxCopy);
|
||||
UNSERIALIZE_SCALAR(regs.TxMaxCopy);
|
||||
UNSERIALIZE_SCALAR(regs.RxThreshold);
|
||||
UNSERIALIZE_SCALAR(regs.TxThreshold);
|
||||
UNSERIALIZE_SCALAR(regs.IntrStatus);
|
||||
UNSERIALIZE_SCALAR(regs.IntrMask);
|
||||
UNSERIALIZE_SCALAR(regs.RxMaxCopy);
|
||||
UNSERIALIZE_SCALAR(regs.TxMaxCopy);
|
||||
UNSERIALIZE_SCALAR(regs.RxMaxIntr);
|
||||
UNSERIALIZE_SCALAR(regs.RxData);
|
||||
UNSERIALIZE_SCALAR(regs.RxDone);
|
||||
UNSERIALIZE_SCALAR(regs.TxData);
|
||||
@@ -1249,6 +1308,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
*/
|
||||
int rxState;
|
||||
UNSERIALIZE_SCALAR(rxState);
|
||||
UNSERIALIZE_SCALAR(rxEmpty);
|
||||
this->rxState = (RxState) rxState;
|
||||
rxFifo.unserialize("rxFifo", cp, section);
|
||||
bool rxPacketExists;
|
||||
@@ -1269,6 +1329,7 @@ Device::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
*/
|
||||
int txState;
|
||||
UNSERIALIZE_SCALAR(txState);
|
||||
UNSERIALIZE_SCALAR(txFull);
|
||||
this->txState = (TxState) txState;
|
||||
txFifo.unserialize("txFifo", cp, section);
|
||||
bool txPacketExists;
|
||||
@@ -1310,15 +1371,19 @@ Device::cacheAccess(MemReqPtr &req)
|
||||
Tick when = curTick + pioLatency;
|
||||
|
||||
switch (daddr) {
|
||||
case Regs::RxDone:
|
||||
case Regs::RxWait:
|
||||
if (rxState != rxIdle) {
|
||||
DPRINTF(EthernetPIO, "rxState=%s (not idle)... waiting\n",
|
||||
TxStateStrings[txState]);
|
||||
rxPioRequest = req;
|
||||
when = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case Regs::TxDone:
|
||||
case Regs::TxWait:
|
||||
if (txState != txIdle) {
|
||||
DPRINTF(EthernetPIO, "txState=%s (not idle)... waiting\n",
|
||||
TxStateStrings[txState]);
|
||||
txPioRequest = req;
|
||||
when = 0;
|
||||
}
|
||||
@@ -1387,6 +1452,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
|
||||
Param<Tick> tx_delay;
|
||||
Param<uint32_t> rx_max_copy;
|
||||
Param<uint32_t> tx_max_copy;
|
||||
Param<uint32_t> rx_max_intr;
|
||||
Param<uint32_t> rx_fifo_size;
|
||||
Param<uint32_t> tx_fifo_size;
|
||||
Param<uint32_t> rx_fifo_threshold;
|
||||
@@ -1394,6 +1460,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
|
||||
|
||||
Param<bool> rx_filter;
|
||||
Param<string> hardware_address;
|
||||
Param<bool> dedicated;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(Device)
|
||||
|
||||
@@ -1426,13 +1493,15 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
|
||||
INIT_PARAM(tx_delay, "Transmit Delay"),
|
||||
INIT_PARAM(rx_max_copy, "rx max copy"),
|
||||
INIT_PARAM(tx_max_copy, "rx max copy"),
|
||||
INIT_PARAM(rx_max_intr, "rx max intr"),
|
||||
INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"),
|
||||
INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"),
|
||||
INIT_PARAM(rx_fifo_threshold, "max size in bytes of rxFifo"),
|
||||
INIT_PARAM(tx_fifo_threshold, "max size in bytes of txFifo"),
|
||||
|
||||
INIT_PARAM(rx_filter, "Enable Receive Filter"),
|
||||
INIT_PARAM(hardware_address, "Ethernet Hardware Address")
|
||||
INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
|
||||
INIT_PARAM(dedicated, "dedicate a kernel thread to the driver")
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(Device)
|
||||
|
||||
@@ -1444,6 +1513,7 @@ CREATE_SIM_OBJECT(Device)
|
||||
params->name = getInstanceName();
|
||||
|
||||
params->clock = clock;
|
||||
|
||||
params->mmu = mmu;
|
||||
params->physmem = physmem;
|
||||
params->configSpace = configspace;
|
||||
@@ -1468,6 +1538,7 @@ CREATE_SIM_OBJECT(Device)
|
||||
params->rx_delay = rx_delay;
|
||||
params->rx_max_copy = rx_max_copy;
|
||||
params->tx_max_copy = tx_max_copy;
|
||||
params->rx_max_intr = rx_max_intr;
|
||||
params->rx_fifo_size = rx_fifo_size;
|
||||
params->tx_fifo_size = tx_fifo_size;
|
||||
params->rx_fifo_threshold = rx_fifo_threshold;
|
||||
@@ -1475,6 +1546,7 @@ CREATE_SIM_OBJECT(Device)
|
||||
|
||||
params->rx_filter = rx_filter;
|
||||
params->eaddr = hardware_address;
|
||||
params->dedicated = dedicated;
|
||||
|
||||
return new Device(params);
|
||||
}
|
||||
|
||||
43
dev/sinic.hh
43
dev/sinic.hh
@@ -115,19 +115,31 @@ class Device : public Base
|
||||
|
||||
/** device register file */
|
||||
struct {
|
||||
uint32_t Config;
|
||||
uint32_t RxMaxCopy;
|
||||
uint32_t TxMaxCopy;
|
||||
uint32_t RxThreshold;
|
||||
uint32_t TxThreshold;
|
||||
uint32_t IntrStatus;
|
||||
uint32_t IntrMask;
|
||||
uint64_t RxData;
|
||||
uint64_t RxDone;
|
||||
uint64_t TxData;
|
||||
uint64_t TxDone;
|
||||
uint32_t Config; // 0x00
|
||||
uint32_t Command; // 0x04
|
||||
uint32_t IntrStatus; // 0x08
|
||||
uint32_t IntrMask; // 0x0c
|
||||
uint32_t RxMaxCopy; // 0x10
|
||||
uint32_t TxMaxCopy; // 0x14
|
||||
uint32_t RxMaxIntr; // 0x18
|
||||
uint32_t Reserved0; // 0x1c
|
||||
uint32_t RxFifoSize; // 0x20
|
||||
uint32_t TxFifoSize; // 0x24
|
||||
uint32_t RxFifoMark; // 0x28
|
||||
uint32_t TxFifoMark; // 0x2c
|
||||
uint64_t RxData; // 0x30
|
||||
uint64_t RxDone; // 0x38
|
||||
uint64_t RxWait; // 0x40
|
||||
uint64_t TxData; // 0x48
|
||||
uint64_t TxDone; // 0x50
|
||||
uint64_t TxWait; // 0x58
|
||||
uint64_t HwAddr; // 0x60
|
||||
} regs;
|
||||
|
||||
uint8_t ®Data8(Addr daddr) { return *((uint8_t *)®s + daddr); }
|
||||
uint32_t ®Data32(Addr daddr) { return *(uint32_t *)®Data8(daddr); }
|
||||
uint64_t ®Data64(Addr daddr) { return *(uint64_t *)®Data8(daddr); }
|
||||
|
||||
private:
|
||||
Addr addr;
|
||||
static const Addr size = Regs::Size;
|
||||
@@ -135,6 +147,7 @@ class Device : public Base
|
||||
protected:
|
||||
RxState rxState;
|
||||
PacketFifo rxFifo;
|
||||
bool rxEmpty;
|
||||
PacketPtr rxPacket;
|
||||
uint8_t *rxPacketBufPtr;
|
||||
int rxPktBytes;
|
||||
@@ -145,6 +158,7 @@ class Device : public Base
|
||||
|
||||
TxState txState;
|
||||
PacketFifo txFifo;
|
||||
bool txFull;
|
||||
PacketPtr txPacket;
|
||||
uint8_t *txPacketBufPtr;
|
||||
int txPktBytes;
|
||||
@@ -191,6 +205,7 @@ class Device : public Base
|
||||
* device configuration
|
||||
*/
|
||||
void changeConfig(uint32_t newconfig);
|
||||
void command(uint32_t command);
|
||||
|
||||
/**
|
||||
* device ethernet interface
|
||||
@@ -212,7 +227,7 @@ class Device : public Base
|
||||
void txDmaCopy();
|
||||
void txDmaDone();
|
||||
friend class EventWrapper<Device, &Device::txDmaDone>;
|
||||
EventWrapper<Device, &Device::rxDmaDone> txDmaEvent;
|
||||
EventWrapper<Device, &Device::txDmaDone> txDmaEvent;
|
||||
|
||||
Tick dmaReadDelay;
|
||||
Tick dmaReadFactor;
|
||||
@@ -244,6 +259,8 @@ class Device : public Base
|
||||
* Memory Interface
|
||||
*/
|
||||
public:
|
||||
void prepareRead();
|
||||
Fault iprRead(Addr daddr, uint64_t &result);
|
||||
virtual Fault read(MemReqPtr &req, uint8_t *data);
|
||||
virtual Fault write(MemReqPtr &req, const uint8_t *data);
|
||||
Tick cacheAccess(MemReqPtr &req);
|
||||
@@ -308,6 +325,7 @@ class Device : public Base
|
||||
Net::EthAddr eaddr;
|
||||
uint32_t rx_max_copy;
|
||||
uint32_t tx_max_copy;
|
||||
uint32_t rx_max_intr;
|
||||
uint32_t rx_fifo_size;
|
||||
uint32_t tx_fifo_size;
|
||||
uint32_t rx_fifo_threshold;
|
||||
@@ -317,6 +335,7 @@ class Device : public Base
|
||||
Tick dma_write_delay;
|
||||
Tick dma_write_factor;
|
||||
bool dma_no_allocate;
|
||||
bool dedicated;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
195
dev/sinicreg.hh
195
dev/sinicreg.hh
@@ -57,23 +57,28 @@ namespace Regs {
|
||||
|
||||
// Registers
|
||||
__SINIC_REG32(Config, 0x00); // 32: configuration register
|
||||
__SINIC_REG32(RxMaxCopy, 0x04); // 32: max rx copy
|
||||
__SINIC_REG32(TxMaxCopy, 0x08); // 32: max tx copy
|
||||
__SINIC_REG32(RxThreshold, 0x0c); // 32: receive fifo threshold
|
||||
__SINIC_REG32(TxThreshold, 0x10); // 32: transmit fifo threshold
|
||||
__SINIC_REG32(IntrStatus, 0x14); // 32: interrupt status
|
||||
__SINIC_REG32(IntrMask, 0x18); // 32: interrupt mask
|
||||
__SINIC_REG32(RxData, 0x20); // 64: receive data
|
||||
__SINIC_REG32(RxDone, 0x28); // 64: receive done
|
||||
__SINIC_REG32(RxWait, 0x30); // 64: receive done (busy wait)
|
||||
__SINIC_REG32(TxData, 0x38); // 64: transmit data
|
||||
__SINIC_REG32(TxDone, 0x40); // 64: transmit done
|
||||
__SINIC_REG32(TxWait, 0x48); // 64: transmit done (busy wait)
|
||||
__SINIC_REG32(HwAddr, 0x50); // 64: mac address
|
||||
__SINIC_REG32(Size, 0x58);
|
||||
__SINIC_REG32(Command, 0x04); // 32: command register
|
||||
__SINIC_REG32(IntrStatus, 0x08); // 32: interrupt status
|
||||
__SINIC_REG32(IntrMask, 0x0c); // 32: interrupt mask
|
||||
__SINIC_REG32(RxMaxCopy, 0x10); // 32: max bytes per rx copy
|
||||
__SINIC_REG32(TxMaxCopy, 0x14); // 32: max bytes per tx copy
|
||||
__SINIC_REG32(RxMaxIntr, 0x18); // 32: max receives per interrupt
|
||||
__SINIC_REG32(Reserved0, 0x1c); // 32: reserved
|
||||
__SINIC_REG32(RxFifoSize, 0x20); // 32: rx fifo capacity in bytes
|
||||
__SINIC_REG32(TxFifoSize, 0x24); // 32: tx fifo capacity in bytes
|
||||
__SINIC_REG32(RxFifoMark, 0x28); // 32: rx fifo high watermark
|
||||
__SINIC_REG32(TxFifoMark, 0x2c); // 32: tx fifo low watermark
|
||||
__SINIC_REG32(RxData, 0x30); // 64: receive data
|
||||
__SINIC_REG32(RxDone, 0x38); // 64: receive done
|
||||
__SINIC_REG32(RxWait, 0x40); // 64: receive done (busy wait)
|
||||
__SINIC_REG32(TxData, 0x48); // 64: transmit data
|
||||
__SINIC_REG32(TxDone, 0x50); // 64: transmit done
|
||||
__SINIC_REG32(TxWait, 0x58); // 64: transmit done (busy wait)
|
||||
__SINIC_REG32(HwAddr, 0x60); // 64: mac address
|
||||
__SINIC_REG32(Size, 0x68); // register addres space size
|
||||
|
||||
// Config register bits
|
||||
__SINIC_VAL32(Config_Reset, 31, 1); // reset chip
|
||||
__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
|
||||
@@ -83,105 +88,103 @@ __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_Reset, 0, 1); // reset chip
|
||||
|
||||
// Interrupt register bits
|
||||
__SINIC_VAL32(Intr_TxFifo, 5, 1); // Fifo oflow/uflow/threshold
|
||||
__SINIC_VAL32(Intr_TxData, 4, 1); // DMA Completed w/ interrupt
|
||||
__SINIC_VAL32(Intr_TxDone, 3, 1); // Packet transmitted
|
||||
__SINIC_VAL32(Intr_RxFifo, 2, 1); // Fifo oflow/uflow/threshold
|
||||
__SINIC_VAL32(Intr_RxData, 1, 1); // DMA Completed w/ interrupt
|
||||
__SINIC_VAL32(Intr_RxDone, 0, 1); // Packet received
|
||||
__SINIC_REG32(Intr_All, 0x3f);
|
||||
__SINIC_REG32(Intr_NoDelay, 0x24);
|
||||
__SINIC_REG32(Intr_Res, ~0x3f);
|
||||
__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_TxPacket, 4, 1); // packet transmitted
|
||||
__SINIC_VAL32(Intr_RxHigh, 3, 1); // rx fifo above high watermark
|
||||
__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
|
||||
|
||||
// RX Data Description
|
||||
__SINIC_VAL64(RxData_Len, 40, 20); // 0 - 1M
|
||||
__SINIC_VAL64(RxData_Addr, 0, 40); // Address 1TB
|
||||
|
||||
// TX Data Description
|
||||
__SINIC_VAL64(TxData_More, 63, 1);
|
||||
__SINIC_VAL64(TxData_Checksum, 62, 1);
|
||||
__SINIC_VAL64(TxData_More, 63, 1); // Packet not complete (will dma more)
|
||||
__SINIC_VAL64(TxData_Checksum, 62, 1); // do checksum
|
||||
__SINIC_VAL64(TxData_Len, 40, 20); // 0 - 1M
|
||||
__SINIC_VAL64(TxData_Addr, 0, 40); // Address 1TB
|
||||
|
||||
// RX Done/Busy Information
|
||||
__SINIC_VAL64(RxDone_Complete, 63, 1);
|
||||
__SINIC_VAL64(RxDone_IpPacket, 45, 1);
|
||||
__SINIC_VAL64(RxDone_TcpPacket, 44, 1);
|
||||
__SINIC_VAL64(RxDone_UdpPacket, 43, 1);
|
||||
__SINIC_VAL64(RxDone_IpError, 42, 1);
|
||||
__SINIC_VAL64(RxDone_TcpError, 41, 1);
|
||||
__SINIC_VAL64(RxDone_UdpError, 40, 1);
|
||||
__SINIC_VAL64(RxDone_More, 32, 1);
|
||||
__SINIC_VAL64(RxDone_FifoLen, 20, 8); // up to 255 packets
|
||||
__SINIC_VAL64(RxDone_Packets, 32, 16); // number of packets in rx fifo
|
||||
__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_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(RxDone_TcpPacket, 22, 1); // this is a TCP packet
|
||||
__SINIC_VAL64(RxDone_UdpPacket, 21, 1); // this is a UDP packet
|
||||
__SINIC_VAL64(RxDone_IpPacket, 20, 1); // this is an IP packet
|
||||
__SINIC_VAL64(RxDone_CopyLen, 0, 20); // up to 256k
|
||||
|
||||
// TX Done/Busy Information
|
||||
__SINIC_VAL64(TxDone_Complete, 63, 1);
|
||||
__SINIC_VAL64(TxDone_FifoLen, 20, 8); // up to 255 packets
|
||||
__SINIC_VAL64(TxDone_CopyLen, 0, 20); // up to 256k
|
||||
__SINIC_VAL64(TxDone_Packets, 32, 16); // number of packets in tx fifo
|
||||
__SINIC_VAL64(TxDone_Busy, 31, 1); // transmit dma busy copying
|
||||
__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_CopyLen, 0, 20); // up to 256k
|
||||
|
||||
inline int
|
||||
regSize(int offset)
|
||||
struct Info
|
||||
{
|
||||
static const char sizes[] = {
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
0,
|
||||
8, 0,
|
||||
8, 0,
|
||||
8, 0,
|
||||
8, 0,
|
||||
8, 0,
|
||||
8, 0,
|
||||
8, 0
|
||||
};
|
||||
|
||||
if (offset & 0x3)
|
||||
return 0;
|
||||
|
||||
if (offset >= Size)
|
||||
return 0;
|
||||
|
||||
return sizes[offset / 4];
|
||||
}
|
||||
|
||||
inline const char *
|
||||
regName(int offset)
|
||||
{
|
||||
static const char *names[] = {
|
||||
"Config",
|
||||
"RxMaxCopy",
|
||||
"TxMaxCopy",
|
||||
"RxThreshold",
|
||||
"TxThreshold",
|
||||
"IntrStatus",
|
||||
"IntrMask",
|
||||
"invalid",
|
||||
"RxData", "invalid",
|
||||
"RxDone", "invalid",
|
||||
"RxWait", "invalid",
|
||||
"TxData", "invalid",
|
||||
"TxDone", "invalid",
|
||||
"TxWait", "invalid",
|
||||
"HwAddr", "invalid"
|
||||
};
|
||||
|
||||
if (offset & 0x3)
|
||||
return "invalid";
|
||||
|
||||
if (offset >= Size)
|
||||
return "invalid";
|
||||
|
||||
return names[offset / 4];
|
||||
}
|
||||
uint8_t size;
|
||||
bool read;
|
||||
bool write;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
/* namespace Regs */ }
|
||||
|
||||
inline const Regs::Info&
|
||||
regInfo(Addr daddr)
|
||||
{
|
||||
static Regs::Info info [] = {
|
||||
{ 4, true, true, "Config" },
|
||||
{ 4, false, true, "Command" },
|
||||
{ 4, true, true, "IntrStatus" },
|
||||
{ 4, true, true, "IntrMask" },
|
||||
{ 4, true, false, "RxMaxCopy" },
|
||||
{ 4, true, false, "TxMaxCopy" },
|
||||
{ 4, true, false, "RxMaxIntr" },
|
||||
{ 0, false, false, "invalid" },
|
||||
{ 4, true, false, "RxFifoSize" },
|
||||
{ 4, true, false, "TxFifoSize" },
|
||||
{ 4, true, false, "RxFifoMark" },
|
||||
{ 4, true, false, "TxFifoMark" },
|
||||
{ 8, true, true, "RxData" }, { 0, false, false, "invalid" },
|
||||
{ 8, true, false, "RxDone" }, { 0, false, false, "invalid" },
|
||||
{ 8, true, false, "RxWait" }, { 0, false, false, "invalid" },
|
||||
{ 8, true, true, "TxData" }, { 0, false, false, "invalid" },
|
||||
{ 8, true, false, "TxDone" }, { 0, false, false, "invalid" },
|
||||
{ 8, true, false, "TxWait" }, { 0, false, false, "invalid" },
|
||||
{ 8, true, false, "HwAddr" }, { 0, false, false, "invalid" }
|
||||
};
|
||||
|
||||
return info[daddr / 4];
|
||||
}
|
||||
|
||||
inline bool
|
||||
regValid(Addr daddr)
|
||||
{
|
||||
if (daddr > Regs::Size)
|
||||
return false;
|
||||
|
||||
if (regInfo(daddr).size == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* namespace Sinic */ }
|
||||
|
||||
#endif // __DEV_SINICREG_HH__
|
||||
|
||||
Reference in New Issue
Block a user