Only issue responses if we aren;t already blocked
[gem5.git] / src / dev / sinic.cc
index df7e4d16746d85245dfc11cf29d1ae98609e8d88..61fb3aa2467daef1c6db61b38373fd33b15bce1c 100644 (file)
@@ -24,6 +24,8 @@
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Nathan Binkert
  */
 
 #include <deque>
 #include <string>
 
 #include "base/inet.hh"
-#include "cpu/exec_context.hh"
+#include "cpu/thread_context.hh"
 #include "cpu/intr_control.hh"
 #include "dev/etherlink.hh"
 #include "dev/sinic.hh"
-#include "dev/pciconfigall.hh"
 #include "mem/packet.hh"
 #include "sim/builder.hh"
 #include "sim/debug.hh"
@@ -315,40 +316,39 @@ Tick
 Device::read(Packet *pkt)
 {
     assert(config.command & PCI_CMD_MSE);
-    assert(pkt->addr >= BARAddrs[0] && pkt->size < BARSize[0]);
+    assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]);
 
     int cpu = pkt->req->getCpuNum();
-    Addr daddr = pkt->addr - BARAddrs[0];
+    Addr daddr = pkt->getAddr() - BARAddrs[0];
     Addr index = daddr >> Regs::VirtualShift;
     Addr raddr = daddr & Regs::VirtualMask;
 
-    pkt->time += pioDelay;
     pkt->allocate();
 
     if (!regValid(raddr))
         panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d",
-              cpu, index, daddr, pkt->addr, pkt->size);
+              cpu, index, daddr, pkt->getAddr(), pkt->getSize());
 
     const Regs::Info &info = regInfo(raddr);
     if (!info.read)
         panic("read %s (write only): "
               "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
-              info.name, cpu, index, daddr, pkt->addr, pkt->size);
+              info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
 
         panic("read %s (invalid size): "
               "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
-              info.name, cpu, index, daddr, pkt->addr, pkt->size);
+              info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
 
     prepareRead(cpu, index);
 
     uint64_t value = 0;
-    if (pkt->size == 4) {
+    if (pkt->getSize() == 4) {
         uint32_t reg = regData32(raddr);
         pkt->set(reg);
         value = reg;
     }
 
-    if (pkt->size == 8) {
+    if (pkt->getSize() == 8) {
         uint64_t reg = regData64(raddr);
         pkt->set(reg);
         value = reg;
@@ -356,7 +356,7 @@ Device::read(Packet *pkt)
 
     DPRINTF(EthernetPIO,
             "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",
-            info.name, cpu, index, daddr, pkt->addr, pkt->size, value);
+            info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize(), value);
 
     // reading the interrupt status register has the side effect of
     // clearing it
@@ -403,36 +403,34 @@ Tick
 Device::write(Packet *pkt)
 {
     assert(config.command & PCI_CMD_MSE);
-    assert(pkt->addr >= BARAddrs[0] && pkt->size < BARSize[0]);
+    assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]);
 
     int cpu = pkt->req->getCpuNum();
-    Addr daddr = pkt->addr - BARAddrs[0];
+    Addr daddr = pkt->getAddr() - BARAddrs[0];
     Addr index = daddr >> Regs::VirtualShift;
     Addr raddr = daddr & Regs::VirtualMask;
 
-    pkt->time += pioDelay;
-
     if (!regValid(raddr))
         panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d",
-                cpu, daddr, pkt->addr, pkt->size);
+                cpu, daddr, pkt->getAddr(), pkt->getSize());
 
     const Regs::Info &info = regInfo(raddr);
     if (!info.write)
         panic("write %s (read only): "
               "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
-              info.name, cpu, index, daddr, pkt->addr, pkt->size);
+              info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
 
-    if (pkt->size != info.size)
+    if (pkt->getSize() != info.size)
         panic("write %s (invalid size): "
               "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
-              info.name, cpu, index, daddr, pkt->addr, pkt->size);
+              info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
 
     VirtualReg &vnic = virtualRegs[index];
 
     DPRINTF(EthernetPIO,
             "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n",
             info.name, index, cpu, info.size == 4 ? pkt->get<uint32_t>() :
-            pkt->get<uint64_t>(), daddr, pkt->addr, pkt->size);
+            pkt->get<uint64_t>(), daddr, pkt->getAddr(), pkt->getSize());
 
     prepareWrite(cpu, index);
 
@@ -923,7 +921,7 @@ Device::rxKick()
         break;
 
       case rxBeginCopy:
-        if (dmaPending())
+        if (dmaPending() || getState() != Running)
             goto exit;
 
         rxDmaAddr = params()->platform->pciToDma(
@@ -1111,7 +1109,7 @@ Device::txKick()
         break;
 
       case txBeginCopy:
-        if (dmaPending())
+        if (dmaPending() || getState() != Running)
             goto exit;
 
         txDmaAddr = params()->platform->pciToDma(
@@ -1289,6 +1287,18 @@ Device::recvPacket(EthPacketPtr packet)
     return true;
 }
 
+void
+Device::resume()
+{
+    SimObject::resume();
+
+    // During drain we could have left the state machines in a waiting state and
+    // they wouldn't get out until some other event occured to kick them.
+    // This way they'll get out immediately
+    txKick();
+    rxKick();
+}
+
 //=====================================================================
 //
 //
@@ -1588,24 +1598,24 @@ Device::unserialize(Checkpoint *cp, const std::string &section)
 
 }
 
+/* namespace Sinic */ }
 
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface)
+BEGIN_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic, SinicInterface)
 
     SimObjectParam<EtherInt *> peer;
-    SimObjectParam<Device *> device;
-
-END_DECLARE_SIM_OBJECT_PARAMS(Interface)
+    SimObjectParam<Sinic::Device *> device;
+END_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic, SinicInterface)
 
-BEGIN_INIT_SIM_OBJECT_PARAMS(Interface)
+BEGIN_INIT_SIM_OBJECT_PARAMS_WNS(Sinic, SinicInterface)
 
     INIT_PARAM_DFLT(peer, "peer interface", NULL),
     INIT_PARAM(device, "Ethernet device of this interface")
 
-END_INIT_SIM_OBJECT_PARAMS(Interface)
+END_INIT_SIM_OBJECT_PARAMS_WNS(Sinic, SinicInterface)
 
-CREATE_SIM_OBJECT(Interface)
+CREATE_SIM_OBJECT_WNS(Sinic, SinicInterface)
 {
-    Interface *dev_int = new Interface(getInstanceName(), device);
+    Sinic::Interface *dev_int = new Sinic::Interface(getInstanceName(), device);
 
     EtherInt *p = (EtherInt *)peer;
     if (p) {
@@ -1616,20 +1626,20 @@ CREATE_SIM_OBJECT(Interface)
     return dev_int;
 }
 
-REGISTER_SIM_OBJECT("SinicInt", Interface)
+REGISTER_SIM_OBJECT_WNS(Sinic, "SinicInt", SinicInterface)
 
 
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
+BEGIN_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice)
 
 
     SimObjectParam<System *> system;
     SimObjectParam<Platform *> platform;
-    SimObjectParam<PciConfigAll *> configspace;
     SimObjectParam<PciConfigData *> configdata;
     Param<uint32_t> pci_bus;
     Param<uint32_t> pci_dev;
     Param<uint32_t> pci_func;
     Param<Tick> pio_latency;
+    Param<Tick> config_latency;
     Param<Tick> intr_delay;
 
     Param<Tick> clock;
@@ -1660,19 +1670,19 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
     Param<bool> delay_copy;
     Param<bool> virtual_addr;
 
-END_DECLARE_SIM_OBJECT_PARAMS(Device)
+END_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice)
 
-BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
+BEGIN_INIT_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice)
 
 
     INIT_PARAM(system, "System pointer"),
     INIT_PARAM(platform, "Platform pointer"),
-    INIT_PARAM(configspace, "PCI Configspace"),
     INIT_PARAM(configdata, "PCI Config data"),
     INIT_PARAM(pci_bus, "PCI bus ID"),
     INIT_PARAM(pci_dev, "PCI device number"),
     INIT_PARAM(pci_func, "PCI function code"),
     INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
+    INIT_PARAM(config_latency, "Number of cycles for a config read or write"),
     INIT_PARAM(intr_delay, "Interrupt Delay"),
     INIT_PARAM(clock, "State machine cycle time"),
 
@@ -1703,21 +1713,21 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
     INIT_PARAM(delay_copy, ""),
     INIT_PARAM(virtual_addr, "")
 
-END_INIT_SIM_OBJECT_PARAMS(Device)
+END_INIT_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice)
 
 
-CREATE_SIM_OBJECT(Device)
+CREATE_SIM_OBJECT_WNS(Sinic, SinicDevice)
 {
-    Device::Params *params = new Device::Params;
+    Sinic::Sinic::Device::Params *params = new Device::Params;
     params->name = getInstanceName();
     params->platform = platform;
     params->system = system;
-    params->configSpace = configspace;
     params->configData = configdata;
     params->busNum = pci_bus;
     params->deviceNum = pci_dev;
     params->functionNum = pci_func;
     params->pio_delay = pio_latency;
+    params->config_delay = config_latency;
     params->intr_delay = intr_delay;
     params->clock = clock;
 
@@ -1748,9 +1758,8 @@ CREATE_SIM_OBJECT(Device)
     params->delay_copy = delay_copy;
     params->virtual_addr = virtual_addr;
 
-    return new Device(params);
+    return new Sinic::Device(params);
 }
 
-REGISTER_SIM_OBJECT("Sinic", Device)
+REGISTER_SIM_OBJECT_WNS(Sinic, "Sinic", SinicDevice)
 
-/* namespace Sinic */ }