diff options
Diffstat (limited to 'src/dev/ide_disk.cc')
-rw-r--r-- | src/dev/ide_disk.cc | 69 |
1 files changed, 65 insertions, 4 deletions
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 §ion) UNSERIALIZE_SCALAR(curSector); UNSERIALIZE_SCALAR(dmaRead); UNSERIALIZE_SCALAR(intrPending); + UNSERIALIZE_SCALAR(dmaAborted); UNSERIALIZE_ENUM(devState); UNSERIALIZE_ENUM(dmaState); UNSERIALIZE_ARRAY(dataBuffer, MAX_DMA_SIZE); |