dev: Move network devices to src/dev/net/
[gem5.git] / src / dev / ide_ctrl.cc
index 3d4e71888ac5171c117ccaf41006c35ed7c49aa3..3e608626575abb2c5082ecf960ffcc4fb88920f1 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2013 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2004-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -32,8 +44,8 @@
 
 #include <string>
 
-#include "base/trace.hh"
 #include "cpu/intr_control.hh"
+#include "debug/IdeCtrl.hh"
 #include "dev/ide_ctrl.hh"
 #include "dev/ide_disk.hh"
 #include "mem/packet.hh"
@@ -41,7 +53,9 @@
 #include "params/IdeController.hh"
 #include "sim/byteswap.hh"
 
-using namespace std;
+// clang complains about std::set being overloaded with Packet::set if
+// we open up the entire namespace std
+using std::string;
 
 // Bus master IDE registers
 enum BMIRegOffset {
@@ -75,18 +89,17 @@ IdeController::Channel::Channel(
 
 IdeController::Channel::~Channel()
 {
-    delete master;
-    delete slave;
 }
 
 IdeController::IdeController(Params *p)
-    : PciDev(p), primary(name() + ".primary", BARSize[0], BARSize[1]),
+    : PciDevice(p), primary(name() + ".primary", BARSize[0], BARSize[1]),
     secondary(name() + ".secondary", BARSize[2], BARSize[3]),
     bmiAddr(0), bmiSize(BARSize[4]),
     primaryTiming(htole(timeRegWithDecodeEn)),
     secondaryTiming(htole(timeRegWithDecodeEn)),
     deviceTiming(0), udmaControl(0), udmaTiming(0), ideConfig(0),
-    ioEnabled(false), bmEnabled(false)
+    ioEnabled(false), bmEnabled(false),
+    ioShift(p->io_shift), ctrlOffset(p->ctrl_offset)
 {
     if (params()->disks.size() > 3)
         panic("IDE controllers support a maximum of 4 devices attached!\n");
@@ -107,6 +120,18 @@ IdeController::IdeController(Params *p)
     }
     primary.select(false);
     secondary.select(false);
+
+    if ((BARAddrs[0] & ~BAR_IO_MASK) && (!legacyIO[0] || ioShift)) {
+        primary.cmdAddr = BARAddrs[0];  primary.cmdSize = BARSize[0];
+        primary.ctrlAddr = BARAddrs[1]; primary.ctrlSize = BARSize[1];
+    }
+    if ((BARAddrs[2] & ~BAR_IO_MASK) && (!legacyIO[2] || ioShift)) {
+        secondary.cmdAddr = BARAddrs[2];  secondary.cmdSize = BARSize[2];
+        secondary.ctrlAddr = BARAddrs[3]; secondary.ctrlSize = BARSize[3];
+    }
+
+    ioEnabled = (config.command & htole(PCI_CMD_IOSE));
+    bmEnabled = (config.command & htole(PCI_CMD_BME));
 }
 
 bool
@@ -119,7 +144,7 @@ void
 IdeController::intrPost()
 {
     primary.bmiRegs.status.intStatus = 1;
-    PciDev::intrPost();
+    PciDevice::intrPost();
 }
 
 void
@@ -144,11 +169,9 @@ IdeController::readConfig(PacketPtr pkt)
 {
     int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
     if (offset < PCI_DEVICE_SPECIFIC) {
-        return PciDev::readConfig(pkt);
+        return PciDevice::readConfig(pkt);
     }
 
-    pkt->allocate();
-
     switch (pkt->getSize()) {
       case sizeof(uint8_t):
         switch (offset) {
@@ -179,6 +202,9 @@ IdeController::readConfig(PacketPtr pkt)
         break;
       case sizeof(uint16_t):
         switch (offset) {
+          case UDMAControl:
+            pkt->set<uint16_t>(udmaControl);
+            break;
           case PrimaryTiming:
             pkt->set<uint16_t>(primaryTiming);
             break;
@@ -199,7 +225,16 @@ IdeController::readConfig(PacketPtr pkt)
                 (uint32_t)pkt->get<uint16_t>());
         break;
       case sizeof(uint32_t):
-        panic("No 32bit reads implemented for this device.");
+        switch (offset) {
+          case PrimaryTiming:
+            pkt->set<uint32_t>(primaryTiming);
+            break;
+          case IDEConfig:
+            pkt->set<uint32_t>(ideConfig);
+            break;
+          default:
+            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;
@@ -216,7 +251,7 @@ IdeController::writeConfig(PacketPtr pkt)
 {
     int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
     if (offset < PCI_DEVICE_SPECIFIC) {
-        PciDev::writeConfig(pkt);
+        PciDevice::writeConfig(pkt);
     } else {
         switch (pkt->getSize()) {
           case sizeof(uint8_t):
@@ -242,6 +277,9 @@ IdeController::writeConfig(PacketPtr pkt)
             break;
           case sizeof(uint16_t):
             switch (offset) {
+              case UDMAControl:
+                udmaControl = pkt->get<uint16_t>();
+                break;
               case PrimaryTiming:
                 primaryTiming = pkt->get<uint16_t>();
                 break;
@@ -263,7 +301,16 @@ IdeController::writeConfig(PacketPtr pkt)
                     offset, (uint32_t)pkt->get<uint16_t>());
             break;
           case sizeof(uint32_t):
-            panic("Write of unimplemented PCI config. register: %x\n", offset);
+            switch (offset) {
+              case PrimaryTiming:
+                primaryTiming = pkt->get<uint32_t>();
+                break;
+              case IDEConfig:
+                ideConfig = pkt->get<uint32_t>();
+                break;
+              default:
+                panic("Write of unimplemented PCI config. register: %x\n", offset);
+            }
             break;
           default:
             panic("invalid access size(?) for PCI configspace!\n");
@@ -300,6 +347,7 @@ IdeController::writeConfig(PacketPtr pkt)
         break;
 
       case PCI_COMMAND:
+        DPRINTF(IdeCtrl, "Writing to PCI Command val: %#x\n", config.command);
         ioEnabled = (config.command & htole(PCI_CMD_IOSE));
         bmEnabled = (config.command & htole(PCI_CMD_BME));
         break;
@@ -394,14 +442,21 @@ IdeController::Channel::accessBMI(Addr offset,
                 newVal.active = oldVal.active;
 
                 // to reset (set 0) IDEINTS and IDEDMAE, write 1 to each
-                if (oldVal.intStatus && newVal.intStatus)
+                if ((oldVal.intStatus == 1) && (newVal.intStatus == 1)) {
                     newVal.intStatus = 0; // clear the interrupt?
-                else
-                    newVal.intStatus = oldVal.intStatus;
-                if (oldVal.dmaError && newVal.dmaError)
+                } else {
+                    // Assigning two bitunion fields to each other does not
+                    // work as intended, so we need to use this temporary variable
+                    // to get around the bug.
+                    uint8_t tmp = oldVal.intStatus;
+                    newVal.intStatus = tmp;
+                }
+                if ((oldVal.dmaError == 1) && (newVal.dmaError == 1)) {
                     newVal.dmaError = 0;
-                else
-                    newVal.dmaError = oldVal.dmaError;
+                } else {
+                    uint8_t tmp = oldVal.dmaError;
+                    newVal.dmaError = tmp;
+                }
 
                 bmiRegs.status = newVal;
             }
@@ -423,7 +478,6 @@ IdeController::Channel::accessBMI(Addr offset,
 void
 IdeController::dispatchAccess(PacketPtr pkt, bool read)
 {
-    pkt->allocate();
     if (pkt->getSize() != 1 && pkt->getSize() != 2 && pkt->getSize() !=4)
          panic("Bad IDE read size: %d\n", pkt->getSize());
 
@@ -440,10 +494,14 @@ IdeController::dispatchAccess(PacketPtr pkt, bool read)
     if (addr >= primary.cmdAddr &&
             addr < (primary.cmdAddr + primary.cmdSize)) {
         addr -= primary.cmdAddr;
+        // linux may have shifted the address by ioShift,
+        // here we shift it back, similarly for ctrlOffset.
+        addr >>= ioShift;
         primary.accessCommand(addr, size, dataPtr, read);
     } else if (addr >= primary.ctrlAddr &&
                addr < (primary.ctrlAddr + primary.ctrlSize)) {
         addr -= primary.ctrlAddr;
+        addr += ctrlOffset;
         primary.accessControl(addr, size, dataPtr, read);
     } else if (addr >= secondary.cmdAddr &&
                addr < (secondary.cmdAddr + secondary.cmdSize)) {
@@ -467,6 +525,7 @@ IdeController::dispatchAccess(PacketPtr pkt, bool read)
         panic("IDE controller access to invalid address: %#x\n", addr);
     }
 
+#ifndef NDEBUG
     uint32_t data;
     if (pkt->getSize() == 1)
         data = pkt->get<uint8_t>();
@@ -476,6 +535,7 @@ IdeController::dispatchAccess(PacketPtr pkt, bool read)
         data = pkt->get<uint32_t>();
     DPRINTF(IdeCtrl, "%s from offset: %#x size: %#x data: %#x\n",
             read ? "Read" : "Write", pkt->getAddr(), pkt->getSize(), data);
+#endif
 
     pkt->makeAtomicResponse();
 }
@@ -495,14 +555,14 @@ IdeController::write(PacketPtr pkt)
 }
 
 void
-IdeController::serialize(std::ostream &os)
+IdeController::serialize(CheckpointOut &cp) const
 {
-    // Serialize the PciDev base class
-    PciDev::serialize(os);
+    // Serialize the PciDevice base class
+    PciDevice::serialize(cp);
 
     // Serialize channels
-    primary.serialize("primary", os);
-    secondary.serialize("secondary", os);
+    primary.serialize("primary", cp);
+    secondary.serialize("secondary", cp);
 
     // Serialize config registers
     SERIALIZE_SCALAR(primaryTiming);
@@ -520,31 +580,32 @@ IdeController::serialize(std::ostream &os)
 }
 
 void
-IdeController::Channel::serialize(const std::string &base, std::ostream &os)
+IdeController::Channel::serialize(const std::string &base,
+                                  CheckpointOut &cp) const
 {
-    paramOut(os, base + ".cmdAddr", cmdAddr);
-    paramOut(os, base + ".cmdSize", cmdSize);
-    paramOut(os, base + ".ctrlAddr", ctrlAddr);
-    paramOut(os, base + ".ctrlSize", ctrlSize);
+    paramOut(cp, base + ".cmdAddr", cmdAddr);
+    paramOut(cp, base + ".cmdSize", cmdSize);
+    paramOut(cp, base + ".ctrlAddr", ctrlAddr);
+    paramOut(cp, base + ".ctrlSize", ctrlSize);
     uint8_t command = bmiRegs.command;
-    paramOut(os, base + ".bmiRegs.command", command);
-    paramOut(os, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
+    paramOut(cp, base + ".bmiRegs.command", command);
+    paramOut(cp, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
     uint8_t status = bmiRegs.status;
-    paramOut(os, base + ".bmiRegs.status", status);
-    paramOut(os, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
-    paramOut(os, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
-    paramOut(os, base + ".selectBit", selectBit);
+    paramOut(cp, base + ".bmiRegs.status", status);
+    paramOut(cp, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
+    paramOut(cp, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
+    paramOut(cp, base + ".selectBit", selectBit);
 }
 
 void
-IdeController::unserialize(Checkpoint *cp, const std::string &section)
+IdeController::unserialize(CheckpointIn &cp)
 {
-    // Unserialize the PciDev base class
-    PciDev::unserialize(cp, section);
+    // Unserialize the PciDevice base class
+    PciDevice::unserialize(cp);
 
     // Unserialize channels
-    primary.unserialize("primary", cp, section);
-    secondary.unserialize("secondary", cp, section);
+    primary.unserialize("primary", cp);
+    secondary.unserialize("secondary", cp);
 
     // Unserialize config registers
     UNSERIALIZE_SCALAR(primaryTiming);
@@ -562,23 +623,22 @@ IdeController::unserialize(Checkpoint *cp, const std::string &section)
 }
 
 void
-IdeController::Channel::unserialize(const std::string &base, Checkpoint *cp,
-    const std::string &section)
+IdeController::Channel::unserialize(const std::string &base, CheckpointIn &cp)
 {
-    paramIn(cp, section, base + ".cmdAddr", cmdAddr);
-    paramIn(cp, section, base + ".cmdSize", cmdSize);
-    paramIn(cp, section, base + ".ctrlAddr", ctrlAddr);
-    paramIn(cp, section, base + ".ctrlSize", ctrlSize);
+    paramIn(cp, base + ".cmdAddr", cmdAddr);
+    paramIn(cp, base + ".cmdSize", cmdSize);
+    paramIn(cp, base + ".ctrlAddr", ctrlAddr);
+    paramIn(cp, base + ".ctrlSize", ctrlSize);
     uint8_t command;
-    paramIn(cp, section, base +".bmiRegs.command", command);
+    paramIn(cp, base +".bmiRegs.command", command);
     bmiRegs.command = command;
-    paramIn(cp, section, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
+    paramIn(cp, base + ".bmiRegs.reserved0", bmiRegs.reserved0);
     uint8_t status;
-    paramIn(cp, section, base + ".bmiRegs.status", status);
+    paramIn(cp, base + ".bmiRegs.status", status);
     bmiRegs.status = status;
-    paramIn(cp, section, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
-    paramIn(cp, section, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
-    paramIn(cp, section, base + ".selectBit", selectBit);
+    paramIn(cp, base + ".bmiRegs.reserved1", bmiRegs.reserved1);
+    paramIn(cp, base + ".bmiRegs.bmidtp", bmiRegs.bmidtp);
+    paramIn(cp, base + ".selectBit", selectBit);
     select(selectBit);
 }