summaryrefslogtreecommitdiff
path: root/src/dev
diff options
context:
space:
mode:
Diffstat (limited to 'src/dev')
-rw-r--r--src/dev/ide_ctrl.cc35
-rw-r--r--src/dev/ide_disk.cc69
-rw-r--r--src/dev/ide_disk.hh17
3 files changed, 108 insertions, 13 deletions
diff --git a/src/dev/ide_ctrl.cc b/src/dev/ide_ctrl.cc
index df02bf5f5..bbc0e379d 100644
--- a/src/dev/ide_ctrl.cc
+++ b/src/dev/ide_ctrl.cc
@@ -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.
*
@@ -111,11 +123,11 @@ IdeController::IdeController(Params *p)
if ((BARAddrs[0] & ~BAR_IO_MASK) && (!legacyIO[0] || ioShift)) {
primary.cmdAddr = BARAddrs[0]; primary.cmdSize = BARSize[0];
- primary.ctrlAddr = BARAddrs[1]; primary.ctrlSize = BARAddrs[1];
+ 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 = BARAddrs[3];
+ secondary.ctrlAddr = BARAddrs[3]; secondary.ctrlSize = BARSize[3];
}
ioEnabled = (config.command & htole(PCI_CMD_IOSE));
@@ -414,14 +426,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;
}
diff --git a/src/dev/ide_disk.cc b/src/dev/ide_disk.cc
index bc7210d42..b910c8a6a 100644
--- a/src/dev/ide_disk.cc
+++ b/src/dev/ide_disk.cc
@@ -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.
*
@@ -143,6 +155,7 @@ IdeDisk::reset(int id)
drqBytesLeft = 0;
dmaRead = false;
intrPending = false;
+ dmaAborted = false;
// set the device state to idle
dmaState = Dma_Idle;
@@ -319,6 +332,12 @@ IdeDisk::writeControl(const Addr offset, int size, const uint8_t *data)
void
IdeDisk::doDmaTransfer()
{
+ if (dmaAborted) {
+ DPRINTF(IdeDisk, "DMA Aborted before reading PRD entry\n");
+ updateState(ACT_CMD_ERROR);
+ return;
+ }
+
if (dmaState != Dma_Transfer || devState != Transfer_Data_Dma)
panic("Inconsistent DMA transfer state: dmaState = %d devState = %d\n",
dmaState, devState);
@@ -334,6 +353,11 @@ IdeDisk::doDmaTransfer()
void
IdeDisk::dmaPrdReadDone()
{
+ if (dmaAborted) {
+ DPRINTF(IdeDisk, "DMA Aborted while reading PRD entry\n");
+ updateState(ACT_CMD_ERROR);
+ return;
+ }
DPRINTF(IdeDisk,
"PRD: baseAddr:%#x (%#x) byteCount:%d (%d) eot:%#x sector:%d\n",
@@ -396,6 +420,14 @@ IdeDisk::regStats()
void
IdeDisk::doDmaRead()
{
+ if (dmaAborted) {
+ DPRINTF(IdeDisk, "DMA Aborted in middle of Dma Read\n");
+ if (dmaReadCG)
+ delete dmaReadCG;
+ dmaReadCG = NULL;
+ updateState(ACT_CMD_ERROR);
+ return;
+ }
if (!dmaReadCG) {
// clear out the data buffer
@@ -427,10 +459,8 @@ IdeDisk::doDmaRead()
void
IdeDisk::dmaReadDone()
{
-
uint32_t bytesWritten = 0;
-
// write the data to the disk image
for (bytesWritten = 0; bytesWritten < curPrd.getByteCount();
bytesWritten += SectorSize) {
@@ -475,7 +505,14 @@ IdeDisk::doDmaDataWrite()
void
IdeDisk::doDmaWrite()
{
- DPRINTF(IdeDisk, "doDmaWrite: rescheduling\n");
+ if (dmaAborted) {
+ DPRINTF(IdeDisk, "DMA Aborted while doing DMA Write\n");
+ if (dmaWriteCG)
+ delete dmaWriteCG;
+ dmaWriteCG = NULL;
+ updateState(ACT_CMD_ERROR);
+ return;
+ }
if (!dmaWriteCG) {
// clear out the data buffer
dmaWriteCG = new ChunkGenerator(curPrd.getBaseAddr(),
@@ -980,7 +1017,10 @@ IdeDisk::updateState(DevAction_t action)
break;
case Transfer_Data_Dma:
- if (action == ACT_CMD_ERROR || action == ACT_DMA_DONE) {
+ if (action == ACT_CMD_ERROR) {
+ dmaAborted = true;
+ devState = Device_Dma_Abort;
+ } else if (action == ACT_DMA_DONE) {
// clear the BSY bit
setComplete();
// set the seek bit
@@ -997,6 +1037,25 @@ IdeDisk::updateState(DevAction_t action)
}
break;
+ case Device_Dma_Abort:
+ if (action == ACT_CMD_ERROR) {
+ setComplete();
+ status |= STATUS_SEEK_BIT;
+ ctrl->setDmaComplete(this);
+ dmaAborted = false;
+ dmaState = Dma_Idle;
+
+ if (!isIENSet()) {
+ devState = Device_Idle_SI;
+ intrPost();
+ } else {
+ devState = Device_Idle_S;
+ }
+ } else {
+ DPRINTF(IdeDisk, "Disk still busy aborting previous DMA command\n");
+ }
+ break;
+
default:
panic("Unknown IDE device state: %#x\n", devState);
}
@@ -1074,6 +1133,7 @@ IdeDisk::serialize(ostream &os)
SERIALIZE_SCALAR(curSector);
SERIALIZE_SCALAR(dmaRead);
SERIALIZE_SCALAR(intrPending);
+ SERIALIZE_SCALAR(dmaAborted);
SERIALIZE_ENUM(devState);
SERIALIZE_ENUM(dmaState);
SERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
@@ -1126,6 +1186,7 @@ IdeDisk::unserialize(Checkpoint *cp, const string &section)
UNSERIALIZE_SCALAR(curSector);
UNSERIALIZE_SCALAR(dmaRead);
UNSERIALIZE_SCALAR(intrPending);
+ UNSERIALIZE_SCALAR(dmaAborted);
UNSERIALIZE_ENUM(devState);
UNSERIALIZE_ENUM(dmaState);
UNSERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE);
diff --git a/src/dev/ide_disk.hh b/src/dev/ide_disk.hh
index b29d13870..6ccca985e 100644
--- a/src/dev/ide_disk.hh
+++ b/src/dev/ide_disk.hh
@@ -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.
*
@@ -177,7 +189,8 @@ typedef enum DevState {
// DMA protocol
Prepare_Data_Dma,
- Transfer_Data_Dma
+ Transfer_Data_Dma,
+ Device_Dma_Abort
} DevState_t;
typedef enum DmaState {
@@ -236,6 +249,8 @@ class IdeDisk : public SimObject
int devID;
/** Interrupt pending */
bool intrPending;
+ /** DMA Aborted */
+ bool dmaAborted;
Stats::Scalar dmaReadFullPages;
Stats::Scalar dmaReadBytes;