summaryrefslogtreecommitdiff
path: root/src/dev
diff options
context:
space:
mode:
Diffstat (limited to 'src/dev')
-rw-r--r--src/dev/alpha/console.cc2
-rw-r--r--src/dev/etherint.hh3
-rw-r--r--src/dev/etherlink.hh1
-rw-r--r--src/dev/i8254xGBe.cc61
-rw-r--r--src/dev/i8254xGBe.hh2
-rw-r--r--src/dev/ide_ctrl.cc6
-rw-r--r--src/dev/io_device.cc103
-rw-r--r--src/dev/io_device.hh25
-rw-r--r--src/dev/ns_gige.cc11
-rw-r--r--src/dev/pcidev.hh2
-rw-r--r--src/dev/sinic.cc11
-rw-r--r--src/dev/uart8250.cc27
-rw-r--r--src/dev/uart8250.hh1
13 files changed, 200 insertions, 55 deletions
diff --git a/src/dev/alpha/console.cc b/src/dev/alpha/console.cc
index f077efe6c..443f376a5 100644
--- a/src/dev/alpha/console.cc
+++ b/src/dev/alpha/console.cc
@@ -76,7 +76,7 @@ AlphaConsole::AlphaConsole(Params *p)
alphaAccess->diskOperation = 0;
alphaAccess->outputChar = 0;
alphaAccess->inputChar = 0;
- bzero(alphaAccess->cpuStack, sizeof(alphaAccess->cpuStack));
+ std::memset(alphaAccess->cpuStack, 0, sizeof(alphaAccess->cpuStack));
}
diff --git a/src/dev/etherint.hh b/src/dev/etherint.hh
index dfc224ecc..430f45d66 100644
--- a/src/dev/etherint.hh
+++ b/src/dev/etherint.hh
@@ -63,6 +63,9 @@ class EtherInt : public SimObject
bool sendPacket(EthPacketPtr packet)
{ return peer ? peer->recvPacket(packet) : true; }
virtual bool recvPacket(EthPacketPtr packet) = 0;
+
+ bool askBusy() {return peer->isBusy(); }
+ virtual bool isBusy() { return false; }
};
#endif // __DEV_ETHERINT_HH__
diff --git a/src/dev/etherlink.hh b/src/dev/etherlink.hh
index bb2854810..a16d6d799 100644
--- a/src/dev/etherlink.hh
+++ b/src/dev/etherlink.hh
@@ -114,6 +114,7 @@ class EtherLink : public SimObject
Interface(const std::string &name, Link *txlink, Link *rxlink);
bool recvPacket(EthPacketPtr packet) { return txlink->transmit(packet); }
void sendDone() { peer->sendDone(); }
+ bool isBusy() { return txlink->busy(); }
};
Link *link[2];
diff --git a/src/dev/i8254xGBe.cc b/src/dev/i8254xGBe.cc
index 3d08bca1e..baf13c49a 100644
--- a/src/dev/i8254xGBe.cc
+++ b/src/dev/i8254xGBe.cc
@@ -656,7 +656,7 @@ IGbE::RxDescCache::writePacket(EthPacketPtr packet)
return false;
pktPtr = packet;
-
+ pktDone = false;
igbe->dmaWrite(igbe->platform->pciToDma(unusedCache.front()->buf),
packet->length, &pktEvent, packet->data);
return true;
@@ -683,8 +683,12 @@ IGbE::RxDescCache::pktComplete()
uint8_t status = RXDS_DD | RXDS_EOP;
uint8_t err = 0;
+
IpPtr ip(pktPtr);
+
if (ip) {
+ DPRINTF(EthernetDesc, "Proccesing Ip packet with Id=%d\n", ip->id());
+
if (igbe->regs.rxcsum.ipofld()) {
DPRINTF(EthernetDesc, "Checking IP checksum\n");
status |= RXDS_IPCS;
@@ -710,12 +714,15 @@ IGbE::RxDescCache::pktComplete()
DPRINTF(EthernetDesc, "Checking UDP checksum\n");
status |= RXDS_UDPCS;
desc->csum = htole(cksum(udp));
- if (cksum(tcp) != 0) {
+ if (cksum(udp) != 0) {
DPRINTF(EthernetDesc, "Checksum is bad!!\n");
err |= RXDE_TCPE;
}
}
- } // if ip
+ } else { // if ip
+ DPRINTF(EthernetSM, "Proccesing Non-Ip packet\n");
+ }
+
desc->status = htole(status);
desc->errors = htole(err);
@@ -727,12 +734,8 @@ IGbE::RxDescCache::pktComplete()
if (igbe->regs.rdtr.delay()) {
DPRINTF(EthernetSM, "RXS: Scheduling DTR for %d\n",
igbe->regs.rdtr.delay() * igbe->intClock());
- if (igbe->rdtrEvent.scheduled())
- igbe->rdtrEvent.reschedule(curTick + igbe->regs.rdtr.delay() *
- igbe->intClock());
- else
- igbe->rdtrEvent.schedule(curTick + igbe->regs.rdtr.delay() *
- igbe->intClock());
+ igbe->rdtrEvent.reschedule(curTick + igbe->regs.rdtr.delay() *
+ igbe->intClock(),true);
}
if (igbe->regs.radv.idv() && igbe->regs.rdtr.delay()) {
@@ -895,6 +898,7 @@ IGbE::TxDescCache::pktComplete()
pktPtr = NULL;
DPRINTF(EthernetDesc, "Partial Packet Descriptor Done\n");
+ enableSm();
return;
}
@@ -915,10 +919,20 @@ IGbE::TxDescCache::pktComplete()
DPRINTF(EthernetDesc, "TxDescriptor data d1: %#llx d2: %#llx\n", desc->d1, desc->d2);
+ if (DTRACE(EthernetDesc)) {
+ IpPtr ip(pktPtr);
+ if (ip)
+ DPRINTF(EthernetDesc, "Proccesing Ip packet with Id=%d\n",
+ ip->id());
+ else
+ DPRINTF(EthernetSM, "Proccesing Non-Ip packet\n");
+ }
+
// Checksums are only ofloaded for new descriptor types
if (TxdOp::isData(desc) && ( TxdOp::ixsm(desc) || TxdOp::txsm(desc)) ) {
DPRINTF(EthernetDesc, "Calculating checksums for packet\n");
IpPtr ip(pktPtr);
+
if (TxdOp::ixsm(desc)) {
ip->sum(0);
ip->sum(cksum(ip));
@@ -927,11 +941,13 @@ IGbE::TxDescCache::pktComplete()
if (TxdOp::txsm(desc)) {
if (isTcp) {
TcpPtr tcp(ip);
+ assert(tcp);
tcp->sum(0);
tcp->sum(cksum(tcp));
DPRINTF(EthernetDesc, "Calculated TCP checksum\n");
} else {
UdpPtr udp(ip);
+ assert(udp);
udp->sum(0);
udp->sum(cksum(udp));
DPRINTF(EthernetDesc, "Calculated UDP checksum\n");
@@ -944,12 +960,8 @@ IGbE::TxDescCache::pktComplete()
DPRINTF(EthernetDesc, "Descriptor had IDE set\n");
if (igbe->regs.tidv.idv()) {
DPRINTF(EthernetDesc, "setting tidv\n");
- if (igbe->tidvEvent.scheduled())
- igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() *
- igbe->intClock());
- else
- igbe->tidvEvent.schedule(curTick + igbe->regs.tidv.idv() *
- igbe->intClock());
+ igbe->tidvEvent.reschedule(curTick + igbe->regs.tidv.idv() *
+ igbe->intClock(), true);
}
if (igbe->regs.tadv.idv() && igbe->regs.tidv.idv()) {
@@ -977,6 +989,7 @@ IGbE::TxDescCache::pktComplete()
DPRINTF(EthernetDesc, "used > WTHRESH, writing back descriptor\n");
writeback((igbe->cacheBlockSize()-1)>>4);
}
+ enableSm();
igbe->checkDrain();
}
@@ -1028,7 +1041,7 @@ IGbE::TxDescCache::hasOutstandingEvents()
void
IGbE::restartClock()
{
- if (!tickEvent.scheduled() && (rxTick || txTick) && getState() ==
+ if (!tickEvent.scheduled() && (rxTick || txTick || txFifoTick) && getState() ==
SimObject::Running)
tickEvent.schedule((curTick/cycles(1)) * cycles(1) + cycles(1));
}
@@ -1156,6 +1169,8 @@ IGbE::txStateMachine()
return;
}
+ DPRINTF(EthernetSM, "TXS: Nothing to do, stopping ticking\n");
+ txTick = false;
}
bool
@@ -1194,6 +1209,7 @@ IGbE::rxStateMachine()
// If the packet is done check for interrupts/descriptors/etc
if (rxDescCache.packetDone()) {
+ rxDmaPacket = false;
DPRINTF(EthernetSM, "RXS: Packet completed DMA to memory\n");
int descLeft = rxDescCache.descLeft();
switch (regs.rctl.rdmts()) {
@@ -1238,6 +1254,12 @@ IGbE::rxStateMachine()
return;
}
+ if (rxDmaPacket) {
+ DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n");
+ rxTick = false;
+ return;
+ }
+
if (!rxDescCache.descUnused()) {
DPRINTF(EthernetSM, "RXS: No descriptors available in cache, stopping ticking\n");
rxTick = false;
@@ -1264,6 +1286,7 @@ IGbE::rxStateMachine()
rxFifo.pop();
DPRINTF(EthernetSM, "RXS: stopping ticking until packet DMA completes\n");
rxTick = false;
+ rxDmaPacket = true;
}
void
@@ -1458,6 +1481,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IGbE)
SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
+ Param<Tick> min_backoff_delay;
+ Param<Tick> max_backoff_delay;
SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
@@ -1479,6 +1504,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IGbE)
INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"),
+ INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"),
+ INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"),
INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
@@ -1503,6 +1530,8 @@ CREATE_SIM_OBJECT(IGbE)
params->name = getInstanceName();
params->platform = platform;
params->system = system;
+ params->min_backoff_delay = min_backoff_delay;
+ params->max_backoff_delay = max_backoff_delay;
params->configData = configdata;
params->busNum = pci_bus;
params->deviceNum = pci_dev;
diff --git a/src/dev/i8254xGBe.hh b/src/dev/i8254xGBe.hh
index 2dec3b08c..b6da53b09 100644
--- a/src/dev/i8254xGBe.hh
+++ b/src/dev/i8254xGBe.hh
@@ -80,6 +80,8 @@ class IGbE : public PciDev
bool txTick;
bool txFifoTick;
+ bool rxDmaPacket;
+
// Event and function to deal with RDTR timer expiring
void rdtrProcess() {
rxDescCache.writeback(0);
diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc
index 1afad529f..921ba1cd0 100644
--- a/src/dev/ide_ctrl.cc
+++ b/src/dev/ide_ctrl.cc
@@ -751,6 +751,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
+ Param<Tick> min_backoff_delay;
+ Param<Tick> max_backoff_delay;
SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
@@ -765,6 +767,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"),
+ INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"),
+ INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"),
INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
@@ -781,6 +785,8 @@ CREATE_SIM_OBJECT(IdeController)
params->name = getInstanceName();
params->platform = platform;
params->system = system;
+ params->min_backoff_delay = min_backoff_delay;
+ params->max_backoff_delay = max_backoff_delay;
params->configData = configdata;
params->busNum = pci_bus;
params->deviceNum = pci_dev;
diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc
index a1285fefc..6528bd81c 100644
--- a/src/dev/io_device.cc
+++ b/src/dev/io_device.cc
@@ -93,7 +93,8 @@ BasicPioDevice::addressRanges(AddrRangeList &range_list)
DmaPort::DmaPort(DmaDevice *dev, System *s)
: Port(dev->name() + "-dmaport", dev), device(dev), sys(s),
- pendingCount(0), actionInProgress(0), drainEvent(NULL)
+ pendingCount(0), actionInProgress(0), drainEvent(NULL),
+ backoffTime(0), inRetry(false), backoffEvent(this)
{ }
bool
@@ -104,12 +105,24 @@ DmaPort::recvTiming(PacketPtr pkt)
if (pkt->result == Packet::Nacked) {
DPRINTF(DMA, "Received nacked Pkt %#x with State: %#x Addr: %#x\n",
pkt, pkt->senderState, pkt->getAddr());
+
+ if (backoffTime < device->minBackoffDelay)
+ backoffTime = device->minBackoffDelay;
+ else if (backoffTime < device->maxBackoffDelay)
+ backoffTime <<= 1;
+
+ backoffEvent.reschedule(curTick + backoffTime, true);
+
+ DPRINTF(DMA, "Backoff time set to %d ticks\n", backoffTime);
+
pkt->reinitNacked();
- sendDma(pkt, true);
+ queueDma(pkt, true);
} else if (pkt->senderState) {
DmaReqState *state;
- DPRINTF(DMA, "Received response Pkt %#x with State: %#x Addr: %#x\n",
- pkt, pkt->senderState, pkt->getAddr());
+ backoffTime >>= 2;
+
+ DPRINTF(DMA, "Received response Pkt %#x with State: %#x Addr: %#x size: %#x\n",
+ pkt, pkt->senderState, pkt->getAddr(), pkt->req->getSize());
state = dynamic_cast<DmaReqState*>(pkt->senderState);
pendingCount--;
@@ -117,6 +130,7 @@ DmaPort::recvTiming(PacketPtr pkt)
assert(state);
state->numBytes += pkt->req->getSize();
+ assert(state->totBytes >= state->numBytes);
if (state->totBytes == state->numBytes) {
state->completionEvent->process();
delete state;
@@ -136,7 +150,8 @@ DmaPort::recvTiming(PacketPtr pkt)
}
DmaDevice::DmaDevice(Params *p)
- : PioDevice(p), dmaPort(NULL)
+ : PioDevice(p), dmaPort(NULL), minBackoffDelay(p->min_backoff_delay),
+ maxBackoffDelay(p->max_backoff_delay)
{ }
@@ -165,19 +180,31 @@ DmaPort::drain(Event *de)
void
DmaPort::recvRetry()
{
+ assert(transmitList.size());
PacketPtr pkt = transmitList.front();
bool result = true;
- while (result && transmitList.size()) {
+ do {
DPRINTF(DMA, "Retry on Packet %#x with senderState: %#x\n",
pkt, pkt->senderState);
result = sendTiming(pkt);
if (result) {
DPRINTF(DMA, "-- Done\n");
transmitList.pop_front();
+ inRetry = false;
} else {
+ inRetry = true;
DPRINTF(DMA, "-- Failed, queued\n");
}
+ } while (!backoffTime && result && transmitList.size());
+
+ if (transmitList.size() && backoffTime && !inRetry) {
+ DPRINTF(DMA, "Scheduling backoff for %d\n", curTick+backoffTime);
+ if (!backoffEvent.scheduled())
+ backoffEvent.schedule(backoffTime+curTick);
}
+ DPRINTF(DMA, "TransmitList: %d, backoffTime: %d inRetry: %d es: %d\n",
+ transmitList.size(), backoffTime, inRetry,
+ backoffEvent.scheduled());
}
@@ -191,6 +218,9 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
DmaReqState *reqState = new DmaReqState(event, this, size);
+
+ DPRINTF(DMA, "Starting DMA for addr: %#x size: %d sched: %d\n", addr, size,
+ event->scheduled());
for (ChunkGenerator gen(addr, size, peerBlockSize());
!gen.done(); gen.next()) {
Request *req = new Request(gen.addr(), gen.size(), 0);
@@ -204,41 +234,80 @@ DmaPort::dmaAction(Packet::Command cmd, Addr addr, int size, Event *event,
assert(pendingCount >= 0);
pendingCount++;
- sendDma(pkt);
+ DPRINTF(DMA, "--Queuing DMA for addr: %#x size: %d\n", gen.addr(),
+ gen.size());
+ queueDma(pkt);
}
}
+void
+DmaPort::queueDma(PacketPtr pkt, bool front)
+{
+
+ if (front)
+ transmitList.push_front(pkt);
+ else
+ transmitList.push_back(pkt);
+ sendDma();
+}
+
void
-DmaPort::sendDma(PacketPtr pkt, bool front)
+DmaPort::sendDma()
{
// some kind of selction between access methods
// more work is going to have to be done to make
// switching actually work
+ assert(transmitList.size());
+ PacketPtr pkt = transmitList.front();
System::MemoryMode state = sys->getMemoryMode();
if (state == System::Timing) {
+ if (backoffEvent.scheduled() || inRetry) {
+ DPRINTF(DMA, "Can't send immediately, waiting for retry or backoff timer\n");
+ return;
+ }
+
DPRINTF(DMA, "Attempting to send Packet %#x with addr: %#x\n",
pkt, pkt->getAddr());
- if (transmitList.size() || !sendTiming(pkt)) {
- if (front)
- transmitList.push_front(pkt);
- else
- transmitList.push_back(pkt);
- DPRINTF(DMA, "-- Failed: queued\n");
- } else {
- DPRINTF(DMA, "-- Done\n");
+
+ bool result;
+ do {
+ result = sendTiming(pkt);
+ if (result) {
+ transmitList.pop_front();
+ DPRINTF(DMA, "-- Done\n");
+ } else {
+ inRetry = true;
+ DPRINTF(DMA, "-- Failed: queued\n");
+ }
+ } while (result && !backoffTime && transmitList.size());
+
+ if (transmitList.size() && backoffTime && !inRetry &&
+ !backoffEvent.scheduled()) {
+ DPRINTF(DMA, "-- Scheduling backoff timer for %d\n",
+ backoffTime+curTick);
+ backoffEvent.schedule(backoffTime+curTick);
}
} else if (state == System::Atomic) {
+ transmitList.pop_front();
+
Tick lat;
+ DPRINTF(DMA, "--Sending DMA for addr: %#x size: %d\n",
+ pkt->req->getPaddr(), pkt->req->getSize());
lat = sendAtomic(pkt);
assert(pkt->senderState);
DmaReqState *state = dynamic_cast<DmaReqState*>(pkt->senderState);
assert(state);
-
state->numBytes += pkt->req->getSize();
+
+ DPRINTF(DMA, "--Received response for DMA for addr: %#x size: %d nb: %d, tot: %d sched %d\n",
+ pkt->req->getPaddr(), pkt->req->getSize(), state->numBytes,
+ state->totBytes, state->completionEvent->scheduled());
+
if (state->totBytes == state->numBytes) {
+ assert(!state->completionEvent->scheduled());
state->completionEvent->schedule(curTick + lat);
delete state;
delete pkt->req;
diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh
index cd7a5296a..bd150bfe4 100644
--- a/src/dev/io_device.hh
+++ b/src/dev/io_device.hh
@@ -107,6 +107,14 @@ class DmaPort : public Port
* here.*/
Event *drainEvent;
+ /** time to wait between sending another packet, increases as NACKs are
+ * recived, decreases as responses are recived. */
+ Tick backoffTime;
+
+ /** If the port is currently waiting for a retry before it can send whatever
+ * it is that it's sending. */
+ bool inRetry;
+
virtual bool recvTiming(PacketPtr pkt);
virtual Tick recvAtomic(PacketPtr pkt)
{ panic("dma port shouldn't be used for pio access."); M5_DUMMY_RETURN }
@@ -122,7 +130,11 @@ class DmaPort : public Port
AddrRangeList &snoop)
{ resp.clear(); snoop.clear(); }
- void sendDma(PacketPtr pkt, bool front = false);
+ void queueDma(PacketPtr pkt, bool front = false);
+ void sendDma();
+
+ /** event to give us a kick every time we backoff time is reached. */
+ EventWrapper<DmaPort, &DmaPort::sendDma> backoffEvent;
public:
DmaPort(DmaDevice *dev, System *s);
@@ -249,8 +261,17 @@ class BasicPioDevice : public PioDevice
class DmaDevice : public PioDevice
{
- protected:
+ public:
+ struct Params : public PioDevice::Params
+ {
+ Tick min_backoff_delay;
+ Tick max_backoff_delay;
+ };
+
+ protected:
DmaPort *dmaPort;
+ Tick minBackoffDelay;
+ Tick maxBackoffDelay;
public:
DmaDevice(Params *p);
diff --git a/src/dev/ns_gige.cc b/src/dev/ns_gige.cc
index 86f56b62e..d9985f808 100644
--- a/src/dev/ns_gige.cc
+++ b/src/dev/ns_gige.cc
@@ -2310,10 +2310,7 @@ NSGigE::transferDone()
DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
- if (txEvent.scheduled())
- txEvent.reschedule(curTick + cycles(1));
- else
- txEvent.schedule(curTick + cycles(1));
+ txEvent.reschedule(curTick + cycles(1), true);
}
bool
@@ -2812,6 +2809,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE)
SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
+ Param<Tick> min_backoff_delay;
+ Param<Tick> max_backoff_delay;
SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
@@ -2846,6 +2845,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE)
INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"),
+ INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"),
+ INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"),
INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
@@ -2884,6 +2885,8 @@ CREATE_SIM_OBJECT(NSGigE)
params->name = getInstanceName();
params->platform = platform;
params->system = system;
+ params->min_backoff_delay = min_backoff_delay;
+ params->max_backoff_delay = max_backoff_delay;
params->configData = configdata;
params->busNum = pci_bus;
params->deviceNum = pci_dev;
diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh
index 56e3ffb4a..5044e2932 100644
--- a/src/dev/pcidev.hh
+++ b/src/dev/pcidev.hh
@@ -105,7 +105,7 @@ class PciDev : public DmaDevice
};
public:
- struct Params : public PioDevice::Params
+ struct Params : public DmaDevice::Params
{
/**
* A pointer to the object that contains the first 64 bytes of
diff --git a/src/dev/sinic.cc b/src/dev/sinic.cc
index f61c161aa..420761620 100644
--- a/src/dev/sinic.cc
+++ b/src/dev/sinic.cc
@@ -1199,10 +1199,7 @@ Device::transferDone()
DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
- if (txEvent.scheduled())
- txEvent.reschedule(curTick + cycles(1));
- else
- txEvent.schedule(curTick + cycles(1));
+ txEvent.reschedule(curTick + cycles(1), true);
}
bool
@@ -1635,6 +1632,8 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice)
SimObjectParam<System *> system;
SimObjectParam<Platform *> platform;
+ Param<Tick> min_backoff_delay;
+ Param<Tick> max_backoff_delay;
SimObjectParam<PciConfigData *> configdata;
Param<uint32_t> pci_bus;
Param<uint32_t> pci_dev;
@@ -1678,6 +1677,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice)
INIT_PARAM(system, "System pointer"),
INIT_PARAM(platform, "Platform pointer"),
+ INIT_PARAM(min_backoff_delay, "Minimum delay after receving a nack packed"),
+ INIT_PARAM(max_backoff_delay, "Maximum delay after receving a nack packed"),
INIT_PARAM(configdata, "PCI Config data"),
INIT_PARAM(pci_bus, "PCI bus ID"),
INIT_PARAM(pci_dev, "PCI device number"),
@@ -1723,6 +1724,8 @@ CREATE_SIM_OBJECT_WNS(Sinic, SinicDevice)
params->name = getInstanceName();
params->platform = platform;
params->system = system;
+ params->min_backoff_delay = min_backoff_delay;
+ params->max_backoff_delay = max_backoff_delay;
params->configData = configdata;
params->busNum = pci_bus;
params->deviceNum = pci_dev;
diff --git a/src/dev/uart8250.cc b/src/dev/uart8250.cc
index ddee33695..50307aad4 100644
--- a/src/dev/uart8250.cc
+++ b/src/dev/uart8250.cc
@@ -68,6 +68,7 @@ Uart8250::IntrEvent::process()
DPRINTF(Uart, "UART InterEvent, interrupting\n");
uart->platform->postConsoleInt();
uart->status |= intrBit;
+ uart->lastTxInt = curTick;
}
else
DPRINTF(Uart, "UART InterEvent, not interrupting\n");
@@ -100,14 +101,11 @@ Uart8250::IntrEvent::scheduleIntr()
Uart8250::Uart8250(Params *p)
- : Uart(p), txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT)
+ : Uart(p), IER(0), DLAB(0), LCR(0), MCR(0), lastTxInt(0),
+ txIntrEvent(this, TX_INT), rxIntrEvent(this, RX_INT)
{
pioSize = 8;
- IER = 0;
- DLAB = 0;
- LCR = 0;
- MCR = 0;
}
Tick
@@ -153,13 +151,13 @@ Uart8250::read(PacketPtr pkt)
if (status & RX_INT) /* Rx data interrupt has a higher priority */
pkt->set(IIR_RXID);
- else if (status & TX_INT)
+ else if (status & TX_INT) {
pkt->set(IIR_TXID);
- else
+ //Tx interrupts are cleared on IIR reads
+ status &= ~TX_INT;
+ } else
pkt->set(IIR_NOPEND);
- //Tx interrupts are cleared on IIR reads
- status &= ~TX_INT;
break;
case 0x3: // Line Control Register (LCR)
pkt->set(LCR);
@@ -222,7 +220,16 @@ Uart8250::write(PacketPtr pkt)
if (UART_IER_THRI & IER)
{
DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n");
- txIntrEvent.scheduleIntr();
+ if (curTick - lastTxInt >
+ (Tick)((Clock::Float::s / 2e9) * 450)) {
+ DPRINTF(Uart, "-- Interrupting Immediately... %d,%d\n",
+ curTick, lastTxInt);
+ txIntrEvent.process();
+ } else {
+ DPRINTF(Uart, "-- Delaying interrupt... %d,%d\n",
+ curTick, lastTxInt);
+ txIntrEvent.scheduleIntr();
+ }
}
else
{
diff --git a/src/dev/uart8250.hh b/src/dev/uart8250.hh
index c28200592..c9c878aed 100644
--- a/src/dev/uart8250.hh
+++ b/src/dev/uart8250.hh
@@ -74,6 +74,7 @@ class Uart8250 : public Uart
protected:
uint8_t IER, DLAB, LCR, MCR;
+ Tick lastTxInt;
class IntrEvent : public Event
{