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 §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); 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; diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh index aedb2d1ae..46d3fe82c 100644 --- a/src/sim/serialize.hh +++ b/src/sim/serialize.hh @@ -57,7 +57,7 @@ class SimObject; * SimObject shouldn't cause the version number to increase, only changes to * existing objects such as serializing/unserializing more state, changing sizes * of serialized arrays, etc. */ -static const uint64_t gem5CheckpointVersion = 0x0000000000000006; +static const uint64_t gem5CheckpointVersion = 0x0000000000000007; template void paramOut(std::ostream &os, const std::string &name, const T ¶m); diff --git a/util/cpt_upgrader.py b/util/cpt_upgrader.py index 623c9b297..b5b54c1f2 100755 --- a/util/cpt_upgrader.py +++ b/util/cpt_upgrader.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2012 ARM Limited +# Copyright (c) 2012-2013 ARM Limited # All rights reserved # # The license below extends only to copyright in the software and shall @@ -209,6 +209,15 @@ def from_5(cpt): else: print "ISA is not x86" +# Version 7 of the checkpoint adds support for the IDE dmaAbort flag +def from_6(cpt): + # Update IDE disk devices with dmaAborted + for sec in cpt.sections(): + # curSector only exists in IDE devices, so key on that attribute + if cpt.has_option(sec, "curSector"): + cpt.set(sec, "dmaAborted", "false") + + migrations = [] migrations.append(from_0) migrations.append(from_1) @@ -216,6 +225,7 @@ migrations.append(from_2) migrations.append(from_3) migrations.append(from_4) migrations.append(from_5) +migrations.append(from_6) verbose_print = False @@ -274,7 +284,6 @@ def process_file(path, **kwargs): verboseprint("\t...completed") cpt.write(file(path, 'w')) - if __name__ == '__main__': from optparse import OptionParser parser = OptionParser("usage: %prog [options] ")