Thread: Use inherited baseCpu rather than cpu in SimpleThread
[gem5.git] / src / dev / ide_disk.cc
index 9fa0cedded139a6f166e8befb4cb1e6a9b34d8a8..f0c8c8668e3c1c8c8e71c110238a3bd9fe71a6a4 100644 (file)
 #include <deque>
 #include <string>
 
+#include "arch/isa_traits.hh"
 #include "base/chunk_generator.hh"
 #include "base/cprintf.hh" // csprintf
 #include "base/trace.hh"
+#include "config/the_isa.hh"
+#include "debug/IdeDisk.hh"
 #include "dev/disk_image.hh"
-#include "dev/ide_disk.hh"
 #include "dev/ide_ctrl.hh"
-#include "dev/alpha/tsunami.hh"
-#include "dev/alpha/tsunami_pchip.hh"
-#include "sim/builder.hh"
-#include "sim/sim_object.hh"
+#include "dev/ide_disk.hh"
 #include "sim/core.hh"
-#include "arch/isa_traits.hh"
+#include "sim/sim_object.hh"
 
 using namespace std;
 using namespace TheISA;
 
-IdeDisk::IdeDisk(const string &name, DiskImage *img,
-                 int id, Tick delay)
-    : SimObject(name), ctrl(NULL), image(img), diskDelay(delay),
+IdeDisk::IdeDisk(const Params *p)
+    : SimObject(p), ctrl(NULL), image(p->image), diskDelay(p->delay),
       dmaTransferEvent(this), dmaReadCG(NULL), dmaReadWaitEvent(this),
       dmaWriteCG(NULL), dmaWriteWaitEvent(this), dmaPrdReadEvent(this),
       dmaReadEvent(this), dmaWriteEvent(this)
 {
     // Reset the device state
-    reset(id);
+    reset(p->driveID);
 
     // fill out the drive ID structure
     memset(&driveID, 0, sizeof(struct ataparams));
@@ -181,7 +179,7 @@ Addr
 IdeDisk::pciToDma(Addr pciAddr)
 {
     if (ctrl)
-        return ctrl->plat->pciToDma(pciAddr);
+        return ctrl->pciToDma(pciAddr);
     else
         panic("Access to unset controller!\n");
 }
@@ -191,120 +189,127 @@ IdeDisk::pciToDma(Addr pciAddr)
 ////
 
 void
-IdeDisk::read(const Addr &offset, IdeRegType reg_type, uint8_t *data)
+IdeDisk::readCommand(const Addr offset, int size, uint8_t *data)
 {
-    DevAction_t action = ACT_NONE;
-
-    switch (reg_type) {
-      case COMMAND_BLOCK:
-        switch (offset) {
-          // Data transfers occur two bytes at a time
-          case DATA_OFFSET:
-            *(uint16_t*)data = cmdReg.data;
-            action = ACT_DATA_READ_SHORT;
-            break;
-          case ERROR_OFFSET:
-            *data = cmdReg.error;
-            break;
-          case NSECTOR_OFFSET:
-            *data = cmdReg.sec_count;
-            break;
-          case SECTOR_OFFSET:
-            *data = cmdReg.sec_num;
-            break;
-          case LCYL_OFFSET:
-            *data = cmdReg.cyl_low;
-            break;
-          case HCYL_OFFSET:
-            *data = cmdReg.cyl_high;
-            break;
-          case DRIVE_OFFSET:
-            *data = cmdReg.drive;
-            break;
-          case STATUS_OFFSET:
-            *data = status;
-            action = ACT_STAT_READ;
-            break;
-          default:
-            panic("Invalid IDE command register offset: %#x\n", offset);
+    if (offset == DATA_OFFSET) {
+        if (size == sizeof(uint16_t)) {
+            *(uint16_t *)data = cmdReg.data;
+        } else if (size == sizeof(uint32_t)) {
+            *(uint16_t *)data = cmdReg.data;
+            updateState(ACT_DATA_READ_SHORT);
+            *((uint16_t *)data + 1) = cmdReg.data;
+        } else {
+            panic("Data read of unsupported size %d.\n", size);
         }
+        updateState(ACT_DATA_READ_SHORT);
+        return;
+    }
+    assert(size == sizeof(uint8_t));
+    switch (offset) {
+      case ERROR_OFFSET:
+        *data = cmdReg.error;
         break;
-      case CONTROL_BLOCK:
-        if (offset == ALTSTAT_OFFSET)
-            *data = status;
-        else
-            panic("Invalid IDE control register offset: %#x\n", offset);
+      case NSECTOR_OFFSET:
+        *data = cmdReg.sec_count;
+        break;
+      case SECTOR_OFFSET:
+        *data = cmdReg.sec_num;
+        break;
+      case LCYL_OFFSET:
+        *data = cmdReg.cyl_low;
+        break;
+      case HCYL_OFFSET:
+        *data = cmdReg.cyl_high;
+        break;
+      case DRIVE_OFFSET:
+        *data = cmdReg.drive;
+        break;
+      case STATUS_OFFSET:
+        *data = status;
+        updateState(ACT_STAT_READ);
         break;
       default:
-        panic("Unknown register block!\n");
+        panic("Invalid IDE command register offset: %#x\n", offset);
     }
-    DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset,
-            (uint32_t)*data);
-
-    if (action != ACT_NONE)
-        updateState(action);
+    DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset, *data);
 }
 
 void
-IdeDisk::write(const Addr &offset, IdeRegType reg_type, const uint8_t *data)
+IdeDisk::readControl(const Addr offset, int size, uint8_t *data)
 {
-    DevAction_t action = ACT_NONE;
+    assert(size == sizeof(uint8_t));
+    *data = status;
+    if (offset != ALTSTAT_OFFSET)
+        panic("Invalid IDE control register offset: %#x\n", offset);
+    DPRINTF(IdeDisk, "Read to disk at offset: %#x data %#x\n", offset, *data);
+}
 
-    switch (reg_type) {
-      case COMMAND_BLOCK:
-        switch (offset) {
-          case DATA_OFFSET:
-            cmdReg.data = *(uint16_t*)data;
-            action = ACT_DATA_WRITE_SHORT;
-            break;
-          case FEATURES_OFFSET:
-            break;
-          case NSECTOR_OFFSET:
-            cmdReg.sec_count = *data;
-            break;
-          case SECTOR_OFFSET:
-            cmdReg.sec_num = *data;
-            break;
-          case LCYL_OFFSET:
-            cmdReg.cyl_low = *data;
-            break;
-          case HCYL_OFFSET:
-            cmdReg.cyl_high = *data;
-            break;
-          case DRIVE_OFFSET:
-            cmdReg.drive = *data;
-            action = ACT_SELECT_WRITE;
-            break;
-          case COMMAND_OFFSET:
-            cmdReg.command = *data;
-            action = ACT_CMD_WRITE;
-            break;
-          default:
-            panic("Invalid IDE command register offset: %#x\n", offset);
+void
+IdeDisk::writeCommand(const Addr offset, int size, const uint8_t *data)
+{
+    if (offset == DATA_OFFSET) {
+        if (size == sizeof(uint16_t)) {
+            cmdReg.data = *(const uint16_t *)data;
+        } else if (size == sizeof(uint32_t)) {
+            cmdReg.data = *(const uint16_t *)data;
+            updateState(ACT_DATA_WRITE_SHORT);
+            cmdReg.data = *((const uint16_t *)data + 1);
+        } else {
+            panic("Data write of unsupported size %d.\n", size);
         }
+        updateState(ACT_DATA_WRITE_SHORT);
+        return;
+    }
+
+    assert(size == sizeof(uint8_t));
+    switch (offset) {
+      case FEATURES_OFFSET:
         break;
-      case CONTROL_BLOCK:
-        if (offset == CONTROL_OFFSET) {
-            if (*data & CONTROL_RST_BIT) {
-                // force the device into the reset state
-                devState = Device_Srst;
-                action = ACT_SRST_SET;
-            } else if (devState == Device_Srst && !(*data & CONTROL_RST_BIT))
-                action = ACT_SRST_CLEAR;
-
-            nIENBit = (*data & CONTROL_IEN_BIT) ? true : false;
-        }
-        else
-            panic("Invalid IDE control register offset: %#x\n", offset);
+      case NSECTOR_OFFSET:
+        cmdReg.sec_count = *data;
+        break;
+      case SECTOR_OFFSET:
+        cmdReg.sec_num = *data;
+        break;
+      case LCYL_OFFSET:
+        cmdReg.cyl_low = *data;
+        break;
+      case HCYL_OFFSET:
+        cmdReg.cyl_high = *data;
+        break;
+      case DRIVE_OFFSET:
+        cmdReg.drive = *data;
+        updateState(ACT_SELECT_WRITE);
+        break;
+      case COMMAND_OFFSET:
+        cmdReg.command = *data;
+        updateState(ACT_CMD_WRITE);
         break;
       default:
-        panic("Unknown register block!\n");
+        panic("Invalid IDE command register offset: %#x\n", offset);
+    }
+    DPRINTF(IdeDisk, "Write to disk at offset: %#x data %#x\n", offset,
+            (uint32_t)*data);
+}
+
+void
+IdeDisk::writeControl(const Addr offset, int size, const uint8_t *data)
+{
+    if (offset != CONTROL_OFFSET)
+        panic("Invalid IDE control register offset: %#x\n", offset);
+
+    if (*data & CONTROL_RST_BIT) {
+        // force the device into the reset state
+        devState = Device_Srst;
+        updateState(ACT_SRST_SET);
+    } else if (devState == Device_Srst && !(*data & CONTROL_RST_BIT)) {
+        updateState(ACT_SRST_CLEAR);
     }
 
+    nIENBit = *data & CONTROL_IEN_BIT;
+
     DPRINTF(IdeDisk, "Write to disk at offset: %#x data %#x\n", offset,
             (uint32_t)*data);
-    if (action != ACT_NONE)
-        updateState(action);
 }
 
 ////
@@ -319,7 +324,7 @@ IdeDisk::doDmaTransfer()
               dmaState, devState);
 
     if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
-        dmaTransferEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
+        schedule(dmaTransferEvent, curTick() + DMA_BACKOFF_PERIOD);
         return;
     } else
         ctrl->dmaRead(curPrdAddr, sizeof(PrdEntry_t), &dmaPrdReadEvent,
@@ -329,6 +334,7 @@ IdeDisk::doDmaTransfer()
 void
 IdeDisk::dmaPrdReadDone()
 {
+
     DPRINTF(IdeDisk,
             "PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
             curPrd.getBaseAddr(), pciToDma(curPrd.getBaseAddr()),
@@ -353,7 +359,7 @@ IdeDisk::doDmaDataRead()
     DPRINTF(IdeDisk, "doDmaRead, diskDelay: %d totalDiskDelay: %d\n",
             diskDelay, totalDiskDelay);
 
-    dmaReadWaitEvent.schedule(curTick + totalDiskDelay);
+    schedule(dmaReadWaitEvent, curTick() + totalDiskDelay);
 }
 
 void
@@ -399,7 +405,7 @@ IdeDisk::doDmaRead()
 
     }
     if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
-        dmaReadWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
+        schedule(dmaReadWaitEvent, curTick() + DMA_BACKOFF_PERIOD);
         return;
     } else if (!dmaReadCG->done()) {
         assert(dmaReadCG->complete() < MAX_DMA_SIZE);
@@ -460,32 +466,39 @@ IdeDisk::doDmaDataWrite()
         bytesRead += SectorSize;
         cmdBytesLeft -= SectorSize;
     }
+    DPRINTF(IdeDisk, "doDmaWrite, bytesRead: %d cmdBytesLeft: %d\n",
+            bytesRead, cmdBytesLeft);
 
-    dmaWriteWaitEvent.schedule(curTick + totalDiskDelay);
+    schedule(dmaWriteWaitEvent, curTick() + totalDiskDelay);
 }
 
 void
 IdeDisk::doDmaWrite()
 {
-
+    DPRINTF(IdeDisk, "doDmaWrite: rescheduling\n");
     if (!dmaWriteCG) {
         // clear out the data buffer
         dmaWriteCG = new ChunkGenerator(curPrd.getBaseAddr(),
                 curPrd.getByteCount(), TheISA::PageBytes);
     }
     if (ctrl->dmaPending() || ctrl->getState() != SimObject::Running) {
-        dmaWriteWaitEvent.schedule(curTick + DMA_BACKOFF_PERIOD);
+        schedule(dmaWriteWaitEvent, curTick() + DMA_BACKOFF_PERIOD);
+        DPRINTF(IdeDisk, "doDmaWrite: rescheduling\n");
         return;
     } else if (!dmaWriteCG->done()) {
         assert(dmaWriteCG->complete() < MAX_DMA_SIZE);
         ctrl->dmaWrite(pciToDma(dmaWriteCG->addr()), dmaWriteCG->size(),
                 &dmaWriteWaitEvent, dataBuffer + dmaWriteCG->complete());
+        DPRINTF(IdeDisk, "doDmaWrite: not done curPrd byte count %d, eot %#x\n",
+                curPrd.getByteCount(), curPrd.getEOT());
         dmaWriteBytes += dmaWriteCG->size();
         dmaWriteTxs++;
         if (dmaWriteCG->size() == TheISA::PageBytes)
             dmaWriteFullPages++;
         dmaWriteCG->next();
     } else {
+        DPRINTF(IdeDisk, "doDmaWrite: done curPrd byte count %d, eot %#x\n",
+                curPrd.getByteCount(), curPrd.getEOT());
         assert(dmaWriteCG->done());
         delete dmaWriteCG;
         dmaWriteCG = NULL;
@@ -496,6 +509,8 @@ IdeDisk::doDmaWrite()
 void
 IdeDisk::dmaWriteDone()
 {
+    DPRINTF(IdeDisk, "doWriteDone: curPrd byte count %d, eot %#x cmd bytes left:%d\n",
+                curPrd.getByteCount(), curPrd.getEOT(), cmdBytesLeft);
     // check for the EOT
     if (curPrd.getEOT()) {
         assert(cmdBytesLeft == 0);
@@ -549,7 +564,7 @@ IdeDisk::startDma(const uint32_t &prdTableBase)
     dmaState = Dma_Transfer;
 
     // schedule dma transfer (doDmaTransfer)
-    dmaTransferEvent.schedule(curTick + 1);
+    schedule(dmaTransferEvent, curTick() + 1);
 }
 
 void
@@ -631,7 +646,7 @@ IdeDisk::startCommand()
             cmdBytes = cmdBytesLeft = (256 * SectorSize);
         else
             cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
-
+        DPRINTF(IdeDisk, "Setting cmdBytesLeft to %d\n", cmdBytesLeft);
         curSector = getLBABase();
 
         devState = Prepare_Data_Out;
@@ -649,6 +664,7 @@ IdeDisk::startCommand()
             cmdBytes = cmdBytesLeft = (256 * SectorSize);
         else
             cmdBytes = cmdBytesLeft = (cmdReg.sec_count * SectorSize);
+        DPRINTF(IdeDisk, "Setting cmdBytesLeft to %d in readdma\n", cmdBytesLeft);
 
         curSector = getLBABase();
 
@@ -687,7 +703,6 @@ IdeDisk::intrPost()
 
     // talk to controller to set interrupt
     if (ctrl) {
-        ctrl->bmi_regs.bmis0 |= IDEINTS;
         ctrl->intrPost();
     }
 }
@@ -1077,12 +1092,12 @@ IdeDisk::unserialize(Checkpoint *cp, const string &section)
 
     switch (event) {
       case None : break;
-      case Transfer : dmaTransferEvent.schedule(reschedule); break;
-      case ReadWait : dmaReadWaitEvent.schedule(reschedule); break;
-      case WriteWait : dmaWriteWaitEvent.schedule(reschedule); break;
-      case PrdRead : dmaPrdReadEvent.schedule(reschedule); break;
-      case DmaRead : dmaReadEvent.schedule(reschedule); break;
-      case DmaWrite : dmaWriteEvent.schedule(reschedule); break;
+      case Transfer : schedule(dmaTransferEvent, reschedule); break;
+      case ReadWait : schedule(dmaReadWaitEvent, reschedule); break;
+      case WriteWait : schedule(dmaWriteWaitEvent, reschedule); break;
+      case PrdRead : schedule(dmaPrdReadEvent, reschedule); break;
+      case DmaRead : schedule(dmaReadEvent, reschedule); break;
+      case DmaWrite : schedule(dmaWriteEvent, reschedule); break;
     }
 
     // Unserialize device registers
@@ -1116,32 +1131,8 @@ IdeDisk::unserialize(Checkpoint *cp, const string &section)
     UNSERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
 }
 
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-enum DriveID { master, slave };
-static const char *DriveID_strings[] = { "master", "slave" };
-BEGIN_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
-
-    SimObjectParam<DiskImage *> image;
-    SimpleEnumParam<DriveID> driveID;
-    Param<int> delay;
-
-END_DECLARE_SIM_OBJECT_PARAMS(IdeDisk)
-
-BEGIN_INIT_SIM_OBJECT_PARAMS(IdeDisk)
-
-    INIT_PARAM(image, "Disk image"),
-    INIT_ENUM_PARAM(driveID, "Drive ID (0=master 1=slave)", DriveID_strings),
-    INIT_PARAM_DFLT(delay, "Fixed disk delay in microseconds", 1)
-
-END_INIT_SIM_OBJECT_PARAMS(IdeDisk)
-
-
-CREATE_SIM_OBJECT(IdeDisk)
+IdeDisk *
+IdeDiskParams::create()
 {
-    return new IdeDisk(getInstanceName(), image, driveID, delay);
+    return new IdeDisk(this);
 }
-
-REGISTER_SIM_OBJECT("IdeDisk", IdeDisk)
-
-#endif //DOXYGEN_SHOULD_SKIP_THIS