SINIC: Commit old code from ASPLOS 2006 studies.
[gem5.git] / src / dev / ide_ctrl.cc
index d8dff0870f63f649d3fec0ae4079e82988cf3caf..6d7f1baf1c80448253313df0116076b9d8c1aae3 100644 (file)
  * 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: Andrew Schultz
+ *          Ali Saidi
+ *          Miguel Serrano
  */
 
 #include <cstddef>
@@ -39,7 +43,8 @@
 #include "dev/pcireg.h"
 #include "dev/platform.hh"
 #include "mem/packet.hh"
-#include "sim/builder.hh"
+#include "mem/packet_access.hh"
+#include "params/IdeController.hh"
 #include "sim/sim_object.hh"
 #include "sim/byteswap.hh"
 
@@ -223,177 +228,145 @@ IdeController::setDmaComplete(IdeDisk *disk)
 // Read and write handling
 ////
 
-void
-IdeController::readConfig(int offset, uint8_t *data)
+Tick
+IdeController::readConfig(PacketPtr pkt)
 {
+    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
     if (offset < PCI_DEVICE_SPECIFIC) {
-        PciDev::readConfig(offset, data);
-    } else if (offset >= IDE_CTRL_CONF_START &&
-               (offset + 1) <= IDE_CTRL_CONF_END) {
+        return PciDev::readConfig(pkt);
+    }
 
+    assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END);
+
+    pkt->allocate();
+
+    switch (pkt->getSize()) {
+      case sizeof(uint8_t):
         switch (offset) {
           case IDE_CTRL_CONF_DEV_TIMING:
-            *data = config_regs.sidetim;
+            pkt->set<uint8_t>(config_regs.sidetim);
             break;
           case IDE_CTRL_CONF_UDMA_CNTRL:
-            *data = config_regs.udmactl;
+            pkt->set<uint8_t>(config_regs.udmactl);
             break;
           case IDE_CTRL_CONF_PRIM_TIMING+1:
-            *data = htole(config_regs.idetim0) >> 8;
+            pkt->set<uint8_t>(htole(config_regs.idetim0) >> 8);
             break;
           case IDE_CTRL_CONF_SEC_TIMING+1:
-            *data = htole(config_regs.idetim1) >> 8;
+            pkt->set<uint8_t>(htole(config_regs.idetim1) >> 8);
             break;
           case IDE_CTRL_CONF_IDE_CONFIG:
-            *data = htole(config_regs.ideconfig) & 0xFF;
+            pkt->set<uint8_t>(htole(config_regs.ideconfig) & 0xFF);
             break;
           case IDE_CTRL_CONF_IDE_CONFIG+1:
-            *data = htole(config_regs.ideconfig) >> 8;
+            pkt->set<uint8_t>(htole(config_regs.ideconfig) >> 8);
             break;
           default:
             panic("Invalid PCI configuration read for size 1 at offset: %#x!\n",
                     offset);
         }
-
-    } else {
-        panic("Read of unimplemented PCI config. register: %x\n", offset);
-    }
-    DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n",
-                offset, (uint32_t)*data);
-}
-
-void
-IdeController::readConfig(int offset, uint16_t *data)
-{
-    if (offset < PCI_DEVICE_SPECIFIC) {
-        PciDev::readConfig(offset, data);
-    } else if (offset >= IDE_CTRL_CONF_START &&
-               (offset + 2) <= IDE_CTRL_CONF_END) {
-
+        DPRINTF(IdeCtrl, "PCI read offset: %#x size: 1 data: %#x\n", offset,
+                (uint32_t)pkt->get<uint8_t>());
+        break;
+      case sizeof(uint16_t):
         switch (offset) {
           case IDE_CTRL_CONF_PRIM_TIMING:
-            *data = config_regs.idetim0;
+            pkt->set<uint16_t>(config_regs.idetim0);
             break;
           case IDE_CTRL_CONF_SEC_TIMING:
-            *data = config_regs.idetim1;
+            pkt->set<uint16_t>(config_regs.idetim1);
             break;
           case IDE_CTRL_CONF_UDMA_TIMING:
-            *data = config_regs.udmatim;
+            pkt->set<uint16_t>(config_regs.udmatim);
             break;
           case IDE_CTRL_CONF_IDE_CONFIG:
-            *data = config_regs.ideconfig;
+            pkt->set<uint16_t>(config_regs.ideconfig);
             break;
           default:
             panic("Invalid PCI configuration read for size 2 offset: %#x!\n",
                     offset);
         }
-
-    } else {
-        panic("Read of unimplemented PCI config. register: %x\n", offset);
+        DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset,
+                (uint32_t)pkt->get<uint16_t>());
+        break;
+      case sizeof(uint32_t):
+        panic("No 32bit reads implemented for this device.");
+        DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset,
+                (uint32_t)pkt->get<uint32_t>());
+        break;
+      default:
+        panic("invalid access size(?) for PCI configspace!\n");
     }
-    DPRINTF(IdeCtrl, "PCI read offset: %#x size: 2 data: %#x\n", offset, *data);
+    pkt->makeAtomicResponse();
+    return configDelay;
 }
 
-void
-IdeController::readConfig(int offset, uint32_t *data)
-{
-    if (offset < PCI_DEVICE_SPECIFIC) {
-        PciDev::readConfig(offset, data);
-    } else {
-        panic("Read of unimplemented PCI config. register: %x\n", offset);
-    }
-    DPRINTF(IdeCtrl, "PCI read offset: %#x size: 4 data: %#x\n", offset, *data);
-}
-void
-IdeController::writeConfig(int offset, const uint8_t data)
-{
-    if (offset < PCI_DEVICE_SPECIFIC) {
-        PciDev::writeConfig(offset, data);
-    } else if (offset >= IDE_CTRL_CONF_START &&
-               (offset + 1) <= IDE_CTRL_CONF_END) {
 
-        switch (offset) {
-          case IDE_CTRL_CONF_DEV_TIMING:
-            config_regs.sidetim = data;
-            break;
-          case IDE_CTRL_CONF_UDMA_CNTRL:
-            config_regs.udmactl = data;
-            break;
-          case IDE_CTRL_CONF_IDE_CONFIG:
-            config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) | (data);
-            break;
-          case IDE_CTRL_CONF_IDE_CONFIG+1:
-            config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) | data << 8;
-            break;
-          default:
-            panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
-                    offset);
-        }
-
-    } else {
-        panic("Read of unimplemented PCI config. register: %x\n", offset);
-    }
-    DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n",
-                offset, (uint32_t)data);
-}
-
-void
-IdeController::writeConfig(int offset, const uint16_t data)
+Tick
+IdeController::writeConfig(PacketPtr pkt)
 {
+    int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
     if (offset < PCI_DEVICE_SPECIFIC) {
-        PciDev::writeConfig(offset, data);
-    } else if (offset >= IDE_CTRL_CONF_START &&
-               (offset + 2) <= IDE_CTRL_CONF_END) {
+        PciDev::writeConfig(pkt);
+    } else {
+        assert(offset >= IDE_CTRL_CONF_START && (offset + 1) <= IDE_CTRL_CONF_END);
 
-        switch (offset) {
-          case IDE_CTRL_CONF_PRIM_TIMING:
-            config_regs.idetim0 = data;
-            break;
-          case IDE_CTRL_CONF_SEC_TIMING:
-            config_regs.idetim1 = data;
+        switch (pkt->getSize()) {
+          case sizeof(uint8_t):
+            switch (offset) {
+              case IDE_CTRL_CONF_DEV_TIMING:
+                config_regs.sidetim = pkt->get<uint8_t>();
+                break;
+              case IDE_CTRL_CONF_UDMA_CNTRL:
+                config_regs.udmactl = pkt->get<uint8_t>();
+                break;
+              case IDE_CTRL_CONF_IDE_CONFIG:
+                config_regs.ideconfig = (config_regs.ideconfig & 0xFF00) |
+                    (pkt->get<uint8_t>());
+                break;
+              case IDE_CTRL_CONF_IDE_CONFIG+1:
+                config_regs.ideconfig = (config_regs.ideconfig & 0x00FF) |
+                    pkt->get<uint8_t>() << 8;
+                break;
+              default:
+                panic("Invalid PCI configuration write for size 1 offset: %#x!\n",
+                        offset);
+            }
+            DPRINTF(IdeCtrl, "PCI write offset: %#x size: 1 data: %#x\n",
+                    offset, (uint32_t)pkt->get<uint8_t>());
             break;
-          case IDE_CTRL_CONF_UDMA_TIMING:
-            config_regs.udmatim = data;
+          case sizeof(uint16_t):
+            switch (offset) {
+              case IDE_CTRL_CONF_PRIM_TIMING:
+                config_regs.idetim0 = pkt->get<uint16_t>();
+                break;
+              case IDE_CTRL_CONF_SEC_TIMING:
+                config_regs.idetim1 = pkt->get<uint16_t>();
+                break;
+              case IDE_CTRL_CONF_UDMA_TIMING:
+                config_regs.udmatim = pkt->get<uint16_t>();
+                break;
+              case IDE_CTRL_CONF_IDE_CONFIG:
+                config_regs.ideconfig = pkt->get<uint16_t>();
+                break;
+              default:
+                panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
+                        offset);
+            }
+            DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n",
+                    offset, (uint32_t)pkt->get<uint16_t>());
             break;
-          case IDE_CTRL_CONF_IDE_CONFIG:
-            config_regs.ideconfig = data;
+          case sizeof(uint32_t):
+            panic("Write of unimplemented PCI config. register: %x\n", offset);
             break;
           default:
-            panic("Invalid PCI configuration write for size 2 offset: %#x!\n",
-                    offset);
+            panic("invalid access size(?) for PCI configspace!\n");
         }
-
-    } else {
-        panic("Write of unimplemented PCI config. register: %x\n", offset);
-    }
-    DPRINTF(IdeCtrl, "PCI write offset: %#x size: 2 data: %#x\n", offset, data);
-
-    /* Trap command register writes and enable IO/BM as appropriate. */
-    if (offset == PCI_COMMAND) {
-        if (letoh(config.command) & PCI_CMD_IOSE)
-            io_enabled = true;
-        else
-            io_enabled = false;
-
-        if (letoh(config.command) & PCI_CMD_BME)
-            bm_enabled = true;
-        else
-            bm_enabled = false;
-    }
-
-}
-
-void
-IdeController::writeConfig(int offset, const uint32_t data)
-{
-    if (offset < PCI_DEVICE_SPECIFIC) {
-        PciDev::writeConfig(offset, data);
-    } else {
-        panic("Read of unimplemented PCI config. register: %x\n", offset);
+        pkt->makeAtomicResponse();
     }
 
-    DPRINTF(IdeCtrl, "PCI write offset: %#x size: 4 data: %#x\n", offset, data);
-
+    /* Trap command register writes and enable IO/BM as appropriate as well as
+     * BARs. */
     switch(offset) {
       case PCI0_BASE_ADDR0:
         if (BARAddrs[0] != 0)
@@ -419,11 +392,25 @@ IdeController::writeConfig(int offset, const uint32_t data)
         if (BARAddrs[4] != 0)
             bmi_addr = BARAddrs[4];
         break;
+
+      case PCI_COMMAND:
+        if (letoh(config.command) & PCI_CMD_IOSE)
+            io_enabled = true;
+        else
+            io_enabled = false;
+
+        if (letoh(config.command) & PCI_CMD_BME)
+            bm_enabled = true;
+        else
+            bm_enabled = false;
+        break;
     }
+    return configDelay;
 }
 
+
 Tick
-IdeController::read(Packet *pkt)
+IdeController::read(PacketPtr pkt)
 {
     Addr offset;
     IdeChannel channel;
@@ -437,7 +424,7 @@ IdeController::read(Packet *pkt)
     parseAddr(pkt->getAddr(), offset, channel, reg_type);
 
     if (!io_enabled) {
-        pkt->result = Packet::Success;
+        pkt->makeAtomicResponse();
         return pioDelay;
     }
 
@@ -504,12 +491,12 @@ IdeController::read(Packet *pkt)
     DPRINTF(IdeCtrl, "read from offset: %#x size: %#x data: %#x\n",
             offset, pkt->getSize(), pkt->get<uint32_t>());
 
-    pkt->result = Packet::Success;
+    pkt->makeAtomicResponse();
     return pioDelay;
 }
 
 Tick
-IdeController::write(Packet *pkt)
+IdeController::write(PacketPtr pkt)
 {
     Addr offset;
     IdeChannel channel;
@@ -520,7 +507,7 @@ IdeController::write(Packet *pkt)
     parseAddr(pkt->getAddr(), offset, channel, reg_type);
 
     if (!io_enabled) {
-        pkt->result = Packet::Success;
+        pkt->makeAtomicResponse();
         DPRINTF(IdeCtrl, "io not enabled\n");
         return pioDelay;
     }
@@ -528,7 +515,7 @@ IdeController::write(Packet *pkt)
     switch (reg_type) {
       case BMI_BLOCK:
         if (!bm_enabled) {
-            pkt->result = Packet::Success;
+            pkt->makeAtomicResponse();
             return pioDelay;
         }
 
@@ -687,7 +674,7 @@ IdeController::write(Packet *pkt)
             offset, pkt->getSize(), pkt->get<uint32_t>());
 
 
-    pkt->result = Packet::Success;
+    pkt->makeAtomicResponse();
     return pioDelay;
 }
 
@@ -757,55 +744,10 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
     UNSERIALIZE_SCALAR(bm_enabled);
     UNSERIALIZE_ARRAY(cmd_in_progress,
                       sizeof(cmd_in_progress) / sizeof(cmd_in_progress[0]));
-    pioPort->sendStatusChange(Port::RangeChange);
 }
 
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeController)
-
-    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;
-    SimObjectVectorParam<IdeDisk *> disks;
-
-END_DECLARE_SIM_OBJECT_PARAMS(IdeController)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(IdeController)
-
-    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(disks, "IDE disks attached to this controller")
-
-END_INIT_SIM_OBJECT_PARAMS(IdeController)
-
-CREATE_SIM_OBJECT(IdeController)
+IdeController *
+IdeControllerParams::create()
 {
-    IdeController::Params *params = new IdeController::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->disks = disks;
-    return new IdeController(params);
+    return new IdeController(this);
 }
-
-REGISTER_SIM_OBJECT("IdeController", IdeController)
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS